Merge pull request #33654 from sftim/20190601_task_configure_service_account_reword

Reword tasks relating to ServiceAccounts
This commit is contained in:
Kubernetes Prow Robot 2022-11-09 13:50:56 -08:00 committed by GitHub
commit f3248058fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 519 additions and 206 deletions

View File

@ -11,109 +11,146 @@ weight: 50
<!-- overview --> <!-- overview -->
This is a Cluster Administrator guide to service accounts. You should be familiar with A _ServiceAccount_ provides an identity for processes that run in a Pod.
[configuring Kubernetes service accounts](/docs/tasks/configure-pod-container/configure-service-account/).
Support for authorization and user accounts is planned but incomplete. Sometimes A process inside a Pod can use the identity of its associated service account to
incomplete features are referred to in order to better describe service accounts. authenticate to the cluster's API server.
For an introduction to service accounts, read [configure service accounts](/docs/tasks/configure-pod-container/configure-service-account/).
This task guide explains some of the concepts behind ServiceAccounts. The
guide also explains how to obtain or revoke tokens that represent
ServiceAccounts.
<!-- body --> <!-- body -->
## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}}
To be able to follow these steps exactly, ensure you have a namespace named
`examplens`.
If you don't, create one by running:
```shell
kubectl create namespace examplens
```
## User accounts versus service accounts ## User accounts versus service accounts
Kubernetes distinguishes between the concept of a user account and a service account Kubernetes distinguishes between the concept of a user account and a service account
for a number of reasons: for a number of reasons:
- User accounts are for humans. Service accounts are for processes, which run - User accounts are for humans. Service accounts are for application processes,
in pods. which (for Kubernetes) run in containers that are part of pods.
- User accounts are intended to be global. Names must be unique across all - User accounts are intended to be global: names must be unique across all
namespaces of a cluster. Service accounts are namespaced. namespaces of a cluster. No matter what namespace you look at, a particular
- Typically, a cluster's user accounts might be synced from a corporate username that represents a user represents the same user.
In Kubernetes, service accounts are namespaced: two different namespaces can
contain ServiceAccounts that have identical names.
- Typically, a cluster's user accounts might be synchronised from a corporate
database, where new user account creation requires special privileges and is database, where new user account creation requires special privileges and is
tied to complex business processes. Service account creation is intended to be tied to complex business processes. By contrast, service account creation is
more lightweight, allowing cluster users to create service accounts for intended to be more lightweight, allowing cluster users to create service accounts
specific tasks by following the principle of least privilege. for specific tasks on demand. Separating ServiceAccount creation from the steps to
- Auditing considerations for humans and service accounts may differ. onboard human users makes it easier for workloads to following the principle of
- A config bundle for a complex system may include definition of various service least privilege.
- Auditing considerations for humans and service accounts may differ; the separation
makes that easier to achieve.
- A configuration bundle for a complex system may include definition of various service
accounts for components of that system. Because service accounts can be created accounts for components of that system. Because service accounts can be created
without many constraints and have namespaced names, such config is portable. without many constraints and have namespaced names, such configuration is
usually portable.
## Service account automation ## Bound service account token volume mechanism {#bound-service-account-token-volume}
Three separate components cooperate to implement the automation around service accounts:
- A `ServiceAccount` admission controller
- A Token controller
- A `ServiceAccount` controller
### ServiceAccount Admission Controller
The modification of pods is implemented via a plugin
called an [Admission Controller](/docs/reference/access-authn-authz/admission-controllers/).
It is part of the API server.
It acts synchronously to modify pods as they are created or updated. When this plugin is active
(and it is by default on most distributions), then it does the following when a pod is created or modified:
1. If the pod does not have a `ServiceAccount` set, it sets the `ServiceAccount` to `default`.
1. It ensures that the `ServiceAccount` referenced by the pod exists, and otherwise rejects it.
1. It adds a `volume` to the pod which contains a token for API access if neither the
ServiceAccount `automountServiceAccountToken` nor the Pod's `automountServiceAccountToken`
is set to `false`.
1. It adds a `volumeSource` to each container of the pod mounted at
`/var/run/secrets/kubernetes.io/serviceaccount`, if the previous step has created a volume
for the ServiceAccount token.
1. If the pod does not contain any `imagePullSecrets`, then `imagePullSecrets` of the
`ServiceAccount` are added to the pod.
#### Bound Service Account Token Volume
{{< feature-state for_k8s_version="v1.22" state="stable" >}} {{< feature-state for_k8s_version="v1.22" state="stable" >}}
The ServiceAccount admission controller will add the following projected volume instead of a By default, the Kubernetes control plane (specifically, the
Secret-based volume for the non-expiring service account token created by the Token controller. [ServiceAccount admission controller](#service-account-admission-controller))
adds a [projected volume](/docs/concepts/storage/projected-volumes/) to Pods,
and this volume includes a token for Kubernetes API access.
Here's an example of how that looks for a launched Pod:
```yaml ```yaml
- name: kube-api-access-<random-suffix> ...
projected: - name: kube-api-access-<random-suffix>
defaultMode: 420 # 0644 projected:
sources: sources:
- serviceAccountToken: - serviceAccountToken:
expirationSeconds: 3607 path: token # must match the path the app expects
path: token - configMap:
- configMap: items:
items: - key: ca.crt
- key: ca.crt path: ca.crt
path: ca.crt name: kube-root-ca.crt
name: kube-root-ca.crt - downwardAPI:
- downwardAPI: items:
items: - fieldRef:
- fieldRef: apiVersion: v1
apiVersion: v1 fieldPath: metadata.namespace
fieldPath: metadata.namespace path: namespace
path: namespace
``` ```
This projected volume consists of three sources: That manifest snippet defines a projected volume that consists of three sources. In this case,
each source also represents a single path within that volume. The three sources are:
1. A `serviceAccountToken` acquired from kube-apiserver via TokenRequest API. It will expire 1. A `serviceAccountToken` source, that contains a token that the kubelet acquires from kube-apiserver
after 1 hour by default or when the pod is deleted. It is bound to the pod and it has The kubelet fetches time-bound tokens using the TokenRequest API. A token served for a TokenRequest expires
its audience set to match the audience of the `kube-apiserver`. either when the pod is deleted or after a defined lifespan (by default, that is 1 hour).
1. A `configMap` containing a CA bundle used for verifying connections to the kube-apiserver. The token is bound to the specific Pod and has the kube-apiserver as its audience.
1. A `downwardAPI` that references the namespace of the pod. This mechanism superseded an earlier mechanism that added a volume based on a Secret,
where the Secret represented the ServiceAccount for the Pod, but did not expire.
1. A `configMap` source. The ConfigMap contains a bundle of certificate authority data. Pods can use these
certificates to make sure that they are connecting to your cluster's kube-apiserver (and not to middlebox
or an accidentally misconfigured peer).
1. A `downwardAPI` source that looks up the name of thhe namespace containing the Pod, and makes
that name information available to application code running inside the Pod.
See more details about [projected volumes](/docs/tasks/configure-pod-container/configure-projected-volume-storage/). Any container within the Pod that mounts this particular volume can access the above information.
### Token Controller {{< note >}}
There is no specific mechanism to invalidate a token issued via TokenRequest. If you no longer
trust a bound service account token for a Pod, you can delete that Pod. Deleting a Pod expires
its bound service account tokens.
{{< /note >}}
TokenController runs as part of `kube-controller-manager`. It acts asynchronously. It: ## Manual Secret management for ServiceAccounts
- watches ServiceAccount creation and creates a corresponding Versions of Kubernetes before v1.22 automatically created credentials for accessing
ServiceAccount token Secret to allow API access. the Kubernetes API. This older mechanism was based on creating token Secrets that
- watches ServiceAccount deletion and deletes all corresponding ServiceAccount could then be mounted into running Pods.
In more recent versions, including Kubernetes v{{< skew currentVersion >}}, API credentials
are [obtained directly](#bound-service-account-token-volume) using the
[TokenRequest](/docs/reference/kubernetes-api/authentication-resources/token-request-v1/) API,
and are mounted into Pods using a projected volume.
The tokens obtained using this method have bounded lifetimes, and are automatically
invalidated when the Pod they are mounted into is deleted.
You can still [manually create](/docs/tasks/configure-pod-container/configure-service-account/#manually-create-an-api-token-for-a-serviceaccount) a Secret to hold a service account token; for example, if you need a token that never expires.
Once you manually create a Secret and link it to a ServiceAccount, the Kubernetes control plane automatically populates the token into that Secret.
{{< note >}}
Although the manual mechanism for creating a long-lived ServiceAccount token exists,
using [TokenRequest](/docs/reference/kubernetes-api/authentication-resources/token-request-v1/)
to obtain short-lived API access tokens is recommended instead.
{{< /note >}}
## Control plane details
### Token controller
The service account token controller runs as part of `kube-controller-manager`.
This controller acts asynchronously. It:
- watches for ServiceAccount deletion and deletes all corresponding ServiceAccount
token Secrets. token Secrets.
- watches ServiceAccount token Secret addition, and ensures the referenced - watches for ServiceAccount token Secret addition, and ensures the referenced
ServiceAccount exists, and adds a token to the Secret if needed. ServiceAccount exists, and adds a token to the Secret if needed.
- watches Secret deletion and removes a reference from the corresponding - watches for Secret deletion and removes a reference from the corresponding
ServiceAccount if needed. ServiceAccount if needed.
You must pass a service account private key file to the token controller in You must pass a service account private key file to the token controller in
@ -123,39 +160,232 @@ Similarly, you must pass the corresponding public key to the `kube-apiserver`
using the `--service-account-key-file` flag. The public key will be used to using the `--service-account-key-file` flag. The public key will be used to
verify the tokens during authentication. verify the tokens during authentication.
#### To create additional API tokens ### ServiceAccount admission controller
A controller loop ensures a Secret with an API token exists for each The modification of pods is implemented via a plugin
ServiceAccount. To create additional API tokens for a ServiceAccount, create a called an [Admission Controller](/docs/reference/access-authn-authz/admission-controllers/).
Secret of type `kubernetes.io/service-account-token` with an annotation It is part of the API server.
referencing the ServiceAccount, and the controller will update it with a This admission controller acts synchronously to modify pods as they are created.
generated token: When this plugin is active (and it is by default on most distributions), then
it does the following when a Pod is created:
Below is a sample configuration for such a Secret: 1. If the pod does not have a `.spec.serviceAccountName` set, the admission controller sets the name of the
ServiceAccount for this incoming Pod to `default`.
1. The admission controller ensures that the ServiceAccount referenced by the incoming Pod exists. If there
is no ServiceAccount with a matching name, the admission controller rejects the incoming Pod. That check
applies even for the `default` ServiceAccount.
1. Provided that neither the ServiceAccount's `automountServiceAccountToken` field nor the
Pod's `automountServiceAccountToken` field is set to `false`:
- the admission controller mutates the incoming Pod, adding an extra
{{< glossary_tooltip text="volume" term_id="volume" >}} that contains
a token for API access.
- the admission controller adds a `volumeMount` to each container in the Pod,
skipping any containers that already have a volume mount defined for the path
`/var/run/secrets/kubernetes.io/serviceaccount`.
For Linux containers, that volume is mounted at `/var/run/secrets/kubernetes.io/serviceaccount`;
on Windows nodes, the mount is at the equivalent path.
1. If the spec of the incoming Pod does already contain any `imagePullSecrets`, then the
admission controller adds `imagePullSecrets`, copying them from the `ServiceAccount`.
### TokenRequest API
{{< feature-state for_k8s_version="v1.22" state="stable" >}}
You use the [TokenRequest](/docs/reference/kubernetes-api/authentication-resources/token-request-v1/)
subresource of a ServiceAccount to obtain a time-bound token for that ServiceAccount.
You don't need to call this to obtain an API token for use within a container, since
the kubelet sets this up for you using a _projected volume_.
If you want to use the TokenRequest API from `kubectl`, see
[Manually create an API token for a ServiceAccount](/docs/tasks/configure-pod-container/configure-service-account/#manually-create-an-api-token-for-a-serviceaccount).
The Kubernetes control plane (specifically, the ServiceAccount admission controller)
adds a projected volume to Pods, and the kubelet ensures that this volume contains a token
that lets containers authenticate as the right ServiceAccount.
(This mechanism superseded an earlier mechanism that added a volume based on a Secret,
where the Secret represented the ServiceAccount for the Pod but did not expire.)
Here's an example of how that looks for a launched Pod:
```yaml
...
- name: kube-api-access-<random-suffix>
projected:
defaultMode: 420 # decimal equivalent of octal 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
```
That manifest snippet defines a projected volume that combines information from three sources:
1. A `serviceAccountToken` source, that contains a token that the kubelet acquires from kube-apiserver
The kubelet fetches time-bound tokens using the TokenRequest API. A token served for a TokenRequest expires
either when the pod is deleted or after a defined lifespan (by default, that is 1 hour).
The token is bound to the specific Pod and has the kube-apiserver as its audience.
1. A `configMap` source. The ConfigMap contains a bundle of certificate authority data. Pods can use these
certificates to make sure that they are connecting to your cluster's kube-apiserver (and not to middlebox
or an accidentally misconfigured peer).
1. A `downwardAPI` source. This `downwardAPI` volume makes the name of the namespace container the Pod available
to application code running inside the Pod.
Any container within the Pod that mounts this volume can access the above information.
## Create additional API tokens {#create-token}
{{< caution >}}
Only create long-lived API tokens if the [token request](#tokenrequest-api) mechanism
is not suitable. The token request mechanism provides time-limited tokens; because these
expire, they represent a lower risk to information security.
{{< /caution >}}
To create a non-expiring, persisted API token for a ServiceAccount, create a
Secret of type `kubernetes.io/service-account-token` with an annotation
referencing the ServiceAccount. The control plane then generates a long-lived token and
updates that Secret with that generated token data.
Here is a sample manifest for such a Secret:
{{< codenew file="secret/serviceaccount/mysecretname.yaml" >}}
To create a Secret based on this example, run:
```shell
kubectl -n examplens create -f https://k8s.io/examples/secret/serviceaccount/mysecretname.yaml
```
To see the details for that Secret, run:
```shell
kubectl -n examplens describe secret mysecretname
```
The output is similar to:
```
Name: mysecretname
Namespace: examplens
Labels: <none>
Annotations: kubernetes.io/service-account.name=myserviceaccount
kubernetes.io/service-account.uid=8a85c4c4-8483-11e9-bc42-526af7764f64
Type: kubernetes.io/service-account-token
Data
====
ca.crt: 1362 bytes
namespace: 9 bytes
token: ...
```
If you launch a new Pod into the `examplens` namespace, it can use the `myserviceaccount`
service-account-token Secret that you just created.
## Delete/invalidate a ServiceAccount token {#delete-token}
If you know the name of the Secret that contains the token you want to remove:
```shell
kubectl delete secret name-of-secret
```
Otherwise, first find the Secret for the ServiceAccount.
```shell
# This assumes that you already have a namespace named 'examplens'
kubectl -n examplens get serviceaccount/example-automated-thing -o yaml
```
The output is similar to:
```yaml ```yaml
apiVersion: v1 apiVersion: v1
kind: Secret kind: ServiceAccount
metadata: metadata:
name: mysecretname
annotations: annotations:
kubernetes.io/service-account.name: myserviceaccount kubectl.kubernetes.io/last-applied-configuration: |
type: kubernetes.io/service-account-token {"apiVersion":"v1","kind":"ServiceAccount","metadata":{"annotations":{},"name":"example-automated-thing","namespace":"examplens"}}
creationTimestamp: "2019-07-21T07:07:07Z"
name: example-automated-thing
namespace: examplens
resourceVersion: "777"
selfLink: /api/v1/namespaces/examplens/serviceaccounts/example-automated-thing
uid: f23fd170-66f2-4697-b049-e1e266b7f835
secrets:
- name: example-automated-thing-token-zyxwv
``` ```
Then, delete the Secret you now know the name of:
```shell
kubectl -n examplens delete secret/example-automated-thing-token-zyxwv
```
The control plane spots that the ServiceAccount is missing its Secret,
and creates a replacement:
```shell ```shell
kubectl create -f ./secret.yaml kubectl -n examplens get serviceaccount/example-automated-thing -o yaml
kubectl describe secret mysecretname ```
```yaml
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
{"apiVersion":"v1","kind":"ServiceAccount","metadata":{"annotations":{},"name":"example-automated-thing","namespace":"examplens"}}
creationTimestamp: "2019-07-21T07:07:07Z"
name: example-automated-thing
namespace: examplens
resourceVersion: "1026"
selfLink: /api/v1/namespaces/examplens/serviceaccounts/example-automated-thing
uid: f23fd170-66f2-4697-b049-e1e266b7f835
secrets:
- name: example-automated-thing-token-4rdrh
``` ```
#### To delete/invalidate a ServiceAccount token Secret ## Clean up
If you created a namespace `examplens` to experiment with, you can remove it:
```shell ```shell
kubectl delete secret mysecretname kubectl delete namespace examplens
``` ```
## Control plane details
### ServiceAccount controller ### ServiceAccount controller
A ServiceAccount controller manages the ServiceAccounts inside namespaces, and A ServiceAccount controller manages the ServiceAccounts inside namespaces, and
ensures a ServiceAccount named "default" exists in every active namespace. ensures a ServiceAccount named "default" exists in every active namespace.
### Token controller
The service account token controller runs as part of `kube-controller-manager`.
This controller acts asynchronously. It:
- watches for ServiceAccount creation and creates a corresponding
ServiceAccount token Secret to allow API access.
- watches for ServiceAccount deletion and deletes all corresponding ServiceAccount
token Secrets.
- watches for ServiceAccount token Secret addition, and ensures the referenced
ServiceAccount exists, and adds a token to the Secret if needed.
- watches for Secret deletion and removes a reference from the corresponding
ServiceAccount if needed.
You must pass a service account private key file to the token controller in
the `kube-controller-manager` using the `--service-account-private-key-file`
flag. The private key is used to sign generated service account tokens.
Similarly, you must pass the corresponding public key to the `kube-apiserver`
using the `--service-account-key-file` flag. The public key will be used to
verify the tokens during authentication.
## {{% heading "whatsnext" %}}
- Read more details about [projected volumes](/docs/concepts/storage/projected-volumes/).

View File

@ -8,42 +8,63 @@ content_type: task
weight: 90 weight: 90
--- ---
<!-- overview --> Kubernetes offers two distinct ways for clients that run within your
A service account provides an identity for processes that run in a Pod. 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" >}}.
{{< note >}} A _service account_ provides an identity for processes that run in a Pod,
This document is a user introduction to Service Accounts and describes how service accounts behave in a cluster set up and maps to a ServiceAccount object. When you authenticate to the API
as recommended by the Kubernetes project. Your cluster administrator may have server, you identify yourself as a particular _user_. Kubernetes recognises
customized the behavior in your cluster, in which case this documentation may the concept of a user, however, Kubernetes itself does **not** have a User
not apply. API.
{{< /note >}}
When you (a human) access the cluster (for example, using `kubectl`), you are This task guide is about ServiceAccounts, which do exist in the Kubernetes
authenticated by the apiserver as a particular User Account (currently this is API. The guide shows you some ways to configure ServiceAccounts for Pods.
usually `admin`, unless your cluster administrator has customized your cluster). Processes in containers inside pods can also contact the apiserver.
When they do, they are authenticated as a particular Service Account (for example, `default`).
## {{% heading "prerequisites" %}} ## {{% heading "prerequisites" %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}} {{< include "task-tutorial-prereqs.md" >}}
<!-- steps --> <!-- steps -->
## Use the Default Service Account to access the API server ## Use the default service account to access the API server
When you create a pod, if you do not specify a service account, it is When Pods contact the API server, Pods authenticate as a particular
automatically assigned the `default` service account in the same namespace. ServiceAccount (for example, `default`). There is always at least one
If you get the raw json or yaml for a pod you have created (for example, `kubectl get pods/<podname> -o yaml`), ServiceAccount in each {{< glossary_tooltip text="namespace" term_id="namespace" >}}.
you can see the `spec.serviceAccountName` field has been
[automatically set](/docs/concepts/overview/working-with-objects/object-management/).
You can access the API from inside a pod using automatically mounted service account credentials, as described in Every Kubernetes namespace contains at least one ServiceAccount: the default
[Accessing the Cluster](/docs/tasks/access-application-cluster/access-cluster). ServiceAccount for that namespace, named `default`.
The API permissions of the service account depend on the If you do not specify a ServiceAccount when you create a Pod, Kubernetes
[authorization plugin and policy](/docs/reference/access-authn-authz/authorization/#authorization-modules) in use. automatically assigns the ServiceAccount named `default` in that namespace.
You can fetch the details for a Pod you have created. For example:
```shell
kubectl get pods/<podname> -o yaml
```
In the output, you see a field `spec.serviceAccountName`.
Kubernetes [automatically](/docs/user-guide/working-with-resources/#resources-are-automatically-modified)
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/user-guide/accessing-the-cluster/#accessing-the-api-from-a-pod) to learn more.
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.
### 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: 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:
```yaml ```yaml
apiVersion: v1 apiVersion: v1
kind: ServiceAccount kind: ServiceAccount
@ -53,8 +74,7 @@ automountServiceAccountToken: false
... ...
``` ```
In version 1.6+, you can also opt out of automounting API credentials for a particular pod: You can also opt out of automounting API credentials for a particular Pod:
```yaml ```yaml
apiVersion: v1 apiVersion: v1
kind: Pod kind: Pod
@ -66,12 +86,16 @@ spec:
... ...
``` ```
The pod spec takes precedence over the service account if both specify a `automountServiceAccountToken` value. If both the ServiceAccount and the Pod's `.spec` specify a value for
`automountServiceAccountToken`, the Pod spec takes precedence.
## Use Multiple Service Accounts ## Use more than one ServiceAccount {#use-multiple-service-accounts}
Every namespace has a default service account resource called `default`. Every namespace has at least one ServiceAccount: the default ServiceAccount
You can list this and any other serviceAccount resources in the namespace with this command: 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:
```shell ```shell
kubectl get serviceaccounts kubectl get serviceaccounts
@ -110,38 +134,73 @@ The output is similar to this:
apiVersion: v1 apiVersion: v1
kind: ServiceAccount kind: ServiceAccount
metadata: metadata:
creationTimestamp: 2015-06-16T00:12:59Z creationTimestamp: 2019-06-16T00:12:34Z
name: build-robot name: build-robot
namespace: default namespace: default
resourceVersion: "272500" resourceVersion: "272500"
uid: 721ab723-13bc-11e5-aec2-42010af0021e uid: 721ab723-13bc-11e5-aec2-42010af0021e
``` ```
You may use authorization plugins to [set permissions on service accounts](/docs/reference/access-authn-authz/rbac/#service-account-permissions). 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` To use a non-default service account, set the `spec.serviceAccountName`
field of a pod to the name of the service account you wish to use. field of a Pod to the name of the ServiceAccount you wish to use.
The service account has to exist at the time the pod is created, or it will be rejected. 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
You cannot update the service account of an already created pod. of a Pod that already exists.
{{< note >}} {{< note >}}
The `spec.serviceAccount` field is a deprecated alias for `spec.serviceAccountName`. 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 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). on the [pod template](/docs/concepts/workloads/pods#pod-templates).
{{< /note >}} {{< /note >}}
You can clean up the service account from this example like this:
### Cleanup {#cleanup-use-multiple-service-accounts}
If you tried creating `build-robot` ServiceAccount from the example above,
you can clean it up by running:
```shell ```shell
kubectl delete serviceaccount/build-robot kubectl delete serviceaccount/build-robot
``` ```
## Manually create a service account API token ## Manually create an API token for a ServiceAccount
Suppose we have an existing service account named "build-robot" as mentioned above, and we create Suppose you have an existing service account named "build-robot" as mentioned earlier.
a new secret manually.
You can get a time-limited API token for that ServiceAccount using `kubectl`:
```shell
kubectl create token admin-user
```
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).
{{< 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.
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.
{{< /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`.
```shell ```shell
kubectl apply -f - <<EOF kubectl apply -f - <<EOF
@ -155,9 +214,16 @@ type: kubernetes.io/service-account-token
EOF EOF
``` ```
Now you can confirm that the newly built secret is populated with an API token for the "build-robot" service account. If you view the Secret using:
```shell
kubectl get secret/build-robot-secret -o yaml
```
Any tokens for non-existent service accounts will be cleaned up by the token controller. 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.
```shell ```shell
kubectl describe secrets/build-robot-secret kubectl describe secrets/build-robot-secret
@ -183,11 +249,19 @@ token: ...
{{< note >}} {{< note >}}
The content of `token` is elided here. The content of `token` is elided 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.
{{< /note >}} {{< /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.
## Add ImagePullSecrets to a service account ## Add ImagePullSecrets to a service account
### Create an imagePullSecret First, [create an imagePullSecret](/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod).
Next, verify it has been created. For example:
- Create an imagePullSecret, as described in [Specifying ImagePullSecrets on a Pod](/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod). - Create an imagePullSecret, as described in [Specifying ImagePullSecrets on a Pod](/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod).
@ -211,41 +285,44 @@ The content of `token` is elided here.
### Add image pull secret to service account ### Add image pull secret to service account
Next, modify the default service account for the namespace to use this secret as an imagePullSecret. Next, modify the default service account for the namespace to use this Secret as an imagePullSecret.
```shell ```shell
kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "myregistrykey"}]}' kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "myregistrykey"}]}'
``` ```
You can instead use `kubectl edit`, or manually edit the YAML manifests as shown below: You can achieve the same outcome by editing the object manually:
```shell ```shell
kubectl get serviceaccounts default -o yaml > ./sa.yaml kubectl edit serviceaccount/default
``` ```
The output of the `sa.yaml` file is similar to this: The output of the `sa.yaml` file is similar to this:
Your selected text editor will open with a configuration looking something like this:
```yaml ```yaml
apiVersion: v1 apiVersion: v1
kind: ServiceAccount kind: ServiceAccount
metadata: metadata:
creationTimestamp: 2015-08-07T22:02:39Z creationTimestamp: 2021-07-07T22:02:39Z
name: default name: default
namespace: default namespace: default
resourceVersion: "243024" resourceVersion: "243024"
uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6 uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6
``` ```
Using your editor of choice (for example `vi`), open the `sa.yaml` file, delete line with key `resourceVersion`, add lines with `imagePullSecrets:` and save. 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.
The output of the `sa.yaml` file is similar to this: After you made those changes, the edited ServiceAccount looks something like this:
```yaml ```yaml
apiVersion: v1 apiVersion: v1
kind: ServiceAccount kind: ServiceAccount
metadata: metadata:
creationTimestamp: 2015-08-07T22:02:39Z creationTimestamp: 2021-07-07T22:02:39Z
name: default name: default
namespace: default namespace: default
uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6 uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6
@ -253,13 +330,7 @@ imagePullSecrets:
- name: myregistrykey - name: myregistrykey
``` ```
Finally replace the serviceaccount with the new updated `sa.yaml` file ### Verify that imagePullSecrets are set for new Pods
```shell
kubectl replace serviceaccount default -f ./sa.yaml
```
### Verify imagePullSecrets was added to pod spec
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: 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:
@ -274,12 +345,7 @@ The output is:
myregistrykey myregistrykey
``` ```
<!--## Adding Secrets to a service account. ## ServiceAccount token volume projection
TODO: Test and explain how to use additional non-K8s secrets with an existing service account.
-->
## Service Account Token Volume Projection
{{< feature-state for_k8s_version="v1.20" state="stable" >}} {{< feature-state for_k8s_version="v1.20" state="stable" >}}
@ -287,31 +353,31 @@ TODO: Test and explain how to use additional non-K8s secrets with an existing se
To enable and use token request projection, you must specify each of the following To enable and use token request projection, you must specify each of the following
command line arguments to `kube-apiserver`: command line arguments to `kube-apiserver`:
* `--service-account-issuer` `--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.
It can be used as 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-key-file`
* `--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-signing-key-file`
File containing PEM-encoded x509 RSA or ECDSA private or public keys, 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. : 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` `--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.
Path to the file that contains the current private key of the service account token issuer. The issuer signs issued ID tokens with this private key.
* `--api-audiences` (can be omitted)
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 the `--service-account-issuer` flag is configured and this flag is not, this field defaults to a single element list containing the issuer URL.
{{< /note >}} {{< /note >}}
The kubelet can also project a service account token into a Pod. You can 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 specify desired properties of the token, such as the audience and the validity
duration. These properties are not configurable on the default service account duration. These properties are _not_ configurable on the default ServiceAccount
token. The service account token will also become invalid against the API when token. The token will also become invalid against the API when either the Pod
the Pod or the ServiceAccount is deleted. or the ServiceAccount is deleted.
This behavior is configured on a PodSpec using a ProjectedVolume type called You can configure this behavior for the `spec` of a Pod using a
[ServiceAccountToken](/docs/concepts/storage/volumes/#projected). To provide a [projected volume](/docs/concepts/storage/volumes/#projected) type called
pod with a token with an audience of "vault" and a validity duration of two `ServiceAccountToken`.
hours, you would configure the following in your PodSpec:
### 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:
{{< codenew file="pods/pod-projected-svc-token.yaml" >}} {{< codenew file="pods/pod-projected-svc-token.yaml" >}}
@ -321,19 +387,24 @@ Create the Pod:
kubectl create -f https://k8s.io/examples/pods/pod-projected-svc-token.yaml 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 The kubelet will: request and store the token on behalf of the Pod; make
token available to the pod at a configurable file path, and refresh the token as it approaches expiration. the token available to the Pod at a configurable file path; and refresh
The kubelet proactively rotates the token if it is older than 80% of its total TTL, or if the token is older than 24 hours. 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.
The application is responsible for reloading the token when it rotates. Periodic reloading (e.g. once every 5 minutes) is sufficient for most use cases. 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.
## Service Account Issuer Discovery ### Service account issuer discovery
{{< feature-state for_k8s_version="v1.21" state="stable" >}} {{< feature-state for_k8s_version="v1.21" state="stable" >}}
The Service Account Issuer Discovery feature is enabled when the Service Account If you have enabled [token projection](#service-account-token-volume-projection)
Token Projection feature is enabled, as described for ServiceAccounts in your cluster, then you can also make use of the discovery
[above](#service-account-token-volume-projection). 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_.
{{< note >}} {{< note >}}
The issuer URL must comply with the The issuer URL must comply with the
@ -341,27 +412,16 @@ The issuer URL must comply with the
practice, this means it must use the `https` scheme, and should serve an OpenID practice, this means it must use the `https` scheme, and should serve an OpenID
provider configuration at `{service-account-issuer}/.well-known/openid-configuration`. provider configuration at `{service-account-issuer}/.well-known/openid-configuration`.
If the URL does not comply, the `ServiceAccountIssuerDiscovery` endpoints will If the URL does not comply, ServiceAccount issuer discovery endpoints are not
not be registered, even if the feature is enabled. registered or accessible.
{{< /note >}} {{< /note >}}
The Service Account Issuer Discovery feature enables federation of Kubernetes When enabled, the Kubernetes API server publishes an OpenID Provider
service account tokens issued by a cluster (the _identity provider_) with Configuration document via HTTP. The configuration document is published at
external systems (_relying parties_). `/.well-known/openid-configuration`.
The OpenID Provider Configuration is sometimes referred to as the _discovery document_.
When enabled, the Kubernetes API server provides an OpenID Provider The Kubernetes API server publishes the related
Configuration document at `/.well-known/openid-configuration` and the associated JSON Web Key Set (JWKS), also via HTTP, at `/openid/v1/jwks`.
JSON Web Key Set (JWKS) at `/openid/v1/jwks`. The OpenID Provider Configuration
is sometimes referred to as the _discovery document_.
Clusters include a default RBAC ClusterRole called
`system:service-account-issuer-discovery`. A default RBAC ClusterRoleBinding
assigns this role to the `system:serviceaccounts` group, which all service
accounts 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.
{{< note >}} {{< note >}}
The responses served at `/.well-known/openid-configuration` and The responses served at `/.well-known/openid-configuration` and
@ -370,6 +430,15 @@ compliant. Those documents contain only the parameters necessary to perform
validation of Kubernetes service account tokens. validation of Kubernetes service account tokens.
{{< /note >}} {{< /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.
The JWKS response contains public keys that a relying party can use to validate 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 the Kubernetes service account tokens. Relying parties first query for the
OpenID Provider Configuration, and use the `jwks_uri` field in the response to OpenID Provider Configuration, and use the `jwks_uri` field in the response to
@ -377,7 +446,7 @@ find the JWKS.
In many cases, Kubernetes API servers are not available on the public internet, 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 but public endpoints that serve cached responses from the API server can be made
available by users or service providers. In these cases, it is possible to 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 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 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 `--service-account-jwks-uri` flag to the API server. Like the issuer URL, the
@ -388,6 +457,13 @@ JWKS URI is required to use the `https` scheme.
See also: See also:
- [Cluster Admin Guide to Service Accounts](/docs/reference/access-authn-authz/service-accounts-admin/) * Read the [Cluster Admin Guide to Service Accounts](/docs/reference/access-authn-authz/service-accounts-admin/)
- [Service Account Signing Key Retrieval KEP](https://github.com/kubernetes/enhancements/tree/master/keps/sig-auth/1393-oidc-discovery) * Read about [Authorization in Kubernetes](/docs/reference/access-authn-authz/authorization/)
- [OIDC Discovery Spec](https://openid.net/specs/openid-connect-discovery-1_0.html) * 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](#service-account-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)

View File

@ -0,0 +1,7 @@
apiVersion: v1
kind: Secret
type: kubernetes.io/service-account-token
metadata:
name: mysecretname
annotations:
- kubernetes.io/service-account.name: myserviceaccount