使用 CertificateSigningRequest 为 Kubernetes API 客户端颁发证书

Kubernetes 允许你使用公钥基础设施 (PKI) 作为客户端对你的集群进行认证。

为了让普通用户能够认证并调用 API,需要执行几个步骤。首先,此用户必须具有由 Kubernetes 集群信任的机构颁发的 X.509 证书。然后客户端必须将该证书提供给 Kubernetes API。

在此过程中,你使用一个 CertificateSigningRequest,并且你或某个其他主体必须批准该请求。

你将创建一个私钥,然后获取颁发的证书,最后为客户端配置该私钥。

开始之前

  • 你需要拥有一个 Kubernetes 集群,并且 kubectl 命令行工具已配置为与你的集群通信。建议你在至少包含两个非控制平面节点的集群上运行此教程。如果你还没有集群,可以使用 minikube 创建一个,或者你可以使用以下 Kubernetes 练习场之一:

  • 你需要 kubectlopensslbase64 工具。

本页面假设你使用的是 Kubernetes 基于角色的访问控制 (RBAC)。如果你有其他或额外的安全机制来处理鉴权,你也需要考虑这些因素。

创建私钥

在此步骤中,你将创建一个私钥。你需要对此文档保密;拥有它的人可以冒充该用户。

# Create a private key
openssl genrsa -out myuser.key 3072

创建 X.509 证书签名请求

设置 CSR 的 CN 和 O 属性很重要。CN 是用户的名称,O 是该用户所属的组。你可以参考 RBAC 了解标准组。

# Change the common name "myuser" to the actual username that you want to use
openssl req -new -key myuser.key -out myuser.csr -subj "/CN=myuser"

创建 Kubernetes CertificateSigningRequest

使用此命令编码 CSR 文档

cat myuser.csr | base64 | tr -d "\n"

创建一个 CertificateSigningRequest 并通过 kubectl 提交给 Kubernetes 集群。以下是你可以用来生成 CertificateSigningRequest 的 shell 代码片段。

cat <<EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: myuser # example
spec:
  # This is an encoded CSR. Change this to the base64-encoded contents of myuser.csr
  request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1ZqQ0NBVDRDQVFBd0VURVBNQTBHQTFVRUF3d0dZVzVuWld4aE1JSUJJakFOQmdrcWhraUc5dzBCQVFFRgpBQU9DQVE4QU1JSUJDZ0tDQVFFQTByczhJTHRHdTYxakx2dHhWTTJSVlRWMDNHWlJTWWw0dWluVWo4RElaWjBOCnR2MUZtRVFSd3VoaUZsOFEzcWl0Qm0wMUFSMkNJVXBGd2ZzSjZ4MXF3ckJzVkhZbGlBNVhwRVpZM3ExcGswSDQKM3Z3aGJlK1o2MVNrVHF5SVBYUUwrTWM5T1Nsbm0xb0R2N0NtSkZNMUlMRVI3QTVGZnZKOEdFRjJ6dHBoaUlFMwpub1dtdHNZb3JuT2wzc2lHQ2ZGZzR4Zmd4eW8ybmlneFNVekl1bXNnVm9PM2ttT0x1RVF6cXpkakJ3TFJXbWlECklmMXBMWnoyalVnald4UkhCM1gyWnVVV1d1T09PZnpXM01LaE8ybHEvZi9DdS8wYk83c0x0MCt3U2ZMSU91TFcKcW90blZtRmxMMytqTy82WDNDKzBERHk5aUtwbXJjVDBnWGZLemE1dHJRSURBUUFCb0FBd0RRWUpLb1pJaHZjTgpBUUVMQlFBRGdnRUJBR05WdmVIOGR4ZzNvK21VeVRkbmFjVmQ1N24zSkExdnZEU1JWREkyQTZ1eXN3ZFp1L1BVCkkwZXpZWFV0RVNnSk1IRmQycVVNMjNuNVJsSXJ3R0xuUXFISUh5VStWWHhsdnZsRnpNOVpEWllSTmU3QlJvYXgKQVlEdUI5STZXT3FYbkFvczFqRmxNUG5NbFpqdU5kSGxpT1BjTU1oNndLaTZzZFhpVStHYTJ2RUVLY01jSVUyRgpvU2djUWdMYTk0aEpacGk3ZnNMdm1OQUxoT045UHdNMGM1dVJVejV4T0dGMUtCbWRSeEgvbUNOS2JKYjFRQm1HCkkwYitEUEdaTktXTU0xMzhIQXdoV0tkNjVoVHdYOWl4V3ZHMkh4TG1WQzg0L1BHT0tWQW9FNkpsYWFHdTlQVmkKdjlOSjVaZlZrcXdCd0hKbzZXdk9xVlA3SVFjZmg3d0drWm89Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo=
  signerName: kubernetes.io/kube-apiserver-client
  expirationSeconds: 86400  # one day
  usages:
  - client auth
EOF

需要注意的一些事项

  • usages 必须是 client auth
  • expirationSeconds 可以设置得更长(例如,864000 表示十天)或更短(例如,3600 表示一小时)。你不能请求短于 10 分钟的持续时间。
  • request 是 CSR 文件内容的 base64 编码值。

批准 CertificateSigningRequest

使用 kubectl 查找你创建的 CSR,并手动批准它。

获取 CSR 列表

kubectl get csr

批准 CSR

kubectl certificate approve myuser

获取证书

从 CSR 中检索证书,检查它是否正常。

kubectl get csr/myuser -o yaml

证书值位于 .status.certificate 下,采用 Base64 编码格式。

从 CertificateSigningRequest 导出已颁发的证书。

kubectl get csr myuser -o jsonpath='{.status.certificate}'| base64 -d > myuser.crt

将证书配置到 kubeconfig 中

下一步是将此用户添加到 kubeconfig 文件中。

首先,你需要添加新的凭据

kubectl config set-credentials myuser --client-key=myuser.key --client-certificate=myuser.crt --embed-certs=true

然后,你需要添加上下文

kubectl config set-context myuser --cluster=kubernetes --user=myuser

测试一下

kubectl --context myuser auth whoami

你应该看到输出确认你是“myuser”。

创建 Role 和 RoleBinding

创建证书后,是时候为此用户定义访问 Kubernetes 集群资源的 Role 和 RoleBinding 了。

这是一个为这个新用户创建 Role 的示例命令

kubectl create role developer --verb=create --verb=get --verb=list --verb=update --verb=delete --resource=pods

这是一个为这个新用户创建 RoleBinding 的示例命令

kubectl create rolebinding developer-binding-myuser --role=developer --user=myuser

接下来

最后修改于 2025 年 3 月 4 日太平洋标准时间下午 8:22:将客户端证书的 CSR 移动到任务部分 (2a3a72e16c)