kubernetes 提供了多种安全认证机制, 其中对于集群通讯间可采用 TLS(https) 双向认证机制,也可采用基于 Token 或用户名密码的单向 tls 认证。k8s一般在内网部署,采用私有 IP 地址进行通讯,权威CA只能签署域名证书,我们这里采用自建CA。
环境:
Master:172.20.103.1
Node:172.20.103.2
基于CA签名的双向数字证书的生成过程如下:
为kube-apiserver生成一个数字证书,并用CA证书签名。
为kube-apiserver进程配置证书相关的启动参数,包括CA证书(用于验证客户端证书的签名真伪)、自己的经过CA签名后的证书及私钥。
为每个访问K8S API Server 的客户端(kube-controller-manager、kube-scheduler、kubelet、kube-proxy及调用API Server的客户端程序kubectl等)进程都可以生成自己的数字证书,也都用CA证书签名,在相关程序的启动参数里增加CA证书、自己的证书等相关参数。
设置kube-apiserver的CA证书相关的文件和启动参数
使用OpenSSL工具在Master服务器上创建CA证书和私钥相关的文件:
yum -y install openssl
cd /var/run/kubernetes/ (证书默认存放目录)
openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -subj "/CN=k8s-master" -days 5000 -out ca.crt
openssl genrsa -out server.key 2048
注意:在生成ca.crt时,-subj参数中“”/CN“”的值为Master主机名。
准备master_ssl.cnf文件,该文件用于x509 v3版本的证书。在该文件中主要需要设置Master服务器的hostname(k8s-master)、IP地址(172.20.103.1)、以及K8S Master Service 的虚拟服务名称(kubernetes.default 等)和该虚拟服务的ClusterIP地址(169.169.0.1)。
master_ssl.cnf 文件的配置如下:
[req]
req_extensions = v3_req
distinguished_name = req_distinguished_name
[req_distinguished_name]
[ v3_req ]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = kubernetes
DNS.2 = kubernetes.default
DNS.3 = kubernetes.default.svc
DNS.4 = kubernetes.default.svc.cluster.local
DNS.5 = k8s-master
IP.1 = 169.169.0.1
IP.2 = 172.20.103.1
基于master_ssl.cnf 创建server.csr 和 server.crt 文件。在生成server.csr 时,-subj参数中“”/CN“”的值需为Master的主机名:
openssl req -new -key server.key -subj "/CN=k8s-master" -config master_ssl.cnf -out server.csr
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 5000 -extensions v3_req -extfile master_ssl.cnf -out server.crt
在全部执行完后会生成6个文件:ca.crt ca.key ca.srl master_ssl.cnf server.crt server.csr server.key
然后设置kube-apiserver的三个启动参数"--client-ca-file","--tls-private-key-file","--tls-cert-file",分别代表CA根证书文件、服务端私钥文件、服务端证书文件:
--client-ca-file=/var/run/kubernetes/ca.crt
--tls-private-key-file=/var/run/kubernetes/server.key
--tls-cert-file=/var/run/kubernetes/server.crt
同时,可以关闭非安全端口(设置--insecure-port=0),设置安全端口为6443(默认值):
--insecure-port=0 --secure-port=6443
最后重启kube-apiserver服务
systemctl restart kube-apiserver
设置kube-controller-manager的客户端证书、私钥和启动参数
openssl genrsa -out cs_client.key 2048
openssl req -new -key cs_client.key -subj "/CN=k8s-master" -out cs_client.csr
openssl x509 -req -in cs_client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out cs_client.crt -days 5000
其中,在生成cs_client.crt时,-CA参数和-CAkey参数使用的是API Server的ca.crt和ca.key文件。
接下来创建/etc/kubernetes/kubeconfig 文件(kube-controller-manager与kube-scheduler共用),配置客户端证书等相关参数,内容如下:
vim /etc/kubernetes/kubeconfig
apiVersion: v1
kind: Config
users:
- name: controllermanager
user:
client-certificate: /var/run/kubernetes/cs_client.crt
client-key: /var/run/kubernetes/cs_client.key
clusters:
- name: local
cluster:
certificate-authority: /var/run/kubernetes/ca.crt
server: https://172.20.103.1:6443
contexts:
- context:
cluster: local
user: controllermanager
name: my-context
current-context: my-context
设置kube-controller-manager服务的启动参数:
--kubeconfig=/etc/kubernetes/kubeconfig
重启kube-controller-manager服务
systemctl restart kube-controller-manager
设置kube-scheduler服务的启动参数:
--kubeconfig=/etc/kubernetes/kubeconfig
重启kube-scheduler服务
systemctl restart kube-scheduler
设置每个Node上kubelet的客户端证书、私钥和启动参数
复制kube-apiserver的ca.crt和ca.key文件到node上,在生成kubelet_client.crt时-CA参数和- CAkey参数使用的是API Server的ca.crt和ca.key文件;生成kubelet_client.csr时,将-subj参数中的“”/CN“”设置为本机Node的IP地址。
在node上创建存放证书的目录:
mkdir /etc/kubernetes/ssl_keys
把master上的ca.crt和ca.key文件复制到node上:
scp ca.crt ca.key root@172.20.103.2:/etc/kubernetes/ssl_keys/
openssl genrsa -out kubelet_client.key 2048
openssl req -new -key kubelet_client.key -subj "/CN=172.20.103.2" -out kubelet_client.csr
openssl x509 -req -in kubelet_client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out kubelet_client.crt -days 5000
接下来创建/etc/kubernetes/kubeconfig文件(kubelet和kube-proxy组件共用),配置客户端证书等相关参数,内容如下:
apiVersion: v1
kind: Config
users:
- name: kubelet
user:
client-certificate: /etc/kubernetes/ssl_keys/kubelet_client.crt
client-key: /etc/kubernetes/ssl_keys/kubelet_client.key
clusters:
- name: local
cluster:
certificate-authority: /etc/kubernetes/ssl_keys/ca.crt
server: https://172.20.103.2:6443
contexts:
- context:
cluster: local
user: kubelet
name: my-context
current-context: my-context
设置kubelet服务的启动参数:
--kubeconfig=/etc/kubernetes/kubeconfig
重启kubelet服务
systemctl restart kubelet
设置kube-proxy服务的启动参数:
--kubeconfig=/etc/kubernetes/kubeconfig
重启kube-proxy服务:
systemctl restart kube-proxy
至此,一个基于CA的双向数字证书认证的K8S集群环境就搭建完成了。
设置kubectl客户端使用安全方式访问API Server
在使用kubectl对K8S集群进行操作时,默认使用非安全端口8080对API Server进行访问,也可以设置为安全访问API Server的模式,需要设置3个证书相关的参数:
“”--certificate-authority“”,“”--client-certificate“”,“”--client-key“”,分别表示用于CA授权的证书,客户端证书和客户端秘钥。
--certificate-authority:使用为kube-apiserver生成的ca.crt文件。
--client-certificate:使用为kube-controller-manager生成的cs_client.crt文件。
--client-key:使用为kube-controller-manager生成的cs_client.key文件
同时,指定API Server的URL地址为HTTPS安全地址(例如:https://k8s-master:443),最后输入需要执行的子命令,即可对API Server进行安全访问了:
kubectl --server=https://172.20.103.1:6443 --certificate-authority=/var/run/kubernetes/ca.crt --client-certificate=/var/run/kubernetes/cs_client.crt --client-key=/var/run/kubernetes/cs_client.key get nodes