Convert site to Hugo (#8316)

This commit converts content and layout to use Hugo.
This commit is contained in:
Bjørn Erik Pedersen
2018-05-05 18:00:51 +02:00
committed by k8s-ci-robot
parent 7745f0e0c5
commit 7f3b633aa0
2327 changed files with 10928 additions and 171503 deletions
+5
View File
@@ -0,0 +1,5 @@
---
title: "Configure Pods and Containers"
weight: 30
---
@@ -0,0 +1,281 @@
---
title: Assign CPU Resources to Containers and Pods
content_template: templates/task
---
{{% capture overview %}}
This page shows how to assign a CPU *request* and a CPU *limit* to
a Container. A Container is guaranteed to have as much CPU as it requests,
but is not allowed to use more CPU than its limit.
{{% /capture %}}
{{% capture prerequisites %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
Each node in your cluster must have at least 1 cpu.
A few of the steps on this page require that the
[Heapster](https://github.com/kubernetes/heapster) service is running
in your cluster. But if you don't have Heapster running, you can do most
of the steps, and it won't be a problem if you skip the Heapster steps.
If you are running minikube, run the following command to enable heapster:
```shell
minikube addons enable heapster
```
To see whether the Heapster service is running, enter this command:
```shell
kubectl get services --namespace=kube-system
```
If the heapster service is running, it shows in the output:
```shell
NAMESPACE NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-system heapster 10.11.240.9 <none> 80/TCP 6d
```
{{% /capture %}}
{{% capture steps %}}
## Create a namespace
Create a namespace so that the resources you create in this exercise are
isolated from the rest of your cluster.
```shell
kubectl create namespace cpu-example
```
## Specify a CPU request and a CPU limit
To specify a CPU request for a Container, include the `resources:requests` field
in the Container's resource manifest. To specify a CPU limit, include `resources:limits`.
In this exercise, you create a Pod that has one Container. The Container has a CPU
request of 0.5 cpu and a CPU limit of 1 cpu. Here's the configuration file
for the Pod:
{{< code file="cpu-request-limit.yaml" >}}
In the configuration file, the `args` section provides arguments for the Container when it starts.
The `-cpus "2"` argument tells the Container to attempt to use 2 cpus.
Create the Pod:
```shell
kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/cpu-request-limit.yaml --namespace=cpu-example
```
Verify that the Pod's Container is running:
```shell
kubectl get pod cpu-demo --namespace=cpu-example
```
View detailed information about the Pod:
```shell
kubectl get pod cpu-demo --output=yaml --namespace=cpu-example
```
The output shows that the one Container in the Pod has a CPU request of 500 millicpu
and a CPU limit of 1 cpu.
```shell
resources:
limits:
cpu: "1"
requests:
cpu: 500m
```
Start a proxy so that you can call the heapster service:
```shell
kubectl proxy
```
In another command window, get the CPU usage rate from the heapster service:
```
curl http://localhost:8001/api/v1/namespaces/kube-system/services/heapster/proxy/api/v1/model/namespaces/cpu-example/pods/cpu-demo/metrics/cpu/usage_rate
```
The output shows that the Pod is using 974 millicpu, which is just a bit less than
the limit of 1 cpu specified in the Pod's configuration file.
```json
{
"timestamp": "2017-06-22T18:48:00Z",
"value": 974
}
```
Recall that by setting `-cpu "2"`, you configured the Container to attempt to use 2 cpus.
But the Container is only being allowed to use about 1 cpu. The Container's CPU use is being
throttled, because the Container is attempting to use more CPU resources than its limit.
{{< note >}}
**Note:** There's another possible explanation for the CPU throttling. The Node might not have
enough CPU resources available. Recall that the prerequisites for this exercise require that each of
your Nodes has at least 1 cpu. If your Container is running on a Node that has only 1 cpu, the Container
cannot use more than 1 cpu regardless of the CPU limit specified for the Container.
{{< /note >}}
## CPU units
The CPU resource is measured in *cpu* units. One cpu, in Kubernetes, is equivalent to:
* 1 AWS vCPU
* 1 GCP Core
* 1 Azure vCore
* 1 Hyperthread on a bare-metal Intel processor with Hyperthreading
Fractional values are allowed. A Container that requests 0.5 cpu is guaranteed half as much
CPU as a Container that requests 1 cpu. You can use the suffix m to mean milli. For example
100m cpu, 100 millicpu, and 0.1 cpu are all the same. Precision finer than 1m is not allowed.
CPU is always requested as an absolute quantity, never as a relative quantity; 0.1 is the same
amount of CPU on a single-core, dual-core, or 48-core machine.
Delete your Pod:
```shell
kubectl delete pod cpu-demo --namespace=cpu-example
```
## Specify a CPU request that is too big for your Nodes
CPU requests and limits are associated with Containers, but it is useful to think
of a Pod as having a CPU request and limit. The CPU request for a Pod is the sum
of the CPU requests for all the Containers in the Pod. Likewise, the CPU limit for
a Pod is the sum of the CPU limits for all the Containers in the Pod.
Pod scheduling is based on requests. A Pod is scheduled to run on a Node only if
the Node has enough CPU resources available to satisfy the Pods CPU request.
In this exercise, you create a Pod that has a CPU request so big that it exceeds
the capacity of any Node in your cluster. Here is the configuration file for a Pod
that has one Container. The Container requests 100 cpu, which is likely to exceed the
capacity of any Node in your cluster.
{{< code file="cpu-request-limit-2.yaml" >}}
Create the Pod:
```shell
kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/cpu-request-limit-2.yaml --namespace=cpu-example
```
View the Pod's status:
```shell
kubectl get pod cpu-demo-2 --namespace=cpu-example
```
The output shows that the Pod's status is Pending. That is, the Pod has not been
scheduled to run on any Node, and it will remain in the Pending state indefinitely:
```
kubectl get pod cpu-demo-2 --namespace=cpu-example
NAME READY STATUS RESTARTS AGE
cpu-demo-2 0/1 Pending 0 7m
```
View detailed information about the Pod, including events:
```shell
kubectl describe pod cpu-demo-2 --namespace=cpu-example
```
The output shows that the Container cannot be scheduled because of insufficient
CPU resources on the Nodes:
```shell
Events:
Reason Message
------ -------
FailedScheduling No nodes are available that match all of the following predicates:: Insufficient cpu (3).
```
Delete your Pod:
```shell
kubectl delete pod cpu-demo-2 --namespace=cpu-example
```
## If you dont specify a CPU limit
If you dont specify a CPU limit for a Container, then one of these situations applies:
* The Container has no upper bound on the CPU resources it can use. The Container
could use all of the CPU resources available on the Node where it is running.
* The Container is running in a namespace that has a default CPU limit, and the
Container is automatically assigned the default limit. Cluster administrators can use a
[LimitRange](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#limitrange-v1-core/)
to specify a default value for the CPU limit.
## Motivation for CPU requests and limits
By configuring the CPU requests and limits of the Containers that run in your
cluster, you can make efficient use of the CPU resources available on your cluster's
Nodes. By keeping a Pod's CPU request low, you give the Pod a good chance of being
scheduled. By having a CPU limit that is greater than the CPU request, you accomplish two things:
* The Pod can have bursts of activity where it makes use of CPU resources that happen to be available.
* The amount of CPU resources a Pod can use during a burst is limited to some reasonable amount.
## Clean up
Delete your namespace:
```shell
kubectl delete namespace cpu-example
```
{{% /capture %}}
{{% capture whatsnext %}}
### For app developers
* [Assign Memory Resources to Containers and Pods](/docs/tasks/configure-pod-container/assign-memory-resource/)
* [Configure Quality of Service for Pods](/docs/tasks/configure-pod-container/quality-service-pod/)
### For cluster administrators
* [Configure Default Memory Requests and Limits for a Namespace](/docs/tasks/administer-cluster/memory-default-namespace/)
* [Configure Default CPU Requests and Limits for a Namespace](/docs/tasks/administer-cluster/cpu-default-namespace/)
* [Configure Minimum and Maximum Memory Constraints for a Namespace](/docs/tasks/administer-cluster/memory-constraint-namespace/)
* [Configure Minimum and Maximum CPU Constraints for a Namespace](/docs/tasks/administer-cluster/cpu-constraint-namespace/)
* [Configure Memory and CPU Quotas for a Namespace](/docs/tasks/administer-cluster/quota-memory-cpu-namespace/)
* [Configure a Pod Quota for a Namespace](/docs/tasks/administer-cluster/quota-pod-namespace/)
* [Configure Quotas for API Objects](/docs/tasks/administer-cluster/quota-api-object/)
{{% /capture %}}
@@ -0,0 +1,375 @@
---
title: Assign Memory Resources to Containers and Pods
content_template: templates/task
---
{{% capture overview %}}
This page shows how to assign a memory *request* and a memory *limit* to a
Container. A Container is guaranteed to have as much memory as it requests,
but is not allowed to use more memory than its limit.
{{% /capture %}}
{{% capture prerequisites %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
Each node in your cluster must have at least 300 MiB of memory.
A few of the steps on this page require that the
[Heapster](https://github.com/kubernetes/heapster) service is running
in your cluster. But if you don't have Heapster running, you can do most
of the steps, and it won't be a problem if you skip the Heapster steps.
If you are running minikube, run the following command to enable heapster:
```shell
minikube addons enable heapster
```
To see whether the Heapster service is running, enter this command:
```shell
kubectl get services --namespace=kube-system
```
If the Heapster service is running, it shows in the output:
```shell
NAMESPACE NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-system heapster 10.11.240.9 <none> 80/TCP 6d
```
{{% /capture %}}
{{% capture steps %}}
## Create a namespace
Create a namespace so that the resources you create in this exercise are
isolated from the rest of your cluster.
```shell
kubectl create namespace mem-example
```
## Specify a memory request and a memory limit
To specify a memory request for a Container, include the `resources:requests` field
in the Container's resource manifest. To specify a memory limit, include `resources:limits`.
In this exercise, you create a Pod that has one Container. The Container has a memory
request of 100 MiB and a memory limit of 200 MiB. Here's the configuration file
for the Pod:
{{< code file="memory-request-limit.yaml" >}}
In the configuration file, the `args` section provides arguments for the Container when it starts.
The `"--vm-bytes", "150M"` arguments tell the Container to attempt to allocate 150 MiB of memory.
Create the Pod:
```shell
kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/memory-request-limit.yaml --namespace=mem-example
```
Verify that the Pod's Container is running:
```shell
kubectl get pod memory-demo --namespace=mem-example
```
View detailed information about the Pod:
```shell
kubectl get pod memory-demo --output=yaml --namespace=mem-example
```
The output shows that the one Container in the Pod has a memory request of 100 MiB
and a memory limit of 200 MiB.
```yaml
...
resources:
limits:
memory: 200Mi
requests:
memory: 100Mi
...
```
Start a proxy so that you can call the Heapster service:
```shell
kubectl proxy
```
In another command window, get the memory usage from the Heapster service:
```
curl http://localhost:8001/api/v1/namespaces/kube-system/services/heapster/proxy/api/v1/model/namespaces/mem-example/pods/memory-demo/metrics/memory/usage
```
The output shows that the Pod is using about 162,900,000 bytes of memory, which
is about 150 MiB. This is greater than the Pod's 100 MiB request, but within the
Pod's 200 MiB limit.
```json
{
"timestamp": "2017-06-20T18:54:00Z",
"value": 162856960
}
```
Delete your Pod:
```shell
kubectl delete pod memory-demo --namespace=mem-example
```
## Exceed a Container's memory limit
A Container can exceed its memory request if the Node has memory available. But a Container
is not allowed to use more than its memory limit. If a Container allocates more memory than
its limit, the Container becomes a candidate for termination. If the Container continues to
consume memory beyond its limit, the Container is terminated. If a terminated Container is
restartable, the kubelet will restart it, as with any other type of runtime failure.
In this exercise, you create a Pod that attempts to allocate more memory than its limit.
Here is the configuration file for a Pod that has one Container. The Container has a
memory request of 50 MiB and a memory limit of 100 MiB.
{{< code file="memory-request-limit-2.yaml" >}}
In the configuration file, in the `args` section, you can see that the Container
will attempt to allocate 250 MiB of memory, which is well above the 100 MiB limit.
Create the Pod:
```shell
kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/memory-request-limit-2.yaml --namespace=mem-example
```
View detailed information about the Pod:
```shell
kubectl get pod memory-demo-2 --namespace=mem-example
```
At this point, the Container might be running, or it might have been killed. If the
Container has not yet been killed, repeat the preceding command until you see that
the Container has been killed:
```shell
NAME READY STATUS RESTARTS AGE
memory-demo-2 0/1 OOMKilled 1 24s
```
Get a more detailed view of the Container's status:
```shell
kubectl get pod memory-demo-2 --output=yaml --namespace=mem-example
```
The output shows that the Container has been killed because it is out of memory (OOM).
```shell
lastState:
terminated:
containerID: docker://65183c1877aaec2e8427bc95609cc52677a454b56fcb24340dbd22917c23b10f
exitCode: 137
finishedAt: 2017-06-20T20:52:19Z
reason: OOMKilled
startedAt: null
```
The Container in this exercise is restartable, so the kubelet will restart it. Enter
this command several times to see that the Container gets repeatedly killed and restarted:
```shell
kubectl get pod memory-demo-2 --namespace=mem-example
```
The output shows that the Container gets killed, restarted, killed again, restarted again, and so on:
```
stevepe@sperry-1:~/steveperry-53.github.io$ kubectl get pod memory-demo-2 --namespace=mem-example
NAME READY STATUS RESTARTS AGE
memory-demo-2 0/1 OOMKilled 1 37s
stevepe@sperry-1:~/steveperry-53.github.io$ kubectl get pod memory-demo-2 --namespace=mem-example
NAME READY STATUS RESTARTS AGE
memory-demo-2 1/1 Running 2 40s
```
View detailed information about the Pod's history:
```
kubectl describe pod memory-demo-2 --namespace=mem-example
```
The output shows that the Container starts and fails repeatedly:
```
... Normal Created Created container with id 66a3a20aa7980e61be4922780bf9d24d1a1d8b7395c09861225b0eba1b1f8511
... Warning BackOff Back-off restarting failed container
```
View detailed information about your cluster's Nodes:
```
kubectl describe nodes
```
The output includes a record of the Container being killed because of an out-of-memory condition:
```
Warning OOMKilling Memory cgroup out of memory: Kill process 4481 (stress) score 1994 or sacrifice child
```
Delete your Pod:
```shell
kubectl delete pod memory-demo-2 --namespace=mem-example
```
## Specify a memory request that is too big for your Nodes
Memory requests and limits are associated with Containers, but it is useful to think
of a Pod as having a memory request and limit. The memory request for the Pod is the
sum of the memory requests for all the Containers in the Pod. Likewise, the memory
limit for the Pod is the sum of the limits of all the Containers in the Pod.
Pod scheduling is based on requests. A Pod is scheduled to run on a Node only if the Node
has enough available memory to satisfy the Pod's memory request.
In this exercise, you create a Pod that has a memory request so big that it exceeds the
capacity of any Node in your cluster. Here is the configuration file for a Pod that has one
Container. The Container requests 1000 GiB of memory, which is likely to exceed the capacity
of any Node in your cluster.
{{< code file="memory-request-limit-3.yaml" >}}
Create the Pod:
```shell
kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/memory-request-limit-3.yaml --namespace=mem-example
```
View the Pod's status:
```shell
kubectl get pod memory-demo-3 --namespace=mem-example
```
The output shows that the Pod's status is PENDING. That is, the Pod has not been
scheduled to run on any Node, and it will remain in the PENDING state indefinitely:
```
kubectl get pod memory-demo-3 --namespace=mem-example
NAME READY STATUS RESTARTS AGE
memory-demo-3 0/1 Pending 0 25s
```
View detailed information about the Pod, including events:
```shell
kubectl describe pod memory-demo-3 --namespace=mem-example
```
The output shows that the Container cannot be scheduled because of insufficient memory on the Nodes:
```shell
Events:
... Reason Message
------ -------
... FailedScheduling No nodes are available that match all of the following predicates:: Insufficient memory (3).
```
## Memory units
The memory resource is measured in bytes. You can express memory as a plain integer or a
fixed-point integer with one of these suffixes: E, P, T, G, M, K, Ei, Pi, Ti, Gi, Mi, Ki.
For example, the following represent approximately the same value:
```shell
128974848, 129e6, 129M , 123Mi
```
Delete your Pod:
```shell
kubectl delete pod memory-demo-3 --namespace=mem-example
```
## If you dont specify a memory limit
If you dont specify a memory limit for a Container, then one of these situations applies:
* The Container has no upper bound on the amount of memory it uses. The Container
could use all of the memory available on the Node where it is running.
* The Container is running in a namespace that has a default memory limit, and the
Container is automatically assigned the default limit. Cluster administrators can use a
[LimitRange](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#limitrange-v1-core)
to specify a default value for the memory limit.
## Motivation for memory requests and limits
By configuring memory requests and limits for the Containers that run in your
cluster, you can make efficient use of the memory resources available on your cluster's
Nodes. By keeping a Pod's memory request low, you give the Pod a good chance of being
scheduled. By having a memory limit that is greater than the memory request, you accomplish two things:
* The Pod can have bursts of activity where it makes use of memory that happens to be available.
* The amount of memory a Pod can use during a burst is limited to some reasonable amount.
## Clean up
Delete your namespace. This deletes all the Pods that you created for this task:
```shell
kubectl delete namespace mem-example
```
{{% /capture %}}
{{% capture whatsnext %}}
### For app developers
* [Assign CPU Resources to Containers and Pods](/docs/tasks/configure-pod-container/assign-cpu-resource/)
* [Configure Quality of Service for Pods](/docs/tasks/configure-pod-container/quality-service-pod/)
### For cluster administrators
* [Configure Default Memory Requests and Limits for a Namespace](/docs/tasks/administer-cluster/memory-default-namespace/)
* [Configure Default CPU Requests and Limits for a Namespace](/docs/tasks/administer-cluster/cpu-default-namespace/)
* [Configure Minimum and Maximum Memory Constraints for a Namespace](/docs/tasks/administer-cluster/memory-constraint-namespace/)
* [Configure Minimum and Maximum CPU Constraints for a Namespace](/docs/tasks/administer-cluster/cpu-constraint-namespace/)
* [Configure Memory and CPU Quotas for a Namespace](/docs/tasks/administer-cluster/quota-memory-cpu-namespace/)
* [Configure a Pod Quota for a Namespace](/docs/tasks/administer-cluster/quota-pod-namespace/)
* [Configure Quotas for API Objects](/docs/tasks/administer-cluster/quota-api-object/)
{{% /capture %}}
@@ -0,0 +1,82 @@
---
title: Assign Pods to Nodes
content_template: templates/task
---
{{% capture overview %}}
This page shows how to assign a Kubernetes Pod to a particular node in a
Kubernetes cluster.
{{% /capture %}}
{{% capture prerequisites %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
{{% /capture %}}
{{% capture steps %}}
## Add a label to a node
1. List the nodes in your cluster:
kubectl get nodes
The output is similar to this:
NAME STATUS AGE VERSION
worker0 Ready 1d v1.6.0+fff5156
worker1 Ready 1d v1.6.0+fff5156
worker2 Ready 1d v1.6.0+fff5156
1. Chose one of your nodes, and add a label to it:
kubectl label nodes <your-node-name> disktype=ssd
where `<your-node-name>` is the name of your chosen node.
1. Verify that your chosen node has a `disktype=ssd` label:
kubectl get nodes --show-labels
The output is similar to this:
NAME STATUS AGE VERSION LABELS
worker0 Ready 1d v1.6.0+fff5156 ...,disktype=ssd,kubernetes.io/hostname=worker0
worker1 Ready 1d v1.6.0+fff5156 ...,kubernetes.io/hostname=worker1
worker2 Ready 1d v1.6.0+fff5156 ...,kubernetes.io/hostname=worker2
In the preceding output, you can see that the `worker0` node has a
`disktype=ssd` label.
## Create a pod that gets scheduled to your chosen node
This pod configuration file describes a pod that has a node selector,
`disktype: ssd`. This means that the pod will get scheduled on a node that has
a `disktype=ssd` label.
{{< code file="pod.yaml" >}}
1. Use the configuration file to create a pod that will get scheduled on your
chosen node:
kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/pod.yaml
1. Verify that the pod is running on your chosen node:
kubectl get pods --output=wide
The output is similar to this:
NAME READY STATUS RESTARTS AGE IP NODE
nginx 1/1 Running 0 13s 10.200.0.4 worker0
{{% /capture %}}
{{% capture whatsnext %}}
Learn more about
[labels and selectors](/docs/concepts/overview/working-with-objects/labels/).
{{% /capture %}}
@@ -0,0 +1,101 @@
---
title: Attach Handlers to Container Lifecycle Events
content_template: templates/task
---
{{% capture overview %}}
This page shows how to attach handlers to Container lifecycle events. Kubernetes supports
the postStart and preStop events. Kubernetes sends the postStart event immediately
after a Container is started, and it sends the preStop event immediately before the
Container is terminated.
{{% /capture %}}
{{% capture prerequisites %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
{{% /capture %}}
{{% capture steps %}}
## Define postStart and preStop handlers
In this exercise, you create a Pod that has one Container. The Container has handlers
for the postStart and preStop events.
Here is the configuration file for the Pod:
{{< code file="lifecycle-events.yaml" >}}
In the configuration file, you can see that the postStart command writes a `message`
file to the Container's `/usr/share` directory. The preStop command shuts down
nginx gracefully. This is helpful if the Container is being terminated because of a failure.
Create the Pod:
kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/lifecycle-events.yaml
Verify that the Container in the Pod is running:
kubectl get pod lifecycle-demo
Get a shell into the Container running in your Pod:
kubectl exec -it lifecycle-demo -- /bin/bash
In your shell, verify that the `postStart` handler created the `message` file:
root@lifecycle-demo:/# cat /usr/share/message
The output shows the text written by the postStart handler:
Hello from the postStart handler
{{% /capture %}}
{{% capture discussion %}}
## Discussion
Kubernetes sends the postStart event immediately after the Container is created.
There is no guarantee, however, that the postStart handler is called before
the Container's entrypoint is called. The postStart handler runs asynchronously
relative to the Container's code, but Kubernetes' management of the container
blocks until the postStart handler completes. The Container's status is not
set to RUNNING until the postStart handler completes.
Kubernetes sends the preStop event immediately before the Container is terminated.
Kubernetes' management of the Container blocks until the preStop handler completes,
unless the Pod's grace period expires. For more details, see
[Termination of Pods](/docs/user-guide/pods/#termination-of-pods).
{{< note >}}
**Note**: Kubernetes only sends the preStop event when a Pod is *terminated*.
This means that the preStop hook is not invoked when the Pod is *completed*.
This limitation is tracked in [issue #55087](https://github.com/kubernetes/kubernetes/issues/55807).
{{< /note >}}
{{% /capture %}}
{{% capture whatsnext %}}
* Learn more about [Container lifecycle hooks](/docs/concepts/containers/container-lifecycle-hooks/).
* Learn more about the [lifecycle of a Pod](/docs/concepts/workloads/pods/pod-lifecycle/).
### Reference
* [Lifecycle](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#lifecycle-v1-core)
* [Container](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#container-v1-core)
* See `terminationGracePeriodSeconds` in [PodSpec](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podspec-v1-core)
{{% /capture %}}
@@ -0,0 +1,7 @@
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
@@ -0,0 +1,4 @@
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice
@@ -0,0 +1,304 @@
---
title: Configure Liveness and Readiness Probes
content_template: templates/task
---
{{% capture overview %}}
This page shows how to configure liveness and readiness probes for Containers.
The [kubelet](/docs/admin/kubelet/) uses liveness probes to know when to
restart a Container. For example, liveness probes could catch a deadlock,
where an application is running, but unable to make progress. Restarting a
Container in such a state can help to make the application more available
despite bugs.
The kubelet uses readiness probes to know when a Container is ready to start
accepting traffic. A Pod is considered ready when all of its Containers are ready.
One use of this signal is to control which Pods are used as backends for Services.
When a Pod is not ready, it is removed from Service load balancers.
{{% /capture %}}
{{% capture prerequisites %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
{{% /capture %}}
{{% capture steps %}}
## Define a liveness command
Many applications running for long periods of time eventually transition to
broken states, and cannot recover except by being restarted. Kubernetes provides
liveness probes to detect and remedy such situations.
In this exercise, you create a Pod that runs a Container based on the
`k8s.gcr.io/busybox` image. Here is the configuration file for the Pod:
{{< code file="exec-liveness.yaml" >}}
In the configuration file, you can see that the Pod has a single Container.
The `periodSeconds` field specifies that the kubelet should perform a liveness
probe every 5 seconds. The `initialDelaySeconds` field tells the kubelet that it
should wait 5 second before performing the first probe. To perform a probe, the
kubelet executes the command `cat /tmp/healthy` in the Container. If the
command succeeds, it returns 0, and the kubelet considers the Container to be alive and
healthy. If the command returns a non-zero value, the kubelet kills the Container
and restarts it.
When the Container starts, it executes this command:
```shell
/bin/sh -c "touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600"
```
For the first 30 seconds of the Container's life, there is a `/tmp/healthy` file.
So during the first 30 seconds, the command `cat /tmp/healthy` returns a success
code. After 30 seconds, `cat /tmp/healthy` returns a failure code.
Create the Pod:
```shell
kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/exec-liveness.yaml
```
Within 30 seconds, view the Pod events:
```shell
kubectl describe pod liveness-exec
```
The output indicates that no liveness probes have failed yet:
```shell
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
24s 24s 1 {default-scheduler } Normal Scheduled Successfully assigned liveness-exec to worker0
23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Pulling pulling image "k8s.gcr.io/busybox"
23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Pulled Successfully pulled image "k8s.gcr.io/busybox"
23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Created Created container with docker id 86849c15382e; Security:[seccomp=unconfined]
23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Started Started container with docker id 86849c15382e
```
After 35 seconds, view the Pod events again:
```shell
kubectl describe pod liveness-exec
```
At the bottom of the output, there are messages indicating that the liveness
probes have failed, and the containers have been killed and recreated.
```shell
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
37s 37s 1 {default-scheduler } Normal Scheduled Successfully assigned liveness-exec to worker0
36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Pulling pulling image "k8s.gcr.io/busybox"
36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Pulled Successfully pulled image "k8s.gcr.io/busybox"
36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Created Created container with docker id 86849c15382e; Security:[seccomp=unconfined]
36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Started Started container with docker id 86849c15382e
2s 2s 1 {kubelet worker0} spec.containers{liveness} Warning Unhealthy Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
```
Wait another 30 seconds, and verify that the Container has been restarted:
```shell
kubectl get pod liveness-exec
```
The output shows that `RESTARTS` has been incremented:
```shell
NAME READY STATUS RESTARTS AGE
liveness-exec 1/1 Running 1 1m
```
## Define a liveness HTTP request
Another kind of liveness probe uses an HTTP GET request. Here is the configuration
file for a Pod that runs a container based on the `k8s.gcr.io/liveness`
image.
{{< code file="http-liveness.yaml" >}}
In the configuration file, you can see that the Pod has a single Container.
The `periodSeconds` field specifies that the kubelet should perform a liveness
probe every 3 seconds. The `initialDelaySeconds` field tells the kubelet that it
should wait 3 seconds before performing the first probe. To perform a probe, the
kubelet sends an HTTP GET request to the server that is running in the Container
and listening on port 8080. If the handler for the server's `/healthz` path
returns a success code, the kubelet considers the Container to be alive and
healthy. If the handler returns a failure code, the kubelet kills the Container
and restarts it.
Any code greater than or equal to 200 and less than 400 indicates success. Any
other code indicates failure.
You can see the source code for the server in
[server.go](https://github.com/kubernetes/kubernetes/blob/master/test/images/liveness/server.go).
For the first 10 seconds that the Container is alive, the `/healthz` handler
returns a status of 200. After that, the handler returns a status of 500.
```go
http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
duration := time.Now().Sub(started)
if duration.Seconds() > 10 {
w.WriteHeader(500)
w.Write([]byte(fmt.Sprintf("error: %v", duration.Seconds())))
} else {
w.WriteHeader(200)
w.Write([]byte("ok"))
}
})
```
The kubelet starts performing health checks 3 seconds after the Container starts.
So the first couple of health checks will succeed. But after 10 seconds, the health
checks will fail, and the kubelet will kill and restart the Container.
To try the HTTP liveness check, create a Pod:
```shell
kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/http-liveness.yaml
```
After 10 seconds, view Pod events to verify that liveness probes have failed and
the Container has been restarted:
```shell
kubectl describe pod liveness-http
```
## Define a TCP liveness probe
A third type of liveness probe uses a TCP Socket. With this configuration, the
kubelet will attempt to open a socket to your container on the specified port.
If it can establish a connection, the container is considered healthy, if it
cant it is considered a failure.
{{< code file="tcp-liveness-readiness.yaml" >}}
As you can see, configuration for a TCP check is quite similar to an HTTP check.
This example uses both readiness and liveness probes. The kubelet will send the
first readiness probe 5 seconds after the container starts. This will attempt to
connect to the `goproxy` container on port 8080. If the probe succeeds, the pod
will be marked as ready. The kubelet will continue to run this check every 10
seconds.
In addition to the readiness probe, this configuration includes a liveness probe.
The kubelet will run the first liveness probe 15 seconds after the container
starts. Just like the readiness probe, this will attempt to connect to the
`goproxy` container on port 8080. If the liveness probe fails, the container
will be restarted.
## Use a named port
You can use a named
[ContainerPort](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#containerport-v1-core)
for HTTP or TCP liveness checks:
```yaml
ports:
- name: liveness-port
containerPort: 8080
hostPort: 8080
livenessProbe:
httpGet:
path: /healthz
port: liveness-port
```
## Define readiness probes
Sometimes, applications are temporarily unable to serve traffic.
For example, an application might need to load large data or configuration
files during startup. In such cases, you don't want to kill the application,
but you dont want to send it requests either. Kubernetes provides
readiness probes to detect and mitigate these situations. A pod with containers
reporting that they are not ready does not receive traffic through Kubernetes
Services.
Readiness probes are configured similarly to liveness probes. The only difference
is that you use the `readinessProbe` field instead of the `livenessProbe` field.
```yaml
readinessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
```
Configuration for HTTP and TCP readiness probes also remains identical to
liveness probes.
Readiness and liveness probes can be used in parallel for the same container.
Using both can ensure that traffic does not reach a container that is not ready
for it, and that containers are restarted when they fail.
## Configure Probes
{{< comment >}}
Eventually, some of this section could be moved to a concept topic.
{{< /comment >}}
[Probes](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#probe-v1-core) have a number of fields that
you can use to more precisely control the behavior of liveness and readiness
checks:
* `initialDelaySeconds`: Number of seconds after the container has started
before liveness or readiness probes are initiated.
* `periodSeconds`: How often (in seconds) to perform the probe. Default to 10
seconds. Minimum value is 1.
* `timeoutSeconds`: Number of seconds after which the probe times out. Defaults
to 1 second. Minimum value is 1.
* `successThreshold`: Minimum consecutive successes for the probe to be
considered successful after having failed. Defaults to 1. Must be 1 for
liveness. Minimum value is 1.
* `failureThreshold`: When a Pod starts and the probe fails, Kubernetes will
try `failureThreshold` times before giving up. Giving up in case of liveness probe means restarting the Pod. In case of readiness probe the Pod will be marked Unready.
Defaults to 3. Minimum value is 1.
[HTTP probes](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#httpgetaction-v1-core)
have additional fields that can be set on `httpGet`:
* `host`: Host name to connect to, defaults to the pod IP. You probably want to
set "Host" in httpHeaders instead.
* `scheme`: Scheme to use for connecting to the host (HTTP or HTTPS). Defaults to HTTP.
* `path`: Path to access on the HTTP server.
* `httpHeaders`: Custom headers to set in the request. HTTP allows repeated headers.
* `port`: Name or number of the port to access on the container. Number must be
in the range 1 to 65535.
For an HTTP probe, the kubelet sends an HTTP request to the specified path and
port to perform the check. The kubelet sends the probe to the pods IP address,
unless the address is overridden by the optional `host` field in `httpGet`. If
`scheme` field is set to `HTTPS`, the kubelet sends an HTTPS request skipping the
certificate verification. In most scenarios, you do not want to set the `host` field.
Here's one scenario where you would set it. Suppose the Container listens on 127.0.0.1
and the Pod's `hostNetwork` field is true. Then `host`, under `httpGet`, should be set
to 127.0.0.1. If your pod relies on virtual hosts, which is probably the more common
case, you should not use `host`, but rather set the `Host` header in `httpHeaders`.
{{% /capture %}}
{{% capture whatsnext %}}
* Learn more about
[Container Probes](/docs/concepts/workloads/pods/pod-lifecycle/#container-probes).
### Reference
* [Pod](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#pod-v1-core)
* [Container](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#container-v1-core)
* [Probe](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#probe-v1-core)
{{% /capture %}}
@@ -0,0 +1,212 @@
---
title: Configure a Pod to Use a PersistentVolume for Storage
content_template: templates/task
---
{{% capture overview %}}
This page shows how to configure a Pod to use a PersistentVolumeClaim for storage.
Here is a summary of the process:
1. A cluster administrator creates a PersistentVolume that is backed by physical
storage. The administrator does not associate the volume with any Pod.
1. A cluster user creates a PersistentVolumeClaim, which gets automatically
bound to a suitable PersistentVolume.
1. The user creates a Pod that uses the PersistentVolumeClaim as storage.
{{% /capture %}}
{{% capture prerequisites %}}
* You need to have a Kubernetes cluster that has only one Node, and the kubectl
command-line tool must be configured to communicate with your cluster. If you
do not already have a single-node cluster, you can create one by using
[Minikube](/docs/getting-started-guides/minikube).
* Familiarize yourself with the material in
[Persistent Volumes](/docs/concepts/storage/persistent-volumes/).
{{% /capture %}}
{{% capture steps %}}
## Create an index.html file on your Node
Open a shell to the Node in your cluster. How you open a shell depends on how
you set up your cluster. For example, if you are using Minikube, you can open a
shell to your Node by entering `minikube ssh`.
In your shell, create a `/mnt/data` directory:
mkdir /mnt/data
In the `/mnt/data` directory, create an `index.html` file:
echo 'Hello from Kubernetes storage' > /mnt/data/index.html
## Create a PersistentVolume
In this exercise, you create a *hostPath* PersistentVolume. Kubernetes supports
hostPath for development and testing on a single-node cluster. A hostPath
PersistentVolume uses a file or directory on the Node to emulate network-attached storage.
In a production cluster, you would not use hostPath. Instead a cluster administrator
would provision a network resource like a Google Compute Engine persistent disk,
an NFS share, or an Amazon Elastic Block Store volume. Cluster administrators can also
use [StorageClasses](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#storageclass-v1-storage)
to set up
[dynamic provisioning](http://blog.kubernetes.io/2016/10/dynamic-provisioning-and-storage-in-kubernetes.html).
Here is the configuration file for the hostPath PersistentVolume:
{{< code file="task-pv-volume.yaml" >}}
The configuration file specifies that the volume is at `/mnt/data` on the
cluster's Node. The configuration also specifies a size of 10 gibibytes and
an access mode of `ReadWriteOnce`, which means the volume can be mounted as
read-write by a single Node. It defines the [StorageClass name](/docs/concepts/storage/persistent-volumes/#class)
`manual` for the PersistentVolume, which will be used to bind
PersistentVolumeClaim requests to this PersistentVolume.
Create the PersistentVolume:
kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/task-pv-volume.yaml
View information about the PersistentVolume:
kubectl get pv task-pv-volume
The output shows that the PersistentVolume has a `STATUS` of `Available`. This
means it has not yet been bound to a PersistentVolumeClaim.
NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM STORAGECLASS REASON AGE
task-pv-volume 10Gi RWO Retain Available manual 4s
## Create a PersistentVolumeClaim
The next step is to create a PersistentVolumeClaim. Pods use PersistentVolumeClaims
to request physical storage. In this exercise, you create a PersistentVolumeClaim
that requests a volume of at least three gibibytes that can provide read-write
access for at least one Node.
Here is the configuration file for the PersistentVolumeClaim:
{{< code file="task-pv-claim.yaml" >}}
Create the PersistentVolumeClaim:
kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/task-pv-claim.yaml
After you create the PersistentVolumeClaim, the Kubernetes control plane looks
for a PersistentVolume that satisfies the claim's requirements. If the control
plane finds a suitable PersistentVolume with the same StorageClass, it binds the
claim to the volume.
Look again at the PersistentVolume:
kubectl get pv task-pv-volume
Now the output shows a `STATUS` of `Bound`.
NAME CAPACITY ACCESSMODES RECLAIMPOLICY STATUS CLAIM STORAGECLASS REASON AGE
task-pv-volume 10Gi RWO Retain Bound default/task-pv-claim manual 2m
Look at the PersistentVolumeClaim:
kubectl get pvc task-pv-claim
The output shows that the PersistentVolumeClaim is bound to your PersistentVolume,
`task-pv-volume`.
NAME STATUS VOLUME CAPACITY ACCESSMODES STORAGECLASS AGE
task-pv-claim Bound task-pv-volume 10Gi RWO manual 30s
## Create a Pod
The next step is to create a Pod that uses your PersistentVolumeClaim as a volume.
Here is the configuration file for the Pod:
{{< code file="task-pv-pod.yaml" >}}
Notice that the Pod's configuration file specifies a PersistentVolumeClaim, but
it does not specify a PersistentVolume. From the Pod's point of view, the claim
is a volume.
Create the Pod:
kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/task-pv-pod.yaml
Verify that the Container in the Pod is running;
kubectl get pod task-pv-pod
Get a shell to the Container running in your Pod:
kubectl exec -it task-pv-pod -- /bin/bash
In your shell, verify that nginx is serving the `index.html` file from the
hostPath volume:
root@task-pv-pod:/# apt-get update
root@task-pv-pod:/# apt-get install curl
root@task-pv-pod:/# curl localhost
The output shows the text that you wrote to the `index.html` file on the
hostPath volume:
Hello from Kubernetes storage
{{% /capture %}}
{{% capture discussion %}}
## Access control
Storage configured with a group ID (GID) allows writing only by Pods using the same
GID. Mismatched or missing GIDs cause permission denied errors. To reduce the
need for coordination with users, an administrator can annotate a PersistentVolume
with a GID. Then the GID is automatically added to any Pod that uses the
PersistentVolume.
Use the `pv.beta.kubernetes.io/gid` annotation as follows:
```yaml
kind: PersistentVolume
apiVersion: v1
metadata:
name: pv1
annotations:
pv.beta.kubernetes.io/gid: "1234"
```
When a Pod consumes a PersistentVolume that has a GID annotation, the annotated GID
is applied to all Containers in the Pod in the same way that GIDs specified in the
Pods security context are. Every GID, whether it originates from a PersistentVolume
annotation or the Pods specification, is applied to the first process run in
each Container.
{{< note >}}
**Note**: When a Pod consumes a PersistentVolume, the GIDs associated with the
PersistentVolume are not present on the Pod resource itself.
{{< /note >}}
{{% /capture %}}
{{% capture whatsnext %}}
* Learn more about [PersistentVolumes](/docs/concepts/storage/persistent-volumes/).
* Read the [Persistent Storage design document](https://git.k8s.io/community/contributors/design-proposals/storage/persistent-storage.md).
### Reference
* [PersistentVolume](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#persistentvolume-v1-core)
* [PersistentVolumeSpec](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#persistentvolumespec-v1-core)
* [PersistentVolumeClaim](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#persistentvolumeclaim-v1-core)
* [PersistentVolumeClaimSpec](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#persistentvolumeclaimspec-v1-core)
{{% /capture %}}
@@ -0,0 +1,626 @@
---
title: Configure a Pod to Use a ConfigMap
content_template: templates/task
---
{{% capture overview %}}
ConfigMaps allow you to decouple configuration artifacts from image content to keep containerized applications portable. This page provides a series of usage examples demonstrating how to create ConfigMaps and configure Pods using data stored in ConfigMaps.
{{% /capture %}}
{{% capture prerequisites %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
{{% /capture %}}
{{% capture steps %}}
## Create a ConfigMap
Use the `kubectl create configmap` command to create configmaps from [directories](#create-configmaps-from-directories), [files](#create-configmaps-from-files), or [literal values](#create-configmaps-from-literal-values):
```shell
kubectl create configmap <map-name> <data-source>
```
where \<map-name> is the name you want to assign to the ConfigMap and \<data-source> is the directory, file, or literal value to draw the data from.
The data source corresponds to a key-value pair in the ConfigMap, where
* key = the file name or the key you provided on the command line, and
* value = the file contents or the literal value you provided on the command line.
You can use [`kubectl describe`](/docs/reference/generated/kubectl/kubectl-commands/#describe) or
[`kubectl get`](/docs/reference/generated/kubectl/kubectl-commands/#get) to retrieve information
about a ConfigMap.
### Create ConfigMaps from directories
You can use `kubectl create configmap` to create a ConfigMap from multiple files in the same directory.
For example:
```shell
kubectl create configmap game-config --from-file=https://k8s.io/docs/tasks/configure-pod-container/configmap/kubectl
```
combines the contents of the `docs/tasks/configure-pod-container/configmap/kubectl/` directory
```shell
ls docs/tasks/configure-pod-container/configmap/kubectl/
game.properties
ui.properties
```
into the following ConfigMap:
```shell
kubectl describe configmaps game-config
Name: game-config
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
game.properties: 158 bytes
ui.properties: 83 bytes
```
The `game.properties` and `ui.properties` files in the `docs/tasks/configure-pod-container/configmap/kubectl/` directory are represented in the `data` section of the ConfigMap.
```shell
kubectl get configmaps game-config -o yaml
```
```yaml
apiVersion: v1
data:
game.properties: |
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
ui.properties: |
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice
kind: ConfigMap
metadata:
creationTimestamp: 2016-02-18T18:52:05Z
name: game-config
namespace: default
resourceVersion: "516"
selfLink: /api/v1/namespaces/default/configmaps/game-config
uid: b4952dc3-d670-11e5-8cd0-68f728db1985
```
### Create ConfigMaps from files
You can use `kubectl create configmap` to create a ConfigMap from an individual file, or from multiple files.
For example,
```shell
kubectl create configmap game-config-2 --from-file=https://k8s.io/docs/tasks/configure-pod-container/configmap/kubectl/game.properties
```
would produce the following ConfigMap:
```shell
kubectl describe configmaps game-config-2
Name: game-config-2
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
game.properties: 158 bytes
```
You can pass in the `--from-file` argument multiple times to create a ConfigMap from multiple data sources.
```shell
kubectl create configmap game-config-2 --from-file=https://k8s.io/docs/tasks/configure-pod-container/configmap/kubectl/game.properties --from-file=https://k8s.io/docs/tasks/configure-pod-container/configmap/kubectl/ui.properties
```
```shell
kubectl describe configmaps game-config-2
Name: game-config-2
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
game.properties: 158 bytes
ui.properties: 83 bytes
```
Use the option `--from-env-file` to create a ConfigMap from an env-file, for example:
```shell
# Env-files contain a list of environment variables.
# These syntax rules apply:
# Each line in an env file has to be in VAR=VAL format.
# Lines beginning with # (i.e. comments) are ignored.
# Blank lines are ignored.
# There is no special handling of quotation marks (i.e. they will be part of the ConfigMap value)).
cat docs/tasks/configure-pod-container/game-env-file.properties
enemies=aliens
lives=3
allowed="true"
# This comment and the empty line above it are ignored
```
```shell
kubectl create configmap game-config-env-file \
--from-env-file=docs/tasks/configure-pod-container/game-env-file.properties
```
would produce the following ConfigMap:
```shell
kubectl get configmap game-config-env-file -o yaml
```
```yaml
apiVersion: v1
data:
allowed: '"true"'
enemies: aliens
lives: "3"
kind: ConfigMap
metadata:
creationTimestamp: 2017-12-27T18:36:28Z
name: game-config-env-file
namespace: default
resourceVersion: "809965"
selfLink: /api/v1/namespaces/default/configmaps/game-config-env-file
uid: d9d1ca5b-eb34-11e7-887b-42010a8002b8
```
When passing `--from-env-file` multiple times to create a ConfigMap from multiple data sources, only the last env-file is used:
```shell
kubectl create configmap config-multi-env-files \
--from-env-file=docs/tasks/configure-pod-container/game-env-file.properties \
--from-env-file=docs/tasks/configure-pod-container/ui-env-file.properties
```
would produce the following ConfigMap:
```shell
kubectl get configmap config-multi-env-files -o yaml
```
```yaml
apiVersion: v1
data:
color: purple
how: fairlyNice
textmode: "true"
kind: ConfigMap
metadata:
creationTimestamp: 2017-12-27T18:38:34Z
name: config-multi-env-files
namespace: default
resourceVersion: "810136"
selfLink: /api/v1/namespaces/default/configmaps/config-multi-env-files
uid: 252c4572-eb35-11e7-887b-42010a8002b8
```
#### Define the key to use when creating a ConfigMap from a file
You can define a key other than the file name to use in the `data` section of your ConfigMap when using the `--from-file` argument:
```shell
kubectl create configmap game-config-3 --from-file=<my-key-name>=<path-to-file>
```
where `<my-key-name>` is the key you want to use in the ConfigMap and `<path-to-file>` is the location of the data source file you want the key to represent.
For example:
```shell
kubectl create configmap game-config-3 --from-file=game-special-key=https://k8s.io/docs/tasks/configure-pod-container/configmap/kubectl/game.properties
kubectl get configmaps game-config-3 -o yaml
```
```yaml
apiVersion: v1
data:
game-special-key: |
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
kind: ConfigMap
metadata:
creationTimestamp: 2016-02-18T18:54:22Z
name: game-config-3
namespace: default
resourceVersion: "530"
selfLink: /api/v1/namespaces/default/configmaps/game-config-3
uid: 05f8da22-d671-11e5-8cd0-68f728db1985
```
### Create ConfigMaps from literal values
You can use `kubectl create configmap` with the `--from-literal` argument to define a literal value from the command line:
```shell
kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm
```
You can pass in multiple key-value pairs. Each pair provided on the command line is represented as a separate entry in the `data` section of the ConfigMap.
```shell
kubectl get configmaps special-config -o yaml
```
```yaml
apiVersion: v1
data:
special.how: very
special.type: charm
kind: ConfigMap
metadata:
creationTimestamp: 2016-02-18T19:14:38Z
name: special-config
namespace: default
resourceVersion: "651"
selfLink: /api/v1/namespaces/default/configmaps/special-config
uid: dadce046-d673-11e5-8cd0-68f728db1985
```
## Define Pod environment variables using ConfigMap data
### Define a Pod environment variable with data from a single ConfigMap
1. Define an environment variable as a key-value pair in a ConfigMap:
```shell
kubectl create configmap special-config --from-literal=special.how=very
```
1. Assign the `special.how` value defined in the ConfigMap to the `SPECIAL_LEVEL_KEY` environment variable in the Pod specification.
```shell
kubectl edit pod dapi-test-pod
```
```yaml
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: k8s.gcr.io/busybox
command: [ "/bin/sh", "-c", "env" ]
env:
# Define the environment variable
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
# The ConfigMap containing the value you want to assign to SPECIAL_LEVEL_KEY
name: special-config
# Specify the key associated with the value
key: special.how
restartPolicy: Never
```
1. Save the changes to the Pod specification. Now, the Pod's output includes `SPECIAL_LEVEL_KEY=very`.
### Define Pod environment variables with data from multiple ConfigMaps
1. As with the previous example, create the ConfigMaps first.
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
special.how: very
```
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: env-config
namespace: default
data:
log_level: INFO
```
1. Define the environment variables in the Pod specification.
```yaml
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: k8s.gcr.io/busybox
command: [ "/bin/sh", "-c", "env" ]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: special.how
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: env-config
key: log_level
restartPolicy: Never
```
1. Save the changes to the Pod specification. Now, the Pod's output includes `SPECIAL_LEVEL_KEY=very` and `LOG_LEVEL=info`.
## Configure all key-value pairs in a ConfigMap as Pod environment variables
{{< note >}}
**Note:** This functionality is available to users running Kubernetes v1.6 and later.
{{< /note >}}
1. Create a ConfigMap containing multiple key-value pairs.
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
SPECIAL_LEVEL: very
SPECIAL_TYPE: charm
```
1. Use `envFrom` to define all of the ConfigMap's data as Pod environment variables. The key from the ConfigMap becomes the environment variable name in the Pod.
```yaml
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: k8s.gcr.io/busybox
command: [ "/bin/sh", "-c", "env" ]
envFrom:
- configMapRef:
name: special-config
restartPolicy: Never
```
1. Save the changes to the Pod specification. Now, the Pod's output includes `SPECIAL_LEVEL=very` and `SPECIAL_TYPE=charm`.
## Use ConfigMap-defined environment variables in Pod commands
You can use ConfigMap-defined environment variables in the `command` section of the Pod specification using the `$(VAR_NAME)` Kubernetes substitution syntax.
For example:
The following Pod specification
```yaml
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: k8s.gcr.io/busybox
command: [ "/bin/sh", "-c", "echo $(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: SPECIAL_LEVEL
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: SPECIAL_TYPE
restartPolicy: Never
```
produces the following output in the `test-container` container:
```shell
very charm
```
## Add ConfigMap data to a Volume
As explained in [Create ConfigMaps from files](#create-configmaps-from-files), when you create a ConfigMap using ``--from-file``, the filename becomes a key stored in the `data` section of the ConfigMap. The file contents become the key's value.
The examples in this section refer to a ConfigMap named special-config, shown below.
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
special.level: very
special.type: charm
```
### Populate a Volume with data stored in a ConfigMap
Add the ConfigMap name under the `volumes` section of the Pod specification.
This adds the ConfigMap data to the directory specified as `volumeMounts.mountPath` (in this case, `/etc/config`).
The `command` section references the `special.level` item stored in the ConfigMap.
```yaml
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: k8s.gcr.io/busybox
command: [ "/bin/sh", "-c", "ls /etc/config/" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
# Provide the name of the ConfigMap containing the files you want
# to add to the container
name: special-config
restartPolicy: Never
```
When the pod runs, the command (`"ls /etc/config/"`) produces the output below:
```shell
special.level
special.type
```
{{< caution >}}
**Caution:** If there are some files in the `/etc/config/` directory, they will be deleted.
{{< /caution >}}
### Add ConfigMap data to a specific path in the Volume
Use the `path` field to specify the desired file path for specific ConfigMap items.
In this case, the `special.level` item will be mounted in the `config-volume` volume at `/etc/config/keys`.
```yaml
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: k8s.gcr.io/busybox
command: [ "/bin/sh","-c","cat /etc/config/keys" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: special-config
items:
- key: special.level
path: keys
restartPolicy: Never
```
When the pod runs, the command (`"cat /etc/config/keys"`) produces the output below:
```shell
very
```
### Project keys to specific paths and file permissions
You can project keys to specific paths and specific permissions on a per-file
basis. The [Secrets](/docs/concepts/configuration/secret/#using-secrets-as-files-from-a-pod) user guide explains the syntax.
### Mounted ConfigMaps are updated automatically
When a ConfigMap already being consumed in a volume is updated, projected keys are eventually updated as well. Kubelet is checking whether the mounted ConfigMap is fresh on every periodic sync. However, it is using its local ttl-based cache for getting the current value of the ConfigMap. As a result, the total delay from the moment when the ConfigMap is updated to the moment when new keys are projected to the pod can be as long as kubelet sync period + ttl of ConfigMaps cache in kubelet.
{{< note >}}
**Note:** A container using a ConfigMap as a
[subPath](/docs/concepts/storage/volumes/#using-subpath) volume will not receive
ConfigMap updates.
{{< /note >}}
{{% /capture %}}
{{% capture discussion %}}
## Understanding ConfigMaps and Pods
The ConfigMap API resource stores configuration data as key-value pairs. The data can be consumed in pods or provide the configurations for system components such as controllers. ConfigMap is similar to [Secrets](/docs/concepts/configuration/secret/), but provides a means of working with strings that don't contain sensitive information. Users and system components alike can store configuration data in ConfigMap.
{{< note >}}
**Note:** ConfigMaps should reference properties files, not replace them. Think of the ConfigMap as representing something similar to the Linux `/etc` directory and its contents. For example, if you create a [Kubernetes Volume](/docs/concepts/storage/volumes/) from a ConfigMap, each data item in the ConfigMap is represented by an individual file in the volume.
{{< /note >}}
The ConfigMap's `data` field contains the configuration data. As shown in the example below, this can be simple -- like individual properties defined using `--from-literal` -- or complex -- like configuration files or JSON blobs defined using `--from-file`.
```yaml
kind: ConfigMap
apiVersion: v1
metadata:
creationTimestamp: 2016-02-18T19:14:38Z
name: example-config
namespace: default
data:
# example of a simple property defined using --from-literal
example.property.1: hello
example.property.2: world
# example of a complex property defined using --from-file
example.property.file: |-
property.1=value-1
property.2=value-2
property.3=value-3
```
### Restrictions
1. You must create a ConfigMap before referencing it in a Pod specification (unless you mark the ConfigMap as "optional"). If you reference a ConfigMap that doesn't exist, the Pod won't start. Likewise, references to keys that don't exist in the ConfigMap will prevent the pod from starting.
1. If you use `envFrom` to define environment variables from ConfigMaps, keys that are considered invalid will be skipped. The pod will be allowed to start, but the invalid names will be recorded in the event log (`InvalidVariableNames`). The log message lists each skipped key. For example:
```shell
kubectl get events
LASTSEEN FIRSTSEEN COUNT NAME KIND SUBOBJECT TYPE REASON SOURCE MESSAGE
0s 0s 1 dapi-test-pod Pod Warning InvalidEnvironmentVariableNames {kubelet, 127.0.0.1} Keys [1badkey, 2alsobad] from the EnvFrom configMap default/myconfig were skipped since they are considered invalid environment variable names.
```
1. ConfigMaps reside in a specific [namespace](/docs/concepts/overview/working-with-objects/namespaces/). A ConfigMap can only be referenced by pods residing in the same namespace.
1. Kubelet doesn't support the use of ConfigMaps for pods not found on the API server.
This includes pods created via the Kubelet's --manifest-url flag, --config flag, or the Kubelet REST API.
{{< note >}}
**Note:** These are not commonly-used ways to create pods.
{{< /note >}}
{{% /capture %}}
{{% capture whatsnext %}}
* Follow a real world example of [Configuring Redis using a ConfigMap](/docs/tutorials/configuration/configure-redis-using-configmap/).
{{% /capture %}}
@@ -0,0 +1,92 @@
---
title: Configure Pod Initialization
content_template: templates/task
---
{{% capture overview %}}
This page shows how to use an Init Container to initialize a Pod before an
application Container runs.
{{% /capture %}}
{{% capture prerequisites %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
{{% /capture %}}
{{% capture steps %}}
## Create a Pod that has an Init Container
In this exercise you create a Pod that has one application Container and one
Init Container. The init container runs to completion before the application
container starts.
Here is the configuration file for the Pod:
{{< code file="init-containers.yaml" >}}
In the configuration file, you can see that the Pod has a Volume that the init
container and the application container share.
The init container mounts the
shared Volume at `/work-dir`, and the application container mounts the shared
Volume at `/usr/share/nginx/html`. The init container runs the following command
and then terminates:
wget -O /work-dir/index.html http://kubernetes.io
Notice that the init container writes the `index.html` file in the root directory
of the nginx server.
Create the Pod:
kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/init-containers.yaml
Verify that the nginx container is running:
kubectl get pod init-demo
The output shows that the nginx container is running:
NAME READY STATUS RESTARTS AGE
init-demo 1/1 Running 0 1m
Get a shell into the nginx container running in the init-demo Pod:
kubectl exec -it init-demo -- /bin/bash
In your shell, send a GET request to the nginx server:
root@nginx:~# apt-get update
root@nginx:~# apt-get install curl
root@nginx:~# curl localhost
The output shows that nginx is serving the web page that was written by the init container:
<!Doctype html>
<html id="home">
<head>
...
"url": "http://kubernetes.io/"}</script>
</head>
<body>
...
<p>Kubernetes is open source giving you the freedom to take advantage ...</p>
...
{{% /capture %}}
{{% capture whatsnext %}}
* Learn more about
[communicating between Containers running in the same Pod](/docs/tasks/access-application-cluster/communicate-containers-same-pod-shared-volume/).
* Learn more about [Init Containers](/docs/concepts/workloads/pods/init-containers/).
* Learn more about [Volumes](/docs/concepts/storage/volumes/).
* Learn more about [Debugging Init Containers](/docs/tasks/debug-application-cluster/debug-init-containers/)
{{% /capture %}}
@@ -0,0 +1,64 @@
---
reviewers:
- jpeeler
- pmorie
title: Configure a Pod to Use a Projected Volume for Storage
content_template: templates/task
---
{{% capture overview %}}
This page shows how to use a [`projected`](/docs/concepts/storage/volumes/#projected) volume to mount several existing volume sources into the same directory. Currently, `secret`, `configMap`, and `downwardAPI` volumes can be projected.
{{% /capture %}}
{{% capture prerequisites %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
{{% /capture %}}
{{% capture steps %}}
## Configure a projected volume for a pod
In this exercise, you create username and password Secrets from local files. You then create a Pod that runs one Container, using a [`projected`](/docs/concepts/storage/volumes/#projected) Volume to mount the Secrets into the same shared directory.
Here is the configuration file for the Pod:
{{< code file="projected-volume.yaml" >}}
1. Create the Secrets:
# Create files containing the username and password:
echo -n "admin" > ./username.txt
echo -n "1f2d1e2e67df" > ./password.txt
# Package these files into secrets:
kubectl create secret generic user --from-file=./username.txt
kubectl create secret generic pass --from-file=./password.txt
1. Create the Pod:
kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/projected-volume.yaml
1. Verify that the Pod's Container is running, and then watch for changes to
the Pod:
kubectl get --watch pod test-projected-volume
The output looks like this:
NAME READY STATUS RESTARTS AGE
test-projected-volume 1/1 Running 0 14s
1. In another terminal, get a shell to the running Container:
kubectl exec -it test-projected-volume -- /bin/sh
1. In your shell, verify that the `projected-volume` directory contains your projected sources:
/ # ls /projected-volume/
{{% /capture %}}
{{% capture whatsnext %}}
* Learn more about [`projected`](/docs/concepts/storage/volumes/#projected) volumes.
* Read the [all-in-one volume](https://github.com/kubernetes/community/blob/{{< param "githubbranch" >}}/contributors/design-proposals/node/all-in-one-volume.md) design document.
{{% /capture %}}
@@ -0,0 +1,234 @@
---
reviewers:
- bprashanth
- liggitt
- thockin
title: Configure Service Accounts for Pods
---
A service account provides an identity for processes that run in a Pod.
*This is a user introduction to Service Accounts. See also the
[Cluster Admin Guide to Service Accounts](/docs/admin/service-accounts-admin/).*
{{< note >}}
**Note:** This document describes how service accounts behave in a cluster set up
as recommended by the Kubernetes project. Your cluster administrator may have
customized the behavior in your cluster, in which case this documentation may
not apply.
{{< /note >}}
When you (a human) access the cluster (for example, using `kubectl`), you are
authenticated by the apiserver as a particular User Account (currently this is
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`).
## 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
automatically assigned the `default` service account in the same namespace.
If you get the raw json or yaml for a pod you have created (for example, `kubectl get pods/podname -o yaml`),
you can see the `spec.serviceAccountName` field has been
[automatically set](/docs/user-guide/working-with-resources/#resources-are-automatically-modified).
You can access the API from inside a pod using automatically mounted service account credentials,
as described in [Accessing the Cluster](/docs/user-guide/accessing-the-cluster/#accessing-the-api-from-a-pod).
The API permissions a service account has depend on the [authorization plugin and policy](/docs/admin/authorization/#a-quick-note-on-service-accounts) in use.
In version 1.6+, you can opt out of automounting API credentials for a service account by setting
`automountServiceAccountToken: false` on the service account:
```yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: build-robot
automountServiceAccountToken: false
...
```
In version 1.6+, you can also opt out of automounting API credentials for a particular pod:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
serviceAccountName: build-robot
automountServiceAccountToken: false
...
```
The pod spec takes precedence over the service account if both specify a `automountServiceAccountToken` value.
## Use Multiple Service Accounts.
Every namespace has a default service account resource called `default`.
You can list this and any other serviceAccount resources in the namespace with this command:
```shell
$ kubectl get serviceAccounts
NAME SECRETS AGE
default 1 1d
```
You can create additional ServiceAccount objects like this:
```shell
$ cat > /tmp/serviceaccount.yaml <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: build-robot
EOF
$ kubectl create -f /tmp/serviceaccount.yaml
serviceaccount "build-robot" created
```
If you get a complete dump of the service account object, like this:
```shell
$ kubectl get serviceaccounts/build-robot -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: 2015-06-16T00:12:59Z
name: build-robot
namespace: default
resourceVersion: "272500"
selfLink: /api/v1/namespaces/default/serviceaccounts/build-robot
uid: 721ab723-13bc-11e5-aec2-42010af0021e
secrets:
- name: build-robot-token-bvbk5
```
then you will see that a token has automatically been created and is referenced by the service account.
You may use authorization plugins to [set permissions on service accounts](/docs/admin/authorization/#a-quick-note-on-service-accounts).
To use a non-default service account, simply set the `spec.serviceAccountName`
field of a pod to the name of the service account you wish to use.
The service account has to exist at the time the pod is created, or it will be rejected.
You cannot update the service account of an already created pod.
You can clean up the service account from this example like this:
```shell
$ kubectl delete serviceaccount/build-robot
```
## Manually create a service account API token.
Suppose we have an existing service account named "build-robot" as mentioned above, and we create
a new secret manually.
```shell
$ cat > /tmp/build-robot-secret.yaml <<EOF
apiVersion: v1
kind: Secret
metadata:
name: build-robot-secret
annotations:
kubernetes.io/service-account.name: build-robot
type: kubernetes.io/service-account-token
EOF
$ kubectl create -f /tmp/build-robot-secret.yaml
secret "build-robot-secret" created
```
Now you can confirm that the newly built secret is populated with an API token for the "build-robot" service account.
Any tokens for non-existent service accounts will be cleaned up by the token controller.
```shell
$ kubectl describe secrets/build-robot-secret
Name: build-robot-secret
Namespace: default
Labels: <none>
Annotations: kubernetes.io/service-account.name=build-robot
kubernetes.io/service-account.uid=da68f9c6-9d26-11e7-b84e-002dc52800da
Type: kubernetes.io/service-account-token
Data
====
ca.crt: 1338 bytes
namespace: 7 bytes
token: ...
```
{{< note >}}
**Note:** The content of `token` is elided here.
{{< /note >}}
## Add ImagePullSecrets to a service account
First, create an imagePullSecret, as described [here](/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod).
Next, verify it has been created. For example:
```shell
$ kubectl get secrets myregistrykey
NAME TYPE DATA AGE
myregistrykey   kubernetes.io/.dockerconfigjson   1       1d
```
Next, modify the default service account for the namespace to use this secret as an imagePullSecret.
```shell
kubectl patch serviceaccount default -p '{\"imagePullSecrets\": [{\"name\": \"acrkey\"}]}'
```
Interactive version requiring manual edit:
```shell
$ kubectl get serviceaccounts default -o yaml > ./sa.yaml
$ cat sa.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: 2015-08-07T22:02:39Z
name: default
namespace: default
resourceVersion: "243024"
selfLink: /api/v1/namespaces/default/serviceaccounts/default
uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6
secrets:
- name: default-token-uudge
$ vi sa.yaml
[editor session not shown]
[delete line with key "resourceVersion"]
[add lines with "imagePullSecrets:"]
$ cat sa.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: 2015-08-07T22:02:39Z
name: default
namespace: default
selfLink: /api/v1/namespaces/default/serviceaccounts/default
uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6
secrets:
- name: default-token-uudge
imagePullSecrets:
- name: myregistrykey
$ kubectl replace serviceaccount default -f ./sa.yaml
serviceaccounts/default
```
Now, any new pods created in the current namespace will have this added to their spec:
```yaml
spec:
imagePullSecrets:
- name: myregistrykey
```
<!--## Adding Secrets to a service account.
TODO: Test and explain how to use additional non-K8s secrets with an existing service account.
-->
@@ -0,0 +1,112 @@
---
title: Configure a Pod to Use a Volume for Storage
content_template: templates/task
---
{{% capture overview %}}
This page shows how to configure a Pod to use a Volume for storage.
A Container's file system lives only as long as the Container does, so when a
Container terminates and restarts, changes to the filesystem are lost. For more
consistent storage that is independent of the Container, you can use a
[Volume](/docs/concepts/storage/volumes/). This is especially important for stateful
applications, such as key-value stores and databases. For example, Redis is a
key-value cache and store.
{{% /capture %}}
{{% capture prerequisites %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
{{% /capture %}}
{{% capture steps %}}
## Configure a volume for a Pod
In this exercise, you create a Pod that runs one Container. This Pod has a
Volume of type
[emptyDir](/docs/concepts/storage/volumes/#emptydir)
that lasts for the life of the Pod, even if the Container terminates and
restarts. Here is the configuration file for the Pod:
{{< code file="pod-redis.yaml" >}}
1. Create the Pod:
kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/pod-redis.yaml
1. Verify that the Pod's Container is running, and then watch for changes to
the Pod:
kubectl get pod redis --watch
The output looks like this:
NAME READY STATUS RESTARTS AGE
redis 1/1 Running 0 13s
1. In another terminal, get a shell to the running Container:
kubectl exec -it redis -- /bin/bash
1. In your shell, go to `/data/redis`, and create a file:
root@redis:/data# cd /data/redis/
root@redis:/data/redis# echo Hello > test-file
1. In your shell, list the running processes:
root@redis:/data/redis# ps aux
The output is similar to this:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
redis 1 0.1 0.1 33308 3828 ? Ssl 00:46 0:00 redis-server *:6379
root 12 0.0 0.0 20228 3020 ? Ss 00:47 0:00 /bin/bash
root 15 0.0 0.0 17500 2072 ? R+ 00:48 0:00 ps aux
1. In your shell, kill the redis process:
root@redis:/data/redis# kill <pid>
where `<pid>` is the redis process ID (PID).
1. In your original terminal, watch for changes to the redis Pod. Eventually,
you will see something like this:
NAME READY STATUS RESTARTS AGE
redis 1/1 Running 0 13s
redis 0/1 Completed 0 6m
redis 1/1 Running 1 6m
At this point, the Container has terminated and restarted. This is because the
redis Pod has a
[restartPolicy](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podspec-v1-core)
of `Always`.
1. Get a shell into the restarted Container:
kubectl exec -it redis -- /bin/bash
1. In your shell, goto `/data/redis`, and verify that `test-file` is still there.
{{% /capture %}}
{{% capture whatsnext %}}
* See [Volume](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#volume-v1-core).
* See [Pod](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#pod-v1-core).
* In addition to the local disk storage provided by `emptyDir`, Kubernetes
supports many different network-attached storage solutions, including PD on
GCE and EBS on EC2, which are preferred for critical data, and will handle
details such as mounting and unmounting the devices on the nodes. See
[Volumes](/docs/concepts/storage/volumes/) for more details.
{{% /capture %}}
@@ -0,0 +1,17 @@
apiVersion: v1
kind: Pod
metadata:
name: cpu-demo-2
namespace: cpu-example
spec:
containers:
- name: cpu-demo-ctr-2
image: vish/stress
resources:
limits:
cpu: "100"
requests:
cpu: "100"
args:
- -cpus
- "2"
@@ -0,0 +1,17 @@
apiVersion: v1
kind: Pod
metadata:
name: cpu-demo
namespace: cpu-example
spec:
containers:
- name: cpu-demo-ctr
image: vish/stress
resources:
limits:
cpu: "1"
requests:
cpu: "0.5"
args:
- -cpus
- "2"
@@ -0,0 +1,21 @@
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec
spec:
containers:
- name: liveness
image: k8s.gcr.io/busybox
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
@@ -0,0 +1,13 @@
apiVersion: v1
kind: Pod
metadata:
name: extended-resource-demo-2
spec:
containers:
- name: extended-resource-demo-2-ctr
image: nginx
resources:
requests:
example.com/dongle: 2
limits:
example.com/dongle: 2
@@ -0,0 +1,13 @@
apiVersion: v1
kind: Pod
metadata:
name: extended-resource-demo
spec:
containers:
- name: extended-resource-demo-ctr
image: nginx
resources:
requests:
example.com/dongle: 3
limits:
example.com/dongle: 3
@@ -0,0 +1,147 @@
---
title: Assign Extended Resources to a Container
content_template: templates/task
---
{{% capture overview %}}
This page shows how to assign extended resources to a Container.
{{< feature-state state="stable" >}}
{{% /capture %}}
{{% capture prerequisites %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
Before you do this exercise, do the exercise in
[Advertise Extended Resources for a Node](/docs/tasks/administer-cluster/extended-resource-node/).
That will configure one of your Nodes to advertise a dongle resource.
{{% /capture %}}
{{% capture steps %}}
## Assign an extended resource to a Pod
To request an extended resource, include the `resources:requests` field in your
Container manifest. Extended resources are fully qualified with any domain outside of
`*.kubernetes.io/`. Valid extended resource names have the form `example.com/foo` where
`example.com` is replaced with your organization's domain and `foo` is a
descriptive resource name.
Here is the configuration file for a Pod that has one Container:
{{< code file="extended-resource-pod.yaml" >}}
In the configuration file, you can see that the Container requests 3 dongles.
Create a Pod:
```shell
kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/extended-resource-pod.yaml
```
Verify that the Pod is running:
```shell
kubectl get pod extended-resource-demo
```
Describe the Pod:
```shell
kubectl describe pod extended-resource-demo
```
The output shows dongle requests:
```yaml
Limits:
example.com/dongle: 3
Requests:
example.com/dongle: 3
```
## Attempt to create a second Pod
Here is the configuration file for a Pod that has one Container. The Container requests
two dongles.
{{< code file="extended-resource-pod-2.yaml" >}}
Kubernetes will not be able to satisfy the request for two dongles, because the first Pod
used three of the four available dongles.
Attempt to create a Pod:
```shell
kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/extended-resource-pod-2.yaml
```
Describe the Pod
```shell
kubectl describe pod extended-resource-demo-2
```
The output shows that the Pod cannot be scheduled, because there is no Node that has
2 dongles available:
```
Conditions:
Type Status
PodScheduled False
...
Events:
...
... Warning FailedScheduling pod (extended-resource-demo-2) failed to fit in any node
fit failure summary on nodes : Insufficient example.com/dongle (1)
```
View the Pod status:
```shell
kubectl get pod extended-resource-demo-2
```
The output shows that the Pod was created, but not scheduled to run on a Node.
It has a status of Pending:
```yaml
NAME READY STATUS RESTARTS AGE
extended-resource-demo-2 0/1 Pending 0 6m
```
## Clean up
Delete the Pod that you created for this exercise:
```shell
kubectl delete pod extended-resource-demo-2
```
{{% /capture %}}
{{% capture whatsnext %}}
### For application developers
* [Assign Memory Resources to Containers and Pods](/docs/tasks/configure-pod-container/assign-memory-resource/)
* [Assign CPU Resources to Containers and Pods](/docs/tasks/configure-pod-container/assign-cpu-resource/)
### For cluster administrators
* [Advertise Extended Resources for a Node](/docs/tasks/administer-cluster/extended-resource-node/)
{{% /capture %}}
@@ -0,0 +1,5 @@
enemies=aliens
lives=3
allowed="true"
# This comment and the empty line above it are ignored
@@ -0,0 +1,21 @@
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-http
spec:
containers:
- name: liveness
image: k8s.gcr.io/liveness
args:
- /server
livenessProbe:
httpGet:
path: /healthz
port: 8080
httpHeaders:
- name: X-Custom-Header
value: Awesome
initialDelaySeconds: 3
periodSeconds: 3
@@ -0,0 +1,30 @@
apiVersion: v1
kind: Pod
metadata:
name: init-demo
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: workdir
mountPath: /usr/share/nginx/html
# These containers are run during pod initialization
initContainers:
- name: install
image: busybox
command:
- wget
- "-O"
- "/work-dir/index.html"
- http://kubernetes.io
volumeMounts:
- name: workdir
mountPath: "/work-dir"
dnsPolicy: Default
volumes:
- name: workdir
emptyDir: {}
@@ -0,0 +1,16 @@
apiVersion: v1
kind: Pod
metadata:
name: lifecycle-demo
spec:
containers:
- name: lifecycle-demo-container
image: nginx
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
preStop:
exec:
command: ["/usr/sbin/nginx","-s","quit"]
@@ -0,0 +1,11 @@
apiVersion: v1
kind: LimitRange
metadata:
name: mem-limit-range
spec:
limits:
- default:
memory: 512Mi
defaultRequest:
memory: 256Mi
type: Container
@@ -0,0 +1,16 @@
apiVersion: v1
kind: Pod
metadata:
name: memory-demo-2
namespace: mem-example
spec:
containers:
- name: memory-demo-2-ctr
image: polinux/stress
resources:
requests:
memory: "50Mi"
limits:
memory: "100Mi"
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "250M", "--vm-hang", "1"]
@@ -0,0 +1,16 @@
apiVersion: v1
kind: Pod
metadata:
name: memory-demo-3
namespace: mem-example
spec:
containers:
- name: memory-demo-3-ctr
image: polinux/stress
resources:
limits:
memory: "1000Gi"
requests:
memory: "1000Gi"
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]
@@ -0,0 +1,16 @@
apiVersion: v1
kind: Pod
metadata:
name: memory-demo
namespace: mem-example
spec:
containers:
- name: memory-demo-ctr
image: polinux/stress
resources:
limits:
memory: "200Mi"
requests:
memory: "100Mi"
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]
@@ -0,0 +1,14 @@
apiVersion: v1
kind: Pod
metadata:
name: redis
spec:
containers:
- name: redis
image: redis
volumeMounts:
- name: redis-storage
mountPath: /data/redis
volumes:
- name: redis-storage
emptyDir: {}
@@ -0,0 +1,13 @@
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd
@@ -0,0 +1,11 @@
apiVersion: v1
kind: Pod
metadata:
name: private-reg
spec:
containers:
- name: private-reg-container
image: <your-private-image>
imagePullSecrets:
- name: regcred
@@ -0,0 +1,23 @@
apiVersion: v1
kind: Pod
metadata:
name: test-projected-volume
spec:
containers:
- name: test-projected-volume
image: busybox
args:
- sleep
- "86400"
volumeMounts:
- name: all-in-one
mountPath: "/projected-volume"
readOnly: true
volumes:
- name: all-in-one
projected:
sources:
- secret:
name: user
- secret:
name: pass
@@ -0,0 +1,144 @@
---
title: Pull an Image from a Private Registry
content_template: templates/task
---
{{% capture overview %}}
This page shows how to create a Pod that uses a Secret to pull an image from a
private Docker registry or repository.
{{% /capture %}}
{{% capture prerequisites %}}
* {{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
* To do this exercise, you need a
[Docker ID](https://docs.docker.com/docker-id/) and password.
{{% /capture %}}
{{% capture steps %}}
## Log in to Docker
On your laptop, you must authenticate with a registry in order to pull a private image:
docker login
When prompted, enter your Docker username and password.
The login process creates or updates a `config.json` file that holds an authorization token.
View the `config.json` file:
cat ~/.docker/config.json
The output contains a section similar to this:
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "c3R...zE2"
}
}
}
{{< note >}}
**Note:** If you use a Docker credentials store, you won't see that `auth` entry but a `credsStore` entry with the name of the store as value.
{{< /note >}}
## Create a Secret in the cluster that holds your authorization token
A Kubernetes cluster uses the Secret of `docker-registry` type to authenticate with a container registry to pull a private image.
Create this Secret, naming it `regcred`:
kubectl create secret docker-registry regcred --docker-server=<your-registry-server> --docker-username=<your-name> --docker-password=<your-pword> --docker-email=<your-email>
where:
* `<your-registry-server>` is your Private Docker Registry FQDN. (https://index.docker.io/v1/ for DockerHub)
* `<your-name>` is your Docker username.
* `<your-pword>` is your Docker password.
* `<your-email>` is your Docker email.
You have successfully set your Docker credentials in the cluster as a Secret called `regcred`.
## Inspecting the Secret `regcred`
To understand the contents of the `regcred` Secret you just created, start by viewing the Secret in YAML format:
kubectl get secret regcred --output=yaml
The output is similar to this:
apiVersion: v1
data:
.dockerconfigjson: eyJodHRwczovL2luZGV4L ... J0QUl6RTIifX0=
kind: Secret
metadata:
...
name: regcred
...
type: kubernetes.io/dockerconfigjson
The value of the `.dockerconfigjson` field is a base64 representation of your Docker credentials.
To understand what is in the `.dockerconfigjson` field, convert the secret data to a
readable format:
kubectl get secret regcred --output="jsonpath={.data.\.dockerconfigjson}" | base64 -d
The output is similar to this:
{"auths":{"yourprivateregistry.com":{"username":"janedoe","password":"xxxxxxxxxxx","email":"jdoe@example.com","auth":"c3R...zE2"}}}
To understand what is in the `auth` field, convert the base64-encoded data to a readable format:
echo "c3R...zE2" | base64 -d
The output, username and password concatenated with a `:`, is similar to this:
janedoe:xxxxxxxxxxx
Notice that the Secret data contains the authorization token similar to your local `~/.docker/config.json` file.
You have successfully set your Docker credentials as a Secret called `regcred` in the cluster.
## Create a Pod that uses your Secret
Here is a configuration file for a Pod that needs access to your Docker credentials in `regcred`:
{{< code file="private-reg-pod.yaml" >}}
Download the above file:
wget -O my-private-reg-pod.yaml https://k8s.io/docs/tasks/configure-pod-container/private-reg-pod.yaml
In file `my-private-reg-pod.yaml`, replace `<your-private-image>` with the path to an image in a private registry such as:
janedoe/jdoe-private:v1
To pull the image from the private registry, Kubernetes needs credentials.
The `imagePullSecrets` field in the configuration file specifies that Kubernetes should get the credentials from a Secret named `regcred`.
Create a Pod that uses your Secret, and verify that the Pod is running:
kubectl create -f my-private-reg-pod.yaml
kubectl get pod private-reg
{{% /capture %}}
{{% capture whatsnext %}}
* Learn more about [Secrets](/docs/concepts/configuration/secret/).
* Learn more about [using a private registry](/docs/concepts/containers/images/#using-a-private-registry).
* See [kubectl create secret docker-registry](/docs/reference/generated/kubectl/kubectl-commands/#-em-secret-docker-registry-em-).
* See [Secret](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#secret-v1-core).
* See the `imagePullSecrets` field of [PodSpec](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podspec-v1-core).
{{% /capture %}}
@@ -0,0 +1,14 @@
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-2
namespace: qos-example
spec:
containers:
- name: qos-demo-2-ctr
image: nginx
resources:
limits:
memory: "200Mi"
requests:
memory: "100Mi"
@@ -0,0 +1,9 @@
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-3
namespace: qos-example
spec:
containers:
- name: qos-demo-3-ctr
image: nginx
@@ -0,0 +1,16 @@
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-4
namespace: qos-example
spec:
containers:
- name: qos-demo-4-ctr-1
image: nginx
resources:
requests:
memory: "200Mi"
- name: qos-demo-4-ctr-2
image: redis
@@ -0,0 +1,16 @@
apiVersion: v1
kind: Pod
metadata:
name: qos-demo
namespace: qos-example
spec:
containers:
- name: qos-demo-ctr
image: nginx
resources:
limits:
memory: "200Mi"
cpu: "700m"
requests:
memory: "200Mi"
cpu: "700m"
@@ -0,0 +1,268 @@
---
title: Configure Quality of Service for Pods
content_template: templates/task
---
{{% capture overview %}}
This page shows how to configure Pods so that they will be assigned particular
Quality of Service (QoS) classes. Kubernetes uses QoS classes to make decisions about
scheduling and evicting Pods.
{{% /capture %}}
{{% capture prerequisites %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
{{% /capture %}}
{{% capture steps %}}
## QoS classes
When Kubernetes creates a Pod it assigns one of these QoS classes to the Pod:
* Guaranteed
* Burstable
* BestEffort
## Create a namespace
Create a namespace so that the resources you create in this exercise are
isolated from the rest of your cluster.
```shell
kubectl create namespace qos-example
```
## Create a Pod that gets assigned a QoS class of Guaranteed
For a Pod to be given a QoS class of Guaranteed:
* Every Container in the Pod must have a memory limit and a memory request, and they must be the same.
* Every Container in the Pod must have a cpu limit and a cpu request, and they must be the same.
Here is the configuration file for a Pod that has one Container. The Container has a memory limit and a
memory request, both equal to 200 MiB. The Container has a cpu limit and a cpu request, both equal to 700 millicpu:
{{< code file="qos-pod.yaml" >}}
Create the Pod:
```shell
kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/qos-pod.yaml --namespace=qos-example
```
View detailed information about the Pod:
```shell
kubectl get pod qos-demo --namespace=qos-example --output=yaml
```
The output shows that Kubernetes gave the Pod a QoS class of Guaranteed. The output also
verifies that the Pod's Container has a memory request that matches its memory limit, and it has
a cpu request that matches its cpu limit.
```yaml
spec:
containers:
...
resources:
limits:
cpu: 700m
memory: 200Mi
requests:
cpu: 700m
memory: 200Mi
...
qosClass: Guaranteed
```
{{< note >}}
**Note:** If a Container specifies its own memory limit, but does not specify a memory request, Kubernetes
automatically assigns a memory request that matches the limit. Similarly, if a Container specifies its own
cpu limit, but does not specify a cpu request, Kubernetes automatically assigns a cpu request that matches
the limit.
{{< /note >}}
Delete your Pod:
```shell
kubectl delete pod qos-demo --namespace=qos-example
```
## Create a Pod that gets assigned a QoS class of Burstable
A Pod is given a QoS class of Burstable if:
* The Pod does not meet the criteria for QoS class Guaranteed.
* At least one Container in the Pod has a memory or cpu request.
Here is the configuration file for a Pod that has one Container. The Container has a memory limit of 200 MiB
and a memory request of 100 MiB.
{{< code file="qos-pod-2.yaml" >}}
Create the Pod:
```shell
kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/qos-pod-2.yaml --namespace=qos-example
```
View detailed information about the Pod:
```shell
kubectl get pod qos-demo-2 --namespace=qos-example --output=yaml
```
The output shows that Kubernetes gave the Pod a QoS class of Burstable.
```yaml
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: qos-demo-2-ctr
resources:
limits:
memory: 200Mi
requests:
memory: 100Mi
...
qosClass: Burstable
```
Delete your Pod:
```shell
kubectl delete pod qos-demo-2 --namespace=qos-example
```
## Create a Pod that gets assigned a QoS class of BestEffort
For a Pod to be given a QoS class of BestEffort, the Containers in the Pod must not
have any memory or cpu limits or requests.
Here is the configuration file for a Pod that has one Container. The Container has no memory or cpu
limits or requests:
{{< code file="qos-pod-3.yaml" >}}
Create the Pod:
```shell
kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/qos-pod-3.yaml --namespace=qos-example
```
View detailed information about the Pod:
```shell
kubectl get pod qos-demo-3 --namespace=qos-example --output=yaml
```
The output shows that Kubernetes gave the Pod a QoS class of BestEffort.
```yaml
spec:
containers:
...
resources: {}
...
qosClass: BestEffort
```
Delete your Pod:
```shell
kubectl delete pod qos-demo-3 --namespace=qos-example
```
## Create a Pod that has two Containers
Here is the configuration file for a Pod that has two Containers. One container specifies a memory
request of 200 MiB. The other Container does not specify any requests or limits.
{{< code file="qos-pod-4.yaml" >}}
Notice that this Pod meets the criteria for QoS class Burstable. That is, it does not meet the
criteria for QoS class Guaranteed, and one of its Containers has a memory request.
Create the Pod:
```shell
kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/qos-pod-4.yaml --namespace=qos-example
```
View detailed information about the Pod:
```shell
kubectl get pod qos-demo-4 --namespace=qos-example --output=yaml
```
The output shows that Kubernetes gave the Pod a QoS class of Burstable:
```yaml
spec:
containers:
...
name: qos-demo-4-ctr-1
resources:
requests:
memory: 200Mi
...
name: qos-demo-4-ctr-2
resources: {}
...
qosClass: Burstable
```
Delete your Pod:
```shell
kubectl delete pod qos-demo-4 --namespace=qos-example
```
## Clean up
Delete your namespace:
```shell
kubectl delete namespace qos-example
```
{{% /capture %}}
{{% capture whatsnext %}}
### For app developers
* [Assign Memory Resources to Containers and Pods](/docs/tasks/configure-pod-container/assign-memory-resource/)
* [Assign CPU Resources to Containers and Pods](/docs/tasks/configure-pod-container/assign-cpu-resource/)
### For cluster administrators
* [Configure Default Memory Requests and Limits for a Namespace](/docs/tasks/administer-cluster/memory-default-namespace/)
* [Configure Default CPU Requests and Limits for a Namespace](/docs/tasks/administer-cluster/cpu-default-namespace/)
* [Configure Minimum and Maximum Memory Constraints for a Namespace](/docs/tasks/administer-cluster/memory-constraint-namespace/)
* [Configure Minimum and Maximum CPU Constraints for a Namespace](/docs/tasks/administer-cluster/cpu-constraint-namespace/)
* [Configure Memory and CPU Quotas for a Namespace](/docs/tasks/administer-cluster/quota-memory-cpu-namespace/)
* [Configure a Pod Quota for a Namespace](/docs/tasks/administer-cluster/quota-pod-namespace/)
* [Configure Quotas for API Objects](/docs/tasks/administer-cluster/quota-api-object/)
{{% /capture %}}
@@ -0,0 +1,11 @@
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-resources
spec:
hard:
pods: "4"
requests.cpu: "1"
requests.memory: 1Gi
limits.cpu: "2"
limits.memory: 2Gi
@@ -0,0 +1,13 @@
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo-2
spec:
securityContext:
runAsUser: 1000
containers:
- name: sec-ctx-demo-2
image: gcr.io/google-samples/node-hello:1.0
securityContext:
runAsUser: 2000
allowPrivilegeEscalation: false
@@ -0,0 +1,11 @@
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo-3
spec:
containers:
- name: sec-ctx-3
image: gcr.io/google-samples/node-hello:1.0
@@ -0,0 +1,11 @@
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo-4
spec:
containers:
- name: sec-ctx-4
image: gcr.io/google-samples/node-hello:1.0
securityContext:
capabilities:
add: ["NET_ADMIN", "SYS_TIME"]
@@ -0,0 +1,360 @@
---
reviewers:
- erictune
- mikedanese
- thockin
title: Configure a Security Context for a Pod or Container
content_template: templates/task
---
{{% capture overview %}}
A security context defines privilege and access control settings for
a Pod or Container. Security context settings include:
* Discretionary Access Control: Permission to access an object, like a file, is based on
[user ID (UID) and group ID (GID)](https://wiki.archlinux.org/index.php/users_and_groups).
* [Security Enhanced Linux (SELinux)](https://en.wikipedia.org/wiki/Security-Enhanced_Linux): Objects are assigned security labels.
* Running as privileged or unprivileged.
* [Linux Capabilities](https://linux-audit.com/linux-capabilities-hardening-linux-binaries-by-removing-setuid/): Give a process some privileges, but not all the privileges of the root user.
* [AppArmor](/docs/tutorials/clusters/apparmor/): Use program profiles to restrict the capabilities of individual programs.
* [Seccomp](https://en.wikipedia.org/wiki/Seccomp): Filter a process's system calls.
* AllowPrivilegeEscalation: Controls whether a process can gain more privileges than its parent process. This bool directly controls whether the [`no_new_privs`](https://www.kernel.org/doc/Documentation/prctl/no_new_privs.txt) flag gets set on the container process. AllowPrivilegeEscalation is true always when the container is: 1) run as Privileged OR 2) has `CAP_SYS_ADMIN`.
For more information about security mechanisms in Linux, see
[Overview of Linux Kernel Security Features](https://www.linux.com/learn/overview-linux-kernel-security-features)
{{% /capture %}}
{{% capture prerequisites %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
{{% /capture %}}
{{% capture steps %}}
## Set the security context for a Pod
To specify security settings for a Pod, include the `securityContext` field
in the Pod specification. The `securityContext` field is a
[PodSecurityContext](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podsecuritycontext-v1-core) object.
The security settings that you specify for a Pod apply to all Containers in the Pod.
Here is a configuration file for a Pod that has a `securityContext` and an `emptyDir` volume:
{{< code file="security-context.yaml" >}}
In the configuration file, the `runAsUser` field specifies that for any Containers in
the Pod, the first process runs with user ID 1000. The `fsGroup` field specifies that
group ID 2000 is associated with all Containers in the Pod. Group ID 2000 is also
associated with the volume mounted at `/data/demo` and with any files created in that
volume.
Create the Pod:
```shell
kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/security-context.yaml
```
Verify that the Pod's Container is running:
```shell
kubectl get pod security-context-demo
```
Get a shell to the running Container:
```shell
kubectl exec -it security-context-demo -- sh
```
In your shell, list the running processes:
```shell
ps aux
```
The output shows that the processes are running as user 1000, which is the value of `runAsUser`:
```shell
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
1000 1 0.0 0.0 4336 724 ? Ss 18:16 0:00 /bin/sh -c node server.js
1000 5 0.2 0.6 772124 22768 ? Sl 18:16 0:00 node server.js
...
```
In your shell, navigate to `/data`, and list the one directory:
```shell
cd /data
ls -l
```
The output shows that the `/data/demo` directory has group ID 2000, which is
the value of `fsGroup`.
```shell
drwxrwsrwx 2 root 2000 4096 Jun 6 20:08 demo
```
In your shell, navigate to `/data/demo`, and create a file:
```shell
cd demo
echo hello > testfile
```
List the file in the `/data/demo` directory:
```shell
ls -l
```
The output shows that `testfile` has group ID 2000, which is the value of `fsGroup`.
```shell
-rw-r--r-- 1 1000 2000 6 Jun 6 20:08 testfile
```
Exit your shell:
```shell
exit
```
## Set the security context for a Container
To specify security settings for a Container, include the `securityContext` field
in the Container manifest. The `securityContext` field is a
[SecurityContext](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#securitycontext-v1-core) object.
Security settings that you specify for a Container apply only to
the individual Container, and they override settings made at the Pod level when
there is overlap. Container settings do not affect the Pod's Volumes.
Here is the configuration file for a Pod that has one Container. Both the Pod
and the Container have a `securityContext` field:
{{< code file="security-context-2.yaml" >}}
Create the Pod:
```shell
kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/security-context-2.yaml
```
Verify that the Pod's Container is running:
```shell
kubectl get pod security-context-demo-2
```
Get a shell into the running Container:
```shell
kubectl exec -it security-context-demo-2 -- sh
```
In your shell, list the running processes:
```
ps aux
```
The output shows that the processes are running as user 2000. This is the value
of `runAsUser` specified for the Container. It overrides the value 1000 that is
specified for the Pod.
```
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
2000 1 0.0 0.0 4336 764 ? Ss 20:36 0:00 /bin/sh -c node server.js
2000 8 0.1 0.5 772124 22604 ? Sl 20:36 0:00 node server.js
...
```
Exit your shell:
```shell
exit
```
## Set capabilities for a Container
With [Linux capabilities](http://man7.org/linux/man-pages/man7/capabilities.7.html),
you can grant certain privileges to a process without granting all the privileges
of the root user. To add or remove Linux capabilities for a Container, include the
`capabilities` field in the `securityContext` section of the Container manifest.
First, see what happens when you don't include a `capabilities` field.
Here is configuration file that does not add or remove any Container capabilities:
{{< code file="security-context-3.yaml" >}}
Create the Pod:
```shell
kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/security-context-3.yaml
```
Verify that the Pod's Container is running:
```shell
kubectl get pod security-context-demo-3
```
Get a shell into the running Container:
```shell
kubectl exec -it security-context-demo-3 -- sh
```
In your shell, list the running processes:
```shell
ps aux
```
The output shows the process IDs (PIDs) for the Container:
```shell
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.0 4336 796 ? Ss 18:17 0:00 /bin/sh -c node server.js
root 5 0.1 0.5 772124 22700 ? Sl 18:17 0:00 node server.js
```
In your shell, view the status for process 1:
```shell
cd /proc/1
cat status
```
The output shows the capabilities bitmap for the process:
```
...
CapPrm: 00000000a80425fb
CapEff: 00000000a80425fb
...
```
Make a note of the capabilities bitmap, and then exit your shell:
```shell
exit
```
Next, run a Container that is the same as the preceding container, except
that it has additional capabilities set.
Here is the configuration file for a Pod that runs one Container. The configuration
adds the `CAP_NET_ADMIN` and `CAP_SYS_TIME` capabilities:
{{< code file="security-context-4.yaml" >}}
Create the Pod:
```shell
kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/security-context-4.yaml
```
Get a shell into the running Container:
```shell
kubectl exec -it security-context-demo-4 -- sh
```
In your shell, view the capabilities for process 1:
```shell
cd /proc/1
cat status
```
The output shows capabilities bitmap for the process:
```shell
...
CapPrm: 00000000aa0435fb
CapEff: 00000000aa0435fb
...
```
Compare the capabilities of the two Containers:
```
00000000a80425fb
00000000aa0435fb
```
In the capability bitmap of the first container, bits 12 and 25 are clear. In the second container,
bits 12 and 25 are set. Bit 12 is `CAP_NET_ADMIN`, and bit 25 is `CAP_SYS_TIME`.
See [capability.h](https://github.com/torvalds/linux/blob/master/include/uapi/linux/capability.h)
for definitions of the capability constants.
{{< note >}}
**Note:** Linux capability constants have the form `CAP_XXX`. But when you list capabilities in your Container manifest, you must omit the `CAP_` portion of the constant. For example, to add `CAP_SYS_TIME`, include `SYS_TIME` in your list of capabilities.
{{< /note >}}
## Assign SELinux labels to a Container
To assign SELinux labels to a Container, include the `seLinuxOptions` field in
the `securityContext` section of your Pod or Container manifest. The
`seLinuxOptions` field is an
[SELinuxOptions](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#selinuxoptions-v1-core)
object. Here's an example that applies an SELinux level:
```yaml
...
securityContext:
seLinuxOptions:
level: "s0:c123,c456"
```
{{< note >}}
**Note:** To assign SELinux labels, the SELinux security module must be loaded on the host operating system.
{{< /note >}}
## Discussion
The security context for a Pod applies to the Pod's Containers and also to
the Pod's Volumes when applicable. Specifically `fsGroup` and `seLinuxOptions` are
applied to Volumes as follows:
* `fsGroup`: Volumes that support ownership management are modified to be owned
and writable by the GID specified in `fsGroup`. See the
[Ownership Management design document](https://git.k8s.io/community/contributors/design-proposals/storage/volume-ownership-management.md)
for more details.
* `seLinuxOptions`: Volumes that support SELinux labeling are relabeled to be accessible
by the label specified under `seLinuxOptions`. Usually you only
need to set the `level` section. This sets the
[Multi-Category Security (MCS)](https://selinuxproject.org/page/NB_MLS)
label given to all Containers in the Pod as well as the Volumes.
{{< warning >}}
**Warning:** After you specify an MCS label for a Pod, all Pods with the same label can access the Volume. If you need inter-Pod protection, you must assign a unique MCS label to each Pod.
{{< /warning >}}
{{% /capture %}}
{{% capture whatsnext %}}
* [PodSecurityContext](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#podsecuritycontext-v1-core)
* [SecurityContext](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#securitycontext-v1-core)
* [Tuning Docker with the newest security enhancements](https://opensource.com/business/15/3/docker-security-tuning)
* [Security Contexts design document](https://git.k8s.io/community/contributors/design-proposals/auth/security_context.md)
* [Ownership Management design document](https://git.k8s.io/community/contributors/design-proposals/storage/volume-ownership-management.md)
* [Pod Security Policies](/docs/concepts/policy/pod-security-policy/)
* [AllowPrivilegeEscalation design
document](https://git.k8s.io/community/contributors/design-proposals/auth/no-new-privs.md)
{{% /capture %}}
@@ -0,0 +1,19 @@
apiVersion: v1
kind: Pod
metadata:
name: security-context-demo
spec:
securityContext:
runAsUser: 1000
fsGroup: 2000
volumes:
- name: sec-ctx-vol
emptyDir: {}
containers:
- name: sec-ctx-demo
image: gcr.io/google-samples/node-hello:1.0
volumeMounts:
- name: sec-ctx-vol
mountPath: /data/demo
securityContext:
allowPrivilegeEscalation: false
@@ -0,0 +1,112 @@
---
title: Share Process Namespace between Containers in a Pod
min-kubernetes-server-version: v1.10
approvers:
- verb
- yujuhong
- dchen1107
content_template: templates/task
---
{{% capture overview %}}
{{< feature-state state="alpha" >}}
This page shows how to configure process namespace sharing for a pod. When
process namespace sharing is enabled, processes in a container are visible
to all other containers in that pod.
You can use this feature to configure cooperating containers, such as a log
handler sidecar container, or to troubleshoot container images that don't
include debugging utilities like a shell.
{{% /capture %}}
{{% capture prerequisites %}}
{{< include "task-tutorial-prereqs.md" >}} {{< version-check >}}
A special **alpha** feature gate `PodShareProcessNamespace` must be set to true
across the system: `--feature-gates=PodShareProcessNamespace=true`.
{{% /capture %}}
{{% capture steps %}}
## Configure a Pod
Process Namespace Sharing is enabled using the `ShareProcessNamespace` field of
`v1.PodSpec`. For example:
{{< code file="share-process-namespace.yaml" >}}
1. Create the pod `nginx` on your cluster:
$ kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/share-process-namespace.yaml
1. Attach to the `shell` container and run `ps`:
$ kubectl attach -it nginx -c shell
If you don't see a command prompt, try pressing enter.
/ # ps ax
PID USER TIME COMMAND
1 root 0:00 /pause
8 root 0:00 nginx: master process nginx -g daemon off;
14 101 0:00 nginx: worker process
15 root 0:00 sh
21 root 0:00 ps ax
You can signal processes in other containers. For example, send `SIGHUP` to
nginx to restart the worker process. This requires the `SYS_PTRACE` capability.
/ # kill -HUP 8
/ # ps ax
PID USER TIME COMMAND
1 root 0:00 /pause
8 root 0:00 nginx: master process nginx -g daemon off;
15 root 0:00 sh
22 101 0:00 nginx: worker process
23 root 0:00 ps ax
It's even possible to access another container image using the
`/proc/$pid/root` link.
/ # head /proc/8/root/etc/nginx/nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
{{% /capture %}}
{{% capture discussion %}}
## Understanding Process Namespace Sharing
Pods share many resources so it makes sense they would also share a process
namespace. Some container images may expect to be isolated from other
containers, though, so it's important to understand these differences:
1. **The container process no longer has PID 1.** Some container images refuse
to start without PID 1 (for example, containers using `systemd`) or run
commands like `kill -HUP 1` to signal the container process. In pods with a
shared process namespace, `kill -HUP 1` will signal the pod sandbox.
(`/pause` in the above example.)
1. **Processes are visible to other containers in the pod.** This includes all
information visible in `/proc`, such as passwords that were passed as arguments
or environment variables. These are protected only by regular Unix permissions.
1. **Container filesystems are visible to other containers in the pod through the
`/proc/$pid/root` link.** This makes debugging easier, but it also means
that filesystem secrets are protected only by filesystem permissions.
{{% /capture %}}
@@ -0,0 +1,17 @@
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
shareProcessNamespace: true
containers:
- name: nginx
image: nginx
- name: shell
image: busybox
securityContext:
capabilities:
add:
- SYS_PTRACE
stdin: true
tty: true
@@ -0,0 +1,11 @@
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: task-pv-claim
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
@@ -0,0 +1,20 @@
kind: Pod
apiVersion: v1
metadata:
name: task-pv-pod
spec:
volumes:
- name: task-pv-storage
persistentVolumeClaim:
claimName: task-pv-claim
containers:
- name: task-pv-container
image: nginx
ports:
- containerPort: 80
name: "http-server"
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: task-pv-storage
@@ -0,0 +1,14 @@
kind: PersistentVolume
apiVersion: v1
metadata:
name: task-pv-volume
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/data"
@@ -0,0 +1,22 @@
apiVersion: v1
kind: Pod
metadata:
name: goproxy
labels:
app: goproxy
spec:
containers:
- name: goproxy
image: k8s.gcr.io/goproxy:0.1
ports:
- containerPort: 8080
readinessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
@@ -0,0 +1,3 @@
color=purple
textmode=true
how=fairlyNice