New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
storage: document Windows projected volume limitations #30366
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
--- | ||
reviewers: | ||
- sftim | ||
- marosset | ||
- jsturtevant | ||
- zshihang | ||
title: Projected Volumes | ||
content_type: concept | ||
--- | ||
|
||
<!-- overview --> | ||
|
||
This document describes the current state of _projected volumes_ in Kubernetes. Familiarity with [volumes](/docs/concepts/storage/volumes/) is suggested. | ||
|
||
<!-- body --> | ||
|
||
## 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. | ||
Comment on lines
+74
to
+76
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
### 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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not a valid PowerShell script. |
||
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 >}} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. kubernetes/kubernetes#104693 (part ofhttps://github.com/kubernetes/enhancements/issues/2802) will deny pods with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. kubernetes/kubernetes#104693 will not be backported. So my plan was to get this merged and backported and then open a PR removing or updating the note. WDYT? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good! |
||
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 | ||
aravindhp marked this conversation as resolved.
Show resolved
Hide resolved
|
||
the Pod being stuck at `ContainerCreating` forever. So it is advised to not use | ||
the Linux only `RunAsUser` option with Windows Pods. | ||
{{< /note >}} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -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/) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit:
Suggested change
|
||||||
|
||||||
### quobyte (deprecated) {#quobyte} | ||||||
|
||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is there a link for this one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could not find a link for this in volumes so I just moved it over as is.