[关闭]
@zhangyy 2021-07-18T14:31:09.000000Z 字数 8365 阅读 157

Kubelet 证书⾃动续期解决⽅案

kubernetes系列



一:关于kubelet 证书的问题

1.1 k8s 证书问题

  1. 在⼀个 K8s 集群中,node 节点上的组件( kubelet kube-proxy )需要与 master 节点(尤其是 kube- apiserver)进⾏通信时,为了确保通信本身的私密性和通信过程不被⼲扰,K8s 会使⽤ TLS 加密通信。只要是证书,就会有到期时间,⽽到期了就需要续签,否则就⽆法正常通信,因此⼀旦启⽤了 TLS 认证 ,就会不得不时刻去关⼼证书到期的问题。
  2. 1.4 版本后,K8s 推出了 功能,以此证书签名和请求都可以通过 K8s 提供的 API 的⽅式
  3. 进⾏,这很⼤程度上节省了证书⽣成签名⼯作。当然随着 的推出,对于集群证书的管理来说就更加简单
  4. 了,⼏条命令即可完成证书⽣命周期的管理。但是对于⼆进制包安装集群的场景来说,这个过程还是⽐较痛苦的。
  5. ⼀般来说,我们会在⽣成 etcd K8s 集群 ca 证书时,将证书有效期声明的较⻓(510年),但是在通过
  6. apiserver CA 签发的 kubelet 证书时,会遵循默认的证书有效期 —— 8760h (即 1年)。
  7. 如果证书过期了,就会在⽇志中出现 certificate has expired or is not yet valid
  8. 的错误信息,node 节点将不能与 master 节点进⾏通信,这将对业务环境造成极⼤的灾难,于是乎我们就不得不时时刻刻去关注着证书什么时候,以便于更早的可以对其进⾏替换。
  9. 当需要管理的节点原来越多的时候,替换证书就会是⼀件⾮常繁琐的事情,我们当然会更加期望能以⼀种更加⽅便 的⽅式去实现这⼀过程,因此也就引出了我们本⽂的话题 —— 如何去实现 Kubelet 证书的⾃动续签。

1.2 TLS bootstrapping 证书⾃动续期⽅案实施

  1. 事实上,⾃ Kubernetes 1.8 版本开始就包含了⼀个 beta 特性 —— kubelet certificate rotation,在当前的证书有
  2. 效期到达总有效期的 70% 90% 时,kubelet 便会发起⼀个 CSR 请求从 apiserver 重新申请证书,新
  3. 证书可⽤后 就会⾃动批准续签。
  4. 注意:
  5. K8s 版本为 1.8 或更⾼时,kubelet certificate relation 会⾃动加载新证书,⽆需⼿动重启服务;K8s 版本低于 1.8 则需要⼿动重启服务才能加载新证书

1.3 配置 kubelet client/server 证书轮换

  1. 1kube-controller-manager 配置参数
  2. 所有 master 节点都需要操作。

image_1fapke760k87ha6h6d1c94jmj9.png-138.1kB

  1. 修改配置文件:kube-controller-manager.conf
  2. ⽂件路径: kubernetes/cfg/kube-controller-manager.conf ,完整配置⽂件内容如下:
  3. KUBE_CONTROLLER_MANAGER_OPTS="--logtostderr=false \
  4. --v=2 \
  5. --log-dir=/data/application/kubernetes/logs \
  6. --leader-elect=true \
  7. --master=127.0.0.1:8080 \
  8. --bind-address=127.0.0.1 \
  9. --allocate-node-cidrs=true \
  10. --cluster-cidr=10.244.0.0/16 \
  11. --service-cluster-ip-range=10.0.0.0/16 \
  12. --cluster-signing-cert-file=/data/application/kubernetes/ssl/ca.pem \
  13. --cluster-signing-key-file=/data/application/kubernetes/ssl/ca-key.pem \
  14. --root-ca-file=/data/application/kubernetes/ssl/ca.pem \
  15. --service-account-private-key-file=/data/application/kubernetes/ssl/ca-key.pem \
  16. --experimental-cluster-signing-duration=87600h0m0s \
  17. --feature-gates=RotateKubeletServerCertificate=true"

image_1fapl39ok18fb1mvh1mk63441d6n1g.png-137.7kB


