关于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
upload-image

下面我们根据这个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的认证方式

upload-image

这里参考大佬的文章根据集群的实际部署对k8s的证书进行了梳理,加深对这方面的知识了解,有什么问题请大家多多指正。

参考链接

https://mp.weixin.qq.com/s/IbxRTQBOeKtL8AlC3R65Rw

https://kubernetes.io/zh/docs/setup/best-practices/certificates/

最后更新于

这有帮助吗?