目录:
1、证书过期时间查询
2、证书过期处理
2.1、客户端kubelet证书自动续期
2.2、重新生成默认一年时长证书
2.3、编译kubeadm延长证书时长
简介:
k8s集群分为两种证书:
- 用于集群 Master、Etcd等通信的证书;
- 用于集群中客户端 Kubelet组件和api通信的证书;
我们在搭建 Kubernetes 集群时,一般只声明用于集群 Master、Etcd等通信的证书有效期为10年或者更久,但未声明集群 Kubelet 组件证书 ,Kubelet组件证书默认有效期为1年。集群运行1年以后就会导致报 certificate has expired or is not yet valid 错误,导致集群 Node不能于集群 Master正常通信。
1.14后的版本可以使用这个命令查看过期时间,如下:
$kubeadm alpha certs check-expiration
kubeadm初始化配置文件:
kubeadm.yaml是一个kubeadm用于集群初始化时候的一个配置文件,这个配置文件主要用于集群初始化的时候指定一些自定义的参数和配置信息。我们在使用kubeadm更新k8s集群证书的时候会使用到这个配置文件。
- 获取一个创建好的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"
注意:若我们集群的证书已经过期了不能使用kubeadm获取到集群的初始化配置文件,那么我们可以手写一个简单的配置文件,写这个文件是因为获取不到集群的基本配置文件的时候kubeadm会去k8s官网找一个stable-1.txt的文件(这个文件的内容就是关于k8s的版本信息)。
- 创建一个简单的kubeadm的配置文件
$vi kubeadm.yaml
apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
kubernetesVersion: v1.13.5 #--------这里改成你集群对应的版本
imageRepository: k8s.gcr.io #-------k8s官方的镜像仓库
上面文件主要作用是告诉kubeadm中Kubernetes集群的版本,以防止它去网上查找,因为被墙,会报错如下:
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证书轮换自动续期:
kubectl证书轮换是在当前证书即将过期时,将自动生成新的密钥,并从k8s api申请新的证书。
kubelet 进程接收 --rotate-certificates 参数,该参数决定 kubelet 在当前使用的证书即将到期时,是否会自动申请新的证书。 由于证书轮换是 beta 特性,必须通过参数 --feature-gates=RotateKubeletClientCertificate=true 进行启用。
kube-controller-manager 进程接收 --experimental-cluster-signing-duration 参数,该参数控制证书签发的有效期限。
当 kubelet 启动时,如被配置为自举(使用--bootstrap-kubeconfig 参数),kubelet 会使用其初始证书连接到 Kubernetes API ,并发送证书签名的请求。 可以通过以下方式查看证书签名请求的状态:
$kubectl get csr
最初,来自节点上 kubelet 的证书签名请求处于 Pending 状态。 如果证书签名请求满足特定条件, 控制管理器会自动批准,此时请求会处于 Approved 状态。 接下来,控制器管理器会签署证书, 证书的有效期限由 --experimental-cluster-signing-duration 参数指定,签署的证书会被附加到证书签名请求中。
Kubelet 会从 Kubernetes API 取回签署的证书,并将其写入磁盘,存储位置通过 --cert-dir 参数指定。 然后 kubelet 会使用新的证书连接到 Kubernetes API。
当签署的证书即将到期时,kubelet 会使用 Kubernetes API,发起新的证书签名请求。 同样地,控制管理器会自动批准证书请求,并将签署的证书附加到证书签名请求中。 Kubelet 会从 Kubernetes API 取回签署的证书,并将其写入磁盘。 然后它会更新与 Kubernetes API 的连接,使用新的证书重新连接到 Kubernetes API。
1)、开启证书轮换:
- 修改kubelet启动配置文件增加如下参数
在/etc/systemd/system/kubelet.service.d/10-kubeadm.conf 增加如下参数:
Environment="KUBELET_EXTRA_ARGS=--feature-gates=RotateKubeletServerCertificate=true --feature-gates=RotateKubeletClientCertificate=true"
- 修改kube-controller-manager.yaml配置文件
在/etc/kubernetes/manifests/kube-controller-manager.yaml 添加如下参数:
- command:
- kube-controller-manager
- --experimental-cluster-signing-duration=87600h0m0s #10年
- --feature-gates=RotateKubeletServerCertificate=true
- ....
- 创建 rbac 对象
创建rbac对象,允许节点轮换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、重新生成默认一年时长证书
在集群已经部署好的情况下集群的证书过期,可以选择对证书进行重新生成。
单master或多master集群(etcd在集群内)处理:
1)、备份原先的证书文件和配置文件:
$cp -rp /etc/kubernetes /etc/kubernetes.bak
2)、删除过期的证书文件:
(注意:1.13.0以下的版本需要删除旧的证书,不然不会重新生成,1.13.5以上的就不用操作了会自动更新的。ca.cer\ca.key\sa的这些证书不要删除ca默认就是10年没必要重新生成,同时kubeadm在重新生成apiserver这些组件的证书的时候需要使用ca证书来进行签发)
$ 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)、生成新的证书文件
生成证书有两种方式一种是重新生成私钥和公钥,一种是使用存在的私钥重新签发。
- 生成相应组件的证书(此格式会使用相应组件的原来的key重新签发证书):
$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
##或者重新签发全部组件的证书
$kubeadm alpha phase certs renew all --config kubeadm.yaml
或如下格式(这种格式需要删除原来存在的相应证书和key,此格式会重新创建相应组件的私钥和公钥):
$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
或如下格式重新生成相关组件的配置文件:
$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)、各节点重启kubelet或相关组件:
$ systemctl restart kubelet
或重新启动docker容器中的kube-apiserver,kube-controller,kube-scheduler,etcd
注意:若集群式采用高可用ha方式安装的话有所区别,etd的相关证书需要另外签发操作,要是之前搭建集群的时候已经使用了长时间的则仅仅需要处理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默认就是10年没必要重新生成,同时kubeadm在重新生成apiserver这些组件的证书的时候需要使用ca证书来进行签发)
$ 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证书续期(重新创建,etcd要是没有过期不用管这步):
以下这三个证书文件是之前高可用集群创建的时候用于解决etcd证书问题,现在要依据下面三个文件重新创建etcd证书。
- 创建etcd的根证书配置:
$cat > ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "876000h"
},
"profiles": {
"kubernetes-Soulmate": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "876000h"
}
}
}
}
EOF
- 创建etcd的根证书签发配置:
$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
- 创建etcd的证书签发列表配置:
$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证书拷贝到本节点上:
$cp -rp ca.pem etcd-key.pem etcd.pem /etc/etcd/ssl/
- 将新生成的etcd证书拷贝到各个etcd节点上:
$scp -r /etc/etcd/ssl root@${other_node}:/etc/etcd/
注意:重启etcd服务(记住,要3个节点一起重启,不然会hang住)
5)、重新生成k8s其它组件证书和admin.conf配置文件
- 重新生成处etcd组件外的其它组件证书(不需要生成etcd相关的证书):
$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节点上:
$scp pki/* root@${other_master}:/etc/kubernetes/pki/
$scp *.conf root@${other_master}:/etc/kubernetes/
8)、各节点重启kubelet:
- 重启节点上的kubelet
$ systemctl restart kubelet
或者重启api、scheduler、controller三个容器
注意:查看kube-controller-manager容器是否还有报"Unauthorized",若有则重启docker。
2.3、编译kubeadm延长证书时长:
1.14后的通过NewSelfSignedCACert这个方法签发的证书都默认为10年有效期了,但这个只影响部分证书,但这样还没满足我们的需求,部分证书是通过NewSignedCert这个方法签发,而这个方法签发的证书默认只有一年有效期。
1)、下载k8s源代码修改相关证书时长:
$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(),
//这里已经调整为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,
// 默认只有一年有效期,改为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)
}
##根据import 找到相关文件并修改
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
编译完产物在 _output/bin/kubeadm 目录下将kubeadm 文件拷贝出来,替换系统中的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
## 根据新证书重新生成新的配置文件
$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)、重启个节点kubelet:
$systemctl restart kubelet