1.4 k8s 1.11 之前的版本

  1. 2kubelet 配置参数
  2. 1.K8s 1.11 版本及以前(了解即可) 注意:
  3. K8s 1.11 版本之前,RotateKubeletServerCertificate 默认是关闭的功能,需要在 kubelet kube- controller-manager 中⼿动开启

image_1fapkk6cnmljbp1np2ecj2amm.png-110kB

  1. 修改配置⽂件: kubelet.conf
  2. 注意: 所有 node 节点都需要进⾏操作(包括作为 node 加⼊集群的 master 节点)。
  3. vim kubernetes/cfg/kubelet.conf
  4. -----
  5. KUBELET_OPTS="--logtostderr=false \
  6. --v=2 \
  7. --log-dir=/data/application/kubernetes/logs \
  8. --hostname-override=t-k8sN-001 \
  9. --network-plugin=cni \
  10. --kubeconfig=/data/application/kubernetes/cfg/kubelet.kubeconfig \
  11. --bootstrap-kubeconfig=/data/application/kubernetes/cfg/bootstrap.kubeconfig \
  12. --config=/data/application/kubernetes/cfg/kubelet-config.yml \
  13. --cert-dir=/data/application/kubernetes/ssl \
  14. --pod-infra-container-image=lizhenliang/pause-amd64:3.0 \
  15. --node-labels=node.kubernetes.io/k8s-node=true \
  16. --feature-gates=RotateKubeletClientCertificate=true,RotateKubeletServerCertificate=true --rotate-certificates"
  17. -----

1.5 k8s 1.11 之后的版本

  1. 新增参数说明

image_1fapksfnt1kh682u1lhk14dc8a413.png-99.5kB

  1. 修改配置⽂件
  2. 注意: 所有 node 节点都需要进⾏操作(包括作为 node 加⼊集群的 master 节点),以下两种⽅法选⼀种即可,推荐 yaml 声明
  3. ⽂件路径: kubernetes/cfg/kubelet-config.yml ,追加内容如下:
  4. vim /opt/kubernetes/cfg/kubelet-config.yml
  5. ----
  6. featureGates:
  7. RotateKubeletServerCertificate: true
  8. rotateCertificates: true
  9. serverTLSBootstrap: true
  10. ----

image_1faq4c0n41kch1umn4jn1fh51lnp1t.png-52.4kB

  1. 文件路径: kubernetes/cfg/kubelet.conf (不推荐,后期版本逐步废弃),⽂件内容如下:
  2. KUBELET_OPTS="--logtostderr=false \
  3. --v=2 \
  4. --log-dir=/data/application/kubernetes/logs \
  5. --hostname-override=t-k8sN-001 \
  6. --network-plugin=cni \
  7. --kubeconfig=/data/application/kubernetes/cfg/kubelet.kubeconfig \
  8. --bootstrap-kubeconfig=/data/application/kubernetes/cfg/bootstrap.kubeconfig \
  9. --cert-dir=/data/application/kubernetes/ssl \
  10. --config=/data/application/kubernetes/cfg/kubelet-config.yml \
  11. --pod-infra-container-image=lizhenliang/pause-amd64:3.0 \
  12. --node-labels=node.kubernetes.io/k8s-node=true \
  13. --feature-gates=RotateKubeletServerCertificate=true \
  14. --rotate-certificates \
  15. --rotate-server-certificates"

1.6 创建 RBAC 规则

  1. 我们知道 kube-apiserver 会从 kubelet 处收到 CSR 请求,并对这些请求进⾏身份认证,但实际上真正负责签发证书的是 kube-controller-manager ,同时 controller-manager 还控制着证书的有效期。因此,想要实现⾃动续签证书,除了自动生成证书发起请求外,还得让 controller-manager 能够⾃动地批复接受到的 CSR 请求。当然,总不能什么 CSR 请求都批发,既然我们是要实现 kubelet证书的自动续签,就必须告知 controller-manager 只对 kubelet 发起的特定 CSR 请求进⾏批复。这需要通过 RBAC规则中的clusterole 来实现。
  2. ClusterRole 实际上只是用于定义⼀种集群范围内的能力,这种能力需要我们通过声明资源来创建。对于自动批复
  3. CSRk8s 提供了以下3 API 方法:
  4. nodeclient: ⾃动批复 组⽤户(默认值,具体根据实际的 token.csv 为准)
  5. ⾸次申请证书的 CSR 请求(新节点,还没有证书)

