在經過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
TLS認證,這也是默認的命令行
authentication: anonymous: enabled: false webhook: enabled: false x509: clientCAFile: xxxx
容許anonymous,這時可不配置客戶端證書vagrant
authentication: anonymous: enabled: true
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證書認證客戶端,那麼還須要配置客戶端證書。下面說明證書配置的三種方法:
修改kubelet的配置文件:
tlsCertFile: kubelet-server.pem tlsPrivateKeyFile: kubelet-server-key.pem authentication: x509: clientCAFile: ca.pem
修改apiserver參數:
--kubelet-certificate-authority=ca.pem --kubelet-client-certificate=kubelet-client.pem --kubelet-client-key=kubelet-client-key.pem
受權kubelet-client用戶:
kubectl create clusterrolebinding kubelet-admin --clusterrole=system:kubelet-api-admin --user=kubelet-client
通過上面5步,認證的過程實際已經OK了,第6步是爲受權過程服務的,kubelet的受權是經過webhook委託給apiserver的。
其實是上述過程的特化,不指定tlsCertFile和tlsPrivateKeyFile時,kubelet會自動生成服務端證書保存在--cert-dir指定目錄中,文件名爲kubelet.crt和kubelet.key,這個證書是自簽名的,因此apiserver不須要指定--kubelet-certificate-authority,其餘配置是同樣的。
還能夠經過TLS bootstrap機制分配kubelet服務證書。跟配置分配訪問apiserver的客戶端證書方法是同樣的(參考官方文檔),額外的配置以下:
修改kubelet配置文件:
serverTLSBootstrap: true
首先建立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
手工批准證書請求:
先查詢證書請求:
[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目錄能夠看到服務端證書已經生成。
客戶端證書配置是免不了的,區別是在服務端證書,顯然自動生成更加方便,TLS bootstrap相對於自簽名證書更加安全,集羣統一使用信任的CA簽名。
TLS bootstrap還能夠配置證書過時後自動從新生成,方法是修改kubelet配置文件:
rotateCertificates: true
TLS bootstrap分配證書的有效期能夠經過kube-controller-manager以下參數修改,默認8760h0m0s,也就是1年:
--experimental-cluster-signing-duration
可配置兩種受權方式:
AlwaysAllow:從字面意思就可知道
authorization: mode: AlwaysAllow
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種作法:
省事型,可用於開發環境
authentication: anonymous: enabled: true authorization: mode: AlwaysAllow
一開始出現的Forbidden問題就是沒有配置AlwaysAllow,默認是Webhook。
安全型,生產環境使用
authentication: anonymous: enabled: false authorization: mode: Webhook
服務端證書經過TLS bootstrap,客戶端證書須要手工配置。
歡迎訪問 鍾潘的博客