kubernetes 提供了多种安全认证机制, 其中对于集群通讯间可采用 TLS(https) 双向认证机制,也可采用基于 Token 或用户名密码的单向 tls 认证。k8s一般在内网部署,采用私有 IP 地址进行通讯,权威CA只能签署域名证书,我们这里采用自建CA。

环境:

Master:172.20.103.1

Node:172.20.103.2

基于CA签名的双向数字证书的生成过程如下:

  1. 为kube-apiserver生成一个数字证书,并用CA证书签名。

  2. 为kube-apiserver进程配置证书相关的启动参数,包括CA证书(用于验证客户端证书的签名真伪)、自己的经过CA签名后的证书及私钥。

  3. 为每个访问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