k8s過期證書解決方案


環境介紹:

#centos7.7
#kubernetes 1.16.0

#Step 1:查看證書過期時間(一年有效期)

openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -text |grep ' Not '
            Not Before: May 24 03:31:50 2019 GMT
            Not After : May 23 03:31:50 2020 GMT


#Step 2:下載1.16.0源碼

# 下載kubernetes v1.16.0源碼,修改關鍵部分代碼的證書生產有效期
# github下載源碼:https://github.com/kubernetes/kubernetes
# 到release下載想到的版本源碼,這裏我下載v1.16.0

# step 3:解壓並且修改源代碼
查看網上的資料主要有兩個地方需要修改

vim ./staging/src/k8s.io/client-go/util/cert/cert.go
# 這個方法裏面NotAfter:              now.Add(duration365d * 10).UTC()
# 默認有效期就是10年,改成50年
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(),
                // NotAfter:              now.Add(duration365d * 10).UTC(),
                NotAfter:              now.Add(duration365d * 50).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)
}

docker run --rm -it -v /root/kubernetes-1.16.0:/go/src/k8s.io/kubernetes \
mirrorgooglecontainers/kube-cross:v1.12.10-1 bash


vim cmd/kubeadm/app/util/pkiutil/pki_helpers.go
# 這個方法裏面看到NotAfter:     time.Now().Add(kubeadmconstants.CertificateValidity).UTC()
# 參數裏面是一個常量kubeadmconstants.CertificateValidity
# 所以這裏可以不修改,我去看看源碼能不能找到這個常量的賦值位置
#func NewSignedCert(cfg *certutil.Config, key crypto.Signer, caCert *x509.Certificate, caKey crypto.Signer) (*x509.Certificate, error) {        serial, err := cryptorand.Int(cryptorand.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,
#                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)
#} 

結果在這裏找到kubeadmconstants.CertificateValidity的定義

