创建TLS证书和秘钥
前言
注意:这一步是在安装配置kubernetes的所有步骤中最容易出错也最难于排查问题的一步,而这却刚好是第一步,万事开头难,不要因为这点困难就望而却步。
kubernetes
系统的各组件需要使用 TLS
证书对通信进行加密,本文档使用 CloudFlare
的 PKI 工具集 cfssl 来生成 Certificate Authority (CA) 和其它证书;
生成的CA证书和密钥文件如下:
ca-key.pem
ca.pem
kubernetes-key.pem
kubernetes.pem
kube-proxy.pem
kube-proxy-key.pem
admin.pem
admin-key.pem
使用证书的组件如下:
etcd:使用 ca.pem、kubernetes-key.pem、kubernetes.pem;
kube-apiserver:使用 ca.pem、kubernetes-key.pem、kubernetes.pem;
kubelet:使用 ca.pem;
kube-proxy:使用 ca.pem、kube-proxy-key.pem、kube-proxy.pem;
kubectl:使用 ca.pem、admin-key.pem、admin.pem
kube-controller-manager:使用 ca-key.pem、ca.pem
注意:以下操作都在 master 节点即 192.168.70.21 这台主机上执行,证书只需要创建一次即可,以后在向集群中添加新节点时只要将 /etc/kubernetes/ 目录下的证书拷贝到新节点上即可。
安装 CFSSL
直接使用二进制源码包安装
cd /opt
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64
chmod +x cfssl_linux-amd64
mv cfssl_linux-amd64 /usr/local/bin/cfssl
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64
chmod +x cfssljson_linux-amd64
mv cfssljson_linux-amd64 /usr/local/bin/cfssljson
wget https://pkg.cfssl.org/R1.2/cfssl-certinfo_linux-amd64
chmod +x cfssl-certinfo_linux-amd64
mv cfssl-certinfo_linux-amd64 /usr/local/bin/cfssl-certinfo
创建 CA (Certificate Authority)
创建 CA 配置文件
mkdir /root/ssl
cd /root/ssl/
cfssl print-defaults config > config.json
cfssl print-defaults csr > csr.json
# 根据config.json 文件的格式创建如下的ca-config.json文件
#过期时间设置大点876000h 100年
vim ca-config.json
{
"signing": {
"default": {
"expiry": "876000h"
},
"profiles": {
"kubernetes": {
"expiry": "876000h",
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
]
}
}
}
}
字段说明
ca-config.json
:可以定义多个 profiles,分别指定不同的过期时间、使用场景等参数;后续在签名证书时使用某个 profile;signing
:表示该证书可用于签名其它证书;生成的 ca.pem 证书中CA=TRUE
;server auth
:表示client可以用该 CA 对server提供的证书进行验证;client auth
:表示server可以用该CA对client提供的证书进行验证;
创建 CA 证书签名请求
mv csr.json ca-csr.json
vim ca-csr.json
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing",
"O": "k8s",
"OU": "System"
}
],
"ca": {
"expiry": "876000h"
}
}
- "CN":
Common Name
,kube-apiserver 从证书中提取该字段作为请求的用户名 (User Name);浏览器使用该字段验证网站是否合法; - "O":
Organization
,kube-apiserver 从证书中提取该字段作为请求用户所属的组 (Group);
生成 CA 证书和私钥
cfssl gencert -initca ca-csr.json | cfssljson -bare ca
ls ca*
ca-config.json ca.csr ca-csr.json ca-key.pem ca.pem
创建 kubernetes 证书
创建 kubernetes 证书签名请求文件 kubernetes-csr.json
:
vim kubernetes-csr.json
{
"CN": "kubernetes",
"hosts": [
"127.0.0.1",
"192.168.76.10",
"192.168.76.11",
"192.168.76.14",
"192.168.76.250",
"10.7.1.45",
"192.168.70.21",
"10.7.4.17",
"10.254.0.1",
"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"
}
]
}
hosts为空配置
vim kubernetes-csr.json
{
"CN": "kubernetes",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
如果 hosts 字段不为空则需要指定授权使用该证书的 IP 或域名列表,由于该证书后续被 etcd
集群和 kubernetes master
注意: 创建kubernete集群的时候hosts字段一定不能为空。里面需要加etcd 集群和kubernetes master节点的ip。
集群使用,所以上面分别指定了 etcd
集群、kubernetes master
集群的主机 IP 和 kubernetes
服务的服务 IP(一般是 kube-apiserver
指定的service-cluster-ip-range
网段的第一个IP,如 10.254.0.1)。
其中192.168.76.250 是master节点高可用 keepalive的虚拟ip。如果不加,mater高可用的时候使用vip的时候报证书错误。
生成 kubernetes 证书和私钥
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kubernetes-csr.json | cfssljson -bare kubernetes
ls kubernetes*
kubernetes.csr kubernetes-csr.json kubernetes-key.pem kubernetes.pem
注意:这里有个坑,服务器装的时候默认装成中文编码,编辑kubernetes-csr.json后,生成kubernetes证书和私钥的时候报错 "code":5200,"message":"failed to unmarshal configuration: invalid character。最后吧服务器编码改后 ,重新从第一步开始就没有报错了。
创建 admin 证书
创建 admin 证书签名请求文件 admin-csr.json
:
vim admin-csr.json
{
"CN": "admin",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing",
"O": "system:masters",
"OU": "System"
}
]
}
- 后续
kube-apiserver
使用RBAC
对客户端(如kubelet
、kube-proxy
、Pod
)请求进行授权; kube-apiserver
预定义了一些RBAC
使用的RoleBindings
,如cluster-admin
将 Groupsystem:masters
与 Rolecluster-admin
绑定,该 Role 授予了调用kube-apiserver
的所有 API的权限;- O 指定该证书的 Group 为
system:masters
,kubelet
使用该证书访问kube-apiserver
时 ,由于证书被 CA 签名,所以认证通过,同时由于证书用户组为经过预授权的system:masters
,所以被授予访问所有 API 的权限;
注意:这个admin 证书,是将来生成管理员用的kube config 配置文件用的,现在我们一般建议使用RBAC 来对kubernetes 进行角色权限控制, kubernetes 将证书中的CN 字段 作为User, O 字段作为 Group中 X509 Client Certs 一段)。
在搭建完 kubernetes 集群后,我们可以通过命令: kubectl get clusterrolebinding cluster-admin -o yaml
,查看到 clusterrolebinding cluster-admin
的 subjects 的 kind 是 Group,name 是 system:masters
。 roleRef
对象是 ClusterRole cluster-admin
。 意思是凡是 system:masters Group
的 user 或者 serviceAccount
都拥有 cluster-admin
的角色。 因此我们在使用 kubectl 命令时候,才拥有整个集群的管理权限。可以使用 kubectl get clusterrolebinding cluster-admin -o yaml
来查看。
生成 admin 证书和私钥:
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes admin-csr.json | cfssljson -bare admin
ls admin*
admin.csr admin-csr.json admin-key.pem admin.pem
创建 kube-proxy 证书
创建 kube-proxy 证书签名请求文件 kube-proxy-csr.json
:
vim kube-proxy-csr.json
{
"CN": "system:kube-proxy",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L": "BeiJing",
"ST": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
- CN 指定该证书的 User 为
system:kube-proxy
; kube-apiserver
预定义的 RoleBindingcluster-admin
将Usersystem:kube-proxy
与 Rolesystem:node-proxier
绑定,该 Role 授予了调用kube-apiserver
Proxy 相关 API 的权限;生成 kube-proxy 客户端证书和私钥
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy
ls kube-proxy*
kube-proxy.csr kube-proxy-csr.json kube-proxy-key.pem kube-proxy.pem
校验证书
以 kubernetes 证书为例
使用 opsnssl
命令
openssl x509 -noout -text -in kubernetes.pem
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
07:a0:70:d7:cb:7b:2b:13:25:05:c6:42:31:0b:ad:af:41:a2:16:2d
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=CN, ST=BeiJing, L=BeiJing, O=k8s, OU=System, CN=kubernetes
Validity
Not Before: Apr 24 07:34:00 2018 GMT
Not After : Mar 31 07:34:00 2118 GMT
Subject: C=CN, ST=BeiJing, L=BeiJing, O=k8s, OU=System, CN=kubernetes
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:e3:6d:bc:0f:78:fe:23:ed:fc:0c:09:49:51:bb:
59:cc:5c:36:75:10:93:38:f4:6c:9e:b7:2f:fd:69:
59:de:07:31:a5:fa:19:1f:70:b1:c8:87:8d:dc:c8:
40:1d:dc:7b:5e:e4:af:3f:0a:ef:99:86:e6:e3:2a:
4c:dd:64:51:3b:b6:4e:c5:e2:d8:88:ba:f2:b2:5e:
58:63:6d:1c:2e:3c:e3:29:d6:40:8d:e7:3a:7f:a7:
18:20:60:c7:91:9d:b8:4f:bf:aa:83:52:e4:a6:5f:
db:7b:2e:c3:02:9e:4b:ba:df:b1:cd:3d:7b:f8:5a:
25:99:6e:70:36:da:34:f4:dc:bb:a1:42:e2:c6:ed:
91:34:1c:e9:cc:d2:42:ff:c6:ae:ee:0e:51:d0:e2:
15:13:5f:11:3b:90:56:b5:1a:e1:5d:a2:6c:0d:f5:
87:ec:d5:f1:3b:72:f4:59:b0:71:43:51:85:d3:cb:
f7:26:fc:3e:6f:c3:a0:ea:5b:a7:07:cc:9c:56:88:
93:bf:84:af:3b:71:6a:20:40:c6:46:5b:24:2e:2c:
8d:74:18:f8:88:f1:29:02:ab:ae:fe:0a:93:fe:8d:
7d:79:75:b7:24:ad:eb:36:24:07:d8:84:c0:4b:37:
1c:17:5c:72:47:a6:df:c4:06:e3:9d:13:0b:e5:b2:
2e:0f
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Subject Key Identifier:
1A:44:CA:AA:8A:D7:8A:4B:DA:1F:35:D4:91:2A:3E:94:86:B4:FF:27
X509v3 Authority Key Identifier:
keyid:38:1B:C7:93:3F:50:F8:24:BB:57:68:48:17:45:C5:45:C5:F0:52:8F
Signature Algorithm: sha256WithRSAEncryption
75:2e:20:9b:24:d1:f9:07:11:a5:51:7f:0e:e3:71:66:a4:fc:
b5:cc:7f:62:92:63:c2:73:3f:a1:8e:1a:2c:78:d1:33:cf:d9:
42:85:32:0e:99:de:54:84:82:a8:b7:ad:a7:74:ba:88:c7:f8:
81:f5:46:b8:d7:4c:e1:3d:0f:2f:53:07:7a:88:ba:df:b1:14:
0b:34:3c:89:ff:74:4d:16:27:7b:e0:c9:08:2f:e4:48:30:80:
de:c1:ed:76:df:71:c4:c4:8a:a6:0e:54:fa:9f:6c:cd:de:9a:
c8:89:42:15:3a:07:b3:53:53:6f:c4:4c:2e:ad:bc:27:60:a4:
e7:b6:60:3b:0f:d1:e4:bd:b4:1f:b7:b3:6c:5e:2c:dc:cd:70:
7f:e3:22:d3:02:52:9b:bb:c0:9e:36:b4:bb:8c:d8:07:0f:ec:
f5:45:86:4c:65:c1:37:90:7a:24:c2:52:56:b8:16:60:93:25:
fd:07:a6:fb:58:01:98:47:58:bf:ca:82:b7:39:85:bf:79:da:
39:a9:42:17:9f:72:3e:1c:4c:24:41:d5:c0:b2:98:01:db:5d:
6f:76:16:86:84:37:af:f0:47:1e:a7:a2:6d:26:b6:9b:0f:c6:
f3:3d:b6:ff:1b:6f:75:2f:2b:39:93:55:6d:7c:26:f6:6f:d9:
b3:e2:11:a0
- 确认
Issuer
字段的内容和ca-csr.json
一致; - 确认
Subject
字段的内容和kubernetes-csr.json
一致; - 确认
X509v3 Subject Alternative Name
字段的内容和kubernetes-csr.json
一致;(hosts为空的话此字段不存在) - 确认
X509v3 Key Usage、Extended Key Usage
字段的内容和ca-config.json
中kubernetes
profile 一致;
使用 cfssl-certinfo
命令
cfssl-certinfo -cert kubernetes.pem
{
"subject": {
"common_name": "kubernetes",
"country": "CN",
"organization": "k8s",
"organizational_unit": "System",
"locality": "BeiJing",
"province": "BeiJing",
"names": [
"CN",
"BeiJing",
"BeiJing",
"k8s",
"System",
"kubernetes"
]
},
"issuer": {
"common_name": "kubernetes",
"country": "CN",
"organization": "k8s",
"organizational_unit": "System",
"locality": "BeiJing",
"province": "BeiJing",
"names": [
"CN",
"BeiJing",
"BeiJing",
"k8s",
"System",
"kubernetes"
]
},
"serial_number": "43540884634737830840015465603197878486649935405",
"not_before": "2018-04-24T07:34:00Z",
"not_after": "2118-03-31T07:34:00Z",
"sigalg": "SHA256WithRSA",
"authority_key_id": "38:1B:C7:93:3F:50:F8:24:BB:57:68:48:17:45:C5:45:C5:F0:52:8F",
"subject_key_id": "1A:44:CA:AA:8A:D7:8A:4B:DA:1F:35:D4:91:2A:3E:94:86:B4:FF:27",
"pem": "-----BEGIN CERTIFICATE-----\nMIID2TCCAsGgAwIBAgIUB6Bw18t7KxMlBcZCMQutr0GiFi0wDQYJKoZIhvcNAQEL\nBQAwZTELMAkGA1UEBhMCQ04xEDAOBgNVBAgTB0JlaUppbmcxEDAOBgNVBAcTB0Jl\naUppbmcxDDAKBgNVBAoTA2s4czEPMA0GA1UECxMGU3lzdGVtMRMwEQYDVQQDEwpr\ndWJlcm5ldGVzMCAXDTE4MDQyNDA3MzQwMFoYDzIxMTgwMzMxMDczNDAwWjBlMQsw\nCQYDVQQGEwJDTjEQMA4GA1UECBMHQmVpSmluZzEQMA4GA1UEBxMHQmVpSmluZzEM\nMAoGA1UEChMDazhzMQ8wDQYDVQQLEwZTeXN0ZW0xEzARBgNVBAMTCmt1YmVybmV0\nZXMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDjbbwPeP4j7fwMCUlR\nu1nMXDZ1EJM49Gyety/9aVneBzGl+hkfcLHIh43cyEAd3Hte5K8/Cu+ZhubjKkzd\nZFE7tk7F4tiIuvKyXlhjbRwuPOMp1kCN5zp/pxggYMeRnbhPv6qDUuSmX9t7LsMC\nnku637HNPXv4WiWZbnA22jT03LuhQuLG7ZE0HOnM0kL/xq7uDlHQ4hUTXxE7kFa1\nGuFdomwN9Yfs1fE7cvRZsHFDUYXTy/cm/D5vw6DqW6cHzJxWiJO/hK87cWogQMZG\nWyQuLI10GPiI8SkCq67+CpP+jX15dbckres2JAfYhMBLNxwXXHJHpt/EBuOdEwvl\nsi4PAgMBAAGjfzB9MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcD\nAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUGkTKqorXikvaHzXU\nkSo+lIa0/ycwHwYDVR0jBBgwFoAUOBvHkz9Q+CS7V2hIF0XFRcXwUo8wDQYJKoZI\nhvcNAQELBQADggEBAHUuIJsk0fkHEaVRfw7jcWak/LXMf2KSY8JzP6GOGix40TPP\n2UKFMg6Z3lSEgqi3rad0uojH+IH1RrjXTOE9Dy9TB3qIut+xFAs0PIn/dE0WJ3vg\nyQgv5EgwgN7B7XbfccTEiqYOVPqfbM3emsiJQhU6B7NTU2/ETC6tvCdgpOe2YDsP\n0eS9tB+3s2xeLNzNcH/jItMCUpu7wJ42tLuM2AcP7PVFhkxlwTeQeiTCUla4FmCT\nJf0HpvtYAZhHWL/Kgrc5hb952jmpQhefcj4cTCRB1cCymAHbXW92FoaEN6/wRx6n\nom0mtpsPxvM9tv8bb3UvKzmTVW18JvZv2bPiEaA=\n-----END CERTIFICATE-----\n"
}
分发证书
将生成的证书和秘钥文件(后缀名为.pem
)拷贝到所有机器的 /etc/kubernetes/ssl
目录下备用;