diff --git a/content/en/docs/concepts/storage/projected-volumes.md b/content/en/docs/concepts/storage/projected-volumes.md new file mode 100644 index 0000000000000..a5914adb6f945 --- /dev/null +++ b/content/en/docs/concepts/storage/projected-volumes.md @@ -0,0 +1,123 @@ +--- +reviewers: +- sftim +- marosset +- jsturtevant +- zshihang +title: Projected Volumes +content_type: concept +--- + + + +This document describes the current state of _projected volumes_ in Kubernetes. Familiarity with [volumes](/docs/concepts/storage/volumes/) is suggested. + + + +## Introduction + +A `projected` volume maps several existing volume sources into the same directory. + +Currently, the following types of volume sources can be projected: + +* [`secret`](/docs/concepts/storage/volumes/#secret) +* [`downwardAPI`](/docs/concepts/storage/volumes/#downwardapi) +* [`configMap`](/docs/concepts/storage/volumes/#configmap) +* `serviceAccountToken` + +All sources are required to be in the same namespace as the Pod. For more details, +see the [all-in-one volume design document](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node/all-in-one-volume.md). + +### Example configuration with a secret, a downwardAPI, and a configMap {#example-configuration-secret-downwardapi-configmap} + +{{< codenew file="pods/storage/projected-secret-downwardapi-configmap.yaml" >}} + +### Example configuration: secrets with a non-default permission mode set {#example-configuration-secrets-nondefault-permission-mode} + +{{< codenew file="pods/storage/projected-secrets-nondefault-permission-mode.yaml" >}} + +Each projected volume source is listed in the spec under `sources`. The +parameters are nearly the same with two exceptions: + +* For secrets, the `secretName` field has been changed to `name` to be consistent + with ConfigMap naming. +* The `defaultMode` can only be specified at the projected level and not for each + volume source. However, as illustrated above, you can explicitly set the `mode` + for each individual projection. + +When the `TokenRequestProjection` feature is enabled, you can inject the token +for the current [service account](/docs/reference/access-authn-authz/authentication/#service-account-tokens) +into a Pod at a specified path. For example: + +{{< codenew file="pods/storage/projected-service-account-token.yaml" >}} + +The example Pod has a projected volume containing the injected service account +token. This token can be used by a Pod's containers to access the Kubernetes API +server. The `audience` field contains the intended audience of the +token. A recipient of the token must identify itself with an identifier specified +in the audience of the token, and otherwise should reject the token. This field +is optional and it defaults to the identifier of the API server. + +The `expirationSeconds` is the expected duration of validity of the service account +token. It defaults to 1 hour and must be at least 10 minutes (600 seconds). An administrator +can also limit its maximum value by specifying the `--service-account-max-token-expiration` +option for the API server. The `path` field specifies a relative path to the mount point +of the projected volume. + +{{< note >}} +A container using a projected volume source as a [`subPath`](/docs/concepts/storage/volumes/#using-subpath) +volume mount will not receive updates for those volume sources. +{{< /note >}} + +## SecurityContext interactions + +The [proposal for file permission handling in projected service account volume](https://github.com/kubernetes/enhancements/pull/1598) +enhancement introduced the projected files having the the correct owner +permissions set. + +### Linux + +In Linux pods that have a projected volume and `RunAsUser` set in the Pod +[`SecurityContext`](/docs/reference/kubernetes-api/workload-resources/pod-v1/#security-context), +the projected files have the correct ownership set including container user +ownership. + +### Windows + +In Windows pods that have a projected volume and `RunAsUsername` set in the +Pod `SecurityContext`, the ownership is not enforced due to the way user +accounts are managed in Windows. Windows stores and manages local user and group +accounts in a database file called Security Account Manager (SAM). Each +container maintains its own instance of the SAM database, to which the host has +no visibility into while the container is running. Windows containers are +designed to run the user mode portion of the OS in isolation from the host, +hence the maintenance of a virtual SAM database. As a result, the kubelet running +on the host does not have the ability to dynamically configure host file +ownership for virtualized container accounts. It is recommended that if files on +the host machine are to be shared with the container then they should be placed +into their own volume mount outside of `C:\`. + +By default, the projected files will have the following ownership as shown for +an example projected volume file: +```powershell +Path : Microsoft.PowerShell.Core\FileSystem::C:\var\run\secrets\kubernetes.io\serviceaccount\..2021_08_31_22_22_18.318230061\ca.crt +Owner : BUILTIN\Administrators +Group : NT AUTHORITY\SYSTEM +Access : NT AUTHORITY\SYSTEM Allow FullControl + BUILTIN\Administrators Allow FullControl + BUILTIN\Users Allow ReadAndExecute, Synchronize +Audit : +Sddl : O:BAG:SYD:AI(A;ID;FA;;;SY)(A;ID;FA;;;BA)(A;ID;0x1200a9;;;BU) +``` +This implies all administrator users like `ContainerAdministrator` will have +read, write and execute access while, non-administrator users will have read and +execute access. + +{{< note >}} +In general, granting the container access to the host is discouraged as it can +open the door for potential security exploits. + +Creating a Windows Pod with `RunAsUser` in it's `SecurityContext` will result in +the Pod being stuck at `ContainerCreating` forever. So it is advised to not use +the Linux only `RunAsUser` option with Windows Pods. +{{< /note >}} diff --git a/content/en/docs/concepts/storage/volumes.md b/content/en/docs/concepts/storage/volumes.md index 56694dee66c32..d3add9f8c558b 100644 --- a/content/en/docs/concepts/storage/volumes.md +++ b/content/en/docs/concepts/storage/volumes.md @@ -801,143 +801,8 @@ For more details, see the [Portworx volume](https://github.com/kubernetes/exampl ### projected -A `projected` volume maps several existing volume sources into the same directory. - -Currently, the following types of volume sources can be projected: - -* [`secret`](#secret) -* [`downwardAPI`](#downwardapi) -* [`configMap`](#configmap) -* `serviceAccountToken` - -All sources are required to be in the same namespace as the Pod. For more details, -see the [all-in-one volume design document](https://github.com/kubernetes/community/blob/master/contributors/design-proposals/node/all-in-one-volume.md). - -#### Example configuration with a secret, a downwardAPI, and a configMap {#example-configuration-secret-downwardapi-configmap} - -```yaml -apiVersion: v1 -kind: Pod -metadata: - name: volume-test -spec: - containers: - - name: container-test - image: busybox - volumeMounts: - - name: all-in-one - mountPath: "/projected-volume" - readOnly: true - volumes: - - name: all-in-one - projected: - sources: - - secret: - name: mysecret - items: - - key: username - path: my-group/my-username - - downwardAPI: - items: - - path: "labels" - fieldRef: - fieldPath: metadata.labels - - path: "cpu_limit" - resourceFieldRef: - containerName: container-test - resource: limits.cpu - - configMap: - name: myconfigmap - items: - - key: config - path: my-group/my-config -``` - -#### Example configuration: secrets with a non-default permission mode set {#example-configuration-secrets-nondefault-permission-mode} - -```yaml -apiVersion: v1 -kind: Pod -metadata: - name: volume-test -spec: - containers: - - name: container-test - image: busybox - volumeMounts: - - name: all-in-one - mountPath: "/projected-volume" - readOnly: true - volumes: - - name: all-in-one - projected: - sources: - - secret: - name: mysecret - items: - - key: username - path: my-group/my-username - - secret: - name: mysecret2 - items: - - key: password - path: my-group/my-password - mode: 511 -``` - -Each projected volume source is listed in the spec under `sources`. The -parameters are nearly the same with two exceptions: - -* For secrets, the `secretName` field has been changed to `name` to be consistent - with ConfigMap naming. -* The `defaultMode` can only be specified at the projected level and not for each - volume source. However, as illustrated above, you can explicitly set the `mode` - for each individual projection. - -When the `TokenRequestProjection` feature is enabled, you can inject the token -for the current [service account](/docs/reference/access-authn-authz/authentication/#service-account-tokens) -into a Pod at a specified path. For example: - -```yaml -apiVersion: v1 -kind: Pod -metadata: - name: sa-token-test -spec: - containers: - - name: container-test - image: busybox - volumeMounts: - - name: token-vol - mountPath: "/service-account" - readOnly: true - volumes: - - name: token-vol - projected: - sources: - - serviceAccountToken: - audience: api - expirationSeconds: 3600 - path: token -``` - -The example Pod has a projected volume containing the injected service account -token. This token can be used by a Pod's containers to access the Kubernetes API -server. The `audience` field contains the intended audience of the -token. A recipient of the token must identify itself with an identifier specified -in the audience of the token, and otherwise should reject the token. This field -is optional and it defaults to the identifier of the API server. - -The `expirationSeconds` is the expected duration of validity of the service account -token. It defaults to 1 hour and must be at least 10 minutes (600 seconds). An administrator -can also limit its maximum value by specifying the `--service-account-max-token-expiration` -option for the API server. The `path` field specifies a relative path to the mount point -of the projected volume. - -{{< note >}} -A container using a projected volume source as a [`subPath`](#using-subpath) volume mount will not -receive updates for those volume sources. -{{< /note >}} +A projected volume maps several existing volume sources into the same +directory. For more details, see [projected volumes](/docs/concepts/storage/projected-volumes/) ### quobyte (deprecated) {#quobyte} diff --git a/content/en/examples/pods/storage/projected-secret-downwardapi-configmap.yaml b/content/en/examples/pods/storage/projected-secret-downwardapi-configmap.yaml new file mode 100644 index 0000000000000..270db99dcd76b --- /dev/null +++ b/content/en/examples/pods/storage/projected-secret-downwardapi-configmap.yaml @@ -0,0 +1,35 @@ +apiVersion: v1 +kind: Pod +metadata: + name: volume-test +spec: + containers: + - name: container-test + image: busybox + volumeMounts: + - name: all-in-one + mountPath: "/projected-volume" + readOnly: true + volumes: + - name: all-in-one + projected: + sources: + - secret: + name: mysecret + items: + - key: username + path: my-group/my-username + - downwardAPI: + items: + - path: "labels" + fieldRef: + fieldPath: metadata.labels + - path: "cpu_limit" + resourceFieldRef: + containerName: container-test + resource: limits.cpu + - configMap: + name: myconfigmap + items: + - key: config + path: my-group/my-config diff --git a/content/en/examples/pods/storage/projected-secrets-nondefault-permission-mode.yaml b/content/en/examples/pods/storage/projected-secrets-nondefault-permission-mode.yaml new file mode 100644 index 0000000000000..f69b43161ebf6 --- /dev/null +++ b/content/en/examples/pods/storage/projected-secrets-nondefault-permission-mode.yaml @@ -0,0 +1,27 @@ +apiVersion: v1 +kind: Pod +metadata: + name: volume-test +spec: + containers: + - name: container-test + image: busybox + volumeMounts: + - name: all-in-one + mountPath: "/projected-volume" + readOnly: true + volumes: + - name: all-in-one + projected: + sources: + - secret: + name: mysecret + items: + - key: username + path: my-group/my-username + - secret: + name: mysecret2 + items: + - key: password + path: my-group/my-password + mode: 511 diff --git a/content/en/examples/pods/storage/projected-service-account-token.yaml b/content/en/examples/pods/storage/projected-service-account-token.yaml new file mode 100644 index 0000000000000..353271a067864 --- /dev/null +++ b/content/en/examples/pods/storage/projected-service-account-token.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Pod +metadata: + name: sa-token-test +spec: + containers: + - name: container-test + image: busybox + volumeMounts: + - name: token-vol + mountPath: "/service-account" + readOnly: true + volumes: + - name: token-vol + projected: + sources: + - serviceAccountToken: + audience: api + expirationSeconds: 3600 + path: token