管理服务账号

这是一篇针对服务账号的集群管理员指南。你应该熟悉 配置 Kubernetes 服务账号

对鉴权和用户账号的支持已在规划中,当前并不完备。 为了更好地描述服务账号,有时这些不完善的特性也会被提及。

用户账号与服务账号

Kubernetes 区分用户账号和服务账号的概念,主要基于以下原因:

  • 用户账号是针对人而言的。而服务账号是针对运行在 Pod 中的进程而言的。
  • 用户账号是全局性的。其名称在某集群中的所有名字空间中必须是唯一的。服务账号是名字空间作用域的。
  • 通常情况下,集群的用户账号可能会从企业数据库进行同步,其创建需要特殊权限, 并且涉及到复杂的业务流程。 服务账号创建有意做得更轻量,允许集群用户为了具体的任务创建服务账号以遵从权限最小化原则。
  • 对人员和服务账号审计所考虑的因素可能不同。
  • 针对复杂系统的配置包可能包含系统组件相关的各种服务账号的定义。 因为服务账号的创建约束不多并且有名字空间域的名称,这种配置是很轻量的。

服务账号的自动化

以下三个独立组件协作完成服务账号相关的自动化:

  • ServiceAccount 准入控制器
  • Token 控制器
  • ServiceAccount 控制器

ServiceAccount 准入控制器

对 Pod 的改动通过一个被称为 准入控制器 的插件来实现。它是 API 服务器的一部分。 当 Pod 被创建或更新时,它会同步地修改 Pod。 如果该插件处于激活状态(在大多数发行版中都是默认激活的), 当 Pod 被创建或更新时它会进行以下操作:

  1. 如果该 Pod 没有设置 ServiceAccount,将其 ServiceAccount 设为 default
  2. 保证 Pod 所引用的 ServiceAccount 确实存在,否则拒绝该 Pod。
  3. 如果服务账号的 automountServiceAccountToken 或 Pod 的 automountServiceAccountToken 都未显式设置为 false,则为 Pod 创建一个 volume,在其中包含用来访问 API 的令牌。
  4. 如果前一步中为服务账号令牌创建了卷,则为 Pod 中的每个容器添加一个 volumeSource,挂载在其 /var/run/secrets/kubernetes.io/serviceaccount 目录下。
  5. 如果 Pod 不包含 imagePullSecrets 设置,将 ServiceAccount 所引用的服务账号中的 imagePullSecrets 信息添加到 Pod 中。

绑定的服务账号令牌卷

特性状态: Kubernetes v1.22 [stable]

ServiceAccount 准入控制器将添加如下投射卷, 而不是为令牌控制器所生成的不过期的服务账号令牌而创建的基于 Secret 的卷。

- name: kube-api-access-<随机后缀>
  projected:
    defaultMode: 420 # 0644
    sources:
      - serviceAccountToken:
          expirationSeconds: 3607
          path: token
      - configMap:
          items:
            - key: ca.crt
              path: ca.crt
          name: kube-root-ca.crt
      - downwardAPI:
          items:
            - fieldRef:
                apiVersion: v1
                fieldPath: metadata.namespace
              path: namespace

此投射卷有三个数据源:

  1. 通过 TokenRequest API 从 kube-apiserver 处获得的 ServiceAccountToken。 这一令牌默认会在一个小时之后或者 Pod 被删除时过期。 该令牌绑定到 Pod 实例上,并将 kube-apiserver 作为其受众(audience)。
  2. 包含用来验证与 kube-apiserver 连接的 CA 证书包的 ConfigMap 对象。 这一特性依赖于 RootCAConfigMap 特性门控。该特性被启用时, 控制面会公开一个名为 kube-root-ca.crt 的 ConfigMap 给所有名字空间。 RootCAConfigMap 在 1.21 版本中进入 GA 状态,默认被启用, 该特性门控会在 1.22 版本中从 --feature-gate 参数中删除。
  3. 引用 Pod 名字空间的一个 DownwardAPI。

参阅投射卷 了解进一步的细节。

Token 控制器

TokenController 作为 kube-controller-manager 的一部分运行,以异步的形式工作。 其职责包括:

  • 监测 ServiceAccount 的创建并创建相应的服务账号令牌 Secret 以允许访问 API。
  • 监测 ServiceAccount 的删除并删除所有相应的服务账号令牌 Secret。
  • 监测服务账号令牌 Secret 的添加,保证相应的 ServiceAccount 存在,如有需要, 向 Secret 中添加令牌。
  • 监测服务账号令牌 Secret 的删除,如有需要,从相应的 ServiceAccount 中移除引用。

你必须通过 --service-account-private-key-file 标志为 kube-controller-manager 的令牌控制器传入一个服务账号私钥文件。该私钥用于为所生成的服务账号令牌签名。 同样地,你需要通过 --service-account-key-file 标志将对应的公钥通知给 kube-apiserver。公钥用于在身份认证过程中校验令牌。

创建额外的 API 令牌

控制器中有专门的循环来保证每个 ServiceAccount 都存在对应的包含 API 令牌的 Secret。 当需要为 ServiceAccount 创建额外的 API 令牌时,可以创建一个类型为 kubernetes.io/service-account-token 的 Secret,并在其注解中引用对应的 ServiceAccount。控制器会生成令牌并更新该 Secret:

下面是这种 Secret 的一个示例配置:

apiVersion: v1
kind: Secret
metadata:
  name: mysecretname
  annotations:
    kubernetes.io/service-account.name: myserviceaccount
type: kubernetes.io/service-account-token
kubectl create -f ./secret.yaml
kubectl describe secret mysecretname

删除/废止服务账号令牌 Secret

kubectl delete secret mysecretname

服务账号控制器

服务账号控制器管理各名字空间下的 ServiceAccount 对象, 并且保证每个活跃的名字空间下存在一个名为 "default" 的 ServiceAccount。