Les cours sont maintenus et donnés par : https://www.alterway.fr/cloud-consulting

Les labs sont içi : https://bit.ly/3XQHbUk
vX.Y.Z (Majeure, Mineure, Patch).sig-network, sig-storage, sig-security).Kubernetes est écrit en Go, compilé statiquement.
Un ensemble de binaires sans dépendances
Faciles à conteneuriser et à packager
Peut se déployer uniquement avec des conteneurs sans dépendance d'OS
k3d, kind, minikube, docker...
Les noeuds qui exécutent les conteneurs embarquent :
Un "container Engine" (Docker, CRI-O, containerd...)
Une "kubelet" (node agent)
Un kube-proxy (un composant réseau nécessaire mais pas suffisant)
Ancien nom des noeuds : Minions

etcd: magasin de données clé-valeur open source cohérent et distribué
kube-apiserver : L'API Server est un composant qui expose l'API Kubernetes, l'API server qui permet la configuration d'objets Kubernetes (Pod, Service, Deployment, etc.)
core services :
kube-scheduler : Implémente les fonctionnalités de schedulingkube-controller-manager : Responsable de l'état du cluster, boucle infinie qui régule l'état du cluster afin d'atteindre un état désirékube-cloud-controller-manager : Est un composant important du plan de contrôle (control plane) de Kubernetes, spécifiquement conçu pour interagir avec l'infrastructure cloud sous-jacentekube-proxy : Permet le forwarding TCP/UDP et le load balancing entre les services et les backends (Pods)Le control plane est aussi appelé "Master"
etcdkube-apiserverSans le kube-apiserver le cluster ne sert à rien. De plus, il est LE SEUL à interagir avec le cluster etcd, que ce soit en écriture ou en lecture.
etcd
kube-schedulerLe kube-scheduler est le composant responsable d'assigner les pods aux nœuds "worker" du cluster. Il choisit alors selon les contraintes qui lui sont imposées un nœud sur lequel les pods peuvent être démarrés et exécutés.
kube-controller-managerLe kube-controller-manager exécute et fait tourner les processus de contrôle du cluster.
namespaces Kuberneteskube-cloud-controller-managerFonction principale :
kube-proxyLe kube-proxy maintient les règles réseau sur les nœuds. Ces règles permettent la communication vers les pods depuis l'intérieur ou l'extérieur de votre cluster.
Responsable de la publication de services
Route les paquets à destination des PODs et réalise le load balancing TCP/UDP
3 modes de proxyfication :
Userspace mode
IPtables mode
IPVS (IP Virtual Server) mode
Remarque: Par défaut, Kube-proxy fonctionne sur le port 10249. Vous pouvez utiliser un ensemble d'endpoints exposés par Kube-proxy pour l'interroger et obtenir des informations.
Pour voir quel mode est utilisé :
Sur un des noeuds executer la commande :
curl -v localhost:10249/proxyMode;echo
# ex: retourne iptablesCertains plugins réseaux, tel que Cilium, permettent de ne plus utiliser kube-proxy et de le remplacer par un composant du CNI
kube-proxy Userspace modekube-proxy IPtables modekube-proxy IPVS modeIPVS mode équilibre la charge en utilisant la fonctionnalité IPVS du noyau Linux. Par rapport au mode IPtables, il offre une meilleure évolutivité et des performances améliorées.
IPVS est le mode recommandé pour les installations à grande échelle car il peut gérer de plus gros volumes de trafic avec efficacité. IPtable Non !
Elle, Il, iel ? 😉


