Concepts

Kubernetes v1.15 documentation non maintenue. Vous consultez une version statique. Pour une documentation à jour, veuillez consulter: dernière version.

Edit This Page

Init Containers

Cette page fournit une vue d’ensemble des conteneurs d’initialisation (init containers) : des conteneurs spécialisés qui s’exécutent avant les conteneurs d’application dans un PodLe plus petit et le plus simple des objets Kubernetes. Un Pod est un ensemble de conteneurs fonctionnant sur votre cluster. . Les init containers peuvent contenir des utilitaires ou des scripts d’installation qui ne sont pas présents dans une image d’application.

Vous pouvez spécifier des init containers dans la spécification du Pod à côté du tableau containers (qui décrit les conteneurs d’application)

Comprendre les init containers

Un PodLe plus petit et le plus simple des objets Kubernetes. Un Pod est un ensemble de conteneurs fonctionnant sur votre cluster. peut avoir plusieurs conteneurs exécutant des applications mais peut aussi avoir un ou plusieurs init containers, qui sont exécutés avant que les conteneurs d’application ne démarrent.

Les init containers se comportent comme les conteneurs réguliers, avec quelques différences :

Si le init container d’un Pod échoue, Kubernetes redémarre le Pod à répétition jusqu’à ce que le init container se termine avec succès. Cependant, si le Pod a une restartPolicy à “Never”, Kubernetes ne redémarre pas le Pod.

Afin de spécifier un init container pour un Pod, il faut ajouter le champ initContainers dans la spécification du Pod, comme un tableau d’objets de type Container, au même niveau que le tableau d’applications containers. Le statut des init containers est retourné dans le champ .status.initContainerStatuses comme un tableau des statuts du conteneur (comparable au champ .status.containerStatuses).

Différences avec les conteneurs réguliers

Les init containers supportent tous les champs et fonctionnalités des conteneurs d’application incluant les limites de ressources, les volumes et les paramètres de sécurité. Cependant, les demandes de ressources pour un init container sont gérées différemment des limites de ressources, tel que documenté dans Ressources.

De plus, les init containers ne supportent pas les readiness probes parce que ces conteneurs s’exécutent jusqu’au bout avant que le Pod soit prêt.

Si l’on spécifie plusieurs init containers pour un Pod, Kubelet exécute chaque init container de manière séquentielle. Chaque init container doit se terminer avec succès avant que le prochain ne puisse s’exécuter. Lorsque tous les init containers se sont exécutés jusqu’au bout, Kubelet initialise les conteneurs d’application pour le Pod et les exécute comme d’habitude.

Utiliser les init containers

Puisque les init containers ont des images séparées des conteneurs d’application, ils apportent certains avantages pour du code de mise en route :

Exemples

Voici plusieurs idées pour utiliser les init containers :

Les init containers en utilisation

Cet exemple définit un simple Pod possédant deux init containers. Le premier attend myservice et le second attend mydb. Une fois que les deux init containers terminent leur exécution, le Pod exécute le conteneur d’application décrit dans sa section spec.

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp-container
    image: busybox:1.28
    command: ['sh', '-c', 'echo "L''app s''exécute!" && sleep 3600']
  initContainers:
  - name: init-myservice
    image: busybox:1.28
    command: ['sh', '-c', 'until nslookup myservice; do echo "En attente de myservice"; sleep 2; done;']
  - name: init-mydb
    image: busybox:1.28
    command: ['sh', '-c', 'until nslookup mydb; do echo "En attente de mydb"; sleep 2; done;']

Les fichiers YAML suivants résument les services mydb et myservice :

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

Vous pouvez démarrer ce Pod en exécutant :

kubectl apply -f myapp.yaml
pod/myapp-pod created

Et vérifier son statut avec :

kubectl get -f myapp.yaml
NAME        READY     STATUS     RESTARTS   AGE
myapp-pod   0/1       Init:0/2   0          6m

ou pour plus de détails :

kubectl describe -f myapp.yaml
Name:          myapp-pod
Namespace:     default
[...]
Labels:        app=myapp
Status:        Pending
[...]
Init Containers:
  init-myservice:
[...]
    State:         Running
[...]
  init-mydb:
[...]
    State:         Waiting
      Reason:      PodInitializing
    Ready:         False
[...]
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

Pour voir les logs des init containers dans ce Pod, exécuter :

kubectl logs myapp-pod -c init-myservice # Inspecter le premier init container
kubectl logs myapp-pod -c init-mydb      # Inspecter le second init container

À ce stade, ces init containers attendent de découvrir les services nommés mydb et myservice.

Voici une configuration que vous pouvez utiliser pour faire apparaître ces Services :

---
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

Pour créer les services mydb et myservice :

kubectl apply -f services.yaml
service/myservice created
service/mydb created

Vous verrez ensuite que ces init containers se terminent et que le Pod myapp-pod évolue vers l’état “Running” (en exécution) :

kubectl get -f myapp.yaml
NAME        READY     STATUS    RESTARTS   AGE
myapp-pod   1/1       Running   0          9m

Cet exemple simple devrait suffire à vous inspirer pour créer vos propres init containers. A suivre contient un lien vers un exemple plus détaillé.

Comportement détaillé

Pendant le démarrage d’un Pod, chaque init container démarre en ordre, après que le réseau et les volumes ont été initialisés. Chaque conteneur doit se terminer avec succès avant que le prochain ne démarre. Si un conteneur n’arrive pas à démarrer à cause d’un problème d’exécution ou se termine avec un échec, il est redémarré selon la restartPolicy du Pod. Toutefois, si la restartPolicy du Pod est configurée à “Always”, les init containers utilisent la restartPolicy “OnFailure”.

Un Pod ne peut pas être Ready tant que tous les init containers ne se sont pas exécutés avec succès. Les ports d’un init container ne sont pas agrégés sous un Service. Un Pod qui s’initialise est dans l’état Pending mais devrait avoir une condition Initializing configurée à “true”.

Si le Pod redémarre ou est redémarré, tous les init containers doivent s’exécuter à nouveau.

Les changements aux spec d’un init containers sont limités au champ image du conteneur. Changer le champ image d’un init container équivaut à redémarrer le Pod.

Puisque les init containers peuvent être redémarrés, réessayés ou ré-exécutés, leur code doit être idempotent. En particulier, le code qui écrit dans des fichiers sur EmptyDirs devrait être préparé à la possibilité qu’un fichier de sortie existe déjà.

Les init containers ont tous les champs d’un conteneur d’application. Cependant, Kubernetes interdit l’utilisation de readinessProbe parce que les init containers ne peuvent pas définir une “readiness” distincte de la complétion. Ceci est appliqué lors de la validation.

L’utilisation de activeDeadlineSeconds sur le Pod et livenessProbe sur le conteneur permet d’empêcher les init containers d’échouer tout le temps. La deadline active inclut les init containers.

Le nom de chaque application et init container dans un Pod doit être unique; une erreur de validation est générée pour tout conteneur partageant un nom avec un autre.

Ressources

Étant donné l’ordonnancement et l’exécution des init containers, les règles suivantes s’appliquent pour l’utilisation des ressources :

Les quotas et limites sont appliqués sur la base de la requête/limite effective d’un Pod.

Les groupes de contrôle au niveau du Pod ( cgroupsUn groupe de processus Linux avec des options d’isolation, de suivi, et de limites des ressources. ) sont basés sur la requête/limite effective de Pod, la même que celle du scheduler.

Raisons du redémarrage d’un Pod

Un Pod peut redémarrer, ce qui cause la ré-exécution des init containers, pour les raisons suivantes :

A suivre

Feedback