在kubeadm init过程中,会生成bootstrap token,node节点可以安装kubelet和kubeadm,执行kubeadm join加入到这个集群。

首先一开始,node上的kubeadm会发起一次“不安全模式”访问kube-apiserver,从而拿到保存在etcd中的cluster-info,也就是我们在kubeadm中最后说到的configmap,cluster-info保存着ca.crt等master的重要数据,而bootstrap token则扮演这个过程中的安全验证角色。node上的kubelet只要拿到cluster-info数据,那么之后就可以以“安全模式”连接到apiserver上去,这样一个新的节点就加入到了集群。

那么我们上面谈到node通过kubeadm join加入集群,在执行join命令时,首先会对当前node环境进行检查,然后会携带2个重要的参数discover-token-ca-cert-hash和token,进行身份验证

discover-token-ca-cert-hash

用于node验证master身份,保证当前node join到正确的master中,执行join时,apiserver会下发下发ca.crt公钥证书,这个证书数据会被node存放在/etc/kubernetes/pki目录下面,然后kubeadm会用公钥证书的哈希值与–discover-token-ca-cert-hash的值进行比对,确定是否为正确的master

通过openssl计算公钥哈希值

openssl x509 -in ca.crt -noout -pubkey | openssl rsa -pubin -outform DER 2>/dev/null | sha256sum | cut -d' ' -f1

可以看到,在join的时候,master将ca.crt下发到node的/etc/kubernetes/pki目录下,然后通过openssl计算ca.crt的哈希值,跟我们join的–discover-token-ca-cert-hash是完全相同的

token

用于master验证node身份,要想在集群首次引导启动时进行token验证,必须在kube-apiserver.yaml中开启enable-bootstrap-token-auth,一旦将此选项设置为true,那么就允许apiserver在集群init的时候,开启token验证。

token分为2段,例如我们这个 “oddhj0.q6ee7d16phc6bth2”,以 “.” 分割,前面一段是token id,后面一段是secret,当kubeadm join访问apiserver的时候,会在请求的header中携带这一个token,apiserver会根据这个token进行身份验证。

apiserver会查询kube-system名称空间下是否存在bootstrap-token前缀的secret

[root@k8s-master ~]# kubectl get secret -n kube-system | grep bootstrap-token
bootstrap-token-oddhj0 bootstrap.kubernetes.io/token 7 6h36m

apiserver会用这个查询到的secret和header中的token进行验证

通过 kubectl get secret bootstrap-token-oddhj0 -o yaml -n kube-system 查看 token-id 和 token-secret 字段的值

进行base64解码

将这2个解码后的数据进行组合,就是 “oddhj0.q6ee7d16phc6bth2”,与header中的token完全一致

最后整个验证过程就完成,node就会成功加入到集群中