深刻理解kubelet認證和受權

在經過kubectl訪問pod信息,例如執行kubectl logs,經常會遇到相似以下錯誤:node

Error from server (Forbidden): Forbidden (user=system:anonymous, verb=get, resource=nodes, subresource=proxy) ( pods/log tiller-deploy-6b5ffb6f-lg9jb)

網上搜索能夠經過啓用anonymous訪問,也就是使用--anonymous-auth=true或者配置文件添加:web

authentication:
    anonymous:
        enabled: true

可是設置以後錯誤依舊,爲此我探究了一下kubelet的認證機制,終於將問題解決,其實很簡單,答案後面揭曉。shell

咱們知道kubectl只會和apiserver交互,對於kubectl logs、kubectl exec等須要訪問pod的這些命令,其實是apiserver調用kubelet接口完成的,上述錯誤正是出在這個過程,而不是kubectl到apiserver的過程。bootstrap

kubelet經過port指定的端口(默認10250)對外暴露服務,這個服務是須要TLS認證的,同時也能夠經過 readOnlyPort 端口(默認10255,0表示關閉)對外暴露只讀服務,這個服務是不須要認證的。apiserver經過--kubelet-https參數指定調用哪一個服務,true爲前者,false爲後者,此時只能執行只讀操做。下面主要說一下前者。api

<!--more-->安全

認證過程

配置認證方式

有三種可配置認證方式:app

  1. TLS認證,這也是默認的命令行

    authentication:
        anonymous:
            enabled: false
        webhook:
            enabled: false
        x509:
            clientCAFile: xxxx
  2. 容許anonymous,這時可不配置客戶端證書vagrant

    authentication:
        anonymous:
            enabled: true
  3. webhook,這時可不配置客戶端證書code

    authentication:
        webhook:
            enabled: true

    這時kubelet經過bearer tokens,找apiserver認證,若是存在對應的serviceaccount,則認證經過。

若是2開啓,則忽略x509和webhook認證;不然,若是1和3同時開啓,則按一、3的順序依次認證,任何一個認證經過則返回經過,不然認證不經過。

經過kubectl命令行訪問kubelet時,沒法傳遞bearer tokens,因此沒法使用webhook認證,這時只能使用x509認證。

證書配置

kubelet對外暴露https服務,必須設置服務端證書,若是經過x509證書認證客戶端,那麼還須要配置客戶端證書。下面說明證書配置的三種方法:

手工指定證書

  1. 假設ca的證書和key:ca.pem,ca-key.pem
  2. 用上述ca生成kubelet服務端證書和key:kubelet-server.pem、kubelet-server-key.pem
  3. 用上述ca生成apiserver使用的客戶端證書和key:kubelet-client.pem、kubelet-client-key.pem,證書CN爲kubelet-client
  4. 修改kubelet的配置文件:

    tlsCertFile: kubelet-server.pem
    tlsPrivateKeyFile: kubelet-server-key.pem
    authentication:
        x509:
            clientCAFile: ca.pem
  5. 修改apiserver參數:

    --kubelet-certificate-authority=ca.pem --kubelet-client-certificate=kubelet-client.pem --kubelet-client-key=kubelet-client-key.pem
  6. 受權kubelet-client用戶:

    kubectl create clusterrolebinding kubelet-admin --clusterrole=system:kubelet-api-admin --user=kubelet-client

    通過上面5步,認證的過程實際已經OK了,第6步是爲受權過程服務的,kubelet的受權是經過webhook委託給apiserver的。

自簽名證書和key

其實是上述過程的特化,不指定tlsCertFile和tlsPrivateKeyFile時,kubelet會自動生成服務端證書保存在--cert-dir指定目錄中,文件名爲kubelet.crt和kubelet.key,這個證書是自簽名的,因此apiserver不須要指定--kubelet-certificate-authority,其餘配置是同樣的。

經過TLS bootstrap機制

