website/content/zh-cn/docs/tasks/configure-pod-container/configure-service-account.md

942 lines
38 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters!

This file contains invisible Unicode characters that may be processed differently from what appears below. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to reveal hidden characters.

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

---
title: 为 Pod 配置服务账号
content_type: task
weight: 120
---
<!--
reviewers:
- enj
- liggitt
- thockin
title: Configure Service Accounts for Pods
content_type: task
weight: 120
-->
<!-- overview -->
<!--
Kubernetes offers two distinct ways for clients that run within your
cluster, or that otherwise have a relationship to your cluster's
{{< glossary_tooltip text="control plane" term_id="control-plane" >}}
to authenticate to the
{{< glossary_tooltip text="API server" term_id="kube-apiserver" >}}.
-->
Kubernetes 提供两种完全不同的方式来为客户端提供支持,这些客户端可能运行在你的集群中,
也可能与你的集群的{{< glossary_tooltip text="控制面" term_id="control-plane" >}}相关,
需要向 {{< glossary_tooltip text="API 服务器" term_id="kube-apiserver" >}}完成身份认证。
<!--
A _service account_ provides an identity for processes that run in a Pod,
and maps to a ServiceAccount object. When you authenticate to the API
server, you identify yourself as a particular _user_. Kubernetes recognises
the concept of a user, however, Kubernetes itself does **not** have a User
API.
-->
**服务账号Service Account** 为 Pod 中运行的进程提供身份标识,
并映射到 ServiceAccount 对象。当你向 API 服务器执行身份认证时,
你会将自己标识为某个**用户User**。Kubernetes 能够识别用户的概念,
但是 Kubernetes 自身**并不**提供 User API。
<!--
This task guide is about ServiceAccounts, which do exist in the Kubernetes
API. The guide shows you some ways to configure ServiceAccounts for Pods.
-->
本服务是关于 ServiceAccount 的,而 ServiceAccount 则确实存在于 Kubernetes 的 API 中。
本指南为你展示为 Pod 配置 ServiceAccount 的一些方法。
## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}}
<!-- steps -->
<!--
## Use the default service account to access the API server
When Pods contact the API server, Pods authenticate as a particular
ServiceAccount (for example, `default`). There is always at least one
ServiceAccount in each {{< glossary_tooltip text="namespace" term_id="namespace" >}}.
Every Kubernetes namespace contains at least one ServiceAccount: the default
ServiceAccount for that namespace, named `default`.
If you do not specify a ServiceAccount when you create a Pod, Kubernetes
automatically assigns the ServiceAccount named `default` in that namespace.
You can fetch the details for a Pod you have created. For example:
-->
## 使用默认的服务账号访问 API 服务器 {#use-the-default-service-account-to-access-the-api-server}
当 Pod 与 API 服务器联系时Pod 会被认证为某个特定的 ServiceAccount例如`default`)。
在每个{{< glossary_tooltip text="名字空间" term_id="namespace" >}}中,至少存在一个
ServiceAccount。
每个 Kubernetes 名字空间至少包含一个 ServiceAccount也就是该名字空间的默认服务账号
名为 `default`。如果你在创建 Pod 时没有指定 ServiceAccountKubernetes 会自动将该名字空间中名为
`default` 的 ServiceAccount 分配给该 Pod。
你可以检视你刚刚创建的 Pod 的细节。例如:
```shell
kubectl get pods/<podname> -o yaml
```
<!--
In the output, you see a field `spec.serviceAccountName`.
Kubernetes automatically
sets that value if you don't specify it when you create a Pod.
An application running inside a Pod can access the Kubernetes API using
automatically mounted service account credentials.
See [accessing the Cluster](/docs/tasks/access-application-cluster/access-cluster/) to learn more.
-->
在输出中,你可以看到字段 `spec.serviceAccountName`。当你在创建 Pod 时未设置该字段时,
Kubernetes 自动为 Pod 设置这一属性的取值。
Pod 中运行的应用可以使用这一自动挂载的服务账号凭据来访问 Kubernetes API。
参阅[访问集群](/zh-cn/docs/tasks/access-application-cluster/access-cluster/)以进一步了解。
<!--
When a Pod authenticates as a ServiceAccount, its level of access depends on the
[authorization plugin and policy](/docs/reference/access-authn-authz/authorization/#authorization-modules)
in use.
-->
当 Pod 被身份认证为某个 ServiceAccount 时,
其访问能力取决于所使用的[鉴权插件和策略](/zh-cn/docs/reference/access-authn-authz/authorization/#authorization-modules)。
<!--
The API credentials are automatically revoked when the Pod is deleted, even if
finalizers are in place. In particular, the API credentials are revoked 60 seconds
beyond the `.metadata.deletionTimestamp` set on the Pod (the deletion timestamp
is typically the time that the **delete** request was accepted plus the Pod's
termination grace period).
-->
当 Pod 被删除时即使设置了终结器API 凭据也会自动失效。
需要额外注意的是API 凭据会在 Pod 上设置的 `.metadata.deletionTimestamp` 之后的 60 秒内失效
(删除时间戳通常是 **delete** 请求被接受的时间加上 Pod 的终止宽限期)。
<!--
### Opt out of API credential automounting
If you don't want the {{< glossary_tooltip text="kubelet" term_id="kubelet" >}}
to automatically mount a ServiceAccount's API credentials, you can opt out of
the default behavior.
You can opt out of automounting API credentials on `/var/run/secrets/kubernetes.io/serviceaccount/token`
for a service account by setting `automountServiceAccountToken: false` on the ServiceAccount:
For example:
-->
### 放弃 API 凭据的自动挂载 {#opt-out-of-api-credential-automounting}
如果你不希望 {{< glossary_tooltip text="kubelet" term_id="kubelet" >}} 自动挂载某
ServiceAccount 的 API 访问凭据,你可以选择不采用这一默认行为。
通过在 ServiceAccount 对象上设置 `automountServiceAccountToken: false`,可以放弃在
`/var/run/secrets/kubernetes.io/serviceaccount/token` 处自动挂载该服务账号的 API 凭据。
例如:
```yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: build-robot
automountServiceAccountToken: false
...
```
<!--
You can also opt out of automounting API credentials for a particular Pod:
-->
你也可以选择不给特定 Pod 自动挂载 API 凭据:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
serviceAccountName: build-robot
automountServiceAccountToken: false
...
```
<!--
If both the ServiceAccount and the Pod's `.spec` specify a value for
`automountServiceAccountToken`, the Pod spec takes precedence.
-->
如果 ServiceAccount 和 Pod 的 `.spec` 都设置了 `automountServiceAccountToken` 值,
则 Pod 上 spec 的设置优先于服务账号的设置。
<!--
## Use more than one ServiceAccount {#use-multiple-service-accounts}
Every namespace has at least one ServiceAccount: the default ServiceAccount
resource, called `default`. You can list all ServiceAccount resources in your
[current namespace](/docs/concepts/overview/working-with-objects/namespaces/#setting-the-namespace-preference)
with:
-->
## 使用多个服务账号 {#use-multiple-service-accounts}
每个名字空间都至少有一个 ServiceAccount名为 `default` 的默认 ServiceAccount 资源。
你可以用下面的命令列举你[当前名字空间](/zh-cn/docs/concepts/overview/working-with-objects/namespaces/#setting-the-namespace-preference)
中的所有 ServiceAccount 资源:
```shell
kubectl get serviceaccounts
```
<!--
The output is similar to this:
-->
输出类似于:
```
NAME SECRETS AGE
default 1 1d
```
<!--
You can create additional ServiceAccount objects like this:
-->
你可以像这样来创建额外的 ServiceAccount 对象:
```shell
kubectl apply -f - <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: build-robot
EOF
```
<!--
The name of a ServiceAccount object must be a valid
[DNS subdomain name](/docs/concepts/overview/working-with-objects/names#dns-subdomain-names).
-->
ServiceAccount 对象的名字必须是一个有效的
[DNS 子域名](/zh-cn/docs/concepts/overview/working-with-objects/names#dns-subdomain-names)。
<!--
If you get a complete dump of the service account object, like this:
-->
如果你查询服务账号对象的完整信息,如下所示:
```shell
kubectl get serviceaccounts/build-robot -o yaml
```
<!--
The output is similar to this:
-->
输出类似于:
```yaml
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: 2019-06-16T00:12:34Z
name: build-robot
namespace: default
resourceVersion: "272500"
uid: 721ab723-13bc-11e5-aec2-42010af0021e
```
<!--
You can use authorization plugins to
[set permissions on service accounts](/docs/reference/access-authn-authz/rbac/#service-account-permissions).
To use a non-default service account, set the `spec.serviceAccountName`
field of a Pod to the name of the ServiceAccount you wish to use.
-->
你可以使用鉴权插件来[设置服务账号的访问许可](/zh-cn/docs/reference/access-authn-authz/rbac/#service-account-permissions)。
要使用非默认的服务账号,将 Pod 的 `spec.serviceAccountName` 字段设置为你想用的服务账号名称。
<!--
You can only set the `serviceAccountName` field when creating a Pod, or in a
template for a new Pod. You cannot update the `.spec.serviceAccountName` field
of a Pod that already exists.
-->
只能在创建 Pod 时或者为新 Pod 指定模板时,你才可以设置 `serviceAccountName`
你不能更新已经存在的 Pod 的 `.spec.serviceAccountName` 字段。
{{< note >}}
<!--
The `.spec.serviceAccount` field is a deprecated alias for `.spec.serviceAccountName`.
If you want to remove the fields from a workload resource, set both fields to empty explicitly
on the [pod template](/docs/concepts/workloads/pods#pod-templates).
-->
`.spec.serviceAccount` 字段是 `.spec.serviceAccountName` 的已弃用别名。
如果要从工作负载资源中删除这些字段,请在
[Pod 模板](/zh-cn/docs/concepts/workloads/pods#pod-templates)上将这两个字段显式设置为空。
{{< /note >}}
<!--
### Cleanup {#cleanup-use-multiple-service-accounts}
If you tried creating `build-robot` ServiceAccount from the example above,
you can clean it up by running:
-->
### 清理 {#cleanup-use-multiple-service-accounts}
如果你尝试了创建前文示例中所给的 `build-robot` ServiceAccount
你可以通过运行下面的命令来完成清理操作:
```shell
kubectl delete serviceaccount/build-robot
```
<!--
## Manually create an API token for a ServiceAccount
Suppose you have an existing service account named "build-robot" as mentioned earlier.
You can get a time-limited API token for that ServiceAccount using `kubectl`:
-->
## 手动为 ServiceAccount 创建 API 令牌 {#manually-create-an-api-token-for-a-serviceaccount}
假设你已经有了一个前文所提到的名为 "build-robot" 的服务账号。
你可以使用 `kubectl` 为该 ServiceAccount 获得一个有时限的 API 令牌:
```shell
kubectl create token build-robot
```
<!--
The output from that command is a token that you can use to authenticate as that
ServiceAccount. You can request a specific token duration using the `--duration`
command line argument to `kubectl create token` (the actual duration of the issued
token might be shorter, or could even be longer).
-->
这一命令的输出是一个令牌,你可以使用该令牌来将身份认证为对应的 ServiceAccount。
你可以使用 `kubectl create token` 命令的 `--duration` 参数来请求特定的令牌有效期
(实际签发的令牌的有效期可能会稍短一些,也可能会稍长一些)。
{{< feature-state feature_gate_name="ServiceAccountTokenNodeBinding" >}}
<!--
Using `kubectl` v1.31 or later, it is possible to create a service
account token that is directly bound to a Node:
-->
使用 kubectl v1.31 或更高版本,可以创建一个直接绑定到 Node 的服务账号令牌:
```shell
kubectl create token build-robot --bound-object-kind Node --bound-object-name node-001 --bound-object-uid 123...456
```
<!--
The token will be valid until it expires or either the associated Node or service account are deleted.
-->
此令牌将有效直至其过期或关联的 Node 或服务账户被删除。
{{< note >}}
<!--
Versions of Kubernetes before v1.22 automatically created long term credentials for
accessing the Kubernetes API. This older mechanism was based on creating token Secrets
that could then be mounted into running Pods. In more recent versions, including
Kubernetes v{{< skew currentVersion >}}, API credentials are obtained directly by using the
[TokenRequest](/docs/reference/kubernetes-api/authentication-resources/token-request-v1/) API,
and are mounted into Pods using a
[projected volume](/docs/reference/access-authn-authz/service-accounts-admin/#bound-service-account-token-volume).
The tokens obtained using this method have bounded lifetimes, and are automatically
invalidated when the Pod they are mounted into is deleted.
-->
Kubernetes 在 v1.22 版本之前自动创建用来访问 Kubernetes API 的长期凭据。
这一较老的机制是基于创建令牌 Secret 对象来实现的Secret 对象可被挂载到运行中的 Pod 内。
在最近的版本中,包括 Kubernetes v{{< skew currentVersion >}}API 凭据可以直接使用
[TokenRequest](/zh-cn/docs/reference/kubernetes-api/authentication-resources/token-request-v1/) API
来获得,并使用一个[投射卷](/zh-cn/docs/reference/access-authn-authz/service-accounts-admin/#bound-service-account-token-volume)挂载到
Pod 中。使用此方法获得的令牌具有受限的生命期长度,并且能够在挂载它们的 Pod
被删除时自动被废弃。
<!--
You can still manually create a service account token Secret; for example,
if you need a token that never expires. However, using the
[TokenRequest](/docs/reference/kubernetes-api/authentication-resources/token-request-v1/)
subresource to obtain a token to access the API is recommended instead.
-->
你仍然可以通过手动方式来创建服务账号令牌 Secret 对象,例如你需要一个永远不过期的令牌时。
不过,使用 [TokenRequest](/zh-cn/docs/reference/kubernetes-api/authentication-resources/token-request-v1/)
子资源来获得访问 API 的令牌的做法仍然是推荐的方式。
{{< /note >}}
<!--
### Manually create a long-lived API token for a ServiceAccount
If you want to obtain an API token for a ServiceAccount, you create a new Secret
with a special annotation, `kubernetes.io/service-account.name`.
-->
### 手动为 ServiceAccount 创建长期有效的 API 令牌 {#manually-create-a-long-lived-api-token-for-a-serviceaccount}
如果你需要为 ServiceAccount 获得一个 API 令牌,你可以创建一个新的、带有特殊注解
`kubernetes.io/service-account.name` 的 Secret 对象。
```shell
kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
name: build-robot-secret
annotations:
kubernetes.io/service-account.name: build-robot
type: kubernetes.io/service-account-token
EOF
```
<!--
If you view the Secret using:
-->
如果你通过下面的命令来查看 Secret
```shell
kubectl get secret/build-robot-secret -o yaml
```
<!--
you can see that the Secret now contains an API token for the "build-robot" ServiceAccount.
Because of the annotation you set, the control plane automatically generates a token for that
ServiceAccounts, and stores them into the associated Secret. The control plane also cleans up
tokens for deleted ServiceAccounts.
-->
你可以看到 Secret 中现在包含针对 "build-robot" ServiceAccount 的 API 令牌。
鉴于你所设置的注解,控制面会自动为该 ServiceAccount 生成一个令牌,并将其保存到相关的 Secret
中。控制面也会为已删除的 ServiceAccount 执行令牌清理操作。
```shell
kubectl describe secrets/build-robot-secret
```
<!--
The output is similar to this:
-->
输出类似于这样:
```
Name: build-robot-secret
Namespace: default
Labels: <none>
Annotations: kubernetes.io/service-account.name: build-robot
kubernetes.io/service-account.uid: da68f9c6-9d26-11e7-b84e-002dc52800da
Type: kubernetes.io/service-account-token
Data
====
ca.crt: 1338 bytes
namespace: 7 bytes
token: ...
```
{{< note >}}
<!--
The content of `token` is omitted here.
Take care not to display the contents of a `kubernetes.io/service-account-token`
Secret somewhere that your terminal / computer screen could be seen by an onlooker.
-->
这里将 `token` 的内容省略了。
注意在你的终端或者计算机屏幕可能被旁观者看到的场合,不要显示
`kubernetes.io/service-account-token` 的内容。
{{< /note >}}
<!--
When you delete a ServiceAccount that has an associated Secret, the Kubernetes
control plane automatically cleans up the long-lived token from that Secret.
-->
当你删除一个与某 Secret 相关联的 ServiceAccount 时Kubernetes 的控制面会自动清理该
Secret 中长期有效的令牌。
{{< note >}}
<!--
If you view the ServiceAccount using:
` kubectl get serviceaccount build-robot -o yaml`
You can't see the `build-robot-secret` Secret in the ServiceAccount API objects
[`.secrets`](/docs/reference/kubernetes-api/authentication-resources/service-account-v1/) field
because that field is only populated with auto-generated Secrets.
-->
如果你使用以下命令查看 ServiceAccount:
` kubectl get serviceaccount build-robot -o yaml`
在 ServiceAccount API 对象中看不到 `build-robot-secret` Secret
[`.secrets`](/zh-cn/docs/reference/kubernetes-api/authentication-resources/service-account-v1/) 字段,
因为该字段只会填充自动生成的 Secret。
{{< /note >}}
<!--
## Add ImagePullSecrets to a service account
First, [create an imagePullSecret](/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod).
Next, verify it has been created. For example:
-->
## 为服务账号添加 ImagePullSecrets {#add-imagepullsecrets-to-a-service-account}
首先,[生成一个 imagePullSecret](/zh-cn/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod)
接下来,验证该 Secret 已被创建。例如:
<!--
- Create an imagePullSecret, as described in
[Specifying ImagePullSecrets on a Pod](/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod).
-->
- 按[为 Pod 设置 imagePullSecret](/zh-cn/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod)
所描述的,生成一个镜像拉取 Secret
```shell
kubectl create secret docker-registry myregistrykey --docker-server=<registry name> \
--docker-username=DUMMY_USERNAME --docker-password=DUMMY_DOCKER_PASSWORD \
--docker-email=DUMMY_DOCKER_EMAIL
```
<!--
- Verify it has been created.
-->
- 检查该 Secret 已经被创建。
```shell
kubectl get secrets myregistrykey
```
<!--
The output is similar to this:
-->
输出类似于这样:
```
NAME TYPE DATA AGE
myregistrykey   kubernetes.io/.dockerconfigjson   1       1d
```
<!--
### Add image pull secret to service account
Next, modify the default service account for the namespace to use this Secret as an imagePullSecret.
-->
### 将镜像拉取 Secret 添加到服务账号 {#add-image-pull-secret-to-service-account}
接下来更改名字空间的默认服务账号,将该 Secret 用作 imagePullSecret。
```shell
kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "myregistrykey"}]}'
```
<!--
You can achieve the same outcome by editing the object manually:
-->
你也可以通过手动编辑该对象来实现同样的效果:
```shell
kubectl edit serviceaccount/default
```
<!--
The output of the `sa.yaml` file is similar to this:
-->
`sa.yaml` 文件的输出类似于:
<!--
Your selected text editor will open with a configuration looking something like this:
-->
你所选择的文本编辑器会被打开,展示如下所示的配置:
```yaml
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: 2021-07-07T22:02:39Z
name: default
namespace: default
resourceVersion: "243024"
uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6
```
<!--
Using your editor, delete the line with key `resourceVersion`, add lines for
`imagePullSecrets:` and save it. Leave the `uid` value set the same as you found it.
After you made those changes, the edited ServiceAccount looks something like this:
-->
使用你的编辑器,删掉包含 `resourceVersion` 主键的行,添加包含 `imagePullSecrets:`
的行并保存文件。对于 `uid` 而言,保持其取值与你读到的值一样。
当你完成这些变更之后,所编辑的 ServiceAccount 看起来像是这样:
```yaml
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: 2021-07-07T22:02:39Z
name: default
namespace: default
uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6
imagePullSecrets:
- name: myregistrykey
```
<!--
### Verify that imagePullSecrets are set for new Pods
Now, when a new Pod is created in the current namespace and using the default
ServiceAccount, the new Pod has its `spec.imagePullSecrets` field set automatically:
-->
### 检查 imagePullSecrets 已经被设置到新 Pod 上 {#verify-that-imagepullsecrets-are-set-for-new-pods}
现在,在当前名字空间中创建新 Pod 并使用默认 ServiceAccount 时,
新 Pod 的 `spec.imagePullSecrets` 会被自动设置。
```shell
kubectl run nginx --image=<registry name>/nginx --restart=Never
kubectl get pod nginx -o=jsonpath='{.spec.imagePullSecrets[0].name}{"\n"}'
```
<!--
The output is:
-->
输出为:
```
myregistrykey
```
<!--
## ServiceAccount token volume projection
-->
## 服务账号令牌卷投射 {#serviceaccount-token-volume-projection}
{{< feature-state for_k8s_version="v1.20" state="stable" >}}
{{< note >}}
<!--
To enable and use token request projection, you must specify each of the following
command line arguments to `kube-apiserver`:
-->
为了启用令牌请求投射,你必须为 `kube-apiserver` 设置以下命令行参数:
<!--
`--service-account-issuer`
: defines the Identifier of the service account token issuer. You can specify the
`--service-account-issuer` argument multiple times, this can be useful to enable
a non-disruptive change of the issuer. When this flag is specified multiple times,
the first is used to generate tokens and all are used to determine which issuers
are accepted. You must be running Kubernetes v1.22 or later to be able to specify
`--service-account-issuer` multiple times.
-->
`--service-account-issuer`
: 定义服务账号令牌发放者的身份标识Identifier。你可以多次指定
`--service-account-issuer` 参数,对于需要变更发放者而又不想带来业务中断的场景,
这样做是有用的。如果这个参数被多次指定,其第一个参数值会被用来生成令牌,
而所有参数值都会被用来确定哪些发放者是可接受的。你所运行的 Kubernetes
集群必须是 v1.22 或更高版本才能多次指定 `--service-account-issuer`
<!--
`--service-account-key-file`
: specifies the path to a file containing PEM-encoded X.509 private or public keys
(RSA or ECDSA), used to verify ServiceAccount tokens. The specified file can contain
multiple keys, and the flag can be specified multiple times with different files.
If specified multiple times, tokens signed by any of the specified keys are considered
valid by the Kubernetes API server.
-->
`--service-account-key-file`
: 给出某文件的路径,其中包含 PEM 编码的 x509 RSA 或 ECDSA 私钥或公钥,用来检查 ServiceAccount
的令牌。所指定的文件中可以包含多个秘钥,并且你可以多次使用此参数,每个参数值为不同的文件。
多次使用此参数时,由所给的秘钥之一签名的令牌会被 Kubernetes API 服务器认为是合法令牌。
<!--
`--service-account-signing-key-file`
: specifies the path to a file that contains the current private key of the service
account token issuer. The issuer signs issued ID tokens with this private key.
-->
`--service-account-signing-key-file`
: 指向某文件的路径,其中包含当前服务账号令牌发放者的私钥。
此发放者使用此私钥来签署所发放的 ID 令牌。
<!--
`--api-audiences` (can be omitted)
: defines audiences for ServiceAccount tokens. The service account token authenticator
validates that tokens used against the API are bound to at least one of these audiences.
If `api-audiences` is specified multiple times, tokens for any of the specified audiences
are considered valid by the Kubernetes API server. If you specify the `--service-account-issuer`
command line argument but you don't set `--api-audiences`, the control plane defaults to
a single element audience list that contains only the issuer URL.
-->
`--api-audiences`(可以省略)
: 为 ServiceAccount 令牌定义其受众Audiences
服务账号令牌身份检查组件会检查针对 API 访问所使用的令牌,
确认令牌至少是被绑定到这里所给的受众之一。
如果 `api-audiences` 被多次指定,则针对所给的多个受众中任何目标的令牌都会被
Kubernetes API 服务器当做合法的令牌。如果你指定了 `--service-account-issuer`
参数,但沒有設置 `--api-audiences`,则控制面认为此参数的默认值为一个只有一个元素的列表,
且该元素为令牌发放者的 URL。
{{< /note >}}
<!--
The kubelet can also project a ServiceAccount token into a Pod. You can
specify desired properties of the token, such as the audience and the validity
duration. These properties are _not_ configurable on the default ServiceAccount
token. The token will also become invalid against the API when either the Pod
or the ServiceAccount is deleted.
-->
kubelet 还可以将 ServiceAccount 令牌投射到 Pod 中。你可以指定令牌的期望属性,
例如受众和有效期限。这些属性在 default ServiceAccount 令牌上**无法**配置。
当 Pod 或 ServiceAccount 被删除时,该令牌也将对 API 无效。
<!--
You can configure this behavior for the `spec` of a Pod using a
[projected volume](/docs/concepts/storage/volumes/#projected) type called
`ServiceAccountToken`.
-->
你可以使用类型为 `ServiceAccountToken` 的[投射卷](/zh-cn/docs/concepts/storage/volumes/#projected)来为
Pod 的 `spec` 配置此行为。
<!--
The token from this projected volume is a {{<glossary_tooltip term_id="jwt" text="JSON Web Token">}} (JWT).
The JSON payload of this token follows a well defined schema - an example payload for a pod bound token:
-->
来自此投射卷的令牌是一个 {{<glossary_tooltip term_id="jwt" text="JSON Web Token">}} (JWT)。
此令牌的 JSON 载荷遵循明确定义的模式,绑定到 Pod 的令牌的示例载荷如下:
<!--
```yaml
{
"aud": [ # matches the requested audiences, or the API server's default audiences when none are explicitly requested
"https://kubernetes.default.svc"
],
"exp": 1731613413,
"iat": 1700077413,
"iss": "https://kubernetes.default.svc", # matches the first value passed to the --service-account-issuer flag
"jti": "ea28ed49-2e11-4280-9ec5-bc3d1d84661a",
"kubernetes.io": {
"namespace": "kube-system",
"node": {
"name": "127.0.0.1",
"uid": "58456cb0-dd00-45ed-b797-5578fdceaced"
},
"pod": {
"name": "coredns-69cbfb9798-jv9gn",
"uid": "778a530c-b3f4-47c0-9cd5-ab018fb64f33"
},
"serviceaccount": {
"name": "coredns",
"uid": "a087d5a0-e1dd-43ec-93ac-f13d89cd13af"
},
"warnafter": 1700081020
},
"nbf": 1700077413,
"sub": "system:serviceaccount:kube-system:coredns"
}
```
-->
```yaml
{
"aud": [ # 匹配请求的受众,或当没有明确请求时匹配 API 服务器的默认受众
"https://kubernetes.default.svc"
],
"exp": 1731613413,
"iat": 1700077413,
"iss": "https://kubernetes.default.svc", # 匹配传递到 --service-account-issuer 标志的第一个值
"jti": "ea28ed49-2e11-4280-9ec5-bc3d1d84661a",
"kubernetes.io": {
"namespace": "kube-system",
"node": {
"name": "127.0.0.1",
"uid": "58456cb0-dd00-45ed-b797-5578fdceaced"
},
"pod": {
"name": "coredns-69cbfb9798-jv9gn",
"uid": "778a530c-b3f4-47c0-9cd5-ab018fb64f33"
},
"serviceaccount": {
"name": "coredns",
"uid": "a087d5a0-e1dd-43ec-93ac-f13d89cd13af"
},
"warnafter": 1700081020
},
"nbf": 1700077413,
"sub": "system:serviceaccount:kube-system:coredns"
}
```
<!--
### Launch a Pod using service account token projection
To provide a Pod with a token with an audience of `vault` and a validity duration
of two hours, you could define a Pod manifest that is similar to:
-->
### 启动使用服务账号令牌投射的 Pod {#launch-a-pod-using-service-account-token-projection}
要为某 Pod 提供一个受众为 `vault` 并且有效期限为 2 小时的令牌,你可以定义一个与下面类似的
Pod 清单:
{{% code_sample file="pods/pod-projected-svc-token.yaml" %}}
<!--
Create the Pod:
-->
创建此 Pod
```shell
kubectl create -f https://k8s.io/examples/pods/pod-projected-svc-token.yaml
```
<!--
The kubelet will: request and store the token on behalf of the Pod; make
the token available to the Pod at a configurable file path; and refresh
the token as it approaches expiration. The kubelet proactively requests rotation
for the token if it is older than 80% of its total time-to-live (TTL),
or if the token is older than 24 hours.
-->
kubelet 组件会替 Pod 请求令牌并将其保存起来;通过将令牌存储到一个可配置的路径以使之在
Pod 内可用在令牌快要到期的时候刷新它。kubelet 会在令牌存在期达到其 TTL 的 80%
的时候或者令牌生命期超过 24 小时的时候主动请求将其轮换掉。
<!--
The application is responsible for reloading the token when it rotates. It's
often good enough for the application to load the token on a schedule
(for example: once every 5 minutes), without tracking the actual expiry time.
-->
应用负责在令牌被轮换时重新加载其内容。通常而言,周期性地(例如,每隔 5 分钟)
重新加载就足够了,不必跟踪令牌的实际过期时间。
<!--
## Service Account Issuer Discovery
-->
## 发现服务账号分发者 {#service-account-issuer-discovery}
{{< feature-state for_k8s_version="v1.21" state="stable" >}}
<!--
If you have enabled [token projection](#serviceaccount-token-volume-projection)
for ServiceAccounts in your cluster, then you can also make use of the discovery
feature. Kubernetes provides a way for clients to federate as an _identity provider_,
so that one or more external systems can act as a _relying party_.
-->
如果你在你的集群中已经为 ServiceAccount 启用了[令牌投射](#serviceaccount-token-volume-projection)
那么你也可以利用其发现能力。Kubernetes 提供一种方式来让客户端将一个或多个外部系统进行联邦,
作为**标识提供者Identity Provider**,而这些外部系统的角色是**依赖方Relying Party**。
{{< note >}}
<!--
The issuer URL must comply with the
[OIDC Discovery Spec](https://openid.net/specs/openid-connect-discovery-1_0.html). In
practice, this means it must use the `https` scheme, and should serve an OpenID
provider configuration at `{service-account-issuer}/.well-known/openid-configuration`.
If the URL does not comply, ServiceAccount issuer discovery endpoints are not
registered or accessible.
-->
分发者的 URL 必须遵从
[OIDC 发现规范](https://openid.net/specs/openid-connect-discovery-1_0.html)。
实现上,这意味着 URL 必须使用 `https` 模式,并且必须在路径
`{service-account-issuer}/.well-known/openid-configuration`
处给出 OpenID 提供者Provider的配置信息。
如果 URL 没有遵从这一规范ServiceAccount 分发者发现末端末端就不会被注册也无法访问。
{{< /note >}}
<!--
When enabled, the Kubernetes API server publishes an OpenID Provider
Configuration document via HTTP. The configuration document is published at
`/.well-known/openid-configuration`.
The OpenID Provider Configuration is sometimes referred to as the _discovery document_.
The Kubernetes API server publishes the related
JSON Web Key Set (JWKS), also via HTTP, at `/openid/v1/jwks`.
-->
当此特性被启用时Kubernetes API 服务器会通过 HTTP 发布一个 OpenID 提供者配置文档。
该配置文档发布在 `/.well-known/openid-configuration` 路径。
这里的 OpenID 提供者配置OpenID Provider Configuration有时候也被称作
“发现文档Discovery Document”。
Kubernetes API 服务器也通过 HTTP 在 `/openid/v1/jwks` 处发布相关的
JSON Web Key SetJWKS
{{< note >}}
<!--
The responses served at `/.well-known/openid-configuration` and
`/openid/v1/jwks` are designed to be OIDC compatible, but not strictly OIDC
compliant. Those documents contain only the parameters necessary to perform
validation of Kubernetes service account tokens.
-->
对于在 `/.well-known/openid-configuration``/openid/v1/jwks` 上给出的响应而言,
其设计上是保证与 OIDC 兼容的,但并不严格遵从 OIDC 的规范。
响应中所包含的文档进包含对 Kubernetes 服务账号令牌进行校验所必需的参数。
{{< /note >}}
<!--
Clusters that use {{< glossary_tooltip text="RBAC" term_id="rbac">}} include a
default ClusterRole called `system:service-account-issuer-discovery`.
A default ClusterRoleBinding assigns this role to the `system:serviceaccounts` group,
which all ServiceAccounts implicitly belong to.
This allows pods running on the cluster to access the service account discovery document
via their mounted service account token. Administrators may, additionally, choose to
bind the role to `system:authenticated` or `system:unauthenticated` depending on their
security requirements and which external systems they intend to federate with.
-->
使用 {{< glossary_tooltip text="RBAC" term_id="rbac">}} 的集群都包含一个的默认
RBAC ClusterRole, 名为 `system:service-account-issuer-discovery`
默认的 RBAC ClusterRoleBinding 将此角色分配给 `system:serviceaccounts` 组,
所有 ServiceAccount 隐式属于该组。这使得集群上运行的 Pod
能够通过它们所挂载的服务账号令牌访问服务账号发现文档。
此外,管理员可以根据其安全性需要以及期望集成的外部系统,选择是否将该角色绑定到
`system:authenticated``system:unauthenticated`
<!--
The JWKS response contains public keys that a relying party can use to validate
the Kubernetes service account tokens. Relying parties first query for the
OpenID Provider Configuration, and use the `jwks_uri` field in the response to
find the JWKS.
-->
JWKS 响应包含依赖方可以用来验证 Kubernetes 服务账号令牌的公钥数据。
依赖方先会查询 OpenID 提供者配置,之后使用返回响应中的 `jwks_uri` 来查找 JWKS。
<!--
In many cases, Kubernetes API servers are not available on the public internet,
but public endpoints that serve cached responses from the API server can be made
available by users or by service providers. In these cases, it is possible to
override the `jwks_uri` in the OpenID Provider Configuration so that it points
to the public endpoint, rather than the API server's address, by passing the
`--service-account-jwks-uri` flag to the API server. Like the issuer URL, the
JWKS URI is required to use the `https` scheme.
-->
在很多场合Kubernetes API 服务器都不会暴露在公网上,不过对于缓存并向外提供 API
服务器响应数据的公开末端而言,用户或者服务提供商可以选择将其暴露在公网上。
在这种环境中,可能会重载 OpenID 提供者配置中的
`jwks_uri`,使之指向公网上可用的末端地址,而不是 API 服务器的地址。
这时需要向 API 服务器传递 `--service-account-jwks-uri` 参数。
与分发者 URL 类似,此 JWKS URI 也需要使用 `https` 模式。
## {{% heading "whatsnext" %}}
<!--
See also:
- Read the [Cluster Admin Guide to Service Accounts](/docs/reference/access-authn-authz/service-accounts-admin/)
- Read about [Authorization in Kubernetes](/docs/reference/access-authn-authz/authorization/)
- Read about [Secrets](/docs/concepts/configuration/secret/)
- or learn to [distribute credentials securely using Secrets](/docs/tasks/inject-data-application/distribute-credentials-secure/)
- but also bear in mind that using Secrets for authenticating as a ServiceAccount
is deprecated. The recommended alternative is
[ServiceAccount token volume projection](#serviceaccount-token-volume-projection).
-->
另请参见:
- 阅读[为集群管理员提供的服务账号指南](/zh-cn/docs/reference/access-authn-authz/service-accounts-admin/)
- 阅读 [Kubernetes中的鉴权](/zh-cn/docs/reference/access-authn-authz/authorization/)
- 阅读 [Secret](/zh-cn/docs/concepts/configuration/secret/) 的概念
- 或者学习[使用 Secret 来安全地分发凭据](/zh-cn/docs/tasks/inject-data-application/distribute-credentials-secure/)
- 不过也要注意,使用 Secret 来完成 ServiceAccount 身份验证的做法已经过时。
建议的替代做法是执行 [ServiceAccount 令牌卷投射](#serviceaccount-token-volume-projection)。
<!--
- Read about [projected volumes](/docs/tasks/configure-pod-container/configure-projected-volume-storage/).
- For background on OIDC discovery, read the
[ServiceAccount signing key retrieval](https://github.com/kubernetes/enhancements/tree/master/keps/sig-auth/1393-oidc-discovery)
Kubernetes Enhancement Proposal
- Read the [OIDC Discovery Spec](https://openid.net/specs/openid-connect-discovery-1_0.html)
-->
- 阅读理解[投射卷](/zh-cn/docs/tasks/configure-pod-container/configure-projected-volume-storage/)
- 关于 OIDC 发现的相关背景信息,阅读[服务账号签署密钥检索 KEP](https://github.com/kubernetes/enhancements/tree/master/keps/sig-auth/1393-oidc-discovery)
这一 Kubernetes 增强提案
- 阅读 [OIDC 发现规范](https://openid.net/specs/openid-connect-discovery-1_0.html)