Kubernetes - 证书相关
1 Kubernetes 中的证书
Kubernetes 所有组件之间的通信都基于 TLS 进行加密,并且都基于 mTLS 进行双向认证。因此,每个组件作为调用者需要配置:client cert + client key + server ca cert,作为服务端需要配置:server cert + server key + client ca cert。
1.1 证书配置
我们从调用关系来看,各个组件需要的证书配置:
-
Kubectl -> APIServer
Kubectl 作为客户端,需要配置 Client Cert + Client Key + Server CA Cert 用以被认证,相关参数位于 kubeconfig 配置中。
1 2 3 4 5 6 7 8 9
users: - name: kind-kind user: client-certificate-data: REDACTED # Client Cert client-key-data: REDACTED # Client Key clusters: - cluster: certificate-authority-data: DATA+OMITTED # CA Cert name: kind-kind
当然,证书认证仅仅是其中一种方式,其他方式见 Kubernetes - 认证与鉴权机制。
APIServer 作为服务端,需要配置 Server Cert + Server Key + Client CA Cert 用以被认证,相关参数通过启动参数配置。
1 2 3 4 5
kube-apiserver \ --tls-cert-file=/var/lib/kubernetes/kube-apiserver.pem \ # Server Cert --tls-private-key-file=/var/lib/kubernetes/kube-apiserver-key.pem \ # Server Key --client-ca-file=/var/lib/kubernetes/cluster-root-ca.pem \ # Client CA Cert # ...
-
APIServer -> ETCD
APIServer 作为客户端,需要配置 Client Cert + Client Key + Server CA Cert 用以被认证,相关参数通过启动参数配置。
1 2 3 4 5
kube-apiserver \ --etcd-certfile=/var/lib/kubernetes/kube-apiserver-etcd-client.pem \ # Client Cert --etcd-keyfile=/var/lib/kubernetes/kube-apiserver-etcd-client-key.pem \ # Client Key --etcd-cafile=/var/lib/kubernetes/cluster-root-ca.pem \ # CA Cert # ...
ETCD 作为服务端,需要配置 Server Cert + Server Key + Client CA Cert,相关参数通过启动参数配置。
1 2 3 4 5
etcd \ --cert-file=/etc/etcd/kube-etcd.pem \\ # Server Cert --key-file=/etc/etcd/kube-etcd-key.pem \\ # Server Key --peer-trusted-ca-file=/etc/etcd/cluster-root-ca.pem # Client CA Cert # ...
-
Scheduler -> APIServer
Scheduler 作为客户端,APIServer 作为服务端,与 Kubectl -> APIServer 中一样。
-
Controller -> APIServer - APIServer 作为服务端,Controller 作为客户端
Controller 作为客户端,APIServer 作为服务端,与 Kubectl -> APIServer 中一样。
-
KubeProxy -> APIServer - APIServer 作为服务端,KubeProxy 作为客户端
KubeProxy 作为客户端,基于 ServiceAccount 方式进行认证。
1 2 3 4
apiVersion: v1 kind: Pod spec: serviceAccount: kube-proxy
-
Kubelet <-> APIServer
Kubelet 作为客户端,Client Cert + Client Key + Server CA Cert 通过
kubeconfig
配置传入。1
kubelet --kubeconfig=/etc/kubernetes/kubelet.conf
Kubelet 也会作为服务端,Server Cert + Server Key + Client CA Cert 通过配置文件传入。
1 2 3 4 5 6 7 8 9
# kubelet --config=/var/lib/kubelet/config.yaml apiVersion: kubelet.config.k8s.io/v1beta1 kind: KubeletConfiguration tlsPrivateKeyFile: /var/lib/kubelet/pki/kubelet.crt # Server Cert tlsCertFile: /var/lib/kubelet/pki/kubelet.key # Server Key authentication: x509: clientCAFile: /etc/kubernetes/pki/ca.crt # Client CA Cert # ...
Note在没有提供tlsPrivateKeyFile
与tlsCertFile
配置情况下,Kubelet 会自签名证书与私钥,并保存到--cert-dir
参数(默认为 /var/lib/kubelet/pki)指定的目录下。APIServer 作为服务端,与 Kubectl -> APIServer 中一样。
APIServer 作为客户端,Client Cert + Client Key + Server CA Cert 通过命令行参数指定。
1 2 3 4 5
kube-apiserver \ --kubelet-client-certificate=/var/lib/kubernetes/kube-apiserver-kubelet-client.pem \ # Client Cert --kubelet-client-key=/var/lib/kubernetes/kube-apiserver-kubelet-client-key.pem \ # Client Key --kubelet-certificate-authority=/var/lib/kubernetes/cluster-root-ca.pem \ # Server CA Cert # ...
1.2 证书目录
ControlPlane 相关组件证书都是先在 Node 生成,然后通过 hostPath
挂载到 Pod 中,目录位于 /etc/kubernetes/pki
下:
|
|
Scheduler 或者 Kubelet 等核心组件访问 APIServer 使用的 kubeconfig
也是预先在 Node 生成,然后通过 hostPath
挂载到 Pod 中,目录位于 /etc/kubernetes
下:
|
|
Kubelet 作为客户端和服务端相关的证书默认位于 /var/lib/kubelet/
目录下(CA 证书使用的 /etc/kubernetes/pki/ca.crt
):
|
|
2 Kubernete 提供的证书签名
Kubernete 内部提供了简单的证书签名机制,基于 API Group certificates.k8s.io
提供。用户通过创建资源 CertificateSigningRequest
来提供 CSR,由 Controller Manager 来进行证书签发。
Controller Manager 基于以下参数提供了一个默认的 CA Cert 与 CA Key,来进行证书签发(默认使用 APIServer 的 CA):
|
|
2.3 证书签发
使用 CertificateSigningRequest
大致流程如下:
-
本地创建 Server Key 与 Server CSR
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
cat <<EOF | cfssl genkey - | cfssljson -bare server { "hosts": [ "my-svc.my-namespace.svc.cluster.local", "my-pod.my-namespace.pod.cluster.local", "192.0.2.24", "10.0.34.2" ], "CN": "my-pod.my-namespace.pod.cluster.local", "key": { "algo": "ecdsa", "size": 256 } } EOF
-
创建
CertificateSigningRequest
对象:1 2 3 4 5 6 7 8 9 10
apiVersion: certificates.k8s.io/v1 kind: CertificateSigningRequest metadata: name: my-svc.my-namespace spec: request: $(cat server.csr | base64 | tr -d '\n') usages: - digital signature - key encipherment - server auth
创建后可以看到相关的 csr 对象:
1 2 3
$ kubectl get csr NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION my-svc.my-namespace 12s example.com/serving kubernetes-admin <none> Pending