Kubernetes n'implémente pas de solution réseau par défaut, mais s'appuie sur des solutions tierces qui implémentent les fonctionnalités suivantes:
Les versions de Kubernetes sont exprimées sous la forme x.y.z, où x est la version majeure, y est la version mineure et z est la version du correctif, conformément à la terminologie du Semantic Versioning.
1.33
Latest Release:1.33.4 (released: 2025-08-12)
End of Life:2026-06-28
Complete 1.33 Schedule and Changelog
| Solution | Description | Avantages | Inconvénients |
|---|---|---|---|
| Minikube | Outil officiel pour installer un cluster Kubernetes local sur une machine. | - Facile à installer et à configurer - Compatible avec la majorité des environnements - Supporte divers hyperviseurs et conteneurs |
- Peut être lourd en ressources - Nécessite une VM pour fonctionner |
| Kind | Kubernetes IN Docker (KinD) utilise Docker pour exécuter des clusters. | - Léger et rapide - Simple à configurer - Idéal pour les tests CI/CD |
- Moins de fonctionnalités avancées - Dépend de Docker |
| MicroK8s | Distribution légère de Kubernetes par Canonical. | - Facile à installer - Léger et optimisé - Idéal pour les environnements de développement |
- Moins de flexibilité dans la configuration - Utilise des snaps (peut ne pas plaire à tout le monde) |
| K3s | Distribution allégée de Kubernetes par Rancher. | - Très léger et rapide - Idéal pour les environnements IoT et edge - Moins de ressources requises |
- Moins de fonctionnalités intégrées - Moins documenté que Minikube |
| Docker Desktop | Inclut une option pour exécuter Kubernetes directement. | - Facile à utiliser pour les développeurs habitués à Docker - Intégration transparente avec Docker |
- Peut être lourd en ressources - Moins flexible que Minikube ou Kind |
| Rancher Desktop | - Open Source, - Choix des version de k8s - Choix du CRI |
- Facile à utiliser | - Moins d'extensions que Minikube |
Installation : https://minikube.sigs.k8s.io/docs/start
Les cluster sont supprimés automatiquement au fichier ~/.kube/config avec la commande minikube delete [--all]
minikube addons listPré-requis : - Linux - Raspberry
ou plus simplement : curl -sfL https://get.k3s.io | sh -
kind create clusterInstallation : https://www.docker.com/products/docker-desktop/
Licence obligatoire si autre utilisation que personnelle (https://www.docker.com/pricing/)


Kubeadm est un outil qui facilite le déploiement de Kubernetes en automatisant les tâches d'initialisation et de configuration d'un cluster.
swap (Support alpha depuis la 1.22)kubeadm init sur le noeud master(control plane)kubeadm join sur les autres noeuds (worker) (avec le token fournit par la commande kubeadm init)kubeadm initEn plus de l'installation de Kubernetes, kubeadm peut :
Génération des fichiers de configuration: Crée les fichiers de configuration nécessaires pour les composants du cluster.
Gestion des certificats: Génère et distribue les certificats nécessaires pour sécuriser les communications entre les composants du cluster.
Gestion des tokens: Crée des tokens d'authentification pour les nœuds qui rejoignent le cluster.
Vérification de la configuration: Valide que le système et les configurations sont compatibles avec Kubernetes.
Mises à jour et modifications: Facilite les mises à jour des versions de Kubernetes et les modifications de la configuration du cluster.
Via Ansible : kubespray https://github.com/kubernetes-sigs/kubespray
Via Terraform : https://github.com/poseidon/typhoon
Voici quelques outils permettant de certifier les déploiements des cluster kubernetes en terme de sécurité et de respects des standards
kubectlLe(s) fichier(s) se trouve(nt) par défaut dans le répertoire ~/.kube/config
kubeconfig peut être passé en paramètre de kubectl avec le flag --kubeconfig
kubectl --kubeconfig=/opt/k8s/config get pokubeconfig peut être passé en paramètre de kubectl avec la variable d'nvironnement KUBECONFIG
KUBECONFIG=/opt/k8s/config kubectl get podsUn seul fichier pour gérer tous les clusters avec trois informations :

apiVersion: v1
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FU..
server: https://akshlprod001-e419e3f0.hcp.northeurope.azmk8s.io:443
name: aks-hl-prod-001
contexts:
- context:
cluster: aks-hl-prod-001
namespace: velero
user: clusterUser_rg-hl-prod-001_aks-hl-prod-001
name: aks-hl-prod-001
current-context: aks-hl-prod-001
kind: Config
preferences: {}
users:
- name: clusterUser_rg-hl-prod-001_aks-hl-prod-001
user:
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0t..
client-key-data: LS0tLS1CRUdJTiBSU0Eg..
token: 0ad033b165e2f7a4f705ca6defef8555ff501345e2324cf337b68820d85dc65bae39c47bb58ad913b0385a0d7eb5df6e872dbd1fe62fd34ca6e4ed58b2e8a733Lorsque vous accédez à plusieurs clusters Kubernetes, vous aurez de nombreux fichiers kubeconfig.
Par défaut, kubectl recherche uniquement un fichier nommé config dans le répertoire $HOME/.kube.
Alors, comment pouvons-nous fusionner plusieurs fichiers kubeconfig en un seul ?
cp ~/.kube/config ~/.kube/config-backup La variable d'environnement KUBECONFIG est une liste de chemins vers des fichiers de configuration, par exemple :
export KUBECONFIG=~/.kube/config:/path/cluster1/config:/path/cluster2/config:/path/cluster3/configkubectl config view --flatten > all-in-one-kubeconfig.yamlmv all-in-one-kubeconfig.yaml ~/.kube/configkubectl config get-contexts
api-resources$ kubectl api-resources
NAME SHORTNAMES APIGROUP NAMESPACED KIND
configmaps cm true ConfigMap
limitranges limits true LimitRange
namespaces ns false Namespace
nodes no false Node
persistentvolumeclaims pvc true PersistentVolumeClaim
persistentvolumes pv false PersistentVolume
pods po true Pod
secrets true Secret
services svc true Service
daemonsets ds apps true DaemonSet
deployments deploy apps true Deployment
replicasets rs apps true ReplicaSet
statefulsets sts apps true StatefulSet
horizontalpodautoscalers hpa autoscaling true HorizontalPodAutoscaler
cronjobs cj batch true CronJob
jobs batch true Job
ingresses ing extensions true Ingresskubectl api-resources ?
kubectl explainkubectl explain typekubectl explain node.speckubectl explain node --recursiveKindLes noms de ressources les plus courants ont 3 formes:
Certaines ressources n'ont pas de nom court (clusterroles, clusterrolebindings, roles ...)
Les points de terminaison (endpoints) ont uniquement une forme plurielle ou courte (ep)
kubectl getNous allons explorer en détail les différents types de ressources Kubernetes plus tard dans ce cours.
Pour l'instant, concentrons-nous sur l'utilisation de kubectl pour récupérer des informations sur notre cluster.
Voiçi quelques exemples d'utilisation de cette commande très puissante
kubectl get nodeskubectl get no
kubectl get nodeskubectl getkubectl get nodes -o widekubectl get nodes -o yaml
kubectl get nodes -o jsonUtiliser JSONPath
kubectl get pods -o=jsonpath='{@}'
kubectl get pods -o=jsonpath='{.items[0]}'
kubectl get pods \
--output=jsonpath='{.items[0].metadata.name}'kubectl getjqkubectl get nodes -o json |
jq ".items[] | {name:.metadata.name} + .status.capacity"⚠ : Il faut utiliser jq quand on a besoin de regexp car JSONPath ne les supporte pas.
ex:
# KO :
kubectl get pods -o jsonpath='{.items[?(@.metadata.name=~/^test$/)].metadata.name}'
# OK :
kubectl get pods -o json | jq -r '.items[] | select(.metadata.name | test("test-")).spec.containers[].image'kubectl getkubectl get ns
kubectl get namespacesdefault-n ou --namespacekubectl -n kube-system get podskubectl getkubectl get pods
kubectl get podkubectl getdefault):kubectl get services
kubectl get svckubectl getnamespace particulierkubectlkubectl get pods --namespace=kube-system
kubectl get pods -n kube-system
# Mais aussi sur d'autres commandes
kubectl create -n NNN ...
kubectl run -n NNN ...
kubectl delete -n NNN ...
# ...kubectl get--all-namespaces-A en raccourcikubectl get pods --all-namespaces
# ou
kubectl get pods -A
# autres actions
kubectl delete -A ...
kubectl label -A ...cd)Évite de toujours préciser le flag -n
kubectl get ns
kubectl config set-context --current --namespace <nom-du-namespace>
# ou
alias kubens='kubectl config set-context --current --namespace '
# ex: kubens kube-system kube-publickube-public est créé par kubeadm
kubectl get all -n kube-publickubectl cluster-infokubectl -n kube-public get configmaps
# voir le contenu du configmap (cm)
kubectl -n kube-public get configmap cluster-info -o yaml
# Ce configmap est lisible par tout le monde sans authentification
curl -k https://{NodeIP}/api/v1/namespaces/kube-public/configmaps/cluster-info
# Contient le kubeconfigCe configmap contient l'url de l'API du serveur, et la clé publique de l'AC
Ce fichier ne contient pas de clés client ni de tokens
Il ne s'agit pas d'informations sensibles
cluster-infocurl -sk https://<IP PRIV>/api/v1/namespaces/kube-public/configmaps/cluster-info \
| jq -r .data.kubeconfigkube-node-leaseQu'est-ce qu'un Lease dans Kubernetes ? Un Lease est un objet qui expire après un certain temps s'il n'est pas renouvelé. Dans le contexte de kube-node-lease, chaque nœud du cluster a un Lease associé. La kubelet (l'agent Kubernetes s'exécutant sur chaque nœud) envoie régulièrement des mises à jour à ce Lease pour indiquer qu'il est toujours en fonctionnement.
leasepar noeudleases permettent d'implémenter une nouvelle méthode pour vérifier l'état de santé des noeudskubectl describekubectl describe a besoin d'un type de ressource et optionnellement un nom de ressourceIl est possible de fournir un préfixe de nom de ressource
ex:
kubectl describe node/worker-0
kubectl describe node worker-0Pourquoi utiliser kubectl describe ? :
Les objets Kubernetes sont créés sous la forme de fichiers JSON ou YAML et envoyés à l'APIServer
Possible d'utiliser la commande kubectl run, mais limitée aux deployments et aux jobs
L'utilisation de fichiers YAML permet de les stocker dans un système de contrôle de version comme git, mercurial, etc...
La documentation de référence pour l'API Kubernetes https://kubernetes.io/docs/reference/#api-reference
deploymentpod# Création d'un pod en tâche de fond
kubectl run pingu --image=alpine -- ping 127.1# Création d'un pod en intératif
kubectl run -i --tty my-pod --image=debian -- /bin/bash⚠ : Notez le --entre le nom de l'image et la commande à lancer
kubectl create deployment ...createkubectl create deployment pingu --image=alpine -- ping 127.1⚠ : Notez le --entre le nom de l'image et la commande à lancer
YAML, utilisez la commande kubectl create :kubectl create -f object.yamlkubectl create -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook/frontend-deployment.yamlkubectl delete -f object.yamlkubectl replace -f object.yaml
kubectl apply -f object.yaml⚠ : Il est possible d'utiliser apply pour créer des resources.
Étape 1: Déployer le Dashboard
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yamlÉtape 2: Créer un compte de service et un rôle d'administration
# dashboard-adminuser.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboardkubectl apply -f dashboard-adminuser.yaml# admin-role-binding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kubernetes-dashboard
kubectl apply -f admin-role-binding.yamlÉtape 3: Récupérer le token d'accès
kubectl -n kubernetes-dashboard create token admin-userCopiez le token affiché et sauvegardez le.
Étape 4: Accéder au Dashboard
Si vous êtes sur votre PC (installation locale de kubernetes)
Démarrer un proxy pour accéder au Dashboard:
kubectl proxy
Si vos machines sont déployées sur un Cloud Provider (AWS, Azure, GCP, etc)
masterkubectl -n kubernetes-dashboard port-forward svc/kubernetes-dashboard 8443:443 --address=0.0.0.0Dans votre navigateur utilisez l'url suivante en l'adaptant avec l'adresse IP publique du master
https://[IP-PUBLIQUE-MASTER]:8443/
Acceptez l'alerte de sécurité concernant le certificate
kubectlkubectl get
Exemples :
# Lister les pods dans le namespace actuel
kubectl get pods
# Lister les nœuds avec plus d'informations
kubectl get nodes -o wide
# Lister les services dans tous les namespaces
kubectl get services -Akubectl describe
Exemple :
# Voir les détails d'un pod spécifique
kubectl describe pod <nom-du-pod>kubectl apply
Exemple :
kubectl apply -f mon-deploiement.yamlkubectl delete
Exemple :
kubectl delete -f mon-deploiement.yamlkubectl api-resources
pods, deployments, ingresses...).Exemple :
kubectl api-resourceskubectl explain
Exemple :
# Comprendre ce qu'on peut mettre dans la section 'spec' d'un pod
kubectl explain pod.specNamespaces
Labels
Annotations
Pods
Deployments
DaemonSets
Jobs
Cronjobs
Services
NamespacesNamespaces : Pensez aux différents départements d'une entreprise (par exemple, les ressources humaines, l'ingénierie, le marketing). Chaque département a ses propres ressources (employés, budgets, projets) et fonctionne de manière assez indépendante, mais ils font tous partie de la même entreprise. Vous ne pouvez pas avoir deux projets avec le même nom dans le même département, mais vous le pouvez dans des départements différents.
Défaut: Le namespace default existe par défaut dans chaque cluster Kubernetes.
LabelsLabels : Imaginez des étiquettes sur des boîtes dans un entrepôt. Vous pouvez étiqueter les boîtes avec des mentions comme "fragile", "lourd", "électronique" ou par destination comme "Paris". Cela vous aide à trouver et à organiser rapidement toutes les boîtes ayant une caractéristique spécifique. Une boîte peut avoir plusieurs étiquettes.
~ . et alphanumMultiples: Un objet peut avoir plusieurs labels.
LabelsapiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: nginx
env: prod
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80LabelsLa commande kubectl get pods, par défaut, ne liste pas les labels.
Il est possible de les voir en utilisant --show-labels:
$ kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
nginx 1/1 Running 0 31s app=nginx,env=prod
kubectl get po -A -l k8s-app=kube-dns
# ou
kubectl get pods --selector=k8s-app=dns
kubectl get po -A -l k8s-app=kube-dns -l pod-template-hash=6d4b75cb6d
# equivalent
kubectl get po -A -l k8s-app=kube-dns,pod-template-hash=6d4b75cb6d
# ou
kubectl get po -A --selector=8s-app=kube-dns,pod-template-hash=6d4b75cb6d
# Lister les valeurs d'un label
kubectl get pods -L k8s-app
# Lister to les labels d'un object
kubectl get deploy --show-labels
kubectl get deploy,po --show-labels
# Utiliser la forme négative
kubectl get po -A -l k8s-app!=kube-dnsAnnotationsAnnotations : C'est comme un commentaire ou une note sur un document. Il fournit des informations supplémentaires pour les humains ou d'autres outils (comme le nom de l'auteur, la date de la dernière révision ou un lien vers une documentation externe), mais il ne change pas la manière dont le document est traité par le système principal.
Multiples: Un objet peut avoir plusieurs annotations.
Annotations
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
cert-manager.io/cluster-issuer: theClusterIssuer
spec:
rules:
- http:
paths:
- path: /testpath
pathType: Prefix
backend:
service:
name: test
port:PodPods : Un Pod est comme un appartement dans un immeuble. L'appartement fournit l'environnement essentiel (murs, électricité, eau) pour ses habitants (les conteneurs). Tous les habitants de l'appartement partagent la même adresse (adresse IP) et peuvent facilement communiquer entre eux. Ils partagent des ressources comme la cuisine et la salle de bain (volumes, réseau).
C'est la plus petite et la plus simple unité dans Kubernetes
En savoir plus : https://kubernetes.io/fr/docs/concepts/workloads/pods/pod/
Pod
docker-compose :apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80PodDans les statuts du pod on trouve la notion de phase d'exécution
Pending: accepté par le cluster, les container ne sont pas initialiséRunning: Au moins un des containers est en cours de démarrage, d'exécution ou de redémarrageSucceeded: Tous les containers se sont arrêtés avec un "exit code" à 0 (zéro); Le pod ne sera pas redémarréFailed: Tous les containers se sont arrêtés et au moins un a un exit code différent de 0Unknown: L'état du pod ne peut pas être déterminé$ kubectl get pods -o wideen sortie :
NAME READY STATUS RESTARTS AGE IP NODE
xx-79c5968bdc-6lcfq 1/1 Running 0 84m 10.244.0.6 kind-cp
yy-ss7nk 1/1 Running 0 84m 10.244.0.5 kind-cpPodDans les statuts du pod on trouve la notion de Conditions d'état des pods
PodScheduled: Un nœud a été sélectionné avec succès pour "lancer" le pod, et la planification est terminée.ContainersReady: Tous les containers sont prêtsInitialized: Les "Init containers sont démarrés"Ready: Le pod est capable de répondre aux demandes ; par conséquent, il doit être inclus dans le service et les répartiteurs de charge.kubectl describe pods <POD_NAME>en sortie
...
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
...PodÉtats des containers (States)
Les containers peuvent avoir seulement 3 états
Waiting: Les processus requis sont en cours d'exécution pour un démarrage réussiRunning: Le container est en cours d'exécutionTerminated: L'exécution du conteneur s'est déroulée et s'est terminée par un succès ou un échec.$ kubectl get pods <POD_NAME> -o jsonpath='{.status}' | jqPod
DeploymentDeployments : C'est comme le gérant d'une chaîne de cafés identiques. Le travail du gérant est de s'assurer qu'un certain nombre de cafés (Pods/réplicas) sont toujours ouverts et fonctionnent de la même manière. Si un café ferme de manière inattendue, le gérant en ouvre un nouveau immédiatement. S'il veut changer le menu (mettre à jour l'application), le gérant déploie le changement dans tous les cafés, un par un, sans les fermer tous en même temps.
Souvent combiné avec un objet de type service
DeploymentapiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:stable
ports:
- containerPort: 80Ou en ligne de commande
kubectl create deployment my-app --image=nginx:latest --replicas=3Deployment
DaemonSetDaemonSets : Pensez à avoir un agent de sécurité à chaque étage d'un immeuble. Vous ne spécifiez pas combien de gardes vous avez besoin au total ; vous déclarez simplement que chaque étage doit en avoir exactement un. Si un nouvel étage est ajouté, un nouveau garde lui est automatiquement assigné.
replicas.fluentd ou logstashnvidia-pluginDaemonSet
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: ssd-monitor
spec:
selector:
matchLabels:
app: ssd-monitor
template:
metadata:
labels:
app: ssd-monitor
spec:
nodeSelector:
disk: ssd
containers:
- name: main
image: luksa/ssd-monitorStatefulSetStatefulSets : C'est la différence entre le bétail (cattle) et les animaux de compagnie (pets). Un Deployment gère le bétail : si une vache tombe malade, vous la remplacez par une autre en bonne santé, et cela n'a pas d'importance. Un StatefulSet gère les animaux de compagnie : si votre chien Fido est malade, vous voulez que Fido soit soigné et revienne. Vous ne voulez pas un nouveau chien identique. Les StatefulSets donnent à chaque Pod une identité unique et stable (un nom comme db-0, db-1) et un stockage persistant qui lui est propre. C'est essentiel pour les applications comme les bases de données, où chaque instance a un rôle et des données spécifiques qui doivent être préservés.
Deployment mais les noms des composants sont prédictiblesPersistent Volume et un Storage Class.Supprimer un StatefulSet ne supprime pas le PV associé

StatefulSetapiVersion: apps/v1
kind: StatefulSet
metadata:
name: web
spec:
selector:
matchLabels:
app: nginx
serviceName: "nginx"
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80kubectl get po
NAME READY STATUS RESTARTS AGE
web-0 0/1 ContainerCreating 0 3s
❯ kubectl get po
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 9s
web-1 0/1 ContainerCreating 0 1s
❯ kubectl get po
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 12s
web-1 1/1 Running 0 4s
web-2 0/1 ContainerCreating 0 2s
❯ kubectl get po
NAME READY STATUS RESTARTS AGE
web-0 1/1 Running 0 15s
web-1 1/1 Running 0 7s
web-2 1/1 Running 0 5sStatefulSet avancé
apiVersion: v1
kind: ConfigMap
metadata:
name: mysql
labels:
app: mysql
app.kubernetes.io/name: mysql
data:
primary.cnf: |
[mysqld]
log-bin
replica.cnf: |
[mysqld]
super-read-only
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
selector:
matchLabels:
app: mysql
app.kubernetes.io/name: mysql
serviceName: mysql
replicas: 3
template:
metadata:
labels:
app: mysql
app.kubernetes.io/name: mysql
spec:
initContainers:
- name: init-mysql
image: mysql:5.7
command:
- bash
- "-c"
- |
set -ex
[[ `hostname` =~ -([0-9]+)$ ]] || exit 1
ordinal=${BASH_REMATCH[1]}
echo [mysqld] > /mnt/conf.d/server-id.cnf
echo server-id=$((100 + $ordinal)) >> /mnt/conf.d/server-id.cnf
if [[ $ordinal -eq 0 ]]; then
cp /mnt/config-map/primary.cnf /mnt/conf.d/
else
cp /mnt/config-map/replica.cnf /mnt/conf.d/
fi
....
- name: clone-mysql
image: gcr.io/google-samples/xtrabackup:1.0
command:
- bash
- "-c"
- |
set -ex
[[ -d /var/lib/mysql/mysql ]] && exit 0
# Skip the clone on primary (ordinal index 0).
[[ `hostname` =~ -([0-9]+)$ ]] || exit 1
ordinal=${BASH_REMATCH[1]}
[[ $ordinal -eq 0 ]] && exit 0
ncat --recv-only mysql-$(($ordinal-1)).mysql 3307 | xbstream -x -C /var/lib/mysql
...
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ALLOW_EMPTY_PASSWORD
value: "1"
...JobJobs : C'est comme une tâche ponctuelle pour un entrepreneur, par exemple, "peindre cette pièce". L'entrepreneur (Job) vient, apporte ses outils (conteneur), effectue le travail (exécute le processus), et part une fois que le travail est terminé avec succès. S'il renverse la peinture et fait un gâchis (échec), il devra peut-être nettoyer et réessayer.
Si un noeud du cluster est en panne, les pods sont reschedulés vers un autre noeud.

JobapiVersion: batch/v1
kind: Job
metadata:
name: pi
spec:
parallelism: 1
completions: 1
template:
metadata:
name: pi
spec:
containers:
- name: pi
image: perl
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: OnFailureEn ligne de commande :
kubectl create job exemple-job --image=busybox -- /bin/sh -c "date; echo Hello from the Kubernetes cluster"CronJobCronJobs : Imaginez un service de nettoyage quotidien programmé pour un bureau. Le service (CronJob) est configuré pour venir chaque jour à 18h (l'horaire) pour effectuer la tâche de nettoyage (le Job). C'est une tâche récurrente et automatisée.
Cronle champ jobTemplate contient la définition de l'application à lancer comme Job.

CronJobapiVersion: batch/v1
kind: CronJob
metadata:
name: batch-job-every-fifteen-minutes
spec:
schedule: '0,15,30,45 * * * *'
jobTemplate:
spec:
template:
metadata:
labels:
app: periodic-batch-job
spec:
restartPolicy: OnFailure
containers:
- name: pi
image: perl
command:
- perl
- '-Mbignum=bpi'
- '-wle'
- print bpi(2000)En ligne de commande :
kubectl create cronjob exemple-cronjob --image=busybox --schedule="*/5 * * * *" -- /bin/sh -c "date; echo Hello from the Kubernetes cluster"Susprendre un cronjob :
kubectl patch cronjob <cronjob-name> -p '{"spec" : {"suspend" : true }}'Reprendre l'exécution :
kubectl patch cronjob <cronjob-name> -p '{"spec" : {"suspend" : false }}'Serviceapp=ventes), et il vous mettra en relation avec une personne disponible dans ce département. Le réceptionniste fournit un point de contact stable.Un Service est un objet Kubernetes qui fournit une abstraction pour accéder à un ensemble de Pods. Il agit comme un point d'entrée unique et stable pour les applications, même si les Pods derrière lui sont créés, détruits ou déplacés.
Voici ses principales caractéristiques :
ClusterIP) et un nom DNS stables qui ne changent pas pendant son cycle de vie. Les applications clientes se connectent au Service plutôt qu'aux Pods directement, dont les adresses IP sont éphémères.labels et des sélecteurs pour identifier dynamiquement l'ensemble des Pods auxquels il doit acheminer le trafic. Cela permet de découpler les applications qui consomment le service des Pods qui le fournissent.Cet objet est fondamental pour la communication inter-applicative au sein du cluster. Nous aborderons en détail les différents types de Services (comme ClusterIP, NodePort, et LoadBalancer) et leurs cas d'usage dans un chapitre dédié au réseau dans Kubernetes.
Init Containersexemple :
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
labels:
app.kubernetes.io/name: MyApp
spec:
containers:
- name: myapp-container
image: busybox:1.28
command: ['sh', '-c', 'echo The app is running! && sleep 3600']
initContainers:
- name: init-myservice
image: busybox:1.28
command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"]
- name: init-mydb
image: busybox:1.28
command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]Init ContainersrestartPolicy du Pod. Cependant, si la restartPolicy du Pod est définie sur Always, les conteneurs d'initialisation utilisent la restartPolicy OnFailure.Ready tant que tous les conteneurs d'initialisation n'ont pas réussi. Les ports d'un conteneur d'initialisation ne sont pas agrégés sous un Service.Pending mais doit avoir une condition Initialized définie à false.Si le Pod redémarre, ou est redémarré, tous les conteneurs d'initialisation doivent s'exécuter à nouveau.
L'approche déclarative consiste à décrire l'état désiré des ressources. Vous déclarez ce que vous voulez obtenir, et Kubernetes s'occupe de mettre en place et de maintenir cet état.
Il facilite également le travail entre équipe.
L'approche impérative consiste à donner des instructions directes à Kubernetes pour effectuer des actions spécifiques. On décrit comment réaliser une tâche, pas seulement le résultat final.
Recommandé dans des environnements de lab ou pour tester une commande
kubectl run nginx --image=nginxkubectl run nginx --image=nginx --dry-run=client -o yamlkubectl create deployment nginx --image=nginx --replicas=4kubectl scale:kubectl scale deployment nginx --replicas=4kubectl create deployment nginx --image=nginx --dry-run=client -o yaml > nginx-deployment.yamlkubectl expose pod redis --port=6379 --name redis-service --dry-run=client -o yamlkubectl expose pod nginx --type=NodePort --port=80 --name=nginx-service --dry-run=client -o yamlkubectl create service nodeport nginx --tcp=80:80 --node-port=30080 --dry-run=client -o yamlCeci n'utilisera pas les labels des pods comme sélecteurs.
Plugin: Un CNI est implémenté sous forme de plugin, ce qui permet de choisir le plugin adapté aux environnements et besoins.


ClusterIP :
apiVersion: v1
kind: Service
metadata:
name: the-service
spec:
ports:
- port: 80
protocol: TCP
targetPort: 8080
selector:
app: web# déploiement
kubectl create deployment web --image=nginx
# service
# par défaut type= ClusterIP
kubectl expose deploy web --port=80 --target-port=8080Headless ClusterIP :
apiVersion: v1
kind: Service
metadata:
name: my-headless-service
spec:
clusterIP: None # <--
selector:
app: test-app
ports:
- protocol: TCP
port: 80
targetPort: 3000# déploiement
kubectl create deployment web --image=nginx
# service
kubectl expose deploy web --port=80 --target-port=8080 --cluster-ip noneNodePort :
apiVersion: v1
kind: Service
metadata:
name: my-nginx
spec:
type: NodePort
ports:
- port: 8080
targetPort: 80
protocol: TCP
name: http
selector:
app: my-nginx# déploiement
kubectl create deployment web --image=nginx
# service
kubectl expose deploy web --type NodePort --protocol TCP --port 80 --target-port 8080LoadBalancer : expose le service à l'externe en utilisant le loadbalancer d'un cloud provider (AWS, Google, Azure)
Service de type Spécial
apiVersion: v1
kind: Service
metadata:
name: myapp
spec:
ports:
- port: 9000
targetPort: 1234
selector:
app: myapp
type: LoadBalancer# déploiement
kubectl create deployment web --image=myapp
# service
kubectl expose deploy web --type LoadBalancer --protocol TCP --port 9000 --target-port 1234ExternalName
Exemples d'utilisation concrets :
Il est aussi possible de mapper un service avec un nom de domaine en spécifiant le paramètre spec.externalName.
kind: Service
apiVersion: v1
metadata:
name: my-service
namespace: prod
spec:
type: ExternalName
externalName: my.database.example.comEn ligne de commande :
kubectl create service externalname my-service --external-name my.database.example.comOn peut définir une IP externe permettant d'accèder à un service interne
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app: nginx
name: nginx
spec:
externalIPs:
- 1.2.3.4
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginxEn ligne de commande :
kubectl expose deploy nginx --port=80 --external-ip=1.2.3.4ClusterIP : C'est le type de service par défaut. Il fournit une IP virtuelle stable accessible uniquement à l'intérieur du cluster, parfait pour la communication entre microservices.
NodePort : Il étend ClusterIP en exposant le service sur un port spécifique de chaque nœud du cluster. C'est utile pour le développement ou les environnements de test.
LoadBalancer : Idéal pour la production, il étend NodePort en provisionnant automatiquement un load balancer externe (souvent fourni par le cloud provider).
ExternalName : Un cas particulier qui permet de créer un alias CNAME vers un service externe au cluster.
Headless Service : A Utiliser quand vous avez besoin d'une découverte de service fine, sans Load Balancing. Très utile pour les bases de données distribuées.
ExternalIPs : Permet d'exposer un service Kubernetes sur une adresse IP spécifique qui existe déjà sur l'un des nœuds du cluster, offrant ainsi un accès direct depuis l'extérieur sans passer par un LoadBalancer.
Choisir le bon type de service dans Kubernetes est essentiel pour l'architecture de votre application. Voici un guide pour vous aider à décider :
ClusterIP
NodePort
http://<IP_DU_NOEUD>:<NODE_PORT>.LoadBalancer
ExternalName
ExternalName (database.local) qui pointe vers l'endpoint externe (xxxx.rds.amazonaws.com).Headless Service
ExternalIPs
<Cluster IP Address><Service Port>kubectl get svc
web ClusterIP 10.96.163.5 <none> 80/TCP 3m56s
kubectl exec web-96d5df5c8-lfmhs -- env | sort
WEB_SERVICE_HOST=10.96.163.5
WEB_SERVICE_PORT=80my-app comme nom d'hôte dans le même namespacemy-app.default comme nom d'hôte dans d'autres namespace<svc name>.<ns>.svc.cluster.localex: my-app.default.svc.cluster.local
Ingress permet d'exposer un service à l'extérieur d'un cluster Kubernetes
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
cert-manager.io/cluster-issuer: le
meta.helm.sh/release-name: argocd
meta.helm.sh/release-namespace: argocd
labels:
app.kubernetes.io/component: server
app.kubernetes.io/instance: argocd
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: argocd-server
app.kubernetes.io/part-of: argocd
app.kubernetes.io/version: v2.10.1
helm.sh/chart: argo-cd-6.0.14
name: argocd-server
namespace: argocd
spec:
ingressClassName: nginx
rules:
- host: argocd.caas.fr
http:
paths:
- backend:
service:
name: argocd-server
port:
number: 443
path: /
pathType: Prefix
tls:
- hosts:
- argocd.caas.fr
secretName: argocd-server-tlsPour utiliser un Ingress, il faut un Ingress Controller
Il existe plusieurs solutions OSS ou non :
⚠︎ Note : Il est possible d'avoir plusieurs Ingress Controller sur un cluster il suffira dans les objets ingress de préciser sur quelle classe d'ingress on souhaite le créer.
Ca se fait par l'attribut ingressClassName.
Ces classes sont créees au moment de l'installation du contrôleur.
Les Ingress vont bientôt être dépréciés en faveur des Gateway API qui sont la nouvelle génération de Kubernetes Ingress, Load Balancing, et Service Mesh APIs.
Plus d'informations ici : https://gateway-api.sigs.k8s.io/
Les Gateway APIs sont une évolution des Ingress Controllers, offrant une approche plus moderne et flexible pour gérer le trafic entrant dans un cluster Kubernetes. Voici les points essentiels :
Architecture en layers:
Avantages principaux:
- Configuration plus fine et granulaire
- Support natif de plusieurs protocoles
- Meilleure séparation des responsabilités
- API plus extensible et cohérente
Cas d'utilisation:
- Multi-tenancy avec isolation du trafic
- Gestion avancée du routage
- Configuration du TLS
- Gestion du trafic nord-sud et est-ouest
Différence avec les Ingress:
Les Gateway APIs offrent plus de fonctionnalités que les Ingress traditionnels :
- Support multi-protocole natif
- Meilleure extensibilité
- Configuration plus détaillée
- Meilleure séparation des rôles
EmptyDir ~= volumes dockerHostPath ~= volumes hôteapiVersion: v1
kind: Pod
metadata:
name: redis
spec:
containers:
- name: redis
image: redis
volumeMounts:
- name: redis-persistent-storage
mountPath: /data/redis
volumes:
- name: redis-persistent-storage
emptyDir: {}apiVersion: v1
kind: Pod
metadata:
name: redis
spec:
containers:
- name: redis
image: redis
volumeMounts:
- name: redis-persistent-storage-host
mountPath: /data/redis
volumes:
- name: redis-persistent-storage-host
hostPath:
path: /mnt/data/redisPersistent Volume (PV) : Représentation de bas niveau d'un volume de stockage.Persistent Volume Claim (PVC) : binding entre un Pod et un Persistent Volume (PV).Storage Class : Permet de provionner dynamiquement d'un Persistent Volumes (PV).
Persistent Volumes pour solliciter un espace de stockage au travers des Persistent Volume Claimskind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
name: slow
provisioner: kubernetes.io/aws-ebs
parameters:
type: io1
zones: us-east-1d, us-east-1c
iopsPerGB: "10"Autre exemple
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: managed-premium
labels:
addonmanager.kubernetes.io/mode: EnsureExists
kubernetes.io/cluster-service: "true"
parameters:
cachingmode: ReadOnly
kind: Managed
storageaccounttype: Premium_LRS
provisioner: kubernetes.io/azure-disk
reclaimPolicy: Delete
volumeBindingMode: Immediate
allowVolumeExpansion: trueAutre exemple
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
annotations:
storageclass.kubernetes.io/is-default-class: "true"
name: local-path
provisioner: rancher.io/local-path
reclaimPolicy: Delete
volumeBindingMode: WaitForFirstConsumerStorageClass
apiVersion: v1
kind: PersistentVolume
metadata:
name: persistent-volume-1
spec:
storageClassName: slow
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/tmp/data"StorageClass auront la politique de récupération spécifiée dans le champ reclaimPolicy de la classe, qui peut être Delete ou Retain.Si aucun reclaimPolicy n'est spécifié lors de la création d'un objet StorageClass, il sera par défaut delete.
Les PV qui sont créés manuellement et gérés via une StorageClass auront la politique de récupération qui leur a été attribuée lors de la création.
La stratégie de récupération s'applique aux volumes persistants et non à la classe de stockage elle-même. Les PV et les PVC créés à l'aide de cette StorageClass hériteront de la stratégie de récupération définie dans StorageClass.
pod et un PV. Le pod demande le volume via le PVC.StatefulSets pour solliciter du stockage (Utilisation du champ volumeClaimTemplates)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: storage-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
storageClassName: "slowl"
selector:
matchLabels:
release: "stable"
matchExpressions:
- {key: capacity, operator: In, values: [10Gi, 20Gi]}Utilisation d'un PVC dans un pod
apiVersion: v1
kind: Pod
metadata:
name: myapp
spec:
containers:
- name: myapp
image: nginx
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: mywebsite
volumes:
- name: mywebsite
persistentVolumeClaim:
claimName: myclaim
ConfigMap peut être sollicité (utilisé) par plusieurs podsapiVersion: v1
kind: ConfigMap
metadata:
name: redis-config
data:
redis-config: |
maxmemory 2mb
maxmemory-policy allkeys-lruapiVersion: v1
kind: ConfigMap
metadata:
name: redis-env
data:
redis_host: "redis_svc"
redis_port: "6349"apiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: k8s.gcr.io/busybox
command: [ "/bin/sh", "-c", "env" ]
env:
- name: REDIS_HOST
valueFrom:
configMapKeyRef:
name: redis-env
key: redis_host
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: env-config
key: log_level
restartPolicy: NeverapiVersion: v1
kind: Pod
metadata:
name: dapi-test-pod
spec:
containers:
- name: test-container
image: k8s.gcr.io/busybox
command: [ "/bin/sh", "-c", "ls /etc/config/" ]
volumeMounts:
- name: redis-conf-volume
mountPath: /etc/config
volumes:
- name: redis-conf-volume
configMap:
# Provide the name of the ConfigMap containing the files you want
# to add to the container
name: redis-config
restartPolicy: Neverkubectl create configmap my-config --from-file=./my/dir/path/kubectl create configmap my-config --from-file=./my/dir/path/myfile.txtkubectl create configmap my-config --from-literal=key1=value1 --from-literal=key2=value2secret utilisé pour stocker des informations sensibles comme les mots de passe, les tokens, les clés SSH...ConfigMap, à la seule différence que le contenu des entrées présentes dans le champ data sont encodés en base64.Secret spécifique à l'authentification sur un registre Docker privé.Secret à partir d'un compte utilisateur et d'un mot de passe.Generic: valeurs arbitraire comme dans une ConfigMaptls: certificat et clé pour utilisation avec un serveur webdocker-registry: utilisé en tant que imagePullSecret par un pod pour pouvoir pull les images d'une registry privée$ kubectl create secret docker-registry mydockerhubsecret \
--docker-username="employeeusername" --docker-password="employeepassword" \
--docker-email="employee.email@organization.com"kubectl create secret generic dev-db-secret --from-literal=username=devuser --from-literal=password='S!B\*d$zDsb'apiVersion: v1
kind: Secret
metadata:
creationTimestamp: 2016-01-22T18:41:56Z
name: mysecret
namespace: default
resourceVersion: "164619"
uid: cfee02d6-c137-11e5-8d73-42010af00002
type: Opaque
data:
username: YWRtaW4=
password: MWYyZDFlMmU2N2RmSe base sur le CPU et la RAM
Exemple concret :
Un nœud Kubernetes avec 4 cœurs CPU.
- Pod BestEffort: Il peut utiliser 0, 1, 2, 3 ou 4 cœurs, selon la disponibilité.
- Pod Burstable (requests: 2 cœurs, pas de limits): Il est garanti d'avoir au moins 2 cœurs, mais il peut en utiliser jusqu'à 4 s'ils sont disponibles. Si un pod Guaranteed a besoin de 2 cœurs, le pod Burstable peut en perdre 2.
- Pod Guaranteed (requests: 2 cœurs, limits: 2 cœurs): Il a toujours 2 cœurs garantis et ne peut pas en utiliser plus.
1 : 1 vCPU entier100m : 0.1 vCPU0.5 : 1/2 vCPUM : en base 10Mi : en base 2apiVersion: v1
kind: Pod
metadata:
name: frontend
spec:
containers:
- name: db
image: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: "password"
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
- name: wp
image: wordpress
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"LimitRange permet de définir les valeurs minimales et maximales des ressources utilisées par les containers et les pods pour les requests et limits de CPU, de mémoire et de stockageLimitRange s'applique au niveau du namespacenamespaceLimitRange ne limite pas le nombre total de ressources disponibles dans le namespaceapiVersion: v1
kind: LimitRange
metadata:
name: limit-example
spec:
limits:
- default:
memory: 512Mi
defaultRequest:
memory: 256 Mi
type: ContainerResourceQuota limite le total des ressources de calcul consommées par les pods ainsi que le total de l'espace de stockage consommé par les PersistentVolumeClaims dans un namespacepods, PVC, réplicas, services et autres objets qui peuvent être créés dans un namespaceapiVersion: v1
kind: ResourceQuota
metadata:
name: cpu-and-ram
spec:
hard:
requests.cpu: 400m
requests.memory: 200Mi
limits.cpu: 600m
limits.memory: 500MiapiVersion: v1
kind: ResourceQuota
metadata:
name: quota-for-objects
spec:
hard:
pods: 200
services: 10
secrets: 20
configmaps: 40
persistentvolumeclaims: 40
services.nodeports: 0
services.loadbalancers: 0
count/roles.rbac.authorization.k8s.io: 10
initialDelaySeconds des Readiness et LivenesshttpGetpath et httpHeaders supplémentaires peuvent être spécifiés de manière optionnelleexectcpSocketgrpcapiVersion: v1
kind: Pod
metadata:
name: test-grpc
spec:
containers:
- name: agnhost
image: registry.k8s.io/e2e-test-images/agnhost:2.35
command: ["/agnhost", "grpc-health-checking"]
ports:
- containerPort: 5000
- containerPort: 8080
readinessProbe:
grpc:
port: 5000Plus d'informations : https://kubernetes.io/blog/2022/05/13/grpc-probes-now-in-beta/
aapiVersion: v1
kind: Pod
metadata:
name: my-app
spec:
containers:
- name: my-app-container
image: my-image
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /healthz
port: 8080
httpHeaders:
- name: Authorization
value: Bearer my-token
initialDelaySeconds: 15
periodSeconds: 5
timeoutSeconds: 1
failureThreshold: 3
livenessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 5
startupProbe:
exec:
command:
- cat /etc/nginx/nginx.conf
initialDelaySeconds: 10
timeoutSeconds: 5initialDelaySeconds
initialDelaySeconds (défaut : 0).temps et seuils
Si une startupProbe échoue, Kubernetes redémarre le conteneur correspondant.
En d'autres termes : avec les paramètres par défaut, le conteneur doit démarrer en 30 secondes. (failureThreshold × periodSeconds)
C'est pourquoi il faut presque toujours ajuster les paramètres d'une startupProbe. (spécifiquement, son failureThreshold)
Parfois, il est plus facile d'utiliser une readinessProbe à la place.(voir la prochaine diapositive pour plus de détails)
N'utilisez pas de probes de liveness pour des problèmes qui ne peuvent pas être résolus par un redémarrage. Sinon, les pods redémarrent sans raison, créant une charge inutile.
Ne dépendez pas d'autres services au sein d'une probe de liveness. Sinon, Possibilités d'échecs en cascade.(exemple : probe de liveness d'un serveur web qui effectue des requêtes vers une base de données)Assurez-vous que les probes de liveness répondent rapidement.
Le délai d'expiration par défaut des probes est de 1 seconde (cela peut être ajusté).
Si la probe prend plus de temps que cela, il finira par provoquer un redémarrage.
Une startupProbe nécessite généralement de modifier le failureThreshold.
Une startupProbe nécessite généralement également une readinessProbe.
Une seule readinessProbe peut remplir les deux rôles.
L'API Kubernetes inclut également des points de terminaison de contrôle d'état : healthz (obsolète), readyz, livez.
kubectl get --raw='/readyz?verbose'Point de terminaison readyz
[+]ping ok
[+]log ok
[+]etcd ok
[+]informer-sync ok
[+]poststarthook/start-kube-apiserver-admission-initializer ok
[+]poststarthook/generic-apiserver-start-informers ok
[+]poststarthook/priority-and-fairness-config-consumer ok
[+]poststarthook/priority-and-fairness-filter ok
[+]poststarthook/start-apiextensions-informers ok
[+]poststarthook/start-apiextensions-controllers ok
[+]poststarthook/crd-informer-synced ok
[+]poststarthook/bootstrap-controller ok
[+]poststarthook/rbac/bootstrap-roles ok
[+]poststarthook/scheduling/bootstrap-system-priority-classes ok
[+]poststarthook/priority-and-fairness-config-producer ok
[+]poststarthook/start-cluster-authentication-info-controller ok
[+]poststarthook/aggregator-reload-proxy-client-cert ok
[+]poststarthook/start-kube-aggregator-informers ok
[+]poststarthook/apiservice-registration-controller ok
[+]poststarthook/apiservice-status-available-controller ok
[+]poststarthook/kube-apiserver-autoregistration ok
[+]autoregister-completion ok
[+]poststarthook/apiservice-openapi-controller ok
[+]shutdown ok
readyz check passedPoint de terminaison livez
kubectl get --raw='/livez?verbose'
+]ping ok
[+]log ok
[+]etcd ok
[+]poststarthook/start-kube-apiserver-admission-initializer ok
[+]poststarthook/generic-apiserver-start-informers ok
[+]poststarthook/priority-and-fairness-config-consumer ok
[+]poststarthook/priority-and-fairness-filter ok
[+]poststarthook/start-apiextensions-informers ok
[+]poststarthook/start-apiextensions-controllers ok
[+]poststarthook/crd-informer-synced ok
[+]poststarthook/bootstrap-controller ok
[+]poststarthook/rbac/bootstrap-roles ok
[+]poststarthook/scheduling/bootstrap-system-priority-classes ok
[+]poststarthook/priority-and-fairness-config-producer ok
[+]poststarthook/start-cluster-authentication-info-controller ok
[+]poststarthook/aggregator-reload-proxy-client-cert ok
[+]poststarthook/start-kube-aggregator-informers ok
[+]poststarthook/apiservice-registration-controller ok
[+]poststarthook/apiservice-status-available-controller ok
[+]poststarthook/kube-apiserver-autoregistration ok
[+]autoregister-completion ok
[+]poststarthook/apiservice-openapi-controller ok
livez check passedUn nœud avec un taint empêche l'exécution sur lui-même des pods qui ne tolèrent pas ce taint
key=value:Effect
Ce champ peut avoir 3 valeurs : NoSchedule, PreferNoSchedule, NoExecute
Equal (key=value:Effect)Exist (keyExist:Effect)En ligne de commande
kubectl taint nodes THENODE special=true:NoExecutekubectl taint node worker-0 node-role.kubernetes.io/master="":NoSchedulekubectl taint node worker-2 test:NoSchedulekubectl taint nodes THENODE special=true:NoExecute-kubectl taint node worker-0 node-role.kubernetes.io/master-kubectl taint node worker-2 test:NoSchedule-kubectl get nodes THENODE -o jsonpath="{.spec.taints}"[{"effect":"NoSchedule","key":"node-role.kubernetes.io/master"}]Les tolerations peuvent être décrites au niveau des pods ou au niveau des templates de pods dans les replicaset, daemonset, statefulset et deployment.
Ces tolerations permettront aux pods de s'exécuter sur les nœuds qui ont le taint correspondant.
apiVersion: v1
kind: Pod
metadata:
...
spec:
tolerations:
- key: node-role.kubernetes.io/master
effect: NoScheduleapiVersion: v1
kind: Pod
metadata:
...
spec:
tolerations:
- key: special
value: "true"
effect: NoExecute
Operator: EqualUne clé vide avec un opérateur Exist fera en sorte que le pod s'exécutera sur tous les nœuds quelque soit leurs taints
exemple :
tolerations:
- operator: "Exists"
Exemples
kubectl label nodes <node-name> <label-key>=<label-value>kubectl label nodes worker-0 disktype=ssd
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
nodeSelector:
disktype: ssdCe système permet de gérer très finement les règles de placement des pods en regard de la simplicité du nodeSelector
soft (pod déployé malgré tout) ou hard (pod déployé uniquement si les règles sont respectées)
preferredDuringSchedulingIgnoredDuringExecutionrequiredDuringSchedulingIgnoredDuringExecutionapiVersion: v1
kind: Pod
metadata:
name: with-node-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/e2e-az-name
operator: In # (NotIn, Exists, DoesNotExist, Gt, Lt)
values:
- e2e-az1
- e2e-az2
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: another-node-label-key
operator: In # (NotIn, Exists, DoesNotExist, Gt, Lt)
values:
- another-node-label-value
containers:
- name: with-node-affinity
image: k8s.gcr.io/pause:2.0apiVersion: v1
kind: Pod
metadata:
name: with-node-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values:
- ssd
containers:
- name: with-node-affinity
image: k8s.gcr.io/pause:2.0apiVersion: v1
kind: Pod
metadata:
name: with-node-affinity
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/e2e-az-name
operator: In
values:
- e2e-az1
- e2e-az2
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: another-node-label-key
operator: In
values:
- another-node-label-value
containers:
- name: with-node-affinity
image: k8s.gcr.io/pause:2.0apiVersion: v1
kind: Pod
metadata:
name: with-pod-affinity
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S1
topologyKey: topology.kubernetes.io/zone
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: security
operator: In
values:
- S2
topologyKey: topology.kubernetes.io/zone
containers:
- name: with-pod-affinity
image: k8s.gcr.io/pause:2.0kubectl top pods et kubectl top nodes$ kubectl top nodes
NAME CPU(cores) CPU% MEMORY(bytes) MEMORY%
gke-cka-pool1-8e771340-lzju 86m 4% 736Mi 13%
gke-cka-pool1-f884d89f-pnbx 155m 8% 811Mi 14%$ kubectl -n lab top pods
NAME CPU(cores) MEMORY(bytes)
lab-middleware-c46cd576f-5vltl 1m 40Mi
lab-middleware-c46cd576f-7zckz 1m 43Mikubectl logs-f permet de diffusion en direct des logs$ kubectl -n lab get pods
NAME READY STATUS RESTARTS AGE
lab-middleware-c46cd576f-5vltl 1/1 Running 0 17d
lab-middleware-c46cd576f-7zckz 1/1 Running 0 17d$ kubectl -n lab logs lab-middleware-c46cd576f-5vltl
info: serving app on http://0.0.0.0:3333
[bugsnag] Loaded!
[bugsnag] Bugsnag.start() was called more than once. Ignoring.
[bugsnag] Bugsnag.start() was called more than once. Ignoring.
[bugsnag] Bugsnag.start() was called more than once. Ignoring.Voici quelques stratégies de mise à jour des applications
Caractéristiques du RollingUpdate :
Caractéristiques du Blue-Green Deployment :
Le mode de mise à jour "Recreate" dans Kubernetes est une stratégie utilisée pour déployer de nouvelles versions d'applications. Voici ses principales caractéristiques :
Voici un exemple de configuration pour utiliser la stratégie "Recreate" dans un fichier de déploiement Kubernetes (deployment.yaml) :
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
replicas: 3
strategy:
type: Recreate
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: my-app-image:latest
ports:
- containerPort: 80Cette configuration spécifie que Kubernetes doit utiliser la stratégie "Recreate" pour mettre à jour l'application my-app.
Si vous avez un ingress controller nginx faire du canary release est très simple.
Caractéristiques du Canary Deployment :
Test en Conditions Réelles : -La nouvelle version est testée en conditions réelles avec un sous-ensemble d'utilisateurs, ce qui permet de détecter les problèmes et de les corriger avant un déploiement complet.
Voir le lab dédié
Qu'est-ce que l'autoscaling?
L'autoscaling est une technique qui permet d'ajuster automatiquement les ressources informatiques en fonction de la demande.
Dans le contexte de Kubernetes, l'autoscaling permet de :
Ajouter ou supprimer des Pods (unité de déploiement de Kubernetes) en fonction de l'utilisation des ressources.
Ajouter ou supprimer des nœuds (machines physiques ou virtuelles) dans le cluster pour répondre aux besoins de capacité.
Pourquoi est-ce important dans Kubernetes?
Optimisation des coûts : Réduire les coûts en ajustant dynamiquement les ressources en fonction de la demande réelle.
Haute disponibilité : Assurer que les applications restent disponibles et performantes en augmentant les ressources en cas de pics de charge.
Gestion efficace des ressources : Éviter le sur-provisionnement ou le sous-provisionnement des ressources.
Utilisé pour ajuster dynamiquement le nombre de pods en fonction de l'utilisation des ressources (CPU, mémoire, etc.).
apiVersion: autoscaling/v1
kind: HorizontalPodAutoscaler
metadata:
name: example-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: example-deployment
minReplicas: 1
maxReplicas: 10
targetCPUUtilizationPercentage: 50En ligne de commande
kubectl apply -f https://k8s.io/examples/application/php-apache.yaml
kubectl autoscale deployment php-apache --cpu-percent=50 --min=1 --max=10Ajuste le nombre de nœuds dans le cluster en fonction des besoins des pods.
Nécessite une intégration avec le fournisseur de cloud (GCP, AWS, Azure, etc.).
Exemple:
Configuration pour GCP.
apiVersion: autoscaling.k8s.io/v1
kind: ClusterAutoscaler
metadata:
name: cluster-autoscaler
spec:
scaleDown:
enabled: true
scaleUp:
enabled: trueVPA n'est pas natif à kubernetes il faut installer un contrôleur
https://github.com/kubernetes/autoscaler.git
Ajuste les ressources allouées à un pod en fonction de l'utilisation réelle.
Contrairement à l'Horizontal Pod Autoscaler (HPA), qui ajuste le nombre de pods, le VPA ajuste les ressources des pods existants.
Pourquoi utiliser le VPA ?
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: example-vpa
spec:
targetRef:
apiVersion: "apps/v1"
kind: Deployment
name: example-deployment
updatePolicy:
updateMode: "Auto"--recordreplicaSet (annotation)replicatset
$ kubectl create -f nginx.yaml --record
deployment.apps/nginx created
# Voir les informations
kubectl rollout history--record# déployer l'image worker:v0.2
kubectl create deployment worker --image=dockercoins/worker:v0.2
# Roll back `worker` vers l'image version 0.1:
kubectl set image deployment worker worker=dockercoins/worker:v0.1 --record
# Le remettre sur la version 0.2:
kubectl set image deployment worker worker=dockercoins/worker:v0.2 --record
# Voir l'historique des changement:
kubectl rollout history deployment workerkubectl scale :kubectl scale --replicas=5 deployment nginxkubectl set image deployment nginx nginx=nginx:1.15kubectl run nginx --image=nginx --dry-run=client
kubectl run nginx --image=nginx --dry-run=serverkubectl run nginx --image=nginx \
--command -- <cmd> <arg1> ... <argN>kubectl run pi --schedule="0/5 * * * ?" --image=perl --restart=OnFailure \
-- perl -Mbignum=bpi -wle 'print bpi(2000)'kubectl run -it busybox --image=busybox -- shkubectl attach my-pod -ikubectl port-forward my-svc 6000kubectl autoscale deployment my-Deployments --min=2 --max=10 --cpu-percent=70 kubectl pour diagnostiquer les applications et le cluster kubernetes :kubectl cluster-info
kubectl get events --sort-by='.lastTimestamp'
kubectl describe node <NODE_NAME>
kubectl describe node <node-name> | grep Taints
kubectl logs (-f) <POD_NAME>kubectl logs# exemple :
kubectl logs deploy/nginxCTRL-Cpour arrêter la sortiekubectl logs supporte les options suivantes : - -f/--follow pour suivre les affichage des logs en temps réel (comme pour tail -f) - --tail pour n'afficher que les n lignes à partir de la fin de la sortie - --since pour n'afficher que les logs à partir d'une certaine date - --timestampsaffichera le timestamp du message
# exemple :
kubectl logs deploy/pingpong --tail 100 --follow --since=5s
# Affichera toutes les logs depuis 5 secondes et commencera au 100eme messages et continuera l'affichage des nouveaux messagesLorsque on spécifie un nom de déploiement, seuls les logs d'un seul pod sont affichés
Pour afficher les logs de plusieurs pod il faudra utiliser un selecteur (label)
kubectl logs -l app=my-app --tail 100 # -f 
kubectl get nodes
kubectl describe nodeskubectl cordon <NODE_NAME>
kubectl drain <NDOE_NAME>
kubectl uncordon <NODE_NAME>
# lister les contextes
kubectl config get-contexts
# Se déplacer dans un contexte
kubectl config use-context <nom-du-contexte>
# ou
alias kubectx='kubectl config use-context '
# ex: kubectx <nom-du-cluster>Évite de toujours préciser le flag -n
kubectl get ns
kubectl config set-context --current --namespace <nom-du-namespace>
# ou
alias kubens='kubectl config set-context --current --namespace '
# ex: kubens kube-system krew est un manager de plugins pour kubectl
installation de krew (https://krew.sigs.k8s.io/docs/user-guide/setup/install/)
kubectl krew install example
kubectl example deployListe des plugins : https://krew.sigs.k8s.io/plugins/ très utiles :
neat : permet de d'avoir un ouput "propre" d'une resource kubernetes - très utile pour créer des manifestes à partir de resources existantesctx : permet de changer de contexte facilementns : permet de changet de namespace facilementnode-shell : Créer un shell racine sur un nœud via kubectl, très pratique sur les CSPdf-pv : Afficher l'utilisation du disque (comme la commande df) pour les volumes persistantspopeye : Analyse vos clusters pour détecter d'éventuels problèmes de ressourcesAuthentication (Qui êtes-vous ?):
Méthodes principales :
Résultat : identité confirmée ou requête rejetée
Authorization (Que pouvez-vous faire ?):
Composants clés :
3 entités sont utilisées :
Users ou les ServiceAccountsDeployments, Pods, Services, etc...create, list, get, delete, watch, patchServiceAccount par namespaceServiceAccount est formatté ainsi : system:serviceaccount:<namespace>:<service_account_name>apiVersion: v1
kind: ServiceAccount
metadata:
name: default
namespace: defaultRole est un ensemble de règles permettant de définir quelle opération (ou verbe) peut être effectuée et sur quelle ressourceRole ne s'applique qu'à un seul namespace et les ressources liées à ce namespacekind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]RoleBinding va allouer à un User, ServiceAccount ou un groupe les permissions dans l'objet Role associéRoleBinding doit référencer un Role dans le même namespace.roleRef spécifié dans le RoleBinding est celui qui crée le liaisonkind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: jane
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.ioClusterRole est similaire au Role à la différence qu'il n'est pas limité à un seul namespacenamespace comme les nodeskind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"] kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: salme-reads-all-pods
subjects:
- kind: User
name: jsalmeron
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.iokubectl auth can-i get pods /
--namespace=default /
--as=spesnova@example.com
La ressource NetworkPolicy est une spécification permettant de définir comment un ensemble de pods communiquent entre eux ou avec d'autres endpoints
Le NetworkPolicy utilisent les labels pour sélectionner les pods sur lesquels s'appliquent les règles qui définissent le trafic alloué sur les pods sélectionnés
Le NetworkPolicy est générique et fait partie de l'API Kubernetes. Il est nécessaire que le plugin réseau déployé supporte cette spécification
NetworkPolicy permettant de bloquer le trafic entrant :kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: web-deny-all
spec:
podSelector:
matchLabels:
app: web
ingress: []Cilium Network Policy Editor : https://editor.networkpolicy.io/?id=xJYCeLwGmAGxTqjm

