mmul.kubelab
Ce rôle peut être utilisé pour déployer un cluster Kubernetes avec une implémentation entièrement automatisée et idempotente de plusieurs composants.
Caractéristiques
Ce rôle peut être configuré pour activer toutes ces fonctionnalités :
Implémentation d'un cluster à un ou plusieurs plans de contrôle avec HAProxy et Keepalived pour une haute disponibilité.
Add-ons réseau multiples Flannel et Calico.
Tableau de bord Kubernetes.
Gestion des utilisateurs avec génération de certificats et mise à jour du fichier
kubeconfig
.Ceph-CSI StorageClass pour les dispositifs de blocs.
MetalLB équilibreur de charge pour les environnements baremetal.
Ingress NGINX pour l'exposition des services.
Cert Manager pour la gestion automatisée des certificats.
Installer le cluster avec le Playbook Ansible
La meilleure façon de préparer l'environnement est d'utiliser un VirtualEnv Python et d'installer ansible avec pip3
:
user@lab ~ # python3 -m venv ansible
user@lab ~ # source ansible/bin/activate
(ansible) user@lab ~ # pip3 install ansible
Collecte d’ansible
En utilisant le package caché ansible-7.5.0-py3-none-any.whl (43,6 Mo)
...
...
Installation des paquets recueillis : resolvelib, PyYAML, pycparser, packaging, MarkupSafe, jinja2, cffi, cryptography, ansible-core, ansible
Installation réussie de MarkupSafe-2.1.2 PyYAML-6.0 ansible-7.5.0 ansible-core-2.14.5 cffi-1.15.1 cryptography-40.0.2 jinja2-3.1.2 packaging-23.1 pycparser-2.21 resolvelib-0.8.1
Ensuite, vous aurez besoin de ce rôle, et dans ce cas, utiliser ansible-galaxy
est un bon choix pour automatiser le tout :
(ansible) user@lab ~ # ansible-galaxy install mmul.kubelab -p ansible/roles/
Démarrage du processus d'installation du rôle
- téléchargement du rôle 'kubelab', détenu par mmul
- téléchargement du rôle depuis https://github.com/mmul-it/kubelab/archive/main.tar.gz
- extraction de mmul.kubelab dans /home/rasca/ansible/roles/mmul.kubelab
- mmul.kubelab (main) a été installé avec succès
Avec le rôle en place, vous pouvez compléter les exigences, encore une fois en utilisant pip3
:
(ansible) user@lab ~ # pip3 install -r ansible/roles/mmul.kubelab/requirements.txt
...
...
Installation réussie d'ansible-vault-2.1.0 cachetools-5.3.0 certifi-2023.5.7 charset-normalizer-3.1.0 google-auth-2.18.0 idna-3.4 kubernetes-26.1.0 oauthlib-3.2.2 pyasn1-0.5.0 pyasn1-modules-0.3.0 python-dateutil-2.8.2 requests-2.30.0 requests-oauthlib-1.3.1 rsa-4.9 six-1.16.0 urllib3-1.26.15 websocket-client-1.5.1
Une fois les exigences disponibles, vous utiliserez généralement le rôle en lançant le playbook tests/kubelab.yml
, comme ceci :
(ansible) user@lab ~ # ansible-playbook -i tests/inventory/kubelab tests/kubelab.yml
REMARQUE : la date et l'heure des systèmes impliqués sont importantes ! Avoir un écart de temps entre la machine sur laquelle vous exécutez les playbooks Ansible et les machines de destination pourrait entraîner un échec de la vérification des certificats.
REMARQUE : vous pouvez choisir à tout moment de réinitialiser tout en passant k8s_reset
comme true
. Cela réinitialisera votre cluster entier, utilisez-le donc avec prudence :
(ansible) user@lab ~ # ansible-playbook -i tests/inventory/kubelab tests/kubelab.yml -e k8s_reset=true
Interagir avec le cluster après l'installation
Une fois que le playbook a terminé son exécution, le meilleur moyen d'interagir avec le cluster est d'utiliser la commande kubectl
, qui peut être installée comme suit :
user@lab ~ # curl -s -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
user@lab ~ # chmod +x kubectl
user@lab ~ # sudo mv kubectl /usr/local/bin
Le rôle Kubernetes produit un répertoire local qui contient le fichier kubeconfig principal, nommé admin.conf. Le moyen le plus simple de l'utiliser est d'exporter la variable KUBECONFIG, comme ceci :
user@lab ~ # export KUBECONFIG=~/kubernetes/admin.conf
Désormais, jusqu'à la fin de la session, chaque fois que vous utiliserez kubectl
, cela s'appuiera sur les informations d'identification contenues dans ce fichier :
user@lab ~ # kubectl cluster-info
Le plan de contrôle Kubernetes fonctionne à https://192.168.122.199:8443
CoreDNS fonctionne à https://192.168.122.199:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
Pour déboguer et diagnostiquer les problèmes du cluster plus avant, utilisez 'kubectl cluster-info dump'.
user@lab ~ # kubectl get nodes
NOM ÉTAT RÔLES ÂGE VERSION
kubernetes-1 Prêt plan de contrôle 26h v1.25.3
kubernetes-2 Prêt plan de contrôle 26h v1.25.3
kubernetes-3 Prêt plan de contrôle 26h v1.25.3
kubernetes-4 Prêt <aucun> 26h v1.25.3
Il est aussi possible d'utiliser différents utilisateurs pour se connecter au cluster, consultez la section Utilisateurs pour plus de détails.
Configuration
Inventaire
Un inventaire typique dépend de ce que vous voulez déployer. En regardant l'exemple kubelab
, vous pouvez déclarer dans le fichier des hôtes (voir tests/inventory/kubelab/hosts) tous les nœuds :
# Hôtes Kubernetes
[kubelab]
kubernetes-1 k8s_role=control-plane run_non_infra_pods=true
kubernetes-2 k8s_role=control-plane run_non_infra_pods=true
kubernetes-3 k8s_role=control-plane run_non_infra_pods=true
kubernetes-4 k8s_role=worker
Vous allez définir quels nœuds agiront en tant que plan de contrôle et si oui ou non ceux-ci exécuteront des pods non-infrastructure (pour faire du plan de contrôle aussi un worker).
Ensuite, vous pouvez définir, à l'intérieur du fichier de groupe (c'est-à-dire inventory/kubelab/group_vars/kubelab.yml), toutes les configurations supplémentaires, en fonction de ce que vous souhaitez mettre en œuvre.
Le nom du groupe d'hôtes pour l'hôte Kubernetes est par défaut kubelab
, mais peut être remplacé en déclarant la variable k8s_host_group
.
Cluster Kubernetes
Si vous souhaitez implémenter un cluster haute disponibilité à plusieurs plans de contrôle, vous devez spécifier ces variables :
k8s_cluster_name: kubelab
k8s_control_plane_node: kubernetes-1
k8s_control_plane_port: 6443
k8s_control_plane_cert_key: "91bded725a628a081d74888df8745172ed842fe30c7a3898b3c63ca98c7226fd"
k8s_multi_control_plane: true
k8s_balancer_VIP: 192.168.122.199
k8s_balancer_interface: eth0
k8s_balancer_port: 8443
k8s_balancer_password: "d6e284576158b1"
k8s_wait_timeout: 1200
k8s_control_plane_ports:
- 2379-2380/tcp
- 6443/tcp
- 8443/tcp
- 10250/tcp
- 10257/tcp
- 10259/tcp
Cela mettra en place un cluster à partir du nœud kubernetes-1
, en activant plusieurs plans de contrôle via k8s_multi_control_plane
et en définissant l'adresse VIP et l'interface.
Remarque : vous voudrez changer à la fois k8s_control_plane_cert_key
et k8s_balancer_password
pour mieux sécuriser.
Remarque : il est possible d'avoir une manière plus atomique de configurer les plages CIDR du réseau des pods, les ports des workers, les plages des nodeports et la gestion du pare-feu, vous pouvez consulter le fichier par défaut.
Add-on réseau
Le rôle Kubernetes prend en charge les add-ons réseau Flannel et Calico. La configuration dépend de quel add-on vous souhaitez mettre en œuvre.
Pour Flannel, vous aurez besoin de quelque chose comme :
# Addon Flannel
k8s_network_addon: flannel
k8s_network_addon_ports:
- 8285/udp
- 8472/udp
Pour savoir comment mettre en œuvre Calico, consultez le fichier par défaut.
Tableau de bord
Le tableau de bord Kubernetes peut être mis en œuvre en ajoutant ceci à la configuration :
k8s_dashboard_enable: true
Une fois l'installation terminée, le moyen le plus simple d'accéder au tableau de bord est d'utiliser kubectl proxy
puis d'accéder à l'URL associée http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/.
Une invite de connexion sera présentée, et vous pourrez vous connecter en utilisant un token. Par défaut, le rôle Kubernetes crée un utilisateur nommé dashboard-user
(vous pouvez le remplacer).
Pour récupérer le token, vous devrez utiliser kubectl
, comme ceci :
user@lab ~ # kubectl -n kubernetes-dashboard create token dashboard-user
<VOTRE TOKEN>
Copiez et collez la sortie de la commande ci-dessus dans le prompt et vous complétez la connexion.
Utilisateurs
Il est possible d'ajouter des utilisateurs à votre cluster, en déclarant quelque chose comme ceci :
k8s_users:
- name: pod-viewer
namespace: default
role_name: pod-viewer-role
role_rules_apigroups: '""'
role_rules_resources: '"pods","pods/exec","pods/log"'
role_rules_verbs: '"*"'
rolebinding_name: pod-viewer-rolebinding
cert_expire_days: 3650
update_kube_config: true
Cela créera un répertoire local contenant ces fichiers :
user@lab ~ # ls -1 kubernetes/users/
pod-viewer.crt
pod-viewer.csr
pod-viewer.key
users.conf
users-rolebindings.yaml
users-roles.yaml
Le fichier users.conf
peut ensuite être utilisé pour accéder au cluster avec cet utilisateur, comme ceci :
user@lab ~ # export KUBECONFIG=~/kubernetes/users/users.conf
rasca@catastrofe [~]> kubectl config get-contexts
COURANT NOM CLUSTER AUTHINFO NAMESPACE
* kubernetes-admin@kubelab kubelab kubernetes-admin
pod-viewer@kubelab kubelab pod-viewer default
user@lab ~ # kubectl config use-context pod-viewer@kubelab
Basculé vers le contexte "pod-viewer@kubelab".
user@lab ~ # kubectl config get-contexts
COURANT NOM CLUSTER AUTHINFO NAMESPACE
kubernetes-admin@kubelab kubelab kubernetes-admin
* pod-viewer@kubelab kubelab pod-viewer default
user@lab ~ # kubectl get pods
Aucune ressource trouvée dans le namespace par défaut.
Ceph CSI
Le rôle Kubernetes prend en charge l'implémentation de la StorageClass Ceph CSI. Elle peut être définie comme suit :
k8s_ceph_csi_enable: true
k8s_ceph_csi_id: lab-ceph
k8s_ceph_csi_secret_userid: kubernetes
k8s_ceph_csi_secret_userkey: AQAWvU5jjBHSGhAAuAXtHFt0h05B5J/VHERGOA==
k8s_ceph_csi_clusterid: d046bbb0-4ee4-11ed-8f6f-525400f292ff
k8s_ceph_csi_pool: kubepool
k8s_ceph_csi_monitors:
- 192.168.122.11:6789
- 192.168.122.12:6789
- 192.168.122.13:6789
Ensuite, il sera possible de déclarer de nouveaux PVC :
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: rbd-pvc
namespace: rasca
spec:
accessModes:
- ReadWriteOnce
volumeMode: Filesystem
resources:
requests:
storage: 1Gi
storageClassName: csi-rbd-sc
Et le Pod associé :
---
apiVersion: v1
kind: Pod
metadata:
name: csi-rbd-demo-pod
namespace: rasca
spec:
containers:
- name: web-server
image: nginx
volumeMounts:
- name: mypvc
mountPath: /var/lib/www/html
volumes:
- name: mypvc
persistentVolumeClaim:
claimName: rbd-pvc
readOnly: false
REMARQUE : pour le moment, seul le provisionnement rbd
est pris en charge.
MetalLB
Pour activer MetalLB, une implémentation d'équilibreur de charge pour les clusters Kubernetes baremetal, en utilisant des protocoles de routage standard, il suffit de déclarer :
k8s_metallb_enable: true
k8s_metallb_pools:
- name: 'first-pool'
addresses: '192.168.122.100-192.168.122.130'
Ensuite, il sera possible d'utiliser cet équilibreur de charge pour créer des IP dans la plage déclarée (voir l'exemple suivant sur ingress-nginx
pour comprendre).
Ingress NGINX
Pour activer Ingress NGINX, un contrôleur Ingress pour Kubernetes utilisant NGINX comme proxy inverse et équilibreur de charge, il suffit de déclarer :
k8s_ingress_nginx_enable: true
Cela installera le contrôleur Ingress NGINX qui peut être utilisé à diverses fins.
Ingress NGINX sur les plans de contrôle
Par exemple, il est possible d'utiliser Ingress NGINX en exposant les ports 80
et 443
sur l'IP équilibré gérée par haproxy, en déclarant cela :
k8s_ingress_nginx_enable: true
k8s_ingress_nginx_haproxy_conf: true
k8s_ingress_nginx_services:
- name: ingress-nginx-externalip
spec:
externalIPs:
- 192.168.122.199
ports:
- name: port-1
port: 80
protocol: TCP
- name: port-2
port: 443
protocol: TCP
selector:
app.kubernetes.io/component: controller
app.kubernetes.io/instance: ingress-nginx
app.kubernetes.io/name: ingress-nginx
Cela exposera les deux ports sur l'IP équilibrée (dans ce cas 192.168.122.199
) et fera en sorte que le service réponde là-bas.
Pour le tester, essayez ceci :
$ kubectl create deployment demo --image=httpd --port=80
deployment.apps/demo créé
$ kubectl expose deployment demo
service/demo exposé
$ kubectl create ingress demo --class=nginx \
--rule="demo.192.168.122.199.nip.io/*=demo:80" \
--annotation="nginx.ingress.kubernetes.io/service-upstream=true"
ingress.networking.k8s.io/demo créé
$ curl http://demo.192.168.122.199.nip.io
<html><body><h1>Ça fonctionne !</h1></body></html>
Ou pour tester TLS :
$ kubectl create deployment demo --image=httpd --port=80
deployment.apps/demo créé
$ kubectl expose deployment demo
service/demo exposé
$ openssl genrsa -out cert.key 2048
aucune sortie
$ openssl req -new -key cert.key -out cert.csr -subj "/CN=demo.192.168.122.199.nip.io"
aucune sortie
$ openssl x509 -req -days 366 -in cert.csr -signkey cert.key -out cert.crt
Demande de certificat auto-signée ok
sujet=CN = demo.192.168.122.199.nip.io
$ kubectl create secret tls tls-secret --cert=./cert.crt --key=./cert.key
secret/tls-secret créé
$ kubectl create ingress demo --class=nginx \
--rule="demo.192.168.122.199.nip.io/*=demo:80,tls=tls-secret" \
--annotation="nginx.ingress.kubernetes.io/service-upstream=true"
ingress.networking.k8s.io/demo créé
$ curl -k https://demo.192.168.122.199.nip.io
<html><body><h1>Ça fonctionne !</h1></body></html>
La raison pour laquelle l'annotation --annotation="nginx.ingress.kubernetes.io/service-upstream=true"
est nécessaire est expliquée dans ce problème Ingress NGINX.
Ingress NGINX avec MetalLB
Une autre façon est de l'utiliser en combinaison avec MetalLB, en déclarant un service LoadBalancer
, comme suit :
k8s_ingress_nginx_enable: true
k8s_ingress_nginx_services:
- name: ingress-nginx-lb
spec:
type: LoadBalancer
loadBalancerIP: 192.168.122.100
ports:
- name: port-1
port: 80
protocol: TCP
- name: port-2
port: 443
protocol: TCP
Cela installera tout ce qui concerne le contrôleur et assignera l'loadBalancerIP
qui fait partie de la plage fournie par MetalLB, en exposant les ports 80
et 443
.
Cert Manager
Pour activer Cert Manager, un contrôleur pour automatiser la gestion des certificats dans Kubernetes, il suffit de déclarer :
k8s_cert_manager_enable: true
k8s_cert_manager_issuers:
- name: letsencrypt
cluster: true
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: [email protected]
privateKeySecretRef:
name: letsencrypt
solvers:
- http01:
ingress:
class: nginx
Cela installera tout ce qui concerne le contrôleur et créera un émetteur de cluster qui utilisera letsencrypt
avec la résolution de défi http01
, via la classe Ingress NGINX.
Une fois tout installé et que vous souhaitez exposer une application, vous pouvez tester tout cela en utilisant quelque chose comme ce yaml :
apiVersion: v1
kind: Namespace
metadata:
name: rasca
---
apiVersion: v1
kind: ConfigMap
metadata:
name: index-html
namespace: rasca
data:
index.html: |
Ceci est mon fabuleux serveur Web !
---
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: rasca
labels:
app: nginx
spec:
containers:
- name: web-server
image: nginx
volumeMounts:
- name: docroot
mountPath: /usr/share/nginx/html
volumes:
- name: docroot
configMap:
name: index-html
---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
namespace: rasca
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
cert-manager.io/cluster-issuer: letsencrypt
name: nginx-ingress
namespace: rasca
spec:
ingressClassName: nginx
rules:
- host: nginx.apps.kubelab.mmul.it
http:
paths:
- backend:
service:
name: nginx-service
port:
number: 80
path: /
pathType: Prefix
tls:
- hosts:
- nginx.apps.kubelab.mmul.it
secretName: nginx.apps.kubelab.mmul.it
Si vous regardez spécifiquement la dernière ressource, l'Ingress
nommé nginx-ingress
, vous verrez deux sections importantes :
Sous
metadata
->annotations
, l'annotationcert-manager.io/cluster-issuer: letsencrypt
Sous
spec:
->tls
, la déclaration de l'hôte.
Avec cela en place, après un certain temps, vous aurez votre certificat servi pour le service exposé.
Licence
MIT
Informations sur l'auteur
Raoul Scarazzini (rascasoft)
This role automates the creation of a Kubernetes cluster complete of additional dashboard, users and operators.
ansible-galaxy install mmul.kubelab