image_1farob8f0160dgot1ria1u5ff9e9.png-115.1kB

  1. selfnodeclient: 自动批复 system:nodes 组⽤户更新 kubelet ⾃身与 apiserver 通讯⽤证书的 CSR 请求 kubelet-client-xxxx.pem
  2. selfnodeserver: 自动批复求system:nodes 组⽤户更新 kubelet 10250 端口API 鉴权⽤证书的 CSR 请求( kubelet.crt

1.7 K8s 1.8 版本前 (了解即可)

  1. 创建 clusterole
  2. vim approve-renewal-csr.yaml
  3. -----
  4. # A ClusterRole which instructs the CSR approver to approve a user requesting # node client credentials.
  5. kind: ClusterRole
  6. apiVersion: rbac.authorization.k8s.io/v1 metadata:
  7. name: approve-node-client-csr rules:
  8. - apiGroups: ["certificates.k8s.io"]
  9. resources: ["certificatesigningrequests/nodeclient"] verbs: ["create"]
  10. ---
  11. # A ClusterRole which instructs the CSR approver to approve a node renewing its # own client credentials.
  12. kind: ClusterRole
  13. apiVersion: rbac.authorization.k8s.io/v1 metadata:
  14. name: approve-node-client-renewal-csr rules:
  15. - apiGroups: ["certificates.k8s.io"]
  16. resources: ["certificatesigningrequests/selfnodeclient"] verbs: ["create"]
  17. ---
  18. # A ClusterRole which instructs the CSR approver to approve a node requesting a # serving cert matching its client cert.
  19. kind: ClusterRole
  20. apiVersion: rbac.authorization.k8s.io/v1 metadata:
  21. name: approve-node-server-renewal-csr rules:
  22. - apiGroups: ["certificates.k8s.io"]
  23. resources: ["certificatesigningrequests/selfnodeserver"] verbs: ["create"]
  24. ----
  25. 创建资源:
  26. kubectl apply -f approve-renewal-csr.yaml
  27. 创建:ClusterRoleBinding 自动批准首次申请证书
  28. 还没有证书,所以是组system:node-bootsrapper
  29. kubectl create clusterrolebinding node-client-auto-approve-csr --clusterrole=approve- node-client-csr --group=system:node-bootstrapper
  30. 自动批准更新 kubelet 自身与 apiserver 通讯用证书
  31. 已有证书,所以是组system:nodes
  32. kubectl create clusterrolebinding node-client-auto-renew-crt --clusterrole=approve- node-client-renewal-csr --group=system:nodes
  33. 自动批准更新 kubelet 10250 端口 API鉴权⽤证书
  34. 已有证书,所以是systemnodes
  35. kubectl create clusterrolebinding node-server-auto-renew-crt --clusterrole=approve- node-server-renewal-csr --group=system:nodes
  36. 如上创建后可以通过 kubectl get clusterrolebinding|egrep "node-(.*)-auto" 进⾏查看,结果如下:

image_1farpkrcu18d91skr4s11qhc1sli13.png-140.4kB


1.8 k8s 1.8 之后的版本

  1. 我们上⾯说到,K8s 提供了三种 ClusterRole 来进⾏ CSR 的自动批复⼯作。在 K8s 1.8 版本前都需要手动创
  2. 建,而从 1.8 版本起 kube-apiserver 会自动创建nodeclient
  3. selfnodeclient ,所以我们只需要再⼿
  4. 动创建selfnodeserver就可以了。

image_1farq663p1g8j14bfkpt1o56i581g.png-109.7kB

  1. 创建clusteRole
  2. vim auto-approve-csr-clusterrole.yml
  3. # A ClusterRole which instructs the CSR approver to approve a node requesting # a serving cert matching its client cert.
  4. kind: ClusterRole
  5. apiVersion: rbac.authorization.k8s.io/v1
  6. metadata:
  7. name: system:certificates.k8s.io:certificatesigningrequests:selfnodeserver
  8. rules:
  9. - apiGroups: ["certificates.k8s.io"]
  10. resources: ["certificatesigningrequests/selfnodeserver"]
  11. verbs: ["create"]

  1. 创建ClusterRoleBinding
  2. vim auto-approve-csr-clusterrolebinding.yaml
  3. # 批复 "system:node-bootstrapper" 组的所有 CSR
  4. apiVersion: rbac.authorization.k8s.io/v1
  5. kind: ClusterRoleBinding
  6. metadata:
  7. name: node-client-auto-approve-csr
  8. subjects:
  9. - kind: Group
  10. name: system:node-bootstrapper
  11. apiGroup: rbac.authorization.k8s.io
  12. roleRef:
  13. kind: ClusterRole
  14. name: system:certificates.k8s.io:certificatesigningrequests:nodeclient
  15. apiGroup: rbac.authorization.k8s.io
  16. ---
  17. # 批复 "system:nodes" 组 kubelet 与 apiserver 通信证书续约请求
  18. apiVersion: rbac.authorization.k8s.io/v1
  19. kind: ClusterRoleBinding
  20. metadata:
  21. name: node-client-auto-renew-crt
  22. subjects:
  23. - kind: Group
  24. name: system:nodes
  25. apiGroup: rbac.authorization.k8s.io
  26. roleRef:
  27. kind: ClusterRole
  28. name: system:certificates.k8s.io:certificatesigningrequests:selfnodeclient
  29. apiGroup: rbac.authorization.k8s.io
  30. ---
  31. # 批复 "system:nodes" 组 kubelet 10250端⼝ API 鉴权证书续约请求
  32. apiVersion: rbac.authorization.k8s.io/v1
  33. kind: ClusterRoleBinding
  34. metadata:
  35. name: node-server-auto-renew-crt
  36. subjects:
  37. - kind: Group
  38. name: system:nodes
  39. apiGroup: rbac.authorization.k8s.io
  40. roleRef:
  41. kind: ClusterRole
  42. name: system:certificates.k8s.io:certificatesigningrequests:selfnodeserver
  43. apiGroup: rbac.authorization.k8s.io

image_1fas1e7tm62gr9e113k1fv078u9.png-99kB

  1. kubectl get clusterrolebinding|egrep "node-(.*)-auto"

image_1fas1frfo1hbaa5j199q1pgtgiom.png-89.4kB

二: 重启服务与删除证书

2.1 重启kube-controller-manger

  1. 重启kube-controller-manager 如果有多个master 就逐个重启
  2. systemctl daemon-reload
  3. systemctl restart kube-controller-manager.service

2.2 删掉kubelet的证书

  1. 查看默认证书时间
  2. openssl x509 -in kubelet-client-current.pem -noout -text | grep "Not"

image_1fas3bisg1snnrusur0og51p441g.png-61.7kB

  1. rm -rf /opt/kubernetes/ssl/kubelet* [所有节点的证书]
  2. 重新启动 节点kubelet
  3. service kubelet restart

image_1fas3ig3nkgv1mp8u1ko8gv301t.png-48kB

image_1fas3iukno7l1m81d4s12qj1gap2a.png-52.4kB

image_1fas3jcp61bar1k8bimp1e61fc52n.png-54.3kB

  1. 查看原 kubelet server 证书的有效期
  2. 会少了两个文件: kubelet.crt , kubelet.key 文件
  3. 默认情况下签发的 kubelet server 证书的有效期只有 1 年,并不受 kube-controller-manager 控制其证书有效期。

image_1fas3pu4a1ou52gj1h6k13et168s34.png-105.7kB

2.3 重新签发证书

  1. 重新签发证书:
  2. kubectl get csr

image_1fas3rve71p3g6psml11vlb13ml3h.png-145.5kB

  1. kubectl get csr|grep "Pending"|awk 'NR>1{print $1}'|xargs kubectl certificate approve
  2. kubectl certificate approve csr-f7jl6

image_1fas3v72k140j12lg1nq2pngnnq3u.png-227.9kB

image_1fas4p2lb14r9h4k6161lphagv4b.png-78.8kB

  1. 证书管理:
  2. openssl x509 -in /opt/kubernetes/ssl/kubelet-client-current.pem -noout -text| grep Not

image_1fas4ru014m95vv3lt2eg6re4o.png-77.4kB

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注