Improve init containers concept page (#14281)
* Improve init containers page - Overall rewording - Link to “Debug init containers” in whatsnext - Explain terms / use glossary references - Use glossary shortcodes where appropriate - Expand terms like QoS and cgroup that aren't in the glossary - Only document & recommend stable syntax - Tweak initContainer examples to use project style - Drop vestigialreference to StatefulSet Also: write “container” in lower case Most of the places where this page talks about containers, it's as a concept rather than an object in the Kubernetes API. Adjust case accordingly. * Reword what's next section
This commit is contained in:
committed by
Kubernetes Prow Robot
parent
a90f783820
commit
e1ec9a6246
@@ -7,99 +7,103 @@ weight: 40
|
|||||||
---
|
---
|
||||||
|
|
||||||
{{% capture overview %}}
|
{{% capture overview %}}
|
||||||
This page provides an overview of Init Containers, which are specialized
|
This page provides an overview of init containers: specialized containers that run
|
||||||
Containers that run before app Containers and can contain utilities or setup
|
before app containers in a {{< glossary_tooltip text="Pod" term_id="pod" >}}.
|
||||||
scripts not present in an app image.
|
Init containers can contain utilities or setup scripts not present in an app image.
|
||||||
|
|
||||||
|
You can specify init containers in the Pod specification alongside the `containers`
|
||||||
|
array (which describes app containers).
|
||||||
{{% /capture %}}
|
{{% /capture %}}
|
||||||
|
|
||||||
|
|
||||||
This feature has exited beta in 1.6. Init Containers can be specified in the PodSpec
|
|
||||||
alongside the app `containers` array. The beta annotation value will still be respected
|
|
||||||
and overrides the PodSpec field value, however, they are deprecated in 1.6 and 1.7.
|
|
||||||
In 1.8, the annotations are no longer supported and must be converted to the PodSpec field.
|
|
||||||
|
|
||||||
{{% capture body %}}
|
{{% capture body %}}
|
||||||
## Understanding Init Containers
|
|
||||||
|
|
||||||
A [Pod](/docs/concepts/workloads/pods/pod-overview/) can have multiple Containers running
|
## Understanding init containers
|
||||||
apps within it, but it can also have one or more Init Containers, which are run
|
|
||||||
before the app Containers are started.
|
|
||||||
|
|
||||||
Init Containers are exactly like regular Containers, except:
|
A {{< glossary_tooltip text="Pod" term_id="pod" >}} can have multiple containers
|
||||||
|
running apps within it, but it can also have one or more init containers, which are run
|
||||||
|
before the app containers are started.
|
||||||
|
|
||||||
* They always run to completion.
|
Init containers are exactly like regular containers, except:
|
||||||
* Each one must complete successfully before the next one is started.
|
|
||||||
|
|
||||||
If an Init Container fails for a Pod, Kubernetes restarts the Pod repeatedly until the Init
|
* Init containers always run to completion.
|
||||||
Container succeeds. However, if the Pod has a `restartPolicy` of Never, it is not restarted.
|
* Each init container must complete successfully before the next one starts.
|
||||||
|
|
||||||
To specify a Container as an Init Container, add the `initContainers` field on the PodSpec as
|
If a Pod's init container fails, Kubernetes repeatedly restarts the Pod until the init container
|
||||||
a JSON array of objects of type
|
succeeds. However, if the Pod has a `restartPolicy` of Never, Kubernetes does not restart the Pod.
|
||||||
[Container](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#container-v1-core)
|
|
||||||
|
To specify an init container for a Pod, add the `initContainers` field into
|
||||||
|
the Pod specification, as an array of objects of type
|
||||||
|
[Container](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#container-v1-core),
|
||||||
alongside the app `containers` array.
|
alongside the app `containers` array.
|
||||||
The status of the init containers is returned in `.status.initContainerStatuses`
|
The status of the init containers is returned in `.status.initContainerStatuses`
|
||||||
field as an array of the container statuses (similar to the `.status.containerStatuses`
|
field as an array of the container statuses (similar to the `.status.containerStatuses`
|
||||||
field).
|
field).
|
||||||
|
|
||||||
### Differences from regular Containers
|
### Differences from regular containers
|
||||||
|
|
||||||
Init Containers support all the fields and features of app Containers,
|
Init containers support all the fields and features of app containers,
|
||||||
including resource limits, volumes, and security settings. However, the
|
including resource limits, volumes, and security settings. However, the
|
||||||
resource requests and limits for an Init Container are handled slightly
|
resource requests and limits for an init container are handled differently,
|
||||||
differently, which are documented in [Resources](#resources) below. Also, Init Containers do not
|
as documented in [Resources](#resources).
|
||||||
support readiness probes because they must run to completion before the Pod can
|
|
||||||
be ready.
|
|
||||||
|
|
||||||
If multiple Init Containers are specified for a Pod, those Containers are run
|
Also, init containers do not support readiness probes because they must run to
|
||||||
one at a time in sequential order. Each must succeed before the next can run.
|
completion before the Pod can be ready.
|
||||||
When all of the Init Containers have run to completion, Kubernetes initializes
|
|
||||||
the Pod and runs the application Containers as usual.
|
|
||||||
|
|
||||||
## What can Init Containers be used for?
|
If you specify multiple init containers for a Pod, Kubelet runs each init
|
||||||
|
container sequentially. Each init container must succeed before the next can run.
|
||||||
|
When all of the init containers have run to completion, Kubelet initializes
|
||||||
|
the application containers for the Pod and runs them as usual.
|
||||||
|
|
||||||
Because Init Containers have separate images from app Containers, they
|
## Using init containers
|
||||||
|
|
||||||
|
Because init containers have separate images from app containers, they
|
||||||
have some advantages for start-up related code:
|
have some advantages for start-up related code:
|
||||||
|
|
||||||
* They can contain and run utilities that are not desirable to include in the
|
* Init containers can contain utilities or custom code for setup that are not present in an app
|
||||||
app Container image for security reasons.
|
|
||||||
* They can contain utilities or custom code for setup that is not present in an app
|
|
||||||
image. For example, there is no need to make an image `FROM` another image just to use a tool like
|
image. For example, there is no need to make an image `FROM` another image just to use a tool like
|
||||||
`sed`, `awk`, `python`, or `dig` during setup.
|
`sed`, `awk`, `python`, or `dig` during setup.
|
||||||
|
* Init containers can securely run utilities that would make an app container image less secure.
|
||||||
* The application image builder and deployer roles can work independently without
|
* The application image builder and deployer roles can work independently without
|
||||||
the need to jointly build a single app image.
|
the need to jointly build a single app image.
|
||||||
* They use Linux namespaces so that they have different filesystem views from app Containers.
|
* Init containers can run with a different view of the filesystem than app containers in the
|
||||||
Consequently, they can be given access to Secrets that app Containers are not able to
|
same Pod. Consequently, they can be given access to
|
||||||
access.
|
{{< glossary_tooltip text="Secrets" term_id="secret" >}} that app containers cannot access.
|
||||||
* They run to completion before any app Containers start, whereas app
|
* Because init containers run to completion before any app containers start, init containers offer
|
||||||
Containers run in parallel, so Init Containers provide an easy way to block or
|
a mechanism to block or delay app container startup until a set of preconditions are met. Once
|
||||||
delay the startup of app Containers until some set of preconditions are met.
|
preconditions are met, all of the app containers in a Pod can start in parallel.
|
||||||
|
|
||||||
|
|
||||||
### Examples
|
### Examples
|
||||||
Here are some ideas for how to use Init Containers:
|
Here are some ideas for how to use init containers:
|
||||||
|
|
||||||
* Wait for a service to be created with a shell command like:
|
* Wait for a {{< glossary_tooltip text="Service" term_id="service">}} to
|
||||||
|
be created, using a shell one-line command like:
|
||||||
for i in {1..100}; do sleep 1; if dig myservice; then exit 0; fi; done; exit 1
|
```shell
|
||||||
|
for i in {1..100}; do sleep 1; if dig myservice; then exit 0; fi; done; exit 1
|
||||||
|
```
|
||||||
|
|
||||||
* Register this Pod with a remote server from the downward API with a command like:
|
* Register this Pod with a remote server from the downward API with a command like:
|
||||||
|
```shell
|
||||||
|
curl -X POST http://$MANAGEMENT_SERVICE_HOST:$MANAGEMENT_SERVICE_PORT/register -d 'instance=$(<POD_NAME>)&ip=$(<POD_IP>)'
|
||||||
|
```
|
||||||
|
|
||||||
`curl -X POST http://$MANAGEMENT_SERVICE_HOST:$MANAGEMENT_SERVICE_PORT/register -d 'instance=$(<POD_NAME>)&ip=$(<POD_IP>)'`
|
* Wait for some time before starting the app container with a command like
|
||||||
|
```shell
|
||||||
|
sleep 60
|
||||||
|
```
|
||||||
|
|
||||||
|
* Clone a Git repository into a {{< glossary_tooltip text="Volume" term_id="volume" >}}
|
||||||
|
|
||||||
* Wait for some time before starting the app Container with a command like `sleep 60`.
|
|
||||||
* Clone a git repository into a volume.
|
|
||||||
* Place values into a configuration file and run a template tool to dynamically
|
* Place values into a configuration file and run a template tool to dynamically
|
||||||
generate a configuration file for the main app Container. For example,
|
generate a configuration file for the main app container. For example,
|
||||||
place the POD_IP value in a configuration and generate the main app
|
place the `POD_IP` value in a configuration and generate the main app
|
||||||
configuration file using Jinja.
|
configuration file using Jinja.
|
||||||
|
|
||||||
More detailed usage examples can be found in the [StatefulSets documentation](/docs/concepts/workloads/controllers/statefulset/)
|
#### Init containers in use
|
||||||
and the [Production Pods guide](/docs/tasks/configure-pod-container/configure-pod-initialization/).
|
|
||||||
|
|
||||||
### Init Containers in use
|
This example defines a simple Pod that has two init containers.
|
||||||
|
The first waits for `myservice`, and the second waits for `mydb`. Once both
|
||||||
The following yaml file outlines a simple Pod which has two Init Containers.
|
init containers complete, the Pod runs the app container from its `spec` section.
|
||||||
The first waits for `myservice` and the second waits for `mydb`. Once both
|
|
||||||
containers complete, the Pod will begin.
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
@@ -122,7 +126,8 @@ spec:
|
|||||||
command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
|
command: ['sh', '-c', 'until nslookup mydb; do echo waiting for mydb; sleep 2; done;']
|
||||||
```
|
```
|
||||||
|
|
||||||
Yaml file below outlines the `mydb` and `myservice` services:
|
|
||||||
|
The following YAML file outlines the `mydb` and `myservice` services:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
@@ -146,7 +151,7 @@ spec:
|
|||||||
targetPort: 9377
|
targetPort: 9377
|
||||||
```
|
```
|
||||||
|
|
||||||
This Pod can be started and debugged with the following commands:
|
You can start this Pod by running:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
kubectl apply -f myapp.yaml
|
kubectl apply -f myapp.yaml
|
||||||
@@ -155,6 +160,7 @@ kubectl apply -f myapp.yaml
|
|||||||
pod/myapp-pod created
|
pod/myapp-pod created
|
||||||
```
|
```
|
||||||
|
|
||||||
|
And check on its status with:
|
||||||
```shell
|
```shell
|
||||||
kubectl get -f myapp.yaml
|
kubectl get -f myapp.yaml
|
||||||
```
|
```
|
||||||
@@ -163,6 +169,7 @@ NAME READY STATUS RESTARTS AGE
|
|||||||
myapp-pod 0/1 Init:0/2 0 6m
|
myapp-pod 0/1 Init:0/2 0 6m
|
||||||
```
|
```
|
||||||
|
|
||||||
|
or for more details:
|
||||||
```shell
|
```shell
|
||||||
kubectl describe -f myapp.yaml
|
kubectl describe -f myapp.yaml
|
||||||
```
|
```
|
||||||
@@ -200,13 +207,42 @@ Events:
|
|||||||
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Created Created container with docker id 5ced34a04634; Security:[seccomp=unconfined]
|
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Created Created container with docker id 5ced34a04634; Security:[seccomp=unconfined]
|
||||||
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Started Started container with docker id 5ced34a04634
|
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Started Started container with docker id 5ced34a04634
|
||||||
```
|
```
|
||||||
|
|
||||||
|
To see logs for the init containers in this Pod, run:
|
||||||
```shell
|
```shell
|
||||||
kubectl logs myapp-pod -c init-myservice # Inspect the first init container
|
kubectl logs myapp-pod -c init-myservice # Inspect the first init container
|
||||||
kubectl logs myapp-pod -c init-mydb # Inspect the second init container
|
kubectl logs myapp-pod -c init-mydb # Inspect the second init container
|
||||||
```
|
```
|
||||||
|
|
||||||
Once we start the `mydb` and `myservice` services, we can see the Init Containers
|
At this point, those init containers will be waiting to discover Services named
|
||||||
complete and the `myapp-pod` is created:
|
`mydb` and `myservices`.
|
||||||
|
|
||||||
|
Here's a configuration you can use to make those Services appear:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: myservice
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 80
|
||||||
|
targetPort: 9376
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: mydb
|
||||||
|
spec:
|
||||||
|
ports:
|
||||||
|
- protocol: TCP
|
||||||
|
port: 80
|
||||||
|
targetPort: 9377
|
||||||
|
```
|
||||||
|
|
||||||
|
To create the `mydb` and `myservice` services:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
kubectl apply -f services.yaml
|
kubectl apply -f services.yaml
|
||||||
@@ -216,84 +252,89 @@ service/myservice created
|
|||||||
service/mydb created
|
service/mydb created
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You'll then see that those init containers complete, and that the `myapp-pod`
|
||||||
|
Pod moves into the Running state:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
kubectl get -f myapp.yaml
|
kubectl get -f myapp.yaml
|
||||||
|
```
|
||||||
|
```
|
||||||
NAME READY STATUS RESTARTS AGE
|
NAME READY STATUS RESTARTS AGE
|
||||||
myapp-pod 1/1 Running 0 9m
|
myapp-pod 1/1 Running 0 9m
|
||||||
```
|
```
|
||||||
|
|
||||||
This example is very simple but should provide some inspiration for you to
|
This simple example should provide some inspiration for you to create your own
|
||||||
create your own Init Containers.
|
init containers. [What's next](#what-s-next) contains a link to a more detailed example.
|
||||||
|
|
||||||
## Detailed behavior
|
## Detailed behavior
|
||||||
|
|
||||||
During the startup of a Pod, the Init Containers are started in order, after the
|
During the startup of a Pod, each init container starts in order, after the
|
||||||
network and volumes are initialized. Each Container must exit successfully before
|
network and volumes are initialized. Each container must exit successfully before
|
||||||
the next is started. If a Container fails to start due to the runtime or
|
the next container starts. If a container fails to start due to the runtime or
|
||||||
exits with failure, it is retried according to the Pod `restartPolicy`. However,
|
exits with failure, it is retried according to the Pod `restartPolicy`. However,
|
||||||
if the Pod `restartPolicy` is set to Always, the Init Containers use
|
if the Pod `restartPolicy` is set to Always, the init containers use
|
||||||
`RestartPolicy` OnFailure.
|
`restartPolicy` OnFailure.
|
||||||
|
|
||||||
A Pod cannot be `Ready` until all Init Containers have succeeded. The ports on an
|
A Pod cannot be `Ready` until all init containers have succeeded. The ports on an
|
||||||
Init Container are not aggregated under a service. A Pod that is initializing
|
init container are not aggregated under a Service. A Pod that is initializing
|
||||||
is in the `Pending` state but should have a condition `Initializing` set to true.
|
is in the `Pending` state but should have a condition `Initializing` set to true.
|
||||||
|
|
||||||
If the Pod is [restarted](#pod-restart-reasons), all Init Containers must
|
If the Pod [restarts](#pod-restart-reasons), or is restarted, all init containers
|
||||||
execute again.
|
must execute again.
|
||||||
|
|
||||||
Changes to the Init Container spec are limited to the container image field.
|
Changes to the init container spec are limited to the container image field.
|
||||||
Altering an Init Container image field is equivalent to restarting the Pod.
|
Altering an init container image field is equivalent to restarting the Pod.
|
||||||
|
|
||||||
Because Init Containers can be restarted, retried, or re-executed, Init Container
|
Because init containers can be restarted, retried, or re-executed, init container
|
||||||
code should be idempotent. In particular, code that writes to files on `EmptyDirs`
|
code should be idempotent. In particular, code that writes to files on `EmptyDirs`
|
||||||
should be prepared for the possibility that an output file already exists.
|
should be prepared for the possibility that an output file already exists.
|
||||||
|
|
||||||
Init Containers have all of the fields of an app Container. However, Kubernetes
|
Init containers have all of the fields of an app container. However, Kubernetes
|
||||||
prohibits `readinessProbe` from being used because Init Containers cannot
|
prohibits `readinessProbe` from being used because init containers cannot
|
||||||
define readiness distinct from completion. This is enforced during validation.
|
define readiness distinct from completion. This is enforced during validation.
|
||||||
|
|
||||||
Use `activeDeadlineSeconds` on the Pod and `livenessProbe` on the Container to
|
Use `activeDeadlineSeconds` on the Pod and `livenessProbe` on the container to
|
||||||
prevent Init Containers from failing forever. The active deadline includes Init
|
prevent init containers from failing forever. The active deadline includes init
|
||||||
Containers.
|
containers.
|
||||||
|
|
||||||
The name of each app and Init Container in a Pod must be unique; a
|
The name of each app and init container in a Pod must be unique; a
|
||||||
validation error is thrown for any Container sharing a name with another.
|
validation error is thrown for any container sharing a name with another.
|
||||||
|
|
||||||
### Resources
|
### Resources
|
||||||
|
|
||||||
Given the ordering and execution for Init Containers, the following rules
|
Given the ordering and execution for init containers, the following rules
|
||||||
for resource usage apply:
|
for resource usage apply:
|
||||||
|
|
||||||
* The highest of any particular resource request or limit defined on all Init
|
* The highest of any particular resource request or limit defined on all init
|
||||||
Containers is the *effective init request/limit*
|
containers is the *effective init request/limit*
|
||||||
* The Pod's *effective request/limit* for a resource is the higher of:
|
* The Pod's *effective request/limit* for a resource is the higher of:
|
||||||
* the sum of all app Containers request/limit for a resource
|
* the sum of all app containers request/limit for a resource
|
||||||
* the effective init request/limit for a resource
|
* the effective init request/limit for a resource
|
||||||
* Scheduling is done based on effective requests/limits, which means
|
* Scheduling is done based on effective requests/limits, which means
|
||||||
Init Containers can reserve resources for initialization that are not used
|
init containers can reserve resources for initialization that are not used
|
||||||
during the life of the Pod.
|
during the life of the Pod.
|
||||||
* QoS tier of the Pod's *effective QoS tier* is the QoS tier for Init Containers
|
* The QoS (quality of service) tier of the Pod's *effective QoS tier* is the
|
||||||
and app containers alike.
|
QoS tier for init containers and app containers alike.
|
||||||
|
|
||||||
Quota and limits are applied based on the effective Pod request and
|
Quota and limits are applied based on the effective Pod request and
|
||||||
limit.
|
limit.
|
||||||
|
|
||||||
Pod level cgroups are based on the effective Pod request and limit, the
|
Pod level control groups (cgroups) are based on the effective Pod request and
|
||||||
same as the scheduler.
|
limit, the same as the scheduler.
|
||||||
|
|
||||||
|
|
||||||
### Pod restart reasons
|
### Pod restart reasons
|
||||||
|
|
||||||
A Pod can restart, causing re-execution of Init Containers, for the following
|
A Pod can restart, causing re-execution of init containers, for the following
|
||||||
reasons:
|
reasons:
|
||||||
|
|
||||||
* A user updates the PodSpec causing the Init Container image to change. Any
|
* A user updates the Pod specification, causing the init container image to change.
|
||||||
changes to the Init Container image restarts the Pod. App Container image
|
Any changes to the init container image restarts the Pod. App container image
|
||||||
changes only restart the app Container.
|
changes only restart the app container.
|
||||||
* The Pod infrastructure container is restarted. This is uncommon and would
|
* The Pod infrastructure container is restarted. This is uncommon and would
|
||||||
have to be done by someone with root access to nodes.
|
have to be done by someone with root access to nodes.
|
||||||
* All containers in a Pod are terminated while `restartPolicy` is set to Always,
|
* All containers in a Pod are terminated while `restartPolicy` is set to Always,
|
||||||
forcing a restart, and the Init Container completion record has been lost due
|
forcing a restart, and the init container completion record has been lost due
|
||||||
to garbage collection.
|
to garbage collection.
|
||||||
|
|
||||||
{{% /capture %}}
|
{{% /capture %}}
|
||||||
@@ -301,6 +342,7 @@ reasons:
|
|||||||
|
|
||||||
{{% capture whatsnext %}}
|
{{% capture whatsnext %}}
|
||||||
|
|
||||||
* [Creating a Pod that has an Init Container](/docs/tasks/configure-pod-container/configure-pod-initialization/#creating-a-pod-that-has-an-init-container)
|
* Read about [creating a Pod that has an init container](/docs/tasks/configure-pod-container/configure-pod-initialization/#creating-a-pod-that-has-an-init-container)
|
||||||
|
* Learn how to [debug init containers](/docs/tasks/debug-application-cluster/debug-init-containers/)
|
||||||
|
|
||||||
{{% /capture %}}
|
{{% /capture %}}
|
||||||
|
|||||||
Reference in New Issue
Block a user