概述
目录
Kubernetes TLS bootstrapping流程引导分析
一、TLS bootstrapping 简介
二、TLS bootstrapping 相关术语
2.1、kubelet server
2.2、CSR请求类型
2.3、KubernetesTLS与RBAC认证
2.4、证书及配置文件作用
三、kubelet初始化流程
四、TLS bootstrapping引导程序初始化流程
Kubernetes TLS bootstrapping流程引导分析
该文章历时一周左右,通过研习多篇博客博文以及官方文档,加上自身学习总结,在原有内容基础上添加部分个人理解、详细注解、配置内容、结合实际生产区别输出,如有理解错误的地方,麻烦指出交流。
一、TLS bootstrapping 简介
在Kubernetes集群中,工作程序节点上的组件kubelet和kube-proxy需要与Kubernetes主组件(特别是kube-apiserver)进行通信。为了确保通信保持私密性而不受到干扰,并确保群集的每个组件都在与另一个受信任的组件通信,我们强烈建议在节点上使用客户端TLS证书。
引导这些组件通信的正常过程,尤其是需要证书的工作程序节点,以便它们可以与kube-apiserver安全通信,这是一个具有挑战性的过程,因为它通常不在Kubernetes的范围内,并且需要大量的额外工作。反过来,这可能使初始化或扩展群集变得颇具挑战性。为了简化流程,从版本1.4开始,Kubernetes引入了证书请求和签名API来简化流程。目前主要用于kubelet,kube-proxy还是由我们统一颁发一个证书。
当集群开启了TLS认证后,每个节点的kubelet组件都要使用由apiserver使用的CA签发的有效证书才能与apiserver通讯;此时如果节点多起来,为每个节点单独签署证书将是一件非常繁琐的事情;TLSbootstrapping功能就是让kubelet先使用一个预定的低权限用户连接到apiserver,然后向apiserver申请证书,kubelet的证书由apiserver动态签署;在配合RBAC授权模型下的工作流程大致如下所示:
二、TLS bootstrapping 相关术语
2.1、kubelet server
官方TLSbootstrapping文档中多次提到过kubeletserver这个东西;在经过翻阅大量文档以及TLSbootstrapping设计文档后得出,kubeletserver指的应该是kubelet的10250端口
kubelet组件在工作时,采用主动的查询机制,即定期请求apiserver获取自己所应当处理的任务,如哪些pod分配到了自己身上,从而去处理这些任务;同时kubelet自己还会暴露出两个本身api的端口,用于将自己本身的私有api暴露出去,这两个端口分别是10250与10255;对于10250端口,kubelet会在其上采用TLS加密以提供适当的鉴权功能;对于10255端口,kubelet会以只读形式暴露组件本身的私有api,并且不做鉴权处理
总结一下,就是说kubelet上实际上有两个地方用到证书,一个是用于与APIserver通讯所用到的证书,另一个是kubelet的10250私有api端口需要用到的证书
2.2、CSR请求类型
kubelet发起的CSR(证书签名请求)请求都是由controllermanager来做实际签署的,对于controllermanager来说,TLSbootstrapping下kubelet发起的CSR请求大致分为以下三种
- nodeclient:kubelet以
O=system:nodes
和CN=system:node:(nodename)
形式发起的CSR请求- selfnodeclient:kubeletclientrenew自己的证书发起的CSR请求(与上一个证书就有相同的O和CN)
- selfnodeserver:kubeletserverrenew自己的证书发起的CSR请求
nodeclient类型的CSR仅在第一次启动时会产生,selfnodeclient类型的CSR请求实际上就是kubeletrenew自己作为client跟apiserver通讯时使用的证书产生的,selfnodeserver类型的CSR请求则是kubelet首次申请或后续renew自己的10250api端口证书时产生的。
2.3、KubernetesTLS与RBAC认证
TLS作用:众所周知TLS的作用就是对通讯加密,防止中间人窃听;同时如果证书不信任的话根本就无法与apiserver建立连接,更不用提有没有权限向apiserver请求指定内容
RBAC作用:当TLS解决了通讯问题后,那么权限问题就应由RBAC解决;RBAC中规定了一个用户或者用户组(subject)具有请求哪些api的权限;在配合TLS加密的时候,实际上apiserver读取客户端证书的CN字段作为用户名,读取O字段作为用户组
从以上两点上可以总结出两点:第一,想要与apiserver通讯就必须采用由apiserverCA签发的证书,这样才能形成信任关系,建立TLS连接;第二,可以通过证书的CN、O字段来提供RBAC所需的用户与用户组。
2.4、证书及配置文件作用
token.csv
该文件为一个用户的描述文件,基本格式为 Token,用户名,UID,用户组;这个文件在 apiserver 启动时被 apiserver 加载,然后就相当于在集群内创建了一个这个用户;接下来就可以用 RBAC 给他授权;持有这个用户 Token 的组件访问 apiserver 的时候,apiserver 根据 RBAC 定义的该用户创建上述配置文件中token文件:
c47ffb939f5ca36231d9e3121a252940,kubelet-bootstrap,10001,"system:node-bootstrapper"
对应的系统的
kubectl get clusterrole -A | grep boot
NAME:system:node-bootstrapperkubectl describe clusterrole system:node-bootstrapper
Name: system:node-bootstrapper
Labels: kubernetes.io/bootstrapping=rbac-defaults
Annotations: rbac.authorization.kubernetes.io/autoupdate: true
PolicyRule: [create get list watch]kubectl get ClusterRoleBinding –A
name:kubeadm:kubelet-bootstrap
role:ClusterRole/system:node-bootstrapperkubectl describe ClusterRoleBinding kubeadm:kubelet-bootstrap
Name: kubeadm:kubelet-bootstrap
Role:Kind: ClusterRole
Role:Name: system:node-bootstrapper
Group: system:bootstrappers:kubeadm:default-node-token
bootstarp.kubeconfig
该文件中内置了 token.csv 中用户的 Token,以及 apiserver CA 证书;kubelet 首次启动会加载此文件,使用 apiserver CA 证书建立与 apiserver 的 TLS 通讯,使用其中的用户 Token 作为身份标识像 apiserver 发起 CSR 请求
kubelet-client.crt
该文件在 kubelet 完成 TLS bootstrapping 后生成,此证书是由 controller manager 签署的,此后 kubelet 将会加载该证书,用于与 apiserver 建立 TLS 通讯,同时使用该证书的 CN 字段作为用户名,O 字段作为用户组向 apiserver 发起其他请求
kubelet.crt
该文件在 kubelet 完成 TLS bootstrapping 后并且没有配置 --feature-gates=RotateKubeletServerCertificate=true 时才会生成;这种情况下该文件为一个独立于 apiserver CA 的自签 CA 证书,有效期为 1 年;被用作 kubelet 10250 api 端口
kubelet-server.crt
该文件在 kubelet 完成 TLS bootstrapping 后并且配置了 --feature-gates=RotateKubeletServerCertificate=true 时才会生成;这种情况下该证书由 apiserver CA 签署,默认有效期同样是 1 年,被用作 kubelet 10250 api 端口鉴权
kubelet-client-current.pem
这是一个软连接文件,当 kubelet 配置了 --feature-gates=RotateKubeletClientCertificate=true 选项后,会在证书总有效期的 70%~90% 的时间内发起续期请求,请求被批准后会生成一个 kubelet-client-时间戳.pem;kubelet-client-current.pem 文件则始终软连接到最新的真实证书文件,除首次启动外,kubelet 一直会使用这个证书同 apiserver 通讯
kubelet-server-current.pem
同样是一个软连接文件,当 kubelet 配置了 --feature-gates=RotateKubeletServerCertificate=true 选项后,会在证书总有效期的 70%~90% 的时间内发起续期请求,请求被批准后会生成一个 kubelet-server-时间戳.pem;kubelet-server-current.pem 文件则始终软连接到最新的真实证书文件,该文件将会一直被用于 kubelet 10250 api 端口鉴权
三、kubelet初始化流程
该流程主要梳理了token、secret、bootstrap config、clusterrole、clusterrolebinding联系。
1、在集群内创建特定的 Bootstrap Token Secret,该 Secret 将替代以前的 token.csv 内置用户声明文件。
kubeadm在该过程中做了如下操作:执行命令kubeadm token create [token]创建类似token.csv内容,可以通过kubeadm token list查看;然后将token加密存储在一个secret对象中供集群调用kubectl get secret -n kube-system。可以通过解密查看secret密文echo 'xxxxxxxxxxxx==' | base64 --decode
2、在集群内创建首次 TLS Bootstrap 申请证书的 ClusterRole、后续 renew Kubelet client/server 的 ClusterRole,以及其相关对应的 ClusterRoleBinding;并绑定到对应的组或用户
clusterrole为一组不受namespace限制的权限的集合,目的是创建具有申请证书权限的clusterrole角色,再通过clusterrolebind将token中指定的用户和用户组绑定到这个角色中,这样的话token的用户和用户组也可以申请证书认证了。
授权kubelet-bootstrap用户允许请求证书
kubectl create clusterrolebinding kubelet-bootstrap
--clusterrole=system:node-bootstrapper
--user=kubelet-bootstrap
3、调整kube-apiserver和 Controller Manager 配置,以使其能自动签署相关证书和自动清理过期的 TLS Bootstrapping Token
3.1、kube-apiserver使用static token或者bootstrap token:
使用static token需要指定--token-auth-file文件
使用bootstrap token需要开启对应功能: --enable-bootstrap-token-auth=true
3.2、kube-controller-manager需要指定和kube-apiserver相同的--client-ca-file,同时需要指定--cluster-signing-cert-file和--cluster-signing-key-file用户签发kubelet证书;
kube-controller-manager自动approve需要为system:bootstrappers用户组和system:nodes用户组绑定对应的角色:
system:certificates.k8s.io:certificatesigningrequests:nodeclient,system:certificates.k8s.io:certificatesigningrequests:selfnodeclient;
同时csr的签发者为kubernetes.io/kube-apiserver-client-kubelet
4、生成特定的包含 TLS Bootstrapping Token 的 bootstrap.kubeconfig 以供 kubelet 启动时使用
4.1、二进制生成bootstrap.kubeconfig文件
KUBE_APISERVER="https://172.10.10.129:6443"#apiserverIP:PORT
TOKEN="c47ffb93xxxxx231d9e3121a252940"#与token.csv里保持一致
kubectlconfigset-clusterkubernetes
--certificate-authority=/opt/kubernetes/ssl/ca.pem
--embed-certs=true
--server=${KUBE_APISERVER}
--kubeconfig=bootstrap.kubeconfig
kubectlconfigset-credentials"kubelet-bootstrap"
--token=${TOKEN}
--kubeconfig=bootstrap.kubeconfig
kubectlconfigset-contextdefault
--cluster=kubernetes
--user="kubelet-bootstrap"
--kubeconfig=bootstrap.kubeconfig
kubectlconfiguse-contextdefault--kubeconfig=bootstrap.kubeconfig
4.2、kubeadm生成bootstrap.kubeconfig文件
apiVersion:v1
kind:Config
clusters:
-cluster:
certificate-authority:/var/lib/kubernetes/ca.pem
server: 172.10.10.129:6443
name:bootstrap
contexts:
-context:
cluster:bootstrap
user:kubelet-bootstrap
name:bootstrap
current-context:bootstrap
preferences:{}
users:
-name:kubelet-bootstrap
user:
token:07401b.f395accd246ae52d
5、调整 Kubelet 配置,使其首次启动加载bootstrap.kubeconfig并使用其中的 TLS Bootstrapping Token 完成首次证书申请
[Service]
Environment="KUBELET_KUBECONFIG_ARGS=
--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf
--kubeconfig=/etc/kubernetes/kubelet.conf"
6、证书被 Controller Manager 签署,成功下发,Kubelet自动重载完成引导流程
7、后续 Kubelet 自动 renew 相关证书
8、可选的: 集群搭建成功后立即清除 Bootstrap Token Secret,或等待 Controller Manager 待其过期后删除,以防止被恶意利用
四、TLS bootstrapping引导程序初始化流程
细节参见官方文档:https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/
初始化流程:
- kubelet启动
- 查询自己有没有证书,有证书直接启动,如果没有kubeconfig文件
- kubelet根据启动参数配置路径寻找bootstrap-kubeconfig文件
- 读取bootstrap-kubeconfig中的apiserver地址和bootstrap token
在 apiserver 配置中指定了一个 token.csv 文件,该文件中是一个预设的用户配置;同时该用户的 Token 和 apiserver 的 CA 证书被写入了 kubelet 所使用的bootstrap.kubeconfig 配置文件中;这样在首次请求时,kubelet 使用 bootstrap.kubeconfig 中的 apiserver CA 证书来与 apiserver 建立 TLS 通讯,使用 bootstrap.kubeconfig 中的用户 Token 来向 apiserver 声明自己的 RBAC 授权身份 - 使用bootstrap token作为凭证访问apiserver
- 该token有权限去创建和获取证书签名请求(CSR) —— bootstrap token的命名具有特定的格式,可以被apiserver识别,username为system:bootstrap:<token id>,属于system:bootstrappers用户组,该用户组需要绑定system:node-bootstrapper的clusterrole,以便可以拥有创建csr的权限
- kubelet为自己创建一个CSR,签发者(csr.Spec.SignerName)为kubernetes.io/kube-apiserver-client-kubelet
- CSR被自动或者手动approved
4.1、controller-manager自动approve,需要system:bootstrappers用户组绑定system:certificates.k8s.io:certificatesigningrequests:nodeclient的clusterrole。controller-manager的CSRApprovingController会通过SubjectAccessReview API的方式来校验csr中的username和group是否有对应权限,同时检查签发者是否为kubernetes.io/kube-apiserver-client-kubelet
4.2、通过kubectl等手动approve - kubelet证书在approved之后由controller-manager创建
- controller-manager将证书更新到csr的status字段中
- kubelet从apiserver获取证书
- kubelet根据取回来的key和证书生成对应的kubeconfig
- kubelet使用生成的kubeconfig开始正常工作
- 如果配置了证书自动续期,则kubelet会在证书快过期的时候利用旧的kubeconfig来续约旧的证书
- 续约的证书被自动或者手动approved签发 —— 自动approve需要system:nodes用户组绑定system:certificates.k8s.io:certificatesigningrequests:selfnodeclient的clusterrole(system:nodes是kubelet之前申请的证书的group,即证书的组织O为system:nodes)
- 涉及的用户,用户组,权限
- bootstrap token的username为system:bootstrap:<token id>
- system:bootstrappers用户组,bootstrap token都属于该用户组
- clusterrole system:node-bootstrapper,拥有创建和获取CSR的权限,system:bootstrappers用户组一般需要绑定该role
- clusterrole system:certificates.k8s.io:certificatesigningrequests:nodeclient,属于该group的user申请的CSR可以被controller-manager自动approve,system:bootstrappers用户组一般需要绑定该role
- system:nodes用户组,kubelet从apiserver获取的证书一般都属于该用户组,即证书的组织O为system:nodes
- clusterrole system:certificates.k8s.io:certificatesigningrequests:selfnodeclient,属于该group的user在证书续期时可以被controller-manager自动approve,system:nodes用户组一般需要绑定该role
参考文档:
https://blog.csdn.net/paopaohll/article/details/89022920
https://mritd.com/2018/08/28/kubernetes-tls-bootstrapping-with-bootstrap-token/
https://cloud.tencent.com/developer/article/1656007
https://mritd.com/2018/01/07/kubernetes-tls-bootstrapping-note/
https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/
最后
以上就是陶醉奇迹为你收集整理的kubernetes二进宫系列——Kubernetes TLS BootStrapping流程引导分析的全部内容,希望文章能够帮你解决kubernetes二进宫系列——Kubernetes TLS BootStrapping流程引导分析所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复