Kubernetes 用户认证全解析:用户类型与 kubeconfig 配置指南

6 阅读8分钟

引言

在 Kubernetes 中,集群访问权限的管理方式与传统系统截然不同:它没有内置的用户数据库,而是通过一系列灵活的认证机制来识别访问者身份。无论是开发者、运维人员还是 CI/CD 流水线,都需要通过恰当的认证方式证明自己是谁,才能与集群交互。本文将深入解析 Kubernetes 中的用户类型、认证方式以及如何通过 kubeconfig 文件高效管理多集群访问,帮助构建安全可控的集群访问体系。

Kubernetes 用户认证体系概览

API Server内置的访问控制机制

  • 认证(Authentication):

    • 核验请求者身份的合法性,进行身份识别,验证客户端身份。
    • 身份核验过程遵循“或”逻辑,且任何一个插件核验成功后都将不再进行后续的插件验证。
    • 均不成功,则失败,或以“匿名者”身份访问,建议禁用“匿名者”。
  • 授权(Authorization):

    • 核验请求的操作是否获得许可,验证客户端是否有权限操作资源对象。
    • 鉴权过程遵循“或”逻辑,且任何一个插件对操作的许可授权后都将不再进行后续的插件验证。
    • 均未许可,则拒绝请求的操作
  • 准入控制(Admission Control):

    • 检查操作内容是否合规,仅同"写"请求相关,负责实现"检验"字段类型是否合法及和补全默认字段。
    • 内容合规性检查过程遵循“与”逻辑,且无论成败,每次的操作请求都要经由所有插件的检验。
    • 将数据写入etcd前,负责检查内容的有效性,因此仅对“写”操作有效。
    • 分两类:validating(校验)和 mutating(补全或订正)。

身份认证策略

  • X.509客户端证书认证

    • 在双向TLS通信中,客户端持有数字证书信任的CA,需要在kube-apiserver程序启动时,通过--client-ca-file选项传递。
    • 认证通过后,客户端数字证书中的CN(Common Name)即被识别为用户名,而O(Organization)被识别为组名。
    • kubeadm部署的K8s集群,默认使用"/etc/kubernetes/pki/ca.crt"(各组件间颁发数字证书的CA)进行客户端认证。
  • 持有者令牌(token)

    • 静态令牌文件(Static Token File)

      • 令牌信息保存于文本文件中,由kube-apiserver在启动时通过--token-auth-file选项加载。
      • 加载完成后的文件变动,仅能通过重启程序进行重载,因此,相关的令牌会长期有效。
      • 客户端在HTTP请求中,通过“Authorization: Bearer TOKEN”标头附带令牌令牌以完成认证。
    • Bootstrap令牌

      • 一般用于加入集群时使用,尤其是在集群的扩容场景时会用到。
    • Service Account令牌

      • 该认证方式将由kube-apiserver程序内置直接启用,它借助于经过签名的Bearer Token来验证请求。
      • 签名时使用的密钥可以由--service-account-key-file选项指定,也可以默认使用API Server的tls私钥
      • 用于将Pod认证到API Server之上,以支持集群内的进程与API Server通信。
      • K8s可使用ServiceAccount准入控制器自动为Pod关联ServiceAccount。
    • OIDC(OpenID Connect)令牌

      • 有点类似于"微信","支付宝"认证的逻辑,自建的话需要配置认证中心。
      • OAuth2认证机制,通常由底层的IaaS服务所提供。
    • Webhook令牌

      • 基于web的形式进行认证,比如之前配置的"钉钉机器人","微信机器人"等;
      • 是一种用于验证Bearer Token的回调机制,能够扩展支持外部的认证服务,例如LDAP等。
  • 身份认证代理(Authenticating Proxy)

    • 由kube-apiserver从请求报文的特定HTTP标头中识别用户身份,相应的标头名称可由特定的选项配置指定。
    • kube-apiserver应该基于专用的CA来验证代理服务器身份。
  • 匿名请求

    • 生产环境中建议禁用匿名认证。

Kubernetes 用户

