問題現象
出現 Kubernetes API 無法調取的現象,使用 kubectl 命令獲取資源均返回如下報錯.
Unable to connect to the server: x509: certificate has expired or is not yet valid
經網上搜索之后發現。應該是 Kubernetes 集群的證書過期了,使用命令排查證書的過期時間.
# kubeadm alpha certs check-expiration
發現確實是證書過期了。
相關介紹以及問題解決
因為我們是使用 kubeadm 部署的 Kubernetes 集群,所以更新起證書也是比較方便的,默認的證書時間有效期是一年,我們集群的 Kubernetes 版本是 1.15.3版本是可以使用以下命令來更新證書的,但是一年之后還是會到期,這樣就很麻煩,所以我們需要了解一下 Kubernetes 的證書,然后我們來生成一個時間很長的證書,這樣我們就可以不用去總更新證書了。
# kubeadm alpha certs renew all --config=kubeadm.yaml # systemctl restart kubelet # kubeadm init phase kubeconfig all --config kubeadm.yaml 然后將生成的配置文件替換,重啟kube-apiserver、kube-controller、kube-scheduler、etcd這4個容器即可
另外kubeadm會在控制面板升級的時候自動更新所有證書,所以使用 kubeadm 搭建得集群最佳的做法是經常升級集群,這樣可以確保你的集群保持最新狀態並保持合理的安全性。但是對於實際的生產環境我們可能並不會去頻繁得升級集群,所以這個時候我們就需要去手動更新證書。
下面我們通過調用 Kubernetes 的 API 來實現更新一個10年的證書。
首先在/etc/kubernetes/manifests/kube-controller-manager.yaml文件加入配置 spec: containers: - command: - kube-controller-manager # 設置證書有效期為10年 - --experimental-cluster-signing-duration=87600h - --client-ca-file=/etc/kubernetes/pki/ca.crt
修改完成后 kube-controller-manager 會自動重啟生效。然后我們需要使用下面的命令為 Kubernetes 證書 API 創建一個證書簽名請求。如果你設置例如 cert-manager 等外部簽名者,則會自動批准證書簽名請求(CSRs)。否者,你必須使用 kubectl certificate 命令手動批准證書。以下 kubeadm 命令輸出要批准的證書名稱,然后等待批准發生:
# kubeadm alpha certs renew all --use-api --config kubeadm.yaml &
需要將全部 pending 的證書全部批准。我們還不能直接重啟控制面板的幾個組件,這是因為使用 kubeadm 安裝的集群對應的etcd 默認是使用的 /etc/kubernetes/pki/etcd/ca.crt 這個證書進行前面的,而上面我們用命令kubectl certificate approve批准過后的證書是使用的默認的/etc/kubernetes/pki/ca.crt 證書進行簽發的,所以我們需要替換 etcd 中的 CA 機構證書:
# 先拷貝靜態Pod資源清單 cp -r /etc/kubernetes/manifests/ /etc/kubernetes/manifests.bak vi /etc/kubernetes/manifests/etcd.yaml ...... spec: containers: - command: - etcd # 修改為CA文件 - --peer-trusted-ca-file=/etc/kubernetes/pki/ca.crt - --trusted-ca-file=/etc/kubernetes/pki/ca.crt ...... volumeMounts: - mountPath: /var/lib/etcd name: etcd-data - mountPath: /etc/kubernetes/pki # 更改證書目錄 name: etcd-certs volumes: - hostPath: path: /etc/kubernetes/pki # 將 pki 目錄掛載到etcd中去 type: DirectoryOrCreate name: etcd-certs - hostPath: path: /var/lib/etcd type: DirectoryOrCreate name: etcd-data ......
由於 kube-apiserver 要連接 etcd 集群,所以也需要重新修改對應的 etcd ca 文件:
vi /etc/kubernetes/manifests/kube-apiserver.yaml ...... spec: containers: - command: - kube-apiserver # 將etcd ca文件修改為默認的ca.crt文件 - --etcd-cafile=/etc/kubernetes/pki/ca.crt ......
除此之外還需要替換 requestheader-client-ca-file 文件,默認是 /etc/kubernetes/pki/front-proxy-ca.crt 文件,現在也需要替換成默認的 CA 文件,否則使用聚合 API,比如安裝了 metrics-server 后執行 kubectl top 命令就會報錯:
# cp /etc/kubernetes/pki/ca.crt /etc/kubernetes/pki/front-proxy-ca.crt
# cp /etc/kubernetes/pki/ca.key /etc/kubernetes/pki/front-proxy-ca.key
這樣我們就得到了一個10年證書的 Kubernetes 集群,還可以通過重新編譯 kubeadm 來實現一個10年證書的,這個我沒有嘗試,不過在初始化集群的時候也是一個方法。
參考文檔: https://kubernetes.io/zh/docs/tasks/administer-cluster/kubeadm/kubeadm-certs/
https://zhuanlan.zhihu.com/p/343031257
