认证
开启 TLS 时,所有的请求都需要首先认证。Kubernetes 支持多种认证机制,并支持同时开启多个认证插件(只要有一个认证通过即可)。如果认证成功,则用户的 username 会传入授权模块做进一步授权验证;而对于认证失败的请求则返回 HTTP 401。
Kubernetes 不直接管理用户
虽然 Kubernetes 认证和授权用到了 user 和 group,但 Kubernetes 并不直接管理用户,不能创建
user对象,也不存储 user。
目前,Kubernetes 支持以下认证插件:
- X509 证书 
- 静态 Token 文件 
- 引导 Token 
- 静态密码文件 
- Service Account 
- OpenID 
- Webhook 
- 认证代理 
- OpenStack Keystone 密码 
X509 证书
使用 X509 客户端证书只需要 API Server 启动时配置 --client-ca-file=SOMEFILE。在证书认证时,其 Common Name(CN)域用作用户名,而 Organization(O)域则用作 group 名。
创建一个客户端证书的方法为:
# Create private key
openssl genrsa -out username.key 2048
# Create CSR (certificate signing request)
openssl req -new -key username.key -out username.csr -subj "/CN=username/O=group"
# Create certificate from CSR using the cluster authority
openssl x509 -req -in username.csr -CA $CA_LOCATION/ca.crt -CAkey $CA_LOCATION/ca.key -CAcreateserial -out username.crt -days 500接着,就可以使用 username.key 和 username.crt 来访问集群:
# Config cluster
kubectl config set-cluster my-cluster --certificate-authority=ca.pem --embed-certs=true --server=https://<APISERVER_IP>:6443
# Config credentials
kubectl config set-credentials username --client-certificate=username.crt --client-key=username.key --embed-certs=true
# Config context
kubectl config set-context username --cluster=my-cluster --user=username
# Config RBAC if it's enabled
# Finally, switch to new context
kubectl config use-context username静态 Token 文件
使用静态 Token 文件认证只需要 API Server 启动时配置 --token-auth-file=SOMEFILE。该文件为 csv 格式,每行至少包括三列 token,username,user id,后面是可选的 group 名,比如
token,user,uid,"group1,group2,group3"客户端在使用 token 认证时,需要在请求头中加入 Bearer Authorization 头,比如
Authorization: Bearer 31ada4fd-adec-460c-809a-9e56ceb75269引导 Token
引导 Token 是动态生成的,存储在 kube-system namespace 的 Secret 中,用来部署新的 Kubernetes 集群。
使用引导 Token 需要 API Server 启动时配置 --experimental-bootstrap-token-auth,并且 Controller Manager 开启 TokenCleaner --controllers=*,tokencleaner,bootstrapsigner。
在使用 kubeadm 部署 Kubernetes 时,kubeadm 会自动创建默认 token,可通过 kubeadm token list 命令查询。
静态密码文件
需要 API Server 启动时配置 --basic-auth-file=SOMEFILE,文件格式为 csv,每行至少三列 password, user, uid,后面是可选的 group 名,如
password,user,uid,"group1,group2,group3"客户端在使用密码认证时,需要在请求头重加入 Basic Authorization 头,如
Authorization: Basic BASE64ENCODED(USER:PASSWORD)Service Account
ServiceAccount 是 Kubernetes 自动生成的,并会自动挂载到容器的 /var/run/secrets/kubernetes.io/serviceaccount 目录中。
在认证时,ServiceAccount 的用户名格式为 system:serviceaccount:(NAMESPACE):(SERVICEACCOUNT),并从属于两个 group:system:serviceaccounts 和 system:serviceaccounts:(NAMESPACE)。
OpenID
OpenID 提供了 OAuth2 的认证机制,是很多云服务商(如 GCE、Azure 等)的首选认证方法。

使用 OpenID 认证,API Server 需要配置
- --oidc-issuer-url,如- https://accounts.google.com
- --oidc-client-id,如- kubernetes
- --oidc-username-claim,如- sub
- --oidc-groups-claim,如- groups
- --oidc-ca-file,如- /etc/kubernetes/ssl/kc-ca.pem
Webhook
API Server 需要配置
# 配置如何访问 webhook server
--authentication-token-webhook-config-file
# 默认 2 分钟
--authentication-token-webhook-cache-ttl配置文件格式为
# clusters refers to the remote service.
clusters:
  - name: name-of-remote-authn-service
    cluster:
      # CA for verifying the remote service.
      certificate-authority: /path/to/ca.pem
      # URL of remote service to query. Must use 'https'.
      server: https://authn.example.com/authenticate
# users refers to the API server's webhook configuration.
users:
  - name: name-of-api-server
    user:
      # cert for the webhook plugin to use
      client-certificate: /path/to/cert.pem
       # key matching the cert
      client-key: /path/to/key.pem
