一 证书分类
服务器证书:
server cert :用户客户端验证服务端的身份。
客户端证书:
client cert:用户服务端验证客户端的身份。
对等证书:
peer cert: 用户成员之间的身份验证,例如etcd,(该证书,它即是server cert,又是client cert)。
二 k8s集群证书的分类
ETCD:
需要server cert标识自己,也需要client cert与其它etcd集群通讯,因此需要一个peer cert(对等证书)。
master节点:
需要标识api-server的server cert,也需要client cert连接到etcd集群,还需要一个对等证书peer跟client交互。
kubelet:
需要标识服务kubelet的server cert,也需要client cert 去请求api-server,因此还需要一个对等证书peer cert。
kubelet,kube-proxy,calico:
需要client cert
三 生成的 CA 证书和秘钥文件
目录位置:/etc/kubernetes/ssl
使用证书的组件
CA 证书说明讲解
可信任证书颁发机构
例如:我们的身份证,它为什么大家都认可它信任它,因为它是*局颁发的所有被信任,这里的CA机构就相当于*局。
CA证书结构:
ca-config.json (CA配置文件)
{
"signing": { #表示该证书可用于签名其它证书;生成的ca.pem证书中CA=TRUE。
"default": {
"expiry": "8760h" #默认证书过期时间(小时,用户可自己调大过期时间)。
},
"profiles": {
"kubernetes": {
"usages": [
"signing",
"key encipherment",
"server auth", #表示client可以用该CA对server提供的证书进行验证。
"client auth" #表示server可以用该CA对client提供的证书进行验证。
],
"expiry": "8760h" #默认证书过期时间(小时,用户可自己调大过期时间)。
}
}
}
}
ca-csr.json(证书签名请求)
{
"CN": "kubernetes", #CN-Common Name:kube-apiserver从证书中提取该字段作为请求的用户名 (User Name);浏览器使用该字段验证网站是否合法
"key": {
"algo": "rsa", #加密算法
"size": 2048 #加密的位数,您可以不改也可以加大
},
"names": [
{
"C": "CN", #国家
"ST": "BeiJing", #城市
"L": "BeiJing", #组织
"O": "k8s", #O-Organization:kube-apiserver从证书中提取该字段作为请求用户所属的组 (Group);
"OU": "System" #组织单元
}
]
}
四 证书生成操作
4.1 证书颁发工具
安装cfssl
这里我们选择CloudFlare的PKI工具集cfssl ,它比OpenSSL要简单
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
export PATH=/usr/local/bin:$PATH
4.2 创建CA(Certificate Authority)
4.2.1 创建ca配置文件:(CA证书的说明可参考上面CA证书讲解部分)
mkdir /root/ssl
cd /root/ssl
cfssl print-defaults config > config.json
cfssl print-defaults csr > csr.json
# 根据config.json文件的格式创建如下的ca-config.json文件
cat > ca-config.json <<EOF
{
"signing": {
"default": {
"expiry": "87600h"
},
"profiles": {
"kubernetes": {
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
],
"expiry": "87600h"
}
}
}
}
4.2.2 创建CA证书签名请求文件
cat > ca-csr.json <<EOF
{
"CN": "kubernetes",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
],
"ca": {
"expiry": "87600h"
}
}
EOF
4.2.3 生成CA证书文和私钥
$cfssl gencert -initca ca-csr.json | cfssljson -bare ca
$ll
total 20
drwxr-xr-x 2 root root 93 Aug 3 10:24 ./
drwxr-xr-x 5 root root 60 Aug 3 09:11 ../
-rw-r--r-- 1 root root 292 Aug 3 10:23 ca-config.json
-rw-r--r-- 1 root root 1001 Aug 3 10:24 ca.csr #证书签名请求文件
-rw-r--r-- 1 root root 253 Aug 3 10:23 ca-csr.json
-rw------- 1 root root 1679 Aug 3 10:24 ca-key.pem #证书私钥
-rw-r--r-- 1 root root 1359 Aug 3 10:24 ca.pem #证书
4.3 创建kubernetes证书
4.3.1 创建kubernetes证书签名请求文件kubernetes-csr.json
注意:
. 如果 hosts 字段不为空则需要指定授权使用该证书的 IP 或域名列表,由于该证书后续被 etcd 集群和 kubernetes master 集群使用,所以上面分别指定了 etcd 集群kubernetes master 集群的主机 IP 和 kubernetes 服务的服务 IP(一般是 kube-apiserver 指定的 service-cluster-ip-range 网段的第一个IP,如 10.254.0.1)。
. 以下物理节点的IP也可以更换为主机名
cat > kubernetes-csr.json <<EOF
{
"CN": "kubernetes",
"hosts": [
"127.0.0.1",
"172.20.0.112",
"172.20.0.113",
"172.20.0.114",
"172.20.0.115",
"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"
}
]
}
EOF
4.3.2 生成kubernetes证书和秘钥
$ cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kubernetes-csr.json | cfssljson -bare kubernetes
$ ll kubernetes*
-rw-r--r-- 1 root root 1269 Aug 3 10:36 kubernetes.csr #证书签名请求文件
-rw-r--r-- 1 root root 578 Aug 3 10:36 kubernetes-csr.json
-rw------- 1 root root 1679 Aug 3 10:36 kubernetes-key.pem #证书私钥
-rw-r--r-- 1 root root 1635 Aug 3 10:36 kubernetes.pem #证书
4.4 创建Admin证书
4.4.1 创建admin证书签名请求文件admin-csr.json
注意:
. kube-apiserver 使用 RBAC 对客户端(如 kubelet、kube-proxy、Pod)请求进行授权;
. kube-apiserver 预定义了一些 RBAC 使用的 RoleBindings,如 cluster-admin 将 Group system:masters 与 Role cluster-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。
. 安装完集群后您可以查看该admin用户的集群权限,以下命令可查看,查看到 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
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: 2017-04-11T11:20:42Z
labels:
kubernetes.io/bootstrapping: rbac-defaults
name: cluster-admin
resourceVersion: "52"
selfLink: /apis/rbac.authorization.k8s.io/v1/clusterrolebindings/cluster-admin
uid: e61b97b2-1ea8-11e7-8cd7-f4e9d49f8ed0
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:masters
4.4.1 创建admin证书签名请求文件admin-csr.json
cat > admin-csr.json <<EOF
{
"CN": "admin",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "system:masters",
"OU": "System"
}
]
}
EOF
4.4.2 生成admin证书和私钥:
$ cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes admin-csr.json | cfssljson -bare admin
$ ll admin*
-rw-r--r-- 1 root root 1009 Aug 3 10:48 admin.csr
-rw-r--r-- 1 root root 229 Aug 3 10:45 admin-csr.json
-rw------- 1 root root 1675 Aug 3 10:48 admin-key.pem
-rw-r--r-- 1 root root 1399 Aug 3 10:48 admin.pem
4.5 创建kube-proxy证书
4.5.1 创建kube-proxy证书签名请求文件kube-proxy-csr.json
注意:
. CN 指定该证书的 User 为 system:kube-proxy;
. kube-apiserver 预定义的 RoleBinding system:node-proxier 将User system:kube-proxy 与 Role system:node-proxier 绑定,该 Role 授予了调用 kube-apiserver Proxy 相关 API 的权限;
cat > kube-proxy-csr.json << EOF
{
"CN": "system:kube-proxy",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
EOF
4.5.2 生成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
$ ll kube-proxy*
-rw-r--r-- 1 root root 1009 Aug 3 10:55 kube-proxy.csr
-rw-r--r-- 1 root root 230 Aug 3 10:54 kube-proxy-csr.json
-rw------- 1 root root 1679 Aug 3 10:55 kube-proxy-key.pem
-rw-r--r-- 1 root root 1403 Aug 3 10:55 kube-proxy.pem
五 校验证书
如 kubernets证书
5.1 使用OpenSSL命令校验:
openssl x509 -noout -text -in kubernetes.pem
检查字段:
. 确认 Issuer 字段的内容和 ca-csr.json 一致;
. 确认 Subject 字段的内容和 kubernetes-csr.json 一致;
. 确认 X509v3 Subject Alternative Name 字段的内容和 kubernetes-csr.json 一致;
. 确认 X509v3 Key Usage、Extended Key Usage 字段的内容和 ca-config.json 中 kubernetes profile 一致;
$ openssl x509 -noout -text -in kubernetes.pem
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
65:d7:41:64:d0:f7:62:78:3a:da:e3:1c:72:25:16:84:b7:bb:9f:8b
Signature Algorithm: sha256WithRSAEncryption
Issuer: C = CN, ST = BeiJing, L = BeiJing, O = k8s, OU = System, CN = kubernetes
Validity
Not Before: Aug 3 02:31:00 2021 GMT
Not After : Aug 1 02:31:00 2031 GMT
Subject: C = CN, ST = BeiJing, L = BeiJing, O = k8s, OU = System, CN = kubernetes
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
00:d2:d8:2c:15:96:6d:97:03:1c:26:1a:17:06:38:
d5:7f:e1:4f:12:3a:f6:52:bd:4e:ae:0a:12:7a:ac:
c9:8a:23:38:2b:5c:3f:46:47:9f:95:15:7a:4d:69:
f3:0a:87:74:5c:28:2e:e5:6c:fe:55:79:51:d1:5a:
9e:ef:fd:a3:65:67:cf:66:f3:fb:d6:4a:29:98:11:
a8:8a:e7:9a:8f:05:bd:4c:23:e9:52:93:43:5a:09:
fc:39:48:ac:f9:04:15:a1:92:1e:af:4d:26:99:7b:
d7:ee:3c:b0:71:bc:a2:95:da:d4:78:dc:44:52:ad:
f3:47:a2:d2:4d:57:25:e5:56:59:ed:c5:dd:2c:5b:
d6:66:f1:7e:0b:4d:61:03:6a:8b:a0:df:54:71:f3:
48:c8:51:02:fc:4b:a2:4d:71:8c:41:af:0b:b7:f3:
61:09:a9:c4:49:7c:e0:68:d6:a6:ea:e3:bd:27:95:
2f:f7:a6:59:56:28:ea:b0:e2:b8:3e:31:74:97:ee:
04:08:70:ae:00:4f:21:a9:37:77:dc:fb:76:c6:78:
c5:fa:a3:46:20:b4:f6:5f:79:d1:16:fc:5f:64:c7:
57:68:34:49:3b:99:40:91:ce:2c:2d:de:fe:fc:fa:
83:5e:5e:73:6c:f1:46:6a:8f:64:f1:b8:6f:92:1b:
66:89
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:
6F:FE:15:72:91:75:2F:F5:E5:50:A9:26:8F:76:C7:8F:26:BD:55:F0
X509v3 Authority Key Identifier:
keyid:3F:8C:95:EE:E9:3A:B1:84:FC:0D:BA:1B:F1:A8:AA:FD:B1:C4:C0:E2
X509v3 Subject Alternative Name:
DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster, DNS:kubernetes.default.svc.cluster.local, IP Address:127.0.0.1, IP Address:172.20.0.112, IP Address:172.20.0.113, IP Address:172.20.0.114, IP Address:172.20.0.115, IP Address:10.254.0.1
Signature Algorithm: sha256WithRSAEncryption
40:6e:12:57:13:87:17:47:6c:5a:6a:bb:9f:8c:06:04:2c:7e:
71:5c:37:f7:6b:87:9c:23:ab:bf:54:df:53:be:f7:a1:3b:46:
b2:87:77:0a:fd:99:ef:7d:44:33:75:b1:bf:fc:ca:1a:20:8a:
c2:d7:e8:bc:e1:ea:7e:fe:7f:bb:58:68:03:a1:5d:9b:62:7e:
9a:48:27:36:42:be:14:41:9f:1a:41:53:31:0f:cf:a7:a8:70:
08:45:99:b9:09:82:fd:00:02:32:52:f5:62:c2:92:96:35:51:
25:ca:cc:08:d5:c4:e8:d2:97:50:93:9a:48:5e:6b:f9:d8:91:
58:4c:fb:24:56:aa:37:1b:78:94:ca:5f:a0:7c:84:91:99:a7:
8e:e5:37:83:50:b8:31:23:2d:bb:74:48:57:aa:5c:b3:5f:37:
15:b4:7d:5d:45:44:63:f5:c0:4b:83:a1:de:4b:a2:12:fe:2b:
e1:5c:58:6a:a6:74:b9:72:b7:3e:ff:89:4d:7c:18:d1:b5:6d:
ea:92:f3:67:53:ad:93:78:72:ab:9f:d8:89:e1:62:ce:d7:56:
57:cc:0b:f6:12:11:ab:17:ff:2e:76:19:c4:fe:36:e0:fe:74:
cc:f8:9f:ee:cd:27:00:21:fc:61:79:48:e5:27:74:bb:bd:e4:
26:8c:8d:50
5.2 使用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": "581408424675478050081912100441044253482994605963",
"sans": [
"kubernetes",
"kubernetes.default",
"kubernetes.default.svc",
"kubernetes.default.svc.cluster",
"kubernetes.default.svc.cluster.local",
"127.0.0.1",
"172.20.0.112",
"172.20.0.113",
"172.20.0.114",
"172.20.0.115",
"10.254.0.1"
],
"not_before": "2021-08-03T02:31:00Z",
"not_after": "2031-08-01T02:31:00Z",
"sigalg": "SHA256WithRSA",
"authority_key_id": "3F:8C:95:EE:E9:3A:B1:84:FC:D:BA:1B:F1:A8:AA:FD:B1:C4:C0:E2",
"subject_key_id": "6F:FE:15:72:91:75:2F:F5:E5:50:A9:26:8F:76:C7:8F:26:BD:55:F0",
"pem": "-----BEGIN CERTIFICATE-----\nMIIEizCCA3OgAwIBAgIUZddBZND3Yng62uMcciUWhLe7n4swDQYJKoZIhvcNAQEL\nBQAwZTELMAkGA1UEBhMCQ04xEDAOBgNVBAgTB0JlaUppbmcxEDAOBgNVBAcTB0Jl\naUppbmcxDDAKBgNVBAoTA2s4czEPMA0GA1UECxMGU3lzdGVtMRMwEQYDVQQDEwpr\ndWJlcm5ldGVzMB4XDTIxMDgwMzAyMzEwMFoXDTMxMDgwMTAyMzEwMFowZTELMAkG\nA1UEBhMCQ04xEDAOBgNVBAgTB0JlaUppbmcxEDAOBgNVBAcTB0JlaUppbmcxDDAK\nBgNVBAoTA2s4czEPMA0GA1UECxMGU3lzdGVtMRMwEQYDVQQDEwprdWJlcm5ldGVz\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0tgsFZZtlwMcJhoXBjjV\nf+FPEjr2Ur1OrgoSeqzJiiM4K1w/RkeflRV6TWnzCod0XCgu5Wz+VXlR0Vqe7/2j\nZWfPZvP71kopmBGoiueajwW9TCPpUpNDWgn8OUis+QQVoZIer00mmXvX7jywcbyi\nldrUeNxEUq3zR6LSTVcl5VZZ7cXdLFvWZvF+C01hA2qLoN9UcfNIyFEC/EuiTXGM\nQa8Lt/NhCanESXzgaNam6uO9J5Uv96ZZVijqsOK4PjF0l+4ECHCuAE8hqTd33Pt2\nxnjF+qNGILT2X3nRFvxfZMdXaDRJO5lAkc4sLd7+/PqDXl5zbPFGao9k8bhvkhtm\niQIDAQABo4IBMTCCAS0wDgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUF\nBwMBBggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBRv/hVykXUv9eVQ\nqSaPdsePJr1V8DAfBgNVHSMEGDAWgBQ/jJXu6TqxhPwNuhvxqKr9scTA4jCBrQYD\nVR0RBIGlMIGiggprdWJlcm5ldGVzghJrdWJlcm5ldGVzLmRlZmF1bHSCFmt1YmVy\nbmV0ZXMuZGVmYXVsdC5zdmOCHmt1YmVybmV0ZXMuZGVmYXVsdC5zdmMuY2x1c3Rl\ncoIka3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FshwR/AAABhwSs\nFABwhwSsFABxhwSsFAByhwSsFABzhwQK/gABMA0GCSqGSIb3DQEBCwUAA4IBAQBA\nbhJXE4cXR2xaarufjAYELH5xXDf3a4ecI6u/VN9TvvehO0ayh3cK/ZnvfUQzdbG/\n/MoaIIrC1+i84ep+/n+7WGgDoV2bYn6aSCc2Qr4UQZ8aQVMxD8+nqHAIRZm5CYL9\nAAIyUvViwpKWNVElyswI1cTo0pdQk5pIXmv52JFYTPskVqo3G3iUyl+gfISRmaeO\n5TeDULgxIy27dEhXqlyzXzcVtH1dRURj9cBLg6HeS6IS/ivhXFhqpnS5crc+/4lN\nfBjRtW3qkvNnU62TeHKrn9iJ4WLO11ZXzAv2EhGrF/8udhnE/jbg/nTM+J/uzScA\nIfxheUjlJ3S7veQmjI1Q\n-----END CERTIFICATE-----\n"
}
六 分发证书
将生成的证书和秘钥文件(后缀名为.pem)拷贝到所有机器的 /etc/kubernetes/ssl 目录下
for n in {cat host.txt}; do ssh root@$n ; mkdir -p /etc/kubernetes/ssl;exit;done
for n in {cat hosts.txt}; do scp -r *.pem root@/etc/kubernetes/ssl/;done
本文有参考云原生社区文章
个人理解,如有错误麻烦指正^_^