为 Pod 配置服务账户

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

    你必须拥有一个 Kubernetes 的集群,同时你的 Kubernetes 集群必须带有 kubectl 命令行工具。 如果你还没有集群,你可以通过 构建一 个你自己的集群,或者你可以使用下面任意一个 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.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. kind: ServiceAccount
    3. metadata:
    4. creationTimestamp: 2015-06-16T00:12:59Z
    5. name: build-robot
    6. namespace: default
    7. resourceVersion: "272500"
    8. uid: 721ab723-13bc-11e5-aec2-42010af0021e
    9. secrets:
    10. - name: build-robot-token-bvbk5

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

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

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

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

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

    手动创建服务账户 API 令牌

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

    现在,你可以确认新构建的 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: ...
    • 创建一个 ImagePullSecret,如同所述。

      1. kubectl create secret docker-registry myregistrykey --docker-server=DUMMY_SERVER \
      2. --docker-username=DUMMY_USERNAME --docker-password=DUMMY_DOCKER_PASSWORD \
      3. --docker-email=DUMMY_DOCKER_EMAIL
    • 确认创建成功:

      1. kubectl get secrets myregistrykey

      输出类似于:

      1. NAME TYPE DATA AGE
      2. myregistrykey kubernetes.io/.dockerconfigjson 1 1d

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

      你也可以使用 kubectl edit,或者如下所示手动编辑 YAML 清单:

      sa.yaml 文件的内容类似于:

      1. apiVersion: v1
      2. kind: ServiceAccount
      3. metadata:
      4. creationTimestamp: 2015-08-07T22:02:39Z
      5. name: default
      6. namespace: default
      7. resourceVersion: "243024"
      8. uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6
      9. secrets:
      10. - name: default-token-uudge

      使用你常用的编辑器(例如 vi),打开 sa.yaml 文件,删除带有键名 resourceVersion 的行,添加带有 imagePullSecrets: 的行,最后保存文件。

      所得到的 文件类似于:

      1. apiVersion: v1
      2. kind: ServiceAccount
      3. metadata:
      4. creationTimestamp: 2015-08-07T22:02:39Z
      5. name: default
      6. namespace: default
      7. uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6
      8. secrets:
      9. - name: default-token-uudge
      10. imagePullSecrets:
      11. - name: myregistrykey

      最后,用新的更新的 sa.yaml 文件替换服务账号。

      1. kubectl replace serviceaccount default -f ./sa.yaml

      现在,在当前命名空间中创建的每个使用默认服务账号的新 Pod,新 Pod 都会自动 设置其 .spec.imagePullSecrets 字段:

      1. kubectl run nginx --image=nginx --restart=Never
      2. kubectl get pod nginx -o=jsonpath='{.spec.imagePullSecrets[0].name}{"\n"}'

      输出为:

      1. myregistrykey

      服务帐户令牌卷投射

      FEATURE STATE: Kubernetes v1.12 [beta]

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

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

      创建 Pod:

      1. kubectl create -f https://k8s.io/examples/pods/pod-projected-svc-token.yaml

      kubelet 组件会替 Pod 请求令牌并将其保存起来,通过将令牌存储到一个可配置的 路径使之在 Pod 内可用,并在令牌快要到期的时候刷新它。 kubelet 会在令牌存在期达到其 TTL 的 80% 的时候或者令牌生命期超过 24 小时 的时候主动轮换它。

      应用程序负责在令牌被轮换时重新加载其内容。对于大多数使用场景而言,周期性地 (例如,每隔 5 分钟)重新加载就足够了。

      FEATURE STATE: Kubernetes v1.18 [alpha]

      通过启用 ServiceAccountIssuerDiscovery 特性门控, 并按启用服务账号令牌投射, 可以启用发现服务账号分发者(Service Account Issuer Discovery)这一功能特性。

      发现服务账号分发者这一功能使得用户能够用联邦的方式结合使用 Kubernetes 集群(Identity Provider,标识提供者)与外部系统(relying parties, 依赖方)所分发的服务账号令牌。

      当此功能被启用时,Kubernetes API 服务器会在 /.well-known/openid-configuration 提供一个 OpenID 提供者配置文档,并在 /openid/v1/jwks 处提供与之关联的 JSON Web Key Set(JWKS)。 这里的 OpenID 提供者配置有时候也被称作 发现文档(Discovery Document)

      特性被启用时,集群也会配置名为 system:service-account-issuer-discovery 的默认 RBAC ClusterRole,但默认情况下不提供角色绑定对象。 举例而言,管理员可以根据其安全性需要以及期望集成的外部系统选择是否将该角色绑定到 system:authenticatedsystem:unauthenticated

      JWKS 响应包含依赖方可以用来验证 Kubernetes 服务账号令牌的公钥数据。 依赖方先会查询 OpenID 提供者配置,之后使用返回响应中的 jwks_uri 来查找 JWKS。

      在很多场合,Kubernetes API 服务器都不会暴露在公网上,不过对于缓存并向外提供 API 服务器响应数据的公开末端而言,用户或者服务提供商可以选择将其暴露在公网上。 在这种环境中,可能会重载 OpenID 提供者配置中的 jwks_uri,使之指向公网上可用的末端地址,而不是 API 服务器的地址。 这时需要向 API 服务器传递 参数。 与分发者 URL 类似,此 JWKS URI 也需要使用 https 模式。

      接下来