mmul.kubelab

Rôle Ansible 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.

Lint le projet Ansible Galaxy

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'annotation cert-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)

À propos du projet

This role automates the creation of a Kubernetes cluster complete of additional dashboard, users and operators.

Installer
ansible-galaxy install mmul.kubelab
Licence
mit
Téléchargements
139
Propriétaire