k8s用户概念

  • “用户”即服务请求者的身份指代,一般使用身份标识符进行识别,比如用户名,用户组,服务账号,匿名用户等。
  • 与普通系统不同,Kubernetes 没有存储用户信息的内置对象,而是通过外部认证机制来识别用户。

k8s用户类型

User Account

  • 用户账户,指非Pod类的客户端访问API Server时使用的身份标识,一般是现实中的"人"。

  • API Server没有为这类账户提供保存其信息的资源类型,相关的信息通常保存于外部的文件(特指"kubeconfig"文件)或认证系统中。

  • 身份核验操作可由API Server进行,也可能是由外部身份认证服务完成。

  • 可以手动定义证书,其中O字段表示组,CN字段表示用户名。

  • 典型认证方式

     # 通过X509客户端证书认证
     kubectl --client-certificate=./user.crt --client-key=./user.key get pods
     ​
     # 通过Bearer Token认证
     kubectl --token="eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9..." get pods
    

Service Account

  • 服务账户,Kubernetes内置的资源类型,用于Pod内的进程访问API Server时使用的身份信息。

  • 引用格式: "system:serviceaccount:NAMESPACE:SA_NAME"

  • 创建和使用示例

     # 创建 ServiceAccount
     apiVersion: v1
     kind: ServiceAccount
     metadata:
       name: my-app-sa
       namespace: default
       
       
     # 在 Pod 中使用 ServiceAccount
     apiVersion: v1
     kind: Pod
     metadata:
       name: my-pod
     spec:
       serviceAccountName: my-app-sa
       containers:
       - name: my-container
         image: nginx
    
  • 查看 ServiceAccount 的认证令牌

     # 获取默认的 ServiceAccount token
     kubectl get secret $(kubectl get serviceaccount default -o jsonpath='{.secrets[0].name}') -o jsonpath='{.data.token}' | base64 -d
     
     # 创建一个新的 ServiceAccount 并获取其 token
     kubectl create serviceaccount my-sa
     kubectl apply -f - <<EOF
     apiVersion: v1
     kind: Secret
     metadata:
       name: my-sa-token
       annotations:
         kubernetes.io/service-account.name: my-sa
     type: kubernetes.io/service-account-token
     EOF
    

Anonymous Account

  • 匿名账户,不能被识别为Service Account,也不能被识别为User Account的用户。
  • 这类账户K8S系统称之为"system:anonymous",即“匿名用户”。

深入kubeconfig 文件

kubeconfig概述

  • kubeconfig是YAML格式的文件,用于存储身份认证信息,以便于客户端加载并认证到API Server。
  • kubeconfig保存有认证到一至多个Kubernetes集群的相关配置信息,并允许管理员按需在各配置间灵活切换

kubeconfig的组成

  • clusters

    • Kubernetes集群访问端点(API Server)列表。可以定义多个K8S集群列表
  • users

    • 认证到API Server的身份凭据列表。可以定义多个用户列表,这个用户可以是token,或者x509证书凭据
  • contexts

    • 将每一个user与可认证到的cluster建立关联的上下文列表
    • 可以将多个用户和对应的集群进行关联,将来使用哪个用户,就会去关联的集群进行访问认证。也可以定义多个上下文的关系
  • current-context

    • 当前默认使用的context

kubeconfig示例

 apiVersion: v1
 kind: Config
 
 # 1. 集群配置 (clusters)
 clusters:
 - name: production-cluster
   cluster:
     certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t...
     #k8s集群API-server地址
     server: https://10.0.0.51:6443
 
 # 2. 用户凭证 (users)
 users:
 - name: alice
   user:
     client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t...
     client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQ...
 
 # 3. 上下文配置 (contexts)
 contexts:
 - name: prod-alice-context
   context:
     cluster: production-cluster
     user: alice
     namespace: production
 
 # 4. 当前上下文
 current-context: prod-alice-context

