在前文介绍的k8s master高可用实践方案中,须要对kube-apiserver的证书进行更新,加入VIP和从节点的IP,而后从新下发证书。回顾K8S集群整个搭建过程当中,最容易让人懵圈的也就是配置证书环节,所以本文对K8S集群所用到的证书进行梳理一下。node
ca.pem 根证书公钥文件
ca-key.pem 根证书私钥文件
ca.csr 证书签名请求,用于交叉签名或从新签名
ca-config.json 使用cfssl工具生成其余类型证书须要引用的配置文件
ca.pem用于签发后续其余的证书文件,所以ca.pem文件须要分发到集群中的每台服务器上去。docker
证书生成命令,默认生成的证书有效期5年json
# echo '{"CN":"CA","key":{"algo":"rsa","size":2048}}' | cfssl gencert -initca - | cfssljson -bare ca - # echo '{"signing":{"default":{"expiry":"43800h","usages":["signing","key encipherment","server auth","client auth"]}}}' > ca-config.json
证书生成命令,默认生成的证书有效期5年bootstrap
# cfssl gencert -ca=/etc/ssl/etcd/ca.pem \ -ca-key=/etc/ssl/etcd/ca-key.pem \ -config=/etc/ssl/etcd/ca-config.json \ -profile=kubernetes flanneld-csr.json | cfssljson -bare flanneld
这里生成证书须要flanneld-csr.json文件api
# cat flanneld-csr.json { "CN": "flanneld", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "FuZhou", "L": "FuZhou", "O": "k8s", "OU": "System" } ] }
flannel启动文件配置服务器
# cat /usr/lib/systemd/system/flanneld.service [Unit] Description=Flanneld overlay address etcd agent After=network.target After=network-online.target Wants=network-online.target After=etcd.service Before=docker.service [Service] Type=notify ExecStart=/usr/local/bin/flanneld \ -etcd-cafile=/etc/ssl/etcd/ca.pem \ -etcd-certfile=/etc/ssl/flanneld/flanneld.pem \ -etcd-keyfile=/etc/ssl/flanneld/flanneld-key.pem \ -etcd-endpoints=https://192.168.115.5,https://192.168.115.6:2379,https://192.168.115.7:2379 \ -etcd-prefix=/kubernetes/network ExecStartPost=/usr/local/bin/mk-docker-opts.sh -k DOCKER_NETWORK_OPTIONS -d /run/flannel/docker Restart=on-failure [Install] WantedBy=multi-user.target RequiredBy=docker.service
一、服务端证书app
server.pem etcd服务端证书公钥文件
server-key.pem etcd服务端证书私钥文件
server.csr 证书签名请求ide
证书生成命令,默认生成的证书有效期5年工具
# export ADDRESS=192.168.115.5,192.168.115.6,192.168.115.7,vm1,vm2,vm3 # export NAME=server # echo '{"CN":"'$NAME'","hosts":[""],"key":{"algo":"rsa","size":2048}}' | \ cfssl gencert -config=ca-config.json -ca=ca.pem -ca-key=ca-key.pem \ -hostname="$ADDRESS" - | cfssljson -bare $NAME
server.pem、server-key.pem文件用来etcd集群间通讯加解密,所以全部的etcd服务器都须要有这两个文件测试
# tail -15 /usr/lib/systemd/system/etcd.service --initial-cluster-token=etcd-cluster-token \ --initial-cluster-state=new \ --cert-file=/etc/ssl/etcd/server.pem \ --key-file=/etc/ssl/etcd/server-key.pem \ --peer-cert-file=/etc/ssl/etcd/server.pem \ --peer-key-file=/etc/ssl/etcd/server-key.pem \ --trusted-ca-file=/etc/ssl/etcd/ca.pem \ --peer-trusted-ca-file=/etc/ssl/etcd/ca.pem \ --peer-client-cert-auth=true \ --client-cert-auth=true" Restart=on-failure LimitNOFILE=65536 [Install] WantedBy=multi-user.target
二、客户端证书
client.pem etcd客户端证书公钥文件
client-key.pem etcd客户端证书私钥文件
client.csr 证书签名请求
证书生成命令,默认生成的证书有效期5年
# export ADDRESS= # export NAME=client # echo '{"CN":"'$NAME'","hosts":[""],"key":{"algo":"rsa","size":2048}}' | \ cfssl gencert -config=ca-config.json -ca=ca.pem -ca-key=ca-key.pem \ -hostname="$ADDRESS" - | cfssljson -bare $NAME
client.pem、client-key.pem文件给etcdctl客户端用来和etcd服务器进行通讯,可根据实际须要进行配置。
# export ETCDCTL_API=3 # etcdctl --write-out=table \ --cert=/etc/ssl/etcd/client.pem \ --key=/etc/ssl/etcd/client-key.pem \ --cacert=/etc/ssl/etcd/ca.pem \ --endpoints=https://192.168.115.5:2379,https://192.168.115.6:2379,https://192.168.115.7:2379 \ member list
Kube-apiserver证书
Kubernetes.pem kube-apiserver证书公钥文件
Kubernetes-key.pem kube-apiserver证书私钥文件
kuberentes.csr kube-apiserver证书签名请求
证书生成命令,默认生成的证书有效期5年
# cfssl gencert -ca=/etc/ssl/etcd/ca.pem \ -ca-key=/etc/ssl/etcd/ca-key.pem \ -config=/etc/ssl/etcd/ca-config.json \ -profile=kubernetes k8s-csr.json | cfssljson -bare kubernetes
这里生成证书须要k8s-csr.json文件,其中定义了master节点的IP列表等信息
# cat k8s-csr.json { "CN": "kubernetes", "hosts": [ "127.0.0.1", "192.168.115.4", "192.168.115.5", "192.168.115.6", "192.168.115.7", "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": "FuZhou", "L": "FuZhou", "O": "k8s", "OU": "System" } ] }
一、kube-proxy证书
Kube-proxy.pem kube-proxy证书公钥文件
Kube-proxy-key.pem kube-proxy证书私钥文件
Kube-proxy.csr kube-proxy证书签名请求
证书生成命令,默认生成的证书有效期5年
# cfssl gencert -ca=/etc/ssl/etcd/ca.pem \ -ca-key=/etc/ssl/etcd/ca-key.pem \ -config=/etc/ssl/etcd/ca-config.json \ -profile=kubernetes kube-proxy-csr.json | cfssljson -bare kube-proxy
这里生成证书须要kube-proxy-csr.json文件
# cat kube-proxy-csr.json { "CN": "system:kube-proxy", "hosts": [], "key": { "algo": "rsa", "size": 2048 }, "names": [ { "C": "CN", "ST": "FuZhou", "L": "FuZhou", "O": "k8s", "OU": "System" } ] }
二、Kubelet证书
Kubelet-client.crt: kubectl客户端证书公钥文件
Kubelet-client.key: kubectl客户端私钥文件
Kubelet.crt:kubelet服务端证书公钥文件
Kubelet.key:kubelet服务端证书私钥文件kubelet-client.crt 文件在 kubelet 完成 TLS bootstrapping 后生成,有效期为 1 年。此证书是由 controller manager 签署的,此后 kubelet 将会加载该证书,用于与 apiserver 创建 TLS 通信,同时使用该证书的 CN 字段做为用户名,O 字段做为用户组向 apiserver 发起其余请求。
kubelet.crt 文件在 kubelet 完成 TLS bootstrapping 后且没有配置 --feature-gates=RotateKubeletServerCertificate=true 时才会生成;该文件为一个独立于 apiserver CA 的自签 CA 证书,有效期为 1 年;被用做 kubelet 10250 api 端口
关于kubelet首次启动 TLS bootstrapping的介绍(先有鸡仍是先有蛋问题的解决方案)可参考文档,https://mritd.me/2018/01/07/kubernetes-tls-bootstrapping-note/
默认签署kubectl客户端和kubelet服务端证书只有 1 年有效期,若是想要调整证书有效期能够经过设置 kube-controller-manager 的 --experimental-cluster-signing-duration 参数实现,该参数默认值为 8760h0m0s。下面咱们来介绍一下如何实现证书到期的自动续签。这个问题若是处理不当,证书过时以后会出现全部的node节点链接不上的状况。
一、kcm服务,这里为了方便测试,过时时间修改成30分钟
# egrep 'feature|experimental' /usr/lib/systemd/system/kube-controller-manager.service --feature-gates=RotateKubeletClientCertificate=true,RotateKubeletServerCertificate=true \ --experimental-cluster-signing-duration=30m0s \ # systemctl daemon-reload # systemctl restart kube-controller-manager
二、kubelet服务
配置完成删掉Kubelet-client.crt、Kubelet-client.key、Kubelet.crt、Kubelet.key四个文件后重启kubelet服务。
# egrep 'feature|rotate' /usr/lib/systemd/system/kubelet.service --feature-gates=RotateKubeletClientCertificate=true,RotateKubeletServerCertificate=true \ --rotate-certificates=true \ # systemctl daemon-reload # systemctl restart kubelet
三、手工签发证书
# kubectl create clusterrolebinding kubelet-clinet \ --clusterrole=system:node \ --user=system:anonymous
若是缺乏对system:anonymous用户的受权,kubelet启动的时候会报错以下:
error: failed to run Kubelet: cannot create certificate signing request: certificatesigningrequests.certificates.k8s.io is forbidden: User "system:anonymous" cannot create certificatesigningrequests.certificates.k8s.io at the cluster scope
# kubectl get csr # kubectl certificate approve csr-fn946 # kubectl certificate approve csr-kwvg9
node节点将会从新生成kubectl客户端和kubelet服务端证书
四、配置自动签发证书,在大规模集群下,这个配置是必须的
# cat rbac.yaml apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: annotations: rbac.authorization.kubernetes.io/autoupdate: "true" labels: kubernetes.io/bootstrapping: rbac-defaults name: system:certificates.k8s.io:certificatesigningrequests:selfnodeserver rules: - apiGroups: - certificates.k8s.io resources: - certificatesigningrequests/selfnodeserver verbs: - create --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: kubeadm:node-autoapprove-certificate-server roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: system:certificates.k8s.io:certificatesigningrequests:selfnodeserver subjects: - apiGroup: rbac.authorization.k8s.io kind: Group name: system:nodes # kubectl create -f rbac.yaml
# kubectl create clusterrolebinding node-client-auto-approve-csr \ --clusterrole=system:certificates.k8s.io:certificatesigningrequests:nodeclient \ --group=system:bootstrappers # kubectl create clusterrolebinding node-client-auto-renew-crt \ --clusterrole=system:certificates.k8s.io:certificatesigningrequests:selfnodeclient \ --group=system:nodes # kubectl create clusterrolebinding node-server-auto-renew-crt \ --clusterrole=system:certificates.k8s.io:certificatesigningrequests:selfnodeserver \ --group=system:nodes
这里须要注意的是删除掉Kubelet-client.crt、Kubelet-client.key两个文件以后,启动kubelet服务,首先会生成一个Kubelet-client.key文件,咱们须要对这个证书的crs请求进行approve,不然node节点没法正常启动。其次,若是kubelet.kubeconfig文件中配置的client-certificate、client-key目录位置和kubelet的启动参数--cert-dir不一致,则kubelet.kubeconfig文件中的配置文件会被自动更新。