Kubernetes 创建 TLS 证书

前言

概述

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

组件证书
etcdca.pem、kubernetes-key.pem、kubernetes.pem
kube-apiserverca.pem、kubernetes-key.pem、kubernetes.pem
kubeletca.pem
kube-proxyca.pem、kube-proxy-key.pem、kube-proxy.pem
kubectlca.pem、admin-key.pem、admin.pem
kube-controller-managerca-key.pem、ca.pem

用于创建证书的 Json 文件

在部署 Kubernetes 集群时创建证书会使用到的 Json 文件,里面包含有 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 集群中添加新节点时,只要将对应的证书拷贝到新节点上即可。千万不要在每个 Node 节点都单独执行生成 Etcd 证书的操作,否则 Etcd 集群里的节点可能会因证书不一致而导致集群启动失败。

安装 CFSSL

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

1
2
3
4
5
6
7
8
9
10
# 二进制方式安装
# 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
## 字段说明:
expiry : 87600h 表示有效期 10 年;
ca-config.json:可以定义多个 profiles,分别指定不同的过期时间、使用场景等参数;后续在签名证书时使用某个 profile;
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 -

# 查看生成结果
# ls
ca-config.json ca.csr ca-csr.json ca-key.pem ca.pem

创建 Server 证书

创建用于生成 Server 证书的 Json 配置文件,如果 hosts 字段不为空,则需要指定授权使用该证书的 IP 或域名列表。由于该证书后续被 Etcd 集群和 Kubernetes 集群使用,所以一般分别指定 Etcd 集群、Kubernetes 集群各 Master、Node 节点的主机 IP 和 Kubernetes 服务 IP(通常是 kube-apiserver 指定的 service-cluster-ip-range 网段的第一个 IP,如 10.254.0.1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# cat << EOF | tee server-csr.json
{
"CN": "kubernetes",
"hosts": [
"192.168.1.61",
"192.168.1.62",
"192.168.1.63",
"192.168.1.64"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
EOF

创建 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 server-csr.json

# 创建Server证书,"-profile" 参数的值必须与 `ca-config.json` 配置文件中的值一致
# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes server-csr.json | cfssljson -bare server

# 查看生成结果
# ls
ca-config.json ca.csr ca-csr.json ca-key.pem ca.pem server.csr server-csr.json server-key.pem server.pem

# 验证证书
# cfssl-certinfo -cert server.pem
# openssl x509 -noout -text -in server.pem

参考博客