写点什么

k8s TLS bootstrap 解析 -k8s TLS bootstrap 流程分析

作者:良凯尔
  • 2022 年 4 月 10 日
  • 本文字数:4085 字

    阅读完需:约 13 分钟

k8s TLS bootstrap解析-k8s TLS bootstrap流程分析

k8s TLS bootstrap 解析-k8s TLS bootstrap 流程分析

概述

当 k8s 集群开启了 TLS 认证后,每个节点的 kubelet 组件都要使用由 kube-apiserver 的 CA 签发的有效证书才能与 kube-apiserver 通信;当节点非常多的时候,为每个节点都单独签署证书是一件非常繁琐而又耗时的事情。


此时 k8s TLS bootstrap 功能应运而生。


k8s TLS bootstrap 功能就是让 kubelet 先使用一个预先商定好的低权限的 bootstrap token 连接到 kube-apiserver,向 kube-apiserver 申请证书,然后 kube-controller-manager 给 kubelet 动态签署证书,后续 kubelet 都将通过动态签署的证书与 kube-apiserver 通信。

TLS bootstrap 涉及组件相关参数

1.kube-apiserver

(1)--client-ca-file:认证客户端证书的 CA 证书;


(2)--enable-bootstrap-token-auth:设置为 true 则代表开启 TLS bootstrap 特性;

2.kube-controller-manager

(1)--cluster-signing-cert-file--cluster-signing-key-file:用来签发 kubelet 证书的 CA 证书和私钥,这里的 kubelet 证书指的是用来跟 kube-apiserver 通信,kube-apiserver 认证 kubelet 身份的证书,所以--cluster-signing-cert-file 指定的值与 kube-apiserver 的--client-ca-file 指定值一致,而私钥则也是对应的私钥;


(2)--cluster-signing-duration:签发给 kubelet 的证书有效期;

3.kubelet

(1)--bootstrap-kubeconfig:TLS bootstrap 的配置文件,文件中一般包含 bootstrap token 和 master url 等信息;


(2)--kubeconfig:在 kubelet 的 CSR 被批复并被 kubelet 取回时,一个引用所生成的密钥和所获得证书的 kubeconfig 文件会被写入到通过 --kubeconfig 所指定的文件路径下,而证书和密钥文件会被放到--cert-dir 所指定的目录中;


(3)--rotate-certificates:开启证书轮换,kubelet 在其现有证书即将过期时通过创建新的 CSR 来轮换其客户端证书。

详细流程解析

下面以 kubeadm 使用 k8s TLS bootstrap 将一个 node 节点加入已有的 master 为例,对 TLS bootstrap 部分进行详细流程解析。

1.RBAC 相关操作

(1)生成 bootstrap token,创建 bootstrap token secret;


bootstrap token secret 模板:


apiVersion: v1data:  auth-extra-groups: system:bootstrappers:kubeadm:default-node-token  expiration: 2022-04-03T11:13:09+08:00  token-id: {token-id}  token-secret: {token-secret}  usage-bootstrap-authentication: "true"  usage-bootstrap-signing: "true"kind: Secretmetadata:  name: bootstrap-token-{token-id}  namespace: kube-systemtype: bootstrap.kubernetes.io/token
复制代码


关于 bootstrap token secret 相关的格式说明:


secret 的 name 格式为bootstrap-token-{token-id}的格式;


secret 的 type 固定为bootstrap.kubernetes.io/token


secret data 中的 token-id 为 6 位数字字母组合字符串,token-secret 为 16 位数字字母组合字符串;


secret data 中的auth-extra-groups定义了 bootstrap token 所代表用户所属的的 group,kubeadm 使用了system:bootstrappers:kubeadm:default-node-token


secret 所对应的 bootstrap token 为{token-id}.{token-secret}


bootstrap token secret 示例:


apiVersion: v1data:  auth-extra-groups: system:bootstrappers:kubeadm:default-node-token  expiration: 2022-04-03T11:13:09+08:00  token-id: abcdef  token-secret: 0123456789abcdef  usage-bootstrap-authentication: "true"  usage-bootstrap-signing: "true"kind: Secretmetadata:  name: bootstrap-token-abcdef  namespace: kube-systemtype: bootstrap.kubernetes.io/token
复制代码


上述 secret 示例中,kubeadm 生成的 bootstrap token 为abcdef.0123456789abcdef,其代表的用户所在用户组为system:bootstrappers:kubeadm:default-node-token


(2)授予 bootstrap token 创建 CSR 证书签名请求的权限,即授予 kubelet 创建 CSR 证书签名请求的权限;


即创建 ClusterRoleBinding -- kubeadm:kubelet-bootstrap


apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata:  name: kubeadm:kubelet-bootstrap  ...roleRef:  apiGroup: rbac.authorization.k8s.io  kind: ClusterRole  name: system:node-bootstrappersubjects:- apiGroup: rbac.authorization.k8s.io  kind: Group  name: system:bootstrappers:kubeadm:default-node-token
复制代码


kubeadm 生成的 bootstrap token 所代表的用户所在用户组为system:bootstrappers:kubeadm:default-node-token,所以这里绑定权限的时候将权限绑定给了用户组system:bootstrappers:kubeadm:default-node-token


接下来看下被授予的权限 ClusterRole -- system:node-bootstrapper


apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata:  name: system:node-bootstrapper  ...rules:- apiGroups:  - certificates.k8s.io  resources:  - certificatesigningrequests  verbs:  - create  - get  - list  - watch
复制代码


