k8s实践(8)--ssl安全认证配置

2022-04-14 16:20:45 浏览数 (1)

一.基于CA签名的双向数字证书认证方式

在一个安全的内网环境中, Kubernetes的各个组件与Master之间可以通过apiserver的非安全端口http://apiserver:8080进行访问。但如果apiserver需要对外提供服务,或者集群中的某些容器也需要访问apiserver以获取集群中的某些信息,则更安全的做法是启用HTTPS安全机制。Kubernetes提供了基于CA签名的双向数字证书认证方式和简单的基于HTTP BASE或TOKEN的认证方式,其中CA证书方式的安全性最高。本节先介绍以CA证书的方式配置Kubernetes集群,要求Master上的kube-apiserver.kube-controller-manager. kube-scheduler进程及各Node上的kubelet, kube-proxy进程进行CA签名双向数字证书安全设置

k8s中哪些组件需要进行tls证书认证,哪些不需要?

kube-scheduler、kube-controller-manager 一般和 kube-apiserver 部署在同一台机器上,它们使用非安全端口和 kube-apiserver通信,非安全端口默认为http的8080,可以使用--insecure-port指定,监听非安全端口的地址默认为127.0.0.1,可以使用--insecure-bind-address指定;

kubelet、kube-proxy、kubectl 部署在其它 Node 节点上,如果通过安全端口访问 kube-apiserver,则必须先通过 TLS 证书认证,再通过 RBAC 授权。安全端口默认为https的6443,可以使用--secure-port指定,监听安全端口的地址默认为0.0.0.0(监听所有接口),可以使用--bind-address指定。

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

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

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

(3)为每个访问Kubernetes API Server的客户端(如kube-controller-manager.kube-scheduler,kubelet, kube-proxy及调用API Server的客户端程序kubectl等)进程生成自己的数字证书,也都用CA证书进行签名,在相关程序的启动参数里增加CA证书、自己的证书等相关参数。1)设置kube-apiserver的CA证书相关的文件和启动参数

生成如下证书:

根证书公钥与私钥:ca-public.pem 与ca-private.pem

API Server公钥与私钥:apiserver-public.pem与apiserver-private.pem

从节点公钥与私钥:kubelet-publi.pem与kubelet-private.pem

集群管理员公钥与私钥:admin.pem与admin-key.pem

二、根证书生成

我们需要一个证书来为自己颁发的证书签名,这个证书可从其他CA获取,或者是自签名的根证书。这里我们生成一个自签名的根证书。

1、CA根证书 ca-private.pem

生成一个2048位的密钥:

# openssl genrsa -out ca-private.pem 2048

2、生成CA私钥

我们自己做测试,那么证书的申请机构和颁发机构都是自己。直接生成证书私钥,-day指定证书有效期

# openssl req -x509 -new -nodes -key ca-private.pem -days 3650 -out ca-public.pem -subj "/CN=kube-ca"

注意:生成ca-private.pem时, -subi参数中"CN"的值通常为域名。

三、生成apiserver服务端证书

1、apiserver证书使用说明

kube-apiserver

使用的证书

证书作用

ca-public.pem

CA根证书

ca-private.pem

CA端私钥

apiserver-public.pem

kube-apiserver的tls认证证书

apiserver-private.pem

kube-apiserver的tls认证私钥

--token-auth-file指定了token.csv的位置,用于kubelet 组件 第一次启动时没有证书如何连接 apiserver 。 Token 和 apiserver 的 CA 证书被写入了 kubelet 所使用的 bootstrap.kubeconfig 配置文件中;这样在首次请求时,kubelet 使用 bootstrap.kubeconfig 中的 apiserver CA 证书来与 apiserver 建立 TLS 通讯,使用 bootstrap.kubeconfig 中的用户 Token 来向 apiserver 声明自己的 RBAC 授权身份

--tls-cert-file=apiserver-public.pem指定kube-apiserver证书地址

