From e1ec9a62462b142a3d0a9a1e7246a4bfef7a739b Mon Sep 17 00:00:00 2001 From: Tim Bannister Date: Fri, 12 Jul 2019 00:31:07 +0100 Subject: [PATCH] Improve init containers concept page (#14281) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 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 --- .../workloads/pods/init-containers.md | 238 ++++++++++-------- 1 file changed, 140 insertions(+), 98 deletions(-) diff --git a/content/en/docs/concepts/workloads/pods/init-containers.md b/content/en/docs/concepts/workloads/pods/init-containers.md index 7a7cc05c9f..d6c03abbea 100644 --- a/content/en/docs/concepts/workloads/pods/init-containers.md +++ b/content/en/docs/concepts/workloads/pods/init-containers.md @@ -7,99 +7,103 @@ weight: 40 --- {{% 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. +This page provides an overview of init containers: specialized containers that run +before app containers in a {{< glossary_tooltip text="Pod" term_id="pod" >}}. +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 %}} - -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 %}} -## Understanding Init Containers -A [Pod](/docs/concepts/workloads/pods/pod-overview/) 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. +## Understanding init containers -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. -* Each one must complete successfully before the next one is started. +Init containers are exactly like regular containers, except: -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. +* Init containers always run to completion. +* 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 -a JSON array of objects of type -[Container](/docs/reference/generated/kubernetes-api/{{< param "version" >}}/#container-v1-core) +If a Pod's init container fails, Kubernetes repeatedly restarts the Pod until the init container +succeeds. However, if the Pod has a `restartPolicy` of Never, Kubernetes does not restart the Pod. + +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. 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). -### 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 -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. +resource requests and limits for an init container are handled differently, +as documented in [Resources](#resources). -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. +Also, init containers do not support readiness probes because they must run to +completion before the Pod can be ready. -## 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: -* 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 +* Init containers can contain utilities or custom code for setup that are 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. +* 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 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. +* Init containers can run with a different view of the filesystem than app containers in the + same Pod. Consequently, they can be given access to + {{< glossary_tooltip text="Secrets" term_id="secret" >}} that app containers cannot access. +* Because init containers run to completion before any app containers start, init containers offer + a mechanism to block or delay app container startup until a set of preconditions are met. Once + preconditions are met, all of the app containers in a Pod can start in parallel. + ### 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: - - for i in {1..100}; do sleep 1; if dig myservice; then exit 0; fi; done; exit 1 +* Wait for a {{< glossary_tooltip text="Service" term_id="service">}} to + be created, using a shell one-line command like: + ```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: + ```shell + curl -X POST http://$MANAGEMENT_SERVICE_HOST:$MANAGEMENT_SERVICE_PORT/register -d 'instance=$()&ip=$()' + ``` - `curl -X POST http://$MANAGEMENT_SERVICE_HOST:$MANAGEMENT_SERVICE_PORT/register -d 'instance=$()&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 - generate a configuration file for the main app Container. For example, - place the POD_IP value in a configuration and generate the main app + generate a configuration file for 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/workloads/controllers/statefulset/) -and the [Production Pods guide](/docs/tasks/configure-pod-container/configure-pod-initialization/). +#### Init containers in use -### 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. +This example defines a simple Pod that has two init containers. +The first waits for `myservice`, and the second waits for `mydb`. Once both +init containers complete, the Pod runs the app container from its `spec` section. ```yaml apiVersion: v1 @@ -122,7 +126,8 @@ spec: 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 apiVersion: v1 @@ -146,7 +151,7 @@ spec: targetPort: 9377 ``` -This Pod can be started and debugged with the following commands: +You can start this Pod by running: ```shell kubectl apply -f myapp.yaml @@ -155,6 +160,7 @@ kubectl apply -f myapp.yaml pod/myapp-pod created ``` +And check on its status with: ```shell kubectl get -f myapp.yaml ``` @@ -163,6 +169,7 @@ NAME READY STATUS RESTARTS AGE myapp-pod 0/1 Init:0/2 0 6m ``` +or for more details: ```shell 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 Started Started container with docker id 5ced34a04634 ``` + +To see logs for the init containers in this Pod, run: ```shell kubectl logs myapp-pod -c init-myservice # Inspect the first 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 -complete and the `myapp-pod` is created: +At this point, those init containers will be waiting to discover Services named +`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 kubectl apply -f services.yaml @@ -216,84 +252,89 @@ service/myservice 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 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. +This simple example should provide some inspiration for you to create your own +init containers. [What's next](#what-s-next) contains a link to a more detailed example. ## 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 +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 +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, -if the Pod `restartPolicy` is set to Always, the Init Containers use -`RestartPolicy` OnFailure. +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 +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. +If the Pod [restarts](#pod-restart-reasons), or is restarted, 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. +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 +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 +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. +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. +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 +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 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 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 + 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. +* The QoS (quality of service) 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 level control groups (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 +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. Any - changes to the Init Container image restarts the Pod. App Container image - changes only restart the app Container. +* A user updates the Pod specification, causing the init container image to change. + Any changes to the init container image restarts the Pod. 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 + forcing a restart, and the init container completion record has been lost due to garbage collection. {{% /capture %}} @@ -301,6 +342,7 @@ reasons: {{% 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 %}}