文章简介:K3s 自带的 CA 有效期 10 年,其签发的 mTLS 证书只有 1 年,远不能满足“一次部署、长期免运维”的生产诉求。本文给出零侵入式方案,让 K3s 一次性使用 100 年有效期的 CA 与终端实体证书,真正做到“证书一生只装一次”。
背景
k3s 默认生成的证书 10 年 CA 证书以及 1 年的客户端证书。如果证书的有效期少于 90 天,k3s server 在重启的时候会续签证书。这就意味着我们需要定期每周或者每月重启 k3s。但是有一个致命问题 ca 证书不会续签,且只有 10 年有效期,当前我们在使用的版本 1.21.* 版本是没有 rotate-ca 的,也就意味着 10 年到期后集群就不可用了。
issue: How to configure my own CA for k3s Certificate and access management for edge computing ,自定义 CA 证书的问题在 此 MR 中解决了,我们可以通过使用contrib/util/generate-custom-ca-certs.sh 修改一下 openssl 自签 100 年证书。同时 此 MR 添加了 rotate-ca 命令,用于 ca 证书过期后更换 ca 证书。实际使用过程中发现 rotate-ca 命令貌似不可用。后使用 restore etcd snapshot 后重新自签一套新证书后启动 k3s 解决。当前版本可以直接生成 rotate-ca 证书,直接 rotate-ca 即可。旧环境可以直接升级到 1.27.x 后使用 rotate-ca 即可。
整体思路
- 提前生成超长寿命 CA(100 年)
- K3s 启动时生成 CATTLE_NEW_SIGNED_CERT_EXPIRATION_DAYS 有效期的 server/client cert
- 同步调整 Kubernetes 控制平面 CSR 有效期(100 年)
步骤 1:生成 100 年 CA 及中间证书
k3s 使用 certutil.NewSelfSignedCACert 签发 CA 证书,有效期是写死的 10 年,这个值不是很生产可用。社区也遇到了这个问题,其中 CA 部分采用的解决办法是自签名一个自定义证书,脚本默认 20 年证书,这里我们改成 100 年:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
--- "ansible/files/generate-custom-ca-certs copy.sh" 2024-08-06 17:43:32.663442036 +0800
+++ ansible/files/generate-custom-ca-certs.sh 2024-08-06 17:53:07.285515777 +0800
@@ -30,6 +30,11 @@
PRODUCT="${PRODUCT:-k3s}"
DATA_DIR="${DATA_DIR:-/var/lib/rancher/${PRODUCT}}"
+if [[ -d "${DATA_DIR}/server/tls" ]]; then
+ echo "SKIPING: ${DATA_DIR}/server/tls is exists"
+ exit 0
+fi
+
if type -t openssl-3 &>/dev/null; then
OPENSSL=openssl-3
else
@@ -93,7 +98,7 @@
else
echo "Generating root certificate authority RSA key and certificate"
${OPENSSL} genrsa ${OPENSSL_GENRSA_FLAGS:-} -out root-ca.key 4096
- ${OPENSSL} req -x509 -new -nodes -sha256 -days 7300 \
+ ${OPENSSL} req -x509 -new -nodes -sha256 -days 37000 \
-subj "/CN=${PRODUCT}-root-ca@${TIMESTAMP}" \
-key root-ca.key \
-out root-ca.pem \
@@ -116,7 +121,7 @@
${OPENSSL} req -new -nodes \
-subj "/CN=${PRODUCT}-intermediate-ca@${TIMESTAMP}" \
-key intermediate-ca.key |
- ${OPENSSL} ca -batch -notext -days 3700 \
+ ${OPENSSL} ca -batch -notext -days 37000 \
-in /dev/stdin \
-out intermediate-ca.pem \
-keyfile root-ca.key \
@@ -139,7 +144,7 @@
${OPENSSL} req -new -nodes \
-subj "/CN=${CERT_NAME}@${TIMESTAMP}" \
-key ${TYPE}-ca.key |
- ${OPENSSL} ca -batch -notext -days 3700 \
+ ${OPENSSL} ca -batch -notext -days 37000 \
-in /dev/stdin \
-out ${TYPE}-ca.pem \
-keyfile intermediate-ca.key \
|
修改后执行即可:
1
|
bash k3s-generate-custom-ca-certs.sh
|
步骤 2:调整 K3s Server / Client 证书有效期
k3s 创建 tls 证书,其 server 证书有效期是 365 天,可以通过环境变量 CATTLE_NEW_SIGNED_CERT_EXPIRATION_DAYS 修改为希望的值,单位天:
1
|
echo 'CATTLE_NEW_SIGNED_CERT_EXPIRATION_DAYS=36500' >> /etc/systemd/system/k3s.service.env
|
步骤 3:让 Kubernetes CSR 也一次签 100 年
Kubernetes 控制平面自带的 kube-controller-manager 默认对 CSR 签发 1 年,可以覆盖这个配置 /etc/rancher/k3s/config.yaml:
1
2
|
kube-controller-manager-arg:
- cluster-signing-duration=876000h # 100year
|
最终验证
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
# 查看 CA 有效期
for i in `ls /var/lib/rancher/k3s/server/tls/*.crt`; do echo $i; openssl x509 -enddate -noout -in $i; done
/var/lib/rancher/k3s/server/tls/client-admin.crt
notAfter=Jun 14 03:39:24 2125 GMT
/var/lib/rancher/k3s/server/tls/client-auth-proxy.crt
notAfter=Jun 14 03:39:24 2125 GMT
/var/lib/rancher/k3s/server/tls/client-ca.crt
notAfter=Oct 27 03:37:22 2126 GMT
/var/lib/rancher/k3s/server/tls/client-ca.nochain.crt
notAfter=Oct 27 03:37:22 2126 GMT
/var/lib/rancher/k3s/server/tls/client-controller.crt
notAfter=Jun 14 03:39:24 2125 GMT
/var/lib/rancher/k3s/server/tls/client-k3s-cloud-controller.crt
notAfter=Jun 14 03:39:24 2125 GMT
/var/lib/rancher/k3s/server/tls/client-k3s-controller.crt
notAfter=Jun 14 03:39:24 2125 GMT
/var/lib/rancher/k3s/server/tls/client-kube-apiserver.crt
notAfter=Jun 14 03:39:24 2125 GMT
/var/lib/rancher/k3s/server/tls/client-kube-proxy.crt
notAfter=Jun 14 03:39:24 2125 GMT
/var/lib/rancher/k3s/server/tls/client-scheduler.crt
notAfter=Jun 14 03:39:24 2125 GMT
/var/lib/rancher/k3s/server/tls/client-supervisor.crt
notAfter=Jun 14 03:39:24 2125 GMT
/var/lib/rancher/k3s/server/tls/intermediate-ca.crt
notAfter=Oct 27 03:37:22 2126 GMT
/var/lib/rancher/k3s/server/tls/request-header-ca.crt
notAfter=Oct 27 03:37:23 2126 GMT
/var/lib/rancher/k3s/server/tls/root-ca.crt
notAfter=Oct 27 03:37:22 2126 GMT
/var/lib/rancher/k3s/server/tls/server-ca.crt
notAfter=Oct 27 03:37:22 2126 GMT
/var/lib/rancher/k3s/server/tls/server-ca.nochain.crt
notAfter=Oct 27 03:37:22 2126 GMT
/var/lib/rancher/k3s/server/tls/serving-kube-apiserver.crt
notAfter=Jun 14 03:39:24 2125 GMT
# 查看 server 证书有效期
openssl x509 -in /var/lib/rancher/k3s/server/tls/serving-kube-apiserver.crt -noout -dates
notBefore=Jul 8 03:37:22 2025 GMT
notAfter=Jun 14 03:39:24 2125 GMT
# 查看 kubelet client 证书有效期
openssl x509 -in /var/lib/rancher/k3s/agent/client-kubelet.crt -noout -dates
notBefore=Jul 8 03:37:22 2025 GMT
notAfter=Jun 14 17:00:14 2125 GMT
|
结语
- CA 100 年(脚本一次性生成,K3s 直接复用)
- Server / Client 证书 100 年(环境变量控制)
- Kubernetes CSR 100 年(controller-manager 参数控制)
至此,一次部署,证书终身免运维的 K3s 集群正式就绪。