還能夠經過TLS bootstrap機制分配kubelet服務證書。跟配置分配訪問apiserver的客戶端證書方法是同樣的(參考官方文檔),額外的配置以下:

  1. 修改kubelet配置文件:

    serverTLSBootstrap: true
  2. 受權容許建立kubelet服務端證書

    首先建立system:certificates.k8s.io:certificatesigningrequests:selfnodeserver,默認是沒有建立的。

    selfnodeserver.yaml文件以下:

# A ClusterRole which instructs the CSR approver to approve a node requesting a
# serving cert matching its client cert.
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
 name: system:certificates.k8s.io:certificatesigningrequests:selfnodeserver
rules:
- apiGroups: ["certificates.k8s.io"]
 resources: ["certificatesigningrequests/selfnodeserver"]
 verbs: ["create"]
kubectl create -f selfnodeserver.yaml

而後建立綁定:

kubectl create clusterrolebinding node-server-auto-renew-crt --clusterrole=system:certificates.k8s.io:certificatesigningrequests:selfnodeserver --group=system:nodes
  1. 手工批准證書請求:

    先查詢證書請求:

    [vagrant@localhost etc]$ kubectl get csr
    NAME                                                   AGE     REQUESTOR                 CONDITION
    csr-2jxvn                                              76s     system:node:10.10.10.16   Pending

    而後批准證書:

    kubectl certificate approve csr-2jxvn

    以後在相應kubelet的--cert-dir目錄能夠看到服務端證書已經生成。

  2. 配置客戶端證書和前面的方法是同樣的,上面3步只是生成服務端證書。

選擇哪一種方式

客戶端證書配置是免不了的,區別是在服務端證書,顯然自動生成更加方便,TLS bootstrap相對於自簽名證書更加安全,集羣統一使用信任的CA簽名。

TLS bootstrap還能夠配置證書過時後自動從新生成,方法是修改kubelet配置文件:

rotateCertificates: true

TLS bootstrap分配證書的有效期能夠經過kube-controller-manager以下參數修改,默認8760h0m0s,也就是1年:

--experimental-cluster-signing-duration

受權過程

配置受權方式

可配置兩種受權方式:

  1. AlwaysAllow:從字面意思就可知道

    authorization:
        mode: AlwaysAllow
  2. Webhook:這是默認模式

    authorization:
        mode: Webhook

    這時受權過程是委託給apiserver的,使用apiserver同樣的受權模式,也就是RBAC。

配置權限

若是經過Webhook受權,就須要經過RBAC爲用戶配置權限。

首先要弄清楚經過認證的用戶是什麼,經過x509證書認證的用戶名是客戶端證書中的CN字段,用戶組爲O字段;經過webhook認證的用戶是token對應的serviceaccount;沒有經過認證或使能anonymous,則用戶爲system:anonymous。

其次要弄清楚應該受權什麼權限,系統已經存在一個system:kubelet-api-admin角色,這是最高的權限,能夠根據須要建立低權限角色。

[vagrant@localhost kube-apiserver]$ kubectl describe clusterrole system:kubelet-api-admin
Name:         system:kubelet-api-admin
Labels:       kubernetes.io/bootstrapping=rbac-defaults
Annotations:  rbac.authorization.kubernetes.io/autoupdate: true
PolicyRule:
  Resources      Non-Resource URLs  Resource Names  Verbs
  ---------      -----------------  --------------  -----
  nodes/log      []                 []              [*]
  nodes/metrics  []                 []              [*]
  nodes/proxy    []                 []              [*]
  nodes/spec     []                 []              [*]
  nodes/stats    []                 []              [*]
  nodes          []                 []              [get list watch proxy]

最後將用戶和角色綁定,即完成權限的配置。

總結

如何配置kubelet的認證和受權,歸結起來經常使用以下2種作法:

  1. 省事型,可用於開發環境

    authentication:
        anonymous:
            enabled: true
    authorization:
        mode: AlwaysAllow

    一開始出現的Forbidden問題就是沒有配置AlwaysAllow,默認是Webhook。

  2. 安全型,生產環境使用

    authentication:
        anonymous:
            enabled: false
    authorization:
        mode: Webhook

    服務端證書經過TLS bootstrap,客戶端證書須要手工配置。

歡迎訪問 鍾潘的博客
相關文章
相關標籤/搜索