- kubernetes学习系列快捷链接
- Kubernetes架构原则和对象设计(一)
- Kubernetes架构原则和对象设计(二)
- Kubernetes架构原则和对象设计(三)
- Kubernetes控制平面组件:etcd(一)
- Kubernetes控制平面组件:etcd(二)
- Kubernetes控制平面组件:etcd常用配置参数
- Kubernetes控制平面组件:etcd高可用集群搭建
- Kubernetes控制平面组件:etcd高可用解决方案
- Kubernetes控制平面组件:Kubernetes如何使用etcd
- kubectl 和 kubeconfig 基本原理
- kubeadm 升级 k8s集群 1.17到1.20
- Kubernetes常见问题解答
- 查看云机器的一些常用配置
本文主要对kubernetes API Server 认证机制中的 X509 认证进行介绍,包括 X509证书 的设计理念、实现原理、认证流程,以及在 Kubernetes 中的具体应用
2.基于 X509 证书的认证方式
2.1.X509认证方式简介
-
X509 是什么
- X509认证是一种基于 SSL/TLS 证书的身份验证机制,广泛应用于 Kubernetes 等分布式系统中,用于确保通信双方的身份合法性。
-
核心概念
- 证书(Certificate) :由可信的证书颁发机构(CA)签发的数字文件,包含公钥和身份信息。
- 私钥(Private Key):与证书中的公钥配对的私钥,用于解密和签名。
- CA(Certificate Authority):证书颁发机构,负责签发和管理证书。
-
工作原理
- 证书签发 :
- 客户端和服务端分别向 CA 申请证书。
- CA 验证身份后签发证书,证书中包含公钥和身份信息。
- 双向认证 :
- 客户端和服务端在建立连接时,会交换彼此的证书。
- 双方使用 CA 的公钥验证对方证书的合法性。
- 加密通信 :
- 验证通过后,双方使用证书中的公钥加密通信数据,确保数据的安全性。
- 证书签发 :
-
优点
- 安全性高:基于非对称加密,确保通信数据的机密性和完整性。
- 身份验证可靠:通过 CA 签发的证书,确保通信双方的身份合法性。
- 广泛支持:X509 是行业标准,兼容性高。
-
缺点
- 管理复杂:证书的签发、更新和吊销需要额外的管理工作。
- 性能开销:加密和解密操作会带来一定的性能损耗。
2.2.X509 在 Kubernetes 中的应用
2.2.1.查看 Kubernetes 的证书配置
- 在 Kubernetes 中,X509 认证通常用于以下场景:
- API Server 认证 :客户端(如
kubectl
)使用 X509 证书向 API Server 证明身份。 - 组件间通信 :Kubernetes 各组件(如
kubelet
、scheduler
、controller-manager
)之间使用 X509 证书进行安全通信。
- API Server 认证 :客户端(如
- 查看kubernetes的证书配置
- kubernetes的默认证书都放在
/etc/kubernetes/pki
下面
ca.crt
和ca.key
:- 集群的根证书和私钥。它相当于一个权威机构,集群其他组件的证书都由这个CA签发
- CA的私钥必须严格保护,因为泄露会导致整个集群的安全体系崩溃。
apiserver.crt
和apiserver.key
:- 这是Kubernetes API Server的证书和私钥,由kubernetes的ca.crt签发,用于HTTPS通信。
apiserver.crt
证书用于让访问API Server的客户端验证服务器身份,确保客户端连接的是合法的API Server。其中的公钥也可以让 客户端进行数据的加密。apiserver.key
:API Server的私钥,对客户端使用公钥加密后的数据,进行解密。非对称加密
apiserver-etcd-client.crt
和apiserver-etcd-client.key
- API Server作为客户端访问etcd时的证书和私钥
apiserver-kubelet-client.crt
和apiserver-kubelet-client.key
- API Server作为客户端与kubelet通信时的证书。
- crt证书用于让 Kubelet 验证 API Server 的身份,确保kubelet只接受来自合法API Server的请求
sa.key
和sa.pub
- Service Account的密钥对,用于签署Service Account的令牌。Kubernetes使用这些密钥来验证Pod的Service Account,确保Pod的身份合法。
- 其他的不一一介绍了
- kubernetes的默认证书都放在
2.2.2.解析证书内容
- 我们知道一个CA证书中包含 证书的有效期、颁发者、主题、公钥 等信息,那么如何解析证书查看这些内容?
bash
[root@VM-226-235-tencentos ~]# openssl x509 -in /etc/kubernetes/pki/apiserver.crt -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number: xxxxxxxxxxx
Signature Algorithm: sha256WithRSAEncryption
Issuer: CN=kubernetes
Validity
Not Before: Apr 17 08:00:10 2024 GMT
Not After : Apr 21 07:13:02 2025 GMT
Subject: CN=kube-apiserver
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
xxxxxxxxxxxxx
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication
X509v3 Subject Alternative Name:
DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster.local, DNS:vm-226-235-tencentos, IP Address:10.96.0.1, IP Address:9.135.226.235
Signature Algorithm: sha256WithRSAEncryption
xxxxxxxxxxxxx

2.2.3.kubeconfig也使用了x509认证
-
第一次安装kubernetes集群,很多人都是用kubeadm安装的,kubeadm默认使用的就是证书的认证方式
-
可以看下生成的kubeconfig的内容
yaml[root@VM-226-235-tencentos ~/zgy/code/service-vendors]# cat ~/.kube/config apiVersion: v1 clusters: - cluster: # 1.使用 ca-data + server,定义一个集群 certificate-authority-data: xxxxxxxx server: https://9.135.226.235:6443 name: kubernetes contexts: - context: # 3.使用 集群名 + user身份,定义上下文。使用该user访问这个集群 cluster: kubernetes user: kubernetes-admin name: kubernetes-admin@kubernetes current-context: kubernetes-admin@kubernetes kind: Config preferences: {} users: - name: kubernetes-admin user: # 2.使用ca-data + ck-data,定义一个user身份 client-certificate-data: xxxxxxxx client-key-data: xxxxxxxx
2.3.实操演练:在Kubernetes中使用X509认证
下面演示:如何在 Kubernetes 中通过 X509 证书 创建一个用户(user-test),并为其授予访问集群资源的权限
参考:https://github.com/cncamp/101/blob/master/module6/basic-auth/x509.MD
- 整体流程
- 生成用户的私钥和 CSR。
- 提交 CSR 到 Kubernetes 并批准。
- 提取签发的证书并配置到 kubectl。
- 为用户授予权限并验证。
2.3.1.Create private key and csr
sh
# 生成用户私钥(user-test.key)
openssl genrsa -out user-test.key 2048
# 生成用户 CSR(user-test.csr)
openssl req -new -key user-test.key -out user-test.csr \
-subj "/C=CN/O=Your Organization/CN=user-test"
# 生成 CA 私钥(ca.key)
openssl genrsa -out ca.key 4096
# 生成 CA 自签名证书(ca.crt)
openssl req -new -x509 -days 10000 \
-key ca.key \
-out ca.crt \
-subj "/C=CN/O=Your Organization/CN=Kubernetes CA"
-
作用:生成用户的私钥和证书签名请求(CSR)。
- user-test.key:用户的私钥文件。
- user-test.csr:证书签名请求文件,包含用户的公钥和身份信息。
- <CA_public>.crt:CA 的公钥证书(可选步骤,用于验证 CSR)。
-
解释:
- 使用 openssl genrsa 生成一个 2048 位的 RSA 私钥。
- 使用 openssl req -new 基于私钥生成 CSR。
- (可选)生成 CA 的公钥证书,用于后续验证。
2.3.2.Encode csr
sh
csr_base64=$(cat user-test.csr | base64 | tr -d '\n')
- 作用:将 CSR 文件编码为 Base64 格式。
- 解释:
- Kubernetes 要求 CSR 文件以 Base64 编码的形式提交。
- tr -d "\n" 用于去除编码后的换行符,确保 CSR 是单行字符串。
2.3.3.Replace request and create csr
- 如果你的kubernetes版本小于1.22,则需要删除expirationSeconds字段,低版本不支持
kubectl version --short
查看kubernetes版本
sh
cat <<EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: user-test
spec:
request: $csr_base64
signerName: kubernetes.io/kube-apiserver-client
usages:
- client auth
EOF
bash
[root@VM-226-235-tencentos ~/zgy/test/x509]# kubectl get csr
NAME AGE SIGNERNAME REQUESTOR CONDITION
user-test 2m51s kubernetes.io/kube-apiserver-client kubernetes-admin Pending
- 作用:在 Kubernetes 中创建一个 CertificateSigningRequest(CSR)资源。
- 解释:
- request:填入上一步生成的 Base64 编码的 CSR。
- signerName:指定签名者(这里是 Kubernetes API Server)。
- expirationSeconds:设置证书的有效期(这里为 1 天)。
- usages:指定证书用途(这里是客户端认证)。
2.3.4.Approve csr
sh
[root@VM-226-235-tencentos ~/zgy/test/x509]# kubectl certificate approve user-test
certificatesigningrequest.certificates.k8s.io/user-test approved
- 作用:批准 CSR 请求。
- 解释:
- Kubernetes 管理员需要手动批准 CSR,之后 API Server 会签发证书。
2.3.5.Check csr
sh
[root@VM-226-235-tencentos ~/zgy/test/x509]# kubectl get csr/user-test -o yaml
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
creationTimestamp: "2025-02-18T05:32:43Z"
name: user-test
resourceVersion: "82475651"
selfLink: /apis/certificates.k8s.io/v1/certificatesigningrequests/user-test
uid: 4eba2640-372e-4cb7-9291-41f3e8c1f2fa
spec:
groups:
- system:masters
- system:authenticated
request: xxxxxxxxxxxx
signerName: kubernetes.io/kube-apiserver-client
usages:
- client auth
username: kubernetes-admin
status:
certificate: xxxxxxxxxxxx
conditions:
- lastTransitionTime: "2025-02-18T05:36:20Z"
lastUpdateTime: "2025-02-18T05:36:20Z"
message: This CSR was approved by kubectl certificate approve.
reason: KubectlApprove
status: "True"
type: Approved
- 作用:查看 CSR 的状态。
- 解释:
- 确认 CSR 是否已被批准,并查看签发的证书是否已生成。
2.3.6.Extract crt
sh
# 提取用户证书(user-test.crt)
kubectl get csr user-test -o jsonpath='{.status.certificate}' | base64 -d > user-test.crt
# 验保证书链有效性
openssl verify -CAfile ca.crt user-test.crt
# 输出应为 "user-test.crt: OK"
- 作用:从 CSR 中提取签发的证书。
- 解释:
- 使用 kubectl get csr 获取 CSR 的状态,提取 status.certificate 字段(Base64 编码的证书)。
- 使用 base64 -d 解码并保存为 user-test.crt 文件。
2.3.7.Set credential
sh
[root@VM-226-235-tencentos ~/zgy/test/x509]# kubectl config set-credentials user-test \
--client-key=user-test.key \
--client-certificate=user-test.crt \
--embed-certs=true
User "user-test" set.
- 查看kubeconfig,可以看到已经有 mysql的user了
bash
[root@VM-226-235-tencentos ~/zgy/test/x509]# cat ~/.kube/config
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: xxxxxxxx
server: https://9.135.226.235:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
current-context: kubernetes-admin@kubernetes
kind: Config
preferences: {}
users:
- name: kubernetes-admin
user:
client-certificate-data: xxxxxx
client-key-data: xxxxxx
- name: user-test
user:
client-certificate-data: xxxxxxx
client-key-data: xxxxxxx
- 作用:将用户的私钥和证书配置到 kubectl 中。
- 解释:
- 使用 kubectl config set-credentials 将 user-test.key 和 user-test.crt 绑定到用户 user-test。
- --embed-certs=true 将证书内容嵌入到 kubeconfig 文件中。
- 不过此时直接去
kubectl get pod --user=user-test
还是会报 403 Forbidden,因为还没有授权
2.3.8.Grant permission
sh
[root@VM-226-235-tencentos ~/zgy/test/x509]# kubectl create role developer --verb=create --verb=get --verb=list --verb=update --verb=delete --resource=pods
role.rbac.authorization.k8s.io/developer created
[root@VM-226-235-tencentos ~/zgy/test/x509]# kubectl create rolebinding developer-binding-user-test \
--role=developer \
--user=user-test
rolebinding.rbac.authorization.k8s.io/developer-binding-user-test created
- 作用:为用户 user-test 授予访问资源的权限。
- 解释:
- 创建一个 Role,定义对 pods 资源的操作权限(如 create、get、list 等)。
- 创建一个 RoleBinding,将 Role 绑定到用户 user-test。
2.3.9.Switch Context
sh
vim ~/.kube/config
contexts:
- context:
cluster: kubernetes
user: kubernetes-admin
name: kubernetes-admin@kubernetes
- context:
cluster: kubernetes
user: user-test
name: kubernetes-user-test@kubernetes
current-context: kubernetes-user-test@kubernetes
- 作用: 添加新的context,并使用
- 解释:
- 修改~/.kube/config,添加新的context,并使用
2.3.10.Get pod
sh
# 如果已经切换上下文,可以直接执行
kubectl get pods
# 如果没有切换上下文,可以使用
kubectl get pods --user=user-test
- 作用:测试用户权限。
- 解释:
- 使用 kubectl get pods 命令,验证用户 user-test 是否能够访问 pods 资源。