为 Pod 配置服务账户

服务账户为 Pod 中运行的进程提供了一个标识。

本文是服务账户的用户使用介绍。您也可以参考集群管理指南之服务账户

注意:

本文档描述 Kubernetes 项目推荐的集群中服务帐户的行为。 集群管理员也可能已经定制了服务账户在集群中的属性,在这种情况下,本文档可能并不适用。

当您(人类)访问集群时(例如,使用 kubectl),api 服务器将您的身份验证为特定的用户帐户(当前这通常是 admin,除非您的集群管理员已经定制了您的集群配置)。 Pod 内的容器中的进程也可以与 api 服务器接触。 当它们进行身份验证时,它们被验证为特定的服务帐户(例如,default)。

准备开始

你必须拥有一个 Kubernetes 的集群,同时你的 Kubernetes 集群必须带有 kubectl 命令行工具。 如果你还没有集群,你可以通过 Minikube 构建一 个你自己的集群,或者你可以使用下面任意一个 Kubernetes 工具构建:

要获知版本信息,请输入 kubectl version.

使用默认的服务账户访问 API 服务器

当您创建 Pod 时,如果没有指定服务账户,Pod 会被指定命名空间中的default服务账户。 如果您查看 Pod 的原始 json 或 yaml(例如:kubectl get pods/podname -o yaml), 您可以看到 spec.serviceAccountName 字段已经被自动设置了。

您可以使用自动挂载给 Pod 的服务账户凭据访问 API,访问集群 中有相关描述。 服务账户的 API 许可取决于您所使用的授权插件和策略

在 1.6 以上版本中,您可以通过在服务账户上设置 automountServiceAccountToken: false 来实现不给服务账号自动挂载 API 凭据:

  1. apiVersion: v1
  2. kind: ServiceAccount
  3. metadata:
  4. name: build-robot
  5. automountServiceAccountToken: false
  6. ...

在 1.6 以上版本中,您也可以选择不给特定 Pod 自动挂载 API 凭据:

  1. apiVersion: v1
  2. kind: Pod
  3. metadata:
  4. name: my-pod
  5. spec:
  6. serviceAccountName: build-robot
  7. automountServiceAccountToken: false
  8. ...

如果 Pod 和服务账户都指定了 automountServiceAccountToken 值,则 Pod 的 spec 优先于服务帐户。

使用多个服务账户

每个命名空间都有一个名为 default 的服务账户资源。 您可以用下面的命令查询这个服务账户以及命名空间中的其他 serviceAccount 资源:

  1. kubectl get serviceAccounts
  2. NAME SECRETS AGE
  3. default 1 1d

您可以像这样来创建额外的 ServiceAccount 对象:

  1. kubectl create -f - <<EOF
  2. apiVersion: v1
  3. kind: ServiceAccount
  4. metadata:
  5. name: build-robot
  6. EOF
  7. serviceaccount/build-robot created

如果您查询服务帐户对象的完整信息,如下所示:

  1. kubectl get serviceaccounts/build-robot -o yaml
  2. apiVersion: v1
  3. kind: ServiceAccount
  4. metadata:
  5. creationTimestamp: 2015-06-16T00:12:59Z
  6. name: build-robot
  7. namespace: default
  8. resourceVersion: "272500"
  9. uid: 721ab723-13bc-11e5-aec2-42010af0021e
  10. secrets:
  11. - name: build-robot-token-bvbk5

那么您就能看到系统已经自动创建了一个令牌并且被服务账户所引用。

您可以使用授权插件来 设置服务账户的访问许可

要使用非默认的服务账户,只需简单的将 Pod 的 spec.serviceAccountName 字段设置为您想用的服务账户名称。

Pod 被创建时服务账户必须存在,否则会被拒绝。

您不能更新已经创建好的 Pod 的服务账户。

您可以清除服务账户,如下所示:

  1. kubectl delete serviceaccount/build-robot

手动创建服务账户 API 令牌

假设我们有一个上面提到的名为 “build-robot” 的服务账户,然后我们手动创建一个新的 Secret。

  1. kubectl create -f - <<EOF
  2. apiVersion: v1
  3. kind: Secret
  4. metadata:
  5. name: build-robot-secret
  6. annotations:
  7. kubernetes.io/service-account.name: build-robot
  8. type: kubernetes.io/service-account-token
  9. EOF
  10. secret/build-robot-secret created

现在,您可以确认新构建的 Secret 中填充了 “build-robot” 服务帐户的 API 令牌。