--tls-private-key-file=apiserver-private.pem指定kube-apiserver私钥地址

--client-ca-file=ca-public.pem 指定根证书地址

--service-account-key-file=ca-private.pem/apiserver-private.pem包含PEM-encoded x509 RSA公钥和私钥的文件路径,用于验证Service Account的token,如果不指定,则使用--tls-private-key-file指定的文件

--etcd-cafile=ca-private.pem 到etcd安全连接使用的SSL CA文件

--etcd-certfile=apiserver-public.pem 到etcd安全连接使用的SSL 证书文件

--etcd-keyfile=apiserver-private.pem到etcd安全连接使用的SSL 私钥文件

基于masterssl.cnf创建apiserver-public.pem和apiserver-private.pem文件。

在生成apiserver.csr时, -subi参数中"/CN"指定的名字需为Master所在的主机名。

2、证书生成

1)证书配置

创建用于生成证书签名请求(CSR)的配置文件masterssl.cnf,该文件用于x509 v3版本的证书。

在该文件中主要需要设置:

(1)、Master服务器的hostname (k8s-master)、IP地址${MASTER_IPV4}(192.168.10.50),

(2)、Kubernetes Master Service的虚拟服务名称(kubernetes.default等)和使用自己规划作为kubernetes service IP端的首IP替换${K8S_SERVICE_IP}

即apiserver参数的--service-cluster-ip-range的首IP,

若--service-cluster-ip-range=192.168.10.0/16,则${K8S_SERVICE_IP}为192.168.0.1

若--service-cluster-ip-range=10.0.0.0/16,则${K8S_SERVICE_IP}为10.0.0.1

masterssl.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 IP.1 = {K8S_SERVICE_IP} IP.2 = {MASTER_IPV4}

1)alt_names指的是最终可以访问的域名或者IP,所以,其实一个证书是可以多个网站同时使用的。被访问域名只要满足DNS和IP中的一个,其证书就是合法的。 SubjectAltName是X509 Version 3 (RFC 2459)的扩展,允许ssl证书指定多个可以匹配的名称。SubjectAltName 可以包含email 地址,ip地址,正则匹配DNS主机名,等等。

SAN(Subject Alternative Name)是 SSL 标准 x509 中定义的一个扩展。使用了 SAN 字段的 SSL 证书,可以扩展此证书支持的域名,使得一个证书可以支持多个不同域名的解析。

2)、生成apiserver服务端私钥:

openssl genrsa -out apiserver-private.pem 2048

3)、生成服务端证书签名请求文件(CSR):

和CA证书的生成不同的是,我们需要先生成一个csr证书请求文件文件(CSR,Cerificate Signing Request),有了这个文件之后再利用CA根证书生成最终的证书。

基于配置文件masterssl.cnf生成证书签名请求文件(CSR):

openssl req -new -key apiserver-private.pem -out apiserver.csr -subj "/CN=k8s-master" -config masterssl.cnf (这个是 NO SAN 命令: openssl req -new -key apiserver-private.pem -out apiserver.csr 只执行 NO SAN 命令也可以签发证书,不过却不能够添加多个域名。)

4)、生成apiserver服务端认证公钥

使用ca-private.pem、 ca-public.pem 和apiserver.csr 生成apiservertls认证公钥

openssl x509 -req -in apiserver.csr -CA ca-public.pem -CAkey ca-private.pem -CAcreateserial -out apiserver-public.pem -days 3650 -extensions v3_req -extfile masterssl.cnf

全部执行完后会生成6个文件:

apiserver-private.csr apiserver-private.pem apiserver-public.pem ca-private.pem ca-public.pem ca-public.srl

查看证书:

openssl x509 -noout -text -in ./apiserver-public.pem

一般生成的根证书(ca-private.pem, ca-public.pem)与apiserver证书(apiserver-private.pem,apiserver-public.pem)放置在Master节点的某个目录(例如/mnt/app/kubernetes/ssl)