多集群环境配置示例

 apiVersion: v1
 kind: Config
 
 clusters:
 - name: development-cluster
   cluster:
     certificate-authority: /path/to/dev-ca.crt
     server: https://dev.example.com:6443
 - name: production-cluster
   cluster:
     insecure-skip-tls-verify: true  # 仅测试环境使用
     server: https://prod.example.com:6443
 
 users:
 - name: developer
   user:
     client-certificate: /path/to/dev-user.crt
     client-key: /path/to/dev-user.key
 - name: admin
   user:
     token: eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9...
 
 contexts:
 - name: dev-context
   context:
     cluster: development-cluster
     user: developer
     namespace: dev-namespace
 - name: prod-context
   context:
     cluster: production-cluster
     user: admin
     namespace: production
 
 current-context: dev-context

常用kubeconfig命令

 # 查看当前配置
 kubectl config view
 ​
 # 查看特定上下文配置
 #打印kubeconfig信息,默认会使用“REDACTED”或者“DATA+OMITTED”关键字隐藏证书信息
 kubectl config view --minify --context=prod-context
 ​
 # 切换当前上下文
 kubectl config use-context prod-context
 ​
 # 添加新集群配置
 kubectl config set-cluster new-cluster \
   --server=https://new.example.com:6443 \
   --certificate-authority=/path/to/ca.crt
 ​
 # 添加用户凭证
 kubectl config set-credentials new-user \
   --client-certificate=/path/to/client.crt \
   --client-key=/path/to/client.key
 ​
 # 添加上下文
 kubectl config set-context new-context \
   --cluster=new-cluster \
   --user=new-user \
   --namespace=default
 ​
 # 重命名上下文
 kubectl config rename-context old-name new-name
 ​
 # 删除配置项
 kubectl config delete-context unwanted-context
 kubectl config delete-cluster old-cluster
 kubectl config delete-credentials old-user

kubectl加载kubeconfig文件的优先级

  1. 使用--kubeconfig的优先级最大,直接无视之后的两个配置文件
  2. 使用KUBECONFIG变量的优先级次之
  3. 使用默认的"~/.kube/config"最后加载

创建一个用户并授权

1.为 Alice 生成证书签发请求私钥和证书签发请求

 #csr:证书签发请求  
 #-out 指定证书签发请求csr  基于alice.key这个私钥签发
 #指定的用户名CN是alice  组织O 为developers
 [root@worker51 ~]# openssl genrsa -out alice.key 2048
 [root@worker51 ~]# openssl req -new -key alice.key -out alice.csr -subj "/CN=alice/O=developers"
 [root@worker51 ~]# ll alice*
 -rw-r--r-- 1 root root  911 Jan 24 10:43 alice.csr
 -rw------- 1 root root 1704 Jan 24 10:43 alice.key

2.使用集群的 CA 签署证书

 openssl x509 -req -in alice.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out alice.crt -days 365

3.为 Alice 配置 kubeconfig

 # --embed-certs=true 是否拷贝证书 是
 kubectl config set-credentials alice \
     --client-certificate=alice.crt \
     --client-key=alice.key \
     --embed-certs=true
 kubectl config set-context alice-context \
     --cluster=your-cluster-name \
     --user=alice
 kubectl config use-context alice-context

4.为 Alice 配置权限(RBAC)

现在用户 alice 可以访问集群了,但默认没有任何权限。需创建一个 RoleRoleBinding 来授权。

 # 创建一个角色,例如允许在 default 命名空间查看 pods
 apiVersion: rbac.authorization.k8s.io/v1
 kind: Rolex
 metadata:
   namespace: default
   name: pod-viewer
 rules:
 - apiGroups: [""]
   resources: ["pods"]
   verbs: ["get", "list", "watch"]
 ---
 # 将角色绑定给用户 alice
 apiVersion: rbac.authorization.k8s.io/v1
 kind: RoleBinding
 metadata:
   namespace: default
   name: view-pods-to-alice
 subjects:
 - kind: User
   name: alice # 这里的名字必须与证书中的 CN 完全一致
   apiGroup: rbac.authorization.k8s.io
 roleRef:
   kind: Role
   name: pod-viewer
   apiGroup: rbac.authorization.k8s.io