Kubernetes 创建 TLS 证书

前言

Kubernetes 系统的各组件需要使用 TLS 证书对通信进行加密,可以使用 CloudFlare 的 PKI 工具集 CFSSL 来生成 Certificate Authority(CA)和其它证书。使用到证书的 Kubernetes 组件如下:

组件使用的证书(证书的名称可能跟下面的不一样)
ca 根证书ca.pemca-key.pem
etcdca.pemetcd-server-key.pemetcd-server.pem
kube-apiserverca.pemkube-apiserver-key.pemkube-apiserver.pem
kube-controller-managerca.pemkube-controller-manager-key.pemkube-controller-manager.pem
kube-schedulerca.pemkube-scheduler-key.pemkube-scheduler.pem
kubeletca.pem
kube-proxyca.pemkube-proxy-key.pemkube-proxy.pem
kubectlca.pemadmin-key.pemadmin.pem

特别注意

  • 一般来说,证书文件名中不带 -key(例如 ca.pem)的是公钥证书,可以公开使用;而带有 -key(例如 ca-key.pem)的是私钥文件,属于敏感信息,必须严格保密,不得对外公开

生成证书的配置文件

在部署 Kubernetes 集群时,Kubernetes 各组件生成证书时使用到的 JSON 配置文件有很多个,目录结构如下,点击下载所有文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
├── ca
│   └── ca-config.json
├── etcd
│   └── server-csr.json
├── kube-apiserver
│   └── server-csr.json
├── kube-controller-manager
│   └── kube-controller-manager-csr.json
├── kubectl
│   └── admin-csr.json
├── kubelet
│   └── kubelet.config.json
├── kube-proxy
│   └── kube-proxy-csr.json
└── kube-scheduler
└── kube-scheduler-csr.json

特别注意

  • 生成证书的操作都是在 Kubernetes 集群的任意一个 Master 节点上执行,证书只需要生成一次即可,以后向 Kubernetes 集群中添加新节点时,只要将对应的证书拷贝到新节点上即可
  • 千万不要在每个 Master 节点和 Node 节点都单独执行生成证书的操作,否则 Kubernetes 集群里的节点可能会因证书不一致而导致集群启动失败

安装 CFSSL

CFSSL 是 CloudFlare 开源的一款 PKI/TLS 工具,包含一个命令行工具和一个用于签名、验证并且捆绑 TLS 证书的 HTTP API 服务,使用 Go 语言编写。

1
2
3
4
5
6
7
8
9
10
# 二进制方式安装CSSL工具
# curl -L https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -o /usr/local/bin/cfssl
# curl -L https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -o /usr/local/bin/cfssljson
# curl -L https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64 -o /usr/local/bin/cfssl-certinfo

# 文件授权
# chmod +x /usr/local/bin/cfssl*

# 配置环境变量
# export PATH=/usr/local/bin:$PATH

生成 CA 证书

创建 CA 证书的配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# cat << EOF | tee ca-config.json
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"expiry": "87600h",
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
]
}
}
}
}
EOF
1
2
3
4
5
6
## 配置说明:
ca-config.json:可以定义多个 profiles,分别指定不同的过期时间、使用场景等参数;后续在签名证书时使用某个 profile;
expiry : 87600h 表示有效期 10 年;
signing:表示该证书可用于签名其它证书;生成的 ca.pem 证书中 CA=TRUE;
server auth:表示 client 可以用该 CA 对 server 提供的证书进行验证;
client auth:表示 server 可以用该 CA 对 client 提供的证书进行验证;

创建 CA 证书签名的配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# cat << EOF | tee ca-csr.json
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
],
"ca": {
"expiry": "87600h"
}
}
EOF
1
2
3
## 配置说明:
"CN":Common Name,kube-apiserver 从证书中提取该字段作为请求的用户名 (User Name);浏览器使用该字段验证网站是否合法;
"O":Organization,kube-apiserver 从证书中提取该字段作为请求用户所属的组 (Group);

生成 CA 证书

1
2
3
4
5
6
7
8
9
10
# 查看当前目录下的文件
# ls
ca-config.json ca-csr.json

# 生成CA证书和私钥
# cfssl gencert -initca ca-csr.json | cfssljson -bare ca -

# 查看生成的CA证书和私钥
# ls ca*.pem
ca-key.pem ca.pem

使用自签 CA 签发证书

使用自签 CA 签发证书,例如使用前面生成的 CA 证书为 API Server 签发证书,需要先创建一个用于签发 API Server 证书的配置文件(如下所示)。若配置文件中的 hosts 字段不为空,则必须在该字段中列出允许使用该证书的 IP 地址或域名列表,即只有这些 IP 或域名才能合法使用该证书。举个例子,如果该证书后续会被 Kubernetes 集群使用到,那么 hosts 字段通常包含 Kubernetes 集群所有节点的 IP,以及 Kubernetes 服务的 Cluster IP(即 kube-apiserver.conf 配置文件中指定的 --service-cluster-ip-range 网段的第一个可用 IP,例如 10.0.0.1,具体取决于 Kubernetes 集群的 Service 网段配置)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# cat << EOF | tee kube-apiserver-csr.json
{
"CN": "kubernetes",
"hosts": [
"10.0.0.1",
"127.0.0.1",
"192.168.2.191",
"192.168.2.112",
"192.168.2.131",
"192.168.2.236",
"kubernetes",
"kubernetes.default",
"kubernetes.default.svc",
"kubernetes.default.svc.cluster",
"kubernetes.default.svc.cluster.local"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
EOF

使用前面生成的 CA 证书为 API Server 签发证书

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 查看当前目录下的文件
# ls
ca-config.json ca.csr ca-csr.json ca-key.pem ca.pem kube-apiserver-csr.json

# 使用自签 CA 证书签发 API Server 证书,"-profile" 参数的值必须与 `ca-config.json` 配置文件中的值一致
# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-apiserver-csr.json | cfssljson -bare kube-apiserver

# 查看生成的 API Server 证书
# ls kube-apiserver*.pem
kube-apiserver-key.pem kube-apiserver.pem

# 验证生成的 API Server 证书
# cfssl-certinfo -cert kube-apiserver.pem
# openssl x509 -noout -text -in kube-apiserver.pem

参考博客