Initialization of Containers
Hai semuanya, setelah kita mempelajari tentang basic Container dan Pod configuration selanjutnya kita bahas Init Containers. Ok seperti biasa karena materi ini akan lumayan panyang jadi kita akan bagi-bagi menjadi beberapa bagian diantaranya:
- What is init containers
- Differences from regular containers
- what are
initContainers
for? - Examples using
initContainers
- Behavior of
initContainers
Ok langsung aja kita bahas ke materi yang pertama
What is init containers
A 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:
- Init containers always run to completion.
- Each init container must complete successfully before the next one starts.
If a Pod’s init container fails, the kubelet repeatedly restarts that init container until it succeeds. However, if the Pod has a restartPolicy
of Never, and an init container fails during startup of that Pod, Kubernetes treats the overall Pod as failed.
To specify an init container for a Pod, add the initContainers
field into the Pod specification, as an array of container
items (similar to the app containers field and its contents).
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
Mungkin sebagian banyak dari temen-temen bertanya apasih bedanya antara initContainers
dengan 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 differently, as documented in Resources.
Also, init containers do not support lifecycle
, livenessProbe
, readinessProbe
, or startupProbe
because they must run to completion before the Pod can be ready.
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.
what are initContainers
for?
Because init containers have separate images from app containers, they have some advantages for start-up related code:
- 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
, ordig
during setup. - The application image builder and deployer roles can work independently without the need to jointly build a single app image.
- 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 Secrets 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.
- Init containers can securely run utilities or custom code that would otherwise make an app container image less secure. By keeping unnecessary tools separate you can limit the attack surface of your app container image.
Examples using initContainers
The most commons of initContainer use for is, if your application need to run task before they can run for exaample migrate db, backup file config, cleanup systemfiles and etc.
For example:
Jika dijalankan maka outputnya seperti berikut:
➜ kubectl -f 02-workloads/01-pod/init-containers.yaml apply
pod/postgres-db created
service/postgres-db created
pod/backend-apps created
➜ kubectl get pod
NAME READY STATUS RESTARTS AGE
backend-apps 0/1 Init:0/1 0 8s
postgres-db 1/1 Running 0 8s
➜ kubectl get pod
NAME READY STATUS RESTARTS AGE
backend-apps 1/1 Running 0 45s
postgres-db 1/1 Running 0 45s
➜ kubectl describe pod backend-apps
Name: backend-apps
Namespace: default
Priority: 0
Node: minikube/192.168.59.105
Start Time: Tue, 03 May 2022 05:05:27 +0700
Labels: app=backend-apps
Annotations: <none>
Status: Running
IP: 172.17.0.4
IPs:
IP: 172.17.0.4
Init Containers:
migrate-db:
Image: flyway/flyway
Port: <none>
Host Port: <none>
Args:
-url=$(DB_URL)
-user=$(DB_USER)
-password=$(DB_PASSWORD)
info
State: Terminated
Reason: Completed
Exit Code: 0
Started: Tue, 03 May 2022 05:05:33 +0700
Finished: Tue, 03 May 2022 05:05:36 +0700
Ready: True
Restart Count: 0
Environment:
DB_URL: jdbc:postgresql://postgres-db:5432/mydb
DB_USER: postgres
DB_PASSWORD: password
Containers:
backend-apps:
Image: nginx:latest
Port: 80/TCP
Host Port: 0/TCP
State: Running
Started: Tue, 03 May 2022 05:05:37 +0700
Ready: True
Restart Count: 0
Environment: <none>
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 86s default-scheduler Successfully assigned default/backend-apps to minikube
Normal Pulling 85s kubelet Pulling image "flyway/flyway"
Normal Pulled 80s kubelet Successfully pulled image "flyway/flyway" in 5.3909989s
Normal Created 80s kubelet Created container migrate-db
Normal Started 80s kubelet Started container migrate-db
Normal Pulled 76s kubelet Container image "nginx:latest" already present on machine
Normal Created 76s kubelet Created container backend-apps
Normal Started 76s kubelet Started container backend-apps
Jika kita lihat secara sequance diagram maka seperti berikut:
Behavior of initContainers
During Pod startup, the kubelet delays running init containers until the networking and storage are ready. Then the kubelet runs the Pod’s init containers in the order they appear in the Pod’s spec.
Each init 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 restarts, 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. 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.
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.
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. If any resource has no resource limit specified this is considered as the highest 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.
- The QoS (quality of service) tier of the Pod’s effective QoS tier is the QoS tier for init containers and app containers alike.