Version imprimable multipages. Cliquer ici pour imprimer.
Configuration des Pods et des conteneurs
- 1: Allouer des ressources mémoire aux conteneurs et aux pods
- 2: Allouer des ressources CPU aux conteneurs et aux pods
- 3: Configurer la qualité de service pour les pods
- 4: Affecter des ressources supplémentaires à un conteneur
- 5: Configurer un pod en utilisant un volume pour le stockage
- 6: Configurer les comptes de service pour les pods
- 7: Récupération d'une image d'un registre privé
- 8: Configurer les Liveness, Readiness et Startup Probes
- 9: Assigner des pods aux nœuds
- 10: Configurer l'initialisation du pod
- 11: Configurer un pod pour utiliser une ConfigMap
- 12: Partager l'espace de nommage des processus entre les conteneurs d'un Pod
- 13: Convertir un fichier Docker Compose en ressources Kubernetes
1 - Allouer des ressources mémoire aux conteneurs et aux pods
Cette page montre comment assigner une mémoire request et une mémoire limit à un conteneur. Un conteneur est garanti d'avoir autant de mémoire qu'il le demande, mais n'est pas autorisé à consommer plus de mémoire que sa limite.
Pré-requis
Vous devez disposer d'un cluster Kubernetes et l'outil de ligne de commande kubectl doit être configuré pour communiquer avec votre cluster. Si vous ne possédez pas déjà de cluster, vous pouvez en créer un en utilisant Minikube, ou vous pouvez utiliser l'un de ces environnements Kubernetes:
Pour consulter la version, entrezkubectl version
.
Chaque nœud de votre cluster doit avoir au moins 300 MiB de mémoire.
Pour quelques étapes de cette page, vous devez lancer [metrics-server] (https://github.com/kubernetes-incubator/metrics-server) dans votre cluster. Si vous avez déjà metrics-server vous pouvez sauter ces étapes.
Si vous utilisez Minikube, exécutez la commande suivante pour activer metrics-server :
minikube addons enable metrics-server
Pour voir si le metrics-server fonctionne, ou un autre fournisseur de l'API des métriques de ressources (metrics.k8s.io
), exécutez la commande suivante :
kubectl get apiservices
Si l'API des métriques de ressources est disponible, la sortie inclura une référence à metrics.k8s.io
.
NAME
v1beta1.metrics.k8s.io
Créer un namespace
Créez un namespace de manière à ce que les ressources que vous créez dans cet exercice soient isolées du reste de votre cluster.
kubectl create namespace mem-example
Spécifier une demande de mémoire et une limite de mémoire
Pour spécifier une demande de mémoire pour un conteneur, incluez le champ resources:requests
.
dans le manifeste des ressources du conteneur. Pour spécifier une limite de mémoire, incluez resources:limits
.
Dans cet exercice, vous créez un pod qui possède un seul conteneur. Le conteneur dispose d'une demande de mémoire de 100 MiB et une limite de mémoire de 200 MiB. Voici le fichier de configuration pour le Pod :
apiVersion: v1
kind: Pod
metadata:
name: memory-demo
namespace: mem-example
spec:
containers:
- name: memory-demo-ctr
image: polinux/stress
resources:
limits:
memory: "200Mi"
requests:
memory: "100Mi"
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]
La section args
de votre fichier de configuration fournit des arguments pour le conteneur lorsqu'il démarre.
Les arguments "--vm-bytes", "150M"
indiquent au conteneur d'allouer 150 MiB de mémoire.
Créez le Pod:
kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit.yaml --namespace=mem-example
Vérifiez que le Pod fonctionne :
kubectl get pod memory-demo --namespace=mem-example
Consultez des informations détaillées sur le Pod :
kubectl get pod memory-demo --output=yaml --namespace=mem-example
La sortie montre que le conteneur dans le Pod a une demande de mémoire de 100 MiB et une limite de mémoire de 200 MiB.
...
resources:
limits:
memory: 200Mi
requests:
memory: 100Mi
...
Exécutez kubectl top
pour récupérer les métriques du pod :
kubectl top pod memory-demo --namespace=mem-example
La sortie montre que le Pod utilise environ 162.900.000 bytes de mémoire, qui est d'environ 150 MiB. Ce qui est supérieur à la demande de 100 MiB du Pod, mais ne dépassant pas la limite de 200 Mio de Pod.
NAME CPU(cores) MEMORY(bytes)
memory-demo <something> 162856960
Supprimez votre Pod :
kubectl delete pod memory-demo --namespace=mem-example
Dépasser la limite de mémoire d'un conteneur
Un conteneur peut dépasser sa demande de mémoire si le nœud dispose de la mémoire disponible. Cependant, un conteneur n'est pas autorisé à utiliser plus que sa limite de mémoire. Si un conteneur alloue plus de mémoire que sa limite, le Conteneur devient un candidat à la terminaison. Si le conteneur continue à consommer de la mémoire au-delà de sa limite, le conteneur est arrêté. Si un conteneur terminé peut être redémarré, le kubelet le redémarre, comme pour tout autre type d'échec d'exécution.
Dans cet exercice, vous créez un Pod qui tente d'allouer plus de mémoire que sa limite. Voici le fichier de configuration d'un Pod qui contient un conteneur avec une demande de mémoire de 50 MiB et une limite de mémoire de 100 MiB :
apiVersion: v1
kind: Pod
metadata:
name: memory-demo-2
namespace: mem-example
spec:
containers:
- name: memory-demo-2-ctr
image: polinux/stress
resources:
requests:
memory: "50Mi"
limits:
memory: "100Mi"
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "250M", "--vm-hang", "1"]
Dans la section args
du fichier de configuration, vous pouvez voir que le conteneur
tentera d'allouer 250 MiB de mémoire, ce qui est bien au-dessus de la limite de 100 MiB.
Créez le Pod :
kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit-2.yaml --namespace=mem-example
Consultez des informations détaillées sur le Pod :
kubectl get pod memory-demo-2 --namespace=mem-example
A ce niveau, le conteneur est soit en train de tourner, soit stoppé. Répétez la commande précédente jusqu'à ce que le conteneur soit terminé :
NAME READY STATUS RESTARTS AGE
memory-demo-2 0/1 OOMKilled 1 24s
Obtenez une vue plus détaillée de l'état du conteneur :
kubectl get pod memory-demo-2 --output=yaml --namespace=mem-example
La sortie indique que le conteneur a été stoppé suite à un manque de mémoire (OOM) :
lastState:
terminated:
containerID: docker://65183c1877aaec2e8427bc95609cc52677a454b56fcb24340dbd22917c23b10f
exitCode: 137
finishedAt: 2017-06-20T20:52:19Z
reason: OOMKilled
startedAt: null
Le conteneur dans cet exercice pourra être redémarré, ainsi le kubelet le redémarre. Répéter cette commande plusieurs fois pour s'assurer que le conteneur est stoppé et redémarré d'une manière répététive :
kubectl get pod memory-demo-2 --namespace=mem-example
La sortie permet de voir que le conteneur est stoppé, redémarré, stoppé à nouveau, redémarré, et ainsi de suite :
kubectl get pod memory-demo-2 --namespace=mem-example
NAME READY STATUS RESTARTS AGE
memory-demo-2 0/1 OOMKilled 1 37s
kubectl get pod memory-demo-2 --namespace=mem-example
NAME READY STATUS RESTARTS AGE
memory-demo-2 1/1 Running 2 40s
Affichez des informations détaillées sur l'historique du Pod :
kubectl describe pod memory-demo-2 --namespace=mem-example
La sortie indique que le conteneur se démarre et échoue continuellement :
... Normal Created Created container with id 66a3a20aa7980e61be4922780bf9d24d1a1d8b7395c09861225b0eba1b1f8511
... Warning BackOff Back-off restarting failed container
Affichez des informations détaillées sur les nœuds de votre cluster :
kubectl describe nodes
La sortie inclut un enregistrement de la mise à mort du conteneur suite à une condition hors mémoire :
Warning OOMKilling Memory cgroup out of memory: Kill process 4481 (stress) score 1994 or sacrifice child
Supprimez votre Pod :
kubectl delete pod memory-demo-2 --namespace=mem-example
Spécifiez une demande de mémoire trop volumineuse pour vos nœuds.
Les demandes de mémoire et les limites sont associées aux conteneurs, mais il est utile de réfléchir avant tout à la capacité de demande et limite mémoire des pods. La demande de mémoire pour le Pod est la somme des demandes de mémoire pour tous ses conteneurs. De même, la mémoire limite pour le Pod est la somme des limites de tous ses Conteneurs.
L'ordonnancement des modules est basé sur les demandes. Un Pod est schedulé pour se lancer sur un Nœud uniquement si le Nœud dispose de suffisamment de mémoire disponible pour répondre à la demande de mémoire du Pod.
Dans cet exercice, vous allez créer un Pod dont la demande de mémoire est si importante qu'elle dépasse la capacité de la mémoire de n'importe quel nœud de votre cluster. Voici le fichier de configuration d'un Pod qui possède un seul conteneur avec une demande de 1000 GiB de mémoire, qui dépasse probablement la capacité de tous les nœuds de votre cluster.
apiVersion: v1
kind: Pod
metadata:
name: memory-demo-3
namespace: mem-example
spec:
containers:
- name: memory-demo-3-ctr
image: polinux/stress
resources:
limits:
memory: "1000Gi"
requests:
memory: "1000Gi"
command: ["stress"]
args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"]
Créez le Pod :
kubectl apply -f https://k8s.io/examples/pods/resource/memory-request-limit-3.yaml --namespace=mem-example
Affichez l'état du Pod :
kubectl get pod memory-demo-3 --namespace=mem-example
La sortie indique que l'état du Pod est PENDING. En d'autres termes, le Pod n'est pas programmé pour tourner sur aucun Nœud, et il restera indéfiniment dans l'état PENDING :
kubectl get pod memory-demo-3 --namespace=mem-example
NAME READY STATUS RESTARTS AGE
memory-demo-3 0/1 Pending 0 25s
Affichez des informations détaillées sur le Pod, y compris les événements :
kubectl describe pod memory-demo-3 --namespace=mem-example
La sortie indique que le conteneur ne peut pas être planifié par manque de mémoire sur les nœuds :
Events:
... Reason Message
------ -------
... FailedScheduling No nodes are available that match all of the following predicates:: Insufficient memory (3).
Unités de mémoire
La ressource mémoire est mesurée en bytes. Vous pouvez exprimer la mémoire sous la forme d'un nombre entier simple ou d'un nombre avec l'un de ces suffixes : E, P, T, G, M, K, Ei, Pi, Ti, Gi, Mi, Ki. Par exemple, les valeurs suivantes représentent approximativement la même valeur :
128974848, 129e6, 129M , 123Mi
Supprimez votre Pod :
kubectl delete pod memory-demo-3 --namespace=mem-example
Si vous ne spécifiez pas de limite de mémoire
Si vous ne spécifiez pas de limite de mémoire pour un conteneur, l'une des situations suivantes s'applique :
-
Le conteneur n'a pas de limite maximale quant à la quantité de mémoire qu'il utilise. Le conteneur pourrait utiliser toute la mémoire disponible sur le nœud où il est en cours d'exécution, ce qui pourrait à son tour invoquer le OOM killer. De plus, dans le cas d'un OOM Kill, un conteneur sans limite de ressources aura plus de chance d'être stoppé.
-
Le conteneur s'exécute dans un namespace qui a une limite de mémoire par défaut, d'ou le conteneur est automatiquement affecté cette limite par defaut. Les administrateurs du cluster peuvent utiliser un LimitRange pour spécifier une valeur par défaut pour la limite de mémoire.
Motivation pour les demandes et les limites de mémoire
En configurant les demandes de mémoire et les limites pour les conteneurs qui s'exécutent dans votre cluster. vous pouvez utiliser efficacement les ressources mémoire disponibles sur les noeuds de votre cluster. En gardant la demande de mémoire d'un Pod basse, vous donnez au Pod une bonne chance d'être schedulé. En ayant une limite de mémoire supérieure à la demande de mémoire, vous accomplissez deux choses :
- Le Pod peut avoir des éclats d'activités où il fait usage de la mémoire qui se trouve être disponible.
- La quantité de mémoire qu'un Pod peut utiliser pendant un éclat d'activité est limitée à une quantité raisonnable.
Clean up
Supprimez votre namespace. Ceci va supprimer tous les Pods que vous avez créés dans cet exercice :
kubectl delete namespace mem-example
A suivre
Pour les développeurs d'applications
Pour les administrateurs de cluster
-
Configuration des demandes et des limites de mémoire par défaut pour un Namespace
-
Configuration des demandes et des limites par défaut de CPU pour un Namespace
-
Configuration des contraintes de mémoire minimales et maximales pour un Namespace
-
Configuration des contraintes minimales et maximales du CPU pour un Namespace
-
Configuration des quotas de mémoire et de CPU pour un Namespace
2 - Allouer des ressources CPU aux conteneurs et aux pods
Cette page montre comment assigner une demande (request en anglais) de CPU et une limite de CPU à un conteneur. Un conteneur est garanti d'avoir autant de CPU qu'il le demande, mais n'est pas autorisé à utiliser plus de CPU que sa limite.
Pré-requis
Vous devez disposer d'un cluster Kubernetes et l'outil de ligne de commande kubectl doit être configuré pour communiquer avec votre cluster. Si vous ne possédez pas déjà de cluster, vous pouvez en créer un en utilisant Minikube, ou vous pouvez utiliser l'un de ces environnements Kubernetes:
Pour consulter la version, entrezkubectl version
.
Chaque nœud de votre cluster doit avoir au moins 1 CPU.
Pour certaines des étapes de cette page, vous devez lancer metrics-server dans votre cluster. Si le serveur de métriques est déja lancé, vous pouvez sauter ces étapes.
Si vous utilisez minikube, exécutez la commande suivante pour activer metrics-server :
minikube addons enable metrics-server
Pour voir si metrics-server (ou un autre fournisseur de l'API des métriques de ressources metrics.k8s.io
) est lancé, tapez la commande suivante:
kubectl get apiservices
Si l'API de métriques de ressources est disponible, la sortie inclura une
référence à metrics.k8s.io
.
NAME
v1beta1.metrics.k8s.io
Créer un namespace
Créez un namespace de manière à ce que les ressources que vous créez dans cet exercice soient isolés du reste de votre cluster.
kubectl create namespace cpu-example
Spécifier une demande de CPU et une limite de CPU
Pour spécifier une demande de CPU pour un conteneur, incluez le champ resources:requests
.
dans le manifeste des ressources du conteneur. Pour spécifier une limite de CPU, incluez resources:limits
.
Dans cet exercice, vous allez créer un Pod qui a un seul conteneur. Le conteneur a une demande de 0.5 CPU et une limite de 1 CPU. Voici le fichier de configuration du Pod :
apiVersion: v1
kind: Pod
metadata:
name: cpu-demo
namespace: cpu-example
spec:
containers:
- name: cpu-demo-ctr
image: vish/stress
resources:
limits:
cpu: "1"
requests:
cpu: "0.5"
args:
- -cpus
- "2"
La section args
du fichier de configuration fournit des arguments pour le conteneur lorsqu'il démarre. L'argument -cpus "2"
demande au conteneur d'utiliser 2 CPUs.
Créez le Pod:
kubectl apply -f https://k8s.io/examples/pods/resource/cpu-request-limit.yaml --namespace=cpu-example
Vérifiez que le Pod fonctionne :
kubectl get pod cpu-demo --namespace=cpu-example
Consultez des informations détaillées sur le Pod :
kubectl get pod cpu-demo --output=yaml --namespace=cpu-example
La sortie indique que le conteneur dans le Pod a une demande CPU de 500 milliCPU. et une limite de CPU de 1 CPU.
resources:
limits:
cpu: "1"
requests:
cpu: 500m
Utilisez kubectl top
pour récupérer les métriques du pod :
kubectl top pod cpu-demo --namespace=cpu-example
La sortie montre que le Pod utilise 974 milliCPU, ce qui est légèrement inférieur à la limite de 1 CPU spécifiée dans le fichier de configuration du Pod.
NAME CPU(cores) MEMORY(bytes)
cpu-demo 974m <something>
Souvenez-vous qu'en réglant -cpu "2"
, vous avez configuré le conteneur pour faire en sorte qu'il utilise 2 CPU, mais que le conteneur ne peut utiliser qu'environ 1 CPU. L'utilisation du CPU du conteneur est entravée, car le conteneur tente d'utiliser plus de ressources CPU que sa limite.
Unités de CPU
La ressource CPU est mesurée en unités CPU. Un CPU, à Kubernetes, est équivalent à:
- 1 AWS vCPU
- 1 GCP Core
- 1 Azure vCore
- 1 Hyperthread sur un serveur physique avec un processeur Intel qui a de l'hyperthreading.
Les valeurs fractionnelles sont autorisées. Un conteneur qui demande 0,5 CPU est garanti deux fois moins CPU par rapport à un conteneur qui demande 1 CPU. Vous pouvez utiliser le suffixe m pour signifier milli. Par exemple 100m CPU, 100 milliCPU, et 0.1 CPU sont tous égaux. Une précision plus fine que 1m n'est pas autorisée.
Le CPU est toujours demandé en tant que quantité absolue, jamais en tant que quantité relative, 0.1 est la même quantité de CPU sur une machine single-core, dual-core ou 48-core.
Supprimez votre pod :
kubectl delete pod cpu-demo --namespace=cpu-example
Spécifier une demande de CPU trop élevée pour vos nœuds.
Les demandes et limites de CPU sont associées aux conteneurs, mais il est utile de réfléchir à la demande et à la limite de CPU d'un pod. La demande de CPU pour un Pod est la somme des demandes de CPU pour tous les conteneurs du Pod. De même, la limite de CPU pour les un Pod est la somme des limites de CPU pour tous les conteneurs du Pod.
L'ordonnancement des pods est basé sur les demandes. Un Pod est prévu pour se lancer sur un Nœud uniquement si le nœud dispose de suffisamment de ressources CPU pour satisfaire la demande de CPU du Pod.
Dans cet exercice, vous allez créer un Pod qui a une demande de CPU si importante qu'elle dépassera la capacité de n'importe quel nœud de votre cluster. Voici le fichier de configuration d'un Pod qui a un seul conteneur. Le conteneur nécessite 100 CPU, ce qui est susceptible de dépasser la capacité de tous les nœuds de votre cluster.
apiVersion: v1
kind: Pod
metadata:
name: cpu-demo-2
namespace: cpu-example
spec:
containers:
- name: cpu-demo-ctr-2
image: vish/stress
resources:
limits:
cpu: "100"
requests:
cpu: "100"
args:
- -cpus
- "2"
Créez le Pod :
kubectl apply -f https://k8s.io/examples/pods/resource/cpu-request-limit-2.yaml --namespace=cpu-example
Affichez l'état du Pod :
kubectl get pod cpu-demo-2 --namespace=cpu-example
La sortie montre que l'état du Pod est en attente. En d'autres termes, le Pod n'a pas été planifié pour tourner sur n'importe quel Nœud, et il restera à l'état PENDING indéfiniment :
kubectl get pod cpu-demo-2 --namespace=cpu-example
NAME READY STATUS RESTARTS AGE
cpu-demo-2 0/1 Pending 0 7m
Afficher des informations détaillées sur le Pod, y compris les événements:
kubectl describe pod cpu-demo-2 --namespace=cpu-example
la sortie signale que le conteneur ne peut pas être planifié en raison d'une quantité insuffisante de ressources de CPU sur les Nœuds :
Events:
Reason Message
------ -------
FailedScheduling No nodes are available that match all of the following predicates:: Insufficient cpu (3).
Supprimez votre Pod :
kubectl delete pod cpu-demo-2 --namespace=cpu-example
Si vous ne spécifiez pas de limite CPU
Si vous ne spécifiez pas de limite CPU pour un conteneur, une de ces situations s'applique :
-
Le conteneur n'a pas de limite maximale quant aux ressources CPU qu'il peut utiliser. Le conteneur pourrait utiliser toutes les ressources CPU disponibles sur le nœud où il est lancé.
-
Le conteneur est lancé dans un namespace qui a une limite par défaut de CPU, ainsi le conteneur reçoit automatiquement cette limite par défaut. Les administrateurs du cluster peuvent utiliser un LimitRange pour spécifier une valeur par défaut pour la limite de CPU.
Motivation pour les demandes et les limites du CPU
En configurant les demandes et les limites de CPU des conteneurs qui se lancent sur votre cluster, vous pouvez utiliser efficacement les ressources CPU disponibles sur les Nœuds de votre cluster. En gardant une demande faible de CPU de pod, vous donnez au Pod une bonne chance d'être ordonnancé. En ayant une limite CPU supérieure à la demande de CPU, vous accomplissez deux choses :
- Le Pod peut avoir des pics d'activité où il utilise les ressources CPU qui sont déjà disponibles.
- La quantité de ressources CPU qu'un Pod peut utiliser pendant une pic d'activité est limitée à une quantité raisonnable.
Nettoyage
Supprimez votre namespace :
kubectl delete namespace cpu-example
A suivre
Pour les développeurs d'applications
Pour les administrateurs de cluster
-
Configuration des demandes et des limites de mémoire par défaut pour un Namespace
-
Configuration des demandes et des limites par défaut de CPU pour un Namespace
-
Configuration des contraintes de mémoire minimales et maximales pour un Namespace
-
Configuration des contraintes minimales et maximales du CPU pour un Namespace
-
Configuration des quotas de mémoire et de CPU pour un Namespace
3 - Configurer la qualité de service pour les pods
Cette page montre comment configurer les Pods pour qu'ils soient affectés à des classes particulières de qualité de service (QoS). Kubernetes utilise des classes de QoS pour prendre des décisions concernant l'ordonnancement et les évictions des pods.
Pré-requis
Vous devez disposer d'un cluster Kubernetes et l'outil de ligne de commande kubectl doit être configuré pour communiquer avec votre cluster. Si vous ne possédez pas déjà de cluster, vous pouvez en créer un en utilisant Minikube, ou vous pouvez utiliser l'un de ces environnements Kubernetes:
Pour consulter la version, entrezkubectl version
.
Les Classes de QoS
Quand Kubernetes crée un Pod, il affecte une de ces classes QoS au Pod :
- Guaranteed
- Burstable
- BestEffort
Créez un namespace
Créez un namespace de manière à ce que les ressources que vous créez dans cet exercice soient isolées du reste de votre cluster.
kubectl create namespace qos-example
Créez un Pod qui se fait attribuer une classe QoS de Guaranteed
Pour qu'un Pod reçoive une classe de QoS Guaranteed :
- Chaque conteneur du Pod doit avoir une limite de mémoire et une demande de mémoire, et elles doivent être les mêmes.
- Chaque conteneur dans le Pod doit avoir une limite CPU et une demande CPU, et ils doivent être les mêmes.
Ci-dessous le fichier de configuration d'un Pod qui a un seul conteneur. Le conteneur dispose d'une limite de mémoire et d'une demande de mémoire, tous deux égaux à 200 MiB. Le conteneur a également une limite CPU et une demande CPU, toutes deux égales à 700 milliCPU :
apiVersion: v1
kind: Pod
metadata:
name: qos-demo
namespace: qos-example
spec:
containers:
- name: qos-demo-ctr
image: nginx
resources:
limits:
memory: "200Mi"
cpu: "700m"
requests:
memory: "200Mi"
cpu: "700m"
Créez le Pod :
kubectl apply -f https://k8s.io/examples/pods/qos/qos-pod.yaml --namespace=qos-example
Consultez des informations détaillées sur le Pod :
kubectl get pod qos-demo --namespace=qos-example --output=yaml
Le résultat indique que Kubernetes a donné au pod une classe de qualité de service de type Guaranteed. De plus, il affiche que la demande de mémoire du conteneur du pod correspond à sa limite de mémoire, et que la demande de CPU correspond à sa limite de CPU.
spec:
containers:
...
resources:
limits:
cpu: 700m
memory: 200Mi
requests:
cpu: 700m
memory: 200Mi
...
status:
qosClass: Guaranteed
Supprimez votre Pod :
kubectl delete pod qos-demo --namespace=qos-example
Créez un Pod qui se fait attribuer une classe QoS de type Burstable
Un Pod reçoit une classe QoS de Burstable si :
- Le Pod ne répond pas aux critères de la classe QoS Guaranteed.
- Au moins un conteneur dans le Pod dispose d'une demande de mémoire ou de CPU.
Voici le fichier de configuration d'un pod qui a un seul conteneur. Le conteneur a une limite de mémoire de 200 MiB et une demande de mémoire de 100 MiB.
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-2
namespace: qos-example
spec:
containers:
- name: qos-demo-2-ctr
image: nginx
resources:
limits:
memory: "200Mi"
requests:
memory: "100Mi"
Créez le Pod :
kubectl apply -f https://k8s.io/examples/pods/qos/qos-pod-2.yaml --namespace=qos-example
Consultez des informations détaillées sur le Pod :
kubectl get pod qos-demo-2 --namespace=qos-example --output=yaml
La sortie montre que Kubernetes a accordé au pod une classe QoS de type Burstable.
spec:
containers:
- image: nginx
imagePullPolicy: Always
name: qos-demo-2-ctr
resources:
limits:
memory: 200Mi
requests:
memory: 100Mi
...
status:
qosClass: Burstable
Supprimez votre Pod :
kubectl delete pod qos-demo-2 --namespace=qos-example
Créez un Pod qui se fait attribuer une classe QoS de type BestEffort
Pour qu'un pod puisse avoir la classe QoS de BestEffort, les conteneurs dans le pod ne doivent pas avoir des limites ou des demandes de mémoire ou de CPU.
Voici le fichier de configuration d'un Pod qui a un seul conteneur. Le conteneur n'a pas des limites ou des demandes de mémoire ou de CPU :
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-3
namespace: qos-example
spec:
containers:
- name: qos-demo-3-ctr
image: nginx
Créez le Pod :
kubectl apply -f https://k8s.io/examples/pods/qos/qos-pod-3.yaml --namespace=qos-example
Consultez des informations détaillées sur le Pod :
kubectl get pod qos-demo-3 --namespace=qos-example --output=yaml
Le résultat montre que Kubernetes a accordé au pod une classe QoS de BestEffort.
spec:
containers:
...
resources: {}
...
status:
qosClass: BestEffort
Supprimez votre Pod :
kubectl delete pod qos-demo-3 --namespace=qos-example
Créez un pod qui contient deux conteneurs
Voici le fichier de configuration d'un Pod qui a deux conteneurs. Un conteneur spécifie une demande de mémoire de 200 MiB. L'autre conteneur ne spécifie aucune demande ou limite.
apiVersion: v1
kind: Pod
metadata:
name: qos-demo-4
namespace: qos-example
spec:
containers:
- name: qos-demo-4-ctr-1
image: nginx
resources:
requests:
memory: "200Mi"
- name: qos-demo-4-ctr-2
image: redis
Notez que le pod répond aux critères de la classe QoS Burstable. En d'autres termes, il ne répond pas aux exigences de la classe de qualité de service Guaranteed, et l'un de ses conteneurs dispose d'une demande de mémoire.
Créez le Pod :
kubectl apply -f https://k8s.io/examples/pods/qos/qos-pod-4.yaml --namespace=qos-example
Consultez des informations détaillées sur le Pod :
kubectl get pod qos-demo-4 --namespace=qos-example --output=yaml
Le résultat montre que Kubernetes a accordé au pod une classe QoS de Burstable:
spec:
containers:
...
name: qos-demo-4-ctr-1
resources:
requests:
memory: 200Mi
...
name: qos-demo-4-ctr-2
resources: {}
...
status:
qosClass: Burstable
Supprimez votre pod :
kubectl delete pod qos-demo-4 --namespace=qos-example
Nettoyage
Supprimez votre namespace.
kubectl delete namespace qos-example
A suivre
Pour les développeurs d'applications
Pour les administrateurs de cluster
-
Configuration des demandes et des limites de mémoire par défaut pour un Namespace
-
Configuration des demandes et des limites par défaut de CPU pour un Namespace
-
Configuration des contraintes de mémoire minimales et maximales pour un Namespace
-
Configuration des contraintes minimales et maximales du CPU pour un Namespace
-
Configuration des quotas de mémoire et de CPU pour un Namespace
4 - Affecter des ressources supplémentaires à un conteneur
Cette page montre comment affecter des ressources supplémentaires à un conteneur.
Kubernetes v1.24 [stable]
Pré-requis
Vous devez disposer d'un cluster Kubernetes et l'outil de ligne de commande kubectl doit être configuré pour communiquer avec votre cluster. Si vous ne possédez pas déjà de cluster, vous pouvez en créer un en utilisant Minikube, ou vous pouvez utiliser l'un de ces environnements Kubernetes:
Pour consulter la version, entrezkubectl version
.
Avant de commencer cet exercice, procédez à l'exercice en Annoncer des ressources supplémentaires pour un nœud. Cela configurera l'un de vos nœuds pour qu'il annoncera une ressource dongle.
Affecter une ressource supplémentaire à un Pod
Pour demander une ressource supplémentaire, incluez le champ resources:requests
dans votre fichier de manifeste du conteneur. Les ressources supplémentaires sont entièrement qualifiées dans n'importe quel domaine à l'extérieur de *.kubernetes.io/
.
Les noms de ressources supplémentaires valides ont la forme example.com/foo
où example.com
est remplacé par le domaine de votre organisation et foo
est le nom descriptif de la ressource.
Voici le fichier de configuration d'un Pod qui a un seul conteneur :
apiVersion: v1
kind: Pod
metadata:
name: extended-resource-demo
spec:
containers:
- name: extended-resource-demo-ctr
image: nginx
resources:
requests:
example.com/dongle: 3
limits:
example.com/dongle: 3
Dans le fichier de configuration, vous pouvez constater que le conteneur demande 3 dongles.
Créez un pod :
kubectl apply -f https://k8s.io/examples/pods/resource/extended-resource-pod.yaml
Vérifiez que le Pod fonctionne :
kubectl get pod extended-resource-demo
Décrivez le Pod :
kubectl describe pod extended-resource-demo
La sortie affiche les demandes des dongles :
Limits:
example.com/dongle: 3
Requests:
example.com/dongle: 3
Tentative de création d'un deuxième Pod
Voici le fichier de configuration d'un Pod qui a un seul conteneur. Le conteneur demande deux dongles.
apiVersion: v1
kind: Pod
metadata:
name: extended-resource-demo-2
spec:
containers:
- name: extended-resource-demo-2-ctr
image: nginx
resources:
requests:
example.com/dongle: 2
limits:
example.com/dongle: 2
Kubernetes ne pourra pas satisfaire la demande de deux dongles, parce que le premier Pod a utilisé trois des quatre dongles disponibles.
Essayez de créer un Pod :
kubectl apply -f https://k8s.io/examples/pods/resource/extended-resource-pod-2.yaml
Décrivez le Pod :
kubectl describe pod extended-resource-demo-2
La sortie montre que le Pod ne peut pas être planifié, du fait qu'il n'y a pas de Nœud qui a 2 dongles disponibles :
Conditions:
Type Status
PodScheduled False
...
Events:
...
... Warning FailedScheduling pod (extended-resource-demo-2) failed to fit in any node
fit failure summary on nodes : Insufficient example.com/dongle (1)
Affichez l'état du Pod :
kubectl get pod extended-resource-demo-2
La sortie indique que le Pod a été créé, mais pas programmé pour tourner sur un Nœud. Il a le statut Pending :
NAME READY STATUS RESTARTS AGE
extended-resource-demo-2 0/1 Pending 0 6m
Nettoyage
Supprimez les Pods que vous avez créés dans cet exercice :
kubectl delete pod extended-resource-demo
kubectl delete pod extended-resource-demo-2
A suivre
Pour les développeurs d'applications
- Allocation des ressources mémoire aux conteneurs et pods
- Allocation des ressources CPU aux conteneurs et pods
Pour les administrateurs de cluster
5 - Configurer un pod en utilisant un volume pour le stockage
Cette page montre comment configurer un Pod pour utiliser un Volume pour le stockage.
Le système de fichiers d'un conteneur ne vit que tant que le conteneur vit. Ainsi, quand un conteneur se termine et redémarre, les modifications apportées au système de fichiers sont perdues. Pour un stockage plus consistant et indépendant du conteneur, vous pouvez utiliser un Volume. C'est particulièrement important pour les applications Stateful, telles que les key-value stores (comme par exemple Redis) et les bases de données.
Pré-requis
Vous devez disposer d'un cluster Kubernetes et l'outil de ligne de commande kubectl doit être configuré pour communiquer avec votre cluster. Si vous ne possédez pas déjà de cluster, vous pouvez en créer un en utilisant Minikube, ou vous pouvez utiliser l'un de ces environnements Kubernetes:
Pour consulter la version, entrezkubectl version
.
Configurer un volume pour un Pod
Dans cet exercice, vous créez un pod qui contient un seul conteneur. Ce Pod a un Volume de type emptyDir qui dure toute la vie du Pod, même si le conteneur se termine et redémarre. Voici le fichier de configuration du Pod :
apiVersion: v1
kind: Pod
metadata:
name: redis
spec:
containers:
- name: redis
image: redis
volumeMounts:
- name: redis-storage
mountPath: /data/redis
volumes:
- name: redis-storage
emptyDir: {}
-
Créez le Pod :
kubectl apply -f https://k8s.io/examples/pods/storage/redis.yaml
-
Vérifiez que le conteneur du pod est en cours d'exécution, puis surveillez les modifications apportées au pod :
kubectl get pod redis --watch
La sortie ressemble à ceci :
NAME READY STATUS RESTARTS AGE redis 1/1 Running 0 13s
-
Dans un autre terminal, accédez à la console shell du conteneur en cours d'exécution :
kubectl exec -it redis -- /bin/bash
-
Dans votre shell, allez dans
/data/redis
, puis créez un fichier :root@redis:/data# cd /data/redis/ root@redis:/data/redis# echo Hello > test-file
-
Dans votre shell, listez les processus en cours d'exécution :
root@redis:/data/redis# apt-get update root@redis:/data/redis# apt-get install procps root@redis:/data/redis# ps aux
La sortie ressemble à ceci :
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND redis 1 0.1 0.1 33308 3828 ? Ssl 00:46 0:00 redis-server *:6379 root 12 0.0 0.0 20228 3020 ? Ss 00:47 0:00 /bin/bash root 15 0.0 0.0 17500 2072 ? R+ 00:48 0:00 ps aux
-
Dans votre shell, arrêtez le processus Redis :
root@redis:/data/redis# kill <pid>
où
<pid>
est l'ID de processus Redis (PID). -
Dans votre terminal initial, surveillez les changements apportés au Pod de Redis. Éventuellement, vous verrez quelque chose comme ça :
NAME READY STATUS RESTARTS AGE redis 1/1 Running 0 13s redis 0/1 Completed 0 6m redis 1/1 Running 1 6m
A ce stade, le conteneur est terminé et redémarré. C'est dû au fait que le Pod de Redis a une
restartPolicy
fixé à Always
.
-
Accédez à la console shell du conteneur redémarré :
kubectl exec -it redis -- /bin/bash
-
Dans votre shell, allez dans
/data/redis
, et vérifiez quetest-file
est toujours là.root@redis:/data/redis# cd /data/redis/ root@redis:/data/redis# ls test-file
-
Supprimez le pod que vous avez créé pour cet exercice :
kubectl delete pod redis
A suivre
-
Voir Volume.
-
Voir Pod.
-
En plus du stockage sur disque local fourni par
emptyDir
, Kubernetes supporte de nombreuses solutions de stockage connectées au réseau, y compris PD sur GCE et EBS sur EC2, qui sont préférés pour les données critiques et qui s'occuperont des autres détails tels que le montage et le démontage sur les nœuds. Voir Volumes pour plus de détails.
6 - Configurer les comptes de service pour les pods
Un ServiceAccount (compte de service) fournit une identité pour les processus qui s'exécutent dans un Pod.
Ceci est une introduction aux comptes de service pour les utilisateurs. Voir aussi Guide de l'administrateur du cluster des comptes de service.
Lorsque vous (un humain) accédez au cluster (par exemple, en utilisant kubectl
), vous êtes
authentifié par l'apiserver en tant que compte d'utilisateur particulier (actuellement, il s'agit
généralement de l'utilisateur admin
, à moins que votre administrateur de cluster n'ait personnalisé votre cluster). Les processus dans les conteneurs dans les Pods peuvent également contacter l'apiserver. Dans ce cas, ils sont authentifiés en tant que compte de service particulier (par exemple, default
).
Pré-requis
Vous devez disposer d'un cluster Kubernetes et l'outil de ligne de commande kubectl doit être configuré pour communiquer avec votre cluster. Si vous ne possédez pas déjà de cluster, vous pouvez en créer un en utilisant Minikube, ou vous pouvez utiliser l'un de ces environnements Kubernetes:
Pour consulter la version, entrezkubectl version
.
Utiliser le compte de service par défaut pour accéder au API server.
Si vous obtenez le raw json ou yaml pour un Pod que vous avez créé (par exemple, kubectl get pods/<podname> -o yaml
), vous pouvez voir que le champ spec.serviceAccountName
a été automatiquement assigné.
Vous pouvez accéder à l'API depuis l'intérieur d'un Pod en utilisant les identifiants de compte de service montés automatiquement, comme décrit dans Accès au cluster. Les permissions API du compte de service dépendent du plugin d'autorisation et de la politique en usage.
Dans la version 1.6+, vous pouvez choisir de ne pas utiliser le montage automatique des identifiants API pour un compte de service en définissant automountServiceAccountToken: false
sur le compte de service :
apiVersion: v1
kind: ServiceAccount
metadata:
name: build-robot
automountServiceAccountToken: false
...
Dans la version 1.6+, vous pouvez également choisir de ne pas monter automatiquement les identifiants API pour un Pod particulier :
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
serviceAccountName: build-robot
automountServiceAccountToken: false
...
La spéc de Pod a prépondérance par rapport au compte de service si les deux spécifient la valeur automountServiceAccountToken
.
Utiliser plusieurs comptes de services.
Chaque Namespace possède une ressource ServiceAccount par défaut appelée default
.
Vous pouvez lister cette ressource et toutes les autres ressources de ServiceAccount dans le Namespace avec cette commande :
kubectl get serviceAccounts
La sortie est comme la suivante :
NAME SECRETS AGE
default 1 1d
Vous pouvez créer des objets ServiceAccount supplémentaires comme ceci :
kubectl apply -f - <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: build-robot
EOF
Si vous obtenez un dump complet de l'objet compte de service, par exemple :
kubectl get serviceaccounts/build-robot -o yaml
La sortie est comme la suivante :
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: 2015-06-16T00:12:59Z
name: build-robot
namespace: default
resourceVersion: "272500"
selfLink: /api/v1/namespaces/default/serviceaccounts/build-robot
uid: 721ab723-13bc-11e5-aec2-42010af0021e
secrets:
- name: build-robot-token-bvbk5
vous verrez alors qu'un token a été automatiquement créé et est référencé par le compte de service.
Vous pouvez utiliser des plugins d'autorisation pour définir les permissions sur les comptes de service.
Pour utiliser un compte de service autre que par défaut, il suffit de spécifier le spec.serviceAccountName
d'un Pod au nom du compte de service que vous souhaitez utiliser.
Le compte de service doit exister au moment de la création du Pod, sinon il sera rejeté.
Vous ne pouvez pas mettre à jour le compte de service d'un Pod déjà créé.
Vous pouvez supprimer le compte de service de cet exemple comme ceci :
kubectl delete serviceaccount/build-robot
Créez manuellement un API token de compte de service.
Supposons que nous ayons un compte de service existant nommé "build-robot" comme mentionné ci-dessus,et que nous allons créer un nouveau Secret manuellement.
kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
name: build-robot-secret
annotations:
kubernetes.io/service-account.name: build-robot
type: kubernetes.io/service-account-token
EOF
Vous pouvez maintenant confirmer que le Secret nouvellement construit est rempli d'un API token pour le compte de service "build-robot".
Tous les tokens pour des comptes de service non-existants seront nettoyés par le contrôleur de token.
kubectl describe secrets/build-robot-secret
La sortie est comme la suivante :
Name: build-robot-secret
Namespace: default
Labels: <none>
Annotations: kubernetes.io/service-account: name=build-robot
kubernetes.io/service-account: uid=da68f9c6-9d26-11e7-b84e-002dc52800da
Type: kubernetes.io/service-account-token
Data
====
ca.crt: 1338 bytes
namespace: 7 bytes
token: ...
token
est éludé ici.
Ajouter ImagePullSecrets à un compte de service
Tout d'abord, créez un imagePullSecret, comme décrit ici. Puis, vérifiez qu'il a été créé. Par exemple :
kubectl get secrets myregistrykey
La sortie est comme la suivante :
NAME TYPE DATA AGE
myregistrykey kubernetes.io/.dockerconfigjson 1 1d
Ensuite, modifiez le compte de service par défaut du Namespace pour utiliser ce Secret comme un imagePullSecret
.
kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "myregistrykey"}]}'
La version interactive nécessite un traitement manuel :
kubectl get serviceaccounts default -o yaml > ./sa.yaml
La sortie du fichier sa.yaml
est similaire à celle-ci :
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: 2015-08-07T22:02:39Z
name: default
namespace: default
resourceVersion: "243024"
selfLink: /api/v1/namespaces/default/serviceaccounts/default
uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6
secrets:
- name: default-token-uudge
En utilisant l'éditeur de votre choix (par exemple vi
), ouvrez le fichier sa.yaml
, supprimez la ligne avec la clé resourceVersion
, ajoutez les lignes avec imagePullSecrets:
et sauvegardez.
La sortie du fichier sa.yaml
est similaire à celle-ci :
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: 2015-08-07T22:02:39Z
name: default
namespace: default
selfLink: /api/v1/namespaces/default/serviceaccounts/default
uid: 052fb0f4-3d50-11e5-b066-42010af0d7b6
secrets:
- name: default-token-uudge
imagePullSecrets:
- name: myregistrykey
Enfin, remplacez le compte de service par le nouveau fichier sa.yaml
mis à jour.
kubectl replace serviceaccount default -f ./sa.yaml
Maintenant, tous les nouveaux Pods créés dans le Namespace courant auront ceci ajouté à leurs spécifications :
spec:
imagePullSecrets:
- name: myregistrykey
Projection du volume des tokens de compte de service
Kubernetes v1.12 [beta]
Ce ServiceAccountTokenVolumeProjection est beta en 1.12 et activé en passant tous les paramètres suivants au serveur API :
--service-account-issuer
--service-account-signing-key-file
--service-account-api-audiences
Kubelet peut également projeter un token de compte de service dans un Pod. Vous pouvez spécifier les propriétés souhaitées du token, telles que l'audience et la durée de validité. Ces propriétés ne sont pas configurables sur le compte de service par défaut. Le token de compte de service devient également invalide par l'API lorsque le Pod ou le ServiceAccount est supprimé
Ce comportement est configuré sur un PodSpec utilisant un type de ProjectedVolume appelé ServiceAccountToken. Pour fournir un Pod avec un token avec une audience de "vault" et une durée de validité de deux heures, vous devriez configurer ce qui suit dans votre PodSpec :
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: nginx
name: nginx
volumeMounts:
- mountPath: /var/run/secrets/tokens
name: vault-token
serviceAccountName: build-robot
volumes:
- name: vault-token
projected:
sources:
- serviceAccountToken:
path: vault-token
expirationSeconds: 7200
audience: vault
Créez le Pod
kubectl create -f https://k8s.io/examples/pods/pod-projected-svc-token.yaml
Kubelet demandera et stockera le token a la place du Pod, rendra le token disponible pour le Pod à un chemin d'accès configurable, et rafraîchissez le token à l'approche de son expiration. Kubelet fait tourner le token de manière proactive s'il est plus vieux que 80% de son TTL total, ou si le token est plus vieux que 24 heures.
L'application est responsable du rechargement du token lorsque celui ci est renouvelé. Un rechargement périodique (par ex. toutes les 5 minutes) est suffisant pour la plupart des cas d'utilisation.
7 - Récupération d'une image d'un registre privé
Cette page montre comment créer un Pod qui utilise un Secret pour récupérer une image d'un registre privé.
Pré-requis
-
Vous devez disposer d'un cluster Kubernetes et l'outil de ligne de commande kubectl doit être configuré pour communiquer avec votre cluster. Si vous ne possédez pas déjà de cluster, vous pouvez en créer un en utilisant Minikube, ou vous pouvez utiliser l'un de ces environnements Kubernetes:
Pour consulter la version, entrezkubectl version
. -
Pour faire cet exercice, vous avez besoin d'un Docker ID et un mot de passe.
Connectez-vous à Docker
Sur votre ordinateur, vous devez vous authentifier à un registre afin de récupérer une image privée :
docker login
Une fois que c'est fait, entrez votre nom d'utilisateur et votre mot de passe Docker.
Le processus de connexion crée ou met à jour un fichier config.json
qui contient un token d'autorisation.
Consultez le fichier config.json
:
cat ~/.docker/config.json
La sortie comporte une section similaire à celle-ci :
{
"auths": {
"https://index.docker.io/v1/": {
"auth": "c3R...zE2"
}
}
}
auth
mais une entrée credsStore
avec le nom du Store comme valeur.
Créez un Secret basé sur les identifiants existants du Docker
Le cluster Kubernetes utilise le type Secret de docker-registry
pour s'authentifier avec
un registre de conteneurs pour y récupérer une image privée.
Si vous avez déjà lancé docker login
, vous pouvez copier ces identifiants dans Kubernetes
kubectl create secret generic regcred \
--from-file=.dockerconfigjson=<path/to/.docker/config.json> \
--type=kubernetes.io/dockerconfigjson
Si vous avez besoin de plus de contrôle (par exemple, pour définir un Namespace ou un label sur le nouveau secret), vous pouvez alors personnaliser le secret avant de le stocker. Assurez-vous de :
- Attribuer la valeur
.dockerconfigjson
dans le nom de l'élément data - Encoder le fichier docker en base64 et colle cette chaîne, non interrompue, comme valeur du champ
data[".dockerconfigjson"]
. - Mettre
type
àkubernetes.io/dockerconfigjson
.
Exemple:
apiVersion: v1
kind: Secret
metadata:
name: myregistrykey
namespace: awesomeapps
data:
.dockerconfigjson: UmVhbGx5IHJlYWxseSByZWVlZWVlZWVlZWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGx5eXl5eXl5eXl5eXl5eXl5eXl5eSBsbGxsbGxsbGxsbGxsbG9vb29vb29vb29vb29vb29vb29vb29vb29vb25ubm5ubm5ubm5ubm5ubm5ubm5ubm5ubmdnZ2dnZ2dnZ2dnZ2dnZ2dnZ2cgYXV0aCBrZXlzCg==
type: kubernetes.io/dockerconfigjson
Si vous obtenez le message d'erreur error: no objects passed to create
, cela peut signifier que la chaîne encodée en base64 est invalide.
Si vous obtenez un message d'erreur comme Secret "myregistrykey" is invalid: data[.dockerconfigjson]: invalid value ...
, cela signifie que la chaîne encodée en base64 a été décodée avec succès, mais n'a pas pu être interprétée comme un fichier .docker/config.json
.
Créez un Secret en fournissant les identifiants sur la ligne de commande
Créez ce secret, en le nommant regcred
:
kubectl create secret docker-registry regcred --docker-server=<your-registry-server> --docker-username=<your-name> --docker-password=<your-pword> --docker-email=<your-email>
où :
<your-registry-server>
est votre FQDN de registre de docker privé. (https://index.docker.io/v1/ for DockerHub)<your-name>
est votre nom d'utilisateur Docker.<your-pword>
est votre mot de passe Docker.<your-email>
est votre email Docker.
Vous avez réussi à définir vos identifiants Docker dans le cluster comme un secret appelé regcred
.
kubectl
.
Inspection du secret regcred
Pour comprendre le contenu du Secret regcred
que vous venez de créer, commencez par visualiser le Secret au format YAML :
kubectl get secret regcred --output=yaml
La sortie est similaire à celle-ci :
apiVersion: v1
kind: Secret
metadata:
...
name: regcred
...
data:
.dockerconfigjson: eyJodHRwczovL2luZGV4L ... J0QUl6RTIifX0=
type: kubernetes.io/dockerconfigjson
La valeur du champ .dockerconfigjson
est une représentation en base64 de vos identifiants Docker.
Pour comprendre ce que contient le champ .dockerconfigjson
, convertissez les données secrètes en un format lisible :
kubectl get secret regcred --output="jsonpath={.data.\.dockerconfigjson}" | base64 --decode
La sortie est similaire à celle-ci :
{"auths":{"your.private.registry.example.com":{"username":"janedoe","password":"xxxxxxxxxxx","email":"jdoe@example.com","auth":"c3R...zE2"}}}
Pour comprendre ce qui se cache dans le champ `auth', convertissez les données encodées en base64 dans un format lisible :
echo "c3R...zE2" | base64 --decode
La sortie en tant que nom d'utilisateur et mot de passe concaténés avec un :
, est similaire à ceci :
janedoe:xxxxxxxxxxx
Remarquez que les données secrètes contiennent le token d'autorisation similaire à votre fichier local ~/.docker/config.json
.
Vous avez réussi à définir vos identifiants de Docker comme un Secret appelé regcred
dans le cluster.
Créez un Pod qui utilise votre Secret
Voici un fichier de configuration pour un Pod qui a besoin d'accéder à vos identifiants Docker dans regcred
:
apiVersion: v1
kind: Pod
metadata:
name: private-reg
spec:
containers:
- name: private-reg-container
image: <your-private-image>
imagePullSecrets:
- name: regcred
Téléchargez le fichier ci-dessus :
wget -O my-private-reg-pod.yaml https://k8s.io/examples/pods/private-reg-pod.yaml
Dans le fichier my-private-reg-pod.yaml
, remplacez <your-private-image>
par le chemin d'accès à une image dans un registre privé tel que
your.private.registry.example.com/janedoe/jdoe-private:v1
Pour récupérer l'image du registre privé, Kubernetes a besoin des identifiants.
Le champ imagePullSecrets
dans le fichier de configuration spécifie que Kubernetes doit obtenir les informations d'identification d'un Secret nommé regcred
.
Créez un Pod qui utilise votre secret et vérifiez que le Pod est bien lancé :
kubectl apply -f my-private-reg-pod.yaml
kubectl get pod private-reg
A suivre
- Pour en savoir plus sur les Secrets.
- Pour en savoir plus sur l'utilisation d'un registre privé.
- Pour en savoir plus sur l'ajout d'un imagePullSecrets à un compte de service.
- Voir kubectl crée un Secret de registre de docker.
- Voir Secret.
- Voir le champ
imagePullSecrets
de PodSpec.
8 - Configurer les Liveness, Readiness et Startup Probes
Cette page montre comment configurer les liveness, readiness et startup probes pour les conteneurs.
Le Kubelet utilise les liveness probes pour détecter quand redémarrer un conteneur. Par exemple, les Liveness probes pourraient attraper un deadlock dans le cas où une application est en cours d'exécution, mais qui est incapable de traiter les requêtes. Le redémarrage d'un conteneur dans un tel état rend l'application plus disponible malgré les bugs.
Le Kubelet utilise readiness probes pour savoir quand un conteneur est prêt à accepter le trafic. Un Pod est considéré comme prêt lorsque tous ses conteneurs sont prêts. Ce signal sert notamment à contrôler les pods qui sont utilisés comme backends pour les Services. Lorsqu'un Pod n'est pas prêt, il est retiré des équilibreurs de charge des Services.
Le Kubelet utilise startup probes pour savoir quand une application d'un conteneur a démarré. Si une telle probe est configurée, elle désactive les contrôles de liveness et readiness jusqu'à cela réussit, en s'assurant que ces probes n'interfèrent pas avec le démarrage de l'application. Cela peut être utilisé dans le cas des liveness checks sur les conteneurs à démarrage lent, en les évitant de se faire tuer par le Kubelet avant qu'ils ne soient opérationnels.
Pré-requis
Vous devez disposer d'un cluster Kubernetes et l'outil de ligne de commande kubectl doit être configuré pour communiquer avec votre cluster. Si vous ne possédez pas déjà de cluster, vous pouvez en créer un en utilisant Minikube, ou vous pouvez utiliser l'un de ces environnements Kubernetes:
Pour consulter la version, entrezkubectl version
.
Définir une commande de liveness
De nombreuses applications fonctionnant pour des longues périodes finissent par passer à des états de rupture et ne peuvent pas se rétablir, sauf en étant redémarrées. Kubernetes fournit des liveness probes pour détecter et remédier à ces situations.
Dans cet exercice, vous allez créer un Pod qui exécute un conteneur basé sur l'image k8s.gcr.io/busybox
. Voici le fichier de configuration pour le Pod :
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-exec
spec:
containers:
- name: liveness
image: k8s.gcr.io/busybox
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
Dans le fichier de configuration, vous constatez que le Pod a un seul conteneur.
Le champ periodSeconds
spécifie que le Kubelet doit effectuer un check de liveness toutes les 5 secondes. Le champ initialDelaySeconds
indique au Kubelet qu'il devrait attendre 5 secondes avant d'effectuer la première probe. Pour effectuer une probe, le Kubelet exécute la commande cat /tmp/healthy
dans le conteneur. Si la commande réussit, elle renvoie 0, et le Kubelet considère que le conteneur est vivant et en bonne santé. Si la commande renvoie une valeur non nulle, le Kubelet tue le conteneur et le redémarre.
Au démarrage, le conteneur exécute cette commande :
/bin/sh -c "touch /tmp/healthy; sleep 30; rm -rf /tmp/healthy; sleep 600"
Pour les 30 premières secondes de la vie du conteneur, il y a un fichier /tmp/healthy
.
Donc pendant les 30 premières secondes, la commande cat /tmp/healthy
renvoie un code de succès. Après 30 secondes, cat /tmp/healthy
renvoie un code d'échec.
Créez le Pod :
kubectl apply -f https://k8s.io/examples/pods/probe/exec-liveness.yaml
Dans les 30 secondes, visualisez les événements du Pod :
kubectl describe pod liveness-exec
La sortie indique qu'aucune liveness probe n'a encore échoué :
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
24s 24s 1 {default-scheduler } Normal Scheduled Successfully assigned liveness-exec to worker0
23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Pulling pulling image "k8s.gcr.io/busybox"
23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Pulled Successfully pulled image "k8s.gcr.io/busybox"
23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Created Created container with docker id 86849c15382e; Security:[seccomp=unconfined]
23s 23s 1 {kubelet worker0} spec.containers{liveness} Normal Started Started container with docker id 86849c15382e
Après 35 secondes, visualisez à nouveau les événements du Pod :
kubectl describe pod liveness-exec
Au bas de la sortie, il y a des messages indiquant que les liveness probes ont échoué, et que les conteneurs ont été tués et recréés.
FirstSeen LastSeen Count From SubobjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
37s 37s 1 {default-scheduler } Normal Scheduled Successfully assigned liveness-exec to worker0
36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Pulling pulling image "k8s.gcr.io/busybox"
36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Pulled Successfully pulled image "k8s.gcr.io/busybox"
36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Created Created container with docker id 86849c15382e; Security:[seccomp=unconfined]
36s 36s 1 {kubelet worker0} spec.containers{liveness} Normal Started Started container with docker id 86849c15382e
2s 2s 1 {kubelet worker0} spec.containers{liveness} Warning Unhealthy Liveness probe failed: cat: can't open '/tmp/healthy': No such file or directory
Attendez encore 30 secondes et vérifiez que le conteneur a été redémarré :
kubectl get pod liveness-exec
La sortie montre que RESTARTS
a été incrémenté :
NAME READY STATUS RESTARTS AGE
liveness-exec 1/1 Running 1 1m
Définir une requête HTTP de liveness
Un autre type de liveness probe utilise une requête GET HTTP. Voici la configuration
d'un Pod qui fait fonctionner un conteneur basé sur l'image k8s.gcr.io/liveness
.
apiVersion: v1
kind: Pod
metadata:
labels:
test: liveness
name: liveness-http
spec:
containers:
- name: liveness
image: k8s.gcr.io/liveness
args:
- /server
livenessProbe:
httpGet:
path: /healthz
port: 8080
httpHeaders:
- name: Custom-Header
value: Awesome
initialDelaySeconds: 3
periodSeconds: 3
Dans le fichier de configuration, vous pouvez voir que le Pod a un seul conteneur.
Le champ periodSeconds
spécifie que le Kubelet doit effectuer une liveness probe toutes les 3 secondes. Le champ initialDelaySeconds
indique au Kubelet qu'il devrait attendre 3 secondes avant d'effectuer la première probe. Pour effectuer une probe, le Kubelet envoie une requête HTTP GET au serveur qui s'exécute dans le conteneur et écoute sur le port 8080. Si le handler du chemin /healthz
du serveur renvoie un code de succès, le Kubelet considère que le conteneur est vivant et en bonne santé. Si le handler renvoie un code d'erreur, le Kubelet tue le conteneur et le redémarre.
Tout code supérieur ou égal à 200 et inférieur à 400 indique un succès. Tout autre code indique un échec.
Vous pouvez voir le code source du serveur dans server.go.
Pendant les 10 premières secondes où le conteneur est en vie, le handler /healthz
renvoie un statut de 200. Après cela, le handler renvoie un statut de 500.
http.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
duration := time.Now().Sub(started)
if duration.Seconds() > 10 {
w.WriteHeader(500)
w.Write([]byte(fmt.Sprintf("erreur: %v", duration.Seconds())))
} else {
w.WriteHeader(200)
w.Write([]byte("ok"))
}
})
Le Kubelet commence à effectuer des contrôles de santé 3 secondes après le démarrage du conteneur. Ainsi, les premiers contrôles de santé seront réussis. Mais après 10 secondes, les contrôles de santé échoueront, et le Kubelet tuera et redémarrera le conteneur.
Pour essayer le HTTP liveness check, créez un Pod :
kubectl apply -f https://k8s.io/examples/pods/probe/http-liveness.yaml
Après 10 secondes, visualisez les événements du Pod pour vérifier que les liveness probes ont échoué et le conteneur a été redémarré :
kubectl describe pod liveness-http
Dans les versions antérieures à la v1.13 (y compris la v1.13), au cas où la variable d'environnement http_proxy
(ou HTTP_PROXY
) est définie sur le noeud où tourne un Pod, le HTTP liveness probe utilise ce proxy.
Dans les versions postérieures à la v1.13, les paramètres de la variable d'environnement du HTTP proxy local n'affectent pas le HTTP liveness probe.
Définir une TCP liveness probe
Un troisième type de liveness probe utilise un TCP Socket. Avec cette configuration, le Kubelet tentera d'ouvrir un socket vers votre conteneur sur le port spécifié. S'il arrive à établir une connexion, le conteneur est considéré comme étant en bonne santé, s'il n'y arrive pas, c'est un échec.
apiVersion: v1
kind: Pod
metadata:
name: goproxy
labels:
app: goproxy
spec:
containers:
- name: goproxy
image: k8s.gcr.io/goproxy:0.1
ports:
- containerPort: 8080
readinessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
Comme vous le voyez, la configuration pour un check TCP est assez similaire à un check HTTP.
Cet exemple utilise à la fois des readiness et liveness probes. Le Kubelet transmettra la première readiness probe 5 secondes après le démarrage du conteneur. Il tentera de se connecter au conteneur goproxy
sur le port 8080. Si la probe réussit, le conteneur sera marqué comme prêt. Kubelet continuera à effectuer ce check tous les 10 secondes.
En plus de la readiness probe, cette configuration comprend une liveness probe.
Le Kubelet effectuera la première liveness probe 15 secondes après que le conteneur démarre. Tout comme la readiness probe, celle-ci tentera de se connecter au conteneur de goproxy
sur le port 8080. Si la liveness probe échoue, le conteneur sera redémarré.
Pour essayer la TCP liveness check, créez un Pod :
kubectl apply -f https://k8s.io/examples/pods/probe/tcp-liveness-readiness.yaml
Après 15 secondes, visualisez les événements de Pod pour vérifier les liveness probes :
kubectl describe pod goproxy
Utilisation d'un port nommé
Vous pouvez utiliser un ContainerPort nommé pour les HTTP or TCP liveness probes :
ports:
- name: liveness-port
containerPort: 8080
hostPort: 8080
livenessProbe:
httpGet:
path: /healthz
port: liveness-port
Protéger les conteneurs à démarrage lent avec des startup probes
Parfois, vous devez faire face à des applications legacy qui peuvent nécessiter un temps de démarrage supplémentaire lors de leur première initialisation.
Dans de telles situations, il peut être compliqué de régler les paramètres de la liveness probe sans compromettant la réponse rapide aux blocages qui ont motivé une telle probe.
L'astuce est de configurer une startup probe avec la même commande, HTTP ou TCP check avec un failureThreshold * periodSeconds
assez long pour couvrir le pire des scénarios des temps de démarrage.
Ainsi, l'exemple précédent deviendrait :
ports:
- name: liveness-port
containerPort: 8080
hostPort: 8080
livenessProbe:
httpGet:
path: /healthz
port: liveness-port
failureThreshold: 1
periodSeconds: 10
startupProbe:
httpGet:
path: /healthz
port: liveness-port
failureThreshold: 30
periodSeconds: 10
Grâce à la startup probe, l'application aura un maximum de 5 minutes (30 * 10 = 300s) pour terminer son démarrage.
Une fois que la startup probe a réussi, la liveness probe prend le relais pour fournir une réponse rapide aux blocages de conteneurs.
Si la startup probe ne réussit jamais, le conteneur est tué après 300s puis soumis à la restartPolicy
(politique de redémarrage) du Pod.
Définir les readiness probes
Parfois, les applications sont temporairement incapables de servir le trafic. Par exemple, une application peut avoir besoin de charger des larges données ou des fichiers de configuration pendant le démarrage, ou elle peut dépendre de services externes après le démarrage. Dans ces cas, vous ne voulez pas tuer l'application, mais vous ne voulez pas non plus lui envoyer de requêtes. Kubernetes fournit des readiness probes pour détecter et atténuer ces situations. Un pod avec des conteneurs qui signale qu'elle n'est pas prête ne reçoit pas de trafic par les services de Kubernetes.
Readiness probes sont configurées de la même façon que les liveness probes. La seule différence est que vous utilisez le champ readinessProbe
au lieu du champ livenessProbe
.
readinessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
La configuration des readiness probes HTTP et TCP reste également identique à celle des liveness probes.
Les readiness et liveness probes peuvent être utilisées en parallèle pour le même conteneur. L'utilisation des deux peut garantir que le trafic n'atteigne pas un conteneur qui n'est pas prêt et que les conteneurs soient redémarrés en cas de défaillance.
Configurer les Probes
Probes ont un certain nombre de champs qui vous pouvez utiliser pour contrôler plus précisément le comportement de la vivacité et de la disponibilité des probes :
initialDelaySeconds
: Nombre de secondes après le démarrage du conteneur avant que les liveness et readiness probes ne soient lancées. La valeur par défaut est de 0 seconde. La valeur minimale est 0.periodSeconds
: La fréquence (en secondes) à laquelle la probe doit être effectuée. La valeur par défaut est de 10 secondes. La valeur minimale est de 1.timeoutSeconds
: Nombre de secondes après lequel la probe time out. Valeur par défaut à 1 seconde. La valeur minimale est de 1.successThreshold
: Le minimum de succès consécutifs pour que la probe soit considérée comme réussie après avoir échoué. La valeur par défaut est 1. Doit être 1 pour la liveness probe. La valeur minimale est de 1.failureThreshold
: Quand un Pod démarre et que la probe échoue, Kubernetes va tenterfailureThreshold
fois avant d'abandonner. Abandonner en cas de liveness probe signifie le redémarrage du conteneur. En cas de readiness probe, le Pod sera marqué Unready. La valeur par défaut est 3, la valeur minimum est 1.
HTTP probes
ont des champs supplémentaires qui peuvent être définis sur httpGet
:
host
: Nom de l'hôte auquel se connecter, par défaut l'IP du pod. Vous voulez peut être mettre "Host" en httpHeaders à la place.scheme
: Schéma à utiliser pour se connecter à l'hôte (HTTP ou HTTPS). La valeur par défaut est HTTP.path
: Chemin d'accès sur le serveur HTTP.httpHeaders
: En-têtes personnalisés à définir dans la requête. HTTP permet des en-têtes répétés.port
: Nom ou numéro du port à accéder sur le conteneur. Le numéro doit être dans un intervalle de 1 à 65535.
Pour une probe HTTP, le Kubelet envoie une requête HTTP au chemin et au port spécifiés pour effectuer la vérification. Le Kubelet envoie la probe à l'adresse IP du Pod, à moins que l'adresse ne soit surchargée par le champ optionnel host
dans httpGet
. Si Le champ scheme
est mis à HTTPS
, le Kubelet envoie une requête HTTPS en ignorant la vérification du certificat. Dans la plupart des scénarios, vous ne voulez pas définir le champ host
.
Voici un scénario où vous le mettriez en place. Supposons que le conteneur écoute sur 127.0.0.1 et que le champ hostNetwork
du Pod a la valeur true. Alors host
, sous httpGet
, devrait être défini à 127.0.0.1. Si votre Pod repose sur des hôtes virtuels, ce qui est probablement plus courant, vous ne devriez pas utiliser host
, mais plutôt mettre l'en-tête Host
dans httpHeaders
.
Le Kubelet fait la connexion de la probe au noeud, pas dans le Pod, ce qui signifie que vous ne pouvez pas utiliser un nom de service dans le paramètre host
puisque le Kubelet est incapable pour le résoudre.
A suivre
- Pour en savoir plus sur Probes des Conteneurs.
Référence
9 - Assigner des pods aux nœuds
Cette page montre comment assigner un Pod à un nœud particulier dans un cluster Kubernetes.
Pré-requis
Vous devez disposer d'un cluster Kubernetes et l'outil de ligne de commande kubectl doit être configuré pour communiquer avec votre cluster. Si vous ne possédez pas déjà de cluster, vous pouvez en créer un en utilisant Minikube, ou vous pouvez utiliser l'un de ces environnements Kubernetes:
Pour consulter la version, entrezkubectl version
.
Ajouter un label à un nœud
-
Listez les nœuds de votre cluster :
kubectl get nodes
La sortie est la suivante :
NAME STATUS ROLES AGE VERSION worker0 Ready <none> 1d v1.13.0 worker1 Ready <none> 1d v1.13.0 worker2 Ready <none> 1d v1.13.0
-
Choisissez l'un de vos nœuds et ajoutez-y un label :
kubectl label nodes <your-node-name> disktype=ssd
où
<your-node-name>
est le nom du noeud que vous avez choisi. -
Vérifiez que le nœud que vous avez choisi a le label
disktype=ssd
:kubectl get nodes --show-labels
La sortie est la suivante :
NAME STATUS ROLES AGE VERSION LABELS worker0 Ready <none> 1d v1.13.0 ...,disktype=ssd,kubernetes.io/hostname=worker0 worker1 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker1 worker2 Ready <none> 1d v1.13.0 ...,kubernetes.io/hostname=worker2
Dans la sortie précédente, vous constatez que le nœud
worker0
possède le labeldisktype=ssd
.
Créez un pod qui sera planifié sur un nœud sélectionné.
Le fichier de configuration de pod décrit un pod qui possède un selector de nœud de type disktype:ssd
. Cela signifie que le pod sera planifié sur un nœud ayant le label disktype=ssd
.
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
env: test
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
nodeSelector:
disktype: ssd
-
Utilisez le fichier de configuration pour créer un pod qui sera ordonnancé sur votre nœud choisi :
kubectl apply -f https://k8s.io/examples/pods/pod-nginx.yaml
-
Vérifiez que le pod fonctionne sur le nœud que vous avez choisi :
kubectl get pods --output=wide
La sortie est la suivante :
NAME READY STATUS RESTARTS AGE IP NODE nginx 1/1 Running 0 13s 10.200.0.4 worker0
Créez un pod qui va être planifié sur un nœud spécifique
Vous pouvez également ordonnancer un pod sur un nœud spécifique via le paramètre nodeName
.
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
nodeName: foo-node # schedule pod to specific node
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
Utilisez le fichier de configuration pour créer un pod qui sera ordonnancé sur foo-node
uniquement.
A suivre
Pour en savoir plus sur labels et selectors.
10 - Configurer l'initialisation du pod
Cette page montre comment utiliser un Init conteneur pour initialiser un Pod avant de lancer un conteneur d'application.
Pré-requis
Vous devez disposer d'un cluster Kubernetes et l'outil de ligne de commande kubectl doit être configuré pour communiquer avec votre cluster. Si vous ne possédez pas déjà de cluster, vous pouvez en créer un en utilisant Minikube, ou vous pouvez utiliser l'un de ces environnements Kubernetes:
Pour consulter la version, entrezkubectl version
.
Créer un Pod qui a un Init Container
Dans cet exercice, vous allez créer un Pod qui a un conteneur d'application et Init conteneur. Le conteneur d'initialisation est achevé avant que le conteneur d'application ne démarre.
Voici le fichier de configuration du Pod :
apiVersion: v1
kind: Pod
metadata:
name: init-demo
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: workdir
mountPath: /usr/share/nginx/html
# These containers are run during pod initialization
initContainers:
- name: install
image: busybox
command:
- wget
- "-O"
- "/work-dir/index.html"
- http://kubernetes.io
volumeMounts:
- name: workdir
mountPath: "/work-dir"
dnsPolicy: Default
volumes:
- name: workdir
emptyDir: {}
Dans le fichier de configuration, vous pouvez voir que le Pod a un Volume que le conteneur d'initialisation et le conteneur d'application partagent.
Le conteneur d'initialisation monte le volume partagé à /work-dir
, et le conteneur d'application monte le volume partagé à /usr/share/nginx/html
. Le conteneur d'initialisation exécute la commande suivante puis se termine :
wget -O /work-dir/index.html http://kubernetes.io
Remarquez que le conteneur d'initialisation écrit le fichier index.html
dans le répertoire racine
du serveur nginx.
Créez le Pod :
kubectl apply -f https://k8s.io/examples/pods/init-containers.yaml
Vérifiez que le conteneur nginx fonctionne :
kubectl get pod init-demo
La sortie montre que le conteneur nginx est en cours d'exécution :
NAME READY STATUS RESTARTS AGE
init-demo 1/1 Running 0 1m
Entrez dans la console shell du conteneur nginx du Pod init-demo :
kubectl exec -it init-demo -- /bin/bash
Dans votre shell, envoyez une requête GET au serveur nginx :
root@nginx:~# apt-get update
root@nginx:~# apt-get install curl
root@nginx:~# curl localhost
La sortie montre que nginx sert la page web qui a été écrite par le conteneur d'initialisation :
<!Doctype html>
<html id="home">
<head>
...
"url": "http://kubernetes.io/"}</script>
</head>
<body>
...
<p>Kubernetes is open source giving you the freedom to take advantage ...</p>
...
A suivre
- Pour en savoir plus sur communiquer entre conteneurs fonctionnant dans le même Pod.
- Pour en savoir plus sur Init Conteneurs.
- Pour en savoir plus sur Volumes.
- Pour en savoir plus sur Débogage des Init Conteneurs
11 - Configurer un pod pour utiliser une ConfigMap
Les ConfigMaps vous permettent de découpler les artefacts de configuration du contenu de l'image pour garder les applications conteneurisées portables. Cette page fournit une série d'exemples d'utilisation montrant comment créer des ConfigMaps et configurer des pods à l'aide des données stockées dans des ConfigMaps.
Pré-requis
Vous devez disposer d'un cluster Kubernetes et l'outil de ligne de commande kubectl doit être configuré pour communiquer avec votre cluster. Si vous ne possédez pas déjà de cluster, vous pouvez en créer un en utilisant Minikube, ou vous pouvez utiliser l'un de ces environnements Kubernetes:
Pour consulter la version, entrezkubectl version
.
Créer un ConfigMap
Vous pouvez utiliser soit kubectl create configmap
ou un générateur ConfigMap dans kustomization.yaml
pour créer un ConfigMap.
Notez que kubectl
prends en charge kustomization.yaml
à partir de la version 1.14.
Créer un ConfigMap à l'aide de kubectl create configmap
Utilisez la commande kubectl create configmap
pour créer des Configmaps depuis des dossiers, fichiers, ou des valeurs littérales:
kubectl create configmap <map-name> <data-source>
où <map-name> est le nom que vous souhaitez attribuer à ConfigMap et <data-source> est le répertoire, le fichier ou la valeur littérale à partir de laquelle récupérer les données.
La source de données correspond à une paire clé-valeur dans ConfigMap, où
- clé = le nom du fichier ou la clé que vous avez fournie sur la ligne de commande, et
- valeur = le contenu du fichier ou la valeur littérale que vous avez fournie sur la ligne de commande.
Vous pouvez utiliser kubectl describe
ou kubectl get
pour récupérer des informations sur un ConfigMap.
Créer des ConfigMaps à partir de répertoires
Vous pouvez utiliser kubectl create configmap
pour créer un ConfigMap à partir de plusieurs fichiers dans le même répertoire.
Par exemple:
# Créez le répertoire local
mkdir -p configure-pod-container/configmap/
# Téléchargez les exemples de fichiers dans le répertoire `configure-pod-container/configmap/`
wget https://kubernetes.io/examples/configmap/game.properties -O configure-pod-container/configmap/game.properties
wget https://kubernetes.io/examples/configmap/ui.properties -O configure-pod-container/configmap/ui.properties
# Créer la configmap
kubectl create configmap game-config --from-file=configure-pod-container/configmap/
combine le contenu du répertoire configure-pod-container/configmap/
game.properties
ui.properties
dans le ConfigMap suivant:
kubectl describe configmaps game-config
où la sortie est similaire à ceci:
Name: game-config
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
game.properties: 158 bytes
ui.properties: 83 bytes
Les fichiers game.properties
et ui.properties
dans le répertoire configure-pod-container/configmap/
sont représentés dans la section data
de la ConfigMap.
kubectl get configmaps game-config -o yaml
La sortie est similaire à ceci:
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2016-02-18T18:52:05Z
name: game-config
namespace: default
resourceVersion: "516"
uid: b4952dc3-d670-11e5-8cd0-68f728db1985
data:
game.properties: |
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
ui.properties: |
color.good=purple
color.bad=yellow
allow.textmode=true
how.nice.to.look=fairlyNice
Créer des ConfigMaps à partir de fichiers
Vous pouvez utiliser kubectl create configmap
pour créer un ConfigMap à partir d'un fichier individuel ou de plusieurs fichiers.
Par exemple,
kubectl create configmap game-config-2 --from-file=configure-pod-container/configmap/game.properties
produirait le ConfigMap suivant:
kubectl describe configmaps game-config-2
où la sortie est similaire à ceci:
Name: game-config-2
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
game.properties: 158 bytes
Vous pouvez passer l'argument --from-file
plusieurs fois pour créer un ConfigMap à partir de plusieurs sources de données.
kubectl create configmap game-config-2 --from-file=configure-pod-container/configmap/game.properties --from-file=configure-pod-container/configmap/ui.properties
Décrivez la ConfigMap crée game-config-2
:
kubectl describe configmaps game-config-2
La sortie est similaire à ceci:
Name: game-config-2
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
game.properties: 158 bytes
ui.properties: 83 bytes
Utilisez l'option --from-env-file
pour créer un ConfigMap à partir d'un fichier env, par exemple:
# Les fichiers env contiennent une liste de variables d'environnement.
# Ces règles de syntaxe s'appliquent:
# Chaque ligne d'un fichier env doit être au format VAR=VAL.
# Les lignes commençant par # (c'est-à-dire les commentaires) sont ignorées.
# Les lignes vides sont ignorées.
# Il n'y a pas de traitement spécial des guillemets (c'est-à-dire qu'ils feront partie de la valeur ConfigMap)).
# Téléchargez les exemples de fichiers dans le dossier `configure-pod-container/configmap/`
wget https://kubernetes.io/examples/configmap/game-env-file.properties -O configure-pod-container/configmap/game-env-file.properties
# Le fichier env `game-env-file.properties` ressemble à ceci
cat configure-pod-container/configmap/game-env-file.properties
enemies=aliens
lives=3
allowed="true"
# Ce commentaire et la ligne vide au-dessus sont ignorés
kubectl create configmap game-config-env-file \
--from-env-file=configure-pod-container/configmap/game-env-file.properties
produirait le ConfigMap suivant:
kubectl get configmap game-config-env-file -o yaml
où la sortie est similaire à ceci:
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2017-12-27T18:36:28Z
name: game-config-env-file
namespace: default
resourceVersion: "809965"
uid: d9d1ca5b-eb34-11e7-887b-42010a8002b8
data:
allowed: '"true"'
enemies: aliens
lives: "3"
--from-env-file
pour créer un ConfigMap à partir de plusieurs sources de données, seul le dernier fichier env est utilisé.
Le comportement consistant à passer plusieurs fois --from-env-file
est démontré par:
# Téléchargez les exemples de fichiers dans le répertoire `configure-pod-container/configmap/`
wget https://k8s.io/examples/configmap/ui-env-file.properties -O configure-pod-container/configmap/ui-env-file.properties
# Créez le configmap
kubectl create configmap config-multi-env-files \
--from-env-file=configure-pod-container/configmap/game-env-file.properties \
--from-env-file=configure-pod-container/configmap/ui-env-file.properties
produirait le ConfigMap suivant:
kubectl get configmap config-multi-env-files -o yaml
où la sortie est similaire à ceci:
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2017-12-27T18:38:34Z
name: config-multi-env-files
namespace: default
resourceVersion: "810136"
uid: 252c4572-eb35-11e7-887b-42010a8002b8
data:
color: purple
how: fairlyNice
textmode: "true"
Définissez la clé à utiliser lors de la création d'un ConfigMap à partir d'un fichier
Vous pouvez définir une clé autre que le nom de fichier à utiliser dans la section data
de votre ConfigMap lorsque vous utilisez l'argument --from-file
:
kubectl create configmap game-config-3 --from-file=<my-key-name>=<path-to-file>
où <my-key-name>
est la clé que vous souhaitez utiliser dans la ConfigMap et <path-to-file>
est l'emplacement du fichier de source de données que vous souhaitez que la clé représente.
Par exemple:
kubectl create configmap game-config-3 --from-file=game-special-key=configure-pod-container/configmap/game.properties
produirait la ConfigMap suivante:
kubectl get configmaps game-config-3 -o yaml
où la sortie est similaire à ceci:
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2016-02-18T18:54:22Z
name: game-config-3
namespace: default
resourceVersion: "530"
uid: 05f8da22-d671-11e5-8cd0-68f728db1985
data:
game-special-key: |
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
Créer des ConfigMaps à partir de valeurs littérales
Vous pouvez utiliser kubectl create configmap
avec l'argument --from-literal
définir une valeur littérale à partir de la ligne de commande:
kubectl create configmap special-config --from-literal=special.how=very --from-literal=special.type=charm
Vous pouvez transmettre plusieurs paires clé-valeur.
Chaque paire fournie sur la ligne de commande est représentée comme une entrée distincte dans la section data
de la ConfigMap.
kubectl get configmaps special-config -o yaml
La sortie est similaire à ceci:
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2016-02-18T19:14:38Z
name: special-config
namespace: default
resourceVersion: "651"
uid: dadce046-d673-11e5-8cd0-68f728db1985
data:
special.how: very
special.type: charm
Créer un ConfigMap à partir du générateur
kubectl
supporte kustomization.yaml
depuis 1.14.
Vous pouvez également créer un ConfigMap à partir de générateurs, puis l'appliquer pour créer l'objet sur l'Apiserver.
Les générateurs doivent être spécifiés dans un kustomization.yaml
à l'intérieur d'un répertoire.
Générer des ConfigMaps à partir de fichiers
Par exemple, pour générer un ConfigMap à partir de fichiers configure-pod-container/configmap/game.properties
# Create a kustomization.yaml file with ConfigMapGenerator
cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: game-config-4
files:
- configure-pod-container/configmap/game.properties
EOF
Appliquer le dossier kustomization pour créer l'objet ConfigMap.
kubectl apply -k .
configmap/game-config-4-m9dm2f92bt created
Vous pouvez vérifier que le ConfigMap a été créé comme ceci:
kubectl get configmap
NAME DATA AGE
game-config-4-m9dm2f92bt 1 37s
kubectl describe configmaps/game-config-4-m9dm2f92bt
Name: game-config-4-m9dm2f92bt
Namespace: default
Labels: <none>
Annotations: kubectl.kubernetes.io/last-applied-configuration:
{"apiVersion":"v1","data":{"game.properties":"enemies=aliens\nlives=3\nenemies.cheat=true\nenemies.cheat.level=noGoodRotten\nsecret.code.p...
Data
====
game.properties:
----
enemies=aliens
lives=3
enemies.cheat=true
enemies.cheat.level=noGoodRotten
secret.code.passphrase=UUDDLRLRBABAS
secret.code.allowed=true
secret.code.lives=30
Events: <none>
Notez que le nom ConfigMap généré a un suffixe obtenu par hachage de son contenu. Cela garantit qu'un nouveau ConfigMap est généré chaque fois que le contenu est modifié.
Définissez la clé à utiliser lors de la génération d'un ConfigMap à partir d'un fichier
Vous pouvez définir une clé autre que le nom de fichier à utiliser dans le générateur ConfigMap.
Par exemple, pour générer un ConfigMap à partir du fichier configure-pod-container/configmap/game.properties
avec la clé game-special-key
# Créer un fichier kustomization.yaml avec ConfigMapGenerator
cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: game-config-5
files:
- game-special-key=configure-pod-container/configmap/game.properties
EOF
Appliquer le dossier kustomization pour créer l'objet ConfigMap.
kubectl apply -k .
configmap/game-config-5-m67dt67794 created
Générer des ConfigMaps à partir de littéraux
Pour générer un ConfigMap à partir de littéraux special.type=charm
et special.how=very
, vous pouvez spécifier le générateur ConfigMap dans kustomization.yaml
comme
# Create a kustomization.yaml file with ConfigMapGenerator
cat <<EOF >./kustomization.yaml
configMapGenerator:
- name: special-config-2
literals:
- special.how=very
- special.type=charm
EOF
Appliquez le dossier kustomization pour créer l'objet ConfigMap.
kubectl apply -k .
configmap/special-config-2-c92b5mmcf2 created
Définir des variables d'environnement de conteneur à l'aide des données ConfigMap
Définissez une variable d'environnement de conteneur avec les données d'une seule ConfigMap
-
Définissez une variable d'environnement comme paire clé-valeur dans un ConfigMap:
kubectl create configmap special-config --from-literal=special.how=very
-
Attribuez la valeur
special.how
défini dans ConfigMap à la variable d'environnementSPECIAL_LEVEL_KEY
dans la spécification du Pod.apiVersion: v1 kind: Pod metadata: name: dapi-test-pod spec: containers: - name: test-container image: k8s.gcr.io/busybox command: [ "/bin/sh", "-c", "env" ] env: # Définie la variable d'environnement - name: SPECIAL_LEVEL_KEY valueFrom: configMapKeyRef: # La ConfigMap contenant la valeur que vous voulez attribuer à SPECIAL_LEVEL_KEY name: special-config # Spécifier la clé associée à la valeur key: special.how restartPolicy: Never
Créez le pod:
kubectl create -f https://kubernetes.io/examples/pods/pod-single-configmap-env-variable.yaml
Maintenant, la sortie du Pod comprend une variable d'environnement SPECIAL_LEVEL_KEY=very
.
Définir des variables d'environnement de conteneur avec des données de plusieurs ConfigMaps
-
Comme avec l'exemple précédent, créez d'abord les ConfigMaps.
apiVersion: v1 kind: ConfigMap metadata: name: special-config namespace: default data: special.how: very --- apiVersion: v1 kind: ConfigMap metadata: name: env-config namespace: default data: log_level: INFO
Créez le ConfigMap:
kubectl create -f https://kubernetes.io/examples/configmap/configmaps.yaml
-
Définissez les variables d'environnement dans la spécification Pod.
apiVersion: v1 kind: Pod metadata: name: dapi-test-pod spec: containers: - name: test-container image: k8s.gcr.io/busybox command: [ "/bin/sh", "-c", "env" ] env: - name: SPECIAL_LEVEL_KEY valueFrom: configMapKeyRef: name: special-config key: special.how - name: LOG_LEVEL valueFrom: configMapKeyRef: name: env-config key: log_level restartPolicy: Never
Créez le pod:
kubectl create -f https://kubernetes.io/examples/pods/pod-multiple-configmap-env-variable.yaml
Maintenant, la sortie du Pod comprend des variables d'environnement SPECIAL_LEVEL_KEY=very
et LOG_LEVEL=INFO
.
Configurer toutes les paires clé-valeur dans un ConfigMap en tant que variables d'environnement de conteneur
-
Créez un ConfigMap contenant plusieurs paires clé-valeur.
apiVersion: v1 kind: ConfigMap metadata: name: special-config namespace: default data: SPECIAL_LEVEL: very SPECIAL_TYPE: charm
Créez le ConfigMap:
kubectl create -f https://kubernetes.io/examples/configmap/configmap-multikeys.yaml
- Utilisez
envFrom
pour définir toutes les données du ConfigMap en tant que variables d'environnement du conteneur. La clé de ConfigMap devient le nom de la variable d'environnement dans le pod.
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: k8s.gcr.io/busybox
command: [ "/bin/sh", "-c", "env" ]
envFrom:
- configMapRef:
name: special-config
restartPolicy: Never
Créez le pod:
kubectl create -f https://kubernetes.io/examples/pods/pod-configmap-envFrom.yaml
Maintenant, la sortie du Pod comprend les variables d'environnement SPECIAL_LEVEL=very
et SPECIAL_TYPE=charm
.
Utiliser des variables d'environnement définies par ConfigMap dans les commandes du Pod
Vous pouvez utiliser des variables d'environnement définies par ConfigMap dans la section command
de la spécification du Pod en utilisant la syntaxe de substitution Kubernetes $(VAR_NAME)
.
Par exemple, la spécification de pod suivante
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: k8s.gcr.io/busybox
command: [ "/bin/echo", "$(SPECIAL_LEVEL_KEY) $(SPECIAL_TYPE_KEY)" ]
env:
- name: SPECIAL_LEVEL_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: SPECIAL_LEVEL
- name: SPECIAL_TYPE_KEY
valueFrom:
configMapKeyRef:
name: special-config
key: SPECIAL_TYPE
restartPolicy: Never
créé en exécutant
kubectl create -f https://kubernetes.io/examples/pods/pod-configmap-env-var-valueFrom.yaml
produit la sortie suivante dans le conteneur test-container
:
very charm
Ajouter des données ConfigMap à un volume
Comme expliqué dans Créer des ConfigMaps à partir de fichiers, lorsque vous créez un ConfigMap à l'aide --from-file
, le nom de fichier devient une clé stockée dans la section data
du ConfigMap.
Le contenu du fichier devient la valeur de la clé.
Les exemples de cette section se réfèrent à un ConfigMap nommé special-config, illustré ci-dessous.
apiVersion: v1
kind: ConfigMap
metadata:
name: special-config
namespace: default
data:
SPECIAL_LEVEL: very
SPECIAL_TYPE: charm
Créez le ConfigMap:
kubectl create -f https://kubernetes.io/examples/configmap/configmap-multikeys.yaml
Remplissez un volume avec des données stockées dans un ConfigMap
Ajoutez le nom ConfigMap sous la section volumes
de la spécification Pod.
Ceci ajoute les données ConfigMap au répertoire spécifié comme volumeMounts.mountPath
(dans ce cas, /etc/config
).
La section command
répertorie les fichiers de répertoire dont les noms correspondent aux clés de ConfigMap.
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: k8s.gcr.io/busybox
command: [ "/bin/sh", "-c", "ls /etc/config/" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
# Indiquez le nom de la ConfigMap contenant les fichiers que vous souhaitez ajouter au conteneur
name: special-config
restartPolicy: Never
Créez le pod:
kubectl create -f https://kubernetes.io/examples/pods/pod-configmap-volume.yaml
Lorsque le pod s'exécute, la commande ls /etc/config/
produit la sortie ci-dessous:
SPECIAL_LEVEL
SPECIAL_TYPE
/etc/config/
, ils seront supprimés.
Ajouter un configmap à un chemin spécifique dans un volume
Utilisez le champ path
pour spécifier le chemin de fichier souhaité pour les éléments de configmap spécifiques.
Dans ce cas, le SPECIAL_LEVEL
sera monté dans le volume config-volume
au chemin /etc/config/keys
.
apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: k8s.gcr.io/busybox
command: [ "/bin/sh","-c","cat /etc/config/keys" ]
volumeMounts:
- name: config-volume
mountPath: /etc/config
volumes:
- name: config-volume
configMap:
name: special-config
items:
- key: SPECIAL_LEVEL
path: keys
restartPolicy: Never
Créez le Pod :
kubectl create -f https://kubernetes.io/examples/pods/pod-configmap-volume-specific-key.yaml
Lorsque le pod fonctionne, la commande cat /etc/config/keys
produit la sortie ci-dessous :
very
/etc/config/
seront supprimés.
Projections de clés pour des chemins et des autorisations de fichiers spécifiques
Vous pouvez projeter des clés vers des chemins spécifiques avec des autorisations spécifiques fichiers par fichiers. Le guide de l'utilisateur Secrets explique la syntaxe.
Les ConfigMaps montées sont mises à jour automatiquement
Lorsqu'une ConfigMap déjà consommée dans un volume est mise à jour, les clés projetées sont éventuellement mises à jour elles aussi. Kubelet vérifie si la ConfigMap montée est fraîche à chaque synchronisation périodique. Cependant, il utilise son cache local basé sur le ttl pour obtenir la valeur actuelle de la ConfigMap. Par conséquent, le délai total entre le moment où la ConfigMap est mise à jour et le moment où les nouvelles clés sont projetées vers le pod peut être aussi long que la période de synchronisation de kubelet (1 minute par défaut) + le ttl du cache ConfigMaps (1 minute par défaut) dans kubelet. Vous pouvez déclencher un rafraîchissement immédiat en mettant à jour l'une des annotations du pod.
Comprendre le lien entre les ConfigMaps et les Pods
La ressource API ConfigMap stocke les données de configuration sous forme de paires clé-valeur. Les données peuvent être consommées dans des pods ou fournir les configurations des composants du système tels que les contrôleurs. ConfigMap est similaire à Secrets, mais fournit un moyen de travailler avec des chaînes de caractères qui ne contiennent pas d'informations sensibles. Les utilisateurs comme les composants du système peuvent stocker des données de configuration dans un ConfigMap.
/etc
de Linux et à son contenu.
Par exemple, si vous créez un volume Kubernetes à partir d'une ConfigMap, chaque élément de données de la ConfigMap est représenté par un fichier individuel dans le volume.
Le champ data
de la ConfigMap contient les données de configuration.
Comme le montre l'exemple ci-dessous, cela peut être simple -- comme des propriétés individuelles définies à l'aide de --from-literal
-- ou complexe -- comme des fichiers de configuration ou des blobs JSON définis à l'aide de --from-file
.
apiVersion: v1
kind: ConfigMap
metadata:
creationTimestamp: 2016-02-18T19:14:38Z
name: example-config
namespace: default
data:
# example of a simple property defined using --from-literal
example.property.1: hello
example.property.2: world
# example of a complex property defined using --from-file
example.property.file: |-
property.1=value-1
property.2=value-2
property.3=value-3
Restrictions
-
Vous devez créer un ConfigMap avant de le référencer dans une spécification de Pod (sauf si vous marquez le ConfigMap comme "facultatif"). Si vous faites référence à un ConfigMap qui n'existe pas, le Pod ne démarrera pas. De même, les références à des clés qui n'existent pas dans la ConfigMap empêcheront le pod de démarrer.
-
Si vous utilisez
envFrom
pour définir des variables d'environnement à partir de ConfigMaps, les clés considérées comme invalides seront ignorées. Le pod sera autorisé à démarrer, mais les noms invalides seront enregistrés dans le journal des événements (InvalidVariableNames
). Le message du journal énumère chaque clé sautée. Par exemple :kubectl get events
Le résultat est similaire à celui-ci :
LASTSEEN FIRSTSEEN COUNT NAME KIND SUBOBJECT TYPE REASON SOURCE MESSAGE 0s 0s 1 dapi-test-pod Pod Warning InvalidEnvironmentVariableNames {kubelet, 127.0.0.1} Keys [1badkey, 2alsobad] from the EnvFrom configMap default/myconfig were skipped since they are considered invalid environment variable names.
-
Les ConfigMaps résident dans un Namespace. Un ConfigMap ne peut être référencé que par des pods résidant dans le même namespace.
-
Vous ne pouvez pas utiliser des ConfigMaps pour static pods, car le Kubelet ne le supporte pas.
A suivre
- Suivez un exemple concret de Configurer Redis en utilisant un ConfigMap.
12 - Partager l'espace de nommage des processus entre les conteneurs d'un Pod
Kubernetes v1.17 [stable]
Cette page montre comment configurer le partage de l'espace de noms d'un processus pour un pod. Lorsque le partage de l'espace de noms des processus est activé, les processus d'un conteneur sont visibles pour tous les autres conteneurs de ce pod.
Vous pouvez utiliser cette fonctionnalité pour configurer les conteneurs coopérants, comme un conteneur de sidecar de gestionnaire de journaux, ou pour dépanner les images de conteneurs qui n'incluent pas d'utilitaires de débogage comme un shell.
Pré-requis
Vous devez disposer d'un cluster Kubernetes et l'outil de ligne de commande kubectl doit être configuré pour communiquer avec votre cluster. Si vous ne possédez pas déjà de cluster, vous pouvez en créer un en utilisant Minikube, ou vous pouvez utiliser l'un de ces environnements Kubernetes:
Votre serveur Kubernetes doit être au moins à la version v1.10. Pour consulter la version, entrezkubectl version
.
Configurer un Pod
Le partage de l'espace de nommage du processus est activé en utilisant le champ shareProcessNamespace
de v1.PodSpec
. Par exemple:
-
Créez le pod
nginx
sur votre cluster :kubectl apply -f https://k8s.io/examples/pods/share-process-namespace.yaml
-
Attachez-le au conteneur
shell
et lancezps
:kubectl attach -it nginx -c shell
Si vous ne verrez pas d'invite de commande, appuyez sur la touche Entrée.
/ # ps ax PID USER TIME COMMAND 1 root 0:00 /pause 8 root 0:00 nginx: master process nginx -g daemon off; 14 101 0:00 nginx: worker process 15 root 0:00 sh 21 root 0:00 ps ax
Vous pouvez signaler les processus dans d'autres conteneurs. Par exemple, envoyez SIGHUP
à
nginx pour relancer le processus de worker. Cela nécessite la fonctionnalité SYS_PTRACE
.
/ # kill -HUP 8
/ # ps ax
PID USER TIME COMMAND
1 root 0:00 /pause
8 root 0:00 nginx: master process nginx -g daemon off;
15 root 0:00 sh
22 101 0:00 nginx: worker process
23 root 0:00 ps ax
Il est même possible d'accéder aux autres conteneurs en utilisant le lien /proc/$pid/root
.
/ # head /proc/8/root/etc/nginx/nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
Comprendre le processus de partage de l'espace de nommage
Les pods partagent de nombreuses ressources, il est donc logique qu'elles partagent également un espace de noms des processus. Pour certaines images de conteneur, on peut envisager de les isoler les uns des autres. Il est donc important de comprendre ces différences :
-
Le processus de conteneur n'a plus de PID 1. Certaines images de conteneurs refusent de démarrer sans PID 1 (par exemple, les conteneurs utilisant
systemd
) ou exécuter des commandes commekill -HUP 1
pour signaler le processus du conteneur. Dans les pods avec un espace de noms partagé du processus,kill -HUP 1
signalera la sandbox du pod. (/pause
dans l'exemple ci-dessus.) -
Les processus sont visibles par les autres conteneurs du pod. Cela inclut tout les informations visibles dans
/proc
, comme les mots de passe passés en argument ou les variables d'environnement. Celles-ci ne sont protégées que par des permissions Unix régulières. -
Les systèmes de fichiers des conteneurs sont visibles par les autres conteneurs du pod à travers le lien
/proc/$pid/root
. Cela rend le débogage plus facile, mais cela signifie aussi que les secrets du système de fichiers ne sont protégés que par les permissions du système de fichiers.
13 - Convertir un fichier Docker Compose en ressources Kubernetes
C'est quoi Kompose ? C'est un outil de conversion de tout ce qui compose (notamment Docker Compose) en orchestrateurs de conteneurs (Kubernetes ou OpenShift). Vous trouverez plus d'informations sur le site web de Kompose à http://kompose.io.
Pré-requis
Vous devez disposer d'un cluster Kubernetes et l'outil de ligne de commande kubectl doit être configuré pour communiquer avec votre cluster. Si vous ne possédez pas déjà de cluster, vous pouvez en créer un en utilisant Minikube, ou vous pouvez utiliser l'un de ces environnements Kubernetes:
Pour consulter la version, entrezkubectl version
.
Installer Kompose
Nous disposons de plusieurs façons d'installer Kompose. Notre méthode préférée est de télécharger le binaire de la dernière version de GitHub.
Kompose est publié via GitHub sur un cycle de trois semaines, vous pouvez voir toutes les versions actuelles sur la page des releases de Github.
# Linux
curl -L https://github.com/kubernetes/kompose/releases/download/v1.16.0/kompose-linux-amd64 -o kompose
# macOS
curl -L https://github.com/kubernetes/kompose/releases/download/v1.16.0/kompose-darwin-amd64 -o kompose
# Windows
curl -L https://github.com/kubernetes/kompose/releases/download/v1.16.0/kompose-windows-amd64.exe -o kompose.exe
chmod +x kompose
sudo mv ./kompose /usr/local/bin/kompose
Alternativement, vous pouvez télécharger le tarball.
L'installation en utilisant go get
extrait de la branche master avec les derniers changements de développement.
go get -u github.com/kubernetes/kompose
Kompose est dans le dépôt CentOS EPEL.
Si vous n'avez pas le dépôt EPEL déjà installé et activé, vous pouvez le faire en lançant sudo yum install epel-release
Si vous avez EPEL activé dans votre système, vous pouvez installer Kompose comme n'importe quel autre logiciel.
sudo yum -y install kompose
Kompose est dans les dépôts Fedora 24, 25 et 26. Vous pouvez l'installer comme n'importe quel autre paquetage.
sudo dnf -y install kompose
Sur macOS, vous pouvez installer la dernière version via Homebrew:
brew install kompose
Utiliser Kompose
En quelques étapes, nous vous emmenons de Docker Compose à Kubernetes. Tous dont vous avez besoin est un fichier docker-compose.yml
.
-
Allez dans le répertoire contenant votre fichier
docker-compose.yml
. Si vous n'en avez pas, faites un test en utilisant celui-ci.version: "2" services: redis-master: image: k8s.gcr.io/redis:e2e ports: - "6379" redis-slave: image: gcr.io/google_samples/gb-redisslave:v3 ports: - "6379" environment: - GET_HOSTS_FROM=dns frontend: image: gcr.io/google-samples/gb-frontend:v4 ports: - "80:80" environment: - GET_HOSTS_FROM=dns labels: kompose.service.type: LoadBalancer
-
Pour convertir le fichier
docker-compose.yml
en fichiers que vous pouvez utiliser aveckubectl
, lancezkompose convert
et ensuitekubectl apply -f <output file>
.$ kompose convert INFO Kubernetes file "frontend-service.yaml" created INFO Kubernetes file "redis-master-service.yaml" created INFO Kubernetes file "redis-slave-service.yaml" created INFO Kubernetes file "frontend-deployment.yaml" created INFO Kubernetes file "redis-master-deployment.yaml" created INFO Kubernetes file "redis-slave-deployment.yaml" created
$ kubectl apply -f frontend-service.yaml,redis-master-service.yaml,redis-slave-service.yaml,frontend-deployment.yaml,redis-master-deployment.yaml,redis-slave-deployment.yaml service/frontend created service/redis-master created service/redis-slave created deployment.apps/frontend created deployment.apps/redis-master created deployment.apps/redis-slave created
Vos déploiements fonctionnent sur Kubernetes.
-
Accédez à votre application.
Si vous utilisez déjà
minikube
pour votre processus de développement :$ minikube service frontend
Sinon, regardons quelle IP votre service utilise !
$ kubectl describe svc frontend Name: frontend Namespace: default Labels: service=frontend Selector: service=frontend Type: LoadBalancer IP: 10.0.0.183 LoadBalancer Ingress: 192.0.2.89 Port: 80 80/TCP NodePort: 80 31144/TCP Endpoints: 172.17.0.4:80 Session Affinity: None No events.
Si vous utilisez un fournisseur de cloud computing, votre IP sera listée à côté de
LoadBalancer Ingress
.$ curl http://192.0.2.89
Guide de l'utilisateur
- CLI
- Documentation
Kompose supporte deux fournisseurs : OpenShift et Kubernetes.
Vous pouvez choisir un fournisseur ciblé en utilisant l'option globale --provider
. Si aucun fournisseur n'est spécifié, Kubernetes est défini par défaut.
kompose convert
Kompose prend en charge la conversion des fichiers Docker Compose V1, V2 et V3 en objets Kubernetes et OpenShift.
Kubernetes
$ kompose --file docker-voting.yml convert
WARN Unsupported key networks - ignoring
WARN Unsupported key build - ignoring
INFO Kubernetes file "worker-svc.yaml" created
INFO Kubernetes file "db-svc.yaml" created
INFO Kubernetes file "redis-svc.yaml" created
INFO Kubernetes file "result-svc.yaml" created
INFO Kubernetes file "vote-svc.yaml" created
INFO Kubernetes file "redis-deployment.yaml" created
INFO Kubernetes file "result-deployment.yaml" created
INFO Kubernetes file "vote-deployment.yaml" created
INFO Kubernetes file "worker-deployment.yaml" created
INFO Kubernetes file "db-deployment.yaml" created
$ ls
db-deployment.yaml docker-compose.yml docker-gitlab.yml redis-deployment.yaml result-deployment.yaml vote-deployment.yaml worker-deployment.yaml
db-svc.yaml docker-voting.yml redis-svc.yaml result-svc.yaml vote-svc.yaml worker-svc.yaml
Vous pouvez également fournir plusieurs fichiers de composition du Docker en même temps :
$ kompose -f docker-compose.yml -f docker-guestbook.yml convert
INFO Kubernetes file "frontend-service.yaml" created
INFO Kubernetes file "mlbparks-service.yaml" created
INFO Kubernetes file "mongodb-service.yaml" created
INFO Kubernetes file "redis-master-service.yaml" created
INFO Kubernetes file "redis-slave-service.yaml" created
INFO Kubernetes file "frontend-deployment.yaml" created
INFO Kubernetes file "mlbparks-deployment.yaml" created
INFO Kubernetes file "mongodb-deployment.yaml" created
INFO Kubernetes file "mongodb-claim0-persistentvolumeclaim.yaml" created
INFO Kubernetes file "redis-master-deployment.yaml" created
INFO Kubernetes file "redis-slave-deployment.yaml" created
$ ls
mlbparks-deployment.yaml mongodb-service.yaml redis-slave-service.jsonmlbparks-service.yaml
frontend-deployment.yaml mongodb-claim0-persistentvolumeclaim.yaml redis-master-service.yaml
frontend-service.yaml mongodb-deployment.yaml redis-slave-deployment.yaml
redis-master-deployment.yaml
Lorsque plusieurs fichiers de docker-compose sont fournis, la configuration est fusionnée. Toute configuration qui est commune sera surchargée par le fichier suivant.
OpenShift
$ kompose --provider openshift --file docker-voting.yml convert
WARN [worker] Service cannot be created because of missing port.
INFO OpenShift file "vote-service.yaml" created
INFO OpenShift file "db-service.yaml" created
INFO OpenShift file "redis-service.yaml" created
INFO OpenShift file "result-service.yaml" created
INFO OpenShift file "vote-deploymentconfig.yaml" created
INFO OpenShift file "vote-imagestream.yaml" created
INFO OpenShift file "worker-deploymentconfig.yaml" created
INFO OpenShift file "worker-imagestream.yaml" created
INFO OpenShift file "db-deploymentconfig.yaml" created
INFO OpenShift file "db-imagestream.yaml" created
INFO OpenShift file "redis-deploymentconfig.yaml" created
INFO OpenShift file "redis-imagestream.yaml" created
INFO OpenShift file "result-deploymentconfig.yaml" created
INFO OpenShift file "result-imagestream.yaml" created
Il supporte également la création de buildconfig pour la directive de build dans un service. Par défaut, il utilise le répertoire distant de la branche git courante comme répertoire source, et la branche courante comme branche source pour le build. Vous pouvez spécifier un repo source et une branche différents en utilisant respectivement les options --build-repo
et --build-branch
.
$ kompose --provider openshift --file buildconfig/docker-compose.yml convert
WARN [foo] Service cannot be created because of missing port.
INFO OpenShift Buildconfig using git@github.com:rtnpro/kompose.git::master as source.
INFO OpenShift file "foo-deploymentconfig.yaml" created
INFO OpenShift file "foo-imagestream.yaml" created
INFO OpenShift file "foo-buildconfig.yaml" created
oc create -f
, vous devez vous assurer que vous poussez l'artefact imagestream avant l'artefact buildconfig, pour contourner ce problème OpenShift : https://github.com/openshift/origin/issues/4518 .
Autres conversions
La transformation par défaut komposer
va générer des Déploiements et Services de Kubernetes, au format yaml. Vous avez une autre option pour générer json avec -j
. Vous pouvez aussi générer des objets de Replication Controllers, Daemon Sets, ou Helm charts.
$ kompose convert -j
INFO Kubernetes file "redis-svc.json" created
INFO Kubernetes file "web-svc.json" created
INFO Kubernetes file "redis-deployment.json" created
INFO Kubernetes file "web-deployment.json" created
Les fichiers *-deployment.json
contiennent les objets Déploiements.
$ kompose convert --replication-controller
INFO Kubernetes file "redis-svc.yaml" created
INFO Kubernetes file "web-svc.yaml" created
INFO Kubernetes file "redis-replicationcontroller.yaml" created
INFO Kubernetes file "web-replicationcontroller.yaml" created
Les fichiers *-replicationcontroller.yaml
contiennent les objets du Contrôleur de Réplication. Si vous voulez spécifier des répliques (la valeur par défaut est 1), utilisez l'option --replicas
: $ kompose convert --replication-controller --replicas 3
$ kompose convert --daemon-set
INFO Kubernetes file "redis-svc.yaml" created
INFO Kubernetes file "web-svc.yaml" created
INFO Kubernetes file "redis-daemonset.yaml" created
INFO Kubernetes file "web-daemonset.yaml" created
Les fichiers *-daemonset.yaml
contiennent les objets du Daemon Set
Si vous voulez générer un Chart à utiliser avec Helm, faites-le simplement :
$ kompose convert -c
INFO Kubernetes file "web-svc.yaml" created
INFO Kubernetes file "redis-svc.yaml" created
INFO Kubernetes file "web-deployment.yaml" created
INFO Kubernetes file "redis-deployment.yaml" created
chart created in "./docker-compose/"
$ tree docker-compose/
docker-compose
├── Chart.yaml
├── README.md
└── templates
├── redis-deployment.yaml
├── redis-svc.yaml
├── web-deployment.yaml
└── web-svc.yaml
La structure du Chart est destinée à fournir un modèle pour la construction de vos chartes de Helm.
Étiquettes
kompose
supporte les étiquettes spécifiques à Kompose dans le fichier docker-compose.yml
afin de définir explicitement le comportement d'un service lors de la conversion.
- Le fichier
kompose.service.type
définit le type de service à créer.
Par exemple :
version: "2"
services:
nginx:
image: nginx
dockerfile: foobar
build: ./foobar
cap_add:
- ALL
container_name: foobar
labels:
kompose.service.type: nodeport
kompose.service.expose
définit si le service doit être accessible depuis l'extérieur du cluster ou non. Si la valeur est fixée à "true", le fournisseur définit automatiquement l'extrémité, et pour toute autre valeur, la valeur est définie comme le nom d'hôte. Si plusieurs ports sont définis dans un service, le premier est choisi pour être l'exposé.- Pour le fournisseur Kubernetes, une ressource ingress est créée et il est supposé qu'un contrôleur ingress a déjà été configuré.
- Pour le fournisseur OpenShift, une route est créée.
Par exemple :
version: "2"
services:
web:
image: tuna/docker-counter23
ports:
- "5000:5000"
links:
- redis
labels:
kompose.service.expose: "counter.example.com"
redis:
image: redis:3.0
ports:
- "6379"
Les options actuellement supportées sont :
Key | Value |
---|---|
kompose.service.type | nodeport / clusterip / loadbalancer |
kompose.service.expose | true / hostname |
kompose.service.type
doit être défini avec ports
uniquement, sinon kompose
échouera.
Redémarrer
Si vous voulez créer des pods normaux sans contrôleurs, vous pouvez utiliser la construction
restart
de docker-compose pour définir cela. Suivez le tableau ci-dessous pour voir ce qui se passe avec la valeur de restart
.
docker-compose restart |
object created | Pod restartPolicy |
---|---|---|
"" |
controller object | Always |
always |
controller object | Always |
on-failure |
Pod | OnFailure |
no |
Pod | Never |
déploiement
ou replicationcontroller
, etc.
Par exemple, le service pival
deviendra un Pod. Ce conteneur a calculé la valeur de pi
.
version: '2'
services:
pival:
image: perl
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restart: "on-failure"
Avertissement concernant les configurations de déploiement
Si le fichier Docker Compose a un volume spécifié pour un service, la stratégie Deployment (Kubernetes) ou DeploymentConfig (OpenShift) est changée en "Recreate" au lieu de "RollingUpdate" (par défaut). Ceci est fait pour éviter que plusieurs instances d'un service n'accèdent à un volume en même temps.
Si le fichier Docker Compose a un nom de service avec _
dedans (par exemple web_service
), alors il sera remplacé par -
et le nom du service sera renommé en conséquence (par exemple web-service
). Kompose fait cela parce que "Kubernetes" n'autorise pas _
dans le nom de l'objet.
Veuillez noter que changer le nom du service peut casser certains fichiers docker-compose
.
Versions du Docker Compose
Kompose supporte les versions Docker Compose : 1, 2 et 3. Nous avons un support limité sur les versions 2.1 et 3.2 en raison de leur nature expérimentale.
Une liste complète sur la compatibilité entre les trois versions est donnée dans notre document de conversion incluant une liste de toutes les clés Docker Compose incompatibles.