目錄:
1、證書過期時間查詢
2、證書過期處理
2.1话瞧、客戶端kubelet證書自動續(xù)期
2.2、重新生成默認(rèn)一年時長證書
2.3寝姿、編譯kubeadm延長證書時長
簡介:
k8s集群分為兩種證書:
- 用于集群 Master交排、Etcd等通信的證書;
- 用于集群中客戶端 Kubelet組件和api通信的證書饵筑;
我們在搭建 Kubernetes 集群時埃篓,一般只聲明用于集群 Master、Etcd等通信的證書有效期為10年或者更久根资,但未聲明集群 Kubelet 組件證書 架专,Kubelet組件證書默認(rèn)有效期為1年。集群運行1年以后就會導(dǎo)致報 certificate has expired or is not yet valid 錯誤玄帕,導(dǎo)致集群 Node不能于集群 Master正常通信部脚。
1.14后的版本可以使用這個命令查看過期時間,如下:
$kubeadm alpha certs check-expiration?
kubeadm初始化配置文件:
kubeadm.yaml是一個kubeadm用于集群初始化時候的一個配置文件裤纹,這個配置文件主要用于集群初始化的時候指定一些自定義的參數(shù)和配置信息委刘。我們在使用kubeadm更新k8s集群證書的時候會使用到這個配置文件。
- 獲取一個創(chuàng)建好的ha k8s集群的初始化配置文件
$kubeadm config view > kubeadm.yaml
apiVersion: kubeadm.k8s.io/v1alpha1
kind: MasterConfiguration
etcd:
endpoints:
- https://10.10.8.141:2379
- https://10.10.8.142:2379
- https://10.10.8.143:2379
caFile: /etc/etcd/ssl/ca.pem
certFile: /etc/etcd/ssl/etcd.pem
keyFile: /etc/etcd/ssl/etcd-key.pem
dataDir: /var/lib/etcd
networking:
podSubnet: 10.244.0.0/16
kubernetesVersion: 1.10.0
api:
advertiseAddress: "10.10.8.140"
token: "b99a00.a144ef80536d4344"
tokenTTL: "0s"
apiServerCertSANs:
- k8s-master1
- k8s-master2
- k8s-master3
- 10.10.8.141
- 10.10.8.142
- 10.10.8.143
- 10.10.8.144
- 10.10.8.140
featureGates:
CoreDNS: true
imageRepository: "k8s.gcr.io"
注意:若我們集群的證書已經(jīng)過期了不能使用kubeadm獲取到集群的初始化配置文件,那么我們可以手寫一個簡單的配置文件锡移,寫這個文件是因為獲取不到集群的基本配置文件的時候kubeadm會去k8s官網(wǎng)找一個stable-1.txt的文件(這個文件的內(nèi)容就是關(guān)于k8s的版本信息)呕童。
- 創(chuàng)建一個簡單的kubeadm的配置文件
$vi kubeadm.yaml
apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
kubernetesVersion: v1.13.5 #--------這里改成你集群對應(yīng)的版本
imageRepository: k8s.gcr.io #-------k8s官方的鏡像倉庫
上面文件主要作用是告訴kubeadm中Kubernetes集群的版本,以防止它去網(wǎng)上查找罩抗,因為被墻拉庵,會報錯如下:
could not fetch a Kubernetes version from the internet: unable to get URL "https://dl.k8s.io/release/stable-1.txt"
1、證書過期時間查詢:
- 查看k8s集群中各個組件證書過期時間1.14版本后有下面這個命令:
$kubeadm alpha certs check-expiration?
- 查看etcd證書過期時間:
$cfssl-certinfo -cert /etc/kubernetes/pki/etcd/server.crt | grep not
$openssl x509 -in etcd.pem -noout -text |grep ' Not '
- 查看集群證書過期時間:
$openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -text |grep ' Not '
$for i in `ls /etc/kubernetes/pki/*.crt`; do echo $i ; openssl x509 -in $i -noout -dates | grep notAfter; done
2套蒂、證書過期處理:
2.1钞支、客戶端kubelet證書輪換自動續(xù)期:
kubectl證書輪換是在當(dāng)前證書即將過期時,將自動生成新的密鑰操刀,并從k8s api申請新的證書烁挟。
kubelet 進程接收 --rotate-certificates 參數(shù),該參數(shù)決定 kubelet 在當(dāng)前使用的證書即將到期時骨坑,是否會自動申請新的證書撼嗓。 由于證書輪換是 beta 特性,必須通過參數(shù) --feature-gates=RotateKubeletClientCertificate=true 進行啟用欢唾。
kube-controller-manager 進程接收 --experimental-cluster-signing-duration 參數(shù)且警,該參數(shù)控制證書簽發(fā)的有效期限。
當(dāng) kubelet 啟動時礁遣,如被配置為自舉(使用--bootstrap-kubeconfig 參數(shù))斑芜,kubelet 會使用其初始證書連接到 Kubernetes API ,并發(fā)送證書簽名的請求祟霍。 可以通過以下方式查看證書簽名請求的狀態(tài):
$kubectl get csr
最初杏头,來自節(jié)點上 kubelet 的證書簽名請求處于 Pending 狀態(tài)。 如果證書簽名請求滿足特定條件沸呐, 控制管理器會自動批準(zhǔn)醇王,此時請求會處于 Approved 狀態(tài)。 接下來崭添,控制器管理器會簽署證書寓娩, 證書的有效期限由 --experimental-cluster-signing-duration 參數(shù)指定,簽署的證書會被附加到證書簽名請求中呼渣。
Kubelet 會從 Kubernetes API 取回簽署的證書棘伴,并將其寫入磁盤,存儲位置通過 --cert-dir 參數(shù)指定徙邻。 然后 kubelet 會使用新的證書連接到 Kubernetes API排嫌。
當(dāng)簽署的證書即將到期時,kubelet 會使用 Kubernetes API缰犁,發(fā)起新的證書簽名請求淳地。 同樣地怖糊,控制管理器會自動批準(zhǔn)證書請求,并將簽署的證書附加到證書簽名請求中颇象。 Kubelet 會從 Kubernetes API 取回簽署的證書伍伤,并將其寫入磁盤。 然后它會更新與 Kubernetes API 的連接遣钳,使用新的證書重新連接到 Kubernetes API扰魂。
1)、開啟證書輪換:
- 修改kubelet啟動配置文件增加如下參數(shù)
在/etc/systemd/system/kubelet.service.d/10-kubeadm.conf 增加如下參數(shù):
Environment="KUBELET_EXTRA_ARGS=--feature-gates=RotateKubeletServerCertificate=true --feature-gates=RotateKubeletClientCertificate=true"
- 修改kube-controller-manager.yaml配置文件
在/etc/kubernetes/manifests/kube-controller-manager.yaml 添加如下參數(shù):
- command:
- kube-controller-manager
- --experimental-cluster-signing-duration=87600h0m0s #10年
- --feature-gates=RotateKubeletServerCertificate=true
- ....
- 創(chuàng)建 rbac 對象
創(chuàng)建rbac對象蕴茴,允許節(jié)點輪換kubelet server證書:
$vi kubelet-ca-update.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: system:certificates.k8s.io:certificatesigningrequests:selfnodeserver
rules:
- apiGroups:
- certificates.k8s.io
resources:
- certificatesigningrequests/selfnodeserver
verbs:
- create
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kubeadm:node-autoapprove-certificate-server
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:certificates.k8s.io:certificatesigningrequests:selfnodeserver
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:nodes
$kubectl create -f kubelet-ca-update.yaml
2.2劝评、重新生成默認(rèn)一年時長證書
在集群已經(jīng)部署好的情況下集群的證書過期,可以選擇對證書進行重新生成倦淀。
單master或多master集群(etcd在集群內(nèi))處理:
1)蒋畜、備份原先的證書文件和配置文件:
$cp -rp /etc/kubernetes /etc/kubernetes.bak
2)、刪除過期的證書文件:
(注意:1.13.0以下的版本需要刪除舊的證書撞叽,不然不會重新生成姻成,1.13.5以上的就不用操作了會自動更新的。ca.cer\ca.key\sa的這些證書不要刪除ca默認(rèn)就是10年沒必要重新生成愿棋,同時kubeadm在重新生成apiserver這些組件的證書的時候需要使用ca證書來進行簽發(fā))
$ rm -f /etc/kubernetes/pki/apiserver*
$ rm -f /etc/kubernetes/pki/front-proxy-client.*
$ rm -rf /etc/kubernetes/pki/etcd/healthcheck-client.*
$ rm -rf /etc/kubernetes/pki/etcd/server.*
$ rm -rf /etc/kubernetes/pki/etcd/peer.*
3)科展、獲取k8s集群初始化的配置文件yaml文件:
$kubeadm config view > kubeadm.yaml
4)、生成新的證書文件
生成證書有兩種方式一種是重新生成私鑰和公鑰糠雨,一種是使用存在的私鑰重新簽發(fā)才睹。
- 生成相應(yīng)組件的證書(此格式會使用相應(yīng)組件的原來的key重新簽發(fā)證書):
$kubeadm alpha phase certs renew etcd-healthcheck-client --config kubeadm.yaml
$kubeadm alpha phase certs renew etcd-peer --config kubeadm.yaml
$kubeadm alpha phase certs renew etcd-server --config kubeadm.yaml
$kubeadm alpha phase certs renew front-proxy-client--config kubeadm.yaml
$kubeadm alpha phase certs renew apiserver-etcd-client --config kubeadm.yaml
$kubeadm alpha phase certs renew apiserver-kubelet-client --config kubeadm.yaml
$kubeadm alpha phase certs renew apiserver --config kubeadm.yaml
##或者重新簽發(fā)全部組件的證書
$kubeadm alpha phase certs renew all --config kubeadm.yaml
或如下格式(這種格式需要刪除原來存在的相應(yīng)證書和key,此格式會重新創(chuàng)建相應(yīng)組件的私鑰和公鑰):
$kubeadm init phase certs apiserver --config kubeadm.yaml
- 生成新的配置文件(admin.conf见秤、controller-manager.conf砂竖、kubelet.conf真椿、scheduler.conf):
$rm -f admin.conf kubelet.conf controller-manager.conf scheduler.conf
$kubeadm alpha phase kubeconfig all --config kubeadm.yaml
或如下格式重新生成相關(guān)組件的配置文件:
$kubeadm init phase kubeconfig all --config ./kubeadm.yaml
- 將新生成的admin.conf文件覆蓋掉.kube/config文件:
$mv $HOME/.kube/config $HOME/.kube/config.old
$cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$chown $(id -u):$(id -g) $HOME/.kube/config
$sudo chmod 644 $HOME/.kube/config
5)鹃答、各節(jié)點重啟kubelet或相關(guān)組件:
$ systemctl restart kubelet
或重新啟動docker容器中的kube-apiserver,kube-controller,kube-scheduler,etcd
注意:若集群式采用高可用ha方式安裝的話有所區(qū)別,etd的相關(guān)證書需要另外簽發(fā)操作突硝,要是之前搭建集群的時候已經(jīng)使用了長時間的則僅僅需要處理k8s其它組件的證書即可测摔。
k8s cluster ha多master集群(etcd在集群外)處理:
1)、備份證書和配置:
$cp -rp /etc/kubernetes /etc/kubernetes.bak
$cp -rm /etc/etcd/ssl /etc/etcd/ssl.bak
2)解恰、刪除過期的證書文件:
(注意:1.13.0以下的版本需要刪除舊的證書锋八,不然不會重新生成,1.13.5以上的就不用操作了會自動更新的护盈;ca.cer\ca.key\sa的這些證書不要刪除ca默認(rèn)就是10年沒必要重新生成挟纱,同時kubeadm在重新生成apiserver這些組件的證書的時候需要使用ca證書來進行簽發(fā))
$ rm -f /etc/kubernetes/pki/apiserver*
$ rm -f /etc/kubernetes/pki/front-proxy-client.*
$ rm -rf /etc/kubernetes/pki/etcd/healthcheck-client.*
$ rm -rf /etc/kubernetes/pki/etcd/server.*
$ rm -rf /etc/kubernetes/pki/etcd/peer.*
3)、獲取k8s集群初始化的配置文件yaml文件:
$kubeadm config view > kubeadm.yaml
4)腐宋、etcd證書續(xù)期(重新創(chuàng)建紊服,etcd要是沒有過期不用管這步):
以下這三個證書文件是之前高可用集群創(chuàng)建的時候用于解決etcd證書問題檀轨,現(xiàn)在要依據(jù)下面三個文件重新創(chuàng)建etcd證書。
- 創(chuàng)建etcd的根證書配置:
$cat > ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "876000h"
},
"profiles": {
"kubernetes-Soulmate": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "876000h"
}
}
}
}
EOF
- 創(chuàng)建etcd的根證書簽發(fā)配置:
$cat > ca-csr.json <<EOF
{
"CN": "kubernetes-Soulmate",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "hangzhou",
"L": "hangzhou",
"O": "k8s",
"OU": "System"
}
]
}
EOF
- 創(chuàng)建etcd的證書簽發(fā)列表配置:
$cat > etcd-csr.json <<EOF
{
"CN": "etcd",
"hosts": [
"127.0.0.1",
"10.10.8.141",
"10.10.8.142",
"10.10.8.143"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "hangzhou",
"L": "hangzhou",
"O": "k8s",
"OU": "System"
}
]
}
EOF
- 生成etcd的證書:
$cfssl gencert -initca ca-csr.json | cfssljson -bare ca
$cfssl gencert -ca=ca.pem \
-ca-key=ca-key.pem \
-config=ca-config.json \
-profile=kubernetes-Soulmate etcd-csr.json | cfssljson -bare etcd
- 將新生成的etcd證書拷貝到本節(jié)點上:
$cp -rp ca.pem etcd-key.pem etcd.pem /etc/etcd/ssl/
- 將新生成的etcd證書拷貝到各個etcd節(jié)點上:
$scp -r /etc/etcd/ssl root@${other_node}:/etc/etcd/
注意:重啟etcd服務(wù)(記住欺嗤,要3個節(jié)點一起重啟参萄,不然會hang住)
5)、重新生成k8s其它組件證書和admin.conf配置文件
- 重新生成處etcd組件外的其它組件證書(不需要生成etcd相關(guān)的證書):
$kubeadm alpha certs renew front-proxy-client --config kubeadm.yaml
$kubeadm alpha certs renew apiserver-kubelet-client --config kubeadm.yaml
$kubeadm alpha certs renew apiserver --config kubeadm.yaml
- 重新生成配置文件(admin.conf煎饼、controller-manager.conf讹挎、kubelet.conf吆玖、scheduler.conf):
$kubeadm alpha phase kubeconfig all --config kubeadm.yaml
或版本不一樣可能kubeadm命令不一樣可以用下面這個命令:
$kubeadm init phase kubeconfig all --config ./kubeadm.yaml
6)、將新生成的admin配置文件覆蓋掉原本的admin文件(非root用戶處理):
$mv $HOME/.kube/config $HOME/.kube/config.old
$cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
$chown $(id -u):$(id -g) $HOME/.kube/config
$sudo chmod 777 $HOME/.kube/config
7)沾乘、將新生成的pki目錄下的證書文件和配置文件拷貝到其他master節(jié)點上:
$scp pki/* root@${other_master}:/etc/kubernetes/pki/
$scp *.conf root@${other_master}:/etc/kubernetes/
8)、各節(jié)點重啟kubelet:
- 重啟節(jié)點上的kubelet
$ systemctl restart kubelet
或者重啟api意鲸、scheduler烦周、controller三個容器
注意:查看kube-controller-manager容器是否還有報"Unauthorized",若有則重啟docker怎顾。
2.3、編譯kubeadm延長證書時長:
1.14后的通過NewSelfSignedCACert這個方法簽發(fā)的證書都默認(rèn)為10年有效期了夭委,但這個只影響部分證書,但這樣還沒滿足我們的需求募强,部分證書是通過NewSignedCert這個方法簽發(fā)株灸,而這個方法簽發(fā)的證書默認(rèn)只有一年有效期。
1)擎值、下載k8s源代碼修改相關(guān)證書時長:
$vi staging/src/k8s.io/client-go/util/cert/cert.go
func NewSelfSignedCACert(cfg Config, key crypto.Signer) (*x509.Certificate, error) {
now := time.Now()
tmpl := x509.Certificate{
SerialNumber: new(big.Int).SetInt64(0),
Subject: pkix.Name{
CommonName: cfg.CommonName,
Organization: cfg.Organization,
},
NotBefore: now.UTC(),
//這里已經(jīng)調(diào)整為10年有效期
NotAfter: now.Add(duration365d * 10).UTC(),
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
BasicConstraintsValid: true,
IsCA: true,
}
certDERBytes, err := x509.CreateCertificate(cryptorand.Reader, &tmpl, &tmpl, key.Public(), key)
if err != nil {
return nil, err
}
return x509.ParseCertificate(certDERBytes)
}
$vi cmd/kubeadm/app/util/pkiutil/pki_helpers.go
func NewSignedCert(cfg *certutil.Config, key crypto.Signer, caCert *x509.Certificate, caKey crypto.Signer) (*x509.Certificate, error) {
serial, err := rand.Int(rand.Reader, new(big.Int).SetInt64(math.MaxInt64))
if err != nil {
return nil, err
}
if len(cfg.CommonName) == 0 {
return nil, errors.New("must specify a CommonName")
}
if len(cfg.Usages) == 0 {
return nil, errors.New("must specify at least one ExtKeyUsage")
}
certTmpl := x509.Certificate{
Subject: pkix.Name{
CommonName: cfg.CommonName,
Organization: cfg.Organization,
},
DNSNames: cfg.AltNames.DNSNames,
IPAddresses: cfg.AltNames.IPs,
SerialNumber: serial,
NotBefore: caCert.NotBefore,
// 默認(rèn)只有一年有效期,改為10年
NotAfter: time.Now().Add(kubeadmconstants.CertificateValidity).UTC(),?
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature,
ExtKeyUsage: cfg.Usages,
}
certDERBytes, err := x509.CreateCertificate(cryptorand.Reader, &certTmpl, caCert, key.Public(), caKey)
if err != nil {
return nil, err
}
return x509.ParseCertificate(certDERBytes)
}
##根據(jù)import 找到相關(guān)文件并修改
vim cmd/kubeadm/app/constants/constants.go?
將CertificateValidity = time.Hour * 24 * 365 改為 time.Hour * 24 * 365 * 10
2)屹蚊、編譯:
docker run --rm -v 你修改后的代碼目錄:/go/src/k8s.io/kubernetes -it icyboy/k8s_build:v1.11.5 bash
$cd /go/src/k8s.io/kubernetes
## 編譯kubeadm, 這里主要編譯kubeadm 即可
make all WHAT=cmd/kubeadm GOFLAGS=-v
## 編譯kubelet
$make all WHAT=cmd/kubelet GOFLAGS=-v
## 編譯kubectl
$make all WHAT=cmd/kubectl GOFLAGS=-v
編譯完產(chǎn)物在 _output/bin/kubeadm 目錄下將kubeadm 文件拷貝出來进每,替換系統(tǒng)中的kubeadm
3)、替換本地kubeadm:
$chmod +x kubeadm && cp -f kubeadm /usr/bin
4)田晚、備份原有的證書和conf文件:
## 備份本地舊的證書
$cp -rp /etc/kubernetes /etc/kubernetes.bak
5)、重新生成10年的證書和新的conf文件:
## 獲取k8s集群初始化的配置文件yaml文件
$kubeadm config view > kubeadm.yaml
## 生成新的證書
$kubeadm alpha phase certs renew all --config ~/kubeadm.yaml
## 根據(jù)新證書重新生成新的配置文件
$kubeadm alpha phase kubeconfig all --config ~/kubeadm.yaml
或版本不一樣可能kubeadm命令不一樣可以用下面這個命令:
$kubeadm init phase kubeconfig all --config ./kubeadm.yaml
## 替換老的config文件
$cp -f /etc/kubernetes/admin.conf ~/.kube/config
6)芹壕、重啟個節(jié)點kubelet:
$systemctl restart kubelet