kuelet在10250端口监听,使用该证书提供https服务,检查证书过期时间的指令:
[dcos@cc-cq2b-x86-mgr-3 ~]$ openssl x509 -in /var/lib/kubelet/pki/kubelet.crt -noout -text|grep 'Not After'
Not After : Jan 15 12:17:59 2022 GMT
由于设计问题,kubernetes官方目前仅仅支持kubelet服务证书的"半自动"轮替,本文就kubelet的服务器端证书的处理方法做些介绍
修复方法
官方的"半自动"证书轮替方案
官方的半自动体现在:
1、kubelet的证书在临近过期时只支持自动创建csr请求,需要使用kubectl指令手工批准kubelet的csr请求
2、需要登录所有节点挨个处理
具体的处理步骤如下:
1、登录kubelet server证书失效的节点
2、修改kubelet daemon配置文件: /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf, 增加以下参数配置:
Environment="KUBELET_EXTRA_ARGS=--rotate-certificates=true --rotate-server-certificates=true"
3、重启节点kubelet
sudo systemctl daemon-reload
sudo service kubelet restart
3、切换到可执行kubectl的节点上查询kubelet生成的csr请求
kubectl get csr
4、切换到可执行kubectl的节点上批准csr请求
kubectl certificate approve <csr请求>
5、切换到原节点验证kubelet的证书是否已更新
echo | openssl s_client -servername 127.0.0.1 -connect 127.0.0.1:10250 2>/dev/null | openssl x509 -noout -text
有两个解决方案:
- 删除过期的证书,让kubelet自动生成一个有效期为1年的证书,可作为临时解决方案
- 手工生成一个长效证书,免去后续维护证书的麻烦
手工生成长效证书
官方的半自动处理方案签发的证书也只有一年,实际上还是不满足生产环境的运维需求,可以直接使用openssl为kubelet生成一个符合kubernetes证书设计规范,有效期为10年的证书,替换所有节点的kubelet证书。
需要替换的证书文件为: /var/lib/kubelet/pki/kubelet.crt
,私有密匙可以直接用原来的,不用替换
生成证书的脚本如下:
#!/bin/bash
error() {
echo "${@}"
exit 1
}
script_dir=$(cd `dirname $0`;pwd)
new_kubelet_cert=${script_dir}/kubelet.crt
new_kubelet_csr=${script_dir}/kubelet.csr
new_kubelet_cert_days=3650
CA_CERT=/etc/kubernetes/key/dcos_ca.crt
CA_KEY=/etc/kubernetes/key/dcos_ca.key
CURRENT_KUBELET_CERT=/var/lib/kubelet/pki/kubelet.crt
CURRENT_KUBELET_KEY=/var/lib/kubelet/pki/kubelet.key
check_file() {
f=$1
if [ ! -f $f ]; then
error "can't find file: $f"
fi
if [ ! -r $f ]; then
error "file $f can't be readed"
fi
}
for item in $CA_CERT $CA_KEY $CURRENT_KUBELET_CERT $CURRENT_KUBELET_KEY; do
check_file $item
done
subj_str=`openssl x509 -in ${CURRENT_KUBELET_CERT} -noout -text|grep 'Subject *: *CN'`
subj=`echo ${subj_str}|awk '{print $NF}'|tr -d '\n'|sed -e 's/ *//'`
if [ -z $subj ]; then
error "can't find CN record of current kubelet crt: ${CURRENT_KUBELET_CERT}"
fi
#subj is something like "CN=10.10.34.180@1656319809"
if [[ ! "${subj}" =~ ((0-9|1?[0-9][0-9]|2[0-4][0-9]|25[0-9])\.){3}(0-9|1?[0-9][0-9]|2[0-4][0-9]|25[0-9])@[0-9]+ ]]; then
error "invalid subj data: ${subj}"
fi
subj="/CN=${subj}"
#alt_name: "IP:10.10.34.180"
alt_name=`openssl x509 -in ${CURRENT_KUBELET_CERT} -noout -text|grep -A1 'Alternative'|tail -n 1|awk -F':' '{print $2}'`
if [ -z $alt_name ]; then
alt_name=`echo ${subj}|awk -F'[=@]+' '{print $2}'`
fi
if [[ ! "${alt_name}" =~ ((0-9|1?[0-9][0-9]|2[0-4][0-9]|25[0-9])\.){3}(0-9|1?[0-9][0-9]|2[0-4][0-9]|25[0-9]) ]]; then
error "invalid alt_name: ${alt_name}"
fi
alt_name="IP:${alt_name}"
csr_conf="distinguished_name = dn\n[dn]\n[v3_ext]\nkeyUsage = critical, digitalSignature, keyEncipherment, Certificate Sign\n"
printf "${csr_conf}extendedKeyUsage = serverAuth\nsubjectAltName = ${alt_name}\n" > csr.conf
check_file csr.conf
openssl req -new -key ${CURRENT_KUBELET_KEY} -subj "${subj}" -reqexts v3_ext -config csr.conf -out ${new_kubelet_csr}
if [ $? -ne 0 ]; then
error "failed to generate ${new_kube_let_csr}"
fi
openssl x509 -in ${new_kubelet_csr} -req -CA ${CA_CERT} -CAkey ${CA_KEY} -CAcreateserial -extensions v3_ext -extfile csr.conf -days ${new_kubelet_cert_days} -out ${new_kubelet_cert}
if [ $? -ne 0 ]; then
error "failed to generte ${new_kubelet_cert}"
fi
rm -f csr.conf kubelet.csr
创建一个脚本,粘贴上述脚本内容,然后执行脚本:
[dcos@cc-cq2b-x86-mgr-3 ~]$ sudo sh cert.sh
Signature ok
subject=CN = 10.112.184.221@1610713079
Getting CA Private Key
[dcos@cc-cq2b-x86-mgr-3 ~]$ ls
cert.sh kubelet.crt
脚本会生成一个有效期为10年的新kubelet.crt证书
2、覆盖原来的证书
sudo cp kubelet.crt /var/lib/kubelet/pki/kubelet.crt
3、重启kubelet进程
sudo systemctl restart kubelet
注意:需要替换所有集群节点的/var/lib/kubelet/pki/kubelet.crt
临时应急修复方法
如果遇到因10250端口证书过期引发的基线安全问题,监控问题等需要紧急修复的,还可以按如下方法进行应急操作:
在每个kubernetes节点上执行以下步骤:
1、删除kubelet的server端证书
sudo rm -f /var/lib/kubelet/pki/kubelet.crt /var/lib/kubelet/pki/kubelet.key
2、重启kubelet进程
sudo systemctl restart kubelet
3、检查新生成的/var/lib/kubelet/pki/kubelet.crt
有效期
openssl x509 -in /var/lib/kubelet/pki/kubelet.crt -noout -text|grep 'Not After'
正常情况下应该为1年
该方案仅仅建议在紧急状态下使用