apiserver的配置中需要指定如下参数:

--service-account-key-file=/mnt/app/kubernetes/ssl/apiserver-private.pem --tls-private-key-file=/mnt/app/kubernetes/ssl/apiserver-private.pem --tls-cert-file=/mnt/app/kubernetes/ssl/apiserver-public.pem --client-ca-file=/mnt/app/kubernetes/ssl/ca-public.pem 同时,可以关掉非安全端口8080,设置安全端口为443 (默认为6443):

最后重启kube-apiserver服务。

3. kube-controller-manager客户端双向认证证书

kubelet 发起的 CSR 请求都是由 kube-controller-manager 来做实际签署的,所有使用的证书都是根证书的密钥对 。由于kube-controller-manager是和kube-apiserver部署在同一节点上,且使用非安全端口通信,故不需要证书。

使用的证书

证书作用

ca.pem

CA根证书

ca-key.pem

kube-apiserver的tls认证私钥

--cluster-signing-cert-file:指定签名的CA机构根证书,用来签名为 TLS BootStrap 创建的证书和私钥

--cluster-signing-key-file:指定签名的CA机构私钥,用来签名为 TLS BootStrap 创建的证书和私钥

--service-account-private-key-file: 同上

--root-ca-file=: 根CA证书文件路径 ,用来对 kube-apiserver 证书进行校验,指定该参数后,才会在Pod 容器的 ServiceAccount 中放置该 CA 证书文件

--kubeconfig :kubeconfig配置文件路径,在配置文件中包括Master的地址信息及必要认证信息

apiversion: v1 kind: Config users: - name: controllermanager user: client-certificate: client-key: /mnt/app/kubernetes/ssl/manager-client-private.pem clusters: - name: local cluster: certificate-authority: /var/run/kubernetes/ca.crt contexts: context: cluster: local user: controllermanager name: my-context current-context: my-context

controller-manager的配置中需要指定如下参数: --service-account-private-key-file=/mnt/app/kubernetes/ssl/apiserver-private.pem --root-ca-file=/mnt/app/kubernetes/ssl/ca-public.pem --cluster-signing-cert-file=/mnt/app/kubernetes/ssl/ca-public.pem --cluster-signing-key-file=/mnt/app/kubernetes/ssl/ca-private.pem

当然也可以为controller-manager创建证书,controller-manager相对于apiserver是客户端:

2)、设置kube-controller-manager的客户端证书、私钥和启动参数

$ openssl genrsa -out manager-client-private.pem 2048

$ openssl req -new -key manager-client-private.pem -subj "/CN=k8s-master" -out manager-client.csr

$ openssl x509 -req -in manager-client.csr -CA ca-public.pem -CAkey ca-private.pem -CAcreateserial -out manager-client-public.pem -days 5000

然后可以通过curl测试:

curl --cacert /mnt/app/kubernetes/ssl/ca-public.pem --key /mnt/app/kubernetes/ssl/manager-client-private.pem --cert /mnt/app/kubernetes/ssl/manager-client-public.pem https://k8s-master:6443

如果看到下面错误,说明认证有问题。 { "kind": "Status", "apiVersion": "v1", "metadata": { }, "status": "Failure", "message": "Unauthorized", "reason": "Unauthorized", "code": 401 }

/mnt/app/kubernetes/ssl/kubeconfig.yaml

apiVersion: v1 kind: Config users: - name: controllermanager user: client-certificate:/mnt/app/kubernetes/ssl/manager-client-public.pem client-key:/mnt/app/kubernetes/ssl/manager-client-private.pem clusters: - name: local cluster: certificate-authority: /mnt/app/kubernetes/ssl/ca-public.pem contexts: - context: cluster: local user: controllermanager name: my-context current-context: my-context

5、删除相关serviceAccount的token

