Convert site to Hugo (#8316)
This commit converts content and layout to use Hugo.
This commit is contained in:
committed by
k8s-ci-robot
parent
7745f0e0c5
commit
7f3b633aa0
@@ -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 Pod’s 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 don’t specify a CPU limit
|
||||
|
||||
If you don’t 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 don’t specify a memory limit
|
||||
|
||||
If you don’t 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
|
||||
can’t 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 don’t 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 pod’s 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
|
||||
Pod’s security context are. Every GID, whether it originates from a PersistentVolume
|
||||
annotation or the Pod’s 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
|
||||
Reference in New Issue
Block a user