Académique Documents
Professionnel Documents
Culture Documents
pratique
Courriel : firstinfo@editionsfirst.fr
Site Internet : www.editionsfirst.fr
ISBN : 978-2-412-04964-8
ISBN numérique : 9782412052877
Dépôt légal : décembre 2019
Git
Git est devenu le standard des systèmes de contrôle des
versions distribuées (versionneur). Si vous connaissez déjà
l’un des outils CVS et SVN, mais pas Git, n’hésitez pas à vous
y intéresser. Si nécessaire, procurez-vous un livre ou un
tutoriel qui lui est dédié. Le site Web de GitHub
(http://github.com) est un excellent point de départ pour
créer un référentiel personnel. Pour plus d’informations au
sujet de GitHub, visitez la page
http://training.github.com qui comporte des tutoriels
interactifs (http://try.github.io).
Langage Python
Nous invitons systématiquement nos étudiants, après avoir
appris à programmer en C et C++ ou Java, à adopter en outre
un langage de script. Fut un temps où Perl régnait dans ce
domaine, mais de nos jours ce sont plutôt Ruby et Go qui
prennent l’avantage. La plupart des exemples du livre
utilisent le langage Python, mais il y a quelques exemples
Ruby. Vous trouverez chez le même éditeur plusieurs livres à
propos du langage Python.
Langage Go
Kubernetes est écrit en langage Go, l’un des nouveaux
langages de prédilection dans de nombreuses start-up, pour
de nombreux projets open source de niveau système. Ce livre
ne présente pas la programmation en Go, mais montre
comment compiler certains projets Go. Il n’est pas inutile
d’avoir un minimum de connaissances de la mise en place
d’un environnement de travail Go. Pour en savoir plus, nous
vous renvoyons au tutoriel disponible (http://bit.ly/go-
intro).
www.editionsfirst.fr
Concept
MotClé
NomVariable
Commande
NomFichier
Codage mettant en exergue les noms de fichiers et de
répertoires (dossiers), ainsi que les chemins d’accès et
adresses Web locales.
AdresseWeb
firstinfo@efirst.com
Remerciements
Nous remercions toute la communauté Kubernetes d’avoir
créé un logiciel de cette qualité. C’est une communauté de
haut niveau, à l’esprit ouvert et toujours prête à vous venir
en aide.
Problème
Vous voulez tester Kubernetes sans devoir l’installer
d’abord.
Solution
Rendez-vous sur le site de Katacoda
(https://www.katacoda.com/courses/kubernetes/play-
ground) qui constitue un terrain de jeu Kubernetes. Vous
devez vous authentifier auprès de GitHub ou d’un des
réseaux sociaux les plus répandus. Vous verrez alors
apparaître la page présentée en Figure 1.1.
Figure 1.1 : Vue générale du terrain de jeu Kubernetes de Katacoda.
https://kubernetes.io/fr/docs/tutorials/
Problème
Vous désirez installer l’interface sur ligne de commande de
Kubernetes pour interagir avec un cluster Kubernetes.
Solution
Vous disposez de trois solutions pour installer kubectl :
$ curl -LO
https://storage.googleapis.com/kubernetes-
release/release/ \
$(curl -s
https://storage.googleapis.com/kubernetes-
release/ \
release/stable.txt) \
/bin/linux/amd64/kubectl
$ chmod +x ./kubectl
Notez que l’outil curl doit être présent. S’il ne l’est pas, vous
l’installez par exemple avec sudo apt install curl.
$ which kubectl
/Users/sebgoa/google-cloud-sdk/bin/kubectl
$ kubectl version
Client Version: version.Info{Major:"1", \
Minor:"7", \
GitVersion:"v1.7.0",
\
GitCommit:"fff5156...", \
GitTreeState:"clean", \
BuildDate:"2017-03-
28T16:36:33Z", \
GoVersion:"go1.7.5",
\
Compiler:"gc", \
Platform:"darwin/amd64"}
...
Voir aussi
• Documentation d’installation de kubectl
(https://kubernetes.io/docs/tasks/kubectl/insta
ll/)
Installer Minikube pour utiliser
une instance locale de
Kubernetes
Problème
Vous voulez utiliser Kubernetes pour faire des tests, du
développement ou pour vous former sur votre machine
locale.
Solution
Utilisez Minikube qui permet d’accéder à Kubernetes depuis
une machine locale sans rien installer, sauf les binaires de
Minikube. Cet outil utilise un hyperviseur local (par exemple
VirtualBox ou KVM) pour lancer une machine virtuelle qui
exécute Kubernetes en mode simple. Vérifiez donc que vous
avez installé une machine virtuelle sur votre système.
$ chmod +x minikube
Discussion
Une fois que vous avez installé Minikube, vérifiez qu’il est
prêt à l’emploi en demandant son numéro de version :
$ minikube version
minikube version: v0.18.0
$ minikube start
Voir aussi
• Documentation de Minikube
(https://kubernetes.io/docs/getting-started-
guides/minikube/)
Problème
Vous avez besoin de tester votre application Kubernetes
localement avec Minikube pour en poursuivre le
développement. Vous avez bien sûr installé et démarré
Minikube (voir section « Installer Minikube pour utiliser
une instance locale de Kubernetes »). Vous avez besoin de
connaître quelques commandes pour simplifier votre
développement.
Solution
L’interface cliente Minikube propose un certain nombre de
commandes pour vous simplifier la vie ainsi qu’une aide
interne permettant de se remémorer les sous-commandes.
En voici un extrait :
$ minikube
...
Available Commands:
addons Modify minikube's kubernetes addons.
...
start Starts a local kubernetes cluster.
status Gets the status of a local kubernetes
cluster.
stop Stops a running local kubernetes
cluster.
version Print the version of minikube.
Discussion
Pour démarrer une machine virtuelle VM qui exécute
localement Kubernetes, vous utilisez la commande minikube
start. Sans mention contraire, elle réserve 2 Go de mémoire
vive. Vous ne devez pas oublier de les restituer au moyen de
la commande minikube stop. Pour réclamer un plus grand
espace mémoire pour la machine virtuelle et plus de
puissance CPU tout en choisissant la version de Kubernetes à
utiliser, procédez ainsi :
Problème
Vous avez démarré Minikube (voir section « Installer
Minikube pour utiliser une instance locale de Kubernetes »)
et vous voulez maintenant démarrer votre première
application dans Kubernetes.
Solution
En guise d’exemple, voyons comment démarrer la plate-
forme de microblogue Ghost (https://ghost.org) dans
Minikube. Deux commandes kubectl sont nécessaires :
Discussion
La commande run de kubectl est un générateur qui permet
de créer un objet de type Deployment (voir Chapitre 4). La
commande expose de kubectl est également un générateur,
sauf qu’elle permet de créer un objet de type Service (voir
Chapitre 5). Ce genre d’objet sert à router le trafic réseau
vers les conteneurs qui ont été démarrés par votre
déploiement.
Accéder au tableau de bord
Minikube
Problème
Dans Minikube, vous voulez visualiser le tableau de bord de
Kubernetes pour pouvoir démarrer votre application depuis
une interface utilisateur graphique.
Solution
Voici comment ouvrir le tableau de bord Kubernetes depuis
Minikube :
$ minikube dashboard
Discussion
Pour créer une application, utilisez dans le coin supérieur
droit le bouton Create puis attribuez un nom à l’application
et choisissez l’image Docker à utiliser. Cliquez ensuite le
bouton Deploy pour faire apparaître une fenêtre montrant
les déploiements et les jeux de réplication. Après quelques
instants, vous voyez apparaître un pod. (Nous décrirons
dans la suite du livre certaines primitives API essentielles.)
Problème
Vous voulez utiliser kubeadm pour amorcer (bootstrap) un
cluster Kubernetes à partir de zéro.
Solution
Vous téléchargez l’outil client kubeadm depuis le référentiel
du paquetage Kubernetes.
L’outil kubeadm doit être installé sur tous les serveurs qui
vont faire partie du cluster Kubernetes et pas seulement sur
le serveur maître, donc sur tous les nœuds.
• le binaire kubelet ;
Discussion
Une fois tous les binaires et outils installés, vous pouvez
commencer l’amorçage de votre cluster Kubernetes.
Procédez à l’initialisation du cluster sur le nœud maître
ainsi :
# kubeadm init
[kubeadm] WARNING: kubeadm is in beta, please do
not use it for production
clusters.
[init] Using Kubernetes version: v1.7.8
[init] Using Authorization modes: [Node RBAC]
[preflight] Running pre-flight checks
...
Voir aussi
• Utilisation de kubeadm pour créer un cluster
(https://kubernetes.io/docs/setup/independent/c
reate-cluster-kubeadm/)
Amorcer un cluster Kubernetes
avec kubeadm
Problème
Vous avez initialisé votre nœud maître Kubernetes (voir
section précédente). Vous devez maintenant ajouter des
nœuds travailleurs à ce cluster.
Solution
Le référentiel du paquetage Kubernetes doit avoir été
configuré et l’outil kubeadm installé, comme indiqué dans la
précédence section. Utilisez la commande join en lui
fournissant le jeton qui a été généré lors de l’étape
d’initialisation sur le nœud maître :
Discussion
La dernière étape consiste à créer un réseau conforme aux
contraintes réseau Kubernetes, notamment en attribuant
une seule adresse IP par pod. Servez-vous pour ce faire
d’une des extensions réseau disponibles (voir aussi
l’installation des extensions dans la documentation
Kubernetes). Vous pouvez par exemple installer l’outil
Weave Net sur un cluster Kubernetes à partir de la
version 1.6.0 avec une seule commande kubectl :
• Weaveworks
(https://www.weave.works/docs/net/latest/kube-
addon/)
Télécharger une version de
Kubernetes depuis GitHub
Problème
Vous avez besoin de télécharger une version officielle de
Kubernetes au lieu de la compiler à partir des fichiers de
code source.
Solution
Vous pouvez procéder manuellement en vous rendant sur la
page de diffusion des versions sur GitHub
(https://github.com/kubernetes/kubernetes/releases)
. Choisissez une version ou une préversion, puis choisissez le
paquet de fichiers à compiler ou bien le fichier portant le
nom kubernetes.tar.gz.
$ curl -s
https://api.github.com/repos/kubernetes/kubernet
es/releases | \
jq -r .[].assets[].browser_download_url
https://github.com/kubernetes/kubernetes/release
s/download/v1.9.0/kubernetes.tar.gz
https://github.com/kubernetes/kubernetes/release
s/download/v1.9.0-beta.2/kubernetes.tar.gz
https://github.com/kubernetes/kubernetes/release
s/download/v1.8.5/kubernetes.tar.gz
https://github.com/kubernetes/kubernetes/release
s/download/v1.9.0-beta.1/kubernetes.tar.gz
https://github.com/kubernetes/kubernetes/release
s/download/v1.7.11/kubernetes.tar.gz
...
$ wget
https://github.com/kubernetes/kubernetes/release
s/download/ \
v1.7.11/kubernetes.tar.gz
Problème
Vous avez téléchargé une archive de version (voir précédente
section), mais elle ne contient pas les fichiers binaires.
Solution
Pour éviter que les fichiers d’archive deviennent trop
volumineux, ils ne contiennent pas les fichiers binaires. Il
faut les télécharger dans un deuxième temps. Pour ce faire,
il suffit d’exécuter le script nommé get-kube-binaries.sh,
comme ceci :
$ tree ./client/bin
./client/bin
├── kubectl
└── kubefed
$ tree server/kubernetes/server/bin
server/kubernetes/server/bin
├── cloud-controller-manager
├── kube-apiserver
...
$ wget https://dl.k8s.io/v1.7.11/kubernetes-
client-linux-amd64.tar.gz
$ wget https://dl.k8s.io/v1.7.11/kubernetes-
server-linux-amd64.tar.gz
Utiliser une image hyperkube
pour exécuter un nœud maître
Kubernetes avec Docker
Problème
Vous avez besoin de créer un nœud maître Kubernetes avec
plusieurs conteneurs Docker. Vous avez besoin d’exécuter
dans les conteneurs le serveur API, le planificateur
scheduler, le contrôleur et le magasin de clés/valeurs etcd.
Solution
Vous pouvez vous appuyer sur un binaire hyperkube, ainsi
qu’un conteneur etcd. En effet, hyperkube est un binaire
complet qui est disponible sous forme d’une image Docker.
Vous pouvez vous en servir pour démarrer tous les processus
Kubernetes.
$ docker run -d \
--net=container:k8s \
gcr.io/google_containers/hyperkube:v1.7.11 \
/apiserver --etcd-
servers=http://127.0.0.1:2379 \
--service-cluster-ip-range=10.0.0.1/24 \
--insecure-bind-address=0.0.0.0 \
--insecure-port=8080 \
--admission-control=AlwaysAdmit
Il ne reste plus qu’à démarrer le contrôleur d’admission qui
va pointer vers le serveur API :
$ docker run -d \
--net=container:k8s \
gcr.io/google_containers/hyperkube:v1.7.11 \
/controller-manager --
master=127.0.0.1:8080
gcr.io/google_containers/hyperkube:v1.7.11 \
/apiserver --help
Discussion
Cette procédure est très pratique pour commencer à explorer
les différents composants de Kubernetes de façon locale,
mais elle est déconseillée dans une configuration destinée à
être mise en production.
Voir aussi
• Images Docker d’hyperkube
(https://github.com/kubernetes/kubernetes/tree/
master/cluster/images/hyperkube)
Écrire un fichier unité systemd
pour exécuter des composants
Kubernetes
Problème
Vous avez fait vos premiers pas avec Minikube (voir
Chapitre 1) et vous savez comment amorcer un cluster
Kubernetes avec kubeadm (voir la section « Amorcer un
cluster Kubernetes avec kubeadm »). Vous voulez
maintenant installer un cluster à partir de zéro. Il vous faut
exécuter les composants Kubernetes avec des fichiers
d’unité systemd. Vous n’avez pour l’instant besoin que d’un
exemple simple d’exécution de kubelet via systemd.
Solution
L’outil systemd sert à gérer des systèmes et des services ;
on parle parfois de système init. Il est devenu le système de
gestion de services par défaut sous Ubuntu 16.04 et
CentOS 7.
[Unit]
Description=kubelet: The Kubernetes Node Agent
Documentation=http://kubernetes.io/docs/
[Service]
ExecStart=/usr/bin/kubelet
Restart=always
StartLimitInterval=0
RestartSec=10
[Install]
WantedBy=multi-user.target
# ls -l /etc/kubernetes/manifests
total 16
-rw------- 1 root root 1071 Jun 13 08:29
etcd.yaml
-rw------- 1 root root 2086 Jun 13 08:29 kube-
apiserver.yaml
-rw------- 1 root root 1437 Jun 13 08:29 kube-
controller-manager.yaml
-rw------- 1 root root 857 Jun 13 08:29 kube-
scheduler.yaml
# cat /etc/kubernetes/manifests/etcd.yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
component: etcd
tier: control-plane
name: etcd
namespace: kube-system
spec:
containers:
- command:
- etcd
- --listen-client-urls=http://127.0.0.1:2379
- --advertise-client-urls=http://127.0.0.1:2379
- --data-dir=/var/lib/etcd
image:
gcr.io/google_containers/etcd-amd64:3.0.17
...
Voir aussi
• Options de configuration de kubelet
• freedesktop.org, « system »
Problème
Vous avez besoin de créer un cluster Kubernetes dans GKE
(Google Kubernetes Engine).
Solution
En utilisant l’interface sur ligne de commande gcloud, vous
créez un cluster Kubernetes au moyen de la commande
container clusters create :
Discussion
Pour pouvoir utiliser GKE, trois actions préalables sont
requises :
• création d’un compte sur la plate-forme Google Cloud
avec la facturation activée ;
...
COMMANDS
...
resize
Resizes an existing cluster for running
containers.
update
Update cluster settings for an existing
container cluster.
upgrade
Upgrade the Kubernetes version of an
existing container cluster.
Voir aussi
• Démarrage rapide de GKE
(https://cloud.google.com/container-
engine/docs/quicks-tart)
Problème
Vous avez besoin de créer un cluster Kubernetes sur Azure
Container Service (ACS).
Solution
Pour réaliser cette procédure, vous devez d’abord créer un
compte gratuit Azure (https://azure.microsoft.com/en-
us/free/) puis installer l’outil d’interface sur ligne de
commande az en
version 2.0 (https://docs.microsoft.com/en-
us/cli/azure/install-azure-cli).
$ az login
To sign in, use a web browser to open the page
https://aka.ms/devicelogin and
enter the code XXXXXXXXX to authenticate.
[
{
"cloudName": "AzureCloud",
"id": "****************************",
"isDefault": true,
"name": "Free Trial",
"state": "Enabled",
"tenantId": "*****************************",
"user": {
"name": "******@hotmail.com",
"type": "user"
}
}
]
$ kubectl cluster-info
Kubernetes master is running at https://k8scb-
k8s-143f1emgmt.northeurope.cloudapp
.azure.com
Heapster is running at https://k8scb-k8s-
143f1emgmt.northeurope.cloudapp.azure
.com/api/v1/namespaces/kube-
system/services/heapster/proxy
KubeDNS is running at https://k8scb-k8s-
143f1emgmt.northeurope.cloudapp.azure
.com/api/v1/namespaces/kube-
system/services/kube-dns/proxy
kubernetes-dashboard is running at
https://k8scb-k8s-143f1emgmt.northeurope
.cloudapp.azure.com/api/v1/namespaces/kube-
system/services/kubernetes-dashboard
/proxy
tiller-deploy is running at https://k8scb-k8s-
143f1emgmt.northeurope.cloudapp
.azure.com/api/v1/namespaces/kube-
system/services/tiller-deploy/proxy
To further debug and diagnose cluster problems,
use 'kubectl cluster-info dump'.
Voir aussi
• Dans la documentation de Microsoft Azure, la page
consacrée au déploiement de clusters Kubernetes pour
conteneurs Linux (https://docs.microsoft.com/en-
us/azure/contai-ner-
service/kubernetes/container-service-
kubernetes-walkthrough)
CHAPITRE 3
Apprendre à utiliser le client
Kubernetes
Problème
Vous voulez connaître la liste des ressources Kubernetes
d’un certain type.
Solution
Utilisez la commande get de kubectl en indiquant le type de
ressource. Voici comment lister tous les pods :
Problème
Certaines de vos ressources ne vous sont plus utiles et vous
voulez vous en débarrasser.
Solution
Utilisez la commande delete de kubectl en indiquant le
type et le nom de la ressource à supprimer.
$ kubectl get ns
NAME STATUS AGE
default Active 2d
kube-public Active 2d
kube-system Active 2d
my-app Active 20m
$ kubectl delete ns my-app
namespace "my-app" deleted
app=niceone :
Discussion
Interdisez-vous de supprimer des objets supervisés tels que
des pods contrôlés directement par un déploiement. Vous
devez soit supprimer les superviseurs, soit appliquer des
opérations spécifiques pour vous débarrasser des ressources
gérées. C’est ainsi que vous supprimez effectivement tous
les pods sur lesquels se fonde un déploiement si vous le
rétrécissez jusqu’à n’avoir que zéro réplica (ou réplique)
(voir le Chapitre 9).
Problème
Vous voulez surveiller les changements que subissent les
objets Kubernetes de façon interactive dans votre fenêtre de
terminal.
Solution
La commande kubectl dispose d’une option --watch prévue
dans ce sens. Voici par exemple comment placer les pods
sous surveillance :
top.
Discussion
Cette option --watch est pratique, mais pas toujours très
fiable en termes de réactualisation de l’affichage. Vous
pouvez dans ce cas utiliser plutôt la commande watch :
Problème
Vous avez besoin de modifier les propriétés d’une ressource
Kubernetes.
Solution
Servez-vous de la commande edit de l’outil kubectl en
indiquant le type de ressource :
Discussion
Si vous avez un souci au niveau de l’outil d’édition, utiliser
EDITOR=vi. Notez que toutes les modifications ne
déclenchent pas un déploiement.
Problème
Vous avez besoin de mieux connaître un certain type de
ressource, par exemple, services, ou bien de savoir à quoi
sert un champ, en particulier dans un manifeste Kubernetes,
avec par exemple un rappel des valeurs par défaut et du
statut obligatoire ou facultatif du champ.
Solution
Vous vous servez de la commande explain de kubectl :
FIELDS:
Status <Object>
Most recently observed status of the
service. Populated by the system. Read-only.
More
info:
https://git.k8s.io/community/contributors/devel/
api-conventions.md#spec-and-
status/
apiVersion <string>
APIVersion defines the versioned schema of
this representation of an object. Servers
should convert recognized schemas to the
latest internal value, and may reject
unrecognized values. More info:
https://git.k8s.io/community/contributors/devel/
api-
conventions.md#resources
kind <string>
Kind is a string value representing the
REST resource this object represents. Servers
may infer this from the endpoint the
client submits requests to. Cannot be updated.
In
CamelCase. More info:
https://git.k8s.io/community/contributors/devel/
api-conventions
.md#types-kinds
metadata <Object>
Standard object's metadata. More info:
https://git.k8s.io/community/contributors/devel/
api-conventions.md#metadata
spec <Object>
Spec defines the behavior of a service.
https://git.k8s.io/community/
contributors/devel/
api-conventions.md#spec-and-status/
DESCRIPTION:
externalIPs is a list of IP addresses for
which nodes in the cluster will also accept
traffic for this service. These IPs are
not managed by Kubernetes. The user is
responsible
for ensuring that traffic arrives at a
node with this IP. A common example is external
load-balancers that are not part of the
Kubernetes system.
Discussion
Cette commande explain extrait les descriptions des
ressources des champs à partir des définitions
Swagger/OpenAPI qui sont rendues accessibles par le
serveur API.
Voir aussi
• Article de blog de Ross Kukulinski « kubectl
explain — #HeptioProTip »
(https://blog.heptio.com/kubectl-explain-
heptioprotip-ee883992a243)
Problème
Vous avez besoin de lancer rapidement une application à
longue durée de vie, par exemple un serveur Web.
Solution
Utilisez la commande kubectl run qui est un générateur
permettant de créer un manifeste de déploiement de façon
impromptue. Voici par exemple comment créer un
déploiement pour démarrer la plate-forme de micro-
blogging Ghost :
Discussion
La commande run accepte un certain nombre de paramètres
pour configurer les déploiements. En voici quelques-uns :
Problème
Au lieu de créer un objet avec un générateur tel que cubectl
run, vous voulez définir ses propriétés, puis le créer.
Solution
Utilisez la commande kubectl create ainsi :
apiVersion: v1
kind: Namespace
metadata:
name: myns
Discussion
Vous pouvez indiquer pour l’option -f une adresse URL ou
un chemin d’accès à un fichier de votre système local. Voici
par exemple comment créer la partie frontale de
l’application canonique Guestbook. Nous récupérons d’abord
l’adresse URL du fichier brut YAML qui définit l’application
dans un seul fichier manifeste et nous pouvons ensuite
saisir la commande suivante :
$ kubectl create -f
https://raw.githubusercontent.com/kubernetes/kub
ernetes/ \
master/examples/guestbook/frontend-
deployment.yaml
Rédiger un manifeste de pod
Problème
Vous voulez écrire le contenu d’un fichier manifeste de pod
sans utiliser de générateur tel que kubectl run.
Solution
Un pod correspond à un objet /api/v1. Comme tous les
autres objets de Kubernetes, son fichier manifeste contient
les champs suivants :
apiVersion: v1
kind: Pod
metadata:
name: oreilly
spec:
containers:
- name: oreilly
image: nginx
Discussion
La spécification API d’un pod peut être bien plus riche que
ce que nous avons montré comme solution. Un pod peut par
exemple contenir plusieurs conteneurs, comme ceci :
apiVersion: v1
kind: Pod
metadata:
name: oreilly
spec:
containers:
- name: oreilly
image: nginx
- name: safari
image: redis
Voir aussi
• La documentation de référence des pods de Kubernetes
(https://kubernetes.io/docs/api-
reference/v1.7/#pod-v1-core)
• La documentation de ReplicaSet
(https://kubernetes.io/docs/concepts/workloads/
controllers/replicaset/)
Lancer un déploiement via un
manifeste
Problème
Vous voulez jouir d’un contrôle complet de la façon dont une
application à longue durée de vie est lancée puis supervisée.
Solution
Rédigez un manifeste stipulant un objet Deployment.
Revenez à la précédente section pour les grands principes de
ce genre de fichier.
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: fancyapp
spec:
replicas: 5
template:
metadata:
labels:
app: fancy
env: development
spec:
containers:
- name: sise
image: mhausenblas/simpleservice:0.5.0
ports:
- containerPort: 9876
env:
- name: SIMPLE_SERVICE_VERSION
value: "0.9"
$ kubectl get rs
NAME DESIRED CURRENT READY AGE
fancyapp-1223770997 5 5 0 13s
$ kubectl get po
NAME READY STATUS
RESTARTS AGE
fancyapp-1223770997-18msl 0/1
ContainerCreating 0 15s
fancyapp-1223770997-1zdg4 0/1
ContainerCreating 0 15s
fancyapp-1223770997-6rqn2 0/1
ContainerCreating 0 15s
fancyapp-1223770997-7bnbh 0/1
ContainerCreating 0 15s
fancyapp-1223770997-qxg4v 0/1
ContainerCreating 0 15s
Discussion
Le déploiement tient le rôle de superviseur pour les pods et
les jeux de réplicas (RS). Vous contrôlez précisément quand
et comment chaque nouvelle version de pod est publiée ou
rétrogradée à une version antérieure. Les jeux RS et les pods
qui sont ainsi supervisés n’ont en général aucun intérêt pour
vous, sauf si vous avez besoin de déboguer un pod (voir
Chapitre 12). La Figure 4.1 montre comment avancer et
reculer parmi les différentes révisions d’un déploiement.
Voir aussi
• Documentation des déploiements de Kubernetes
(https://kubernetes.io/docs/concepts/workloads/
controllers/deployment/)
Actualiser un déploiement
Problème
Vous utilisez un déploiement et désirez déployer une
nouvelle version de l’application.
Solution
Mettez à jour le déploiement, puis laissez la stratégie de
mise à jour par défaut nommée RollingUpdate réaliser
automatiquement le rollout.
...
ports:
- containerPort: 9876
...
Que faire si vous constatez que vous avez fait une erreur ou
détecté des problèmes avec la nouvelle version publiée ?
Kubernetes permet facilement de régresser pour retrouver
un état stable et connu au moyen de la commande kubectl
rollout undo. Supposons que la dernière retouche était une
erreur et que vous vouliez revenir en révision 2 :
Problème
Vous avez besoin de mettre en place un mécanisme stable et
fiable permettant de détecter et d’accéder à votre application
dans le cluster.
Solution
Créez un service Kubernetes pour les pods qui vont
supporter l’application.
Discussion
Pour accéder à ce service depuis votre navigateur, vous
démarrez un proxy dans une autre session de terminal,
comme ceci :
$ kubectl proxy
Starting to serve on 127.0.0.1:8001
Vous pouvez ensuite ouvrir votre navigateur sur l’adresse
suivante :
$ open
http://localhost:8001/api/v1/proxy/namespaces/de
fault/services/nginx/
apiVersion: v1
kind: Service
metadata:
name: nginx
spec:
selector:
run: nginx
ports:
- port: 80
Voir aussi
• Documentation des services de Kubernetes
(https://kubernetes.io/docs/concepts/services-
networking/service)
Problème
Vous avez créé (voir la section précédente) un service et vous
désirez maintenant vérifier que votre inscription DNS est
correcte.
Solution
Par défaut, le type de service utilisé par Kubernetes est
ClusterIP. Cela permet d’exposer le service sur une adresse
IP interne au cluster. Si l’extension de cluster DNS est
disponible et fonctionne correctement, vous pouvez alors
accéder au service au moyen d’un nom de domaine
totalement qualifié FQDN (Fully Qualified Domain Name) en
utilisant la syntaxe suivante :
$SERVICENAME.$NAMESPACE.svc.cluster.local
/ # nslookup nginx
Server: 10.96.0.10
Address 1: 10.96.0.10 kube-dns.kube-
system.svc.cluster.local
Name: nginx
Address 1: 10.109.24.56
nginx.default.svc.cluster.local
Problème
Vous avez défini un service, par exemple de type ClusterIP
comme vu dans la précédente section. Vous voulez changer
son type, afin de pouvoir exposer votre application en tant
que NodePort ou en utilisant un équilibreur de charge d’un
fournisseur de cloud, donc avec le type de service
LoadBalancer.
Solution
Pour changer le type de service, vous vous servez de votre
éditeur préféré avec la commande kubectl edit. Supposons
que vous disposiez d’un fichier manifeste portant le nom
simple-nginx-svc.yaml avec le contenu suivant :
kind: Service
apiVersion: v1
metadata:
name: webserver
spec:
ports:
- port: 80
selector:
app: nginx
Problème
Vous voulez déployer un contrôleur d’entrée réseau Ingress
sur Minikube pour gérer des objets Ingress. Ce genre
d’objet vous intéressera dès que vous aurez besoin de
fournir un accès à vos applications s’exécutant dans
Kubernetes depuis l’extérieur du cluster Kubernetes. Pour
autant, vous ne voulez pas créer un service de type NodePort
ou LoadBalancer.
Solution
Pour qu’un objet Ingress (décrit dans la section suivante)
fasse effet en fournissant une route depuis l’extérieur d’un
cluster vers vos pods, il faut déployer un contrôleur Ingress.
kube-system :
Voir aussi
• Documentation concernant les objets Ingress
(https://kubernetes.io/docs/concepts/services-
networking/ingress/)
• Contrôleur Ingress basé nginx
(https://github.com/kubernetes/ingress-
nginx/blob/master/README.md)
Rendre des services accessibles
de l’extérieur du cluster
Problème
Vous avez besoin d’accéder à un service Kubernetes de
l’extérieur du cluster.
Solution
Utilisez un contrôleur Ingress (voir précédente section).
Vous le configurez en créant des objets Ingress. L’exemple
qui suit montre le manifeste d’une règle Ingress qui permet
de configurer un chemin d’accès à un service nginx :
$ cat nginx-ingress.yaml
kind: Ingress
apiVersion:
extensions/v1beta1
metadata:
name: nginx-
public
annotations:
ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host:
http:
paths:
- path: /web
backend:
serviceName: nginx
servicePort: 80
Vous pouvez voir l’objet Ingress que vous avez créé pour
nginx dans le tableau de bord Kubernetes (Figure 5.3).
$ curl -k https://192.168.99.100/web
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
body {
width: 35em;
margin: 0 auto;
font-family: Tahoma, Verdana, Arial,
sans-serif;
}
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is
successfully installed and
working. Further configuration is required.</p>
Discussion
Le fonctionnement général d’un service Ingress correspond
au diagramme de la Figure 5.4 : le contrôleur Ingress écoute
le point d’extrémité /ingresses du serveur API pour
découvrir les nouvelles règles. Il configure ensuite les routes
pour que le trafic externe arrive sur un service spécifique
interne au cluster, dans l’exemple, il s’agit de service1 sur
le port 9876.
Figure 5.4 : Concept général des entrées réseau Ingress.
Voir aussi
• Le référentiel GitHub pour Kubernetes/ingress-nginx
(https://github.com/kubernetes/ingress)
Problème
Vous voulez connaître les différents points d’extrémité
(endpoints) API disponibles sur un serveur API Kubernetes.
Solution
Si vous avez accès à ce serveur API par un port privé sans
authentification, vous pouvez directement émettre une
requête HTTP vers le serveur API pour découvrir les points
d’extrémité. Vous pouvez par exemple, avec Minikube,
accéder via SSH à la machine virtuelle (minikube ssh) pour
vous connecter au serveur API sur le port 8080, comme
ceci :
$ curl localhost:8080/api/v1
...
{
"name": "pods",
"namespaced": true,
"kind": "Pod",
"verbs": [
"create",
"delete",
"deletecollection",
"get",
"list",
"patch",
"proxy",
"update",
"watch"
],
"shortNames": [
"po"
]
},
...
$ curl localhost:8001/foobar
Le chemin API /foobar permet donc de dresser la liste de tous
les points d’extrémité API. Précisons que les deux options --
port et --api-prefix sont facultatives.
Discussion
Dans votre découverte des points d’extrémité API, vous allez
par exemple voir apparaître ceux-ci :
• /api/v1
• /apis/apps
• /apis/authentication.k8s.io
• /apis/authorization.k8s.io
• /apis/autoscaling
• /apis/batch
Voir aussi
• Principes des objets Kubernetes
(https://kubernetes.io/docs/concepts/overview/w
or-king-with-objects/kubernetes-objects/)
Problème
Kubernetes propose plusieurs générateurs de manifeste
(kubectl run, kubectl create), mais il n’est pas inutile
d’apprendre à rédiger un manifeste Kubernetes pour
exprimer les spécifications des objets. Pour y parvenir, il
faut connaître la structure d’un manifeste Kubernetes.
Solution
Nous avons découvert les différents groupes API dans la
section précédente et vu comment savoir à quel groupe
appartient chaque objet.
Toutes les ressources API sont soient des objets, soit des
listes. Chaque ressource est dotée d’un paramètre kind et
d’un paramètre apiVersion. De plus, chaque paramètre
kind doit posséder un bloc metadata qui contient le nom
de l’objet, son espace de noms (voir prochaine section) et
éventuellement quelques labels ou étiquettes (voir section
« Utiliser des labels dans des requêtes »), ainsi que des
annotations (voir section « Ajouter une annotation et une
ressource »).
apiVersion: v1
kind: Pod
metadata:
name: mypod
...
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
...
status
...
Voir aussi
• Principe des objets Kubernetes
(https://kubernetes.io/docs/concepts/overview/w
or-king-with-objects/kubernetes-objects/)
Créer un espace de noms pour
éviter les collisions
Problème
Vous voulez créer deux objets homonymes, tout en évitant
un conflit de noms.
Solution
Vous créez deux espaces de noms puis placez un objet dans
chaque espace.
$ kubectl get ns
NAME STATUS AGE
default Active 30s
my-app Active 1s
kube-public Active 29s
kube-system Active 30s
apiVersion: v1
kind: Namespace
metadata:
name: my-app
Discussion
Dès que vous tentez de créer deux objets homonymes dans le
même espace de noms, par exemple dans default, vous
provoquez une collision, ce qui est sanctionné par une erreur
émise par le serveur API de Kubernetes. Si vous démarrez le
second objet dans un autre espace de noms, le serveur API
accepte de le créer :
Problème
Vous désirez poser une limite au volume de ressources
disponible dans le même espace de noms, par exemple pour
restreindre le nombre de pods pouvant être exécutés dans
cet espace.
Solution
Il suffit de définir un objet ResourceQuota pour poser une
limite pour un espace de noms :
$ cat resource-quota-pods.yaml
apiVersion: v1
kind: ResourceQuota
metadata:
name: podquota
spec:
hard:
pods: "10"
Voici comment exploiter ce fichier :
Discussion
Vous pouvez définir plusieurs quotas par espace de noms, et
notamment le nombre de pods, de secrets et de mappes de
configuration.
Voir aussi
• Configuration des quotas des objets API
(https://kubernetes.io/docs/tasks/adminis-ter-
cluster/quota-api-object/)
Étiqueter un objet avec un label
Problème
Vous voulez marquer un objet avec un label pour pouvoir le
retrouver facilement. Ce label ou cette étiquette permettra
d’appliquer des requêtes d’utilisateur (voir section « Utiliser
des labels dans des requêtes ») ou de servir dans le contexte
d’une automatisation système.
Solution
Vous vous servez de la commande kubectl label. Voici
comment donner à un pod nommé foobar la paire
clé/valeur tier=frontend :
Discussion
Les labels ou étiquettes de Kubernetes permettent de gérer
les objets de façon souple et non hiérarchisée. Chaque label
est incarné par une paire clé/valeur qui n’a pas de
signification particulière pour Kubernetes. (Le contenu
d’une telle paire n’est pas interprété par le système.) Les
labels servent à exprimer une appartenance (par exemple,
l’objet X appartient au département ABC), pour décrire un
environnement (par exemple, tel service est utilisé en
production) ou tout autre besoin de description d’objet.
Précisons qu’il y a des limites à la longueur des labels et aux
valeurs autorisées.
Voir aussi
• Labels et sélecteurs
(https://kubernetes.io/docs/concepts/overview/w
orking-with-ob-jects/labels/#syntax-and-
character-set)
Utiliser des labels dans des
requêtes
Problème
Vous avez besoin d’interroger des objets de façon efficace.
Solution
Servez-vous de la commande kubectl get --selector.
Partons de la série de pods suivante :
(app=cockroachdb) :
Discussion
Le label d’un objet fait partie de ses métadonnées et tout
objet Kubernetes peut recevoir un label. Les labels sont
utilisés par le noyau Kubernetes pour sélectionner les pods
et les déploiements (voir Chapitre 4) et les services (voir le
Chapitre 5).
apiVersion: v1
kind: Pod
metadata:
name: foobar
labels:
tier: frontend
...
Une fois que les labels sont définis, vous pouvez en obtenir
la liste avec kubectl get. Tenez compte des précisions
suivantes :
Voir aussi
• Documentation des labels Kubernetes
(https://kubernetes.io/docs/concepts/overview/w
orking-with-objects/labels/)
Ajouter une annotation et une
ressource
Problème
Vous aimeriez annoter une ressource en fournissant une
paire clé/valeur générique, éventuellement avec des données
non visibles par les humains.
Solution
Servez-vous de la commande kubectl annotate :
Discussion
Les annotations permettent d’augmenter les possibilités
d’automatisation dans Kubernetes. Lorsque vous créez un
déploiement avec la commande kubectl run mais oubliez
d’utiliser l’option --record, la colonne CHANGE-CAUSE de
l’historique du déploiement reste vide (voir le Chapitre 4).
Pour garder une trace des commandes qui ont un effet sur le
déploiement, vous pouvez les annoter en injectant la clé
kubernetes.io/change-cause. En supposant un
déploiement nommé foobar, nous pouvons l’annoter ainsi :
Problème
Vous avez besoin de lancer l’exécution d’un processus à
durée d’exécution limitée, par exemple une conversion en
masse, une opération de sauvegarde ou une mise à jour d’un
schéma de base de données.
Solution
Vous utilisez une ressource Kubernetes de type Job pour
lancer puis superviser le pod qui va réaliser les traitements
du processus par lot.
apiVersion: batch/v1
kind: Job
metadata:
name: counter
spec:
template:
metadata:
name: counter
spec:
containers:
- name: counter
image: busybox
command:
- "sh"
- "-c"
- "for i in 1 2 3 ; do echo $i ; done"
restartPolicy: Never
Voir aussi
• Achèvement d’exécution des jobs
(https://kubernetes.io/docs/concepts/workloads/
controllers/jobs-run-to-completion/)
Exécuter une tâche planifiée
dans un pod
Problème
Vous avez besoin de faire exécuter une tâche à un moment
précis au sein d’un pod géré par Kubernetes.
Solution
Servez-vous d’un objet Kubernetes de type CronJob. Il s’agit
d’une variante spécialisée de l’objet générique Job (voir
section précédente).
Voir aussi
• Documentation de CronJob
(https://kubernetes.io/docs/concepts/workloads/
control-lers/cron-jobs/)
Démarrer un démon
d’infrastructure par nœud
Problème
Vous voulez démarrer un démon d’infrastructure, tel qu’un
collecteur de logs ou un agent de supervision, en
garantissant qu’un et un seul code s’exécute par nœud.
Solution
Pour démarrer et superviser le processus démon, vous
utilisez un composant DaemonSet. Voici par exemple
comment démarrer un agent FluentD sur chaque nœud du
cluster. Vous créez un fichier avec le contenu suivant et
portant le nom fluentd-daemonset.yaml :
kind: DaemonSet
apiVersion: extensions/v1beta1
metadata:
name: fluentd
spec:
template:
metadata:
labels:
app: fluentd
name: fluentd
spec:
containers:
- name: fluentd
image: gcr.io/google_containers/fluentd-
elasticsearch:1.3
env:
- name: FLUENTD_ARGS
value: -qq
volumeMounts:
- name: varlog
mountPath: /varlog
- name: containers
mountPath: /var/lib/docker/containers
volumes:
- hostPath:
path: /var/log
name: varlog
- hostPath:
path: /var/lib/docker/containers
name: containers
$ kubectl get ds
NAME DESIRED CURRENT READY UP-TO-DATE
AVAILABLE NODE-SELECTOR AGE
fluentd 1 1 1 1 1
<none> 17s
Discussion
L’affichage précédent est le résultat du lancement de la
commande dans Minikube. C’est la raison pour laquelle vous
ne voyez qu’un pod dans cette configuration. Si vous
aviez 15 nœuds dans le cluster, vous verriez 15 pods, à raison
d’un pod par nœud. Vous pouvez limiter le démon à certains
nœuds au moyen d’une section nodeSelector dans la partie
spec du manifeste de DaemonSet.
Gérer des applications Stateful
et leader/suiveur
Problème
Votre application doit pouvoir s’appuyer sur des pods ayant
des caractéristiques différentes ; par exemple, une base de
données pourra être exploitée par un meneur (leader) qui
permet les lectures et les écritures, accompagné de plusieurs
suiveurs (followers), qui n’assurent que les lectures. Vous ne
pouvez pas utiliser de déploiement dans cette situation
parce qu’un déploiement ne permet de superviser que des
pods identiques. Il vous faut néanmoins un superviseur
capable de gérer un ensemble de pods, un peu comme
plusieurs espèces d’animaux domestiques en cohabitation et
non comme un troupeau.
Solution
Servez-vous d’un composant StatefulSet, qui permet de
définir des charges de travail avec des noms réseau
différents, un déploiement, une mise à l’échelle et une fin
policées et/ou un stockage persistant. Par exemple, pour
exploiter un entrepôt de données redimensionnable très
populaire CockroachDB, vous pouvez vous inspirer de
l’exemple qui suit. Cet exemple définit dans son noyau le
composant StatefulSet suivant :
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
name: cockroachdb
spec:
serviceName: "cockroachdb"
replicas: 3
template:
metadata:
labels:
app: cockroachdb
spec:
initContainers:
- name: bootstrap
image: cockroachdb/cockroach-k8s-init:0.2
imagePullPolicy: IfNotPresent
args:
- "-on-start=/on-start.sh"
- "-service=cockroachdb"
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
volumeMounts:
- name: datadir
mountPath: "/cockroach/cockroach-data"
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- cockroachdb
topologyKey: kubernetes.io/hostname
containers:
- name: cockroachdb
image: cockroachdb/cockroach:v1.0.3
imagePullPolicy: IfNotPresent
ports:
- containerPort: 26257
name: grpc
- containerPort: 8080
name: http
volumeMounts:
- name: datadir
mountPath: /cockroach/cockroach-data
command:
- "/bin/bash"
- "-ecx"
- |
if [ ! "$(hostname)" == "cockroachdb-0" ]
|| \
[ -e "/cockroach/cockroach-
data/cluster_exists_marker" ]
then
CRARGS+=("--join" "cockroachdb-public")
fi
exec /cockroach/cockroach ${CRARGS[*]}
terminationGracePeriodSeconds: 60
volumes:
- name: datadir
persistentVolumeClaim:
claimName: datadir
volumeClaimTemplates:
- metadata:
name: datadir
annotations:
volume.alpha.kubernetes.io/storage-class:
anything
spec:
accessModes:
- "ReadWriteOnce"
resources:
requests:
storage: 1Gi
https://raw.githubusercontent.com/kubernetes/kub
ernetes/master/ \
examples/cockroachdb/cockroachdb-
statefulset.yaml
$ curl -s -o crex.sh \
https://raw.githubusercontent.com/kubernetes/kub
ernetes/master/ \
examples/cockroachdb/minikube.sh
$ ./crex.sh
+ kubectl delete
statefulsets,persistentvolumes,persistentvolumec
laims,services...
...
+ kubectl create -f -
persistentvolumeclaim "datadir-cockroachdb-3"
created
+ kubectl create -f cockroachdb-statefulset.yaml
service "cockroachdb-public" created
service "cockroachdb" created
poddisruptionbudget "cockroachdb-budget" created
statefulset "cockroachdb" created
Discussion
L’ancien nom dans Kubernetes pour les objets StatefulSet
était PetSet (ensemble d’animaux domestiques), ce qui
vous donne une idée de la motivation initiale. À partir de
Kubernetes 1.7, StatefulSet est devenu une caractéristique
bêta, ce qui signifie que l’interface API n’allait plus changer
à ce niveau (seules des retouches de l’interface utilisateur
pourraient ensuite apparaître.) Un objet StatefulSet
incarne un contrôleur qui distribue des identités uniques aux
pods qu’il supervise. Précisons que par sécurité la
suppression d’un objet StatefulSet n’entraîne pas
automatiquement la suppression des volumes qui lui sont
associés.
Voir aussi
• Principes de StatefulSet
(https://kubernetes.io/docs/tutorials/stateful-
applica-tion/basic-stateful-set/)
Problème
Un de vos pods a besoin de la présence d’un autre service
pour fonctionner correctement.
Solution
Vous influencez le comportement au démarrage d’un pod au
moyen d’un conteneur init.
kind: Deployment
apiVersion: apps/v1beta1
metadata:
name: nginx
spec:
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: webserver
image: nginx
ports:
- containerPort: 80
initContainers:
- name: checkbackend
image: busybox
command: ['sh', '-c', 'until
nslookup backend.default.svc; do echo "Waiting
for
backend to come up"; sleep 3; done; echo
"Backend is up, ready to launch web server"']
$ kubectl get po
NAME READY STATUS RESTARTS AGE
backend-853383893-2g0gs 1/1 Running 0 43m
nginx-2101406530-jwghn 1/1 Running 0 10m
$ kubectl logs nginx-2101406530-jwghn -c
checkbackend
Server: 10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-
system.svc.cluster.local
Name: backend.default.svc
Address 1: 10.0.0.46
backend.default.svc.cluster.local
Backend is up, ready to launch web server
Problème
Vous utilisez un pod avec au moins deux conteneurs et
voulez pouvoir échanger des données en utilisant des
opérations du système de fichiers.
Solution
Créez un volume local de type emptyDir.
apiVersion: v1
kind: Pod
metadata:
name: sharevol
spec:
containers:
- name: c1
image: centos:7
command:
- "bin/bash"
- "-c"
- "sleep 10000"
volumeMounts:
- name: xchange
mountPath: "/tmp/xchange"
- name: c2
image: centos:7
command:
- "bin/bash"
- "-c"
- "sleep 10000"
volumeMounts:
- name: xchange
mountPath: "/tmp/data"
volumes:
- name: xchange
emptyDir: {}
Discussion
Le volume local est supporté par le nœud dans lequel
s’exécutent le code et ses conteneurs. Si ce nœud s’arrête,
ou si vous devez en assurer la maintenance (voir
Chapitre 12), le volume local se volatilise et toutes les
données sont perdues.
Voir aussi
• Documentation concernant les volumes Kubernetes
(https://kubernetes.io/docs/concepts/storage/vo
lumes/)
Passage d’une clé d’accès API à
un pod via un secret
Problème
Vous êtes administrateur et avez besoin de rendre disponible
aux développeurs une clé d’accès API de façon sécurisée,
c’est-à-dire sans la transmettre en clair dans vos
manifestes Kubernetes.
Solutions
Utilisez un volume local du type secret.
Type: Opaque
Data
====
passphrase: 13 bytes
apiVersion: v1
kind: Pod
metadata:
name: ppconsumer
spec:
containers:
- name: shell
image: busybox
command:
- "sh"
- "-c"
- "mount | grep access && sleep 3600"
volumeMounts:
- name: passphrase
mountPath: "/tmp/access"
readOnly: true
volumes:
- name: passphrase
secret:
secretName: pp
/ # cat /tmp/access/passphrase
ouvrir sesame
Discussion
Les secrets n’existent que dans le contexte d’un espace de
noms. Il faut en tenir compte pour les configurer et les
utiliser.
Voir aussi
• Documentation Kubernetes sur les secrets
(https://kubernetes.io/docs/concepts/confi-
guration/secret/)
Problème
Vous avez besoin de fournir des données de configuration à
une application sans devoir les stocker dans l’image de
conteneur, ni les écrire en dur dans la spécification du pod.
Solution
Utilisez une mappe de configuration. C’est une ressource
Kubernetes de première classe qui permet de fournir des
données de configuration à un pod en utilisant des variables
d’environnement ou un fichier.
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: cmapp
spec:
replicas: 1
template:
metadata:
labels:
app: cmapp
spec:
containers:
- name: sise
image:
mhausenblas/simpleservice:0.5.0
ports:
- containerPort: 9876
env:
- name:
SIMPLE_SERVICE_VERSION
valueFrom:
configMapKeyRef:
name: siseconfig
key: siseversion
Cette première approche permet de transmettre la
configuration dans une variable d’environnement. Voyons
maintenant comment monter la configuration en tant que
fichier dans le pod, en utilisant un volume.
debug: true
home: ⁓/abc
apiVersion: v1
kind: Pod
metadata:
name: oreilly
spec:
containers:
- image: busybox
command:
- sleep
- "3600"
volumeMounts:
- mountPath: /oreilly
name: oreilly
volumes:
- name:
configMap:
name: configfile
Une fois que vous avez créé le pod, vous pouvez vérifier que
le fichier nommé example.cfg y a bien été inséré :
Voir aussi
• Configuration d’un pod pour utiliser une mappe de
configuration
(https://kubernetes.io/docs/tasks/configure-
pod-container/configure-pod-configmap/)
Utiliser un volume persistant
avec Minikube
Problème
Vous ne voulez pas que les données stockées sur un disque
utilisé par le conteneur soient perdues lors du redémarrage
du pod qui héberge ce conteneur.
Solution
Utilisez un volume persistant PV (Persistant Volume). Si vous
utilisez Minikube, vous créez un tel volume comme étant de
type hostPath et vous le montez comme un volume
classique dans le système de fichiers du conteneur.
kind: PersistentVolume
apiVersion: v1
metadata:
name: hostpathpv
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/tmp/pvdata"
$ minikube ssh
$ cat /tmp/pvdata/index.html
Ce contenu persiste et signe
$ exit
Une fois le répertoire préparé sur le nœud, vous pouvez
créer le volume à partir du fichier manifeste hostpath-
pv.yaml :
$ kubectl get pv
NAME CAPACITY ACCESSMODES RECLAIMPOLICY
STATUS ... ... ...
hostpathpv 1Gi RWO Retain
Available ... ... ...
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: mypvc
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 200Mi
$ kubectl get pv
NAME CAPACITY ACCESSMODES ... STATUS
CLAIM STORAGECLASS
hostpathpv 1Gi RWO ... Bound
default/mypvc manual
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: nginx-with-pv
spec:
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: webserver
image: nginx
ports:
- containerPort: 80
volumeMounts:
- mountPath:
"/usr/share/nginx/html"
name: webservercontent
volumes:
- name: webservercontent
persistentVolumeClaim:
claimName: mypvc
$ curl -k -s https://192.168.99.100/web
Ce contenu persiste et signe
Discussion
Notre solution utilisait le type hostPath pour le volume
persistant. Dans un environnement de production, vous ne
procéderez pas ainsi. Vous demanderez à votre
administrateur de cluster de provisionner un volume réseau
supporté par NFS ou un volume EBS d’Amazon afin de
garantir que les données vont survivre aux pannes d’un
nœud.
Voir aussi
• Documentation des volumes persistants de Kubernetes
(https://kubernetes.io/docs/concepts/storage/pe
rsistent-volumes/)
Problème
Vous voulez utiliser Minikube pour découvrir comment
déployer une application avec conservation d’état dans
Kubernetes. Cela correspond par exemple au déploiement
d’une base de données MySQL.
Solution
Utilisez un objet de type volume persistant PV (voir la
précédente section) dans la définition du pod ou dans le
modèle de la base de données.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
$ kubectl get pv
NAME CAPACITY
... ... ... ... ...
pvc-da58c85c-e29a-11e7-ac0b-080027fcc0e7 1Gi
... ... ... ... ...
apiVersion: v1
kind: Pod
metadata:
name: db
spec:
containers:
- image: mysql:5.5
name: db
volumeMounts:
- mountPath: /var/lib/mysql
name: data
env:
- name: MYSQL_ROOT_PASSWORD
value: root
volumes:
- name: data
persistentVolumeClaim:
claimName: data
Discussion
Dès le départ, Minikube est configuré avec une classe de
stockage par défaut qui définit un mécanisme
d’approvisionnement de volumes persistants. De ce fait, lors
de la création d’une réclamation de volume persistant,
Kubernetes crée de façon dynamique un volume persistant
correspondant pour répondre à la demande.
C’est ce qui s’est produit dans notre solution. Dès que vous
avez créé le PVC nommé data, Kubernetes a créé un volume
PV approprié. Si vous étudiez plus en détail la classe de
stockage par défaut de Minikube, vous pouvez voir le type
d’approvisionneur :
$ kubectl get pv
NAME
CAPACITY ... CLAIM ...
pvc-da58c85c-e29a-11e7-ac0b-080027fcc0e7 1Gi
... default/foobar ...
$ kubectl get pv pvc-da58c85c-e29a-11e7-ac0b-
080027fcc0e7 -o yaml
apiVersion: v1
kind: PersistentVolume
...
hostPath:
path: /tmp/hostpath-provisioner/pvc-da58c85c-
e29a-11e7-ac0b-080027fcc0e7
type: ""
...
$ minikube ssh
_ _
_ _ ( ) ( )
___ ___ (_) ___ (_)| |/') _ _ | |_ __
/' _ ' _ '\| |/' _ '\| || , < ( ) ( )| '_'\
/'__'\
| ( ) ( ) || || ( ) || || |\'\ | (_) || |_) )(
___/
(_) (_) (_)(_)(_) (_)(_)(_)
(_)'\___/'(_,__/''\____)
$ ls -l /tmp/hostpath-provisioner/pvc-da58c85c-
e29a-11e7-ac0b-080027fcc0e7
total 28688
-rw-rw---- 1 999 999 2 Dec 16 20:02
data.pid
-rw-rw---- 1 999 999 5242880 Dec 16 20:02
ib_logfile0
-rw-rw---- 1 999 999 5242880 Dec 16 20:02
ib_logfile1
-rw-rw---- 1 999 999 18874368 Dec 16 20:02
ibdata1
drwx------ 2 999 999 4096 Dec 16 20:02 mysql
drwx------ 2 999 999 4096 Dec 16 20:03
oreilly
drwx------ 2 999 999 4096 Dec 16 20:02
performance_schema
Voir aussi
• Documentation des volumes persistants de Kubernetes
(https://kubernetes.io/docs/concepts/storage/pe
rsistent-volumes/#persistentvolumeclaims)
Problème
Au lieu d’approvisionner manuellement des volumes
persistants avec des actions de réclamation PVC (voir la
précédente section), vous voulez automatiser le processus
pour approvisionner les volumes PV de façon dynamique en
fonction d’exigences de volume ou de facturation.
Solution
Pour le cas spécifique de Google GKE, vous suivrez la
procédure décrite dans l’article de blog de Saad Ali
« Dynamic Provisioning and Storage Classes in Kubernetes »
(http://blog.kubernetes.io/2016/10/dynamic-
provisioning-and-storage-in-kubernetes.html).
Discussion
La logique générale d’approvisionnement et de réclamation
de volumes persistants est illustrée dans la Figure 8.2.
Figure 8.2 : Logique d’approvisionnement et de réclamation de volumes persistants.
—
VPA (Vertical Pod Autoscaler) : augmente ou
diminue les demandes de ressources des
conteneurs qui s’exécutent dans un pod. Ce
mécanisme vertical VBA est encore en cours de
développement et nous ne le décrirons pas ici.
Pour en savoir plus, vous pouvez parcourir un
article de l’auteur Michael à propos des
ressources de conteneurs
(https://hackernoon.com/container-
resource-consumption-too-impor-tant-to-
ignore-7484609a3bb7).
Problème
Vous avez besoin de rendre un déploiement adaptable à la
charge dans le sens horizontal, donc en faisant varier le
nombre de réplicas.
Solution
Pour adapter un déploiement à une augmentation de charge,
vous utilisez la commande kubectl scale.
Problème
Vous voulez que votre cluster Google GKE adapte
automatiquement sa géométrie en termes de nombre de
nœuds selon la charge.
Solution
Utilisez le mécanisme de GKE Cluster Autoscaler. Dans cette
section, nous supposons que vous avez déjà installé la
commande gcloud et configuré l’environnement,
notamment en créant un projet et en activant la facturation.
Figure 9.2 : La console Google Cloud montre que le cluster a été redimensionné pour
trois nœuds.
Voir aussi
• Cluster Autoscaler dans le référentiel
kubernetes/autoscaler
(https://github.com/kubernetes/autoscaler/tree/
master/cluster-autoscaler)
Problème
Vous voulez que votre cluster Kubernetes fonctionnant dans
AWS EC2 adapte automatiquement sa géométrie en termes
de nombre de nœuds selon la charge.
Solution
Utilisez le mécanisme AWS Cluster Autoscaler. C’est un
paquetage Helm qui exploite les groupes autoscaling AWS. Si
vous n’avez pas encore installé Helm, voyez d’abord le début
du Chapitre 14.
Redimensionnement horizontal
de pod dans GKE
Problème
Vous voulez faire augmenter ou réduire automatiquement le
nombre de pods d’un déploiement en fonction de la charge.
Solution
Utilisez le mécanisme HPA (Horizontal Pod Autoscaler).
Discussion
Le redimensionnement que nous venons de décrire
correspond à une adaptation automatique du nombre de
réplicas grâce au contrôleur HPA, qui peut être influencé par
une ressource HPA. Le contrôleur (qui fait partie du
gestionnaire de contrôleurs dans le plan de contrôle)
surveille les métriques des pods grâce à des instances
cAdvisor qui s’exécutent sur chaque nœud du cluster, puis
il les agrège au moyen de Heapster. Le contrôleur HPA
calcule alors le nombre de réplicas nécessaires pour
satisfaire à la métrique cible définie dans la ressource HPA
(la communauté Kubernetes parle d’algorithme
Autoscaling). Grâce à ce calcul, le contrôleur HPA adapte le
nombre de réplicas sur la ressource cible, qui peut être par
exemple un déploiement.
Voir aussi
• Mécanisme HPA (Horizontal Pod Autoscaler)
(https://github.com/kubernetes/charts/tree/mast
er/stable/cluster-autoscaler)
• Présentation du HPA
(https://kubernetes.io/docs/tasks/run-
application/horizontal-pod-autoscale-
walkthrough/)
Problème
Vous voulez qu’une application dispose d’une identité
unique afin de pouvoir contrôler les accès aux ressources à
un niveau très détaillé.
Solution
Vous créez un compte de service, puis l’utilisez dans une
spécification de pod.
Tokens: myappsa-token-rr6jc
Type: kubernetes.io/service-account-token
Data
====
ca.crt: 1066 bytes
namespace: 7 bytes
token:
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9 ...
kind: Pod
apiVersion: v1
metadata:
name: myapp
spec:
serviceAccountName: myappsa
containers:
- name: main
image: centos:7
command:
- "bin/bash"
- "-c"
- "sleep 10000"
/var/run/secrets/kubernetes.io/serviceaccount/to
ken
system:serviceaccount:$NAMESPACE:$SERVICEACCOUNT
Voir aussi
• Gestion des comptes de service
(https://kubernetes.io/docs/admin/service-
accounts-admin/)
Problème
Vous avez besoin de savoir quelles actions vous sont
autorisées, par exemple la mise à jour d’un déploiement ou
l’affichage des secrets.
Solution
La solution qui suit suppose que vous avez choisi comme
méthode d’autorisation le contrôle d’accès basé rôles RBAC.
--extra-config=apiserver.Authorization.Mode=RBAC
Vous pouvez définir vos propres rôles en plus des rôles par
défaut qui sont définis dans l’espace de noms kube-system,
comme le montre la section suivante.
User "system:serviceaccount:kube-system:default"
cannot list pods in the
namespace "sec". (get pods)
Discussion
Comme le montre la Figure 10.1, plusieurs éléments sont en
interaction lors d’une autorisation de type RBAC :
• une entité : c’est un groupe, un utilisateur ou un compte
de service ;
Dans les règles d’un rôle, les actions sur une ressource
correspondent à des verbes :
• create
• update/patch
• delete
Voir aussi
• Présentation des autorisations Kubernetes
(https://kubernetes.io/docs/admin/authorization
/)
Problème
Vous voulez pouvoir autoriser ou interdire une certaine
action pour un utilisateur ou une application identifié, par
exemple lire les secrets ou mettre à jour un déploiement.
Solution
Supposons que nous ayons besoin d’autoriser une
application à afficher les pods, c’est-à-dire à les lister et à
en extraire des détails.
kind: Pod
apiVersion: v1
metadata:
name: myapp
namespace: sec
spec:
serviceAccountName: myappsa
containers:
- name: main
image: centos:7
command:
- "bin/bash"
- "-c"
- "sleep 10000"
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
name: podreader
namespace: sec
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list"]
Il n’est dans certains cas pas facile de décider s’il faut utiliser un
rôle classique ou un rôle au niveau cluster et/ou un lien de rôle. Voici
quelques règles qui pourraient vous y aider :
Voir aussi
• Configuration de RBAC dans un cluster Kubernetes
(https://docs.bitnami.com/kuber-netes/how-
to/configure-rbac-in-your-kubernetes-cluster/)
Problème
Vous avez besoin de définir le contexte sécuritaire d’une
application au niveau pod. C’est par exemple le cas lorsque
vous avez besoin d’exécuter l’application sous forme d’un
processus non privilégié ou de limiter les types de volumes
auxquels elle peut accéder.
Solution
Pour instaurer une police au niveau pod dans Kubernetes,
vous renseignez le champ nommé securityContext dans la
spécification du pod.
kind: Pod
apiVersion: v1
metadata:
name: secpod
spec:
containers:
- name: shell
image: centos:7
command:
- "bin/bash"
- "-c"
- "sleep 10000"
securityContext:
runAsUser: 5000
Voir aussi
• Documentation des polices de sécurité de pod
(https://kubernetes.io/docs/concepts/policy/pod
-security-policy/)
Problème
Vous avez besoin d’accéder aux journaux d’une application
qui s’exécute dans un conteneur hébergé dans un pod.
Solution
Utilisez la commande kubectl logs. Pour un rappel des
options, utilisez l’aide interne de la commande :
Aliases:
logs, log
Examples:
# Return snapshot logs from pod nginx with only
one container
kubectl logs nginx
...
En supposant un pod lancé par un déploiement (voir
Chapitre 4), la commande suivante permet d’afficher le
contenu de ses journaux :
Problème
Vous voulez que Kubernetes redémarre automatiquement le
ou les pods dans lesquels votre application s’exécute si
celle-ci entre dans un état instable ou subit une avarie.
Solution
Servez-vous d’une sonde de vitalité liveness. Si cette sonde
renvoie un échec, le composant kubelet va
automatiquement redémarrer le code. Cette sonde est définie
dans la spécification du code, dans la section containers.
Vous pouvez associer une telle sonde à chacun des
conteneurs d’un pod.
apiVersion: v1
kind: Pod
metadata:
name: liveness-nginx
spec:
containers:
- name: liveness
image: nginx
livenessProbe:
httpGet:
path: /
port: 80
Voir aussi
• Kubernetes, « Configure Liveness and Readiness Probes »
(https://kubernetes.io/docs/tasks/configure-
pod-container/configure-liveness-readiness-
probes/#define-a-liveness-command)
• Documentation des sondes des conteneurs Kubernetes
(https://kubernetes.io/docs/concepts/workloads/
pods/pod-lifecycle/#container-probes)
Retenir le trafic vers un pod
avec une sonde de disponibilité
Problème
Vos sondes de vitalité indiquent que vos pods sont actifs et
s’exécutent correctement (voir section précédente).
Cependant, vous ne voulez envoyer du trafic vers ces pods
qu’une fois l’application prête à servir les requêtes.
Solution
Vous ajoutez des sondes de disponibilité (readiness) dans la
spécification des pods. Ces sondes de disponibilité peuvent
prendre trois formes (comme celles de vitalité décrites plus
haut). Voici un exemple simple consistant à exécuter un pod
avec l’image Docker nginx. La sonde de disponibilité lance
une requête HTTP vers le port 80 :
apiVersion: v1
kind: Pod
metadata:
name: liveness-nginx
spec:
containers:
- name: liveness
image: nginx
livenessProbe:
httpGet:
path: /
port: 80
Discussion
La sonde de disponibilité de notre exemple est la même que
celle de vitalité de la section « Récupérer d’une avarie avec
une sonde de vitalité », mais elle devrait en réalité être
différente puisqu’elles ont comme objectif de rapporter des
informations différentes au sujet de l’application. La sonde
de vitalité teste si le processus de l’application est actif,
même s’il n’est pas encore prêt à accepter les requêtes. La
sonde de disponibilité vérifie que l’application est prête à
servir des requêtes. Un pod ne peut donc faire partie du
service qu’une fois que sa sonde de disponibilité le confirme
(voir le Chapitre 5).
Voir aussi
• Cycle de vie d’un conteneur et sondes de conteneur
(https://kubernetes.io/docs/concepts/workloads/
pods/pod-lifecycle/#container-probes)
Problème
Vous voulez pouvoir vérifier de façon automatique que
l’application est en bonne santé et faire en sorte que
Kubernetes agisse dans le cas contraire.
Solution
Pour que Kubernetes se soucie de la santé de votre
application, vous lui ajoutez des sondes de vitalité et de
disponibilité, comme nous allons le voir.
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: webserver
spec:
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:stable
ports:
- containerPort: 80
livenessProbe:
initialDelaySeconds: 2
periodSeconds: 10
httpGet:
path: /
port: 80
readinessProbe:
initialDelaySeconds: 2
periodSeconds: 10
httpGet:
path: /
port: 80
Voir aussi
• Configuration des sondes liveness et readiness
(https://kubernetes.io/docs/tasks/confi-gure-
pod-container/configure-liveness-readiness-
probes/)
Problème
Vous voulez surveiller l’utilisation des ressources dans
Minikube au moyen de la commande kubectl top, mais
vous constatez que l’extension Heapster n’est pas active :
Solution
Les versions récentes de la commande minikube sont
livrées avec un gestionnaire d’extensions qui permet
d’activer Heapster ainsi que quelques autres compléments,
par exemple un contrôleur Ingress, au moyen d’une seule
commande :
Problème
Vous voulez pouvoir visualiser et interroger les métriques du
système et des applications d’un cluster de façon
centralisée.
Solution
Servez-vous de l’outil Prometheus ainsi :
global:
scrape_interval: 5s
evaluation_interval: 5s
scrape_configs:
- job_name: 'kubernetes-nodes'
scheme: https
tls_config:
ca_file:
/var/run/secrets/kubernetes.io/serviceaccount/ca.
crt
server_name: 'gke-k8scb-default-
pool-be16f9ee-522p'
insecure_skip_verify: true
bearer_token_file:
/var/run/secrets/kubernetes.io/serviceaccount/tok
en
kubernetes_sd_configs:
- role: node
relabel_configs:
- action: labelmap
regex:
__meta_kubernetes_node_label_(.+)
- job_name: 'kubernetes-cadvisor'
scheme: https
tls_config:
ca_file:
/var/run/secrets/kubernetes.io/serviceaccount/ca.
crt
bearer_token_file:
/var/run/secrets/kubernetes.io/serviceaccount/tok
en
kubernetes_sd_configs:
- role: node
relabel_configs:
- action: labelmap
regex:
__meta_kubernetes_node_label_(.+)
- target_label: __address__
replacement:
kubernetes.default.svc:443
- source_labels:
[__meta_kubernetes_node_name]
regex: (.+)
target_label: __metrics_path__
replacement:
/api/v1/nodes/${1}:4194/proxy/metrics
Nous pouvons nous servir de ce fichier pour créer une
mappe de configuration :
# apiVersion: rbac.authorization.k8s.io/v1beta1
# kind: ClusterRole
# metadata:
# name: prometheus
# rules:
# - apiGroups: [""]
# resources:
# - nodes
# - nodes/proxy
# - services
# - endpoints
# - pods
# verbs: ["get", "list", "watch"]
# - nonResourceURLs: ["/metrics"]
# verbs: ["get"]
# ---
apiVersion: v1
kind: ServiceAccount
metadata:
name: prometheus
namespace: default
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: prometheus
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: prometheus
namespace: default
kind:
Deployment
apiVersion:
extensions/v1beta1
metadata:
name: prom
namespace: default
labels:
app: prom
spec:
replicas: 1
selector:
matchLabels:
app: prom
template:
metadata:
name: prom
labels:
app: prom
spec:
serviceAccount:
prometheus
containers:
- name: prom
image:
prom/prometheus
imagePullPolicy: Always
volumeMounts:
- name:
prometheus-volume-1
mountPath:
"/prometheus"
- name: prom-
config-volume
mountPath:
"/etc/prometheus/"
volumes:
- name:
prometheus-volume-1
emptyDir: {}
- name: prom-
config-volume
configMap:
name: prom-
config-cm
defaultMode: 420
---
kind: Service
apiVersion: v1
metadata:
name: prom-svc
labels:
app: prom
spec:
ports:
- port: 80
targetPort: 9090
selector:
app: prom
type:
LoadBalancer
externalTrafficPolicy: Cluster
---
kind: Ingress
apiVersion:
extensions/v1beta1
metadata:
name: prom-
public
annotations:
ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host:
http:
paths:
- path: /
backend:
serviceName: prom-svc
servicePort: 80
Il ne reste qu’à créer l’application à partir du manifeste :
Discussion
Prometheus constitue un système de monitorat et d’alerte
puissant et souple. Il vous permet, ainsi que les nombreuses
librairies d’instrumentation disponibles, de créer vos
propres rapports d’application avec des métriques de haut
niveau, par exemple le nombre de transactions réalisées,
selon les mêmes modalités utilisées par un kubelet pour
indiquer le taux d’utilisation CPU.
Problème
Vous voulez visualiser et analyser les journaux de toutes les
applications du cluster de façon centralisée.
Solution
Utilisez le trio EFK (Elasticsearch - Fluentd - Kibana)
comme nous allons le montrer.
$ minikube start
Starting local Kubernetes v1.7.0 cluster...
Starting VM...
Getting VM IP address...
Moving files into cluster...
Setting up certs...
Starting cluster components...
Connecting to cluster...
Setting up kubeconfig...
Kubectl is now configured to use the cluster.
$ minikube addons list | grep ingress
- ingress: enabled
kind: Ingress
apiVersion: extensions/v1beta1
metadata:
name: kibana-public
annotations:
ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: null
http:
paths:
- path: /
backend:
serviceName: kibana
servicePort: 5601
---
kind: Service
apiVersion: v1
metadata:
labels:
app: efk
name: kibana
spec:
ports:
- port: 5601
selector:
app: efk
---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: kibana
spec:
replicas: 1
template:
metadata:
labels:
app: efk
spec:
containers:
- env:
- name: ELASTICSEARCH_URL
value:
http://kibana:changeme@elasticsearch:9200
name: kibana
image:
docker.elastic.co/kibana/kibana:5.5.1
ports:
- containerPort: 5601
---
kind: Service
apiVersion: v1
metadata:
labels:
app: efk
name: elasticsearch
spec:
ports:
- port: 9200
selector:
app: efk
---
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: es
spec:
replicas: 1
template:
metadata:
labels:
app: efk
spec:
initContainers:
- name: init-sysctl
image: busybox
imagePullPolicy: IfNotPresent
command:
- sysctl
- '-w'
- vm.max_map_count=262144
securityContext:
privileged: true
containers:
- name: es
image:
docker.elastic.co/elasticsearch/elasticsearch:5.
5.1
ports:
- containerPort: 9200
env:
- name: ES_JAVA_OPTS
value: '-Xms512m -Xmx512m'
---
kind: DaemonSet
apiVersion: extensions/v1beta1
metadata:
name: fluentd
spec:
template:
metadata:
labels:
app: efk
name: fluentd
spec:
containers:
- name: fluentd
image:
gcr.io/google_containers/fluentd-
elasticsearch:1.3
env:
- name: FLUENTD_ARGS
value: -qq
volumeMounts:
- name: varlog
mountPath: /varlog
- name: containers
mountPath:
/var/lib/docker/containers
volumes:
- hostPath:
path: /var/log
name: varlog
- hostPath:
path: /var/lib/docker/containers
name: containers
Une fois que tout a démarré, ouvrez une session Kibana avec
les crédentiels suivants :
Username: kibana
Password: changeme
Discussion
Le transfert des journaux peut également être réalisé avec
l’outil Logstash, mais nous avons opté pour Fluentd dans la
solution parce qu’il s’agit d’un projet CNCF qui rencontre de
plus en plus de succès.
Voir aussi
• Article de Manoj Bhagwat « To Centralize Your Docker
Logs with Fluentd and ElasticSearch on Kubernetes »
(https://medium.com/@manoj.bhagwat60/to-
centralize-your-docker-logs-with-fluentd-and-
elasticsearch-on-kubernetes-42d2ac0e8b6c)
• Description EFK Stack pour AWS
(https://eksworkshop.com/logging/)
• elk-kubernetes (https://github.com/kayrus/elk-
kubernetes)
• FluentD (https://www.fluentd.org/)
• Kibana (https://www.elastic.co/products/kibana)
CHAPITRE 12
Maintenance et dépannage
Problème
Il devient vite fastidieux de devoir saisir en entier les noms
des commandes et des paramètres de l’outil kubectl. Un
mécanisme de complétion automatique serait apprécié.
Solution
Il suffit d’activer l’autocomplétion de kubectl.
Voir aussi
• Présentation de kubectl
(https://kubernetes.io/docs/user-guide/kubectl-
overview/)
Problème
Vous avez correctement défini un service (voir le Chapitre 5)
qui s’appuie sur plusieurs pods, mais l’un d’entre eux
montre un comportement erratique. Vous voulez l’écarter de
la liste des points d’extrémité (endpoints) afin d’étudier ce
qui ne va pas plus tard.
Solution
Il y a lieu de changer le label du pod au moyen de l’option --
overwrite. Cela permet ensuite de modifier la valeur du
label run de ce pod. En écrasant le label, vous êtes certain
que le pod ne sera pas sélectionné par le sélecteur de
services (Voir la première section du Chapitre 5) et
disparaîtra donc de la liste des points d’extrémité. En
parallèle, le mécanisme de l’ensemble de réplicas qui
surveille ces pods va détecter qu’un des pods a disparu et va
d’office démarrer une nouvelle réplica.
Problème
Un service interne vous cause des soucis et vous voulez
pouvoir tester son fonctionnement au niveau local sans
exposer le service de façon externe.
Solution
Utilisez un proxy local vers le serveur API au moyen de
kubectl proxy.
$ kubectl proxy
Starting to serve on 127.0.0.1:8001
$ curl
http://localhost:8001/api/v1/proxy/namespaces/de
fault/services/nginx/
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
Précisons que vous pouvez dorénavant accéder à la totalité de l’API
Kubernetes via localhost au moyen de curl.
Comprendre et analyser les
statuts des ressources
Problème
Vous voulez réagir en prenant connaissance du statut d’une
ressource, par exemple un pod, au moyen d’un script ou
dans un autre environnement d’automatisation comme un
pipeline CI/ CD.
Solution
Utilisez la commande kubectl get $KIND/$NAME -o json
puis analysez le résultat au format JSON au moyen d’une des
deux méthodes que nous présentons.
Problème
Vous faites face à un pod qui soit ne démarre pas comme
prévu, soit retombe au bout d’un certain temps.
Solution
Adoptez la technique basée sur une boucle OODA pour
découvrir et réparer le problème de façon systématique :
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: unhappy
spec:
replicas: 1
template:
metadata:
labels:
app: nevermind
spec:
containers:
- name: shell
image: busybox
command:
- "sh"
- "-c"
- "echo I will just print something here
and then exit"
$ kubectl get po
NAME READY STATUS
RESTARTS AGE
unhappy-3626010456-4j251 0/1
CrashLoopBackOff 1 7s
Discussion
Qu’il s’agisse d’un pod qui tombe en panne ou d’un
comportement erratique, les causes peuvent être
nombreuses. Voici quelques points à vérifier avant de
suspecter un bogue logiciel :
Voir aussi
• Documentation de dépannage des applications
Kubernetes
(https://kubernetes.io/docs/tasks/debug-
application-cluster/debug-application/)
Problème
Vous avez besoin d’obtenir un instantané détaillé du statut
global d’un cluster pour prendre une décision, faire de
l’audit ou dépanner.
Solution
Utilisez la commande kubectl cluster-info. Voici par
exemple comment créer un vidage du statut de cluster dans
le sous-répertoire cluster-state-2019-10-13 :
.
├── default
│ ├── cockroachdb-0
│ │ └── logs.txt
│ ├── cockroachdb-1
│ │ └── logs.txt
│ ├── cockroachdb-2
│ │ └── logs.txt
│ ├── daemonsets.json
│ ├── deployments.json
│ ├── events.json
│ ├── jump-1247516000-sz87w
│ │ └── logs.txt
│ ├── nginx-4217019353-462mb
│ │ └── logs.txt
│ ├── nginx-4217019353-z3g8d
│ │ └── logs.txt
│ ├── pods.json
│ ├── prom-2436944326-pr60g
│ │ └── logs.txt
│ ├── replicasets.json
│ ├── replication-controllers.json
│ └── services.json
├── kube-public
│ ├── daemonsets.json
│ ├── deployments.json
│ ├── events.json
│ ├── pods.json
│ ├── replicasets.json
│ ├── replication-controllers.json
│ └── services.json
├── kube-system
│ ├── daemonsets.json
│ ├── default-http-backend-wdfwc
│ │ └── logs.txt
│ ├── deployments.json
│ ├── events.json
│ ├── kube-addon-manager-minikube
│ │ └── logs.txt
│ ├── kube-dns-910330662-dvr9f
│ │ └── logs.txt
│ ├── kubernetes-dashboard-5pqmk
│ │ └── logs.txt
│ ├── nginx-ingress-controller-d2f2z
│ │ └── logs.txt
│ ├── pods.json
│ ├── replicasets.json
│ ├── replication-controllers.json
│ └── services.json
└── nodes.json
Ajouter des nœuds de travail
Kubernetes
Problème
Vous voulez ajouter un nœud de travail (worker node) à votre
cluster Kubernetes.
Solution
Commencez par préparer ou approvisionner une nouvelle
machine en fonction des besoins de votre environnement.
Dans un contexte de machines nues Bare Metal, vous
installez physiquement le nouveau serveur dans une baie.
Dans un environnement de cloud public, vous créez une
nouvelle machine virtuelle. Une fois la préparation réalisée,
vous installez les trois composants qui constituent un nœud
de travail Kubernetes :
kubelet
Container runtime
kube-proxy
Discussion
Contrairement à d’autres ressources Kubernetes, et
notamment les déploiements et services, les nœuds de
travail ne sont pas créés directement par le plan de contrôle
Kubernetes, car ce dernier se contente de les administrer.
Autrement dit, lorsque Kubernetes crée un nœud, il ne crée
en fait qu’un objet qui va représenter le travail. Il valide ce
nœud par un test de santé en se fondant sur le champ
metadata.name du nœud. Si le nœud est considéré comme
valable, c’est-à-dire que tous ses composants s’exécutent
bien, il peut être considéré comme faisant partie du cluster.
Dans le cas contraire, le nœud est ignoré en termes
d’activité du cluster, et ce jusqu’à ce qu’il devienne valide.
Voir aussi
• Description des nœuds Kubernetes dans le document
d’architecture
(https://github.com/kubernetes/community/blob/m
aster/contributors/design-
proposals/architecture/ architecture.md#the-
kubernetes-node)
• Pods statiques
(https://kubernetes.io/docs/tasks/administer-
cluster/static-pod/)
Retirer un nœud pour
maintenance
Problème
Vous avez besoin de faire la maintenance d’un nœud, par
exemple pour lui appliquer un correctif de sécurité ou pour
mettre à jour le système.
Solution
Vous utilisez la commande kubectl drain. Voici par
exemple comment basculer en mode maintenance le nœud
nommé 123-worker :
Discussion
Dans tous les cas, la commande kubectl drain commence
par marquer le nœud mentionné comme devenant non
planifiable, afin d’empêcher l’arrivée de nouveaux pods (ce
qui équivaut à kubectl cordon). Dans un deuxième temps,
la commande procède à une éviction des pods si le serveur
API supporte cette opération. Dans le cas contraire, la
commande applique une opération de suppression kubectl
delete pour supprimer les pods. La documentation de
Kubernetes décrit précisément la séquence d’opérations
(nous la reproduisions dans la Figure 12.3).
Figure 12.3 : Scénario de mise à l’écart d’un nœud de travail.
Voir aussi
• Purge de nœud avec respect des SLO applicatifs
(https://kubernetes.io/docs/tasks/administer-
cluster/safely-drain-node/)
Problème
Vous avez besoin d’accéder à la base etcd pour effectuer
une sauvegarde ou vérifier directement le statut du cluster.
Solution
Pour accéder à etcd et lancer une requête, vous pouvez
utiliser curl ou etcdctl. Voici par exemple comment
procéder dans le contexte de Minikube, si l’outil jq est
installé :
$ minikube ssh
$ curl 127.0.0.1:2379/v2/keys/registry | jq .
{
"action": "get",
"node": {
"key": "/registry",
"dir": true,
"nodes": [
{
"key":
"/registry/persistentvolumeclaims",
"dir": true,
"modifiedIndex": 241330,
"createdIndex": 241330
},
{
"key": "/registry/apiextensions.k8s.io",
"dir": true,
"modifiedIndex": 641,
"createdIndex": 641
},
...
Discussion
Dans Kubernetes, etcd est un des composants du plan de
contrôle. Rappelons que le serveur API (voir le Chapitre 6)
est sans conservation d’état (stateless) et constitue le seul
composant de Kubernetes qui communique directement avec
etcd, qui est le composant de stockage distribué qui gère le
statut du cluster. En fait, etcd est une base contenant des
paires clé/valeur. Dans la version etcd2, les clés étaient
présentées sous forme hiérarchique, mais cette approche a
été remplacée dans etcd3 par un modèle à plat, tout en
maintenant la rétrocompatibilité avec les clés hiérarchisées.
Jusqu’à la version 1.5.2 de Kubernetes, on utilisait etcd2, puis le
basculement s’est fait vers etcd3. Dans Kubernetes 1.5.x, etcd3
reste utilisé dans le mode API v2. L’évolution vise l’API v3 etcd en
remplacement de la v2. Du point de vue du développeur, cela n’a pas
d’impact, car le serveur API se charge d’abstraire les interactions. En
tant qu’administrateur en revanche, vous ferez attention à la version
de etcd que vous utilisez et dans quel mode API.
Voir aussi
• Guide d’administration de cluster etcd
v2 (https://coreos.com/etcd/docs/latest/v2/admi
n_guide.html)
Problème
Vous voulez constituer votre propre paquetage de binaire
Kubernetes à partir du code source, au lieu de télécharger les
binaires officiels d’une release ou des recompilations
d’autres sources (voir Chapitre 2).
Solution
Vous dupliquez par clonage le référentiel GitHub de
Kubernetes puis vous recompilez depuis les sources.
$ git clone
https://github.com/kubernetes/kubernetes
$ cd kubernetes
$ make quick-release
Pour cette construction sur base Docker, vous devez disposer d’au
moins 4 Go de mémoire RAM. Vérifiez que le démon Docker a accès
au minimum à cet espace. Sous macOS, vous ouvrez les préférences
de Docker for Mac pour augmenter l’espace mémoire alloué.
Les binaires vont être disponibles dans le répertoire
_output/release-stage et un paquetage complet vous attendra
dans le répertoire _output/release-tars.
$ git clone
https://github.com/kubernetes/Kubernetes
$ cd kubernetes
$ make
Voir aussi
• Guides de développement détaillé de Kubernetes
(https://github.com/kubernetes/community/tree/m
aster/contributors/devel)
• Langage Go (http://golang.org)
• Sources de Kubernetes
(https://github.com/kubernetes/kubernetes)
Compiler un seul composant
Problème
Vous voulez reconstruire un composant de Kubernetes à
partir des fichiers source, mais pas l’ensemble du projet. Par
exemple, vous ne voulez recompiler que le client kubectl.
Solution
Au lieu de choisir comme cible, make quick-release ou de
spécifier make comme dans la section précédente, vous
spécifiez par exemple, make kubectl.
$ make kubectl
$ make kubeadm
$ make hyperkube
Problème
Voulez utiliser le langage Python pour créer des scripts
exploitant l’API Kubernetes.
Solution
Vous installez le module de Python nommé kubernetes. Il
est en cours de développement dans l’incubateur
Kubernetes. Vous pouvez l’installer depuis les sources ou
depuis le site d’index des paquetages Python PyPi :
config.load_kube_config()
v1 = client.CoreV1Api()
res = v1.list_pod_for_all_namespaces(watch=False)
Discussion
Le client Python a été créé en conformité avec la
spécification OpenAPI de l’API Kubernetes. Il est toujours à
jour et généré automatiquement. Il permet d’accéder à tous
les éléments API depuis ce client.
Voir aussi
• Incubateur Kubernetes
(https://github.com/kubernetes-
incubator/client-python)
Problème
Vous avez à gérer une charge de travail spécifique, mais
aucune des ressources existantes, Deployment, Job ou
StatefulSet, ne convient vraiment. Vous aimeriez donc
pouvoir enrichir l’API Kubernetes en définissant une
nouvelle ressource pour incarner votre charge de travail tout
en utilisant kubectl de façon normale.
Solution
Vous créez une définition de ressource CRD (Custome
Resource Definition), comme nous allons voir.
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: functions.example.com
spec:
group: example.com
version: v1
scope: Namespaced
names:
kind: Function
plural: functions
apiVersion: example.com/v1
kind: Function
metadata:
name: myfaas
spec:
code: "http://src.example.com/myfaas.js"
ram: 100Mi
Discussion
Nous venons de voir que la création d’une définition CRD est
facile. Du point de vue de l’utilisateur final, les CRD
proposent une API cohérente et ne se distinguent quasiment
pas des ressources natives que sont les pods et jobs. Toutes
les commandes habituelles fonctionnent comme prévu, par
exemple, kubectl get ou kubectl delete.
Voir aussi
• Extension de l’API Kubernetes avec les CRD
(https://kubernetes.io/docs/tasks/access-
kubernetes-api/extend-api-custom-resource-
definitions/)
Problème
Vous voulez éviter de devoir écrire à la main tous les
manifestes Kubernetes. Vous aimeriez pouvoir faire chercher
un paquetage dans un référentiel pour télécharger et
installer le contenu via l’interface sur ligne de commande.
Solution
Adoptez l’outil Helm, qui est le gestionnaire de paquetages
de Kubernetes. Il définit un paquetage comme un ensemble
de manifestes accompagné de quelques métadonnées. Les
manifestes sont en fait des modèles : les valeurs réelles n’y
sont injectées que lors de la création d’une instance du
paquetage par Helm. Un paquetage traité par Helm porte le
nom de charte.
$ wget
https://storage.googleapis.com/kubernetes-helm/
\
helm-v2.7.2-darwin-amd64.tar.gz
$ helm version
$ helm init
$HELM_HOME has been configured at
/Users/sebgoa/.helm.
Problème
Vous avez installé l’outil helm (voir section précédente).
Vous voulez maintenant chercher des chartes et les déployer.
Solution
Helm est livré en standard avec plusieurs référentiels de
chartes préconfigurées et maintenues par la communauté.
Vous pouvez en apprendre plus sur GitHub. Il y en a plus
de 100 !
$ helm ls
NAME REVISION UPDATED
STATUS CHART ...
broken-badger 1 Fri May 12 11:50:43 2017
DEPLOYED redis-0.5.1 ...
Problème
Vous avez créé une application qui utilise plusieurs
manifestes Kubernetes. Vous aimeriez la transformer en un
paquetage sous forme d’une charte Helm.
Solution
Servez-vous des commandes helm create et helm
package.
$ tree oreilly/
oreilly/
├── Chart.yaml
├── charts
├── templates
│ ├── NOTES.txt
│ ├── _helpers.tpl
│ ├── deployment.yaml
│ ├── ingress.yaml
│ └── service.yaml
└── values.yaml
2 directories, 7 files
$ ls -l ⁓/.helm/repository/local/
total 16
-rw-r--r-- 1 sebgoa staff 379 Dec 16 21:25
index.yaml
-rw-r--r-- 1 sebgoa staff 1321 Dec 16 21:25
oreilly-0.1.0.tgz
Voir aussi
• Création d’une première charte Helm dans la
documentation Bitnami de Kubernetes
(https://docs.bitnami.com/kubernetes/how-
to/create-your-first-helm-chart/)
Problème
Vous utilisez déjà des conteneurs avec Docker et vous avez
créé quelques fichiers compose Docker pour définir une
application multiconteneur. Vous voulez maintenant
basculer vers Kubernetes, mais vous vous demandez s’il est
possible de réutiliser vos fichiers compose Docker et
comment.
Solution
Adoptez l’outil kompose qui sert à convertir des fichiers
compose Docker en manifestes Kubernetes.
$ wget https://github.com/kubernetes-
incubator/kompose/releases/download/ \
v1.6.0/kompose-darwin-amd64
$ sudo mv kompose-darwin-amd64
/usr/local/bin/kompose
$ kompose version
1.6.0 (ae4ef9e)
version: '2'
services:
redis:
image: redis
ports:
- "6379:6379"
$ kompose up
Discussion
Les trois principales commandes de l’outil kompose sont
convert, up et down. Pour plus de détails, utilisez l’option -
-help.
Problème
Vous avez besoin de créer un cluster Kubernetes sur AWS.
Solution
Pour créer et gérer des clusters Kubernetes sur AWS, vous
utilisez l’outil kubicorn. Pour l’instant, il ne fournit pas de
releases binaires ; vous devez donc avoir installé le langage
Go pour que les exemples qui suivent fonctionnent.
$ go version
go version go1.8 linux/amd64
$ go get github.com/kris-nova/kubicorn
...
Create, Manage, Image, and Scale Kubernetes
infrastructure in the cloud.
Usage:
kubicorn [flags]
kubicorn [command]
Available Commands:
adopt Adopt a Kubernetes cluster into a
Kubicorn state store
apply Apply a cluster resource to a cloud
completion Generate completion code for bash
and zsh shells.
create Create a Kubicorn API model from a
profile
delete Delete a Kubernetes cluster
getconfig Manage Kubernetes configuration
help Help about any command
image Take an image of a Kubernetes
cluster
list List available states
version Verify Kubicorn version
Flags:
-C, --color Toggle colorized logs
(default true)
-f, --fab Toggle colorized logs
-h, --help help for kubicorn
-v, --verbose int Log level (default 3)
$ cat _state/k8scb/cluster.yaml
SSH:
Identifier: ""
metadata:
creationTimestamp: null
publicKeyPath: ⁓/.ssh/id_rsa.pub
user: ubuntu
cloud: amazon
kubernetesAPI:
metadata:
creationTimestamp: null
port: "443"
location: us-west-2
...
Nous utilisons ici un profil de ressource par défaut qui suppose que
vous disposez d’une paire de clés dans ⁓/.ssh qui portent le nom
id_rsa et id_rsa.pub (clé publique). Vous modifierez donc ces
paramètres si ce n’est pas le cas. Notez que la région par défaut
choisie est ici l’Oregon, us-west-2.
Vous devez disposer pour continuer d’un compte utilisateur
AWSIAM (Identity and Access Management) dans lequel les
droits suivants sont actifs : AmazonEC2FullAccess,
AutoScalingFullAccess et AmazonVPCFullAccess. Si vous
ne disposez pas d’un tel compte IAM, le moment est venu
d’en créer un.
$ export
AWS_ACCESS_KEY_ID=***************************
$ export
AWS_SECRET_ACCESS_KEY=**************************
***************
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/advantage
NAME DESIRED
CURRENT READY AGE
rs/calico-policy-controller-1727037546 1
1 1 4m
rs/kube-dns-2425271678 1
1 0 4m
Une fois cela fait, pensez à supprimer le cluster Kubernetes
qui vous a servi à faire vos essais, en n’oubliant pas que cela
peut prendre quelques minutes :
Discussion
Le projet kubicorn est assez récent, mais il fonctionne
correctement, et permet même de créer des clusters sur
Azure et sur Digital Ocean.
Voir aussi
• Guide AWS Identity and Access Management « Creating an
IAM User in Your AWS Account »
(http://docs.aws.amazon.com/IAM/latest/UserGuid
e/id_users_create.html)
Problème
Vous voulez stocker tous vos manifestes Kubernetes dans un
système de contrôle de version (un versionneur) en étant
certain qu’ils sont partagés en toute sécurité, même de
façon publique, et y compris les secrets.
Solution
Servez-vous du contrôleur Kubernetes Sealed-secrets qui
permet de décrypter dans un seul sens des secrets cryptés en
créant des objets de type Secret internes au cluster, des
secrets scellés (voir Chapitre 8).
$ wget https://github.com/bitnami/sealed-
secrets/releases/download/v0.5.1/
kubeseal-$GOOS-$GOARCH
$ kubectl create -f
https://github.com/bitnami/sealed-
secrets/releases/
download/v0.5.1/sealedsecret-crd.yaml
$ kubectl create -f
https://github.com/bitnami/sealed-
secrets/releases/
download/v0.5.1/controller.yaml
Vous disposez alors d’une nouvelle ressource spécifique et
d’un nouveau pod qui s’exécute dans l’espace de noms
kube-system :
$ cat secret.json
{
"kind": "Secret",
"apiVersion": "v1",
"metadata": {
"name": "oreilly",
"creationTimestamp": null
},
"data": {
"password": "cm9vdA=="
}
}
$ cat sealedsecret.json
{
"kind": "SealedSecret",
"apiVersion": "bitnami.com/v1alpha1",
"metadata": {
"name": "oreilly",
"namespace": "default",
"creationTimestamp": null
},
"spec": {
"data":
"AgDXiFG0V6NKF8e9k1NeBMc5t4QmfZh3QKuDORAsFNCt50w
TwRhRLRAQOnz0sDk..."
}
}
Vous pouvez enregistrer le fichier sealedsecret.json dans votre
système de contrôle de version. Le seul moyen de le
décrypter est d’utiliser la clé privée qui est stockée dans le
contrôleur de secrets scellés. Une fois que vous avez créé
l’objet SealedSecret, le contrôleur va le détecter, le
décrypter et générer le secret correspondant :
Voir aussi
• Référentiel sealed-secrets
(https://github.com/bitnami/sealed-secrets)
Problème
Vous voulez déployer dans Kubernetes des fonctions écrites
en Python, en Node.js, en Ruby ou en Powershell sans avoir
à construire d’abord un conteneur Docker. Vous voulez
également pouvoir appeler ces fonctions via HTTP ou leur
envoyer des événements via un bus de messages.
Solution
Profitez de la solution sans serveur native à Kubernetes
nommée kubeless.
$ curl -sL
https://github.com/kubeless/kubeless/releases/do
wnload/v0.3.1/ \
kubeless-rbac-v0.3.1.yaml | kubectl create -f -
$ wget
https://github.com/kubeless/kubeless/releases/do
wnload/v0.3.1/ \
kubeless_darwin-amd64.zip
$ sudo cp bundles/kubeless_darwin-amd64/kubeless
/usr/local/bin
def handler(context):
print context.json
return context.json
$ kubeless function ls
NAME NAMESPACE HANDLER
RUNTIME TYPE TOPIC
post-python default hellowithdata.handler
python 2.7 HTTP
$ kubectl get pods
NAME READY STATUS
RESTARTS AGE
post-python-5bcb9f7d86-d7nbt 1/1 Running 0
6s
Le contrôleur kubeless va détecter le nouvel objet
Function et créer un déploiement correspondant. Le code
de la fonction est stocké dans une mappe de configuration
(voir Chapitre 8) puis injecté dans le pod actif pendant
l’exécution. La fonction devient alors appelable via HTTP.
Voici les quelques objets concernés :
$ kubectl get cm
NAME DATA AGE
post-python 3 2m
Voir aussi
• Référentiel de kubeless
(https://github.com/kubeless/kubeless)
• Exemples kubeless
(https://github.com/kubeless/kubeless/tree/mast
er/examples)
Couverture
Guide pratique de Kubernetes - L'art de
construire des conteneurs d'applications -
collection O'Reilly
Copyright
Introduction
Lectorat principal
Structure du livre
Conventions typographiques
Actualiser un déploiement
Redimensionner un déploiement
Déboguer un pod
ANNEXE A. Ressources
Ressources générales
Tutoriels et exemples