1 – Les PODs :
Dans un cluster Kubernetes un Pod est un groupe d’un ou plusieurs conteneurs qui partage la même couche réseau et le même stockage.
Depuis un manisfest :
apiVersion: v1
kind: Pod
metadata:
name: monpodnginx
spec:
containers:
- name: monnginx
image: nginx
ports:
- containerPort: 80
Puis on applique la configuration en appelant le fichier depuis Kubernetes
kubectl apply -f monpodnginx.yml
Nous pouvons aussi le faire directement en ligne de commande :
kubectl run monpodnginx --image=nginx --port=80
Nous vérifions que notre nouveau POD est bien créer et démarrer
kubectl get pod
NAME READY STATUS RESTARTS AGE
monpodnginx 1/1 Running 0 4h16m
Notre pod va se voir attribuer une IP au sein du cluster Kubernetes que nous allons pouvoir interroger seulement depuis celui-ci :
kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
monpodnginx 1/1 Running 0 24s 10.244.3.10 ks8-node-2 none none
Depuis le master nous pouvons effectuer un curl pour valider la réponse du serveur web :
curl 10.244.3.10 80
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
On peut se connecter au pod pour modifier la page html de cette manière :
kubectl exec monpodnginx -it sh
Pour supprimer le pod :
kubectl delete pod monpodnginx
ou
kubectl delete pod --all
2 – Déploiements et services
Un déploiement est une représentation logique d’un ou plusieurs pod (configuration).
Un service est un moyen d’accéder à nos pods
A – Création d’un déploiement
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ou directement en commandes :
kubectl create deployment monpodnginx --image=nginx
Nous pouvons afficher notre déploiement avec cette commande :
kubectl get deployments
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 1/1 1 1 24s
Notre déploiement contient un pod :
kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-deployment-d46f5678b-ltrmk 1/1 Running 0 92s
B – Création du service :
Pour que notre POD soit accessible depuis une machine extérieur à notre cluster K8S nous allons créer un service :
kubectl create service nodeport monpodnginx --tcp=8080:80
Le port 8080 correspond au port qui pourra être utilisé par un autre pod pour communiquer avec notre pod nginx (ClusterPort).
Le port 80 correspond au port en écoute du serveur nginx (TargetPort).
Le port qui sera joignable depuis l’extérieur sera généré automatiquement dans le range de port suivant 30000-32767 (NodePort).
kubectl get service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
monpodnginx NodePort 10.102.58.21 none> 8080:31618/TCP 5s
Nodeport = Expose le service pour qu’il soit joignable depuis l’extérieur du cluster K8S via un port dans le range suivant : 30000-32767
Clusterip = Expose le service sur une IP interne au cluster. Il sera seulement accessible depuis un autre POD du cluster
Pour y accéder depuis notre navigateur il suffit d’indiquer l’ip de notre master et le port générer automatiquement lors de la création du service ici : 31618
Il est aussi possible de passer par la commande ci-dessous qui permet d’exposer une ressource :
kubectl expose deployment monpodnginx --type NodePort --port 80
ou par le biais d’un manisfest :
apiVersion: v1
kind: Service
metadata:
name: monpodnginx
spec:
selector:
app: monpodnginx
type: NodePort
ports:
- protocol: TCP
port: 8080
nodePort: 31618
targetPort: 80
3 – Les volumes persistants :
Nous allons maintenant associer un volume à notre pod. Ici j’ai monté un partage nfs sur mon master. Le stockage sera donc accessible depuis n’importe quelle nœud de notre cluster k8s.
A – Création du serveur nfs
apt-get install nfs-kernel-server
vi /etc/export
/share/nfs 192.168.4.0/24(rw,sync,no_root_squash)
exportfs -a
/etc/init.d/nfs-kernel-server start
Depuis un nœud K8S nous pouvons essayer de monter le partage de cette manière :
root@k8s-node-1:~# mount -t nfs k8s-master.ophyde.tech:/share/nfs /tmp
root@k8s-node-1:~# umount /tmp
B – Persistant Volume :
Nous allons commencer par créer un « Persistant Volume ».
Le Persistant Volume (PV) correspond à un élément de stockage qui a été provisionné par l’administrateur. Il s’agit d’une ressource de stockage dans le cluster au même titre qu’un nœud du cluster. Il comporte les détails techniques d’accès au stockage (NFS, ISCSI etc)
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv001-nfs
spec:
storageClassName: nfs-nas
capacity:
storage: 2Gi
accessModes:
- ReadWriteMany
nfs:
server: k8s-master.ophyde.tech
path: /share/nfs
Les modes d’accès sont suivants :
- ReadWriteOnce — le volume peut être monté en lecture-écriture par un seul nœud
- ReadOnlyMany — le volume peut être monté en lecture seule par plusieurs nœuds
- ReadWriteMany — le volume peut être monté en lecture-écriture par de nombreux nœuds
kubectl apply -f pvnas.yaml
On affiche notre Persistant Volume :
kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pv001-nfs 2Gi RWX Retain Available nfs-nas 19s
C – Persistant Volume Claim :
Le Persistant Volume Claim (PVC) correspond à un élément de stockage qui a été provisionné par l’utilisateur. Il s’agit d’une ressource de stockage dans le cluster au même titre qu’un POD. Cela permet à l’utilisateur de consommer des ressources de stockage abstraites sans avoir connaissance du type de stockage. L’utilisateur ne connait donc pas les détails technique de mise en œuvre du stockage.
Nous allons maintenant créer un Persistant Volume Claim qui pourra être utiliser par un conteneur appartenant à un de nos POD.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc001-nfs
spec:
storageClassName: nfs-nas
accessModes:
- ReadWriteMany
resources:
requests:
storage: 2Gi
kubectl apply -f pvnas.yaml
La liaison entre le PV et le PVC se fait par le biais du storageClassName ici il correspond à nfs-nas
kubectl get pv,pvc
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
persistentvolume/pv001-nfs 2Gi RWX Retain Bound default/pvc001-nfs nfs-nas 14s
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
persistentvolumeclaim/pvc001-nfs Bound pv001-nfs 2Gi RWX nfs-nas 10s
D – Utilisation du stockage par notre pod
Nous souhaitons déporter le répertoire /usr/share/nginx/html qui contient nos pages web de notre conteneur nginx sur notre stockage persistant.
Les pods accèdent au stockage en utilisant le PVC comme volume.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: monnginx
image: nginx
ports:
- containerPort: 80
volumeMounts:
- name: www
mountPath: /usr/share/nginx/html
volumes:
- name: www
persistentVolumeClaim:
claimName: pvc001-nfs
On lance la création de notre POD :
kubectl apply -f monpodnginx.yaml
kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
monpodnginx 1/1 Running 0 4m 10.244.3.11 k8s-node-2 none none
kubectl describe pod
Name: monpodnginx
Namespace: default
Priority: 0
--- Ignored line ---
Volumes:
www:
Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
ClaimName: pvc001-nfs
ReadOnly: false
--- Ignored line ---
Et nous exposons notre pod pour qu’il soit joignable de l’extérieur :
kubectl create service nodeport nginx-deployment --tcp=8080:80
kubectl get service -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
nginx-deployment NodePort 10.104.18.232 none> 8080:31832/TCP 4m44s app=nginx-deployment
Le POD me retourne un 403 Forbiden car il ne dispose pas d’un index.html (rappelez-vous nous avons monté notre pvc directement dans le dossier contenant nos pages web)
Pour remédiez à cela il suffit de rajouter sur notre stockage persistant une page html.
root@k8s-master-1:/# echo "Mon pod nginx 1" >> /share/nfs/index.html
Si vous souhaitez installer votre propre cluster vous pouvez vous reporter à cet article
Source :