由于系统重新生成证书,需要删除相关serviceAccount的token,然后重启apiserver,apiserver根据最新

kubectl get secret -n kube-system NAME TYPE DATA AGE coredns-token-cdn9x kubernetes.io/service-account-token 3 3d default-token-lht2v kubernetes.io/service-account-token 3 3d

kubectl delete secret coredns-token-cdn9x -n kube-system secret "coredns-token-cdn9x" deleted

四、node节点客户端双向证书生成

设置每台Node上kubelet的客户端证书、私钥和启动参数

1)、首先复制kube-apiserver的ca-public.pem和ca-private.pem文件到Node上,

2)、在生成kubelet-public.pem时-CA参数和-CAkey参数使用的是apiserver的ca-public.pem和ca-private.pem文件。

3)、在生成kubelet client.csr时-subj参数中的"/CN"设置为本Node的IP地址。

-subj 指定证书申请者的个人信息

可以将节点IP放入到环境变量

# Export this worker's IP address.

export WORKER_IP=<WORKER_IPV4>

openssl genrsa -out kubelet-private.pem 2048 openssl req -new -key kubelet-private.pem -out kubelet.csr -subj "/CN=kubelet-key" -config kubelet-openssl.cnf openssl x509 -req -in kubelet.csr -CA ca-public.pem -CAkey ca-private.pem -CAcreateserial -out kubelet-public.pem -days 3650 -extensions v3_req -extfile kubelet-openssl.cnf

openssl genrsa -out kubelet-private.pem 2048 openssl req -new -key kubelet-private.pem -out kubelet.csr -subj "/CN=kubelet-key" openssl x509 -req -in kubelet.csr -CA ca-public.pem -CAkey ca-private.pem -CAcreateserial -out kubelet-public.pem -days 3650

curl --cacert /mnt/app/kubernetes/ssl/ca-public.pem --key /mnt/app/kubernetes/ssl/kubelet-private.pem --cert /mnt/app/kubernetes/ssl/kubelet-public.pem https://k8s-master:6443

将这些文件复制到一个目录中(例如/etc/kubernetes/ssl/)。

其中kubelet-openssl.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] IP.1 = $ENV::WORKER_IP

从节点上配置kubelet所使用的配置文件worker-kubeconfig.yaml (kubelet和kube-proxy进程共用)指定证书:

配置客户端证书等相关参数,内容如下:

kubelet的如下参数使用证书:

--kubeconfig=/etc/kubernetes/worker-kubeconfig.yaml --tls-private-key-file=/etc/kubernetes/ssl/kubelet-private.pem --tls-cert-file=/etc/kubernetes/ssl//kubelet-public.pem

重启kubelet

kube-proxy复用上一步kubelet创建的客户端证书,配置启动参数:

--master=https://192.168.18.3:443

--kubeconfig=/etc/kubernetes/worker-kubeconfig.yaml

重启kube-proxy服务。

至此,一个基于CA的双向数字证书认证的Kubernetes集群环境就搭建完成了。

五、集群管理员双向认证证书生成

此证书用于kubectl,设置方式如下:

openssl genrsa -out admin-key.pem 2048 openssl req -new -key admin-key.pem -out admin.csr -subj "/CN=kube-admin" openssl x509 -req -in admin.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out admin.pem -days 365 # 配置一个名为default的集群,并指定服务地址与根证书 kubectl config set-cluster default --server=https://172.17.4.101:443 --certificate-authority={PWD}/ssl/ca.pem

# 设置一个管理用户为admin,并配置访问证书 kubectl config set-credentials admin --certificate-authority={PWD}/ssl/ca.pem --client-key={PWD}/ssl/admin-key.pem --client-certificate=

# 设置一个名为default使用default集群与admin用户的上下文, kubectl config set-context default --cluster=default --user=admin

# 启用default为默认上下文 kubectl config use-context default

0 人点赞