Articles dans la catégorie ’Kubernetes’
Installation de AWX / Ansible
AWX est une interface web qui permet de planifier et déployer des playbooks ansible et d’automatiser la journalisation, l’audit et le suivi des systèmes.
Depuis la version 18, AWX nécessite une plateforme Kubernetes pour son déploiement.
Dans cet article, nous allons le déployer sur le cluster Kubernetes installé dans cet article. A noter, il faudra également que le LoadBalancer MetalLB soit installé comme détaillé ici.
Installation de PostgreSQL
Même si awx permet, lors de son déploiement, d’installer un serveur PostgreSQL, nous allons installer notre propre serveur dans le cadre de cette installation.
Nous allons forcer le déploiement du serveur sur worker-2 et nous allons créer un volume persistant sous /k8s/pgsql.
Sur worker-2, nous exécutons donc la commande suivante :
mkdir -p /k8s/pgsql
Depuis un noeud master, nous créons le fichier pgsql.yaml :
--- apiVersion: v1 kind: Namespace metadata: name: postgresql --- apiVersion: v1 kind: ConfigMap metadata: name: postgresql-config namespace: postgresql labels: app: postgresql data: POSTGRES_DB: awx POSTGRES_USER: awxuser POSTGRES_PASSWORD: awxuserpassword --- kind: PersistentVolume apiVersion: v1 metadata: name: postgresql-pv labels: type: local app: postgresql spec: storageClassName: manual capacity: storage: 100Gi accessModes: - ReadWriteOnce hostPath: path: "/k8s/pgsql" --- kind: PersistentVolumeClaim apiVersion: v1 metadata: name: postgresql-pvc namespace: postgresql labels: app: postgresql spec: storageClassName: manual accessModes: - ReadWriteOnce resources: requests: storage: 100Gi --- apiVersion: apps/v1 kind: StatefulSet metadata: name: postgresql-statefulset namespace: postgresql labels: app: postgresql spec: serviceName: "postgresql" replicas: 1 selector: matchLabels: app: postgresql template: metadata: labels: app: postgresql spec: nodeName: worker-2 containers: - name: postgresql image: postgres:14 envFrom: - configMapRef: name: postgresql-config ports: - containerPort: 5432 volumeMounts: - name: postgresql-data mountPath: /var/lib/postgresql/data volumes: - name: postgresql-data persistentVolumeClaim: claimName: postgresql-pvc --- apiVersion: v1 kind: Service metadata: name: postgresql-service namespace: postgresql labels: app: postgresql spec: ports: - port: 5432 type: ClusterIP selector: app: postgresql
Puis nous exécutons la commande :
kubectl create -f pgsql.yaml
Nous pouvons ensuite vérifier que le déploiement a bien été effectué :
Installation de AWX
L’ensemble des manipulations se fera depuis un noeud master (ici master-1).
Installation de Kustomize
Kustomize est un outil de transformation de configuration Kubernetes qui permet de personnaliser les fichiers YAML en laissant les fichiers d’origine intacts. Nous allons installer le binaire kustomize dans /usr/local/bin :
curl -s "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" | bash mv kustomize /usr/local/bin chmod +rx /usr/local/bin/kustomize
Installation de ingress-nginx
L’ingress-nginx va permettre de gérer les connexions extérieures et notamment le chiffrement https.
Récupérons le fichier yaml de déploiement :
wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.2.0/deploy/static/provider/baremetal/deploy.yaml
Ensuite, dans ce fichier, modifions la partie :
apiVersion: v1 kind: Service ... app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx type: NodePort
en :
apiVersion: v1 kind: Service ... app.kubernetes.io/instance: ingress-nginx app.kubernetes.io/name: ingress-nginx type: LoadBalancer
Ensuite, installons Ingress-nginx à l’aide de la commande :
kubectl create -f deploy.yaml
Installation de awx
Créons tout d’abord un namespace awx :
kubectl create namespace awx
Puis nous allons créer un secret nommé awx-tls dans le namespace awx qui comportera le certificat et la clé de chiffrement pour l’accès https au site.
En supposant que le répertoire courant comporte les fichiers server.key (clé privée) et server.crt (certificat), la commande à exécuter est :
kubectl create secret tls awx-tls --namespace awx --key server.key --cert server.crt
Nous allons créer maintenant un secret nommé awx-postgres-configuration dans le namespace awx qui contiendra les informations pour se connecter à la base de données créée précédemment.
Editons le fichier postgres_configuration_secret.yaml :
--- apiVersion: v1 kind: Secret metadata: name: awx-postgres-configuration namespace: awx stringData: host: "postgresql-service.postgresql" port: "5432" database: "awx" username: "awxuser" password: "awxuserpassword" sslmode: "prefer" type: "unmanaged" type: Opaque
Puis intégrons le avec la commande :
kubectl create -f postgres_configuration_secret.yaml
Nous allons utiliser (et installer) l’operateur AWX qui va gérer l’installation de l’application AWX sur notre cluster Kubernetes.
Créons un fichier kustomization.yaml :
apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization resources: - github.com/ansible/awx-operator/config/default?ref=0.22.0 - awx.yaml images: - name: quay.io/ansible/awx-operator newTag: 0.22.0 namespace: awx
Il est recommandé de remplacer la release (0.22.0) par le numéro de la dernière release disponible.
Créons ensuite un fichier awx-admin-password.yaml qui contiendra le mot de passe admin de notre instance awx :
--- apiVersion: v1 kind: Secret metadata: name: awx-admin-password namespace: awx stringData: password: "adminpassword"
Puis intégrons le avec la commande :
kubectl create -f awx-admin-password.yaml
Créons ensuite un fichier awx.yaml :
--- apiVersion: awx.ansible.com/v1beta1 kind: AWX metadata: name: awx spec: service_type: ClusterIP postgres_configuration_secret: awx-postgres-configuration ingress_type: ingress hostname: awx.be-root.com ingress_tls_secret: awx-tls
Attention, le hostname indiqué ici sera utilisé par nginx pour faire reverse-proxy vers le bon service.
Ensuite lançons la commande :
kustomize build . | kubectl apply -n awx -f -
Nous allons maintenant éditer l’ingress awx-ingress pour y ajouter la ligne kubernetes.io/ingress.class: nginx :
kubectl edit ingress awx-ingress -n awx
Nous pouvons maintenant vérifier que l’ensemble et fonctionnel :
Nous pouvons également remarquer que l’adresse externe 192.168.11.170 a été affectée par le LoadBalancer MetalLB à l’ingress-nginx. Nous pouvons donc faire une déclaration DNS pour faire pointer le hostname awx.be-root.com vers l’adresse 192.168.11.170.
Nous pouvons ensuite accéder à awx en https en ouvrant une page web et en utilisant le login admin et le mot de passe adminpassword :
Kubernetes : monter un volume iscsi dans un pod
Dans cet article, nous allons voir comment monter un volume persistant stocké sur un san iscsi dans un pod sous Kubernetes.
Actuellement, Kubernetes ne propose que 2 modes de montages pour les volumes iscsi : ReadWriteOnce (le volume peut être monté en lecture-écriture par un seul noeud) ou ReadOnlyMany (le volume peut être monté en lecture seule par plusieurs noeuds).
Prérequis
Nous allons nous baser sur l’architecture installée dans cet article. Sur les noeuds Worker-1, Worker-2 et Master-1 nous allons ajouter une interface réseau qui sera connectée via un switch ethernet au san iscsi. Cette interface permettra aux pods qui seront déployés sur Worker-1 et Worker-2 de monter le volume iscsi. Sur Master-1, cette interface permettra uniquement d’initialiser le volume et d’y placer des données.
La plage réseau reservée pour le réseau dédié au traffic iscsi sera 192.168.0.0/24. Les interfaces réseaux du san iscsi sont configurées sur les adresses 192.168.0.21, ,192.168.0.22, 192.168.0.23, 192.168.0.24 et le portail sur l’adresse 192.168.0.20. Le san utilisé prend en charge le multipathing.
Nous assignerons les adresses 192.168.0.10, 192.168.0.11, 192.168.0.12 respectivement à Master-1,Worker-1, Worker-2.
Par exemple, pour Worker-1, créons le fichier /etc/sysconfig/network-scripts/ifcfg-iSCSI :
TYPE=Ethernet PROXY_METHOD=none BROWSER_ONLY=no BOOTPROTO=none IPADDR=192.168.0.11 PREFIX=24 DEFROUTE=yes IPV4_FAILURE_FATAL=no IPV6_DISABLED=yes NAME=iSCSI UUID=7c0ad515-f084-3fa1-9764-bf7974e23ee8 DEVICE=ens224 ONBOOT=yes MTU="9000"
Un volume iscsi est créé sur le san. L’accès à ce volume utilise CHAP pour l’authentification de l’initiateur par la cible ainsi que pour l’authentification de l’initiateur par la cible lors de la session discovery.
Configuration
Les étapes suivantes sont à faire sur Worker-1, Worker-2 et Master-1.
Tout d’abord nous installons les logiciels requis :
dnf -y install iscsi-initiator-utils device-mapper-multipath
Nous allons modifier le nom de l’initiateur dans /etc/iscsi/initiatorname.iscsi en fonction de l’hôte sur lequel nous nous trouvons :
InitiatorName=iqn.1994-05.com.redhat:k8s-worker1
Puis nous créons le fichier /etc/multipath.conf :
defaults { polling_interval 10 path_grouping_policy multibus path_checker tur rr_min_io 10 max_fds 8192 rr_weight priorities failback immediate no_path_retry fail user_friendly_names yes }
Nota : le fichier multipath.conf peut varier en fonction du SAN utilisé. A adapter en fonction des préconisations du constructeur
Préparation du volume
Sur Master-1, nous allons modifier le fichier /etc/iscsi/iscsid.conf :
# ************* # CHAP Settings # ************* node.session.auth.authmethod = CHAP node.session.auth.username = nom_utilisateur node.session.auth.password = mot_de_passe discovery.sendtargets.auth.authmethod = CHAP discovery.sendtargets.auth.username = nom_utilisateur discovery.sendtargets.auth.password = mot_de_passe
Bien évidemment, nom_utilisateur et mot_de_passe sont à adapter en fonction de ce qui a été défini sur le SAN par rapport à l’accès au volume.
Sur Master-1, Worker-1 et Worker-2, nous pouvons à présent démarrer les services :
systemctl enable --now iscsid systemctl enable --now multipathd
Sur Master-1, nous pouvons à présent nous connecter au SAN :
iscsiadm -m discovery -t sendtargets -p 192.168.0.20 iscsiadm -m node --login
Nous pouvons ensuite vérifier que le lun iscsi est bien détecté :
Nous allons maintenant le formater :
mkfs.ext4 /dev/mapper/mpatha
Puis le monter :
mount /dev/mapper/mpatha /mnt
Nous créons ensuite le fichier /mnt/index.html :
<html> <body> <h1> This index.html is on an iscsi lun</h1> </body> </html>
Puis nous pouvons démonter le volume :
umount /mnt
Création du volume persistant
Sur Master-1, nous allons créer un fichier chap-secret.yaml comportant les identifiants CHAP :
--- apiVersion: v1 kind: Secret metadata: name: chap-secret type: "kubernetes.io/iscsi-chap" stringData: discovery.sendtargets.auth.username: nom_utilisateur discovery.sendtargets.auth.password: mot_de_passe node.session.auth.username: nom_utilisateur node.session.auth.password: mot_de_passe
Puis nous exécutons la commande :
kubectl create -f chap-secret.yaml
Nous allons ensuite créer un fichier pv-iscsi.yaml définissant le Persistant Volume ainsi qu’un Persistant Volume Claim :
--- apiVersion: v1 kind: PersistentVolume metadata: name: pv001 spec: capacity: storage: 10Gi accessModes: - ReadOnlyMany iscsi: targetPortal: 192.168.0.20 portals: ['192.168.0.21:3260', '192.168.0.22:3260','192.168.0.23:3260','192.168.0.24:3260' ] iqn: iqn.2001-05.com.mysan:0-af1ff6-9689a88eb-1c29e1debb962875-k8s-volume1 lun: 0 fsType: 'ext4' readOnly: true chapAuthDiscovery: true chapAuthSession: true secretRef: name: chap-secret --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pv001-pvc spec: accessModes: - ReadOnlyMany resources: requests: storage: 1Gi
Bien évidemment, l’iqn est à modifier en fonction de l’iqn du volume exporté par le SAN.
Puis nous exécutons la commande :
kubectl create -f pv-iscsi.yaml
Test avec un pod NGINX
Nous allons tester le bon fonctionnement en déployant un pod nginx. Nous monterons le volume sous /usr/share/html afin de pouvoir afficher notre fichier html.
Créons le fichier nginx-test.yaml :
--- apiVersion: v1 kind: Service metadata: name: test-nginx labels: run: test-nginx spec: type: NodePort ports: - port: 8080 nodePort: 30080 targetPort: 80 protocol: TCP name: http - port: 443 protocol: TCP name: https selector: run: test-nginx --- apiVersion: apps/v1 kind: Deployment metadata: name: test-nginx spec: selector: matchLabels: run: test-nginx replicas: 1 template: metadata: labels: run: test-nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80 volumeMounts: - name: www mountPath: "/usr/share/nginx/html" volumes: - name: www persistentVolumeClaim: claimName: pv001-pvc
Puis lançons la création avec :
kubectl create -f nginx-test.yaml
Nous pouvons ensuite vérifier le bon fonctionnement de l’ensemble :
Et lorsque nous ouvrons un navigateur à l’adresse http://xxx.xxx.xxx.xxx:30080 nous pouvons y voir notre fichier index.html (xxx.xxx.xxx.xxx étant l’adresse ip d’un noeud du cluster kubernetes).
Installation du LoadBalancer MetalLB pour Kubernetes
Présentation
Dans cet article nous allons installer MetalLB qui est un loadbalancer pour Kubernetes. Il permet ainsi d’utiliser des services de type LoadBalancer (traditionnellement utilisés par les clusters hebergés chez des cloud providers) tout en faisant tourner son propre cluster Kubernetes baremetal.
Ainsi, contrairement à un service de type ExternalIP, l’adresse IP attribuée au service LoadBalancer ne dépend pas d’un nœud en particulier.
MetalLB fonctionne soit en mode BGP soit en mode Layer 2. Dans cet article, nous allons le configurer pour le faire fonctionner dans le mode Layer 2. Nous partirons du cluster installé dans cet article.
Le fonctionnement dans ce mode à quelques ressemblances avec celui de keepalived. Une adresse IP sera fournie au service et tout le traffic à destination de ce service sera redirigé vers un noeud worker. Kube-proxy redirigera ensuite les requêtes vers les pods du service.
En cas de dysfonctionnement du nœud, un nouveau nœud fonctionnel répondra alors aux requêtes à destination de l’adresse IP attribuée. A la différence keepalived, les noeuds ne communiquent pas entre eux. En effet, MetalLB utilise memberlist pour connaître la disponibilité des nœuds du cluster k8s. Il ne s’agira donc pas d’un vrai équilibrage de charge mais plutôt d’une mise en place de haute disponibilité.
Installation
Tout d’abord, nous allons configurer firewalld sur l’ensemble des noeuds (supprimer la ligne correspondant au noeud courant) :
firewall-cmd --permanent --zone=public --add-rich-rule="rule family="ipv4" source address="192.168.11.101/32" port protocol="tcp" port="7946" accept" firewall-cmd --permanent --zone=public --add-rich-rule="rule family="ipv4" source address="192.168.11.102/32" port protocol="tcp" port="7946" accept" firewall-cmd --permanent --zone=public --add-rich-rule="rule family="ipv4" source address="192.168.11.103/32" port protocol="tcp" port="7946" accept" firewall-cmd --permanent --zone=public --add-rich-rule="rule family="ipv4" source address="192.168.11.121/32" port protocol="tcp" port="7946" accept" firewall-cmd --permanent --zone=public --add-rich-rule="rule family="ipv4" source address="192.168.11.122/32" port protocol="tcp" port="7946" accept" firewall-cmd --permanent --zone=public --add-rich-rule="rule family="ipv4" source address="192.168.11.101/32" port protocol="udp" port="7946" accept" firewall-cmd --permanent --zone=public --add-rich-rule="rule family="ipv4" source address="192.168.11.102/32" port protocol="udp" port="7946" accept" firewall-cmd --permanent --zone=public --add-rich-rule="rule family="ipv4" source address="192.168.11.103/32" port protocol="udp" port="7946" accept" firewall-cmd --permanent --zone=public --add-rich-rule="rule family="ipv4" source address="192.168.11.121/32" port protocol="udp" port="7946" accept" firewall-cmd --permanent --zone=public --add-rich-rule="rule family="ipv4" source address="192.168.11.122/32" port protocol="udp" port="7946" accept" firewall-cmd --reload
Ensuite nous allons positionner le paramètre StrictARP à True de la section ipvs grace à la commande :
kubectl edit configmap -n kube-system kube-proxy
L’installation se fait ensuite en lançant ces deux commandes :
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/namespace.yaml kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/metallb.yaml
Configuration
La configuration de MetalLB se fait à l’aide d’un fichier au format yaml.
Nous allons définir le pool d’adresse 192.168.11.170 à 192.168.11.199 que MetalLB va pouvoir assigner aux services.
Editons un fichier nommé config.yaml :
apiVersion: v1 kind: ConfigMap metadata: namespace: metallb-system name: config data: config: | address-pools: - name: default protocol: layer2 addresses: - 192.168.11.170-192.168.11.199
Nous pouvons ensuite appliquer ce fichier :
kubectl apply -f config.yaml
Fonctionnement
Pour tester le fonctionnement, nous allons créer le fichier nginx-lb.yaml suivant :
apiVersion: v1 kind: Service metadata: name: test-nginx labels: run: test-nginx annotations: metallb.universe.tf/address-pool: default spec: type: LoadBalancer ports: - port: 80 targetPort: 80 protocol: TCP name: http - port: 443 protocol: TCP name: https selector: run: test-nginx --- apiVersion: apps/v1 kind: Deployment metadata: name: test-nginx spec: selector: matchLabels: run: test-nginx replicas: 3 template: metadata: labels: run: test-nginx spec: containers: - name: nginx image: nginx ports: - containerPort: 80
Puis nous l’intégrons grâce à la commande :
kubectl create -f nginx-lb.yaml
La commande kubectl describe svc/test-nginx permet de connaitre l’adresse IP attribué (ici 192.168.11.170) ainsi que le noeud répondant aux requêtes (ici worker-1) :
En faisant pointer un navigateur web à cette adresse, nous avons donc bien la page d’accueil de nginx :
Si nous arrêtons le worker-1, nous pouvons voir que c’est le worker-2 qui prend le relais :