Kubernetes中initContainers和容器的区别 [英] Difference between initContainers and containers in Kubernetes
问题描述
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!!
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:
- You created a container with a php server, but you want the content of
index.html
to be always updated, without having to change the pod manifest itself. - So you added a
initContainer
to fetch the updatedindex.php
and add to the container. - I've fixed your yaml with the
volume
parameters to add theemptyDir
that will hold the downloaded file and changing themountPath
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';
- As you can see the
initContainer
ran before the pod, downloaded the file to the mounted volume that is shared with the PHP serverContainer
.
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.
- Here is a pod with a
initContainer
calledinit-mydb
that waits and watched for a service calledmydb
to be onrunning
state before allowing the containermyapp-container
start, imaginemyapp-container
is an app that requires the database connection before execution, otherwise it would fail repeatedly.
Reproduction:
- here is the manifest
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"]
- Now let's apply it see the status of the deployment:
$ 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
- The pods are hold on
Init:0/1
status waiting for the completion of the init container. - Now let's create the service which the
initContainer
is waiting to berunning
before completing his task:
apiVersion: v1
kind: Service
metadata:
name: mydb
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9377
- We will apply it and monitor the changes in the pods:
$ 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!
这篇关于Kubernetes中initContainers和容器的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!