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

一.基于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.pemapiserver-private.pem

从节点公钥与私钥kubelet-publi.pemkubelet-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.pemapiserver-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/api

如果看到下面错误,说明认证有问题。
{
  "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.pemca-private.pem文件到Node上,

2)、在生成kubelet-public.pem时-CA参数和-CAkey参数使用的是apiserver的ca-public.pemca-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集群环境就搭建完成了。

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


1、kubeconfig 介绍

kubeconfig文件保存了k8s集群的集群、用户、命名空间、认证的信息。kubectl命令使用kubeconfig文件来获取集群的信息,然后和API server进行通讯。

注意:用于配置对集群的访问的文件称为kubecconfig文件。也就是说,kubeconfig文件中包含的内容是集群的配置。但是,并不是必须有个文件名字叫kubeconfig

默认情况下,kubectl命令从$HOME/.kube目录下查找一个名字叫做config的文件。可以通过KUBECONFIG环境变量或者--kubeconfig参数来指定其他的kubeconfig文件。

kubeconfig中主要由如下部分组成:

  • clusters (集群)
  • users(用户)
  • context(上下文)

1)、 kubeconfig支持多集群、多用户、多认证

在实际的使用中的如下场景:

  • kubelet使用证书认证(kubelet和api server进行认证)
  • 用户使用token进行认证
  • 管理员为不同的用户提供不同的证书

都可以使用kubeconfig来组织起集群、用户、命名空间的信息。同样,也可以使用context在集群和命名空间之间进行切换。

2)、Context的定义

在kubeconfig中,context中将访问一个集群的参数进行分组。访问这个context名称就是访问这个参数组。context就是一组信息的别名,举例来说,当在高德中使用家的地址,公司的地址就是一个别名,就能迅速的定位到具体的地址信息。

每个context都有3个参数:

  1. cluster (集群)
  2. namespace(命名空间)
  3. user(用户)

默认情况下,kubectl命令从current context中来获取参数,然后与集群进行通讯。

2、具体生成步骤

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

openssl genrsa -out admin-key.pem 2048
openssl req -new -key admin-key.pem -out admin.csr -subj "/CN=admin/O=system:masters"
openssl x509 -req -in admin.csr -CA ca-public.pem -CAkey ca-private.pem -CAcreateserial -out admin.pem -days 365

#kube-apiserver提取CN作为客户端的用户名,即admin。
#kube-apiserver预定义的 RBAC使用的ClusterRoleBindings system:masters将用户admin与ClusterRole system:masters绑定

# 配置一个名为default的集群,并指定服务地址与根证书
kubectl config set-cluster kubernetes --server=https://127.0.0.1:6443 --embed-certs=true --certificate-authority=ca-public.pem --kubeconfig=kubectl.kubeconfig


# 设置一个管理用户为admin,并配置访问证书
kubectl config set-credentials admin --certificate-authority=ca-public.pem --embed-certs=true --client-key=admin-key.pem --client-certificate=admin.pem --kubeconfig=kubectl.kubeconfig

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

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

验证:

kubectl --kubeconfig=kubectl.kubeconfig get ns

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hguisu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值