基于证书签名请求快速构建kubeconfig
概述
Kubernetes 提供 certificates.k8s.io
API,可让你配置由你控制的证书颁发机构(CA) 签名的 TLS 证书。 你的工作负载可以使用这些 CA 和证书来建立信任。
请求签名流程
CertificateSigningRequest 资源类型允许客户使用它申请发放 X.509 证书。
首先我们需要创建一个CSR证书请求文件,并通过CertificateSigningRequest资源对象的spec.request
提交到k8s中。
创建完成的CertificateSigningRequest,要先通过批准,然后才能签名。这里会根据 spec.signerName
字段所选的签名者自动或者人工批准,人工批准的话需要手动执行kube certificate approve
命令,本文也是采用的这种方法。同样我们也可以驳回证书签名请求。
对于已批准的证书会通过证书签名控制器自动创建证书并更新到CertificateSigningRequest资源对象的status.certificate
字段中。如果不满足签名条件或者驳回的话,这个字段就会一直为空。
注意:为了减少集群中遗留的过时的 CertificateSigningRequest 资源的数量, 垃圾收集控制器将会周期性地运行。 此垃圾收集器会清除在一段时间内没有改变过状态的 CertificateSigningRequests:
- 已批准的请求:1小时后自动删除
- 已拒绝的请求:1小时后自动删除
- 已失败的请求:1小时后自动删除
- 挂起的请求:24小时后自动删除
- 所有请求:在颁发的证书过期后自动删除
具体操作
创建密钥
基于openssl生成PKI私钥和CSR证书请求
1 | openssl genrsa -out zerchin.key 2048 |
其中,CN 是用户名,O 是该用户归属的组。如下:
1 | Organization Name (eg, company) [Default Company Ltd]:rancher |
获取CSR文件的base64编码
1 | cat zerchin.csr | base64 | tr -d "\n" |
创建CertificateSigningRequest
1 | cat << EOF > certificateSigningRequest.yaml |
其中:
signerName
:Kubernetes提供了四种内置的签名者,这里我们使用kubernetes.io/kube-apiserver-client
,签名的证书被apiserver视为客户证书。
expirationSeconds
:过期时间,这个过期时间指的是签发等待的时间,过了这个时间就不能签发了,可以重新再次发起。该参数在 k8s 1.22+ 版本支持,低于此版本可以去掉这个参数。
usages
:必须是client auth
request
:是CSR文件内容的base64 编码值。
批准证书签名请求
获取CSR列表
1 | $ kubectl get csr |
获取证书签名请求列表
1 | $ kubectl get certificatesigningrequests.certificates.k8s.io |
批准CSR
1 | $ kubectl certificate approve zerchin |
查看csr和certificate的状态,一定要有Approved
和Issued
两个状态
1 | $ kubectl get csr |
从CertificateSigningRequest中导出颁发的证书
证书的内容使用 base64 编码,存放在字段 status.certificate
1 | kubectl get csr zerchin -o jsonpath='{.status.certificate}'| base64 -d > zerchin.crt |
构建kubeconfig文件
新建一个kubeconfig文件
1 | touch zerchin-kubeconfig |
设置k8s集群
1 | $ kubectl --kubeconfig zerchin-kubeconfig config set-cluster k8s --server=https://192.168.2.12:6443 --certificate-authority=/etc/kubernetes/ssl/kube-ca.pem --embed-certs=true |
设置用户
1 | $ kubectl --kubeconfig zerchin-kubeconfig config set-credentials zerchin --client-key=./zerchin.key --client-certificate=./zerchin.crt --embed-certs=true |
设置context
1 | $ kubectl --kubeconfig zerchin-kubeconfig config set-context zerchin --cluster=k8s --user=zerchin |
切换context
1 | $ kubectl --kubeconfig zerchin-kubeconfig config use-context zerchin |
创建角色并绑定到该用户上
创建role
1 | $ kubectl create role zerchin-role --verb=create --verb=get --verb=list --verb=update --verb=delete --resource=pods |
创建rolebinding
1 | $ kubectl create rolebinding zerchin-role-binding --role=zerchin-role --user=zerchin |
验证
执行kubectl命令进行验证,首先验证一下pod的权限
1 | $ kubectl --kubeconfig zerchin-kubeconfig get pods |
看一下node的权限
1 | $ kubectl --kubeconfig zerchin-kubeconfig get nodes |
可以看到,我们可以正常执行kubectl命令去查看pod,但是没有其他资源的权限,验证成功。
可能遇到的问题
批准CSR之后,如果无法从CertificateSigningRequest中导出颁发的证书(
.status.certificate
路径不存在),并且执行kubectl get csr
查看只有一个Approved
状态,没有Issued
状态,那么大概率是controller-manager没有挂载CA证书进来,需要先挂载进来后再次签发。Rancher/RKE集群可以参考这个如下配置添加CA证书挂载,编辑
cluster.yml
文件,在kube-controller
下添加此配置参数:
1 | services: |
参考文档:
https://kubernetes.io/zh-cn/docs/reference/access-authn-authz/certificate-signing-requests/
https://kubernetes.io/zh-cn/docs/tasks/tls/managing-tls-in-a-cluster/