部署高可用 kube-controller-manager 集群
本文檔介紹部署高可用 kube-controller-manager 集群的步驟。
該集群包含 3 個節點,啟動後將通過競爭選舉機制產生一個 leader 節點,其它節點為阻塞狀態。當 leader 節點不可用後,剩余節點將再次進行選舉產生新的 leader 節點,從而保證服務的可用性。
為保證通信安全,本文檔先生成 x509 證書和私鑰,kube-controller-manager 在如下兩種情況下使用該證書:
- 與 kube-apiserver 的安全端口通信時;
- 在安全端口(https,10252) 輸出 prometheus 格式的 metrics;
註意:如果沒有特殊指明,本文檔的所有操作均在 k8s-master1 節點上執行,然後遠程分發文件和執行命令。
創建 kube-controller-manager 證書和私鑰
創建證書簽名請求:
cd /opt/k8s/work cat > kube-controller-manager-csr.json <<EOF { "CN": "system:kube-controller-manager", "key": { "algo": "rsa", "size": 2048 }, "hosts": [ "127.0.0.1", "192.168.161.150","192.168.161.151", "192.168.161.152" ], "names": [ { "C": "CN", "ST": "BeiJing", "L": "BeiJing", "O": "system:kube-controller-manager", "OU": "4Paradigm" } ] } EOF
- hosts 列表包含所有 kube-controller-manager 節點 IP;
- CN 為 system:kube-controller-manager、O 為 system:kube-controller-manager,kubernetes 內置的 ClusterRoleBindings system:kube-controller-manager 賦予 kube-controller-manager 工作所需的權限。
生成證書和私鑰:
cd /opt/k8s/work cfssl gencert -ca=/opt/k8s/work/ca.pem -ca-key=/opt/k8s/work/ca-key.pem -config=/opt/k8s/work/ca-config.json -profile=kubernetes kube-controller-manager-csr.json | cfssljson -bare kube-controller-manager ls kube-controller-manager*pem
將生成的證書和私鑰分發到所有 master 節點:
cd /opt/k8s/work source /opt/k8s/bin/environment.sh for node_ip in 192.168.161.150 192.168.161.151 192.168.161.152 do echo ">>> ${node_ip}" scp kube-controller-manager*.pem [email protected]${node_ip}:/etc/kubernetes/cert/ done
創建和分發 kubeconfig 文件
kubeconfig 文件包含訪問 apiserver 的所有信息,如 apiserver 地址、CA 證書和自身使用的證書;
cd /opt/k8s/work source /opt/k8s/bin/environment.sh kubectl config set-cluster kubernetes --certificate-authority=/opt/k8s/work/ca.pem --embed-certs=true --server=${KUBE_APISERVER} --kubeconfig=kube-controller-manager.kubeconfig kubectl config set-credentials system:kube-controller-manager --client-certificate=kube-controller-manager.pem --client-key=kube-controller-manager-key.pem --embed-certs=true --kubeconfig=kube-controller-manager.kubeconfig kubectl config set-context system:kube-controller-manager --cluster=kubernetes --user=system:kube-controller-manager --kubeconfig=kube-controller-manager.kubeconfig kubectl config use-context system:kube-controller-manager --kubeconfig=kube-controller-manager.kubeconfig
分發 kubeconfig 到所有 master 節點:
cd /opt/k8s/work source /opt/k8s/bin/environment.sh for node_ip in 192.168.161.150 192.168.161.151 192.168.161.152 do echo ">>> ${node_ip}" scp kube-controller-manager.kubeconfig [email protected]${node_ip}:/etc/kubernetes/ done
創建和分發 kube-controller-manager systemd unit 文件
cd /opt/k8s/work source /opt/k8s/bin/environment.sh cat > kube-controller-manager.service <<EOF [Unit] Description=Kubernetes Controller Manager Documentation=https://github.com/GoogleCloudPlatform/kubernetes [Service] WorkingDirectory=${K8S_DIR}/kube-controller-manager ExecStart=/opt/k8s/bin/kube-controller-manager \ --port=0 \ --secure-port=10252 \ --bind-address=127.0.0.1 \ --kubeconfig=/etc/kubernetes/kube-controller-manager.kubeconfig \ --authentication-kubeconfig=/etc/kubernetes/kube-controller-manager.kubeconfig \ --authorization-kubeconfig=/etc/kubernetes/kube-controller-manager.kubeconfig \ --service-cluster-ip-range=${SERVICE_CIDR} \ --cluster-name=kubernetes \ --cluster-signing-cert-file=/etc/kubernetes/cert/ca.pem \ --cluster-signing-key-file=/etc/kubernetes/cert/ca-key.pem \ --experimental-cluster-signing-duration=8760h \ --root-ca-file=/etc/kubernetes/cert/ca.pem \ --service-account-private-key-file=/etc/kubernetes/cert/ca-key.pem \ --leader-elect=true \ --controllers=*,bootstrapsigner,tokencleaner \ --horizontal-pod-autoscaler-use-rest-clients=true \ --horizontal-pod-autoscaler-sync-period=10s \ --tls-cert-file=/etc/kubernetes/cert/kube-controller-manager.pem \ --tls-private-key-file=/etc/kubernetes/cert/kube-controller-manager-key.pem \ --use-service-account-credentials=true \ --kube-api-qps=1000 \ --kube-api-burst=2000 \ --logtostderr=true \ --v=2 Restart=on-failure RestartSec=5 [Install] WantedBy=multi-user.target EOF
--port=0
:關閉監聽 http /metrics 的請求,同時--address
參數無效,--bind-address
參數有效;--secure-port=10252
、--bind-address=0.0.0.0
: 在所有網絡接口監聽 10252 端口的 https /metrics 請求;--kubeconfig
:指定 kubeconfig 文件路徑,kube-controller-manager 使用它連接和驗證 kube-apiserver;--authentication-kubeconfig
和--authorization-kubeconfig
:kube-controller-manager 使用它連接 apiserver,對 client 的請求進行認證和授權。kube-controller-manager
不再使用--tls-ca-file
對請求 https metrics 的 Client 證書進行校驗。如果沒有配置這兩個 kubeconfig 參數,則 client 連接 kube-controller-manager https 端口的請求會被拒絕(提示權限不足)。--cluster-signing-*-file
:簽名 TLS Bootstrap 創建的證書;--experimental-cluster-signing-duration
:指定 TLS Bootstrap 證書的有效期;--root-ca-file
:放置到容器 ServiceAccount 中的 CA 證書,用來對 kube-apiserver 的證書進行校驗;--service-account-private-key-file
:簽名 ServiceAccount 中 Token 的私鑰文件,必須和 kube-apiserver 的--service-account-key-file
指定的公鑰文件配對使用;--service-cluster-ip-range
:指定 Service Cluster IP 網段,必須和 kube-apiserver 中的同名參數一致;--leader-elect=true
:集群運行模式,啟用選舉功能;被選為 leader 的節點負責處理工作,其它節點為阻塞狀態;--controllers=*,bootstrapsigner,tokencleaner
:啟用的控制器列表,tokencleaner 用於自動清理過期的 Bootstrap token;--horizontal-pod-autoscaler-*
:custom metrics 相關參數,支持 autoscaling/v2alpha1;--tls-cert-file
、--tls-private-key-file
:使用 https 輸出 metrics 時使用的 Server 證書和秘鑰;--use-service-account-credentials=true
: kube-controller-manager 中各 controller 使用 serviceaccount 訪問 kube-apiserver;
完整 unit 見 kube-controller-manager.service
分發 systemd unit 文件到所有 master 節點:
cd /opt/k8s/work source /opt/k8s/bin/environment.sh for node_ip in 192.168.161.150 192.168.161.151 192.168.161.152 do echo ">>> ${node_ip}" scp kube-controller-manager.service [email protected]${node_ip}:/etc/systemd/system/ done
kube-controller-manager 的權限
ClusteRole: system:kube-controller-manager 的權限很小,只能創建 secret、serviceaccount 等資源對象,各 controller 的權限分散到 ClusterRole system:controller:XXX 中。
需要在 kube-controller-manager 的啟動參數中添加 --use-service-account-credentials=true
參數,這樣 main controller 會為各 controller 創建對應的 ServiceAccount XXX-controller。
內置的 ClusterRoleBinding system:controller:XXX 將賦予各 XXX-controller ServiceAccount 對應的 ClusterRole system:controller:XXX 權限。
另外,--authentication-kubeconfig
和 --authorization-kubeconfig
參數指定的證書需要有創建 "subjectaccessreviews" 的權限,否則提示:
$ curl --cacert /opt/k8s/work/ca.pem --cert /opt/k8s/work/admin.pem --key /opt/k8s/work/admin-key.pem https://127.0.0.1:10252/metrics Internal Server Error: "/metrics": subjectaccessreviews.authorization.k8s.io is forbidden: User "system:kube-controller-manager" cannot create resource "subjectaccessreviews" in API group "authorization.k8s.io" at the cluster scope
解決辦法是創建一個 ClusterRoleBinding,賦予相應的權限:
$ kubectl create clusterrolebinding controller-manager:system:auth-delegator --user system:kube-controller-manager --clusterrole system:auth-delegator
clusterrolebinding.rbac.authorization.k8s.io/controller-manager:system:auth-delegator created
部署高可用 kube-controller-manager 集群