Update ServiceAccount tasks in light of TokenRequest
Now that TokenRequest is the default way to get a service account token for a Pod, update the task pages that relate to this.
This commit is contained in:
parent
f9db6ae934
commit
a4629cd19b
|
|
@ -19,7 +19,8 @@ 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 add and remove tokens from ServiceAccounts.
|
||||
guide also explains how to obtain or revoke tokens that represent
|
||||
ServiceAccounts.
|
||||
|
||||
<!-- body -->
|
||||
|
||||
|
|
@ -40,21 +41,126 @@ kubectl create namespace examplens
|
|||
Kubernetes distinguishes between the concept of a user account and a service account
|
||||
for a number of reasons:
|
||||
|
||||
- User accounts are for humans. Service accounts are for processes, which run
|
||||
in pods.
|
||||
- User accounts are intended to be global. Names must be unique across all
|
||||
namespaces of a cluster. In Kubernetes, service accounts are namespaced.
|
||||
- Typically, a cluster's user accounts might be synced from a corporate
|
||||
- User accounts are for humans. Service accounts are for application processes,
|
||||
which (for Kubernetes) run in containers that are part of pods.
|
||||
- User accounts are intended to be global: names must be unique across all
|
||||
namespaces of a cluster. No matter what namespace you look at, a particular
|
||||
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
|
||||
tied to complex business processes. Service account creation is intended to be
|
||||
more lightweight, allowing cluster users to create service accounts for
|
||||
specific tasks by following the principle of least privilege.
|
||||
- Auditing considerations for humans and service accounts may differ.
|
||||
- A config bundle for a complex system may include definition of various service
|
||||
tied to complex business processes. By contrast, service account creation is
|
||||
intended to be more lightweight, allowing cluster users to create service accounts
|
||||
for specific tasks on demand. Separating ServiceAccount creation from the steps to
|
||||
onboard human users makes it easier for workloads to following the principle of
|
||||
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
|
||||
without many constraints and have namespaced names, such config is portable.
|
||||
without many constraints and have namespaced names, such configuration is
|
||||
usually portable.
|
||||
|
||||
## ServiceAccount admission controller
|
||||
## Bound service account token volume mechanism {#bound-service-account-token-volume}
|
||||
|
||||
{{< feature-state for_k8s_version="v1.22" state="stable" >}}
|
||||
|
||||
By default, the Kubernetes control plane (specifically, the
|
||||
[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
|
||||
...
|
||||
- name: kube-api-access-<random-suffix>
|
||||
projected:
|
||||
sources:
|
||||
- serviceAccountToken:
|
||||
path: token # must match the path the app expects
|
||||
- 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 consists of three sources. In this case,
|
||||
each source also represents a single path within that volume. The three sources are:
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
Any container within the Pod that mounts this particular volume can access the above information.
|
||||
|
||||
{{< 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 >}}
|
||||
|
||||
## Manual Secret management for ServiceAccounts
|
||||
|
||||
Versions of Kubernetes before v1.22 automatically created 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](#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.
|
||||
- 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.
|
||||
|
||||
### ServiceAccount admission controller
|
||||
|
||||
The modification of pods is implemented via a plugin
|
||||
called an [Admission Controller](/docs/reference/access-authn-authz/admission-controllers/).
|
||||
|
|
@ -81,10 +187,18 @@ it does the following when a Pod is created:
|
|||
1. If the spec of the incoming Pod does already contain any `imagePullSecrets`, then the
|
||||
admission controller adds `imagePullSecrets`, copying them from the `ServiceAccount`.
|
||||
|
||||
### Bound service account token volume mechanism {#bound-service-account-token-volume}
|
||||
### 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.
|
||||
|
|
@ -101,7 +215,7 @@ Here's an example of how that looks for a launched Pod:
|
|||
defaultMode: 420 # decimal equivalent of octal 0644
|
||||
sources:
|
||||
- serviceAccountToken:
|
||||
expirationSeconds: 3597
|
||||
expirationSeconds: 3607
|
||||
path: token
|
||||
- configMap:
|
||||
items:
|
||||
|
|
@ -132,11 +246,16 @@ Any container within the Pod that mounts this volume can access the above inform
|
|||
|
||||
## Create additional API tokens {#create-token}
|
||||
|
||||
The control plane ensures that a Secret with an API token exists for each
|
||||
ServiceAccount. To create additional API tokens for a ServiceAccount, create a
|
||||
{{< 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, and the control plane will update that Secret with a
|
||||
generated token.
|
||||
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:
|
||||
|
||||
|
|
@ -232,9 +351,6 @@ secrets:
|
|||
- name: example-automated-thing-token-4rdrh
|
||||
```
|
||||
|
||||
You can see that there is now a new associated Secret with a different name. The
|
||||
old Secret is no longer valid.
|
||||
|
||||
## Clean up
|
||||
|
||||
If you created a namespace `examplens` to experiment with, you can remove it:
|
||||
|
|
|
|||
|
|
@ -169,8 +169,38 @@ 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`:
|
||||
|
||||
```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`
|
||||
with a special annotation, `kubernetes.io/service-account.name`.
|
||||
|
||||
```shell
|
||||
kubectl apply -f - <<EOF
|
||||
|
|
@ -225,6 +255,9 @@ Secret somewhere that your terminal / computer screen could be seen by an
|
|||
onlooker.
|
||||
{{< /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
|
||||
|
||||
First, [create an imagePullSecret](/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod).
|
||||
|
|
|
|||
Loading…
Reference in New Issue