Kubernetes控制平面组件:APIServer 基于 X509 证书的认证机制

云原生学习路线导航页(持续更新中)

本文主要对kubernetes API Server 认证机制中的 X509 认证进行介绍,包括 X509证书 的设计理念、实现原理、认证流程,以及在 Kubernetes 中的具体应用

2.基于 X509 证书的认证方式

2.1.X509认证方式简介

  • X509 是什么

    • X509认证是一种基于 SSL/TLS 证书的身份验证机制,广泛应用于 Kubernetes 等分布式系统中,用于确保通信双方的身份合法性。
  • 核心概念

    • 证书(Certificate) :由可信的证书颁发机构(CA)签发的数字文件,包含公钥和身份信息
    • 私钥(Private Key):与证书中的公钥配对的私钥,用于解密和签名。
    • CA(Certificate Authority):证书颁发机构,负责签发和管理证书。
  • 工作原理

    1. 证书签发
      • 客户端和服务端分别向 CA 申请证书。
      • CA 验证身份后签发证书,证书中包含公钥和身份信息。
    2. 双向认证
      • 客户端和服务端在建立连接时,会交换彼此的证书。
      • 双方使用 CA 的公钥验证对方证书的合法性。
    3. 加密通信
      • 验证通过后,双方使用证书中的公钥加密通信数据,确保数据的安全性。
  • 优点

    • 安全性高:基于非对称加密,确保通信数据的机密性和完整性。
    • 身份验证可靠:通过 CA 签发的证书,确保通信双方的身份合法性。
    • 广泛支持:X509 是行业标准,兼容性高。
  • 缺点

    • 管理复杂:证书的签发、更新和吊销需要额外的管理工作。
    • 性能开销:加密和解密操作会带来一定的性能损耗。

2.2.X509 在 Kubernetes 中的应用

2.2.1.查看 Kubernetes 的证书配置

  • 在 Kubernetes 中,X509 认证通常用于以下场景:
    • API Server 认证 :客户端(如 kubectl)使用 X509 证书向 API Server 证明身份。
    • 组件间通信 :Kubernetes 各组件(如 kubeletschedulercontroller-manager)之间使用 X509 证书进行安全通信。
  • 查看kubernetes的证书配置
    • kubernetes的默认证书都放在 /etc/kubernetes/pki 下面
    • ca.crtca.key
      • 集群的根证书和私钥。它相当于一个权威机构,集群其他组件的证书都由这个CA签发
      • CA的私钥必须严格保护,因为泄露会导致整个集群的安全体系崩溃。
    • apiserver.crtapiserver.key
      • 这是Kubernetes API Server的证书和私钥,由kubernetes的ca.crt签发,用于HTTPS通信。
      • apiserver.crt 证书用于让访问API Server的客户端验证服务器身份,确保客户端连接的是合法的API Server。其中的公钥也可以让 客户端进行数据的加密。
      • apiserver.key:API Server的私钥,对客户端使用公钥加密后的数据,进行解密。非对称加密
    • apiserver-etcd-client.crtapiserver-etcd-client.key
      • API Server作为客户端访问etcd时的证书和私钥
    • apiserver-kubelet-client.crtapiserver-kubelet-client.key
      • API Server作为客户端与kubelet通信时的证书。
      • crt证书用于让 Kubelet 验证 API Server 的身份,确保kubelet只接受来自合法API Server的请求
    • sa.keysa.pub
      • Service Account的密钥对,用于签署Service Account的令牌。Kubernetes使用这些密钥来验证Pod的Service Account,确保Pod的身份合法。
    • 其他的不一一介绍了

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 资源。
相关推荐
谷隐凡二8 小时前
Kubernetes主从架构简单解析:基于Python的模拟实现
python·架构·kubernetes
陈陈CHENCHEN8 小时前
SuperMap iManager for K8s 离线环境镜像仓库 Containerd 部署
kubernetes
会飞的小蛮猪11 小时前
Ubuntu24.04 基于Containerd部署K8s1.34(私服部署)
docker·云原生·kubernetes
间彧1 天前
Kubernetes滚动发布详解
kubernetes
间彧1 天前
在实际生产环境中,Kubernetes声明式API如何实现蓝绿部署、金丝雀发布等高级部署策略?
kubernetes
间彧1 天前
Kubernetes声明式API相比传统命令式API在故障恢复场景下的具体优势有哪些?
kubernetes·github
间彧1 天前
为什么说Kubernetes的API设计是其成功的关键因素之一?
kubernetes
间彧1 天前
Kubernetes Deployment 配置简化实战:从复杂到高效
kubernetes
可爱的小小小狼1 天前
k8s:服务网格Service Mesh(服务网格)istio和envoy
kubernetes·istio·service_mesh
YFLICKERH1 天前
【加密协议】SSL/TLS 协议工作流程
网络协议·ssl/tls