关于kubernetes证书的那点事
本篇文章主要介绍了k8s中用的证书和组件之间是如何进行认证访问的。
k8s证书介绍
众所周知。Kubernetes 需要 PKI 证书才能进行基于 TLS 的身份验证。如果你是使用kubeadm安装的 Kubernetes, 则会自动生成集群所需的证书。但是如果是通过二进制搭建,所有的证书是需要自己生成的,这里我们说说集群必需的证书。
服务器单向认证:只需要服务器端提供证书,客户端通过服务器端证书验证服务的身份,但服务器并不验证客户端的身份。这种情况一般适用于对 Internet 开放的服务,例如搜索引擎网站,任何客户端都可以连接到服务器上进行访问,但客户端需要验证服务器的身份,以避免连接到伪造的恶意服务器。
双向 TLS 认证:除了客户端需要验证服务器的证书,服务器也要通过客户端证书验证客户端的身份。这种情况下服务器提供的是敏感信息,只允许特定身份的客户端访问
Kubernetes为了安全性,都是采用双向认证。通常我们在部署k8s时候,kubeadm会自动生成集群所需要的证书,下面我们就这些证书一一给大家进行讲解。 这是我们用kubeadm搭建完一个集群后再/etc/kubernetes目录下所生成的文件
[root@VM-4-3-centos etc]# tree kubernetes/
kubernetes/
|-- admin.conf
|-- controller-manager.conf
|-- kubelet.conf
|-- scheduler.conf
|-- manifests
| |-- etcd.yaml
| |-- kube-apiserver.yaml
| |-- kube-controller-manager.yaml
| `-- kube-scheduler.yaml
|-- pki
| |-- apiserver.crt
| |-- apiserver-etcd-client.crt
| |-- apiserver-etcd-client.key
| |-- apiserver.key
| |-- apiserver-kubelet-client.crt
| |-- apiserver-kubelet-client.key
| |-- ca.crt
| |-- ca.key
| |-- etcd
| | |-- ca.crt
| | |-- ca.key
| | |-- healthcheck-client.crt
| | |-- healthcheck-client.key
| | |-- peer.crt
| | |-- peer.key
| | |-- server.crt
| | `-- server.key
| |-- front-proxy-ca.crt
| |-- front-proxy-ca.key
| |-- front-proxy-client.crt
| |-- front-proxy-client.key
| |-- sa.key
| `-- sa.pub
下面我们根据这个k8s的组件之间通讯图来一一讲解每个证书的作用。
CA证书
kubeadm安装的集群中我们都是用3套CA证书来管理和签发其他证书,一套CA给ETCD使用,一套是给kubernetes内部组件使用,还有一套是给配置聚合层使用的,当然如果你觉得管理3套CA比较麻烦,您也可以用一套来管理。
etcd证书
etcd证书位于/etc/kubernetes/pki/etcd目录下,我们根据etcd的yaml配置解释下证书的作用
etcd 对外提供服务的服务器证书及私钥
etcd 节点之间相互进行认证的 peer 证书、私钥以及验证 peer 的 CA
etcd 验证访问其服务的客户端的 CA
kube-apiserver证书
apiserver证书位于/etc/kubernetes/pki,同样我们通过apiserver的yaml文件来一一解释下每个证书的作用。
访问etcd的客户端证书及私钥,这个证书是由etcd的CA证书签发,因此也需要在apiserver中配置etcd的CA证书
用来签发k8s中其他证书的CA证书及私钥
apiServer的对外提供服务的服务端证书及私钥
apiserver 访问 kubelet 所需的客户端证书及私钥
配置聚合层(apiserver扩展)的CA和客户端证书及私钥
说明:要使聚合层在您的环境中正常工作以支持代理服务器和扩展 apiserver 之间的相互 TLS 身份验证, 需要满足一些设置要求。Kubernetes 和 kube-apiserver 具有多个 CA, 因此请确保代理是由聚合层 CA 签名的,而不是由主 CA 签名的。扩展apiserver为了能够和apiserver通讯,所以需要在apiserver中配置,假如你不需要这个功能可以不配置该证书。
```front-proxy-ca.crt front-proxy-client.crt front-proxy-ca.key front-proxy-client.key
```
验证 service account token 的公钥
到这里,集群生成的所有证书介绍完了,那么像kube-controller-mananger、kube-scheduler、kube-proxy、kubele这些组件也是需要访问apiserver的,那么他们是怎么通讯的呢?下面我们可以看看这些组件是如何和apiserver进行通讯的。
kube-controller-mananger
还是和之前一样,我们通过kube-controller-mananger的yaml文件配置来看看是如何访问apiserver。
你会发现在yaml中配置了/etc/kubernetes/controller-manager.conf这个配置文件,而不是配置controller-manager的客户端证书之类的。Kubernetes 这里的设计是这样的,kube-controller-mananger、kube-scheduler、kube-proxy、kubelet等组件,采用一个kubeconfig 文件中配置的信息来访问 kube-apiserver。该文件中包含了 kube-apiserver 的地址,验证 kube-apiserver 服务器证书的 CA 证书,自己的客户端证书和私钥等访问信息,这样组件只需要配置这个kubeconfig就行。
由于创建工作负载的时候,我们有时候会用到service accout,那么这里需要和apiserver认证,所以我们需要在controller-manager
配置上sa私钥,当然需要和apiserver通讯,自然需要配置上kubernates的CA证书
下面我们看看controller-manager.conf这个文件配置的证书和秘钥是什么。
我们解析下certificate-authority-data这个内容看看是不是CA的证书
从解码可以发现,kubeconfig配置的就是kubernates的CA证书,client-certificate-data和client-key-data就是controller-manager用来访问apiserver的客户端证书和秘钥,只不过kubeconfig对内容进行了base64编码。这个就是整个controller-manager和apiserver证书认证的方式。
kube-scheduler
kube-scheduler也是同样的原理,也是在yaml中配置一个kubeconfig来进行访问apiserver
同理,解析certificate-authority-data也是kubernates的CA证书,client-certificate-data和client-key-data就是kube-scheduler用来访问apiserver的客户端证书和秘钥
kube-proxy
在这里我们并未发现kube-proxy的kubeconfig,kube-proxy也是需要访问apiserver的,那么是如何进行认证的。还是从yaml文件进行分析一下,如果需要认证,肯定会在yaml中配置对应的证书或者包含证书的文件或token
从上面token的内容,这个里面包含一个CA证书是kubernates查到ca证书,token就是用来和apiserver通讯的客户端证书和秘钥
kubelet
kubelet和其他组件类似,用的kubeconfig来进行认证的,都是用kubernates的CA生成。
这边我们会给每个节点生成一份客户端的证书和私钥,master上用的是kubelet.conf ,节点上的kubelet.conf如下,直接指向一个kubelet-client-current.pem文件,这里包含了证书和私钥,每一个节点都不一样。因此每个节点都会有一个自己的客户端证书和私钥。
现在有一个问题就是,k8s中节点可能有几万个,那么是如何快速给节点自动生成客户端证书和秘钥然后配置给kubelet呢?
查看kubelet进程可以发现还有一个kubeconfig是bootstrap-kubelet.conf,我们来看看这个文件配置的是什么?
Kubernetes 提供了 TLS bootstrapping 的方式来简化 Kubelet 证书的生成过程。其原理是预先提供一个 bootstrapping token,kubelet 通过该 kubelet 调用 kube-apiserver 的证书签发 API 来生成 自己需要的证书。要启用该功能,需要在 kube-apiserver 中启用 --enable-bootstrap-token-auth ,并创建一个 kubelet 访问 kube-apiserver 使用的 bootstrap token secret。如果使用 kubeadmin 安装,可以使用 kubeadm token create命令来创建 token。
采用TLS bootstrapping 生成证书的流程如下: 1. 调用 kube-apiserver 生成一个 bootstrap token。 将该 bootstrap token 写入到一个 kubeconfig 文件中,作为 kubelet 调用 kube-apiserver 的客户端验证方式。 2. 通过 --bootstrap-kubeconfig 启动参数将 bootstrap token 传递给 kubelet 进程。 3. Kubelet 采用 bootstrap token 调用 kube-apiserver API,生成自己所需的服务器和客户端证书。 4. 证书生成后,Kubelet 采用生成的证书和 kube-apiserver 进行通信,并删除本地的 kubeconfig 文件,以避免 bootstrap token 泄漏风险。
Service Account 认证
前面我们有说在kube-apiserver 和 kube-controller-manager分配配置的sa的公钥和私钥,这里就是用来对service account来进行认证的,我们一般在RBAC中来限制service account的访问限制。kubernetes 会为该 service account 生成一个 JWT token,并使用 secret 将该 service account token 加载到 pod 上。pod 中的应用可以使用 service account token 来访问 api server。service account 证书被用于生成和验证 service account token。该证书的用法和前面介绍的其他证书不同,因为实际上使用的是其公钥和私钥,而并不需要对证书进行验证。下面是service account的认证方式

这里参考大佬的文章根据集群的实际部署对k8s的证书进行了梳理,加深对这方面的知识了解,有什么问题请大家多多指正。
参考链接
https://mp.weixin.qq.com/s/IbxRTQBOeKtL8AlC3R65Rw
https://kubernetes.io/zh/docs/setup/best-practices/certificates/
最后更新于
这有帮助吗?