# kubeconfig files require a context. Provide one for the API server.
current-context: webhook
contexts:
- context:
    cluster: name-of-remote-authn-service
    user: name-of-api-sever
  name: webhookKubernetes 发给 webhook server 的请求格式为
{
  "apiVersion": "authentication.k8s.io/v1beta1",
  "kind": "TokenReview",
  "spec": {
    "token": "(BEARERTOKEN)"
  }
}示例:kubernetes-github-authn 实现了一个基于 WebHook 的 github 认证。
认证代理
API Server 需要配置
--requestheader-username-headers=X-Remote-User
--requestheader-group-headers=X-Remote-Group
--requestheader-extra-headers-prefix=X-Remote-Extra-
# 为了防止头部欺骗,证书是必选项
--requestheader-client-ca-file
# 设置允许的 CN 列表。可选。
--requestheader-allowed-namesOpenStack Keystone 密码
需要 API Server 在启动时指定 --experimental-keystone-url=<AuthURL>,而 https 时还需要设置 --experimental-keystone-ca-file=SOMEFILE。
不支持 Keystone v3
目前只支持 keystone v2.0,不支持 v3(无法传入 domain)。
匿名请求
如果使用 AlwaysAllow 以外的认证模式,则匿名请求默认开启,但可用 --anonymous-auth=false 禁止匿名请求。
匿名请求的用户名格式为 system:anonymous,而 group 则为 system:unauthenticated。
Kubelet 凭证提供程序的服务账户令牌(v1.33 Alpha)
从 Kubernetes v1.33 开始,引入了 Service Account Token Integration for Kubelet Credential Providers 这一 Alpha 特性,允许 kubelet 凭证提供程序使用 Pod 的服务账户令牌来获取镜像拉取凭证,从而实现工作负载级别的镜像访问控制。
工作原理
当启用此特性后:
- 令牌生成:Kubelet 为 Pod 生成短期、自动轮换的服务账户令牌 
- 令牌传递:这些令牌通过 - CredentialProviderRequest传递给凭证提供程序
- 凭证交换:凭证提供程序使用服务账户令牌向镜像仓库(如 AWS ECR、GCP Artifact Registry、Azure ACR)交换临时的镜像拉取凭证 
- 镜像拉取:Kubelet 使用获得的临时凭证代表 Pod 拉取镜像 
配置方法
- 启用特性门控: - kubelet --feature-gates=ServiceAccountTokenForKubeletCredentialProviders=true
- 配置凭证提供程序: 在凭证提供程序配置中设置 - tokenAttributes字段以选择接收服务账户令牌:- apiVersion: kubelet.config.k8s.io/v1 kind: CredentialProviderConfig providers: - name: my-provider tokenAttributes: audience: "https://my-registry.example.com" expirationSeconds: 3600
- Pod 配置: Pod 使用服务账户,kubelet 会自动为其生成令牌用于镜像拉取: - apiVersion: v1 kind: Pod metadata: name: my-app spec: serviceAccountName: my-app-sa containers: - name: app image: my-registry.example.com/app:v1
优势
- 消除长期密钥:不再需要在集群中存储长期有效的镜像拉取密钥 
- 工作负载隔离:每个 Pod 使用自己的服务账户令牌,实现细粒度的访问控制 
- 自动轮换:令牌自动过期和轮换,提高安全性 
- 与云原生集成:可以与云提供商的 IAM 系统无缝集成 
这一特性预计在 Kubernetes v1.34 中升级为 Beta 版本。更多信息请参考 KEP-4412。
Credential Plugin
从 v1.11 开始支持 Credential Plugin(Beta),通过调用外部插件来获取用户的访问凭证。这是一种客户端认证插件,用来支持不在 Kubernetes 中内置的认证协议,如 LDAP、OAuth2、SAML 等。它通常与 Webhook 配合使用。
Credential Plugin 可以在 kubectl 的配置文件中设置,比如
apiVersion: v1
kind: Config
users:
- name: my-user
  user:
    exec:
      # Command to execute. Required.
      command: "example-client-go-exec-plugin"
      # API version to use when decoding the ExecCredentials resource. Required.
      #
      # The API version returned by the plugin MUST match the version listed here.
      #
      # To integrate with tools that support multiple versions (such as client.authentication.k8s.io/v1alpha1),
      # set an environment variable or pass an argument to the tool that indicates which version the exec plugin expects.
      apiVersion: "client.authentication.k8s.io/v1beta1"
      # Environment variables to set when executing the plugin. Optional.
      env:
      - name: "FOO"
        value: "bar"
      # Arguments to pass when executing the plugin. Optional.
      args:
      - "arg1"
      - "arg2"
clusters:
- name: my-cluster
  cluster:
    server: "https://172.17.4.100:6443"
    certificate-authority: "/etc/kubernetes/ca.pem"
contexts:
- name: my-cluster
  context:
    cluster: my-cluster
    user: my-user
current-context: my-cluster具体的插件开发及使用方法请参考 kubernetes/client-go。
开源工具
如下的开源工具可以帮你简化认证和授权的配置:
参考资料
- Protect Kubernetes External Endpoints with OAuth2 Proxy by Alen Komljen 
- Single Sign-On for Internal Apps in Kubernetes using Google Oauth / SSO by William Broach 
- Single Sign-On for Kubernetes: An Introduction by Joel Speed 
- Let’s Encrypt, OAuth 2, and Kubernetes Ingress by Ian Chiles 
- Comparing Kubernetes Authentication Methods by Etienne Dilocker 
- Effective RBAC by Jordan Liggitt 
- Configure RBAC In Your Kubernetes Cluster via Bitnami 
- Using RBAC, Generally Available in Kubernetes v1.8 by Eric Chiang 
最后更新于
