深入理解kubelet認證和授權


在通過kubectl訪問pod信息,例如執行kubectl logs,常常會遇到類似如下錯誤:

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

網上搜索可以通過啟用anonymous訪問,也就是使用--anonymous-auth=true或者配置文件添加:

authentication:
    anonymous:
        enabled: true

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

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

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

認證過程

配置認證方式

有三種可配置認證方式:

  1. TLS認證,這也是默認的

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

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

    authentication:
        webhook:
        	enabled: true
    

    這時kubelet通過bearer tokens,找apiserver認證,如果存在對應的serviceaccount,則認證通過。

如果2開啟,則忽略x509和webhook認證;否則,如果1和3同時開啟,則按1、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
    
  3. 手工批准證書請求:

    先查詢證書請求:

    [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目錄可以看到服務端證書已經生成。

  4. 配置客戶端證書和前面的方法是一樣的,上面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,客戶端證書需要手工配置。

歡迎訪問鍾潘的博客


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM