K3S
Mis à jour le 16/08/2024
source: https://docs.k3s.io
Gestion des containers en bas niveau
crictl
Installation
Avec multipass
common-config.yaml
#cloud-config
# cloud config de base pour multipass
# lancement:
# multipass launch --name test --memory 1G --cpus 4 --disk 10G --cloud-init common-config.yaml
# package_update: true
# package_upgrade: true
packages:
- net-tools
- emacs-nox
- elpa-yaml-mode
write_files:
# emacs par défaut via variable EDITOR
- path: /etc/environment
content: |
EDITOR=emacs
append: true
# des alias "biens" définis dans le fichier principal de configuration de bash
- path: /etc/skel/.bashrc
append: true
content: |
# alias personalisés
alias du='du -h'
alias df='df -h'
alias locate='locate -i'
alias cal='ncal -bMw'
alias less='less -i'
alias egrep='egrep --color=auto'
alias fgrep='fgrep --color=auto'
alias grep='grep --color=auto'
alias ll='ls -lFh'
users:
- # default = ubuntu avec multipass
ssh_authorized_keys:
# ma clef du pc pour l'utilisateur "default" (ubuntu)
- ssh-ed25519 AAAAC3N...contenu du fichier de clef publique ssh...
swap:
filename: /swapfile
size: 1G
maxsize: 1G
3 VMs avec multipass
multipass launch --name k3s-master --memory 1G --cpus 4 --disk 10G --cloud-init common-config.yaml
multipass launch --name k3s-worker1 --memory 1G --cpus 4 --disk 10G
multipass launch --name k3s-worker2 --memory 1G --cpus 4 --disk 10G
k3s-master
curl -sfL https://get.k3s.io | K3S_KUBECONFIG_MODE="644" sh -
echo 'write-kubeconfig-mode: "0644"' | sudo tee /etc/rancher/k3s/config.yaml
# puis redémarrer la VM pour le prendre en compte
# c'est sans doute faisable dès la 1ère commande => apparemment oui avec la variable définie dans la commande d'installation
# complétion automatique
sudo -i
kubectl completion bash >/etc/bash_completion.d/kubectl
exit
.bashrc
alias k='kubectl'
source /usr/share/bash-completion/bash_completion
complete -F __start_kubectl k
master dédié
kubectl taint node k3s-master node-role.kubernetes.io/master:NoSchedule
Les worker
Sur le master, afficher la valeur de K3S_TOKEN
sudo cat /var/lib/rancher/k3s/server/node-token
Sur les noeuds:
curl -sfL https://get.k3s.io | K3S_URL=https://k3s-master:6443 K3S_TOKEN=valeurK3S_TOKEN sh -
Test
k run shell --image alpine --image-pull-policy IfNotPresent -- sleep 3600
k exec -it shell -- ash
ping free.fr
exit
Dashboard
source: https://github.com/kubernetes/dashboard
GITHUB_URL=https://github.com/kubernetes/dashboard/releases
VERSION_KUBE_DASHBOARD=$(curl -w '%{url_effective}' -I -L -s -S ${GITHUB_URL}/latest -o /dev/null | sed -e 's|.*/||')
k apply -f https://raw.githubusercontent.com/kubernetes/dashboard/${VERSION_KUBE_DASHBOARD}/aio/deploy/recommended.yaml
Mettre le service en type NodePort (plus simple que passer par le proxy k8s)
Authentification
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kubernetes-dashboard
---
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
k -n kubernetes-dashboard create token admin-user --duration 700h
Stockage (PV/PVC)
K3s out of the box: Rancher’s Local Path Provisioner
- utilise la StorageClass nommée local-path
- configuré via la ConfigMap nommée local-path-config
- contient ceci qui semble dire où se trouve le stockage, et permettrait de configurer des chemins en fonction du node
{ "nodePathMap": [ { "node": "DEFAULT_PATH_FOR_NON_LISTED_NODES", "paths": [ "/var/lib/rancher/k3s/storage" ] } ] }
- contient ceci qui semble dire où se trouve le stockage, et permettrait de configurer des chemins en fonction du node
- la quantité de storage demandée n’est pas un quota
- la création d’un PVC créé un répertoire pour le PV (dans /var/lib/rancher/k3s/storage, nommé pvc-GUID) qui a le droit 0777 => utile
- La suppression du PVC supprime le PV et donc tous les fichiers créés (normal, il y a persistentVolumeReclaimPolicy: Delete sur le PV)
- Le PV est de HostPathType: DirectoryOrCreate et avec un Node Affinity sur le noeud qui l’héberge (cf le describe du PV) => peut être que tout POD qui veut utiliser le PV est sur le “bon host”. D’ailleurs, si on force un POD sur une autre noeud que celui du PV, le POD reste en pending pendant un certain temps (plutôt court) puis disparaît.
Exemple
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-k3s
namespace: default
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-path
resources:
requests:
storage: 512Mi
---
apiVersion: v1
kind: Pod
metadata:
name: pvc-k3s-test
namespace: default
spec:
containers:
- name: pvc-k3s-test-container
image: alpine
imagePullPolicy: IfNotPresent
args:
- sleep
- "3600"
volumeMounts:
- name: pvc-k3s
mountPath: /data
volumes:
- name: pvc-k3s
persistentVolumeClaim:
claimName: pvc-k3s
Longhorn
Au moins 2Go sur les noeuds
Système de PV “automatiques” qui marche sur (normalement) toutes les infrastructures K8S. -> Réplication mode blocks sur plusieurs noeuds du cluster.
source: https://longhorn.io/docs/1.4.2/deploy/install/
Vérification des prérequis
Note: jq maybe required to be installed locally prior to running env check script -> sur la plateforme multipass, c’est nécessaire.
curl -sSfL https://raw.githubusercontent.com/longhorn/longhorn/v1.4.2/scripts/environment_check.sh | bash
Installation
kubectl apply -f https://raw.githubusercontent.com/longhorn/longhorn/v1.4.2/deploy/longhorn.yaml
monitor the progress of the installation (namespace: longhorn-system)
kubectl get pods \
--namespace longhorn-system \
--watch
-> créé 31 PODS dans le namespace (dans la version de cette documentation -> 26)
- Autoriser la désinstallation, car si on supprime le namespace sans passer par la procédure de désinstallation et qu’on lance cette dernière après, elle plante puisque la désinstallation est interdite et on ne peut plus changer le setting. A faire si on n’est pas en production ou du moins en connaissance de cause !
k get settings.longhorn.io/deleting-confirmation-flag -n longhorn-system kubectl -n longhorn-system patch -p '{"value": "true"}' --type=merge lhs deleting-confirmation-flag
Désinstallation
Supprimer le namespace ne suffit pas car il y a des ressources en dehors:
kubectl api-resources --verbs=list --namespaced |grep longhorn
kubectl api-resources --verbs=list --namespaced -o name|grep longhorn|xargs -n 1 kubectl get --show-kind --ignore-not-found -n longhorn-system
Suppression propre:
kubectl apply -f https://raw.githubusercontent.com/longhorn/longhorn/v1.4.2/uninstall/uninstall.yaml
kubectl get job/longhorn-uninstall -n longhorn-system -w
# ou (en adaptant le nom du pod)
k -n longhorn-system logs -f longhorn-uninstall-rjlgx
# Quand c'est terminé, Remove remaining components:
kubectl delete -f https://raw.githubusercontent.com/longhorn/longhorn/v1.4.2/deploy/longhorn.yaml
kubectl delete -f https://raw.githubusercontent.com/longhorn/longhorn/v1.4.2/uninstall/uninstall.yaml
Utilisation
Mettre le service longhorn-frontend en NodePort. C’est un service HTTP.
Changer le Config Map longhorn-storageclass afin de choisir le nombre de réplicas (max: nombre de worker nodes) et éventuellement le fsType en xfs. -> vérifier dans le storageClass
pvc
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: longhorn-pvc1
spec:
accessModes:
- ReadWriteOnce
storageClassName: longhorn
resources:
requests:
storage: 256Mi
pod
apiVersion: v1
kind: Pod
metadata:
name: longhorn-pvc1-pod
namespace: default
spec:
containers:
- name: longhorn-pvc1-container
image: alpine
args:
- sleep
- "3600"
imagePullPolicy: IfNotPresent
volumeMounts:
- name: volume-longhorn1
mountPath: /data
volumes:
- name: volume-longhorn1
persistentVolumeClaim:
claimName: longhorn-pvc1
- Le PVC créé un PV qui est un fichier .img à taille dynamique dans
/var/lib/longhorn/replicas
(ce chemin est configurable) - La taille est la taille du fichier .img, donc il n’y a pas de débordement (c’est comme un quota)
- L’extension de la taille du volume dans le gestionnaire Longhorn finit par être effective (au bout d’un peu de temps) dans le container attaché.
- La suppression du PVC supprime tout
- On peut faire des snapshot des volumes (la restauration est à froid)
- On peut faire des backup automatiques des volumes (via NFS par exemple)
Application PRIMES
apiVersion: v1
kind: Namespace
metadata:
name: primes
---
# frontal WEB
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: primes
name: primes-deployment
namespace: primes
spec:
replicas: 2
selector:
matchLabels:
app: primes
template:
metadata:
labels:
app: primes
spec:
containers:
- image: quay.io/bruno_dubois1012/flask-primes:v2.0
name: primes-container
imagePullPolicy: IfNotPresent
env:
- name: REDIS
value: redis-primes-svc.primes.svc.cluster.local
initContainers:
- name: wait-db-ready-init-container
image: alpine
imagePullPolicy: IfNotPresent
command:
- sh
- -c
- apk add netcat-openbsd; until echo quit|nc redis-primes-svc.primes.svc.cluster.local 6379; do sleep 1 ;done
---
#PVC K3S
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-redis-primes
namespace: primes
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-path
resources:
requests:
storage: 512Mi
---
# Base noSQL Redis
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
run: redis-primes
name: redis-primes-deployment
namespace: primes
spec:
replicas: 1 # ne pas changer sans apprendre le produit (c'est une base de données!!!)
strategy:
type: Recreate
selector:
matchLabels:
run: redis-primes
template:
metadata:
labels:
run: redis-primes
spec:
volumes:
- name: pvc-redis-primes
persistentVolumeClaim:
claimName: pvc-redis-primes
containers:
- name: redis-primes-container
image: redis
imagePullPolicy: IfNotPresent
volumeMounts:
- name: pvc-redis-primes
mountPath: /data
---
# SERVICES
kind: Service
apiVersion: v1
metadata:
name: redis-primes-svc
namespace: primes
spec:
selector:
run: redis-primes
ports:
- protocol: TCP
port: 6379
targetPort: 6379
name: redis
---
kind: Service
apiVersion: v1
metadata:
name: primes-svc
namespace: primes
spec:
selector:
app: primes
ports:
- protocol: TCP
port: 80
targetPort: 5000
name: flask-http
nodePort: 31987
type: NodePort
Network Policies
Ca marche !!!
Exemple
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
namespace: default
name: deny-from-other-namespaces
spec:
podSelector:
matchLabels:
# donc ceci s'applique à tous les pods du ns
ingress:
- from:
- podSelector: {}
# donc podSelector contient 1 règle vide, donc tous les pods du même ns sont autorisés
# REM si un svc LoadBalancer est associé à un des pod, l'IP externe est bloquée
# pour autoriser une IP externe:
- from:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 10.0.0.0/8
- 192.168.0.0/16
- 172.16.0.0/12
# Donc la liste de "from" est liée par OU
# on aurait aussi pu mettre (avec des labels communs aux pods de ns):
# - from:
# - podSelector:
# matchLabels:
# l1: .......
# l2: .......
# ......
# voir: https://github.com/ahmetb/kubernetes-network-policy-recipes/issues/1
dashboard v3 alpha
# cert-manager
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.12.0/cert-manager.yaml
# dashboard
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v3.0.0-alpha0/charts/kubernetes-dashboard.yaml