参考文档
一文带你彻底厘清 Kubernetes 中的证书工作机制 | 云原生社区(中国)
TLS认证
双向TLS认证:
客户端需要验证服务端的证书,服务端也需要通过客户端证书验证客户端身份。
双向TLS认证回涉及到以下文件:
- 服务器端证书:服务器用于证明自身身份的数字证书,里面主要包含了服务器端的公钥以及服务器的身份信息。
- 服务器端私钥:服务器端证书中包含的公钥所对应的私钥。公钥和私钥是成对使用的,在进行 TLS 验证时,服务器使用该私钥来向客户端证明自己是服务器端证书的拥有者。
- 客户端证书:客户端用于证明自身身份的数字证书,里面主要包含了客户端的公钥以及客户端的身份信息。
- 客户端私钥:客户端证书中包含的公钥所对应的私钥,同理,客户端使用该私钥来向服务器端证明自己是客户端证书的拥有者。
- 服务器端 CA 根证书:签发服务器端证书的 CA 根证书,客户端使用该 CA 根证书来验证服务器端证书的合法性。
- 客户端 CA 根证书:签发客户端证书的 CA 根证书,服务器端使用该 CA 根证书来验证客户端证书的合法性。
Kubernetes中使用到的证书
上图中使用序号对证书进行了标注。图中的箭头表明了组件的调用方向,箭头所指方向为服务提供方,另一头为服务调用方。图中标注的这些证书的作用分别如下:
-
etcd 集群中各个节点之间相互通信使用的证书。由于一个 etcd 节点既为其他节点提供服务,又需要作为客户端访问其他节点,因此该证书同时用作服务器证书和客户端证书。
-
etcd 集群向外提供服务使用的证书。该证书是服务器证书。
-
kube-apiserver 作为客户端访问 etcd 使用的证书。该证书是客户端证书。
-
kube-apiserver 对外提供服务使用的证书。该证书是服务器证书。
-
kube-controller-manager 作为客户端访问 kube-apiserver 使用的证书,该证书是客户端证书。
-
kube-scheduler 作为客户端访问 kube-apiserver 使用的证书,该证书是客户端证书。
-
kube-proxy 作为客户端访问 kube-apiserver 使用的证书,该证书是客户端证书。
-
kubelet 作为客户端访问 kube-apiserver 使用的证书,该证书是客户端证书。
-
管理员用户通过 kubectl 访问 kube-apiserver 使用的证书,该证书是客户端证书。
-
kubelet 对外提供服务使用的证书。该证书是服务器证书。
-
kube-apiserver 作为客户端访问 kubelet 采用的证书。该证书是客户端证书。
-
kube-controller-manager 用于生成和验证 service-account token 的证书。该证书并不会像其他证书一样用于身份认证,而是将证书中的公钥/私钥对用于 service account token 的生成和验证。kube-controller-manager 会用该证书的私钥来生成 service account token,然后以 secret 的方式加载到 pod 中。pod 中的应用可以使用该 token 来访问 kube-apiserver, kube-apiserver 会使用该证书中的公钥来验证请求中的 token。
Kubernetes证书配置
etcd证书配置
需要在 etcd 的启动命令行中配置以下证书相关参数:
- etcd 对外提供服务的服务器证书及私钥。
- etcd 节点之间相互进行认证的 peer 证书、私钥以及验证 peer 的 CA。
- etcd 验证访问其服务的客户端的 CA。
/usr/local/bin/etcd \\
--cert-file=/etc/etcd/kube-etcd.pem \\ # 对外提供服务的服务器证书
--key-file=/etc/etcd/kube-etcd-key.pem \\ # 服务器证书对应的私钥
--peer-cert-file=/etc/etcd/kube-etcd-peer.pem \\ # peer 证书,用于 etcd 节点之间的相互访问
--peer-key-file=/etc/etcd/kube-etcd-peer-key.pem \\ # peer 证书对应的私钥
--trusted-ca-file=/etc/etcd/cluster-root-ca.pem \\ # 用于验证访问 etcd 服务器的客户端证书的 CA 根证书
--peer-trusted-ca-file=/etc/etcd/cluster-root-ca.pem\\ # 用于验证 peer 证书的 CA 根证书
kubernetes证书配置
需要在 kube-apiserver 中配置以下证书相关参数:
- kube-apiserver 对外提供服务的服务器证书及私钥。
- kube-apiserver 访问 etcd 所需的客户端证书及私钥。
- kube-apiserver 访问 kubelet 所需的客户端证书及私钥。
- 验证访问其服务的客户端的 CA。
- 验证 etcd 服务器证书的 CA 根证书。
- 验证 service account token 的公钥。
/usr/local/bin/kube-apiserver \\
--tls-cert-file=/var/lib/kubernetes/kube-apiserver.pem \\ # 用于对外提供服务的服务器证书
--tls-private-key-file=/var/lib/kubernetes/kube-apiserver-key.pem \\ # 服务器证书对应的私钥
--etcd-certfile=/var/lib/kubernetes/kube-apiserver-etcd-client.pem \\ # 用于访问 etcd 的客户端证书
--etcd-keyfile=/var/lib/kubernetes/kube-apiserver-etcd-client-key.pem \\ # 用于访问 etcd 的客户端证书的私钥
--kubelet-client-certificate=/var/lib/kubernetes/kube-apiserver-kubelet-client.pem \\ # 用于访问 kubelet 的客户端证书
--kubelet-client-key=/var/lib/kubernetes/kube-apiserver-kubelet-client-key.pem \\ # 用于访问 kubelet 的客户端证书的私钥
--client-ca-file=/var/lib/kubernetes/cluster-root-ca.pem \\ # 用于验证访问 kube-apiserver 的客户端的证书的 CA 根证书
--etcd-cafile=/var/lib/kubernetes/cluster-root-ca.pem \\ # 用于验证 etcd 服务器证书的 CA 根证书
--kubelet-certificate-authority=/var/lib/kubernetes/cluster-root-ca.pem \\ # 用于验证 kubelet 服务器证书的 CA 根证书
--service-account-key-file=/var/lib/kubernetes/service-account.pem \\ # 用于验证 service account token 的公钥
...
cfssl 证书生成(以etcd证书为例)
cfssl是一个开源的证书管理工具,使用json文件生成证书,相比openssl更方便使用。
# 创建工作目录
mkdir cfssl && cd cfssl/
# 下载软件包
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
# 增加可执行权限
chmod +x cfssl_linux-amd64 cfssljson_linux-amd64 cfssl-certinfo_linux-amd64
# 放置到可执行文件目录
mv cfssl_linux-amd64 /usr/local/bin/cfssl
mv cfssljson_linux-amd64 /usr/local/bin/cfssljson
mv cfssl-certinfo_linux-amd64 /usr/bin/cfssl-certinfo
# 创建证书请求文件
cat > server-csr.json << EOF
{
"CN": "etcd",
"hosts": [
"172.16.133.10",
"172.16.133.11",
"172.16.133.12"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing"
}
]
}
EOF
# 注:上述文件hosts字段中IP为所有etcd节点的集群内部通信IP,一个都不能少!为了方便后期扩容可以多写几个预留的IP。
# 生成证书,会生成server.pem和server-key.pem文件
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=www server-csr.json | cfssljson -bare server