vim ./cmd/kubeadm/app/constants/constants.go
// 就是這個常量定義CertificateValidity,我改成*50年
const (
        // KubernetesDir is the directory Kubernetes owns for storing various configuration files
        KubernetesDir = "/etc/kubernetes"
        // ManifestsSubDirName defines directory name to store manifests
        ManifestsSubDirName = "manifests"
        // TempDirForKubeadm defines temporary directory for kubeadm
        // should be joined with KubernetesDir.
        TempDirForKubeadm = "tmp"

        // CertificateValidity defines the validity for all the signed certificates generated by kubeadm
        // CertificateValidity = time.Hour * 24 * 365
        CertificateValidity = time.Hour * 24 * 365 * 50

        // CACertAndKeyBaseName defines certificate authority base name
        CACertAndKeyBaseName = "ca"
        // CACertName defines certificate name
        CACertName = "ca.crt"
        // CAKeyName defines certificate name
        CAKeyName = "ca.key"
源代碼改好了,接下來就是編譯kubeadm了

#Step 4:編譯kubeadm

剛開始嘗試服務器安裝yum -y install go環境,執行make方法編譯,發現特別慢,而且編譯顯示的內容也不對(get "gotest.tools/gotestsum":found meta tag get.metaImport{...}等內容),(也可能是golang版本是13不支持的原因但是沒有測試)只能嘗試下載容器,在容器裏面編譯,通過網上找資料,發現官網原來有提供一個k8s.gcr.io/kube-cross的容器用於對代碼做編譯。
由於我不能***,如果不能***的用戶,到https://hub.docker.com搜索 kube-cross關鍵字,我找了一個版本比較新的mirrorgooglecontainers/kube-cross:v1.12.10-1鏡像,v1.12.10-1應該就是鏡像裏面go環境的版本。

注:在使用mirrorgooglecontainers/kube-cross:v1.12.10-1編譯之前,我試過下載一個go版本是v.1.11.x的鏡像,編譯會報錯,大概意思是我下載的kubernetes源碼必須用v1.12.x才能編譯。

拉取鏡像

docker pull mirrorgooglecontainers/kube-cross:v1.12.10-1

# 運行容器,並進入到容器內部
docker run --rm -it -v 你修改源碼後的kubernetes根目錄:/go/src/k8s.io/kubernetes \
mirrorgooglecontainers/kube-cross:v1.12.10-1 bash

#例如我的源代碼放到了/root/kubernetes-1.16.0下
docker run --rm -it -v /root/kubernetes-1.16.0:/go/src/k8s.io/kubernetes \
mirrorgooglecontainers/kube-cross:v1.12.10-1 bash

# cd到容器內部的掛載路徑,可以ls -al查看一下里面的文件是不是主機掛載目錄的源碼文件
cd /go/src/k8s.io/kubernetes

# 編譯kubeadm, 這裏主要編譯kubeadm 即可
make all WHAT=cmd/kubeadm GOFLAGS=-v

#部分編譯過程節選,用make編譯不出現以下過程的可能是出問題了
#k8s.io/kubernetes/vendor/k8s.io/legacy-cloud-providers/vsphere/vclib/diskmanagers
#k8s.io/kubernetes/vendor/k8s.io/legacy-cloud-providers/vsphere
#k8s.io/kubernetes/vendor/github.com/GoogleCloudPlatform/k8s-cloud-provider/pkg/cloud/mock
#k8s.io/kubernetes/vendor/k8s.io/legacy-cloud-providers/gce
#k8s.io/kubernetes/pkg/volume/vsphere_volume
#k8s.io/kubernetes/pkg/cloudprovider/providers
#k8s.io/kubernetes/pkg/volume/gcepd
#。。。。。。。。


# 編譯kubelet
# make all WHAT=cmd/kubelet GOFLAGS=-v

# 編譯kubectl
# make all WHAT=cmd/kubectl GOFLAGS=-v

#編譯完產物在 _output/bin/kubeadm 目錄下,
#其中bin是使用了軟連接
#真實路徑是_output/local/bin/linux/amd64/kubeadm
編譯成功後,可以退出容器,能看到掛載路徑中已經有編譯好的kubeadm

路徑./_output/local/bin/linux/amd64/kubeadm
#例:/root/kubernetes-1.16.0/_output/local/bin/linux/amd64

#Step 5:替換掉正在使用的kubeadm

cp /usr/bin/kubeadm /usr/bin/kubeadm.bak
cp _output/local/bin/linux/amd64/kubeadm /usr/bin/kubeadm

#Step 6:執行命令更新證書

可以先備份證書,證書在/etc/kubernetes/pki,我這裏就不備份了

1、檢查證書到期時間

kubeadm alpha certs check-expiration
CERTIFICATE                EXPIRES                  RESIDUAL TIME   EXTERNALLY MANAGED
admin.conf                 Nov 20, 2069 04:30 UTC   49y             no      
apiserver                  Nov 20, 2069 04:30 UTC   49y             no      
apiserver-etcd-client      Nov 20, 2069 04:30 UTC   49y             no      
apiserver-kubelet-client   Nov 20, 2069 04:30 UTC   49y             no      
controller-manager.conf    Nov 20, 2069 04:30 UTC   49y             no      
etcd-healthcheck-client    Nov 20, 2069 04:30 UTC   49y             no      
etcd-peer                  Nov 20, 2069 04:30 UTC   49y             no      
etcd-server                Nov 20, 2069 04:30 UTC   49y             no      
front-proxy-client         Nov 20, 2069 04:30 UTC   49y             no      
scheduler.conf             Nov 20, 2069 04:30 UTC   49y             no       

#使用renew命令即可更新證書,續訂全部證書(適用於1.14版本及以上:需要外網環境)
#***如果是在斷網的情況下必須把有效期改好,再部署設備,否則後期證書過期手動更新證書非常麻煩,切記,切記,切記
kubeadm alpha certs renew all 


#如果你是舊版 kubeadm版本,那麼可以用這個腳本來更新你的證書,生成證書默認有效期爲10年(3650天),你可以更改腳本里面的CAER_DAYS變量來達到你想要的證書有效期,單位是“天”
#下載地址:https://github.com/yuyicai/update-kube-cert/blob/master/README.md
#更新kubeadm生成的證書有效期爲10年

低版本證書手動更新

#下面爲低版本更新僅供參考沒有測試
#更新證書(適用於1.13版本及以下)
#在1.13版本及之前,需要使用kubeadm alpha phase certs來生成新的證書
#
#移動老的證書
#注意是: 必須移動,不然會使用現有的證書,不會重新生成!
#
#cd /etc/kubernetes
#mkdir -p pki.bak/etcd
#mkdir conf.bak
#mv pki/apiserver* ./pki.bak/
#mv pki/front-proxy-client.* ./pki.bak/
#mv pki/etcd/healthcheck-client.* ./pki.bak/etcd/
#mv pki/etcd/peer.* ./pki.bak/etcd/
#mv pki/etcd/server.* ./pki.bak/etcd/
#mv ./admin.conf ./conf.bak/
#mv ./kubelet.conf ./conf.bak/
#mv ./controller-manager.conf ./conf.bak/
#mv ./scheduler.conf ./conf.bak/
#注意ca的不動!
#
#生成新的證書
#建議不要重新生成ca證書,因爲更新了ca證書,集羣節點就需要手工操作,才能讓集羣正常(會涉及重新join)
#
#kubeadm alpha phase certs etcd-healthcheck-client --config /tmp/cluster.yaml
#
#kubeadm alpha phase certs etcd-peer --config /tmp/cluster.yaml
#
#kubeadm alpha phase certs etcd-server --config /tmp/cluster.yaml
#
#kubeadm alpha phase certs front-proxy-client--config /tmp/cluster.yaml
#
#kubeadm alpha phase certs apiserver-etcd-client --config /tmp/cluster.yaml
#
#kubeadm alpha phase certs apiserver-kubelet-client --config /tmp/cluster.yaml
#
#kubeadm alpha phase certs apiserver --config /tmp/cluster.yaml
#
#kubeadm alpha phase certs sa --config /tmp/cluster.yaml
#更新kubeconfig文件
#生成新的配置文件
#
#kubeadm alpha phase kubeconfig all --apiserver-advertise-address=${MASTER_API_SERVER_IP}
#將新生成的admin配置文件覆蓋掉原本的admin文件
#
#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
#完成後重啓kube-apiserver,kube-controller,kube-scheduler,etcd這4個容器
#
#如果有多臺master,則將第一臺生成的相關證書拷貝到其餘master即可。
#
#查看證書更新後的使用週期
## openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -text |grep ' Not '
#            Not Before: May 24 03:31:50 2019 GMT
#            Not After : Sep  9 02:36:46 2020 GMT
#
#參考
#https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm-alpha/

證書更新完畢就不用擔心k8s證書過期問題了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章