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 资源。
相关推荐
木二32 分钟前
附039.Kubernetes_v1.32.2高可用部署架构二
kubernetes·ingress·kubernetes dashboard·longhorn
行者Sun19892 小时前
【K8s】专题十六(2):Kubernetes 包管理工具之 Helm 使用
云原生·容器·kubernetes·helm
格桑阿sir3 小时前
Kubernetes控制平面组件:API Server RBAC授权机制 详解
kubernetes·云计算·rbac·授权·authorization·apiserver·鉴权机制
土豆沒加20 小时前
ubuntu22.04使用minikube安装k8s
云原生·容器·kubernetes
猫吃了源码21 小时前
KubeKey一键安装部署k8s集群和KubeSphere详细教程
云原生·容器·kubernetes
你可以叫我仔哥呀21 小时前
k8s学习记录:环境搭建(基于Kubeadmin)
学习·容器·kubernetes
Karoku0661 天前
【CI/CD】CI/CD环境搭建流程和持续集成环境配置
运维·ci/cd·docker·容器·kubernetes·prometheus
Bright16682 天前
centos9安装k8s集群
云原生·容器·kubernetes
xidianjiapei0012 天前
Kubernetes的Ingress 资源是什么?
云原生·容器·kubernetes