9

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

 3 years ago
source link: https://guisu.blog.csdn.net/article/details/95459273
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

一.基于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.pemCA根证书ca-private.pemCA端私钥apiserver-public.pemkube-apiserver的tls认证证书apiserver-private.pemkube-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.pemCA根证书ca-key.pemkube-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=${PWD}/ssl/admin.pem

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

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK