Version imprimable multipages. Cliquer ici pour imprimer.
Les conteneurs
- 1: Images
- 2: Classe d'exécution (Runtime Class)
- 3: L'environnement du conteneur
- 4: Hooks de cycle de vie de conteneurs
1 - Images
Vous créez une image Docker et la poussez dans un registre avant de la référencer depuis un pod Kubernetes.
La propriété image
d'un conteneur utilise la même syntaxe que la commande docker
, y compris pour les registres privés et les tags.
Mettre à jour des images
La politique de récupération par défaut est IfNotPresent
, Kubelet ne récupère alors pas une image si elle est déjà présente sur le nœud.
Si vous voulez forcer une récupération à chaque fois, vous pouvez faire une des actions suivantes :
- définissez
imagePullPolicy
du conteneur àAlways
. - omettez
imagePullPolicy
et utilisez:latest
comme tag pour l'image à utiliser. - omettez
imagePullPolicy
et le tag de l'image à utiliser. - activez l'admission controller AlwaysPullImages.
Notez que vous devez éviter d'utiliser le tag :latest
, voir Bonnes pratiques pour la configuration pour plus d'informations.
Créer des images multi-architecture à partir de manifestes
La CLI Docker prend maintenant en charge la commande docker manifest
avec des sous-commandes comme create
, annotate
et push
. Ces commandes peuvent être utilisées pour construire et pousser les manifestes. Vous pouvez utiliser docker manifest inspect
pour voir le manifeste.
Vous pouvez voir la documentation Docker ici : https://docs.docker.com/edge/engine/reference/commandline/manifest/
Voici comment nous l'utilisons dans notre outil de build: https://cs.k8s.io/?q=docker%20manifest%20(create%7Cpush%7Cannotate)&i=nope&files=&repos=
Ces commandes se basent et sont implémentées purement sur la CLI Docker. Vous devrez soit éditer $HOME/.docker/config.json
et définir la clé experimental
à enabled
ou vous pouvez simplement définir la variable d'environnement DOCKER_CLI_EXPERIMENTAL
à enabled
lorsque vous appelez les commandes de la CLI.
Note:
Veuillez utiliser les versions 18.06 ou ultérieure, les versions antérieures ayant des bugs ou ne prenant pas en charge l'optionexperimental
pour la ligne de commande. Par exemple https://github.com/docker/cli/issues/1135 cause des problèmes sous containerd
.Si vous avez des problèmes en téléchargeant des manifestes viciés, nettoyez les anciens manifestes dans $HOME/.docker/manifests
pour recommencer de zéro.
Pour Kubernetes, nous avons historiquement utilisé des images avec des suffixes -$(ARCH)
. Pour une rétrocompatibilité, veuillez générer les anciennes images avec des suffixes. Par exemple, l'image pause
qui a le manifeste pour toutes les architetures et l'image pause-amd64
qui est rétrocompatible
pour d'anciennes configurations ou des fichiers YAML qui auraient codé en dur les images avec des suffixes.
Utiliser un registre privé
Les registres privés peuvent demander des clés pour pouvoir lire leurs images.
Ces certificats peuvent être fournis de différentes manières :
- En utilisant la Google Container Registry
- par cluster
- automatiqueent configuré dans Google Compute Engine ou Google Kubernetes Engine
- tous les pods peuvent lire le registre privé du projet
- En utilisant Amazon Elastic Container Registry (ECR)
- utilise les rôles et politiques IAM pour contrôler l'accès aux dépôts ECR
- rafraîchit automatiquement les certificats de login ECR
- En utilisant Oracle Cloud Infrastructure Registry (OCIR)
- utilise les rôles et politiques IAM pour contrôler l'accès aux dépôts OCIR
- En utilisant Azure Container Registry (ACR)
- En utilisant IBM Cloud Container Registry
- utilise les rôles et politiques IAM pour contrôler l'accès à l'IBM Cloud Container Registry
- En configurant les nœuds pour s'authentifier auprès d'un registre privé
- tous les pods peuvent lire les registres privés configurés
- nécessite la configuration des nœuds par un administrateur du cluster
- En utilisant des images pré-chargées
- tous les pods peuvent utiliser toutes les images mises en cache sur un nœud
- nécessite l'accès root à tous les nœuds pour la mise en place
- En spécifiant ImagePullSecrets dans un Pod
- seuls les pods fournissant ses propres clés peuvent accéder au registre privé
Chaque option est décrite plus en détails ci-dessous.
Utiliser la Google Container Registry
Kubernetes prend en charge nativement la Google Container Registry (GCR), lorsqu'il s'exécute dans Google Compute Engine (GCE). Si vous exécutez votre cluster dans GCE ou Google Kubernetes Engine, utilisez simplement le nom complet de l'image (par ex. gcr.io/my_project/image:tag).
Tous les pods dans un cluster auront un accès en lecture aux images dans le registre.
Kubelet va s'authentifier auprès de GCR en utilisant le compte de service Google de l'instance.
Le compte de service dans l'instance aura un https://www.googleapis.com/auth/devstorage.read_only
,
afin qu'il puisse récupérer depuis le GCR du projet mais qu'il ne puisse pas pousser une image.
Utiliser Amazon Elastic Container Registry
Kubernetes prend en charge nativement Amazon Elastic Container Registry, lorsque les nœuds sont des instances de AWS EC2.
Utilisez simplement le nom complet de l'image (par ex. ACCOUNT.dkr.ecr.REGION.amazonaws.com/imagename:tag
)
dans la définition du Pod.
Tous les utilisateurs du cluster qui peuvent créer des pods auront la possibilité d'exécuter des pods qui utilisent n'importe quelle image du registre ECR.
Kubelet va aller chercher et rafraîchir périodiquement les certificats ECR. Les permissions suivantes sont requises par kubelet :
ecr:GetAuthorizationToken
ecr:BatchCheckLayerAvailability
ecr:GetDownloadUrlForLayer
ecr:GetRepositoryPolicy
ecr:DescribeRepositories
ecr:ListImages
ecr:BatchGetImage
Exigences :
- Vous devez utiliser kubelet version
v1.2.0
ou ultérieure. (exécutez par ex./usr/bin/kubelet --version=true
). - Si vos nœuds sont dans une région différente de votre registre, vous devez utiliser la version
v1.3.0
ou ultérieure. - ECR doit être disponible dans votre région.
Dépannage :
- Vérifiez toutes les exigences ci-dessus.
- Copiez les certificats de $REGION (par ex.
us-west-2
) sur votre poste de travail. Connectez-vous en SSH sur l'hôte et exécutez Docker manuellement avec ces certificats. Est-ce que ça marche ? - Vérifiez que kubelet s'exécute avec
--cloud-provider=aws
. - Augmentez la verbosité des logs de kubelet à au moins 3 et recherchez dans les logs de kubelet (par exemple avec
journalctl -u kubelet
) des lignes similaires à :
-
aws_credentials.go:109] unable to get ECR credentials from cache, checking ECR API
-
aws_credentials.go:116] Got ECR credentials from ECR API for <AWS account ID for ECR>.dkr.ecr.<AWS region>.amazonaws.com
Utiliser Azure Container Registry (ACR)
En utilisant Azure Container Registry vous pouvez vous authentifier en utilisant soit un utilisateur admin soit un service principal. Dans les deux cas, l'authentification est faite via l'authentification standard de Docker. Ces instructions assument l'outil en ligne de commande azure-cli.
Vous devez d'abord créer un registre et générer des certificats, la documentation complète pour cela peut être touvée dans la documentation de Azure container registry.
Une fois votre registre de conteneurs créé, vous utiliserez les certificats suivants pour vous connecter :
DOCKER_USER
: service principal ou utilisateur adminDOCKER_PASSWORD
: mot de passe du service principal ou utilisateur adminDOCKER_REGISTRY_SERVER
:${un-nom-de-registre}.azurecr.io
DOCKER_EMAIL
:${une-adresse-email}
Une fois que vous avez défini ces variables, vous pouvez configurer un Secret Kubernetes et l'utiliser pour déployer un Pod.
Utiliser IBM Cloud Container Registry
IBM Cloud Container Registry fournit un registre d'images multi-tenant privé que vous pouvez utiliser pour stocker et partager de manière sécurisée vos images. Par défaut, les images de votre registre privé sont scannées par le Vulnerability Advisor intégré pour détecter des failles de sécurité et des vulnérabilités potentielles. Les utilisateurs de votre compte IBM Cloud peuvent accéder à vos images, ou vous pouvez des rôles et politiques IAM pour fournir l'accès aux namespaces de l'IBM Cloud Container Registry.
Pour installer le plugin du CLI de IBM Cloud Container Registry et créer un namespace pour vos images, voir Débuter avec IBM Cloud Container Registry.
Si vous utilisez le même compte et la même région, vous pouvez déployer des images stockées dans IBM Cloud Container Registry vers la namespace default
de votre cluster IBM Cloud Kubernetes Service sans configuration supplémentaire, voir Construire des conteneurs à partir d'images. Pour les autres options de configuration, voir Comprendre comment autoriser votre cluster à télécharger des images depuis un registre.
Configurer les nœuds pour s'authentifier auprès d'un registre privé
Note:
Si vous travaillez dans Google Kubernetes Engine, vous trouverez un.dockercfg
sur chaque nœud avec les certificats pour Google Container Registry. Vous ne pourrez pas utiliser cette méthode.Note:
Si vous travaillez dans AWS EC2 et utilisez EC2 Container Registry (ECR), kubelet sur chaque nœud va gérer et mettre à jour les certificats du login ECR. Vous ne pourrez pas utiliser cette méthode.Note:
Cette méthode est utilisable si vous avez le contrôle sur la configuration des nœuds. Elle ne marchera pas correctement sur GCE, et sur tout autre fournisseur cloud qui fait du remplacement de nœud automatique.Note:
Kubernetes prend pour l'instant en charge uniquement les sectionsauths
et HttpHeaders
de la config docker. Cela veut dire que les aides aux certificats (credHelpers
ou credsStore
) ne sont pas pris en charge.Docker stocke les clés pour les regisres privés dans le fichier $HOME/.dockercfg
ou $HOME/.docker/config.json
. Si vous placez le même fichier dans un des chemins de recherche ci-dessous, kubelet l'utilise comme fournisseur de clés lorsque les images sont récupérées.
{--root-dir:-/var/lib/kubelet}/config.json
{cwd of kubelet}/config.json
${HOME}/.docker/config.json
/.docker/config.json
{--root-dir:-/var/lib/kubelet}/.dockercfg
{cwd of kubelet}/.dockercfg
${HOME}/.dockercfg
/.dockercfg
Note:
Vous pouvez avoir à définirHOME=/root
explicitement dans votre fichier d'environnement pour kubelet.Voici les étapes recommandées pour configurer vos nœuds pour qu'ils utilisent un registre privé. Dans cet exemple, exécutez-les sur votre poste de travail :
- Exécutez
docker login [server]
pour chaque jeu de certificats que vous désirez utiliser. Ceci met à jour$HOME/.docker/config.json
. - Examinez
$HOME/.docker/config.json
dans un éditeur pour vous assurer qu'il contient uniquement les certificats que vous désirez utiliser. - Récupérez la liste de vos nœuds, par exemple :
- si vous voulez connaître les noms :
nodes=$(kubectl get nodes -o jsonpath='{range.items[*].metadata}{.name} {end}')
- si vous voulez connaître les IPs :
nodes=$(kubectl get nodes -o jsonpath='{range .items[*].status.addresses[?(@.type=="ExternalIP")]}{.address} {end}')
- si vous voulez connaître les noms :
- Copiez votre fichier
.docker/config.json
local dans un des chemins de recherche ci-dessus.- par exemple :
for n in $nodes; do scp ~/.docker/config.json root@$n:/var/lib/kubelet/config.json; done
- par exemple :
Vérifiez en créant un pod utilisant une image privée, par ex. :
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: test-image-privee-1
spec:
containers:
- name: utilise-image-privee
image: $NOM_IMAGE_PRIVEE
imagePullPolicy: Always
command: [ "echo", "SUCCESS" ]
EOF
pod/test-image-privee-1 created
Si tout fonctionne, alors, après quelques instants, vous pouvez exécuter :
kubectl logs test-image-privee-1
et voir que la commande affiche :
SUCCESS
Si vous suspectez que la commande a échouée, vous pouvez exécuter :
kubectl describe pods/test-image-privee-1 | grep 'Failed'
En cas d'échec, l'affichage sera similaire à :
Fri, 26 Jun 2015 15:36:13 -0700 Fri, 26 Jun 2015 15:39:13 -0700 19 {kubelet node-i2hq} spec.containers{uses-private-image} failed Failed to pull image "user/privaterepo:v1": Error: image user/privaterepo:v1 not found
Vous devez vous assurer que tous les nœuds du cluster ont le même fichier .docker/config.json
. Dans le cas contraire, les pods vont s'exécuter sur certains nœuds et échouer sur d'autres. Par exemple, si vous utilisez l'autoscaling des nœuds, alors chaque modèle d'instance doit inclure le fichier .docker/config.json
ou monter un disque le contenant.
Tous les pods auront un accès en lecture aux images d'un registre privé dès que les clés du registre privé sont ajoutées au fichier .docker/config.json
.
Images pré-chargées
Note:
Si vous travaillez dans Google Kubernetes Engine, vous trouverez un.dockercfg
sur chaque nœud avec les certificats pour Google Container Registry. Vous ne pourrez pas utiliser cette méthode.Note:
Cette méthode est utilisable si vous avez le contrôle sur la configuration des nœuds. Elle ne marchera pas correctement sur GCE, et sur tout autre fournisseur cloud qui fait du remplacement de nœud automatique.Par défaut, kubelet essaiera de récupérer chaque image depuis le registre spécifié.
Cependant, si la propriété imagePullPolicy
du conteneur est IfNotPresent
ou Never
,
alors une image locale est utilisée (respectivement de préférence ou exclusivement).
Si vous désirez vous reposer sur des images pré-chargées pour éviter l'authentification à un registre, vous devez vous assurer que tous les nœuds du cluster ont les mêmes images pré-chargées.
Ceci peut être utilisé pour pré-charger certaines images pour gagner du temps, ou comme une alternative à l'authentification à un registre privé.
Tous les pods auront un accès en lecture aux images pré-chargées.
Spécifier ImagePullSecrets dans un Pod
Note:
Cette méthode est actuellement la méthode recommandée pour Google Kubernetes Engine, GCE, et tout autre fournisseur de cloud où la création de nœuds est automatisée.Kubernetes permet de spécifier des clés de registre dans un pod.
Créer un Secret avec une config Docker
Exécutez la commande suivante, en substituant les valeurs en majuscule :
kubectl create secret docker-registry <name> --docker-server=SERVEUR_REGISTRE_DOCKER --docker-username=UTILISATEUR_DOCKER --docker-password=MOT_DE_PASSE_DOCKER --docker-email=EMAIL_DOCKER
secret/myregistrykey created.
Si vous avez déjà un fichier de clés Docker, alors, plutôt que d'utiliser la commande ci-dessus,
vous pouvez importer le fichier de clés comme un Secret Kubernetes.
Créer un Secret basé sur des clés Docker existantes explique comment s'y prendre.
Ceci est particulièrement utile si vous utilisez plusieurs registres privés, kubectl create secret docker-registry
créant un Secret ne fonctionnant qu'avec un seul registre privé.
Note:
Les pods peuvent référencer des pull secrets dans leur propre namespace uniquement, ces étapes doivent donc être faites pour chaque namespace.Se référer à un imagePullSecrets dans un Pod
Vous pouvez maintenant créer des pods qui référencent ce secret en ajoutant une section imagePullSecrets
dans la définition du pod.
cat <<EOF > pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: foo
namespace: awesomeapps
spec:
containers:
- name: foo
image: janedoe/awesomeapp:v1
imagePullSecrets:
- name: myregistrykey
EOF
cat <<EOF >> ./kustomization.yaml
resources:
- pod.yaml
EOF
Ceci doit être fait pour chaque pod utilisant un registre privé.
Cependant, la définition de ce champ peut être automatisé en définissant imagePullSecrets
dans une ressource serviceAccount.
Voyez Ajouter un ImagePullSecrets à un Service Account pour des instructions détaillées.
Vous pouvez utiliser cette méthode en conjonction avec un .docker/config.json
par nœud. Les certificats seront alors regroupés. Cette approche fonctionnera dans Google Kubernetes Engine.
Cas d'utilisation
Il y a plusieurs solutions pour configurer des registres privés. Voici quelques cas d'utilisation classiques et des propositions de solutions.
- Cluster exécutant uniquement des images non propriétaires (par ex. open-source). Inutile de protéger les images.
- Utilisez des images publiques dans le Hub Docker.
- Pas de configuration requise.
- Dans GCE/Google Kubernetes Engine, un miroir local est automatiquement utilisé pour améliorer la vitesse et la disponibilité.
- Utilisez des images publiques dans le Hub Docker.
- Cluster exécutant quelques images propriétaires qui doivent être protégées de l'extérieur de l'entreprise, mais visibles pour tous les utilisteurs du cluster.
- Utilisez un registre Docker hébergé privé.
- Il peut être hébergé sur le Hub Docker, ou ailleurs.
- Configurez manuellement .docker/config.json sur caque nœud comme décrit ci-dessus.
- Ou, utilisez un registre privé interne derrière votre pare-feu avec un accès ouvert en lecture.
- Aucune configuration Kubernetes n'est nécessaire.
- Ou, dans GCE/Google Kubernetes Engine, utilisez le Google Container Registry du projet.
- Cela fonctionnera mieux pour l'autoscaling du cluster que la configuration manuelle des nœuds.
- Ou, dans un cluster où le changement de la configuration des nœuds est difficile, utilisez
imagePullSecrets
.
- Utilisez un registre Docker hébergé privé.
- Cluster avec des images propriétaires, dont quelques-unes nécessitent un contrôle d'accès plus strict.
- Assurez-vous que l'admission controller AlwaysPullImages est actif. Autrement, tous les Pods ont potentiellement accès à toutes les images.
- Déplacez les données sensibles dans une ressource "Secret", plutôt que de les intégrer dans une image.
- Un cluster multi-tenant où chaque tenant doit avoir son propre registre privé.
- Assurez-vous que l'admission controller AlwaysPullImages est actif. Autrement, tous les Pods ont potentiellement accès à toutes les images.
- Utilisez un registre privé nécessitant l'autorisation.
- Générez des certificats de registre pour chaque tenant, placez-les dans des secrets, et placez ces secrets dans les namespaces de chaque tenant. pod - Le tenant ajoute ce secret dans les imagePullSecrets de chaque pod.
Si vous devez accéder à plusieurs registres, vous pouvez créer un secret pour chaque registre.
Kubelet va fusionner tous les imagePullSecrets
dans un unique .docker/config.json
virtuel.
2 - Classe d'exécution (Runtime Class)
Kubernetes v1.12 [alpha]
Cette page décrit la ressource RuntimeClass et le mécanisme de sélection d'exécution (runtime).
Runtime Class
La RuntimeClass est une fonctionnalité alpha permettant de sélectionner la configuration d'exécution du conteneur à utiliser pour exécuter les conteneurs d'un pod.
Installation
En tant que nouvelle fonctionnalité alpha, certaines étapes de configuration supplémentaires doivent être suivies pour utiliser la RuntimeClass:
- Activer la fonctionnalité RuntimeClass (sur les apiservers et les kubelets, nécessite la version 1.12+)
- Installer la RuntimeClass CRD
- Configurer l'implémentation CRI sur les nœuds (dépend du runtime)
- Créer les ressources RuntimeClass correspondantes
1. Activer RuntimeClass feature gate (portail de fonctionnalité)
Voir Feature Gates pour une explication
sur l'activation des feature gates. La RuntimeClass
feature gate doit être activée sur les API servers et
les kubelets.
2. Installer la CRD RuntimeClass
La RuntimeClass CustomResourceDefinition (CRD) se trouve dans le répertoire addons du dépôt Git Kubernetes: kubernetes/cluster/addons/runtimeclass/runtimeclass_crd.yaml
Installer la CRD avec kubectl apply -f runtimeclass_crd.yaml
.
3. Configurer l'implémentation CRI sur les nœuds
Les configurations à sélectionner avec RuntimeClass dépendent de l'implémentation CRI. Consultez la documentation correspondante pour votre implémentation CRI pour savoir comment le configurer. Comme c'est une fonctionnalité alpha, tous les CRI ne prennent pas encore en charge plusieurs RuntimeClasses.
Note:
La RuntimeClass suppose actuellement une configuration de nœud homogène sur l'ensemble du cluster (ce qui signifie que tous les nœuds sont configurés de la même manière en ce qui concerne les environnements d'exécution de conteneur). Toute hétérogénéité (configuration variable) doit être gérée indépendamment de RuntimeClass via des fonctions de planification (scheduling features) (voir Affectation de pods sur les nœuds).Les configurations ont un nom RuntimeHandler
correspondant , référencé par la RuntimeClass.
Le RuntimeHandler doit être un sous-domaine DNS valide selon la norme RFC 1123 (alphanumériques + -
et .
caractères).
4. Créer les ressources RuntimeClass correspondantes
Les configurations effectuées à l'étape 3 doivent chacune avoir un nom RuntimeHandler
associé, qui
identifie la configuration. Pour chaque RuntimeHandler (et optionellement les handlers vides ""
),
créez un objet RuntimeClass correspondant.
La ressource RuntimeClass ne contient actuellement que 2 champs significatifs: le nom RuntimeClass
(metadata.name
) et le RuntimeHandler (spec.runtimeHandler
). la définition de l'objet ressemble à ceci:
apiVersion: node.k8s.io/v1alpha1 # La RuntimeClass est définie dans le groupe d'API node.k8s.io
kind: RuntimeClass
metadata:
name: myclass # Le nom avec lequel la RuntimeClass sera référencée
# La RuntimeClass est une ressource non cantonnées à un namespace
spec:
runtimeHandler: myconfiguration # Le nom de la configuration CRI correspondante
Note:
Il est recommandé de limiter les opérations d'écriture sur la RuntimeClass (create/update/patch/delete) à l'administrateur du cluster. C'est la configuration par défault. Voir Vue d'ensemble d'autorisation pour plus de détails.Usage
Une fois que les RuntimeClasses sont configurées pour le cluster, leur utilisation est très simple.
Spécifiez runtimeClassName
dans la spécficiation du pod. Par exemple:
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
runtimeClassName: myclass
# ...
Cela indiquera à la kubelet d'utiliser la RuntimeClass spécifiée pour exécuter ce pod. Si la
RuntimeClass n'existe pas, ou si la CRI ne peut pas exécuter le handler correspondant, le pod passera finalement à
l'état failed
. Recherchez
l'événement correspondant pour un
message d'erreur.
Si aucun runtimeClassName
n'est spécifié, le RuntimeHandler par défault sera utilisé, qui équivaut
au comportement lorsque la fonctionnalité RuntimeClass est désactivée.
3 - L'environnement du conteneur
Cette page décrit les ressources disponibles pour les conteneurs dans l'environnement de conteneur.
L'environnement du conteneur
L’environnement Kubernetes conteneur fournit plusieurs ressources importantes aux conteneurs:
- Un système de fichier, qui est une combinaison d'une image et un ou plusieurs volumes.
- Informations sur le conteneur lui-même.
- Informations sur les autres objets du cluster.
Informations sur le conteneur
Le nom d'hôte d'un conteneur est le nom du pod dans lequel le conteneur est en cours d'exécution.
Il est disponible via la commande hostname
ou
gethostname
dans libc.
Le nom du pod et le namespace sont disponibles en tant que variables d'environnement via l'API downward.
Les variables d'environnement définies par l'utilisateur à partir de la définition de pod sont également disponibles pour le conteneur, de même que toutes les variables d'environnement spécifiées de manière statique dans l'image Docker.
Informations sur le cluster
Une liste de tous les services en cours d'exécution lors de la création d'un conteneur est disponible pour ce conteneur en tant que variables d'environnement. Ces variables d'environnement correspondent à la syntaxe des liens Docker.
Pour un service nommé foo qui correspond à un conteneur bar, les variables suivantes sont définies:
FOO_SERVICE_HOST=<l'hôte sur lequel le service est exécuté>
FOO_SERVICE_PORT=<le port sur lequel le service fonctionne>
Les services ont des adresses IP dédiées et sont disponibles pour le conteneur avec le DNS, si le module DNS est activé.
A suivre
- En savoir plus sur les hooks du cycle de vie d'un conteneur.
- Acquérir une expérience pratique en attachant les handlers aux événements du cycle de vie du conteneur.
4 - Hooks de cycle de vie de conteneurs
Cette page décrit comment un conteneur pris en charge par kubelet peut utiliser le framework de Hooks de cycle de vie de conteneurs pour exécuter du code déclenché par des événements durant son cycle de vie.
Aperçu
De manière similaire à quantité de frameworks de langages de programmation qui ont des hooks de cycle de vie de composants, comme Angular, Kubernetes fournit aux conteneurs des hooks de cycle de vie. Les hooks permettent à un conteneur d'être au courant d'événements durant son cycle de vie et d'exécuter du code implémenté dans un handler lorsque le hook de cycle de vie correspondant est exécuté.
Hooks de conteneurs
Il existe deux hooks exposés aux conteneurs :
PostStart
Ce hook s'exécute immédiatement après qu'un conteneur soit créé. Cependant, il n'y a aucune garantie que le hook s'exécute avant l'ENTRYPOINT du conteneur. Aucun paramètre n'est passé au handler.
PreStop
Ce hook est appelé immédiatement avant qu'un conteneur se termine, en raison d'un appel à l'API ou d'un événement comme un échec de la liveness probe, un droit de préemption, un conflit de ressources ou autres. Un appel au hook preStop échoue si le conteneur est déjà dans l'état terminé ou complété. Il est bloquant, ce qui veut dire qu'il est synchrone, et doit donc se terminer avant que l'appel pour supprimer le conteneur soit envoyé. Aucun paramètre n'est passé au handler.
Une description plus précise du comportement de l'arrêt peut être trouvé dans Arrêt de Pods.
Implémentation d'un handler de hook
Les conteneurs peuvent accéder à un hook en implémentant et enregistrant un handler pour ce hook. Il existe deux types de handlers de hook pouvant être implémentés pour des conteneurs :
- Exec - Exécute une commande donnée, comme
pre-stop.sh
, dans les cgroups et namespaces du conteneur. Les ressources consommées par la commande sont comptabilisées pour le conteneur. - HTTP - Exécute une requête HTTP sur un endpoint spécifique du conteneur.
Exécution d'un handler de hook
Lorsqu'un hook de cycle de vie de conteneur est appelé, le système de gestion de Kubernetes exécute le handler dans le conteneur enregistré pour ce hook.
Les appels aux handlers de hook sont synchrones dans le contexte du pod contenant le conteneur.
Ceci veut dire que pour un hook PostStart
,
bien que l'ENTRYPOINT du conteneur et le hook soient lancés de manière asynchrone, si le hook prend trop de temps à s'exécuter ou se bloque,
le conteneur ne peut pas atteindre l'état running
.
Le comportement est similaire pour un hook PreStop
.
Si le hook se bloque durant l'exécution,
la phase du Pod reste en état Terminating
et le hook est tué après terminationGracePeriodSeconds
que le pod se termine.
Si un hook PostStart
ou PreStop
échoue,
le conteneur est tué.
Les utilisateurs doivent rendre leurs handlers de hook aussi légers que possible. Il existe des cas, cependant, où de longues commandes ont un intérêt, comme pour enregistrer un état avant de stopper un conteneur.
Garanties de déclenchement d'un hook
La politique de déclenchement d'un hook est au moins une fois,
ce qui veut dire qu'un hook peut être déclenché plus d'une fois pour un événement donné,
comme PostStart
ou PreStop
.
Il appartient à l'implémentation du hook de prendre en compte correctement ce comportement.
En général, un seul déclenchement est fait. Si, par exemple, un récepteur de hook HTTP est hors service et ne peut pas prendre en charge du trafic, il n'y a aucune tentative de renvoi. Dans quelques rares cas, cependant, un double envoi peut se produire. Par exemple, si kubelet redémarre au milieu d'un déclenchement de hook, le hook pourrait être re-déclenché après que kubelet redémarre.
Débugger des handlers de hook
Les logs pour un handler de hook ne sont pas exposés dans les événements du Pod.
Si un handler échoue pour une raison particulière, il envoie un événement.
Pour PostStart
, c'est l'événement FailedPostStartHook
et pour PreStop
, c'est l'événement FailedPreStopHook
.
Vous pouvez voir ces événements en exécutant kubectl describe pod <pod_name>
.
Voici un exemple d'affichage d'événements lors de l'exécution de cette commande :
Events:
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
1m 1m 1 {default-scheduler } Normal Scheduled Successfully assigned test-1730497541-cq1d2 to gke-test-cluster-default-pool-a07e5d30-siqd
1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Pulling pulling image "test:1.0"
1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Created Created container with docker id 5c6a256a2567; Security:[seccomp=unconfined]
1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Pulled Successfully pulled image "test:1.0"
1m 1m 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Started Started container with docker id 5c6a256a2567
38s 38s 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Killing Killing container with docker id 5c6a256a2567: PostStart handler: Error executing in Docker Container: 1
37s 37s 1 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Normal Killing Killing container with docker id 8df9fdfd7054: PostStart handler: Error executing in Docker Container: 1
38s 37s 2 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} Warning FailedSync Error syncing pod, skipping: failed to "StartContainer" for "main" with RunContainerError: "PostStart handler: Error executing in Docker Container: 1"
1m 22s 2 {kubelet gke-test-cluster-default-pool-a07e5d30-siqd} spec.containers{main} Warning FailedPostStartHook
A suivre
- En savoir plus sur l'Environnement d'un conteneur.
- Entraînez-vous à attacher des handlers de conteneurs à des événements de cycle de vie.