Move Init Containers topic. (#2866)
This commit is contained in:
@@ -0,0 +1,279 @@
|
||||
---
|
||||
assignees:
|
||||
- erictune
|
||||
title: Init Containers
|
||||
redirect_from:
|
||||
- "/docs/concepts/abstractions/init-containers/"
|
||||
- "/docs/concepts/abstractions/init-containers.html"
|
||||
---
|
||||
|
||||
{% capture overview %}
|
||||
This page provides an overview of Init Containers, which are specialized
|
||||
Containers that run before app Containers and can contain utilities or setup
|
||||
scripts not present in an app image.
|
||||
{% endcapture %}
|
||||
|
||||
{:toc}
|
||||
|
||||
{% include 1-5-beta.md %}
|
||||
|
||||
**Once the feature exits beta, Init Containers will be specified in the PodSpec
|
||||
alongside the app `containers` array.**
|
||||
|
||||
{% capture body %}
|
||||
## Understanding Init Containers
|
||||
|
||||
A [Pod](/docs/concepts/abstractions/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.
|
||||
|
||||
Init Containers are exactly like regular Containers, except:
|
||||
|
||||
* They always run to completion.
|
||||
* 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
|
||||
Container succeeds. However, if the Pod has a `restartPolicy` of Never, it is not restarted.
|
||||
|
||||
To specify a Container as an Init Container, add the `annotations` key
|
||||
`pod.beta.kubernetes.io/init-containers`. Its value should be a
|
||||
JSON array of objects of type
|
||||
[Container](http://kubernetes.io/docs/api-reference/v1/definitions/#_v1_container).
|
||||
|
||||
The status of an Init Container is returned as another annotation,
|
||||
`pod.beta.kubernetes.io/init-container-statuses`, which is an array of
|
||||
container statuses similar to the `status.containerStatuses` field.
|
||||
|
||||
### Differences from regular Containers
|
||||
|
||||
Init Containers support all the fields and features of app Containers,
|
||||
including resource limits, volumes, and security settings. However, the
|
||||
resource requests and limits for an Init Container are handled slightly
|
||||
differently, which are documented in [Resources](#resources) below. Also, Init Containers do not
|
||||
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
|
||||
one at a time in sequential order. Each must succeed before the next can run.
|
||||
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?
|
||||
|
||||
Because Init Containers have separate images from app Containers, they
|
||||
have some advantages for start-up related code:
|
||||
|
||||
* They can contain and run utilities that are not desirable to include in the
|
||||
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
|
||||
`sed`, `awk`, `python`, or `dig` during setup.
|
||||
* The application image builder and deployer roles can work independently without
|
||||
the need to jointly build a single app image.
|
||||
* They use Linux namespaces so that they have different filesystem views from app Containers.
|
||||
Consequently, they can be given access to Secrets that app Containers are not able to
|
||||
access.
|
||||
* They run to completion before any app Containers start, whereas app
|
||||
Containers run in parallel, so Init Containers provide an easy way to block or
|
||||
delay the startup of app Containers until some set of preconditions are met.
|
||||
|
||||
### Examples
|
||||
Here are some ideas for how to use Init Containers:
|
||||
|
||||
* Wait for a service to be created with a shell command like:
|
||||
|
||||
for i in {1..100}; do sleep 1; if dig myservice; then exit 0; fi; exit 1
|
||||
|
||||
* Register this Pod with a remote server from the downward API with a command like:
|
||||
|
||||
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 `sleep 60`.
|
||||
* Clone a git repository into a volume.
|
||||
* Place values into a configuration file and run a template tool to dynamically
|
||||
generate a configuration file for the the main app Container. For example,
|
||||
place the POD_IP value in a configuration and generate the main app
|
||||
configuration file using Jinja.
|
||||
|
||||
More detailed usage examples can be found in the [StatefulSets documentation](/docs/concepts/abstractions/controllers/statefulsets/)
|
||||
and the [Production Pods guide](/docs/user-guide/production-pods.md#handling-initialization).
|
||||
|
||||
### Init Containers in use
|
||||
|
||||
The following yaml file outlines a simple Pod which has two Init Containers.
|
||||
The first waits for `myservice` and the second waits for `mydb`. Once both
|
||||
containers complete the Pod will begin.
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: myapp-pod
|
||||
labels:
|
||||
app: myapp
|
||||
annotations:
|
||||
pod.beta.kubernetes.io/init-containers: '[
|
||||
{
|
||||
"name": "init-myservice",
|
||||
"image": "busybox",
|
||||
"command": ["sh", "-c", "until nslookup myservice; do echo waiting for myservice; sleep 2; done;"]
|
||||
},
|
||||
{
|
||||
"name": "init-mydb",
|
||||
"image": "busybox",
|
||||
"command": ["sh", "-c", "until nslookup mydb; do echo waiting for mydb; sleep 2; done;"]
|
||||
}
|
||||
]'
|
||||
spec:
|
||||
containers:
|
||||
- name: myapp-container
|
||||
image: busybox
|
||||
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
|
||||
```
|
||||
|
||||
This Pod can be started and debugged with the following commands:
|
||||
|
||||
```
|
||||
$ kubectl create -f myapp.yaml
|
||||
pod "myapp-pod" created
|
||||
$ kubectl get -f myapp.yaml
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
myapp-pod 0/1 Init:0/2 0 6m
|
||||
$ kubectl describe -f myapp.yaml
|
||||
i11:32 $ kubectl describe -f examples/init-container.yaml
|
||||
Name: myapp-pod
|
||||
Namespace: default
|
||||
[...]
|
||||
Labels: app=myapp
|
||||
Status: Pending
|
||||
[...]
|
||||
Init Containers:
|
||||
init-myservice:
|
||||
[...]
|
||||
State: Running
|
||||
[...]
|
||||
init-mydb:
|
||||
[...]
|
||||
State: Running
|
||||
[...]
|
||||
Containers:
|
||||
myapp-container:
|
||||
[...]
|
||||
State: Waiting
|
||||
Reason: PodInitializing
|
||||
Ready: False
|
||||
[...]
|
||||
Events:
|
||||
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
|
||||
--------- -------- ----- ---- ------------- -------- ------ -------
|
||||
16s 16s 1 {default-scheduler } Normal Scheduled Successfully assigned myapp-pod to 172.17.4.201
|
||||
16s 16s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Pulling pulling image "busybox"
|
||||
13s 13s 1 {kubelet 172.17.4.201} spec.initContainers{init-myservice} Normal Pulled Successfully pulled image "busybox"
|
||||
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
|
||||
$ kubectl logs myapp-pod -c init-myservice # Inspect the first init container
|
||||
$ kubectl logs myapp-pod -c init-mydd # Inspect the second init container
|
||||
```
|
||||
|
||||
Once we start the `mydb` and `myservice` Services we can see the Init Containers
|
||||
complete and the `myapp-pod` is created:
|
||||
|
||||
```
|
||||
$ kubectl create -f services.yaml
|
||||
service "myservice" created
|
||||
service "mydb" created
|
||||
$ kubectl get -f myapp.yaml
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
myapp-pod 1/1 Running 0 9m
|
||||
```
|
||||
|
||||
This example is very simple but should provide some inspiration for you to
|
||||
create your own Init Containers.
|
||||
|
||||
## Detailed behavior
|
||||
|
||||
During the startup of a Pod, the Init Containers are started in order, after the
|
||||
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
|
||||
exits with failure, it is retried according to the Pod `restartPolicy`. However,
|
||||
if the Pod `restartPolicy` is set to Always, the Init Containers use
|
||||
`RestartPolicy` OnFailure.
|
||||
|
||||
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
|
||||
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
|
||||
execute again.
|
||||
|
||||
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.
|
||||
|
||||
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`
|
||||
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
|
||||
prohibits `readinessProbe` from being used because Init Containers cannot
|
||||
define readiness distinct from completion. This is enforced during validation.
|
||||
|
||||
Use `activeDeadlineSeconds` on the Pod and `livenessProbe` on the Container to
|
||||
prevent Init Containers from failing forever. The active deadline includes Init
|
||||
Containers.
|
||||
|
||||
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.
|
||||
|
||||
### Resources
|
||||
|
||||
Given the ordering and execution for Init Containers, the following rules
|
||||
for resource usage apply:
|
||||
|
||||
* The highest of any particular resource request or limit defined on all Init
|
||||
Containers is the *effective init request/limit*
|
||||
* 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 effective init request/limit for a resource
|
||||
* Scheduling is done based on effective requests/limits, which means
|
||||
Init Containers can reserve resources for initialization that are not used
|
||||
during the life of the Pod.
|
||||
* QoS tier of the Pod's *effective QoS tier* is the QoS tier for Init Containers
|
||||
and app containers alike.
|
||||
|
||||
Quota and limits are applied based on the effective Pod request and
|
||||
limit.
|
||||
|
||||
Pod level cgroups are based on the effective Pod request and limit, the
|
||||
same as the scheduler.
|
||||
|
||||
|
||||
### Pod restart reasons
|
||||
|
||||
A Pod can restart, causing re-execution of Init Containers, for the following
|
||||
reasons:
|
||||
|
||||
* A user updates the PodSpec causing the Init Container image to change.
|
||||
App Container image changes only restart the app Container.
|
||||
* The Pod infrastructure container is restarted. This is uncommon and would
|
||||
have to be done by someone with root access to nodes.
|
||||
* 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
|
||||
to garbage collection.
|
||||
|
||||
## Support and compatibility
|
||||
|
||||
A cluster with Kubelet and Apiserver version 1.4.0 or greater supports Init
|
||||
Containers with the beta annotations. Support varies for other combinations of
|
||||
Kubelet and Apiserver versions; see the [release notes](https://github.com/kubernetes/kubernetes/blob/master/CHANGELOG.md) for details.
|
||||
|
||||
{% endcapture %}
|
||||
|
||||
|
||||
{% 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)
|
||||
|
||||
{% endcapture %}
|
||||
|
||||
|
||||
{% include templates/concept.md %}
|
||||
Reference in New Issue
Block a user