8.1创建TLS证书和密钥
为了保证线上集群的信任和数据安全,节点之间必须要使用TLS证书来相互通信。这里我们使用自签名的证书,所以要先生成自有的TLS证书。
使用 CloudFlare
的 PKI 工具集 cfssl 来生成 Certificate Authority (CA) 和其它证书。
8.2生成的 CA 证书和秘钥文件如下:
o ca-key.pem
o ca.pem
o kubernetes-key.pem
o kubernetes.pem
o kube-proxy.pem
o kube-proxy-key.pem
o admin.pem --更正为kubectl.pem
o admin-key.pem --更正为kubectl-key.pem
o etcd-key.pem
o etcd.pem
使用证书的组件如下:
o etcd:是否启用https根据需求,内部访问可以不使用https 使用ca.pem、etcd-key.pem、etcd.pem;
o master(kube-apiserver/kube-controller-manager/kube-scheduler):使用 ca.pem、kubernetes-key.pem、kubernetes.pem;
o kubelet:使用 ca.pem;
o kube-proxy:使用 ca.pem、kube-proxy-key.pem、kube-proxy.pem;
o kubectl:使用 ca.pem、admin-key.pem、admin.pem;
o flannel:使用flannel-key.pem,flannel.pem
注意:以下操作都在 master 节点上执行,证书只需要创建一次即可,以后在向集群中添加新节点时只要将 /etc/kubernetes/ssl 目录下的证书拷贝到新节点上即可。 |
8.3安装 CFSSL
直接使用二进制源码包安装:
$ 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
[root@master01 ~]# ls /usr/local/bin/ cfssl cfssl-certinfo cfssljson
因为涉及的证书比较多,为了便于区分,这里先进行分类说明:
证书类型 | 文件名 | 用途说明 |
CA | ca* | 证书机构,颁发证书和签名 |
master | kubernetes*.pem | master三个组件使用[一般都部署在同一台机器] |
kubectl | admin*.pem | 客户端管理工具kubectl使用[kubernetes-client] |
kube-proxy | kube-proxy*.pem | kube-proxy部署在node上 |
生成出来的证书都是两个pem文件,将这里两个文件拷贝到目标机器上。
另外其他需要证书的组件都可以按照步骤生成证书即可
8.4 创建 CA (Certificate Authority)
[root@master01 ssl]# pwd /root/k8s/ssl [root@master01 ssl]# cfssl print-defaults config |sed /^$/d > config.json # 注意默认输出最后有空行,所以这里用了sed处理了一下 cp config.json ca-config.json [root@node01 ssl]# cat ca-config.json { "signing": { "default": { "expiry": "87600h" }, "profiles": { "kubernetes": { "expiry": "87600h", "usages": [ "signing", "key encipherment", "server auth" ] }, "client": { "expiry": "87600h", "usages": [ "signing", "key encipherment", "client auth" ] } } } }
字段说明
o ca-config.json:可以定义多个 profiles,分别指定不同的过期时间、使用场景等参数;后续在签名证书时使用某个 profile;
o signing:表示该证书可用于签名其它证书;生成的 ca.pem 证书中 CA=TRUE;
o server auth:表示client可以用该 CA 对server提供的证书进行验证;
o client auth:表示server可以用该CA对client提供的证书进行验证;
8.4.1创建 CA 证书签名请求:
创建 ca-csr.json
文件:
[root@master01 ssl]# cfssl print-defaults csr | sed /^$/d > csr.json cp csr.json ca-csr.json 修改之后的内容如下:根据默认输出内容修改为实际环境值 [root@master01 ssl]# cat ca-csr.json { "CN": "kubernetes", "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "L": "HangZhou", "ST": "ZJ", "O": "k8s", "OU": "System" } ] }
o “CN”:Common Name,kube-apiserver 从证书中提取该字段作为请求的用户名 (User Name);浏览器使用该字段验证网站是否合法;
o “O”:Organization,kube-apiserver 从证书中提取该字段作为请求用户所属的组 (Group);
8.4.2生成 CA 证书和私钥:
[root@master01 ssl]# cfssl gencert -initca ca-csr.json | cfssljson -bare ca 2019/03/04 23:43:49 [INFO] generating a new CA key and certificate from CSR 2019/03/04 23:43:49 [INFO] generate received request 2019/03/04 23:43:49 [INFO] received CSR 2019/03/04 23:43:49 [INFO] generating key: rsa-2048 2019/03/04 23:43:49 [INFO] encoded CSR 2019/03/04 23:43:49 [INFO] signed certificate with serial number 711935179240700127888697823340475658255165125725 [root@master01 ssl]# ls ca-config.json ca.csr ca-csr.json ca-key.pem ca.pem config.json csr.json # 加亮三个文件为新生成 |
8.4.3创建 kubernetes 证书[master使用]
创建 kubernetes 证书签名请求文件 kubernetes-csr.json
:
[root@master01 ssl]# cp ca-csr.json kubernetes-csr.json
修改内容为如下:
{ "CN": "kubernetes", "hosts": [ "127.0.0.1", "192.168.10.100", "192.168.10.101", "192.168.10.102", "10.1.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", "L": "HangZhou", "ST": "ZJ", "O": "k8s", "OU": "System " } ] } |
将 host字段里的私有ip 换成你要部署的节点ip .
127.0.0.1是master三个组件一般都部署在同一台机器,会有监听本地端口,组件内部通信采用了127.0.0.1地址
实际上只要将你的所有master节点ip写上就行了.
o 如果 hosts 字段不为空则需要指定授权使用该证书的 IP 或域名列表,由于该证书后续被 kubernetes master集群使用,所以上面分别指定了kubernetes master集群的主机 IP 和 **kubernetes 服务的服务 IP**(一般是kube-apiserver指定的service-cluster-ip-range网段的第一个IP,如我这里选择的是10.1.0.1。同时这个地址也将会是后续容器内部DNS服务器的地址
o 按照上面的配置,向集群中增加新节点后不需要重新生成证书。
下面生成 kubernetes 证书和私钥:
[root@master01 ssl]# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kubernetes-csr.json | cfssljson -bare kubernetes [root@master01 ssl]# ls -lrt kubernetes* -rw-r--r--. 1 root root 518 Mar 4 23:54 kubernetes-csr.json -rw-r--r--. 1 root root 1594 Mar 4 23:56 kubernetes.pem -rw-------. 1 root root 1675 Mar 4 23:56 kubernetes-key.pem -rw-r--r--. 1 root root 1245 Mar 4 23:56 kubernetes.csr |
8.4.4创建 admin 证书[kubernetes-client:kubectl管理工具使用]
创建 admin 证书签名请求文件 admin-csr.json
,
[root@master01 ssl]# cp kubernetes-csr.json admin-csr.json
修改后内容如下
{ "CN": "admin", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "L": "Hangzhou", "ST": "ZJ", "O": "system:masters", "OU": "System" } ] } |
o 后续 kube-apiserver 使用 RBAC 对客户端(如 kubelet、kube-proxy、Pod)请求进行授权;
o kube-apiserver 预定义了一些 RBAC 使用的 RoleBindings,如 cluster-admin 将 Group system:masters 与 Role cluster-admin 绑定,该 Role 授予了调用kube-apiserver 的所有 API的权限;
o OU 指定该证书的 Group 为 system:masters,kubelet 使用该证书访问 kube-apiserver 时 ,由于证书被 CA 签名,所以认证通过,同时由于证书用户组为经过预授权的 system:masters,所以被授予访问所有 API 的权限;
[root@master01 ssl]# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes admin-csr.json | cfssljson -bare admin [root@master01 ssl]# ls admin* admin.csr admin-csr.json admin-key.pem admin.pem |
8.4.5 创建kube-proxy证书
[root@master01 ssl]# cp admin-csr.json kube-proxy-csr.json
{ "CN": "system:kube-proxy", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "L": "HangZhou", "ST": "ZJ", "O": "k8s", "OU": "System" } ] } |
o CN 指定该证书的 User 为 system:kube-proxy;
o kube-apiserver 预定义的 RoleBinding cluster-admin 将User system:kube-proxy 与 Role system:node-proxier 绑定,该 Role 授予了调用 kube-apiserver Proxy 相关 API 的权限;
生成 kube-proxy 客户端证书和私钥:
[root@master01 ssl]# cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy [root@master01 ssl]# ls kube-proxy* kube-proxy.csr kube-proxy-csr.json kube-proxy-key.pem kube-proxy.pem |
8.4.6 创建etcd证书
本来etcd不用开启https也可以,但是如果是生产环境或者etcd的访问权限需要严格控制起来,则建议开启x509双向认证。
因为我发现如果不开启https,那么任意在一台机器上部署etcdctl都能对etcd数据库进行访问(默认没有开启用户认证模式,k8s环境中一旦开启是否会影响到集群之间的访问是个未知])。
[root@master01 ssl]# cat create-etcd.sh
#!/bin/bash cd /root/k8s/ssl cat > etcd-csr.json << EOF { "CN": "etcd", "hosts": [ "127.0.0.1", "192.168.10.100", "192.168.10.105", "192.168.10.106", "192.168.10.107" ], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "L": "Hangzhou", "ST": "ZJ", "O": "k8s", "OU": "System" } ] } EOF
# 生成证书和私钥 cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes etcd-csr.json | cfssljson -bare etcd
# check pem echo "=====确认证书内容属性!!!=====" openssl x509 -noout -text -in etcd.pem|egrep "Issuer:|Subject:|DNS|IP" |
· hosts 字段指定授权使用该证书的 etcd 节点 IP 或域名列表,这里将 etcd 集群的三个节点 IP 都列在其中;127.0.0.1可用于本地测试,192.168.10.100是VIP地址
· 除了CN名称,其他信息保持跟kubectl/master等相同
分发证书和私钥到各个etcd节点:[不要忘了ca证书]
[root@master01 ssl]# for host in etcd01 etcd02 etcd03;do scp ca.pem etcd-key.pem etcd.pem $host:/etc/kubernetes/ssl/;done
8.4.7 创建flannel证书
[root@master01 ssl]# cat create-flanneld.sh
#!/bin/bash cd /root/k8s/ssl cat > flanneld-csr.json << EOF { "CN": "flanneld", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "L": "Hangzhou", "ST": "ZJ", "O": "k8s", "OU": "System" } ] } EOF
# 生成证书和私钥 cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes flanneld-csr.json | cfssljson -bare flanneld
# check pem echo "=====确认证书内容属性!!!=====" openssl x509 -noout -text -in flanneld.pem|egrep "Issuer:|Subject:|DNS|IP" |
该证书只会被 kubectl 当做 client 证书使用,所以 hosts 字段为空;
将生成的证书和私钥分发到所有节点(master 和 worker):
8.4.8校验证书
以 kubernetes 证书为例:
# openssl x509 -noout -text -in kubernetes.pem
o 确认 Issuer 字段的内容和 ca-csr.json 一致;
o 确认 Subject 字段的内容和 kubernetes-csr.json 一致;
o 确认 X509v3 Subject Alternative Name 字段的内容和 kubernetes-csr.json 一致;
o 确认 X509v3 Key Usage、Extended Key Usage 字段的内容和 ca-config.json 中 kubernetesprofile 一致;
8.5 分发证书
生成证书的过程可以到任何一台机器上进行,生成之后作为原始文件可以留作备份,然后将这些证书分别拷贝到集群的目标机器。比如master机器就把master相关证书拷贝过去,需要安装管理工具kubectl的机器,就把admin相关证书拷贝过去。
为了统一,集群中机器存放证书的路径规定为:/etc/kubernetes/ssl
将生成的证书和秘钥文件(两个后缀名为.pem
的文件
)拷贝到 /etc/kubernetes/ssl
目录下:
还没有评论,来说两句吧...