Reputation: 5020
I noticed in a deployment file there are two fields for containers like initContainers
and containers
and looks confusing to me and I search through the internet but can't understand. Could anyone please tell me the difference between initContainers
and containers
and how we use them together?
For example
containers:
- name: php
image: php:7-fpm
volumeMounts:
- name: dir
mountPath: /dir
initContainers:
- name: install
image: busybox
volumeMounts:
- name: dir
mountPath: /dir
command:
- wget
- "-O"
- "/dir/index.php"
- https://raw.githubusercontent.com/videofalls/demo/master/index.php
It's really appreciable and thanks in advance!!
Upvotes: 5
Views: 7970
Reputation: 4128
About Containers:
Containers are a technology for packaging the (compiled) code for an application along with the dependencies it needs at run time. Each container that you run is repeatable; the standardization from having dependencies included means that you get the same behavior wherever you run it.
About InitContainer:
Init containers are exactly like regular containers, except:
- Init containers always run to completion before the container execution.
- Each initContainer must complete successfully before the next one starts.
- 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.
Summarizing:
Containers
hosts your dockerized applications, initContainer
run tasks that are required to run before the main Container execution.
One simple example is the code you provided:
index.html
to be always updated, without having to change the pod manifest itself.initContainer
to fetch the updated index.php
and add to the container.volume
parameters to add the emptyDir
that will hold the downloaded file and changing the mountPath
to the default html folder /var/www/html
:apiVersion: v1
kind: Pod
metadata:
name: php-updated
spec:
containers:
- name: php
image: php:7-fpm
volumeMounts:
- name: dir
mountPath: /var/www/html/
initContainers:
- name: install
image: busybox
volumeMounts:
- name: dir
mountPath: /var/www/html/
command:
- wget
- "-O"
- "/var/www/html/index.php"
- https://raw.githubusercontent.com/videofalls/demo/master/index.php
volumes:
- name: dir
emptyDir: {}
POC:
$ kubectl apply -f php.yaml
pod/php-updated created
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
php-updated 1/1 Running 0 3s
$ kubectl exec -it php-updated -- /bin/bash
root@php-updated:/var/www/html# cat index.php
<?php
echo 'Demo Test';
initContainer
ran before the pod, downloaded the file to the mounted volume that is shared with the PHP server Container
.NOTE: The above webserver is not fully functional because the full php-fpm
deployment is a little more complex, and it's not the core of this question, so I'll leave this tutorial for it: PHP-FPM, Nginx, Kubernetes, and Docker
One could argue that index.html
is not a critical file for Pod initialization, and could be replaced during pod execution using Command
so I'll leave here an answer I gave for persistently changing resolv.conf
before pod initialization even after pod restart: DNS Config is Skipped in GKE.
Another great usage of initContainer
is to make a pod wait for another resource in the cluster to be ready before initializing.
initContainer
called init-mydb
that waits and watched for a service called mydb
to be on running
state before allowing the container myapp-container
start, imagine myapp-container
is an app that requires the database connection before execution, otherwise it would fail repeatedly.Reproduction:
my-app.yaml
:apiVersion: apps/v1
kind: Deployment
metadata:
labels:
run: my-app
name: my-app
spec:
replicas: 2
selector:
matchLabels:
run: my-app
template:
metadata:
labels:
run: my-app
spec:
restartPolicy: Always
containers:
- name: myapp-container
image: busybox:1.28
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
initContainers:
- name: init-mydb
image: busybox:1.28
command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]
$ kubectl apply -f my-app.yaml
deployment.apps/my-app created
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
my-app-6b4fb4958f-44ds7 0/1 Init:0/1 0 4s
my-app-6b4fb4958f-s7wmr 0/1 Init:0/1 0 4s
Init:0/1
status waiting for the completion of the init container.initContainer
is waiting to be running
before completing his task:apiVersion: v1
kind: Service
metadata:
name: mydb
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9377
$ kubectl apply -f mydb-svc.yaml
service/mydb created
$ kubectl get pods -w
NAME READY STATUS RESTARTS AGE
my-app-6b4fb4958f-44ds7 0/1 Init:0/1 0 91s
my-app-6b4fb4958f-s7wmr 0/1 Init:0/1 0 91s
my-app-6b4fb4958f-s7wmr 0/1 PodInitializing 0 93s
my-app-6b4fb4958f-44ds7 0/1 PodInitializing 0 94s
my-app-6b4fb4958f-s7wmr 1/1 Running 0 94s
my-app-6b4fb4958f-44ds7 1/1 Running 0 95s
^C
$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/my-app-6b4fb4958f-44ds7 1/1 Running 0 99s
pod/my-app-6b4fb4958f-s7wmr 1/1 Running 0 99s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/mydb ClusterIP 10.100.106.67 <none> 80/TCP 14s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/my-app 2/2 2 2 99s
NAME DESIRED CURRENT READY AGE
replicaset.apps/my-app-6b4fb4958f 2 2 2 99s
Finally I'll leave you a few more examples on how to use InitContainers
:
If you have any questions let me know in the comments!
Upvotes: 14
Reputation: 6471
Init Containers
run before the main container runs. Normally init containers are used to ensure the server environment is ready for your application to start to run.
Go through the detailed official document for better understanding
Upvotes: 5