Tufin Network Policy Viewer : https://orca.tufin.io/netpol/

Kubernetes NetworkPolicy viewer : https://artturik.github.io/network-policy-viewer/

Alpha en 1.22, GA depuis la 1.25
Plus simple que les PSP.
Trois labels optionnels peuvent être ajoutés aux namespaces :
pod-security.kubernetes.io/warn
audit = autorise la création mais génère un événement d'audit de l'API (sera visible si l'audit de l'API a été activé et configuré)
Les valeurs possibles sont :
(définir la valeur à privileged n'a pas vraiment d'effet)
apiVersion: v1
kind: Namespace
metadata:
labels:
kubernetes.io/metadata.name: formation-k8s
pod-security.kubernetes.io/enforce: baseline
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
name: formation-k8sLes trois lignes suivantes définissent les labels:
pod-security.kubernetes.io/enforce=baseline :
- Applique la politique de sécurité "baseline" en mode "enforce".
- Cela empêchera la création de pods qui ne respectent pas les critères de sécurité de base.
pod-security.kubernetes.io/audit=restricted :
- Configure l'audit en mode "restricted".
- Cela générera des événements d'audit pour les pods qui ne respectent pas les critères de sécurité restrictifs.
pod-security.kubernetes.io/warn=restricted :
- Active les avertissements en mode "restricted".
- Cela produira des avertissements lors de la création de pods qui ne respectent pas les critères de sécurité restrictifs.
apiVersion: v1
kind: Namespace
metadata:
labels:
kubernetes.io/metadata.name: formation-k8s
pod-security.kubernetes.io/enforce: privileged
pod-security.kubernetes.io/audit: privileged
pod-security.kubernetes.io/warn: privileged
name: formation-k8s(aux côtés de Containerd, Prometheus et Kubernetes lui-même)
A voir :
Charts.helm est un outil CLI
Il est utilisé pour trouver, installer, mettre à jour des charts
Un Chart est une archive contenant des bundles YAML modélisés. Un chart est pratiquement un regroupement de ressources Kubernetes pré-configurées.
Release : Une instance d'un chart helm s'exécutant dans un cluster Kubernetes.Repository : répertoire ou espace (public ou privé) où sont regroupés les charts.
Les charts sont versionnés
Les charts peuvent être stockés sur des référentiels privés ou publics
mychart/
├── Chart.yaml
├── charts
├── templates
│ ├── NOTES.txt
│ ├── _helpers.tpl
│ ├── deployment.yaml
│ ├── hpa.yaml
│ ├── ingress.yaml
│ ├── service.yaml
│ ├── serviceaccount.yaml
│ └── tests
│ └── test-connection.yaml
└── values.yaml
Installer Helm (sur une distribution Linux):
curl \
https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get-helm-3 | bashcharts disponibles sur les répertoires officiels : helm searchcharts disponibles pour prometheus : helm search prometheusAfficher les options disponibles dans un chart Helm: helm inspect stable/prometheus
Un repository (repo) est une collection de charts
Le surnom sert à référencer les charts de ce repo
(they can be hosted by a static HTTP server, or on a local directory) - Par exemple helm install hello/world : le chart world dans le repo hello, hello peut être quelque chose comme https://alterway.fr/charts/
Vérifions quels référentiels nous avons et ajoutons le référentiel stable
(le repo stable contient un ensemble des charts officiels)
# Lister vos repos:
helm repo list
# Ajouter the `stable` repo:
helm repo add stable https://charts.helm.sh/stableOn peut chercher les charts avec la commande suivante helm search
Il faut spécifier ou chercher repo ou hub
# Chercher nginx dans tous les repos ajoutés précédemment
helm search repo nginx
# Chercher nginx sur le hub Helm:
helm search hub nginxHelm Hub indexe tout un tas de repo, en utilisant le serveur Monocular.
"Installer un chart" veut dire installer une release
Il faut donner un nom à cette Release
(ou utiliser le flag --generate-name pour que helm le fasse automatiquement pour nous)
# Installer le chart nginx :
helm install nginx stable/nginx
# List the releases:
helm list# Lister toutes les resources créées dans une release
kubectl get all --selector=release=nginxPar défaut, le chart stable/nginx crée un service de typeLoadBalancer
On veut changer cela en un NodePort
on peut utiliser kubectl edit service nginx-nginx, mais ...
... nos modifications seraient écrasées la prochaine fois qu'on met à jour ce Chart !
On va pour cela définir une valeur pour le type de service
Les valeurs sont des paramètres que le Chart peut utiliser pour modifier son comportement
Les valeurs ont des valeurs par défaut
Chaque Chart peut de définir ses propres valeurs et leurs valeurs par défaut
helm show or helm inspect# Look at the README for nginx:
helm show readme stable/nginx
# Look at the values and their defaults:
helm show values stable/nginxLes values n'ont peut être pas de commentaires utiles.
Le fichier readme peut ou pas, donner des informations sur ces values.
Les valeurs peuvent être définies lors de l'installation d'un Chart ou lors de sa mise à jour helm install helm upgrade
Dans notre exemple, on va mettre à jour nginx pour changer le type de service
# Update `nginx`:
helm upgrade nginx stable/nginx --set service.type=NodePorthelm create myapp va permettre de créer la structure de répertoire et de fichiers d'un chart "standard"nginx en templétisant les services, deployment, serviceAccount, etc...kubectl apply/create/delete -f)kustomizationskustomizations peut se voir comme une superposition (overlay) (ajout ou modification)kustomizations sont définies dans un fichier kustomizations.yamllabelsou annotations pour toutes les ressourcesconfigmaps ou secretsapiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
patchesStrategicMerge:
- scale-deployment.yaml
- ingress-hostname.yaml
resources:
- deployment.yaml
- service.yaml
- ingress.yamlapiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
commonLabels:
add-this-to-all-my-resources: please
patchesStrategicMerge:
- prod-scaling.yaml
- prod-healthchecks.yaml
bases:
- api/
- frontend/
- db/
- github.com/example/app?ref=tag-or-branch
resources:
- ingress.yaml
- permissions.yaml
configMapGenerator:
- name: appconfig
files:
- global.conf
- local.conf=prod.confhttps://kubectl.docs.kubernetes.io/references/kustomize/glossary/
base : Une base est une kustomisation référencée par une autre kustomisationoverlay : un overlay est une kustomization qui dépend d'une autre kustomizationkustomization : Une kustomization peut être à la fois une base et un overlaypatch : un patch décrit comment modifier une ressource existantevariant : une variante est le résultat, dans un cluster, de l'application d'un overlay à une base├── base
│ ├── deployment.yaml
│ ├── kustomization.yaml
│ └── service.yaml
└── overlays
├── dev
│ ├── kustomization.yaml
│ └── patch.yaml
├── prod
│ ├── kustomization.yaml
│ └── patch.yaml
└── staging
├── kustomization.yaml
└── patch.yamlArgoCD est un outil de déploiement continu (CD) déclaratif pour Kubernetes. - Conçu pour implémenter le GitOps - Open source et partie de la CNCF - Permet de synchroniser l'état souhaité (Git) avec l'état réel (Kubernetes)
┌─────────────┐
│ │
│ Git │
│ │
└──────┬──────┘
│
▼
┌──────────────┐ ┌──────────────┐ ┌─────────────┐
│ ArgoCD │ │ ArgoCD │ │ │
│ API │◄──┤ Controller │──►│ Kubernetes │
│ Server │ │ │ │ Cluster │
└──────────────┘ └──────────────┘ └─────────────┘

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: mon-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/mon-org/mon-app.git
targetRevision: HEAD
path: k8s
destination:
server: https://kubernetes.default.svc
namespace: productionArgo Workflows pour l'orchestration
Les services nous permettent d'accéder à un pod ou à un ensemble de pods
Qu'en est-il des services HTTP?
Si nous utilisons les services NodePort, les clients doivent spécifier les numéros de port
(c'est-à-dire http: // xxxxx: 31234 au lieu de simplement http: // xxxxx)
Les services LoadBalancer sont bien, mais:
ils ne sont pas disponibles dans tous les environnements
ils entraînent souvent un coût supplémentaire (par exemple, ils fournissent un ELB)
ils nécessitent une étape supplémentaire pour l'intégration DNS (en attendant que le LoadBalancer soit provisionné; puis en l'ajoutant au DNS)
Ressource API Kubernetes (kubectl get ingress / ingresses / ing)
Conçu pour exposer les services HTTP
Ingress ControllerIngress Controller = répartiteur de charge + boucle de contrôle
La boucle de contrôle surveille les Objects Ingress et configure le LB en conséquence
Associer les entrées DNS à l'adresse du LB
L'Ingress Controller prend ces ressources et configure le LB (load balancer)
Un exemple simple
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: podinfo-ing
namespace: podinfo
spec:
ingressClassName: nginx
rules:
- host: podinfo.formation.com
http:
paths:
- backend:
service:
name: podinfo
port:
number: 9898
path: /
pathType: Prefix
tls:
- hosts:
- podinfo.formation.com
secretName: podinfo.formation.com-tlskubectl drain permet de vider un noeud des pods qu'il héberge vers un autre noeud, puis de marquer le noeud "not schedulable". Ainsi au cours de l'opération de maintenance, aucun pod ne peut lui être affecté.kubectl uncordon, le noeud est remis dans le cluster et peut à nouveau héberger des pods.kubectl cordon marque uniquement le noeud "not schedulable" tout en conservant les pods qu'il héberge. Il s'assure simplement que de nouveaux pods ne lui soient pas affectés.kubeadm upgrade plan fournit les informations sur la version actuelle de kubeadm installée, la version du cluster et la dernière version stable de Kubernetes disponible kubectl drain worker-0
apt-get upgrade -y kubeadm=1.21.0-00
apt-get upgrade -y kubelet=1.21.0-00
apt-get upgrade node config --kubelet-version v1.21.0
systemctl restart kubelet
kubectl uncordon worker-0etcdctl est un client en ligne de commande du service ETCDetcdctl snapshot save -h = sauvegarder la base de données.etcdctl snapshot restore -h = restaurer la base de données. $ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-deploy-8fd84bbd6-b8d48 1/1 Running 0 45d
nginx-deploy-8fd84bbd6-fqmgk 1/1 Running 0 45d
nginx-deploy-8fd84bbd6-nvq5b 1/1 Running 0 45d
mysql-database 0/1 CrashLoopBackOff 1 18s
mysql-database1 0/1 ImagePullBackOff 0 6s
web-deploy-654fb8bb79-24nvd 0/1 Pending 0 2ssi l'état de votre pod n'est pas "Running", vous devrez suivre quelques étapes de débogage
L'état de votre pod est en "CrashLoopBackOff"
Faites une description sur le pod et regardez la section "Events". Vous remarquerez peut-être un warning "Back-off restarting failed"
$ kubectl describe pods mysql-database
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 2m18s default-scheduler Successfully assigned default/mysql-database to gke-certif-test-default-pool-27dfc050-9bww
Normal Pulled 76s (x4 over 2m7s) kubelet, gke-certif-test-default-pool-27dfc050-9bww Successfully pulled image "mysql"
Normal Created 76s (x4 over 2m3s) kubelet, gke-certif-test-default-pool-27dfc050-9bww Created container mysql
Normal Started 75s (x4 over 2m2s) kubelet, gke-certif-test-default-pool-27dfc050-9bww Started container mysql
Warning BackOff 46s (x8 over 2m1s) kubelet, gke-certif-test-default-pool-27dfc050-9bww Back-off restarting failed container
Normal Pulling 32s (x5 over 2m17s) kubelet, gke-certif-test-default-pool-27dfc050-9bww Pulling image "mysql"Vous pouvez connaître la raison de l'échec en vérifiant les logs des conteneurs de votre pod
$ kubectl logs mysql-database --container=mysql
2020-03-06 10:07:26+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.19-1debian10 started.
2020-03-06 10:07:26+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql'
2020-03-06 10:07:26+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.19-1debian10 started.
2020-03-06 10:07:26+00:00 [ERROR] [Entrypoint]: Database is uninitialized and password option is not specified
You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORDL'état de votre pod est en "ImagePullBackOff"
Faites une description sur le pod et regardez la section "Events". Vous pouvez remarquer l'erreur "ErrImagePull". Cela signifie que vous avez mis une mauvaise image de docker ou que vous avez une mauvaise autorisation d'accès au registre
$ kubectl describe pods mysql-database1
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 105s default-scheduler Successfully assigned default/mysql-database1 to gke-certif-test-default-pool-27dfc050-9bww
Normal SandboxChanged 103s kubelet, gke-certif-test-default-pool-27dfc050-9bww Pod sandbox changed, it will be killed and re-created.
Normal BackOff 31s (x6 over 103s) kubelet, gke-certif-test-default-pool-27dfc050-9bww Back-off pulling image "mysql:dert12"
Warning Failed 31s (x6 over 103s) kubelet, gke-certif-test-default-pool-27dfc050-9bww Error: ImagePullBackOff
Normal Pulling 16s (x4 over 104s) kubelet, gke-certif-test-default-pool-27dfc050-9bww Pulling image "mysql:dert12"
Warning Failed 15s (x4 over 104s) kubelet, gke-certif-test-default-pool-27dfc050-9bww Failed to pull image "mysql:dert12": rpc error: code = Unknown desc = Error response from daemon: manifest for mysql:dert12 not found: manifest unknown: manifest unknown
Warning Failed 15s (x4 over 104s) kubelet, gke-certif-test-default-pool-27dfc050-9bww Error: ErrImagePullL'état de votre pod est en "Pending"
Faites une description sur le pod et regardez la section "Events". Notez que le scheduler n'a pas de nœud dans lequel placer votre pod en raison d'une ressource insuffisante. Vous pouvez augmenter votre CPU ou votre mémoire (selon le message d'avertissement), cela peut se produire en ajoutant de nouveaux nœuds ou en diminuant le nombre de réplicas du déploiement
$ kubectl describe pods web-deploy-654fb8bb79-24nvd
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 90s (x2 over 95s) default-scheduler 0/2 nodes are available: 2 Insufficient cpu.
Normal NotTriggerScaleUp 65s cluster-autoscaler pod didn't trigger scale-up (it wouldn't fit if a new node is added): 1 max node group size reached
Warning FailedScheduling 20s default-scheduler 0/6 nodes are available: 6 Insufficient cpu.L'état de votre pod est en "waiting"
Si un pod est bloqué dans l'état "waiting", il a été planifié sur un nœud de travail, mais il ne peut pas s'exécuter sur cette machine. Encore une fois, les informations de kubectl describe... devraient être informatives. La cause la plus courante des pods en "waiting" est l'échec de l'extraction de l'image. Il y a trois choses à vérifier :
- Assurez-vous que le nom de l'image est correct.
- Avez-vous poussé l'image vers le repository ?
- Exécutez un docker pull <image> manuel sur votre machine pour voir si l'image peut être extraite. $ kubectl get pods
$ kubectl describe pods pod-name
$ kubectl logs pod-name --container=pods-containers-name
$ kubectl logs --previous pod-name --container=pods-containers-name
$ kubectl exec -it pod-name -- bash $ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.16.0.1 <none> 443/TCP 46d
web-service LoadBalancer 10.16.7.129 34.68.167.93 80:30250/TCP 9m54sIl existe plusieurs problèmes courants qui peuvent empêcher les services de fonctionner correctement. Tout d'abord, vérifiez qu'il existe des endpoints pour le service. Pour chaque objet Service, l'API server met à disposition une ressource endpoint.
$ kubectl get endpoints web-service
NAME ENDPOINTS AGE
web-service 10.12.0.27:80,10.12.0.28:80,10.12.0.4:80 11mAssurez-vous que les endpoints correspondent au nombre de conteneurs que vous pensez être membres de votre service. Dans ce scénario, le service Web sert un déploiement Web avec 3 réplicas de pods.
$ kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
web-deployment 3/3 3 3 4h43m au cas où les endpoints du service sont manquants, vérifiez le sélecteur du service
...
spec:
- selector:
run: web-deploymentCe sélecteur doit correspondre aux labels des pods sinon le service ne pourra pas exposer les pods
$ kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
web-deployment-654fb8bb79-6n9q2 1/1 Running 0 4h53m run=web-deployment
web-deployment-654fb8bb79-ljnhw 1/1 Running 0 15m run=web-deployment
web-deployment-654fb8bb79-vpcwb 1/1 Running 0 15m run=web-deploymentSi la liste des pods correspond aux attentes, mais que les endpoints sont toujours vides, il est possible que les bons ports ne soient pas exposés. Si le service a un containerPort spécifié, mais que les pods sélectionnés n'ont pas ce port répertorié, ils ne seront pas ajoutés à la liste des endpoints.
Vérifiez que le containerPort du pod correspond au targetPort du service
$ kubectl get componentstatus
NAME STATUS MESSAGE ERROR
controller-manager Healthy ok
scheduler Healthy ok $ kubectl get nodes
NAME STATUS ROLES AGE VERSION
worker-1 Ready worker 8d v1.21.0
worker-2 Ready worker 8d v1.21.0
master-1 Ready master 8d v1.21.0 $ kubectl get pods -n kube-systems
NAME READY STATUS RESTARTS AGE
coredns-78fcdf6894-5dntv 1/1 Running 0 1h
coredns-78fcdf6894-knpzl 1/1 Running 0 1h
etcd-master 1/1 Running 0 1h
kube-apiserver-master 1/1 Running 0 1h
kube-controller-manager-master 1/1 Running 0 1h
kube-proxy-fvbpj 1/1 Running 0 1h
kube-proxy-v5r2t 1/1 Running 0 1h
kube-scheduler-master 1/1 Running 0 1h
weave-net-7kd52 2/2 Running 1 1h
weave-net-jtl5m 2/2 Running 1 1h $ service kube-apiserver status
● kube-apiserver.service - Kubernetes API Server
Loaded: loaded (/etc/systemd/system/kube-apiserver.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2019-03-20 07:57:25 UTC; 1 weeks 1 days ago
Docs: https://github.com/kubernetes/kubernetes
Main PID: 15767 (kube-apiserver)
Tasks: 13 (limit: 2362)Répétez le même process pour les autres services tels que: kube-controller-manager, kube-scheduler, kubelet, kube-proxy
$ kubectl logs kube-apiserver-master -n kube-system
I0401 13:45:38.190735 1 server.go:703] external host was not specified, using 172.17.0.117
I0401 13:45:38.194290 1 server.go:145] Version: v1.11.3
I0401 13:45:38.819705 1 plugins.go:158] Loaded 8 mutating admission controller(s) successfully in the following order:
NamespaceLifecycle,LimitRanger,ServiceAccount,NodeRestriction,Priority,DefaultTolerationSeconds,DefaultStorageClass,MutatingAdmissionWebhook.
I0401 13:45:38.819741 1 plugins.go:161] Loaded 6 validating admission controller(s) successfully in the following order:
LimitRanger,ServiceAccount,Priority,PersistentVolumeClaimResize,ValidatingAdmissionWebhook,ResourceQuota.
I0401 13:45:38.821372 1 plugins.go:158] Loaded 8 mutating admission controller(s) successfully in the following order:
NamespaceLifecycle,LimitRanger,ServiceAccount,NodeRestriction,Priority,DefaultTolerationSeconds,DefaultStorageClass,MutatingAdmissionWebhook.
I0401 13:45:38.821410 1 plugins.go:161] Loaded 6 validating admission controller(s) successfully in the following order:
LimitRanger,ServiceAccount,Priority,PersistentVolumeClaimResize,ValidatingAdmissionWebhook,ResourceQuota.
I0401 13:45:38.985453 1 master.go:234] Using reconciler: lease
W0401 13:45:40.900380 1 genericapiserver.go:319] Skipping API batch/v2alpha1 because it has no resources.
W0401 13:45:41.370677 1 genericapiserver.go:319] Skipping API rbac.authorization.k8s.io/v1alpha1 because it has no resources.
W0401 13:45:41.381736 1 genericapiserver.go:319] Skipping API scheduling.k8s.io/v1alpha1 because it has no resources. $ kubectl get nodes
NAME STATUS ROLES AGE VERSION
worker-1 Ready <none> 8d v1.21.0
worker-2 NotReady <none> 8d v1.21.0 $ kubectl describe node worker-1
...
Conditions:
Type Status LastHeartbeatTime Reason Message
---- ------ ----------------- ------ -------
OutOfDisk False Mon, 01 Apr 2019 14:30:33 +0000 KubeletHasSufficientDisk kubelet has sufficient disk space available
MemoryPressure False Mon, 01 Apr 2019 14:30:33 +0000 KubeletHasSufficientMemory kubelet has sufficient memory available
DiskPressure False Mon, 01 Apr 2019 14:30:33 +0000 KubeletHasNoDiskPressure kubelet has no disk pressure
PIDPressure False Mon, 01 Apr 2019 14:30:33 +0000 KubeletHasSufficientPID kubelet has sufficient PID available
Ready True Mon, 01 Apr 2019 14:30:33 +0000 KubeletReady kubelet is posting ready status. AppArmor enabled $ kubectl describe node worker-2
Conditions:
Type Status LastHeartbeatTime Reason Message
---- ------ ----------------- ------ -------
OutOfDisk Unknown Mon, 01 Apr 2019 14:20:20 +0000 NodeStatusUnknown Kubelet stopped posting node status.
MemoryPressure Unknown Mon, 01 Apr 2019 14:20:20 +0000 NodeStatusUnknown Kubelet stopped posting node status.
DiskPressure Unknown Mon, 01 Apr 2019 14:20:20 +0000 NodeStatusUnknown Kubelet stopped posting node status.
PIDPressure False Mon, 01 Apr 2019 14:20:20 +0000 KubeletHasSufficientPID kubelet has sufficient PID available
Ready Unknown Mon, 01 Apr 2019 14:20:20 +0000 NodeStatusUnknown Kubelet stopped posting node status. $ openssl x509 -in /var/lib/kubelet/worker-1.crt -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
ff:e0:23:9d:fc:78:03:35
Signature Algorithm: sha256WithRSAEncryption
Issuer: <CN = KUBERNETES-CA>
Validity
Not Before: Mar 20 08:09:29 2019 GMT
<Not After : Apr 19 08:09:29 2019 GMT>
Subject: CN = system:node:worker-1, O = system:nodes
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
00:b4:28:0c:60:71:41:06:14:46:d9:97:58:2d:fe:
a9:c7:6d:51:cd:1c:98:b9:5e:e6:e4:02:d3:e3:71:
...La durée de l'examen est de 2h
Avec des exercices pratiques dans un cluster déjà opératinnel
Accès à la documentation officielle de Kubernetes est autorisé
https://github.com/cncf/curriculum
Certified Kubernetes Security Specialist (CKS)
Les programmes CKAD, CKA et CKS ont été développés par la Cloud Native Computing Foundation (CNCF), en collaboration avec la Linux Foundation, pour faciliter l'extension de l'écosystème Kubernetes grâce à des certifications standardisées.
https://www.cncf.io/certification/ckad/ https://www.cncf.io/certification/cka/ https://www.cncf.io/certification/cks/