Académique Documents
Professionnel Documents
Culture Documents
of Kubernetes : Up an d Running
ISBN : 978-2-49-193567-5
© 2017, Kelsey Hightower, Brendan Burns and Joe Beda
This translation is published and sold by permission of O’Reilly
Media Inc.,
which owns or controls all rights to publish and sell the same.
© Dunod, 2019
11 rue Paul Bert, 92240 Malakoff
www.dunod.com
ISBN : 978-2-10-079254-2
Couverture
Page de titre
Page de Copyright
Avant-propos
1 Introduction
1.1 Vitesse
1.4 Efficacité
2.5 Nettoyage
4.2 Contextes
5 Pods
6 Étiquettes et annotations
6.1 Étiquettes
6.2 Annotations
6.3 Nettoyage
7.6 Nettoyage
8 ReplicaSets
9 DaemonSets
10 Jobs
11 ConfigMaps et secrets
11.1 ConfigMaps
11.2 Secrets
12 Déploiements
14.1 Parse
14.2 Ghost
14.3 Redis
Liste de courses
Index
Avant-propos
◆ En forme de dédicace
Que vous soyez néophyte dans les systèmes distribués ou que vous
déployiez des systèmes cloud-native depuis des années, les
conteneurs et Kubernetes peuvent vous aider à réaliser des progrès
en matière de vitesse, d’agilité, de fiabilité et d’efficacité. Cet
ouvrage décrit l’orchestrateur de clusters Kubernetes et la façon
dont ses outils et son API peuvent être utilisés pour améliorer le
développement, la livraison et la maintenance des applications
distribuées. Bien qu’aucune expérience antérieure avec Kubernetes
ne soit requise, il est préférable d’être à l’aise avec la création et le
déploiement des applications basées sur un serveur si vous voulez
tirer le meilleur parti de ce livre. La familiarité avec des concepts
comme l’équilibrage de charge et le stockage réseau sera utile, mais
pas nécessaire. De la même manière, une expérience de Linux, des
conteneurs Linux, et de Docker, n’est pas essentielle, mais elle vous
aidera à profiter au maximum des ressources de cet ouvrage.
Nous avons été impliqués dans Kubernetes depuis son tout début.
Ce fut vraiment extraordinaire d’assister à la transformation de cette
technologie qui est passée d’une curiosité utilisée pour des
expériences à une infrastructure cruciale de production qui alimente
les applications à grande échelle dans des domaines variés qui vont
de l’apprentissage automatique (machine learning) aux services en
ligne. Quand cette transition s’est produite, il est devenu de plus en
plus clair qu’un livre qui décrirait à la fois la façon d’utiliser les
concepts de base de Kubernetes et les motivations sous-jacentes à
l’élaboration de ces concepts serait une contribution importante pour
le développement d’applications cloud-native. Nous espérons qu’à la
lecture de ce livre, non seulement vous allez apprendre à créer des
applications fiables et évolutives en vous appuyant sur Kubernetes,
mais que vous allez aussi comprendre les défis majeurs des
systèmes distribués qui ont conduit au développement de
Kubernetes.
◆ Organisation de ce livre
◆ Ressources en ligne
Introduction
_ 1.1 VITESSE
La rapidité est le facteur clé aujourd’hui dans presque tous les
développements informatiques. La nature du logiciel a changé et on
est passé d’un programme vendu dans une boîte contenant un CD à
des services basés sur le Web qui sont modifiés toutes les heures,
ce qui signifie que ce qui fait la différence avec vos concurrents,
c’est souvent la vitesse avec laquelle vous savez développer et
déployer de nouveaux composants et de nouvelles fonctionnalités.
Il est cependant important de noter que cette rapidité n’est pas
simplement définie en termes de vitesse brute. Même si vos
utilisateurs sont toujours à la recherche d’améliorations itératives, ils
resteront plus intéressés par un service extrêmement fiable. Par le
passé, on tolérait qu’un service soit en maintenance à minuit tous les
soirs, mais aujourd’hui, nos utilisateurs s’attendent à bénéficier d’une
disponibilité constante, même si le logiciel qu’ils exécutent est mis à
jour en permanence.
Par conséquent, la vitesse n’est pas mesurée en fonction du nombre
de mises à jour que vous pouvez livrer en une heure ou en un jour,
mais plutôt en fonction du nombre de choses que vous pouvez livrer
tout en maintenant un service hautement disponible.
C’est dans ce but que les conteneurs et Kubernetes peuvent fournir
les outils dont vous avez besoin pour réagir rapidement, tout en
restant disponibles. Les concepts de base qui permettent cela sont
l’immutabilité, la configuration déclarative, et les systèmes d’auto-
guérison en ligne. Ces idées sont toutes interdépendantes afin
d’améliorer radicalement la rapidité avec laquelle vous pouvez
déployer de manière fiable des logiciels.
1.2.1 Découplage
_ 1.5 RÉSUMÉ
Kubernetes a été construit pour changer radicalement la façon dont
les applications sont créées et déployées dans le cloud.
Fondamentalement, il a été conçu pour donner aux développeurs
plus de rapidité, d’efficacité et d’agilité. Nous espérons que les
sections précédentes vous auront incité à déployer vos applications
à l’aide de Kubernetes. Maintenant que vous êtes convaincu, les
chapitres suivants vont vous apprendre la manière de déployer votre
application.
2
Création et exécution
de conteneurs
Ce code peut être stocké dans un fichier texte, que l’on nomme en
général Dockerfile et qui est utilisé pour créer une image Docker.
Pour commencer, vous devez compiler les fichiers binaires de kuard.
Pour cela, vous pouvez exécuter make dans le répertoire kuard.
Exécutez la commande suivante pour créer l’image Docker kuard :
$ docker build -t kuard-amd64:1 .
Nous avons choisi de créer l’image en nous basant sur Alpine, qui
est une distribution Linux minimaliste. Par conséquent, l’image finale
devrait peser environ 6 Mo, ce qui est une taille beaucoup plus
restreinte que la plupart des images disponibles qui ont tendance à
être construites à partir de versions plus complètes de systèmes
d’exploitation comme Debian.
À ce stade, notre image kuard réside dans le registre local Docker
où l’image a été construite et où elle n’est accessible qu’à une seule
machine. La véritable puissance de Docker provient de sa capacité à
partager des images à travers des milliers de machines et la vaste
communauté Docker.
Vous pensez sans doute que GrosFichier n’est plus présent dans
cette image. Après tout, lorsque vous exécutez l’image, il n’est plus
accessible. Mais en fait il est toujours présent dans la couche A, ce
qui signifie que chaque fois que vous voulez envoyer ou extraire
l’image, GrosFichier est toujours transmis par le réseau, même si
vous ne pouvez plus y accéder.
Il y a un autre écueil qui concerne la mise en cache et la
construction des images. Vous devez vous rappeler que chaque
couche est différente et indépendante de la couche qui est en
dessous. Chaque fois que vous modifiez une couche, cela change
les couches qui viennent après. Si vous modifiez les couches
précédentes, cela signifie qu’il faut les reconstruire, les renvoyer et
les extraire pour déployer votre image vers l’environnement de
développement.
Pour mieux comprendre cela, comparons ces deux images :
.
└── couche A : contient un système d’exploitation de base
└── couche B : ajoute le code source server.js
└── couche C : installe le package 'node'
et :
.
└── couche A : contient un système d’exploitation de base
└── couche B : installe le package 'node'
└── couche C : ajoute le code source server.js
L’outil CLI Docker peut être utilisé pour déployer des conteneurs.
Pour déployer un conteneur à partir de l’image gcr.io/kuar-
demo/kuard-amd64:1, exécutez la commande suivante :
$ docker run -d --name kuard \
--publish 8080:8080 \
gcr.io/kuar-demo/kuard-amd64:1
kuard possède une interface Web simple, que vous pouvez charger
en pointant votre navigateur à http://localhost:8080 ou via la ligne de
commande :
$ curl http://localhost:8080
Le CPU est aussi une ressource critique sur une machine. Vous
pouvez restreindre l’utilisation du CPU à l’aide de l’option --cpu-
shares avec la commande docker run :
$ docker run -d --name kuard \
--publish 8080:8080 \
--memory 200m \
--memory-swap 1G \
--cpu-shares 1024 \
gcr.io/kuar-demo/kuard-amd64:1
_ 2.5 NETTOYAGE
Une fois que vous en avez terminé avec une image, vous pouvez la
supprimer avec la commande docker rmi :
docker rmi <nom de balise>
ou
docker rmi <identificateur d’image>
_ 2.6 RÉSUMÉ
Les conteneurs d’applications fournissent une bonne abstraction
pour les applications et, lorsqu’ils sont packagés dans des images
au format Docker, les applications deviennent faciles à créer, à
déployer et à distribuer. Les conteneurs offrent aussi une isolation
entre les applications fonctionnant sur le même ordinateur, ce qui
permet d’éviter les conflits de dépendance.
Dans les chapitres suivants, nous allons voir comment la possibilité
de monter des répertoires externes permet non seulement
d’exécuter des applications stateless dans un conteneur, mais aussi
des applications comme mysql ou bien d’autres applications qui
génèrent beaucoup de données.
3
Cela prendra quelques minutes. Une fois le cluster créé, vous pouvez
obtenir des informations d’identification sur le cluster avec :
$ az acs kubernetes get-credentials --resource-group=kuar --name=kuar-cluster
Si vous n’avez pas encore installé l’outil kubectl, vous pouvez le faire
en utilisant :
$ az acs kubernetes install-cli
scheduler Healthy ok
controller-manager Healthy ok
Vous pouvez voir qu’il s’agit d’un cluster à quatre nœuds qui est actif
depuis 45 jours. Dans Kubernetes, les nœuds sont séparés en nœuds
master (conteneurs comme le serveur API, l’ordonnanceur, etc.) qui
gèrent le cluster, et nœuds worker où vos conteneurs seront exécutés.
Kubernetes n’ordonnance généralement pas le travail sur les nœuds
master afin de s’assurer que les charges de travail des utilisateurs ne
nuisent pas au fonctionnement global du cluster.
Vous pouvez utiliser la commande kubectl describe pour obtenir plus
d’informations sur un nœud spécifique tel que node-1 :
$ kubectl describe nodes node-1
Vous voyez d’abord des informations de base sur le nœud :
Name: node-1
Role:
Labels: beta.kubernetes.io/arch=arm
beta.kubernetes.io/os=linux
kubernetes.io/hostname=node-1
Sun, 05 Feb
OutOfDisk False KubeletHasSufficientDisk kubelet…
2017…
Sun, 05 Feb
MemoryPressure False KubeletHasSufficientMemory kubelet…
2017…
Sun, 05 Feb
DiskPressure False KubeletHasNoDiskPressure kubelet…
2017…
Sun, 05 Feb
Ready True KubeletReady kubelet…
2017…
alpha.kubernetes.io/nvidia-gpu: 0
cpu: 4
memory: 882636Ki
pods: 110
Allocatable:
alpha.kubernetes.io/nvidia-gpu: 0
cpu: 4
memory: 882636Ki
pods: 110
Architecture: arm
PodCIDR: 10.244.2.0/24
ExternalID: node-1
kube- 220Mi
kube-system 260m (6%) 0 (0%) 140Mi (16%)
dns… (25%)
kube-
kube-system 0 (0%) 0 (0%) 0 (0%) 0 (0%)
fla…
kube-
kube-system 0 (0%) 0 (0%) 0 (0%) 0 (0%)
pro…
Allocated resources:
(Total limits may be over 100 percent, i.e., overcommitted.
No events.
À partir de cette sortie, vous pouvez voir les pods sur le nœud (par
exemple, le pod kube-dns qui fournit des services DNS du cluster), le
CPU et la mémoire que chaque pod demande à partir du nœud, ainsi
que les ressources totales demandées. Il est intéressant de noter ici
que Kubernetes garde à la fois la trace de la demande et de la limite
supérieure des ressources pour chaque pod qui s’exécute sur une
machine. La différence entre les demandes et les limites est décrite
en détail au chapitre 5, mais en un mot, les ressources demandées
par un pod sont garanties sur le nœud, tandis que la limite d’un pod
est le montant maximal d’une ressource donnée qu’un pod peut
consommer. La limite d’un pod peut être supérieure à sa demande, et
dans ce cas, les ressources supplémentaires sont fournies sur le
principe d’une obligation de moyens si bien qu’il n’y a aucune garantie
qu’elles soient présentes sur le nœud.
kube-dns 1 1 1 1 45d
kubernetes-
1 1 1 1 45d
dashboard
Le tableau de bord dispose également d’un service qui effectue
l’équilibrage de charge du tableau de bord :
$ kubectl get services --namespace=kube-system kubernetes-dashboard
_ 3.6 RÉSUMÉ
Nous espérons à ce stade que vous disposez d’un (voire de trois)
cluster Kubernetes en état de fonctionner et que vous avez utilisé
quelques commandes pour explorer le cluster que vous avez créé.
Par la suite, nous allons passer un peu plus de temps à explorer
l’interface en ligne de commande de ce cluster Kubernetes et vous
apprendrez à maîtriser l’outil kubectl. Dans le reste du livre, vous
utiliserez kubectl et votre cluster de test pour explorer les différents
objets de l’API Kubernetes.
4
Commandes kubectl
courantes
_ 4.2 CONTEXTES
Si vous souhaitez modifier l’espace de noms par défaut de façon
permanente, vous pouvez utiliser un contexte. Celui-ci est enregistré
dans un fichier de configuration kubectl, qui est généralement situé
dans $HOME/.kube/config. Ce fichier de configuration stocke
également la façon de rechercher votre cluster et de s’y authentifier.
Par exemple, vous pouvez créer un contexte avec un autre espace
de noms par défaut avec la commande kubectl suivante :
$ kubectl config set-context mon-contexte --namespace=monespace
_ 4.7 RÉSUMÉ
kubectl est un outil puissant pour gérer vos applications dans votre
cluster Kubernetes. Ce chapitre a illustré de nombreuses utilisations
courantes de l’outil, mais kubectl dispose d’une très bonne aide en
ligne que vous pouvez afficher avec la commande :
kubectl help
ou :
kubectl help nom-de-commande
5
Pods
Vous pouvez voir le nom du pod (kuard) que nous avons donné dans
le fichier de manifeste au format YAML. En plus du nombre de
conteneurs prêts (1/1), la sortie indique également l’état, le nombre
de fois où le pod a été redémarré, ainsi que sa durée d’activité.
Si vous avez exécuté cette commande immédiatement après la
création du pod, vous pouvez voir :
L’état Pending (attente) indique que le pod a été soumis, mais qu’il
n’a pas encore été ordonnancé.
Si une erreur plus importante se produit (par exemple, une tentative
de création d’un pod avec une image conteneur qui n’existe pas),
elle sera également répertoriée dans le champ Status.
Parfois, la vue sur une seule ligne est insuffisante parce qu’elle est
trop succincte. En outre, Kubernetes assure la maintenance de
nombreux événements sur les pods qui sont présents dans le flux
d’événements, mais qui ne sont pas attachés à l’objet Pod.
Pour obtenir plus d’informations sur un pod (ou un objet
Kubernetes), vous pouvez utiliser la commande kubectl describe.
Par exemple, pour décrire le pod que nous avons créé
précédemment, vous pouvez exécuter :
$ kubectl describe pods kuard
Name: kuard
Namespace: default
Node: node1/10.0.15.185
Start Time: Sun, 02 Jul 2017 15:00:38 -0700
Labels: <none>
Annotations: <none>
Status: Running
IP: 192.168.199.238
Controllers: <none>
Image: gcr.io/kuar-demo/kuard-amd64:1
Port: 8080/TCP
State: Running
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
default-
50s Normal Scheduled Success…
scheduler
Plus loin dans le livre, nous allons vous montrer comment exposer
un service au monde ou à d’autres conteneurs à l’aide d’équilibreurs
de charge, mais la plupart du temps vous souhaiterez simplement
accéder à un pod spécifique, même s’il ne gère aucun trafic sur
Internet.
Pour ce faire, vous pouvez utiliser la prise en charge de la
redirection de port intégrée à l’API Kubernetes et disponible avec les
outils en ligne de commande.
Lorsque vous exécutez :
$ kubectl port-forward kuard 8080:8080
un tunnel sécurisé est créé à partir de votre ordinateur local, via le
master Kubernetes, vers l’instance du pod s’exécutant sur l’un des
nœuds worker.
Tant que la commande de redirection de port est en cours
d’exécution, vous pouvez accéder au pod (en l’occurrence, avec
l’interface Web de kuard) sur http://localhost:8080.
◆ Communication/synchronisation
◆ Cache
Une application peut utiliser un volume qui est utile pour améliorer
les performances, mais qui n’est pas nécessaire au bon
fonctionnement de l’application. Par exemple, une application
conserve peut-être des vignettes d’images plus volumineuses. Bien
entendu, ces vignettes peuvent être reconstituées à partir des
images originales, mais leur affichage sera alors moins performant.
Si vous voulez qu’un tel cache ne soit pas supprimé après un
redémarrage du conteneur dû à un contrôle défaillant, emptyDir
fonctionne également bien dans ce cas de figure.
◆ Données persistantes
Souvent, vous voulez que les données qu’un pod utilise demeurent
dans ce pod, même s’il est redémarré sur une machine hôte
différente.
Pour ce faire, vous pouvez monter un volume de stockage réseau
distant dans votre pod. Lors de l’utilisation du stockage basé sur le
réseau, Kubernetes monte et démonte automatiquement le stockage
approprié chaque fois qu’un pod utilisant ce volume est ordonnancé
sur une machine particulière.
Il existe de nombreuses méthodes pour monter des volumes sur le
réseau. Kubernetes inclut la prise en charge des protocoles standard
tels que NFS et iSCSI, ainsi que les API de stockage basées sur les
principaux fournisseurs de cloud (publics et privés). Dans de
nombreux cas, les fournisseurs de cloud créent également le disque
pour vous s’il n’existe pas déjà.
Voici un exemple d’utilisation d’un serveur NFS :
...
# Rest of pod definition above here
volumes:
- name: "kuard-data"
nfs:
server: my.nfs.server.local
path: "/exports"
_ 5.9 SYNTHÈSE
De nombreuses applications sont stateful, et en tant que telles, nous
devons conserver toutes les données et garantir l’accès au volume
de stockage sous-jacent, quelle que soit la machine sur laquelle
l’application s’exécute. Comme nous l’avons vu précédemment, cela
peut être réalisé à l’aide d’un volume persistant sauvegardé par le
stockage connecté au réseau. Nous voulons également garantir
qu’une instance saine de l’application est en cours d’exécution en
permanence, ce qui signifie que nous voulons nous assurer que le
conteneur qui exécute kuard est prêt avant de l’exposer aux clients.
Grâce à une combinaison de volumes persistants, de sondes de
disponibilité et d’activité, et de restrictions de ressources,
Kubernetes fournit tout ce qu’il faut pour exécuter les applications
stateful de manière fiable. L’exemple 5-6 rassemble tout cela dans
un seul manifeste.
Exemple 5-6. kuard-pod-full.yaml
apiVersion: v1
kind: Pod
metadata:
name: kuard
spec:
volumes:
- name: "kuard-data"
nfs:
server: my.nfs.server.local
path: "/exports"
containers:
- image: gcr.io/kuar-demo/kuard-amd64:1
name: kuard
ports:
- containerPort: 8080
name: http
protocol: TCP
resources:
requests:
cpu: "500m"
memory: "128Mi"
limits:
cpu: "1000m"
memory: "256Mi"
volumeMounts:
- mountPath: "/data"
name: "kuard-data"
livenessProbe:
httpGet:
path: /healthy
port: 8080
initialDelaySeconds: 5
timeoutSeconds: 1
periodSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 30
timeoutSeconds: 1
periodSeconds: 10
failureThreshold: 3
_ 5.10 RÉSUMÉ
Les pods représentent l’unité atomique de travail dans un cluster
Kubernetes. Les pods sont composés d’un ou de plusieurs
conteneurs travaillant en symbiose. Pour créer un pod, on écrit un
manifeste de pod et on le soumet au serveur API Kubernetes à l’aide
de l’outil en ligne de commande ou (moins fréquemment) en
effectuant des appels HTTP et JSON directement sur le serveur.
Une fois que vous avez soumis le manifeste au serveur API,
l’ordonnanceur Kubernetes trouve une machine où le pod peut être
hébergé et il le planifie sur cette machine. Une fois ordonnancé, le
démon kubelet de cette machine est responsable de la création des
conteneurs qui correspondent au pod, ainsi que de l’exécution de
tous les contrôles d’intégrité définis dans le manifeste.
Une fois qu’un pod est ordonnancé pour un nœud, aucune
replanification n’a lieu en cas de défaillance de ce nœud. De plus,
pour créer plusieurs réplicas du même pod, vous devez les créer et
les nommer manuellement. Dans un prochain chapitre, nous
étudierons l’objet ReplicaSet et nous montrerons comment
automatiser la création de plusieurs pods identiques et garantir qu’ils
sont recréés en cas de défaillance de la machine du nœud.
6
Étiquettes et annotations
_ 6.1 ÉTIQUETTES
Les étiquettes fournissent des métadonnées d’identification pour les
objets. Elles représentent les qualités fondamentales de l’objet qui
seront utilisées pour leur regroupement, leur affichage et leur
exploitation.
Clé Valeur
acme.com/app-version 1.0.0
appVersion 1.0.0
app.version 1.0.0
kubernetes.io/cluster-
true
service
Dans cet exemple, nous allons créer quelques déploiements (ce qui
illustrera la manière de créer une matrice de pods) avec quelques
étiquettes intéressantes. Nous allons prendre deux applications
(appelées alpaca et bandicoot) qui auront chacune leur
environnement. Nous aurons aussi deux versions différentes.
1. Tout d’abord, on crée le déploiement alpaca-prod et on définit les
étiquettes ver, app et env :
$ kubectl run alpaca-prod \
--image=gcr.io/kuar-demo/kuard-amd64:1 \
--replicas=2 \
--labels="ver=1,app=alpaca,env=prod"
Vous pouvez aussi utiliser l’option -L de kubectl get pour afficher une
valeur d’étiquette sous la forme d’une colonne :
$ kubectl get deployments -L canary
alpaca-prod 2 2 <none>
alpaca-test 1 1 true
bandicoot-prod 2 2 <none>
bandicoot-staging 1 1 <none>
Si nous voulons seulement lister les pods qui ont l’étiquette ver
définie à 2, nous pouvons utiliser le paramètre --selector :
$ kubectl get pods --selector="ver=2"
Si nous spécifions deux sélecteurs séparés par une virgule, seuls les
objets qui satisfont les deux conditions seront retournés. Il s’agit
d’une opération avec un ET logique :
$ kubectl get pods --selector="app=bandicoot,ver=2"
Enfin, nous pouvons demander si une étiquette est définie. Ici, nous
demandons tous les déploiements ayant l’étiquette canary définie
avec n’importe quelle valeur :
$ kubectl get deployments --selector="canary"
alpaca-test 1 1 1 1 7m
Opérateur Description
Tous les termes sont évalués en tant que ET logique. La seule façon
de représenter l’opérateur != est de le convertir en une expression
NotIn avec une valeur unique.
L’ancienne forme de spécification des sélecteurs (utilisée dans les
ReplicationControllers et les services) ne prend en charge que
l’opérateur =. Il s’agit d’un ensemble simple de paires clé/valeur qui
doivent toutes correspondre à un objet cible à sélectionner.
Le sélecteur app=alpaca, ver=1 sera représenté de la manière
suivante :
selector:
app: alpaca
ver: 1
_ 6.2 ANNOTATIONS
Les annotations fournissent un emplacement pour stocker des
métadonnées supplémentaires pour les objets Kubernetes dans le
seul but de simplifier la tâche des outils et des bibliothèques. Elles
offrent la possibilité à d’autres programmes de piloter Kubernetes via
une API pour stocker des données opaques dans un objet. Les
annotations peuvent être utilisées pour l’outil lui-même ou pour
transmettre des informations de configuration entre des systèmes
externes.
Alors que les étiquettes sont utilisées pour identifier et regrouper des
objets, les annotations sont employées pour fournir des informations
supplémentaires sur l’emplacement d’un objet, son utilisation ou sa
stratégie. Ces deux fonctionnalités se recouvrent, et l’opportunité
d’utiliser une annotation ou une étiquette est une affaire de goût. En
cas de doute, ajoutez des informations à un objet sous la forme
d’une annotation et transformez-la en étiquette si vous voulez
l’utiliser dans un sélecteur.
Les annotations sont utilisées pour :
Garder une trace des motifs de la dernière mise à jour d’un objet.
Communiquer une politique d’ordonnancement spécialisée à un
planificateur spécialisé.
Compléter les données sur le dernier outil employé pour mettre à
jour la ressource et documenter la manière dont la ressource a
été mise à jour (utilisé pour détecter les modifications par d’autres
outils et effectuer une fusion intelligente).
Les informations concernant le build, la release ou l’image qui ne
peuvent pas être gérées avec des étiquettes (cela peut inclure un
hachage Git, un timestamp, un numéro de PR, etc.).
Activer l’objet Deployment (chapitre 12) pour garder une trace des
ReplicaSets qu’il gère pour les déploiements.
Fournir des données supplémentaires pour améliorer la qualité
visuelle ou la convivialité d’une interface utilisateur. Par exemple,
les objets peuvent inclure un lien vers une icône (ou une version
codée en base64 d’une icône).
Prototyper une fonctionnalité alpha dans Kubernetes (au lieu de
créer un champ API de première classe, les paramètres de cette
fonctionnalité sont encodés dans une annotation).
Les annotations sont utilisées en divers endroits dans Kubernetes,
mais principalement dans les déploiements. Pendant les
déploiements, les annotations sont utilisées pour suivre l’état du
déploiement et fournir les informations nécessaires à une
restauration dans un état antérieur.
Les utilisateurs doivent éviter d’utiliser le serveur API Kubernetes
comme une base de données à usage général. Les annotations sont
conçues pour les petites quantités de données qui sont associées à
une ressource spécifique. Si vous souhaitez stocker des données
dans Kubernetes mais que vous n’avez pas d’objet évident à y
associer, envisagez de stocker ces données dans une autre base de
données plus appropriée.
_ 6.3 NETTOYAGE
Il est facile de nettoyer tous les déploiements que nous avons
expérimentés dans ce chapitre :
$ kubectl delete deployments --all
_ 6.4 RÉSUMÉ
Les étiquettes sont utilisées pour identifier et éventuellement
regrouper des objets dans un cluster Kubernetes. Les étiquettes
sont aussi utilisées dans les requêtes de sélecteur pour fournir un
regroupement flexible d’objets en cours d’exécution tels que des
pods.
Les annotations offrent un stockage des métadonnées des objets
sous la forme clé/valeur qui peuvent être utilisées par des outils
d’automatisation et des bibliothèques clientes. Les annotations
peuvent aussi être utilisées pour stocker des données de
configuration pour des outils externes tels que des ordonnanceurs
tiers et des outils de surveillance.
Les étiquettes et les annotations sont essentielles pour comprendre
comment les composants clés d’un cluster Kubernetes fonctionnent
ensemble afin de garantir l’état du cluster désiré. L’utilisation
correcte des étiquettes et des annotations est la clé de la flexibilité
de Kubernetes et fournit le point de départ pour la construction
d’outils d’automatisation et de workflows de déploiement.
7
Après avoir exécuté ces commandes, nous avons trois services. Ceux que nous
venons de créer sont alpaca-prod et bandicoot-prod. Le service kubernetes est
créé automatiquement afin que vous puissiez trouver l’API Kubernetes et
communiquer avec elle à partir de l’application.
Si l’on regarde la colonne SELECTOR, on peut voir que le service alpaca-prod
donne simplement un nom à un sélecteur et spécifie les ports avec lesquels il faut
dialoguer pour ce service. La commande kubectl expose extrait facilement le
sélecteur d’étiquettes et les ports correspondants (8080, en l’occurrence) à partir
de la définition du déploiement.
En outre, un nouveau type d’adresse IP virtuelle, appelé IP de cluster, est assigné
à ce service. Il s’agit d’une adresse IP spéciale pour laquelle le système réalise un
équilibrage de charge à travers tous les pods identifiés par le sélecteur.
Pour interagir avec les services, nous allons faire une redirection de port sur l’un
des pods alpaca. Exécutez la commande suivante dans une fenêtre de terminal
(vous pourrez voir le fonctionnement de la redirection de port en accédant au pod
alpaca à http://localhost:48858) :
$ ALPACA_POD=$(kubectl get pods -l app=alpaca \
-o jsonpath='{.items[0].metadata.name}')
$ kubectl port-forward $ALPACA_POD 48858:8080
Comme l’IP de cluster est virtuelle, elle est stable et il convient de lui donner une
adresse DNS. Cela met fin à tous les problèmes des clients qui mettent en cache
les résultats DNS. Dans un espace de noms, c’est aussi facile que d’utiliser le nom
du service pour se connecter à l’un des pods identifiés par un service.
Kubernetes fournit un service DNS qui est exposé aux pods en cours d’exécution
dans le cluster. Ce service DNS Kubernetes a été installé en tant que composant
système lorsque le cluster a été créé pour la première fois. Le service DNS est lui-
même géré par Kubernetes, et cela représente un excellent exemple de
l’architecture Kubernetes bâtie sur Kubernetes. Le service DNS Kubernetes fournit
des noms DNS pour les adresses IP du cluster.
Vous pouvez le tester en développant la section « DNS Query » de la page d’état
du serveur kuard. Faites une requête sur l’enregistrement A du service alpaca-
prod. La sortie doit ressembler à quelque chose comme ce qui suit :
;; opcode: QUERY, status: NOERROR, id: 12071
;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;alpaca-prod.default.svc.cluster.local. IN A
;; ANSWER SECTION:
alpaca-prod.default.svc.cluster.local. 30 IN A 10.115.245.13
Souvent, quand une application démarre pour la première fois, elle n’est pas prête
à traiter les requêtes. Il y a généralement un certain temps d’initialisation qui peut
aller d’une durée inférieure à la seconde jusqu’à plusieurs minutes. L’objet Service
a la bonne idée de surveiller les pods qui sont prêts grâce à un contrôle de leur
disponibilité. Nous allons modifier notre déploiement pour ajouter une vérification
de la disponibilité :
$ kubectl edit deployment/alpaca-prod
Cela définit les pods que ce déploiement va créer et vérifie leur disponibilité via un
HTTP GET sur /ready via le port 8080. Cette vérification est effectuée toutes les
2 secondes dès la création du pod. Si trois contrôles successifs échouent, alors le
pod sera considéré comme n’étant pas prêt. Toutefois, si un seul contrôle réussit, le
pod sera de nouveau considéré comme étant prêt.
On n’envoie du trafic que sur les pods prêts.
La mise à jour de la définition de déploiement telle que nous venons de la voir va
supprimer et recréer les pods alpaca. En tant que tel, nous devons redémarrer la
commande de redirection de port décrite plus haut :
$ ALPACA_POD=$(kubectl get pods -l app=alpaca \
-o jsonpath='{.items[0].metadata.name}')
$ kubectl port-forward $ALPACA_POD 48858:8080
Changez le champ spec.type en NodePort. Vous pouvez aussi réaliser cela lors de
la création du service via kubectl expose en spécifiant --type=NodePort. Le
système attribuera un nouveau NodePort :
$ kubectl describe service alpaca-prod
Name: alpaca-prod
Namespace: default
Labels: app=alpaca
env=prod
ver=1
Annotations: <none>
Selector: app=alpaca,env=prod,ver=1
Type: NodePort
IP: 10.115.245.13
Port: <unset> 8080/TCP
NodePort: <unset> 32711/TCP
Endpoints: 10.112.1.66:8080,10.112.2.104:8080,10.112.2.105:8080
Session Affinity: None
No events.
Ici, nous voyons que le système a assigné le port 32711 à ce service. Maintenant,
nous pouvons atteindre n’importe quel nœud de notre cluster sur ce port afin
d’accéder au service. Si vous vous trouvez sur le même réseau, vous pouvez y
accéder directement. Si votre cluster est quelque part dans le cloud, vous pouvez
utiliser un tunnel SSH avec une commande du genre :
$ ssh <node> -L 8080:localhost:32711
Name: alpaca-prod
Namespace: default
Labels: app=alpaca
env=prod
ver=1
Selector: app=alpaca,env=prod,ver=1
Type: LoadBalancer
IP: 10.115.245.13
Endpoints: 10.112.1.66:8080,10.112.2.104:8080,10.112.2.105:8080
Events:
Ici, nous voyons que nous avons une adresse 104.196.248.204 qui est maintenant
assignée au service alpaca-prod. Ouvrez votre navigateur et essayez-la !
Cet exemple provient d’un cluster géré sur la plateforme Google Cloud via GKE.
Vous noterez cependant que la façon dont le LoadBalancer est configuré est
spécifique au service de cloud. En outre, certains services de cloud ont des
équilibreurs de charge basés sur le DNS (par exemple, AWS ELB). Dans ce cas,
vous verrez un nom d’hôte à la place d’une adresse IP. En fonction du fournisseur
de cloud, cela peut aussi prendre un peu de temps pour que l’équilibreur de charge
soit pleinement opérationnel.
_ 7.5 FONCTIONNALITÉS AVANCÉES
Kubernetes est conçu pour être un système extensible. En tant que tel, il existe des
couches qui permettent des intégrations plus avancées. Si vous comprenez les
détails de la façon dont un concept sophistiqué comme les services est mis en
œuvre, cela facilitera le dépannage ou vous aidera à créer des intégrations plus
poussées. Cette section va approfondir certains détails.
Name: alpaca-prod
Namespace: default
Labels: app=alpaca
env=prod
ver=1
Subsets:
Addresses: 10.112.1.54,10.112.2.84,10.112.2.85
NotReadyAddresses: <none>
Ports:
No events.
Pour utiliser un service, une application avancée peut communiquer directement
avec l’API Kubernetes afin de rechercher des points de terminaison et les appeler.
L’API Kubernetes a même la capacité de « surveiller » les objets et d’être avertie
dès qu’ils sont modifiés. De cette façon, un client peut réagir immédiatement dès
que les adresses IP associées à un service changent.
Nous allons vous montrer comment cela fonctionne. Dans une fenêtre de terminal,
exécutez la commande suivante et laissez-la tourner :
$ kubectl get endpoints alpaca-prod --watch
alpaca-prod 10.112.1.54:8080,10.112.2.84:8080,10.112.2.85:8080 1m
Si vous revenez sur le terminal affichant la sortie du point de terminaison qui est
surveillé, vous verrez que lorsque vous avez supprimé et recréé ces pods, la sortie
de la commande reflète les adresses IP mises à jour qui sont associées au service.
Votre sortie ressemblera à quelque chose de ce genre :
alpaca-prod 10.112.1.54:8080,10.112.2.84:8080,10.112.2.85:8080 1m
alpaca-prod 10.112.1.54:8080,10.112.2.84:8080 1m
alpaca-prod <none> 1m
alpaca-prod 10.112.2.90:8080 1m
alpaca-prod 10.112.1.57:8080,10.112.2.90:8080 1m
alpaca-prod 10.112.0.28:8080,10.112.1.57:8080,10.112.2.90:8080 1m
L’objet Endpoints est parfait si vous écrivez un nouveau code qui est créé pour
s’exécuter sur Kubernetes depuis le début. Malheureusement, la plupart des
projets ne sont pas conçus dans ce cadre-là ! La plupart des systèmes existants
sont construits pour fonctionner avec de vieilles adresses IP classiques qui ne
changent pas aussi souvent.
Les services Kubernetes sont construits au-dessus des sélecteurs d’étiquettes sur
des pods. Cela signifie que vous pouvez utiliser l’API Kubernetes pour effectuer
une découverte des services rudimentaire sans utiliser aucun objet Service,
comme nous allons vous en faire la démonstration.
Avec kubectl (et via l’API), nous pouvons facilement voir quelles adresses IP sont
attribuées à chaque pod dans notre exemple de déploiement :
$ kubectl get pods -o wide --show-labels
alpaca-prod-12334-
... 10.112.1.54 ... app=alpaca,env=prod,ver=1
87f8h
alpaca-prod-12334-
... 10.112.2.84 ... app=alpaca,env=prod,ver=1
jssmh
bandicoot-prod-5678-
... 10.112.1.55 ... app=bandicoot,env=prod,ver=2
sbxzl
bandicoot-prod-5678-
... 10.112.2.86 ... app=bandicoot,env=prod,ver=2
x0dh8
C’est parfait, mais que se passe-t-il si vous avez de très nombreux pods ? Vous
souhaiterez probablement filtrer cela en fonction des étiquettes appliquées dans le
cadre du déploiement. Faisons cela uniquement pour l’application alpaca :
$ kubectl get pods -o wide --selector=app=alpaca,env=prod
À ce stade, nous avons les bases de la découverte des services ! Nous pouvons
toujours utiliser des étiquettes pour identifier l’ensemble de pods qui nous
intéresse, récupérer tous les pods correspondant à ces étiquettes, et extraire
l’adresse IP. Conserver un ensemble correct d’étiquettes et en assurer la
synchronisation pourrait cependant s’avérer difficile et c’est la raison pour laquelle
l’objet Service a été créé.
Les adresses IP du cluster sont des adresses IP virtuelles stables qui équilibrent la
charge du trafic sur tous les points de terminaison d’un service. Ce miracle est
accompli par un composant fonctionnant sur chaque nœud du cluster et qui se
nomme kube-proxy (figure 7.1).
Dans la figure 7.1, kube-proxy surveille les nouveaux services dans le cluster via le
serveur d’API. Il programme ensuite une série de règles iptables dans le noyau de
cet hôte pour réécrire la destination des paquets de telle sorte qu’ils soient dirigés
vers l’un des points de terminaison de ce service. Si l’ensemble des points de
terminaison d’un service change (en raison des mouvements des pods ou en
raison d’un échec de la vérification de la disponibilité), l’ensemble des règles
iptables est réécrit.
L’adresse IP du cluster lui-même est généralement assignée par le serveur d’API
quand le service est créé. Toutefois, lors de la création du service, l’utilisateur peut
choisir une adresse IP de cluster spécifique. Une fois qu’elle est définie, l’IP du
cluster ne peut pas être modifiée sans supprimer et recréer l’objet Service.
La plage d’adresses du service Kubernetes est configurée à l’aide du
paramètre --service-cluster-ip-range du binaire kube-apiserver. La plage
d’adresses de service ne doit pas se chevaucher avec les sous-réseaux IP et
les plages assignées à chaque pont Docker ou à chaque nœud Kubernetes.
En outre, toute adresse IP de cluster explicite qui est demandée doit provenir
de cette plage et ne pas être déjà utilisée.
Alors que la plupart des utilisateurs doivent employer les services DNS pour
trouver les adresses IP du cluster, il existe des mécanismes plus anciens dont on
peut encore se servir. On peut notamment citer l’injection de variables
d’environnement dans les pods quand ils démarrent.
Pour voir cela en action, examinons la console de l’instance bandicoot de kuard.
Entrez les commandes suivantes dans votre terminal :
$ BANDICOOT_POD=$(kubectl get pods -l app=bandicoot \
-o jsonpath='{.items[0].metadata.name}')
$ kubectl port-forward $BANDICOOT_POD 48858:8080
Clé Valeur
ALPACA_PROD_PORT tcp://10.115.245.13:808
ALPACA_PROD_PORT_8080_TCP tcp://10.115.245.13:808
ALPACA_PROD_PORT_8080_TCP_ADDR 10.115.245.13
ALPACA_PROD_PORT_8080_TCP_PORT 8080
ALPACA_PROD_PORT_8080_TCP_PROTO tcp
ALPACA_PROD_SERVICE_HOST 10.115.245.13
ALPACA_PROD_SERVICE_PORT 8080
_ 7.6 NETTOYAGE
Exécutez les commandes suivantes pour vous débarrasser de tous les objets créés
dans ce chapitre :
$ kubectl delete services,deployments -l app
_ 7.7 RÉSUMÉ
Kubernetes est un système dynamique qui remet en cause les méthodes
traditionnelles de nommage et de connexion des services sur le réseau. L’objet
Service fournit un moyen souple et puissant d’exposer des services à la fois dans
le cluster et hors du cluster. Avec les techniques étudiées dans ce chapitre, vous
pouvez connecter les services les uns aux autres et les exposer en dehors du
cluster.
Même si l’emploi des mécanismes de découverte dynamique des services dans
Kubernetes introduit de nouveaux concepts et peut, au premier abord, sembler
complexe, la compréhension et l’adaptation de ces techniques est la clé pour
libérer toute la puissance de Kubernetes. Une fois que votre application peut
trouver dynamiquement des services et réagir au placement dynamique de ces
applications, vous pouvez cesser de vous inquiéter de l’endroit où les choses
tournent et du moment où elles sont déplacées. Il s’agit d’une pièce critique du
puzzle pour commencer à penser aux services d’une façon logique et laisser
Kubernetes s’occuper des détails du placement des conteneurs.
8
ReplicaSets
_ 8.4 SPÉCIFICATIONS
DES REPLICASETS
Comme tous les concepts de Kubernetes, les ReplicaSets sont
définis à l’aide d’une spécification. Tous les ReplicaSets doivent
avoir un nom unique (défini grâce au champ metadata.name), une
section spec qui décrit le nombre de pods (réplicas) qui doivent être
exécutés à l’échelle du cluster à un moment donné, et un modèle de
pod qui décrit le pod à créer lorsque le nombre défini de réplicas
n’est pas atteint. L’exemple 8-1 illustre une définition minimale de
ReplicaSet.
Exemple 8-1. kuard-rs.yaml
apiVersion: extensions/v1beta1
kind: ReplicaSet
metadata:
name: kuard
spec:
replicas: 1
template:
metadata:
labels:
app: kuard
version: "2"
spec:
containers:
- name: kuard
image: "gcr.io/kuar-demo/kuard-amd64:2"
8.4.2 Étiquettes
kuard-
1/1 Running 0 11s
yvzgd
Name: kuard
Namespace: default
Image(s): kuard:1.9.15
Selector: app=kuard,version=2
Labels: app=kuard,version=2
No volumes.
Si vous ne voulez pas supprimer les pods qui sont gérés par le
ReplicaSet, vous pouvez définir le paramètre --cascade à false pour
garantir que seul l’objet ReplicaSet est supprimé et non les pods :
$ kubectl delete rs kuard --cascade=false
_ 8.9 RÉSUMÉ
La création de pods avec des ReplicaSets fournit la base de la
conception d’applications robustes avec un basculement
automatique et facilite le déploiement de ces applications en
autorisant des modèles de déploiement évolutifs. Les ReplicaSets
devraient être utilisés pour n’importe quel pod important, même s’il
s’agit d’un pod unique. Certaines personnes utilisent même par
défaut des ReplicaSets à la place des pods. En général, un cluster
comportera de nombreux ReplicaSets et vous n’avez donc aucune
raison de vous en priver.
9
DaemonSets
Les DaemonSets ont besoin d’un nom unique sur l’ensemble des
DaemonSets d’un espace de noms Kubernetes donné. Chaque
DaemonSet doit inclure un modèle de spécification de pod qui sera
utilisé pour créer des pods en fonction des besoins. C’est à cet
endroit que les similitudes entre les ReplicaSets et les DaemonSets
prennent fin. Contrairement aux ReplicaSets, les DaemonSets
créent par défaut des pods sur chaque nœud du cluster, à moins
qu’un sélecteur de nœud ne soit utilisé.
Une fois que vous avez mis en place une configuration de
DaemonSet valide, vous pouvez utiliser la commande kubectl apply
pour soumettre le DaemonSet à l’API Kubernetes. Dans cette
section, nous allons créer un DaemonSet pour nous assurer que le
serveur HTTP fluentd s’exécute sur tous les nœuds de notre cluster :
$ kubectl apply -f fluentd.yaml
daemonset "fluentd" created
Une fois que le DaemonSet fluentd a été soumis avec succès à l’API
Kubernetes, vous pouvez interroger son état actuel à l’aide de la
commande kubectl describe :
$ kubectl describe daemonset fluentd –namespace=kube-system
Name: fluentd
Image(s): fluent/fluentd:v0.14.10
Selector: app=fluentd
Node-Selector: <none>
Labels: app=fluentd
Cette sortie indique qu’un pod fluentd a été déployé avec succès sur
les trois nœuds de notre cluster. Nous pouvons vérifier ceci en
utilisant la commande kubectl get pods avec le paramètre -o pour
afficher les nœuds où chaque pod fluentd a été assigné :
$ kubectl get pods -o wide
k0-default-pool-35609c18-
fluentd-1q6c6 13m
z7tb
fluentd-mwi7h 13m k0-default-pool-35609c18-
ydae
k0-default-pool-35609c18-
fluentd-zr6l7 13m
pol3
k0-default-pool-35609c18-
fluentd-1q6c6 13m
z7tb
k0-default-pool-35609c18-
fluentd-mwi7h 13m
ydae
k0-default-pool-35609c18-
fluentd-oipmq 43s
0xnl
k0-default-pool-35609c18-
fluentd-zr6l7 13m
pol3
k0-default-pool-35609c18-
Ready 23m
0xnl
k0-default-pool-35609c18-
Ready 1d
pol3
k0-default-pool-35609c18-
Ready 1d
ydae
k0-default-pool-35609c18-
Ready 1d
z7tb
En utilisant un sélecteur d’étiquettes, on peut filtrer les nœuds en
fonction des étiquettes. Pour répertorier uniquement les nœuds qui
ont l’étiquette ssd définie à true, utilisez la commande kubectl get
nodes avec le paramètre --selector :
$ kubectl get nodes --selector ssd=true
k0-default-pool-35609c18-
Ready 1d
z7tb
_ 9.6 RÉSUMÉ
Les DaemonSets fournissent une abstraction facile à utiliser pour
l’exécution d’un ensemble de pods sur chaque nœud d’un cluster
Kubernetes, ou si le cas l’exige, sur un sous-ensemble de nœuds
basés sur des étiquettes. Le DaemonSet fournit son propre
contrôleur et son propre ordonnanceur pour s’assurer que les
services clés, comme les agents de surveillance, sont toujours
opérationnels sur les bons nœuds de votre cluster.
Pour certaines applications, il est simplement souhaitable de
programmer un certain nombre de réplicas car on ne se soucie pas
vraiment de leur emplacement tant qu’ils ont suffisamment de
ressources pour fonctionner de manière fiable. Cependant, il existe
une autre classe d’applications, comme les agents et les
applications de surveillance, qui doivent être présents sur chaque
machine d’un cluster pour qu’il fonctionne correctement. Ces
DaemonSets ne sont pas vraiment des applications traditionnelles,
mais ils servent plutôt à ajouter des fonctionnalités au cluster
Kubernetes lui-même. Comme le DaemonSet est un objet déclaratif
actif géré par un contrôleur, il est facile de signifier votre intention
qu’un agent s’exécute sur chaque ordinateur sans avoir à le
déployer explicitement sur chaque machine. Ceci est
particulièrement utile dans le contexte d’un cluster Kubernetes mis à
l’échelle de manière automatique où les nœuds peuvent
constamment évoluer sans intervention de l’utilisateur. Dans de tels
cas, le DaemonSet ajoute automatiquement les agents appropriés à
chaque nœud au fur et à mesure qu’il est ajouté au cluster par le
processus de mise à l’échelle automatique.
10
Jobs
Jusqu’à présent, nous nous sommes concentrés sur des processus qui
durent longtemps, comme les bases de données et les applications Web.
Ces types de charges de travail s’exécutent jusqu’à ce qu’ils soient mis à
jour ou que le service ne soit plus nécessaire. Alors que ces processus longs
constituent la grande majorité des charges de travail qui s’exécutent sur un
cluster Kubernetes, on a aussi souvent besoin d’exécuter des tâches de
courte durée et ponctuelles. L’objet Job est conçu pour gérer ces types de
tâches.
Un job crée des pods qui s’exécutent jusqu’à ce qu’ils se terminent avec
succès (c’est-à-dire avec un code de sortie égal à 0). En revanche, un pod
normal redémarre continuellement, quel que soit son code de sortie. Les
jobs sont utiles pour les choses que vous ne voulez faire qu’une seule fois,
comme les migrations de bases de données ou les traitements par lots. Si
elle était gérée dans un pod normal, la tâche de migration d’une base de
données s’exécuterait en boucle, en repeuplant continuellement la base de
données après chaque sortie.
Dans ce chapitre, nous explorons les modèles de jobs les plus courants
proposés par Kubernetes. Nous allons également tirer parti de ces modèles
dans des scénarios s’appliquant à des situations réelles.
Cas
Type Comportement completions parallelisme
d’utilisation
Un seul pod
fonctionnant
Migration de
une seule fois
Ponctuel bases de 1 1
jusqu’à ce qu’il
données
se termine avec
succès
Cas
Type Comportement completions parallelisme
d’utilisation
Un ou plusieurs
pods
Plusieurs
s’exécutant une
pods traitant
Achèvements ou plusieurs
un
fixes fois jusqu’à 1+ 1+
ensemble
parallèles atteindre un
de travaux
nombre
en parallèle
d’achèvements
fixe
Un ou plusieurs
Traitement
pods
File d’attente de plusieurs
fonctionnant
de travaux : pods à partir
une seule fois 1 2+
jobs d’une file de
jusqu’à ce qu’ils
parallèles travaux
se terminent
centralisée
avec succès
Les jobs ponctuels permettent d’exécuter un pod une seule fois jusqu’à ce
qu’il se termine avec succès. Bien qu’elle puisse paraître facile, cette tâche
nécessite un certain nombre d’opérations. Tout d’abord, un pod doit être créé
et soumis à l’API Kubernetes. Cela se fait à l’aide d’un modèle de pod défini
dans la configuration du job. Une fois qu’un job est en cours d’exécution, le
pod qui gère le job doit être surveillé car il faut contrôler qu’il se termine avec
succès. Il y a de multiples raisons pour qu’un job échoue, notamment une
erreur d’application, une exception non interceptée pendant l’exécution, ou
bien une panne de nœud avant que le job ne se termine. Dans tous les cas,
le contrôleur de jobs est responsable de la recréation du pod jusqu’à ce qu’il
se termine avec succès.
Il existe plusieurs façons de créer un job ponctuel dans Kubernetes. La plus
simple est d’utiliser l’outil en ligne de commande kubectl :
$ kubectl run -i oneshot \
--image=gcr.io/kuar-demo/kuard-amd64:1 \
--restart=OnFailure \
-- --keygen-enable \
--keygen-exit-on-complete \
--keygen-num-to-gen 10
...
(ID 0) Workload starting
(ID 0 1/10) Item done: SHA256:nAsUsG54XoKRkJwyN+OShkUPKew3mwq7OCc
(ID 0 2/10) Item done: SHA256:HVKX1ANns6SgF/er1lyo+ZCdnB8geFGt0/8
(ID 0 3/10) Item done: SHA256:irjCLRov3mTT0P0JfsvUyhKRQ1TdGR8H1jg
(ID 0 4/10) Item done: SHA256:nbQAIVY/yrhmEGk3Ui2sAHuxb/o6mYO0qRk
(ID 0 5/10) Item done: SHA256:CCpBoXNlXOMQvR2v38yqimXGAa/w2Tym+aI
(ID 0 6/10) Item done: SHA256:wEY2TTIDz4ATjcr1iimxavCzZzNjRmbOQp8
(ID 0 7/10) Item done: SHA256:t3JSrCt7sQweBgqG5CrbMoBulwk4lfDWiTI
(ID 0 8/10) Item done: SHA256:E84/Vze7KKyjCh9OZh02MkXJGoty9PhaCec
(ID 0 9/10) Item done: SHA256:UOmYex79qqbI1MhcIfG4hDnGKonlsij2k3s
(ID 0 10/10) Item done: SHA256:WCR8wIGOFag84Bsa8f/9QHuKqF+0mEnCADY
(ID 0) Workload exiting
Puis utilisez la commande kubectl describe pour obtenir des informations sur
le job :
$ kubectl describe jobs oneshot
Name: oneshot
Namespace: default
Image(s): gcr.io/kuar-demo/kuard-amd64:1
Selector: controller-uid=cf87484b-e664-11e6-8222-42010a8a007b
Parallelism: 1
Completions: 1
Start Time: Sun, 29 Jan 2017 12:52:13 -0800
Labels: Job=oneshot
Pods Statuses: 0 Running / 1 Succeeded / 0 Failed
No volumes.
Events:
... Reason Message
... ------ -------
... SuccessfulCreate Created pod: oneshot-4kfdt
Vous pouvez afficher les résultats du job en regardant les journaux du pod
qui a été créé :
$ kubectl logs oneshot-4kfdt
...
Serving on :8080
(ID 0) Workload starting
(ID 0 1/10) Item done: SHA256:+r6b4W81DbEjxMcD3LHjU+EIGnLEzbpxITKn8IqhkPI
(ID 0 2/10) Item done: SHA256:mzHewajaY1KA8VluSLOnNMk9fDE5zdn7vvBS5Ne8AxM
(ID 0 3/10) Item done: SHA256:TRtEQHfflJmwkqnNyGgQm/IvXNykSBIg8c03h0g3onE
(ID 0 4/10) Item done: SHA256:tSwPYH/J347il/mgqTxRRdeZcOazEtgZlA8A3/HWbro
(ID 0 5/10) Item done: SHA256:IP8XtguJ6GbWwLHqjKecVfdS96B17nnO21I/TNc1j9k
(ID 0 6/10) Item done: SHA256:ZfNxdQvuST/6ZzEVkyxdRG98p73c/5TM99SEbPeRWfc
(ID 0 7/10) Item done: SHA256:tH+CNl/IUl/HUuKdMsq2XEmDQ8oAvmhMO6Iwj8ZEOj0
(ID 0 8/10) Item done: SHA256:3GfsUaALVEHQcGNLBOu4Qd1zqqqJ8j738i5r+I5XwVI
(ID 0 9/10) Item done: SHA256:5wV4L/xEiHSJXwLUT2fHf0SCKM2g3XH3sVtNbgskCXw
(ID 0 10/10) Item done: SHA256:bPqqOonwSbjzLqe9ZuVRmZkz+DBjaNTZ9HwmQhbdWLI
(ID 0) Workload exiting
Dans cet exemple, nous voyons que le même pod a redémarré quatre fois.
Kubernetes est dans l’état CrashLoopBackOff pour ce pod. Il n’est pas rare
d’avoir un bug quelque part qui provoque un plantage du programme dès
qu’il démarre. Dans ce cas, Kubernetes va attendre un peu avant de
redémarrer le pod, afin d’éviter des plantages en boucle qui consommeraient
les ressources du nœud. Tout cela est géré localement au niveau du nœud
par kubelet sans que le job ne soit impliqué.
Supprimons le job (kubectl delete jobs oneshot), et essayons autre chose.
Nous allons modifier à nouveau le fichier de configuration et faire passer le
paramètre restartPolicy de OnFailure à Never. Exécutez la commande
kubectl apply -f jobs-oneshot-failure2.yaml.
Si nous attendons un peu, puis examinons les pods liés au job, nous allons
trouver quelque chose d’intéressant :
$ kubectl get pod -l job-name=oneshot -a
oneshot-
NAME READY STATUS RESTARTS AGE 0/1
0wm49
oneshot- oneshot-
1/1 Running 0 6s 0/1
hkzw0 k5swz
28s oneshot-
Error 0 0/1 Error 0 19s
m1rdw
oneshot-
0/1 Error 0 57s
x157b
La génération des clés peut être lente. Nous allons démarrer ensemble un
groupe de workers afin de rendre la génération de clés plus rapide. Nous
allons utiliser une combinaison de paramètres completions et parallelism.
Notre objectif est de générer 100 clés en exécutant 10 kuard générant
chacun 10 clés. Mais comme nous ne voulons pas surcharger notre cluster,
nous allons nous limiter à cinq pods à la fois.
Cela se traduit par le paramètre completions défini à 10 et parallelism à 5. La
configuration est illustrée dans l’exemple 10-3.
Exemple 10-3. job-parallel.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: parallel
labels:
chapter: jobs
spec:
parallelism: 5
completions: 10
template:
metadata:
labels:
chapter: jobs
spec:
containers:
- name: kuard
image: gcr.io/kuar-demo/kuard-amd64:1
imagePullPolicy: Always
args:
- "--keygen-enable"
- "--keygen-exit-on-complete"
- "--keygen-num-to-gen=10"
restartPolicy: OnFailure
N’hésitez pas à fouiner dans les jobs terminés et à vérifier leurs logs pour
voir les empreintes des clés qu’ils ont générées. Faites le ménage en
supprimant l’objet Job, une fois qu’il est terminé, grâce à la commande
kubectl delete job parallel.
Il est courant que les jobs traitent le travail à partir d’une file d’attente de
travaux. Dans ce scénario, une tâche crée un certain nombre d’éléments de
travail et les publie dans une file d’attente de travaux. Un job worker peut
être exécuté pour traiter chaque élément de travail jusqu’à ce que la file
d’attente de travaux soit vide (figure 10.1).
Figure 10.1 – Jobs parallèles.
Exécutez ces commandes et vous devriez voir sur la sortie de votre terminal
une centaine d’objets JSON avec un identificateur de message unique pour
chaque élément de travail. Vous pouvez vérifier l’état de la file d’attente en
regardant l’onglet « MemQ Server » dans l’interface utilisateur, ou vous
pouvez demander directement à l’API de la file d’attente de travaux :
$ curl 127.0.0.1:8080/memq/server/stats
{
"kind": "stats",
"queues": [
{
"depth": 100,
"dequeued": 0,
"drained": 0,
"enqueued": 100,
"name": "keygen"
}
]
}
Une fois que le job a été créé, vous pouvez voir les pods qui supportent le
job :
$ kubectl get pods
Vous noterez qu’il y a cinq pods qui s’exécutent en parallèle. Ces pods
continueront à s’exécuter jusqu’à ce que la file d’attente de travaux soit vide.
Vous pouvez observer quand cela se produit dans l’interface utilisateur sur le
serveur de la file d’attente de travaux. Au fur et à mesure que la file d’attente
se vide, les pods des consommateurs quitteront et le job consumers sera
considéré comme étant achevé.
◆ Nettoyage
En utilisant des étiquettes, on peut supprimer toutes les choses que nous
avons créées dans cette section :
$ kubectl delete rs,svc,job -l chapter=jobs
_ 10.3 RÉSUMÉ
Sur un cluster unique, Kubernetes peut gérer à la fois les charges de travail
qui durent longtemps, comme les applications Web, et les charges de travail
de courte durée, comme les traitements par lots. L’abstraction Job vous
permet de modéliser des modèles de travail par lots qui vont des tâches
simples ponctuelles aux tâches parallèles traitant de nombreux éléments
jusqu’à achèvement du travail.
Les jobs sont une primitive de bas niveau qui peut être utilisée directement
pour des charges de travail simples. Toutefois, Kubernetes est conçu à la
base pour être extensible grâce à des objets de niveau supérieur. Les jobs
ne font pas exception à cette règle et ils peuvent facilement être utilisés par
les systèmes d’orchestration de niveau supérieur pour gérer des tâches plus
complexes.
11
ConfigMaps et secrets
_ 11.1 CONFIGMAPS
On peut se représenter un ConfigMap comme un objet Kubernetes
qui définit un petit système de fichiers. On peut aussi se le
représenter comme un ensemble de variables qui peuvent être
employées quand on définit l’environnement ou la ligne de
commande pour les conteneurs. La chose principale à retenir est
que le ConfigMap est combiné avec le pod juste avant qu’il ne soit
exécuté. Cela signifie que l’image du conteneur et la définition du
pod peuvent être réutilisées à travers de nombreuses applications
en changeant simplement le ConfigMap qui est employé.
Type: Opaque
Data
====
kuard.crt: 1050 bytes
kuard.key: 1679 bytes
Le secret kuard-tls en place, nous pouvons l’utiliser à partir d’un pod
en utilisant un volume de secrets.
◆ Volumes de secrets
.auth_token Token..properties
config_file _password.txt
Lors de la sélection d’un nom de clé, vous devez prendre
en compte le fait que ces clés peuvent être exposées à des
pods via un montage de volume. Choisissez un nom qui sera
significatif lorsqu’il sera spécifié sur une ligne de commande ou
dans un fichier de configuration. Le stockage d’une clé TLS
sous la forme key.pem est plus clair que tls-key lors de la
configuration des applications pour accéder aux secrets.
11.4.1 Liste
default-token- kubernetes.io/service-account-
3 1h
f5jq2 token
my-config 3 1m
kubectl describe peut être utilisé pour obtenir plus de détails sur un
objet particulier :
$ kubectl describe configmap my-config
Name: my-config
Namespace: default
Labels: <none>
Annotations: <none>
Data
====
another-param: 13 bytes
extra-param: 11 bytes
my-config.txt: 116 bytes
Enfin, vous pouvez voir les données brutes (y compris les valeurs
dans les secrets…) avec une commande similaire à kubectl get
configmap my-config -o yaml ou kubectl get secret kuard-tls-o yaml.
11.4.2 Création
La façon la plus simple de créer un secret ou un ConfigMap consiste
à exécuter une commande kubectl create secret generic ou kubectl
create configmap. Il existe une grande variété de façons de spécifier
les éléments de données qui sont stockés dans le secret ou le
ConfigMap. On peut combiner les différentes options en une seule
commande :
--from-file=<nom-de-fichier>
Une fois qu’un ConfigMap ou qu’un secret est mis à jour à l’aide de
l’API, il sera automatiquement publié sur tous les volumes qui
utilisent ce ConfigMap ou ce secret. Cela peut prendre quelques
secondes, mais la liste des fichiers et le contenu des fichiers, tels
qu’ils sont vus par kuard, seront mis à jour avec ces nouvelles
valeurs. En utilisant cette fonctionnalité de mise à jour en direct,
vous pouvez mettre à jour la configuration des applications sans les
redémarrer.
Actuellement, il n’existe aucun moyen intégré pour signaler à une
application qu’une nouvelle version d’un ConfigMap est déployée. Il
appartient à l’application (ou à un script utilitaire) de rechercher les
fichiers de configuration à modifier et de les recharger.
L’utilisation du navigateur de fichiers dans kuard (accessible par
kubectl port-forward) est une excellente façon d’exploiter de manière
interactive les mises à jour dynamiques des secrets et des
ConfigMaps.
_ 11.5 RÉSUMÉ
Les ConfigMaps et les secrets sont un excellent moyen d’offrir une
configuration dynamique à votre application. Ils vous permettent de
créer une image de conteneur (et une définition de pod) une seule
fois et de la réutiliser dans des contextes différents. Vous pouvez
ainsi utiliser exactement la même image, que vous en soyez au
stade du développement, de la simulation ou bien de la production.
Vous pouvez aussi employer une seule image à travers plusieurs
équipes et services. Séparer la configuration du code de l’application
rendra vos applications plus fiables et plus réutilisables.
12
Déploiements
nginx 1 1 1 1 13s
nginx-
1 1 1 13m
1128242161
nginx-
2 2 2 13m
1128242161
nginx-
2 2 2 13m
1128242161
Name: nginx
Namespace: default
Labels: run=nginx
Selector: run=nginx
StrategyType: RollingUpdate
MinReadySeconds: 0
OldReplicaSets: <none>
Events:
Une fois que vous avez enregistré et validé cette modification, vous
pouvez mettre à jour le déploiement à l’aide de la commande kubectl
apply :
$ kubectl apply -f nginx-deployment.yaml
nginx 3 3 3 3 4m
Encore une fois, vous pouvez utiliser kubectl apply pour mettre à
jour le déploiement :
$ kubectl apply -f nginx-deployment.yaml
nginx-
0 0 0 ... ...
1128242161
nginx-
3 3 3 ... ...
1128635377
REVISION CHANGE-CAUSE
1 <none>
REVISION CHANGE-CAUSE
1 <none>
REVISION CHANGE-CAUSE
1 <none>
REVISION CHANGE-CAUSE
1 <none>
Parfois, il arrive cependant que le fait que l’on vous signale qu’un
pod est prêt ne vous donne pas l’assurance que ce pod se comporte
effectivement correctement. En effet, certaines erreurs ne se
produisent qu’après un certain laps de temps. Par exemple, une fuite
de mémoire peut prendre quelques minutes avant qu’elle
n’apparaisse, ou bien vous pouvez avoir un bug qui ne soit
déclenché que par 1% des requêtes. Dans la plupart des situations
réelles, il est souhaitable d’attendre un certain temps pour s’assurer
que la nouvelle version fonctionne correctement avant de passer à la
mise à jour du prochain pod.
Pour les déploiements, cette période d’attente est définie par le
paramètre minReadySeconds :
...
spec:
minReadySeconds: 60
...
Une fois que nous avons créé le ReplicaSet, il va à son tour créer un
pod exécutant MySQL, en utilisant le disque persistant que nous
avons créé au départ. La dernière étape consiste à exposer cela
sous la forme d’un service Kubernetes (exemple 13-7).
Exemple 13-7. mysql-service.yaml
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
ports:
- port: 3306
protocol: TCP
selector:
app: mysql
Une fois que vous avez initié le ReplicaSet Mongo, vous pouvez
ajouter les réplicas restants en exécutant les commandes suivantes
dans l’outil mongo sur le pod mongo-0.mongo :
$ kubectl exec -it mongo-0 mongo
> rs.add("mongo-1.mongo:27017");
> rs.add("mongo-2.mongo:27017");
HOST=mongo-0.mongo:27017
while true; do
sleep 3600
done
Si vous préférez une autre méthode, vous pouvez tous les combiner
en un seul fichier YAML où les objets individuels sont séparés par --
-. Assurez-vous de conserver le même ordre, puisque la définition du
StatefulSet s’appuie sur la définition du ConfigMap existant.
_ 13.4 RÉSUMÉ
Une fois que nous avons combiné les StatefulSets, les demandes de
volumes persistants, et les sondes d’activité, nous avons une
installation cloud-native, évolutive et renforcée de MongoDB
fonctionnant sur Kubernetes. Bien que cet exemple traite de
MongoDB, les étapes de création des StatefulSets pour gérer
d’autres solutions de stockage sont assez similaires et vous pouvez
suivre des modèles analogues.
14
Déploiement d’applications
réelles
_ 14.1 PARSE
Le serveur Parse (https://parse.com) est une API cloud qui est
dédiée à la fourniture d’un stockage facile à utiliser pour les
applications mobiles. Il fournit une grande variété de bibliothèques
clientes qui le rendent facile à intégrer à Android, iOS et à d’autres
plateformes mobiles. Parse a été acheté par Facebook en 2013,
mais le produit a été arrêté par la suite. Heureusement pour nous,
un serveur compatible a été publié en open source par l’équipe de
développement de Parse, si bien que nous pouvons l’utiliser. Cette
section décrit comment configurer Parse dans Kubernetes.
_ 14.2 GHOST
Ghost est un moteur de blogging populaire avec une interface
conviviale écrite en JavaScript. Il peut utiliser une base de données
SQLite basée sur des fichiers ou bien MySQL pour le stockage.
config = {
development: {
url: 'http://localhost:2368',
database: {
client: 'sqlite3',
connection: {
filename: path.join(process.env.GHOST_CONTENT,
'/data/ghost-dev.db')
},
debug: false
},
server: {
host: '0.0.0.0',
port: '2368'
},
paths: {
contentPath: path.join(process.env.GHOST_CONTENT, '/')
}
}
};
module.exports = config;
Une fois que vous avez enregistré ce fichier de configuration ghost-
config.js, vous pouvez créer un objet Kubernetes ConfigMap avec la
commande :
$ kubectl create cm --from-file ghost-config.js ghost-config
spec:
replicas: 1
selector:
matchLabels:
run: ghost
template:
metadata:
labels:
run: ghost
spec:
containers:
- image: ghost
name: ghost
command:
- sh
- -c
- cp /ghost-config/ghost-config.js /var/lib/ghost/config.js
&& /usr/local/bin/docker-entrypoint.sh node current/index.js
volumeMounts:
- mountPath: /ghost-config
name: config
volumes:
- name: config
configMap:
defaultMode: 420
name: ghost-config
Il faut noter une chose ici : nous copions le fichier config.js à partir
d’un emplacement différent de l’emplacement où Ghost s’attend à le
trouver, puisque le ConfigMap ne peut monter que des répertoires,
et non pas des fichiers individuels. Ghost attend la présence d’autres
fichiers dans son répertoire qui ne sont pas dans ce ConfigMap, si
bien que nous ne pouvons pas monter le ConfigMap entier dans
/var/lib/ghost.
Vous pouvez exécuter ceci avec la commande :
$ kubectl apply -f ghost.yaml
Une fois que le pod est fonctionnel, vous pouvez l’exposer en tant
que service avec :
$ kubectl expose deployments ghost --port=2368
◆ Ghost + MySQL
Bien entendu, cet exemple n’est pas très évolutif, ni même fiable,
puisque le contenu du blog est stocké dans un fichier local à
l’intérieur du conteneur. Une approche plus évolutive consiste à
stocker les données du blog dans une base de données MySQL.
Pour ce faire, modifiez d’abord config.js pour inclure :
...
database: {
client: 'mysql',
connection: {
host : 'mysql',
user : 'root',
password : 'root',
database : 'ghost_db',
charset : 'utf8'
}
},
...
_ 14.3 REDIS
Redis est un système de gestion de paires clé/valeur en mémoire
très populaire, avec de nombreuses fonctionnalités supplémentaires.
C’est une application intéressante à déployer car c’est un bon
exemple de la valeur de l’abstraction des pods Kubernetes. Ceci est
dû au fait qu’une installation fiable de Redis consiste en fait en deux
programmes fonctionnant ensemble. Le premier est redis-server, qui
implémente le système de paires clé/valeur, et l’autre est redis-
sentinel, qui implémente la vérification de l’intégrité et le
basculement vers un cluster Redis répliqué.
Lorsque Redis est déployé de manière répliquée, il existe un serveur
maître unique qui peut être utilisé pour les opérations de lecture et
d’écriture. En outre, il existe d’autres serveurs de réplicas qui
dupliquent les données écrites sur le serveur maître et qui peuvent
être utilisés pour l’équilibrage de charge des opérations de lecture.
N’importe lequel de ces réplicas peut basculer pour devenir le
serveur maître si le maître original tombe en panne. Ce basculement
est effectué par la sentinelle de Redis. Dans notre déploiement, le
serveur Redis et sa sentinelle sont hébergés dans le même fichier.
dir /redis-data
dir .
redis-sentinel /redis-config/sentinel.conf
_ 14.4 RÉSUMÉ
Dans les sections précédentes, nous avons décrit comment déployer
une grande variété d’applications en utilisant différents concepts
Kubernetes. Nous avons vu comment mettre en place des services
de nommage et de découverte pour déployer des interfaces Web
comme Ghost, ainsi que des serveurs API comme Parse. Nous
avons aussi vu comment l’abstraction des pods facilite le
déploiement des composants qui constituent un cluster Redis fiable.
Même si vous ne souhaitez pas réellement déployer ces applications
en production, ces exemples illustrent des modèles que vous pouvez
imiter pour gérer vos applications à l’aide de Kubernetes. Nous
espérons que la mise en pratique des concepts que nous avons
décrits dans les chapitres précédents dans des exemples tirés du
monde réel vous aura aidé à mieux comprendre comment exploiter
Kubernetes.
ANNEXE
Construction d’un cluster
Kubernetes
avec des Raspberry Pi
# Utilise le DNS Google par défaut, mais vous pouvez remplacer cette valeur
# par le DNS de votre fournisseur d’accès à Internet
option domain-name-servers 8.8.8.8, 8.8.4.4;
◆ Opérations supplémentaires
Installation de Kubernetes
Enfin, faites une mise à jour et installez les outils Kubernetes. Cela
va également mettre à niveau tous les paquets de votre système :
# apt-get update
$ apt-get upgrade
$ apt-get install -y kubelet kubeadm kubectl kubernetes-cni
Configuration du cluster
Sur le nœud master (celui qui exécute le DHCP et qui est connecté
à Internet), exécutez :
$ sudo kubeadm init --pod-network-cidr 10.244.0.0/16 \
--apiserver-advertise-address 10.0.0.1 \
--apiserver-cert-extra-sans kubernetes.cluster.home
Notez que vous diffusez votre adresse IP interne, et non pas votre
adresse externe.
En fin de compte, cela affichera une commande pour joindre les
nœuds à votre cluster. Cela devrait ressembler à quelque chose
similaire à ce qui suit :
$ kubeadm join --token=<token> 10.0.0.1
Une fois que vous avez mis à jour le fichier kube-flannel.yaml, vous
pouvez créer la configuration réseau de Flanel avec :
$ kubectl apply -f kube-flannel.yaml
abstraction 1
Alpine 1
Amazon Web Services 1
annotation 1
création 1
utilisation 1
API 1
sélecteur d’étiquettes 1
application
évolution 1
exemple 1
exemple réel 1
mobile stockage 1
apply 1
auto-guérison 1
auto-réparation 1
Azure Cloud 1
base de données
MySQL 1
blog
application Ghost 1
boucle de rapprochement 1, 2
cgroups 1
cloud
intégration 1
cluster
composants 1, 2
créé à partir de Raspberry Pi 1
dépassement des limites 1
déploiement 1
évolution 1
MongoDB 1
provisionnement dynamique du volume 1
variables d’environnement 1
vérification de l'état 1
code
exemples du livre 1
completions 1, 2
ConfigMap 1
contraintes de nommage 1
création 1, 2
gestion 1
liste 1
mise à jour 1
utilisation 1
configuration déclarative 1
conteneur
catégories 1
contrôles d'intégrité 1
copie de fichiers 1
création d'image 1
d’application 1
débogage 1
exécution de commandes 1
format d’image Docker 1
image 1
logs 1, 2
mise à jour de l'image 1
mise en quarantaine 1
optimisation de la taille de l'image 1
registre distant 1
registre privé 1
registre public 1
sécurité des images 1
stockage distant de l'image 1
stratification 1
suppression d'une image 1
système 1
contexte 1
DaemonSet 1
ajout d’étiquettes aux nœuds 1
création 1
déploiement des mises à jour 1
limitation à certains nœuds 1
mise à jour 1
ordonnanceur 1
sélecteurs de nœuds 1
suppression 1
suppression des pods individuels 1
débogage 1
découplage 1, 2, 3
découverte des services 1
déploiement 1
création 1
cycle de vie 1
exemple 1
exemples d'applications réelles 1
gestion 1
historique 1
informations détaillées 1
mise à jour 1
mise à l’échelle 1
ralentissement 1
stratégies 1
suppression 1
Deployment 1
fonctionnement interne 1
développement
évolutivité 1
rapidité 1
disponibilité
vérification 1
DNS 1, 2, 3
Docker 1
exécution de conteneur 1
format d’image 1
limitation des ressources 1
registres privés 1
runtime 1
Dockerfile 1
données persistantes 1
disques distants 1
edit 1
Endpoints 1
équilibrage de charge 1, 2, 3, 4
équipe
évolutivité 1
espace de noms 1, 2
état actuel 1
état désiré 1
état observé 1
etcd 1
étiquette 1, 2
création 1
modification 1
origine 1
sélecteurs 1
syntaxe 1
évolutivité 1
exemples de code
téléchargement 1
gcloud 1
Ghost 1
configuration 1
MySQL 1
Google Cloud Platform 1
Google Container Engine 1
Google Container Registry 1
HPA 1
Hypriot 1
immutabilité 1
infrastructure
abstraction 1
infrastructure immutable 1
infrastructure mutable 1
intégrité
contrôles 1
types de contrôles 1
interface utilisateur 1
job 1
chargement d’une file d’attente 1
création 1
démarrage d’une file d’attente 1
file d'attente 1
modèles 1
ponctuel 1
JSON 1
JSONPath 1
kuard
exemple d’application 1
interface Web 1
kubectl 1
commandes courantes 1
kube-proxy 1
Kubernetes
abstraction de l’infrastructure 1
affichage des objets 1
API 1
client 1
cluster avec des Raspberry Pi 1
création des objets 1
découplage 1
demande d’API 1
déploiement 1
déploiement de cluster 1
description 1
DNS 1
efficacité 1
évolutivité 1
importation de services externes 1
installation en local 1
installation sur Amazon Web Services 1
installation sur Google Container Engine 1
installation sur Microsoft Azure 1
installation sur un Raspberry Pi 1
interface utilisateur 1
isolation des problèmes 1
modèles d'utilisation de volumes 1
modification d'un objet 1
objet ConfigMap 1
objet DaemonSet 1
objet Deployment 1
objet Endpoints 1
objet Job 1
objet ReplicaSet 1
objet Service 1
origine 1
pods 1
proxy 1
runtime de conteneur par défaut 1
solutions de stockage 1
stockage natif 1
suppression d'un objet 1
vitesse 1
Linux
distribution minimaliste 1
LoadBalancer 1
manifeste 1
métadonnées 1, 2
métrique d’utilisation 1
micro-service 1
Microsoft Azure 1
minikube 1, 2
MongoDB 1
automatisation du déploiement 1
MySQL 1
exécution dans un pod 1
Ghost 1
nœud
liste 1
nœud master 1
nœud worker 1
Open Container Initiative 1
ordonnancement 1
ordonnanceur 1
requêtes 1
parallelism 1, 2
parallélisme 1
Parse 1
création du serveur 1
déploiement du serveur 1
test 1
PersistentVolumeClaim 1
PersistentVolumes 1
planificateur Voir ordonnanceur 1
pod 1
accès 1
création 1
création d'un manifeste 1
défaillance 1
exécution 1
informations détaillées 1
liste 1
manifeste 1
modèle 1
MySQL 1
rapport avec les ReplicaSets 1
suppression 1
utilisation de volumes 1
utilité 1
point de terminaison 1
proxy 1
Raspberry Pi 1
configuration du cluster 1
création d'un cluster 1
génération des images 1
installation de Kubernetes 1
Raspbian 1
Recreate 1
redirection de port 1
Redis 1
configuration 1
création d’un service 1
déploiement 1
sentinelle 1
test du cluster 1
ReplicaSet 1
création 1
emploi 1
inspection 1
mise à l’échelle automatique 1
mise à l’échelle basée sur le CPU 1
mise à l'échelle déclarative 1
mise à l'échelle impérative 1
rapport avec les pods 1
recherche à partir d’un pod 1
recherche de pods 1
spécifications 1
suppression 1
ressources
gestion 1
limitation de la mémoire 1
limitation du CPU 1
métriques 1
minimales requises 1
plafonnement 1
séparation 1
RESTful 1
RollingUpdate 1
configuration d’une stratégie 1
scale 1
secret 1
contraintes de nommage 1
création 1, 2
d’extraction d’image 1
gestion 1
liste 1
mise à jour 1
utilisation 1
Service 1
service
découverte 1
découverte manuelle 1
évolution 1
gestion des versions multiples 1
sans sélecteurs 1
singleton fiable
exécution 1
SLA 1
sonde d'activité 1
sonde de disponibilité 1, 2
stateful 1, 2, 3, 4
StatefulSet 1
MongoDB 1
propriétés 1
volumes persistants 1
stateless 1, 2, 3, 4, 5
stockage persistant 1
stratégie
déploiements 1
système distribué 1
variable d’environnement 1
volume
persistance des données 1
provisionnement dynamique 1
volume de secrets 1
YAML 1
1. Brendan Burns et al., “Borg, Omega, and Kubernetes: Lessons Learned from Three
Container-Management Systems over a Decade,” ACM Queue 14 (2016): 70–93,
disponible à http://bit.ly/2vIrL4S.
2. NdT : on attribue cette expression à Jeff Bezos, le fondateur d’Amazon.
3. NdT : depuis la parution de l’édition originale de cet ouvrage, Amazon propose ce
service. Vous trouverez de plus amples informations sur
https://aws.amazon.com/fr/kubernetes/.
4. Comme vous l’apprendrez dans le chapitre suivant, un espace de noms dans
Kubernetes est une entité pour l’organisation des ressources Kubernetes. Vous pouvez
vous le représenter comme un dossier dans un système de fichiers.
5. Il s’agit d’une syntaxe YAML compacte : un élément d’une liste (matchExpressions)
est un mappage avec trois entrées. La dernière entrée (values) a une valeur qui est une
liste avec deux éléments.
6. Pour plus de précision voir https://www.tableau.com/fr-fr/about/blog/2017/3/what-
data-gravity-anyway-67725