令牌控制器将清理不存在的服务帐户的所有令牌。

  1. kubectl describe secrets/build-robot-secret
  2. Name: build-robot-secret
  3. Namespace: default
  4. Labels: <none>
  5. Annotations: kubernetes.io/service-account.name=build-robot
  6. kubernetes.io/service-account.uid=da68f9c6-9d26-11e7-b84e-002dc52800da
  7. Type: kubernetes.io/service-account-token
  8. Data
  9. ====
  10. ca.crt: 1338 bytes
  11. namespace: 7 bytes
  12. token: ...

注意:

这里省略了 token 的内容。

为服务账户添加 ImagePullSecrets

首先,创建一个 ImagePullSecrets,可以参考这里 的描述。 然后,确认创建是否成功。例如:

  1. kubectl get secrets myregistrykey
  2. NAME TYPE DATA AGE
  3. myregistrykey kubernetes.io/.dockerconfigjson 1 1d

接着修改命名空间的默认服务帐户,以将该 Secret 用作 imagePullSecret。

  1. kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "myregistrykey"}]}'

需要手动编辑的交互式版本:

  1. kubectl get serviceaccounts default -o yaml > ./sa.yaml
  2. cat sa.yaml
  3. apiVersion: v1
  4. kind: ServiceAccount
  5. metadata:
  6. creationTimestamp: 2015-08-07T22:02:39Z
  7. name: default
  8. namespace: default
  9. resourceVersion: "243024"
  10. uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6
  11. secrets:
  12. - name: default-token-uudge
  13. vi sa.yaml
  14. [editor session not shown]
  15. [delete line with key "resourceVersion"]
  16. [add lines with "imagePullSecrets:"]
  17. cat sa.yaml
  18. apiVersion: v1
  19. kind: ServiceAccount
  20. metadata:
  21. creationTimestamp: 2015-08-07T22:02:39Z
  22. name: default
  23. namespace: default
  24. uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6
  25. secrets:
  26. - name: default-token-uudge
  27. imagePullSecrets:
  28. - name: myregistrykey
  29. kubectl replace serviceaccount default -f ./sa.yaml
  30. serviceaccounts/default

现在,在当前命名空间中创建的每个新 Pod 的 spec 中都会添加下面的内容:

  1. spec:
  2. imagePullSecrets:
  3. - name: myregistrykey

服务帐户令牌卷投影

FEATURE STATE: Kubernetes v1.12 beta

该功能目前处于 beta 状态,意味着:

  • 版本名称包含 beta (例如 v2beta3)。
  • 代码经过了充分测试,启用该功能被认为是安全的。默认情况下被启用。
  • 对整体功能的支持在未来不会被移除,尽管细节上可能会做更改。
  • 在后续的 beta 或稳定版本中,对象的模式、语义可能以不兼容的方式发生变化。当这种情况发生时,我们将提供迁移到下一个版本的说明。这可能需要删除、编辑和重建 API 对象,编辑过程可能需要一些思考。这可能导致依赖该功能的应用程序停机一段时间。
  • 建议仅在非业务关键场景使用该功能,因为在后续版本中可能会发生不兼容的更改。如果您有多个可以独立升级的集群,那么您可能可以放松这个限制。
  • 请尝试使用我们的 beta 版功能,并给出反馈!在它们退出 beta 测试阶段之后,我们将很难去做更多的更改。

注意:

ServiceAccountTokenVolumeProjection 在 1.12 版本中是 beta 阶段,可以通过向 API 服务器传递以下所有参数来启用它:

  • --service-account-issuer
  • --service-account-signing-key-file
  • --service-account-api-audiences

kubelet 还可以将服务帐户令牌投影到 Pod 中。 您可以指定令牌的所需属性,例如受众和有效持续时间。 这些属性在默认服务帐户令牌上无法配置。 当删除 Pod 或 ServiceAccount 时,服务帐户令牌也将对 API 无效。

使用名为 ServiceAccountToken 的 ProjectedVolume 类型在 PodSpec 上配置此功能。 要向 Pod 提供具有 “vault” 观众以及两个小时有效期的令牌,可以在 PodSpec 中配置以下内容:

  1. kind: Pod
  2. apiVersion: v1
  3. spec:
  4. containers:
  5. - image: nginx
  6. name: nginx
  7. volumeMounts:
  8. - mountPath: /var/run/secrets/tokens
  9. name: vault-token
  10. volumes:
  11. - name: vault-token
  12. projected:
  13. sources:
  14. - serviceAccountToken:
  15. path: vault-token
  16. expirationSeconds: 7200
  17. audience: vault

Kubelet 将代表 Pod 请求和存储令牌,使令牌在可配置的文件路径上对 Pod 可用,并在令牌接近到期时刷新令牌。 如果令牌存活时间大于其总 TTL 的 80% 或者大于 24 小时,Kubelet 则会主动旋转令牌。

应用程序负责在令牌旋转时重新加载令牌。 对于大多数情况,定期重新加载(例如,每 5 分钟一次)就足够了。