(3)授予 bootstrap token 权限,让 kube-controller-manager 可以自动审批其发起的 CSR;


即创建 ClusterRoleBinding -- kubeadm:node-autoapprove-bootstrap


apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata:  name: kubeadm:node-autoapprove-bootstrap  ...roleRef:  apiGroup: rbac.authorization.k8s.io  kind: ClusterRole  name: system:certificates.k8s.io:certificatesigningrequests:nodeclientsubjects:- apiGroup: rbac.authorization.k8s.io  kind: Group  name: system:bootstrappers:kubeadm:default-node-token
复制代码


kubeadm 生成的 bootstrap token 所代表的用户所在用户组为system:bootstrappers:kubeadm:default-node-token,所以这里绑定权限的时候将权限绑定给了用户组system:bootstrappers:kubeadm:default-node-token


接下来看下被授予的权限 ClusterRole -- system:certificates.k8s.io:certificatesigningrequests:nodeclient


apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata:  name: system:certificates.k8s.io:certificatesigningrequests:nodeclient  ...rules:- apiGroups:  - certificates.k8s.io  resources:  - certificatesigningrequests/nodeclient  verbs:  - create
复制代码


(4)授予 kubelet 权限,让 kube-controller-manager 自动批复 kubelet 的证书轮换请求;


即创建 ClusterRoleBinding -- kubeadm:node-autoapprove-certificate-rotation


apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRoleBindingmetadata:  name: kubeadm:node-autoapprove-certificate-rotation  ...roleRef:  apiGroup: rbac.authorization.k8s.io  kind: ClusterRole  name: system:certificates.k8s.io:certificatesigningrequests:selfnodeclientsubjects:- apiGroup: rbac.authorization.k8s.io  kind: Group  name: system:nodes
复制代码


kubelet 创建的 CSR 用户名格式为system:node:<name>,用户组为system:nodes,所以 kube-controller-manager 为 kubelet 生成的证书所代表的用户所在用户组为system:nodes,所以这里绑定权限的时候将权限绑定给了用户组system:nodes


接下来看下被授予的权限 ClusterRole -- system:certificates.k8s.io:certificatesigningrequests:selfnodeclient


apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata:  name: system:certificates.k8s.io:certificatesigningrequests:selfnodeclient  ...rules:- apiGroups:  - certificates.k8s.io  resources:  - certificatesigningrequests/selfnodeclient  verbs:  - create
复制代码

2.启动 kubelet,开始 TLS bootstrap

(0)根据 bootstrap token 以及 master url 等信息生成 bootstrap-kubeconfig 文件;


(1)启动 kubelet,配置了 kubeconfig 文件目录,但 kubeconfig 文件为空,再指定 bootstrap-kubeconfig 文件为上述步骤生成的 bootstrap-kubeconfig 文件;


(2)kubelet 发现配置的 kubeconfig 文件为空,则加载 bootstrap-kubeconfig 文件,读取其中的 bootstrap token 以及 master url;


(3)kubelet 使用 bootstrap token 与 apiserver 通信,创建 CSR 证书签名请求;


(4)kube-controller-manager 批复 CSR 证书签名请求,为其签发相关证书;


(5)kubelet 取回 kube-controller-manager 生成的相关证书,默认存放在/var/lib/kubelet/pki 目录下,然后根据证书生成 kubeconfig 文件,后续 kubelet 将使用该 kubeconfig 文件与 kube-apiserver 进行认证通信;


# ls /var/lib/kubelet/pki/kubelet-client-2022-03-18-14-29-00.pem  kubelet-client-current.pem  kubelet.crt  kubelet.key
复制代码


kubelet-client-current.pem 是个软链,指向 kubelet-client-2022-03-18-14-29-00.pem 文件,kubelet-client-2022-03-18-14-29-00.pem 文件名记录的是证书创建时间,后续 kubelet 将会根据证书过期时间,在证书临过期前向 kube-apiserver 重新申请证书,然后自动轮换该证书;


# cat /etc/kubernetes/kubelet.confapiVersion: v1clusters:- cluster:    certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0F...    server: https://192.168.1.10:6443  name: test-clustercontexts:- context:    cluster: test-cluster    user: system:node:test-cluster-node-1  name: system:node:test-cluster-node-1current-context: system:node:test-cluster-node-1kind: Configpreferences: {}users:- name: system:node:test-cluster-node-1  user:    client-certificate: /var/lib/kubelet/pki/kubelet-client-current.pem    client-key: /var/lib/kubelet/pki/kubelet-client-current.pem
复制代码

3.kubelet 自动轮换证书

(1)kubelet 在证书接近于过期时自动向 kube-apiserver 请求更新证书;


(2)kube-controller-manager 自动批复,为其签发新的证书;


(3)kubelet 取回 kube-controller-manager 生成的相关证书,替换掉本地的旧证书,后续 kubelet 将使用新证书来与 kube-apiserver 进行认证通信;

总结

最后以一幅图来总结一下 k8s TLS bootstrap 的整个流程。



发布于: 刚刚阅读数: 2
用户头像

良凯尔

关注

热爱的力量 2020.01.10 加入

kubernetes开发者

评论

发布
暂无评论
k8s TLS bootstrap解析-k8s TLS bootstrap流程分析_容器_良凯尔_InfoQ写作平台