Archive dans 2021

Personnaliser une VM Ubuntu avec Cloud-Init sur vSphere

Cloud-Init semble être l’outil de personnalisation de prédilection pour les OS majeurs visant à être installer sur différents environnement cloud (AWS, Azure, GCP, vSphere, …), il est très puissant, hétérogène mais au début, il est difficile à appréhender.

Les informations de personnalisation sont stockées dans un fichier appelé user-data. Ce fichier est transmis à Cloud-Init grâce à un mécanisme propre à chaque cloud. Dans notre cas, ce sont les VMtools qui vont transmettre le fichier user-data, une fois reçu, Cloud-Init l’exécutera.

J’ai perdu énormément de temps à trouver les étapes minimales pour personnaliser l’OS Ubuntu avec Cloud-Init dans un environnement vSphere. Je recherchais la possibilité de personnaliser l’OS lors des clones à partir de template OVF.

Ci-dessous la procédure que j’utilise pour un Ubuntu 20.04.2 LTS, fraîchement installé et après son premier reboot. J’ai gardé les valeurs par défaut hormis le clavier Français et l’installation de l’option OpenSSH server.

Il faut dire à Cloud-Init de récupérer le fichier de personnalisation user-data via les paramètres OVF de la VM, il y a une étape à faire coté VM et une coté OS.

 

Coté OS :

  • Supprimer le fichier qui met la Datasource à none au lieu d’OVF
    • sudo rm /etc/cloud/cloud.cfg.d/99-installer.cfg
  • Si vous souhaitez que la configuration réseau se fasse, supprimer le fichier qui la désactive
    • sudo rm /etc/cloud/cloud.cfg.d/subiquity-disable-cloudinit-networking.cfg
  • Si vous êtes en DHCP, la VM récupérera toujours la même IP car elle gardera le même machine ID. Pour éviter cela il faut remettre à zéro l’identité de l’OS :
    • sudo truncate -s 0 /etc/machine-id

 

Coté VM :

  • Récupérer le contenu de votre fichier cloud-init user-data et le codé avec base64 :
    • Base64 user-data.yaml
  • A partir du vSphere client, lorsque la VM est arrêtée, Activer les propriétés de l’OVF :
    • Sélectionnez la VM => Configure => vApp Options => vApp Options are disabled … Edit => Cliquer sur “Enable vApp options”
    • Dans l’onglet OVF details => => sélectionner la case VMware Tools
  • A partir du vSphere client, lorsque la VM est arrêtée, ajouter le champ user-data dans les propriétés de l’OVF :
    • => Sélectionnez la VM => Configure => vApp Options => Properties => ADD mettre le Label et Key id  à la valeur user-data.
  • A partir du vSphere client, lorsque la VM est arrêtée, ajouter la valeur au champ user-data dans les propriétés de l’OVF :
    • Sélectionnez la VM => Configure => vApp Options => Properties => SET VALUE, un popup s’ouvre et mettre la clé base64 du contenu du fichier user-data récupérée un peu plus haut

 

 

Maintenant à partir de cette VM, faite directement un clone pour en faire une autre VM ou pour en faire un template. Si vous souhaitez changer le fichier user-data, au moment du déploiement de la VM, changez uniquement la clé base64 par la nouvelle clé.

 

 

Déployer des VMs dans et via Kubernetes

Les applications sont souvent composées de PODs Kubernetes et de VMs. L’exemple le plus commun que l’on retrouve est, une base de données sous forme de VM et le reste de l’application sous forme de PODs. Par reflexe, à tort ou à raison, ce qui nécessite de la persistance de données est mis sous forme de VMs.

La plateforme vSphere with Tanzu est une plateforme permetant elle aussi d’héberger simultanément et nativement des PODs Kubernetes et des VMs.

Jusqu’à présent les VMs et les PODs étaient déployées via des méthodes différentes et connectés sur des réseaux différents, ce qui pouvait engendrer pour les développeurs un délai de mise à disposition d’environnement de développement et des risques d’échecs de connexion. En effet, les développeurs devaient demander à l’équipe qui gère l’infrastructure, le déploiement d’une VM avec une expression de besoin.

Pour diminuer l’impact temps et les risques d’erreur, les équipes d’infrastructure ont mis en place des outils d’automatisation via un système de ticketing ou via un portail self-service pour donner ainsi une certaine autonomie. Le déploiement est bien simplifié mais ce n’est pas encore suffisant car ça implique au développeur l’apprentissage et l’utilisation d’outils supplémentaires et de récupérer les modalités de connexions à la VM déployée. Le portail self-service n’est pas désuet pour autant, il a beaucoup d’autres valeurs comme la gestion de la gouvernance, j’espère avoir l’occasion d’écrire un article dessus pour les détaillées.

Schéma de principe montrant un développeur qui click sur son portail pour déployer une VM qui sera connectée à un réseau.
Ce même développeur utilise la commande Kubernetes kubectl pour déployer ses PODs. Kubernetes utilise son propre réseau.

Depuis vSphere 7U2a il est désormais possible de provisionner des VMs de la même manière que l’on déploie des PODs, en utilisant la commande kubectl de Kubernetes. Pour être plus précis, depuis le début de vSphere with Tanzu (à l’origine ça s’appelait Projet Pacific) il était possible de déployer des Machines virtuelles à partir de Kubernetes, elles étaient cependant réservées aux usages internes de Kubernetes comme pour la création de Tanzu Kubernetes Cluster.

Désormais le développeur peut lui aussi déployer ses propres machines virtuelles, elles seront en plus connectées au même réseau que les pods. La perte de temps et les risques d’erreur sont ainsi éliminés. J’ai fait le test sur mon environnement de démonstration qui est mutualisé avec mes autres collègues, ça prend moins de 3 minutes pour avoir une base MongoDB fraîchement installée à partir d’un Linux Ubuntu complètement vierge.

Schéma de principe montrant un développeur qui utilise fois la commande Kubernetes kubectl pour déployer ses PODs et ses VMs.
Le tout sera connecté au même réseau Kubernetes

 

Quels sont les périmètres de chaque persona ?

Il y en a deux, le fournisseur de ressources et le consommateur. Le fournisseur est l’administrateur de l’infrastructure qui va présenter les ressources à consommer et si nécessaire les caper. Le consommateur est le développeur qui va utiliser ces ressources via Kubernetes pour développer son application.

La personne de l’infrastructure avec son outil habituel (vSphere client), créé un Namespace de ressources, octroi les droits d’accès au développeur, définir les classes de service (nb de CPU, quantité de RAM) auquel le développeur aura le droit d’utiliser et la librairie d’image de VM qu’il pourra utiliser.

Le développeur se connecte via son compte au Namespace fourni et créé ainsi ses fichiers YAML afin de définir ses besoins en ressources pour sa ou ses machines virtuelles et s’ils le souhaitent, il peut la ou les personnaliser afin d’y installer ses outils et les services dont il a besoin.

En résumé, vSphere with Tanzu laisse le choix au développeur d’avoir ses composant applicatifs développés et hébergés sur des PODs ou sur des VMs et ce en utilisant le même outil, le même réseau et la même plateforme. Il y gagne ainsi en temps de déploiement, de développement et en agilité.

 

Si vous souhaitez soulevez le capot, je vous invite à lire cet article : Etapes pour la création de VM via kubectl

Etapes pour la création de VM via kubectl

Pour créer une machine virtuelle avec vSphere with Tanzu via la commande kubectl, il y a des étapes à respecter pour l’administrateur et pour le développeur, elles sont très simples mais ce ne m’a pas empêché de perdre un peu de temps coté personnalisation sur la partie OS.

je vous recommande cet article pour comprendre l’intéret de déployer des VM via Kubernetes : Déployer des VMs dans et via Kubernetes. Le blog de mon collègue : Introducing Virtual Machine Provisioning, via Kubernetes with VM Service | VMware est aussi très bien détaillé.

Dans la dernière partie cet article, je vais apporter quelques précisions sur la partie Content Library et sur la partie YAML. Mais d’abord, revoyons avant les partie à faire coté administrateur et coté développeur

 

Concernant l’administrateur

La première étape consiste à télécharger les images VMs qui sont différentes de celles utilisées pour TKC (Tanzu Kubernetes Cluster aussi appelé Guest Cluster). Les images sont disponibles dans la marketplace VMware, au moment de la rédaction de cet article, il y en a 2 (Ubuntu et Centos), la version Ubuntu actuelle ne permet pas l’utilisation de volume persistent (PVC) car elle est basée sur une version virtual hardware 10 et il faut au minimum une version 12, ce problème va bientôt être corrigé.

Il faut aller sur la marketplace et faire une recherche avec le mot clé « vm service », ça permet de filtrer (un peu) les images compatibles => VMware Marketplace.

Ensuite cliquer sur l’image souhaitée, se connecter avec son compte MyVMware.

Vous avez deux possibilités, la télécharger puis la charger dans une content library locale

ou récupérer l’url de souscription pour créer une content library qui se synchronisera à celle hébergée par VMware.

Une fois l’image chargée ou le lien renseigné, vous devriez avoir une content library de ce type :

Toujours depuis l’interface vSphere, il faut maintenant créer, un namespace, octroyer les droits aux utilisateurs pour qu’ils puissent s’y connecter, affecter la classe de VM, la content library et la classe de stockage, ce qui devrait donner ceci :

 

L’exemple ci-dessus montre une fois le namespace créé, comment affecter une classe de VM, une content library, autoriser les développeurs qui pourront consommer ce namespace, quelle classe de stockage à utiliser et enfin si besoin caper les ressource, CPU, mémoire et stockage.

C’est tout ce qu’il y a à faire coté administrateur d’infrastructure.

 

Concernant le développeur

Il faut un descriptif YAML pour :

  • La configmap qui contient la personnalisation de la VM
  • La création de la VM
  • Le service réseau si vous souhaitez vous y connecter à partir d’un réseau extérieur (optionnel)
  • Le PVC si vous souhaitez utiliser des volumes persistants (optionnel)

Via la commande Kubernetes, le développeur se connecte avec son compte au Namespace fourni, il pourra ainsi lister les classes de services qu’il peut utiliser ainsi que les images qu’il pourra déployer.

kubectl get virtualmachineclass

NAME                  CPU   MEMORY   AGE
best-effort-2xlarge   8     64Gi     22d
best-effort-4xlarge   16    128Gi    22d
best-effort-8xlarge   32    128Gi    22d
best-effort-large     4     16Gi     22d
best-effort-medium    2     8Gi      31d
best-effort-small     2     4Gi      31d
best-effort-xlarge    4     32Gi     22d
best-effort-xsmall    2     2Gi      22d
..
guaranteed-xsmall     2     2Gi      22d

 

kubectl get virtualmachineimage
NAME                                                         VERSION                           OSTYPE                FORMAT   AGE
centos-stream-8-vmservice-v1alpha1-1619529007339                                               centos8_64Guest       ovf      4h8m
ob-15957779-photon-3-k8s-v1.16.8—vmware.1-tkg.3.60d2ffd    v1.16.8+vmware.1-tkg.3.60d2ffd    vmwarePhoton64Guest   ovf      2d19h
ob-16466772-photon-3-k8s-v1.17.7—vmware.1-tkg.1.154236c    v1.17.7+vmware.1-tkg.1.154236c    vmwarePhoton64Guest   ovf      2d19h
ob-16545581-photon-3-k8s-v1.16.12—vmware.1-tkg.1.da7afe7   v1.16.12+vmware.1-tkg.1.da7afe7   vmwarePhoton64Guest   ovf      2d19h
……
ubuntu-20-1621373774638                                                                        ubuntu64Guest         ovf      4h8m

Il peut ainsi créer ses fichiers descriptifs YAML afin de définir ses besoins en ressources pour sa ou ses machines virtuelles et s’ils le souhaitent, il peut la ou les personnaliser afin d’y installer ses outils.

Le fichier descriptif configmap, comprend la personnalisation de la VM. Les 3 champs importants à renseigner pour la personnalisation sont :

  1. Le hostname qui contient le hostname de l’OS
  2. La public-keys, qui contient la clé publique d’un poste à partir duquel on se connectera à l’os en ssh.
  3. La partie user-data est, si vous le souhaitez, l’endroit où on met le contenu du fichier de configuration Cloud Init, il faudra le chiffrer avec la commande base64.

 

cat loeil-du-se-vm-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
    name: loeil-du-se-vm-configmap # Le nom de la ConfigMap, doit être le même que celui référencé dans le YAML de la VirtualMachine
    namespace: loeil-du-se
data:
  # Champs OVF utilisés lors du déploiment de la VM
  hostname: loeil-du-se
  public-keys: ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDC4Cclh3rN/l70lBNlwQyK6ZtugxqT/7HeerHZKPSO0hcl5ZWLvz2+7QG5FqvYbkPP6EomvyDhE2MPnQ0kWaIrumVxYXAbVdpBBKKdTI3xJpewWB2syxgVOXP2ZOrw4cRLFv18rnESGHfsohedyaSB1qvubPWAqBFa+PSS4xh3zKalUknwc7Bs14fci8tEwEg8cpvNsqvrPZliJ6qTYFGqKuG6Ct+y449JNW6k6itTepgSYvUdJfjBTxk5tDzBdWz28km5N7lxgUB0rIWgSDl1XLCBrmm+H6bkHtD59MxAuxwLjih4tS4PzspcVjwWiJhd0HH7u2wbsPLCrrAX7am4EP40zphu9IR+fVxk+2jp7eD2uXPS6p9sDPEWHl6wGclI7pnfuoyvcn+CIwCtMweLuUw5MPj2eIIXcBhqUffeVAXVHrx8+e7+yHvqfyhqm2J9Ay3yt3zvAcXW0VqDxfvnfmv8sc9VNUW+8fUeyoo4b4uZRLLSf2DHM8= root@fbenrejdal-z01 # Clé publique SSH du poste permettant de se connecter sans mot de passe à l’OS de la VM
  user-data: | # optionel, le contenu chiffré en base64 du fichier Cloud Init. La clé peut être sur une seule ligne ou sur plusieurs, elle doit démarrer au niveau du “r” sous user-data
     I2Nsb3VkLWNvbmZpZwojIFdBVENIT1VUIHRoZSBmaXJzdCBsaW5lIG11c3Qgc3RhcnQgd2l0aCAj
     Y2xvdWQtY29uZmlnCmdyb3VwczoKICAtIGRldm9wcwp1c2VyczoKICAtIGRlZmF1bHQgIyBDcmVh
     dGUgdGhlIGRlZmF1bHQgdXNlciBmb3IgdGhlIE9TCiAgLSBuYW1lOiBmYmUKICAgIHNzaC1hdXRo
     b3JpemVkLWtleXM6ICMgdGhlIHB1YmxpYyBrZXkgb2YgbXkgbGFwdG9wLCBpdCBjb3VsZCBhbHNv
     IGJlIGZpbGxlZCBpbiB0aGUgT1ZGIHByb3BlcnR5CiAgICAgIC0gc3NoLXJzYSBBQUFBQjNOemFD
     MXljMkVBQUFBREFRQUJBQUFCZ1FEQzRDY2xoM3JOL2w3MGxCTmx3UXlLNlp0dWd4cVRHLzdIZWVy
     SFpLUFNPMGhjbDVaV0x2ejIrN1FHNUZxdllia1BQNkVvbXZ5RGhFMk1QblEwa1dhSXJ1bVZ4WVhB
     YlZkcEJCS0tkVEkzeEpwZXdXL0Iyc3l4Z1ZPWFAyWk9ydzRjUkxGdjE4cm5FU0dIZisvc29oZWR5
     YVNCMXF2dWJQV0FxQkZhK1BTUzR4aDZELzN6S2FsVWtud2M3QnMxNGZjaTh0RXdFZzhjcHZOc3F2
     clBabGlKNnFUWUZHcUt1RzZDdCt5NDQ5Sk5XNms2aXRUZXBnU1l2VWRKZmpCVHhrNXREekJkV3oy
     OGttNU43bHhnVUIwcklXZ1NEbDFYTENCcm1tK0g2YmtIdEQ1OU14QXV4d0xqaWg0dFM0UHpzcGNW
     dGFydCBtb25nb2QK

 

La base64 est obtenu de la manière suivante :
base64  loeil-du-se-vm-cloud-init.yaml

Son contenu en clair :
cat  loeil-du-se-vm-cloud-init.yaml
#cloud-config
# ATTENTION la première ligne doit commencer par #cloud-config
groups:
  – devops
users:
  – default # Créé l’utisateur par défaut
  – name: fbe
  ssh-authorized-keys: # Clé SSH de mon laptop me permettant de me connecter via SSH sans mot de passe. Clé déjà renseignée dans la configmap
    – ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDC4Cclh3rN/l70lBNlwQyK6ZtugxqTG7HeerHZKPSO0hcl5ZWLvz2+7QG5FqvYbkPP6EomvyDhE2MPnQ0kWaIrumVxYXAbVdpBBKKdTI3xJpewWB2syxgVOXP2ZOrw4cRLFv18rnESGHf+sohedyaSB1qvubPWAqBFa+PSS4xh6D3zKalUknwc7Bs14fci8tEwEg8cpvNsqvrPZliJ6qTYFGqKuG6Ct+y449JNW6k6itTepgSYvUdJfjBTxk5tDzBdWz28km5N7lxgUB0rIWgSDl1XLCBrmm+H6bkHtD59MxAuxwLjih4tS4PzspcVjwWiJhd0HH7u2wbsPLCrrAX7am4EP40zphu9IR+fVxk+2jp7eD2uXPS6p9sDPEWHl6wGclI7pnfuoyvcn+CIwCtMweLuUw5MPj2eIIXcBhqUffeVAXVHrx8+e7+yHvqfyhqm2J9Ay3yt3zvAcXW0VqDxfvnfmv8sc9VNUW+8fUeyoo4b4uZRLLSf2DHM8= root@fbenrejdal-z01
      groups: sudo, devops
    shell: /bin/bash
    passwd: VMware1!
    sudo: [‘ALL=(ALL) NOPASSWD:ALL’] # l’utilisateur fbe n’aura pas à rentrer de mot de passe avec la commande sudo
  ssh_pwauth: true
  chpasswd:
  list: |
    fbe:VMware1! # changer le mot de passe de l’utilisateur fbe
    expire: false  # Pour que le mot de passe n’expire pas
runcmd: # Exemple de runcmd pour installer MongoDB. Cloud Init est aussi capable d’utiliser directement APT pour faire des installations
  – echo “deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/4.4 multiverse” | tee /etc/apt/sources.list.d/mongodb-org-4.4.list
  – wget -qO – https://www.mongodb.org/static/pgp/server-4.4.asc | apt-key add –
  – echo “deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/4.4 multiverse” | tee /etc/apt/sources.list.d/mongodb-org-4.4.list
  – apt-get update
  – apt-get install -y mongodb-org
  – echo “mongodb-org hold” | dpkg –set-selections
  – echo “mongodb-org-server hold” | dpkg –set-selections
  – echo “mongodb-org-shell hold” | dpkg –set-selections
  – echo “mongodb-org-mongos hold” | dpkg –set-selections
  – echo “mongodb-org-tools hold” | dpkg –set-selections
  – sed -i ‘s/127.0.0.1/0.0.0.0/’ /etc/mongod.conf
  – ufw allow from any to any port 27017 proto tcp
  – sleep 2
  – systemctl start mongod

Très très important, le fichier doit absolument commencer par #cloud-config et pas autre chose. Ça reste un fichier Cloud Init classique.

Si vous ne maitrisez pas trop Cloud Init, j’y ai mis des commentaires pour que ce soit un peu plus lisible.

 

Le fichier descriptif de la VM

cat loeil-du-se-vm-deployment.yaml
apiVersion: vmoperator.vmware.com/v1alpha1
kind: VirtualMachine
metadata:
  name: loeil-du-se-vm
  namespace: loeil-du-se
labels:
  vm: loeil-du-se-vm
spec:
  imageName: ubuntu-20-1621373774638 #L’image doit être présente dans la content library et visible via la commande kubectl get virtualmachineimage
  className: best-effort-xsmall
  powerState: poweredOn
  storageClass: silver-storage-policy
  networkInterfaces:
  – networkType: nsx-t # soit nsx-t ou vsphere-distributed en fonction de votre installation
# networkName:
si -networkType est vsphere-distributed il faut mettre le nom du port group des workload
  vmMetadata:
    configMapName: loeil-du-se-vm-configmap # Nom de la configmap où la personnalisation de la VM est stockée
    transport: OvfEnv
#
#  Au moment de l’écriture de cet article l’image ubuntu (ubuntu-20-1621373774638) ne peut pas utiliser les volumes car elle est basée sur la version 10 du virtual hardware est il faut au minimum qu’elle soit en 12
#  L’image centos image (centos-stream-8-vmservice-v1alpha1-1619529007339) peut utiliser des volumes
#  volumes: # au moment de l’écriture de cet article, le paramètre mount n’est pas utilisable, le volume est vu mais doit être monté à la main ou via Cloud Init
#    – name: loeil-du-se-volume
#      persistentVolumeClaim:
#      claimName: loeil-du-se-pvc
#      readOnly: false

 

Optionnel, le fichier descriptif du service réseau

Dans mon exemple, je créé un service de type LoadBalancer pour me connecter en ssh à partir d’un réseau externe à celui des PODs.

Attention, le kind n’est pas Service comme habituellement mais VirtualMachineService

cat loeil-du-se-vm-service.yaml
apiVersion: vmoperator.vmware.com/v1alpha1
kind: VirtualMachineService
metadata:
  name: loeil-du-se-vm
spec:
  selector:
    vm: loeil-du-se-vm
  type: LoadBalancer
  ports:
    – name: ssh
      port: 22
      protocol: TCP
      targetPort: 22

 

Une fois les fichiers YAML créés, il ne reste plus qu’à les faire prendre en compte par Kubernetes.

Kubectl create -f loeil-du-se-vm-configmap.yaml

Kubectl create -f loeil-du-se-vm-deployment.yaml

Kubectl create -f loeil-du-se-vm-service.yaml

 

Pour verifier la creation de la VM :

Kubectl get vm

 

Pour en savoir un peu plus :

Kubectl describe vm loeil-du-se-vm

 

Ca reste une VM classique, donc elle va bénéficier de HA et vMotion (via DRS ou mode maintenance du host). Par contre, elle est « Developer Managed », c’est-à-dire qu’elle n’est pas administrable via le vCenter, vous ne verrez pas par exemple le contenu de la console.

Une astuce tout de même, vérifiez sur quel ESXi la VM s’exécute, ensuite connectez-vous directement sur l’ESXi via un navigateur et là vous aurez accès à la console.

Pour se connecter en ssh, si vous avez comme moi un accès via un loadbalancer vous pouvez vous y connecter directement, sinon vous devrez passer par un POD de rebond (genre busybox, alpine ou autre) et faire un ssh avec l’adresse IP sur le réseau de POD. Vous pouvez la retrouver ainsi :

kubectl get vm loeil-du-se-vm -o jsonpath='{.status.vmIp}’; echo
10.244.0.130

 

Le ssh doit se faire via le user renseigné dans le Cloud Init, j’avais mis fbe, ca donne ça :

kubectl get svc loeil-du-se-vm
NAME             TYPE           CLUSTER-IP    EXTERNAL-IP    PORT(S)        AGE
loeil-du-se-vm   LoadBalancer   10.96.1.108   172.20.18.71   22:32148/TCP   2d22h

ssh fbe@172.20.18.71

To run a command as administrator (user “root”), use “sudo <command>”.
See “man sudo_root” for details.
fbe@loeil-du-se:~$

 

Si le ssh ne fonctionne pas, c’est que le user n’a pas était pris en compte par Cloud Init, essayez avec root pour obtenir le user par défaut, en générale ubuntu pour Ubuntu et cloud-user pour CentOS :

ssh roo@172.20.18.71
Please login as the user “ubuntu” rather than the user “root”.

 

Si vous avez l’erreur ci-dessous, c’est que le poste à partir duquel vous vous connectez n’a pas la clé ssh publique renseignée ou il y a une erreur dans celle-ci, il faut donc vérifier la clé figurant dans le fichier de configmap :

fbe@172.20.18.71: Permission denied (publickey,password).

Pour debugger Cloud Init, il faut se connecter à l’os de la vm via ssh ou via la console est regardez la log /var/log/cloud-init-output.log

Voilà, n’hésitez pas à me pinger si vous avez besoin d’informations complémentaires.

Quelle plateforme pour les applications « Share Nothing Architecture » ?

Les entreprises cherchent de l’agilité pour aller de plus en plus vite dans leur croissance. Lorsqu’elles développent des applications à destination de l’interne ou de l’externe c’est pour accompagner cette croissance de manière à avoir un impact direct ou indirect. Il faut donc tout faire pour que les développeurs puissent développer ces applications en ayant eux aussi l’agilité attendue. D’où l’attrait des services du cloud public, en effet tout est déjà prêt à être consommé, il déploie simplement un service de données (type base de données ou objet) et interconnecte l’application avec, ils se focalisent sur leur développement. Avoir cette souplesse dans son datacenter permettrait d’allier agilité et sécurité maîtrisée.

La plate-forme VMware Cloud Foundation withTanzu (anciennement vSphere with Kubernetes ou encore Projet Pacific) est une plate-forme mixte capable d’héberger simultanément des applications fonctionnant sur des machines virtuelles et des applications fonctionnant sur des PODs Kubernetes (des containers). Elle permet aussi de fournir d’ores et déjà les services réseau, les services de stockage, le service de registry et le service de sauvegarde/restauration. La plate-forme se dote désormais de services autour de la donnée. Au moment de la rédaction de cet article, deux solutions y sont déjà intégrées : Minio et Cloudian, solutions de stockage objets compatible avec l’API S3, deux autres sont en cours d’intégration : Dell EMC ObjectScale lui aussi un stockage objet compatible S3 et Datastax une base de données NoSQL à base de Cassandra. D’autres viendront rapidement.

 

En quoi est-ce révolutionnaire ?

Contrairement à la majorité des applications dites traditionnelles/classiques/monolithique, les applications dites modernes/Cloud Native/scalable, elles, ne comptent pas sur les artifices de l’infrastructure pour optimiser leur performance ou pour assurer leur résilience, elles utilisent leurs propres mécanismes de manière à être disponible, performante autant que possible et ce quelle que soit l’infrastructure. Elles ont bien sûr besoin de cette infrastructure mais brute, juste pour consommer directement les ressources telles quelles, brutes (les processeurs, de la mémoire et des axes d’IO). Ces applications sont bien souvent des applications SNA (Shared Nothing Architecture), chaque instance servant une même application utilise ses propres ressources sur un serveur distinct et répartissent les données entres ces serveurs, les lectures et  les écritures des données sont ainsi distribuées pour de meilleur performances et une meilleure résilience en prenant en compte la perte potentiel d’un serveur voire d’un site complet.

Sur une infrastructure physique (sans virtualisation), chaque instance à son propre serveur et ses propres ressources. Il n’y a donc pas de problème de placement, une instance sur chaque serveur, cependant, cela induit un problème financier car les serveurs sont dédiés à cet usage, ce n’est pas optimum à moins de consommer toutes les ressources et tout le temps, ce qui est rarement le cas.

Sur une infrastructure virtuelle, les ressources sont partagées, par conséquent celles non utilisées le sont par d’autres applications, elle permet aussi de s’affranchir des problèmes de comptabilité avec le matériel et de bénéficier de tous les autres avantages maintenant connus apportés par la virtualisation. Cependant elle apporte une contrainte pour les applications SNA, comme les instances sont virtualisées, comment s’assurer que ces instances et surtout les données générées sont bien réparties sur des serveurs de virtualisation distincts et donc pouvoir se prémunir de la perte de l’un d’entres eux ?

C’est là que la plateforme VMware Cloud Foundation with Tanzu couplée au module vSAN Data Persistence plateforme (vDPp) entre en jeux. Elle permet aux éditeurs partenaire de tirer le meilleur parti de la plateforme en fournissant leur solution « as a Service ». Cela passe par le développement d’un opérateur qui va automatiser l’installation, la configuration et simplifier le maintien en condition opérationnelle de l’application.

Il suffit de cliquer pour que le service soit opérationnel

 

vDPp connait l’infrastructure, l’application, elle, sait comment assurer sa disponibilité et obtenir ses meilleures performance. L’opérateur va ainsi répartir le nombre d’instance nécessaire sur différents serveurs de virtualisation.

Cette politique de stockage vSAN permet

de garder l’instance applicative sur le même serveur de virtualisation où sont stockées les données.

 

Lors d’opérations de maintenance, l’application est tenue informée afin qu’elle puisse prendre en compte le décommissionnement à chaud d’un serveur de virtualisation.

vDPp tient également informée l’application de manière pro-active si des disques commencent à donner des signes de défaillance.

Les développeurs quant à eux, n’ont qu’à consommer ces services via les APIs habituelles et se consacrer au développement de leur application sans se soucier de rien d’autre. Ils ont un service de données activable à la demande, résiliant, performance.

 

En résumé :

La plateforme VMware Cloud Foundation with Tanzu couplée avec vSAN Data Persistence platform offre une agilité unique pour faciliter le maintien en condition opérationnelle des services de données. Grace à cela, les développeurs se focalisent sur le développement de leur application en continuant d’utiliser leurs outils traditionnels, ils ont une plate-forme souple à l’instar de ce qui se fait sur le cloud public.

Il faut voir la plateforme Cloud Foundation with Tanzu comme une plateforme complète pour développer et héberger les applications traditionnelles comme les applications modernes avec les services intégrés disponible à la demande que cela nécessite.

Déployer Kubeapps pour un usage multi-clusters

 

Dans cet article nous allons voir comment déployer Kubeapps en environnement multi-cluster. Habituellement il se déployait cluster par cluster, ici, l’objectif est d’avoir une seule instance Kubeapps capable de déployer et de gérer les applications sur plusieurs clusters. Pour cela, il faut que chaque cluster soit capable de s’authentifier à une source IdP (Identity Provider).

Dans mon exemple je vais utiliser des clusters TKG 1.2.1 avec l’extension incluse Dex. Dex va permettre l’authentification avec un provider OpenID Connect (OIDC).  Pour info, dans notre exemple l’extension Gangway qui normalement va de pair avec Dex n’est pas utile. Elle sert à générer un Kubeconfig une fois que l’utilisateur s’est authentifié via la page web du cluster. Kubeapps n’a pas besoin de cette extension car il utilise un proxy Oauth2. Sur mon environnement, je vais utiliser des clusters existant qui sont déjà configurés avec l’extension Gangway et 1 que je vais créer sans installer Gangway (2 clusters auraient pu suffire mais c’est tellement simple à déployer avec TKG qu’on ne va pas se priver).

Étape primordiale, c’est d’ avoir l’extension Dex d’installée sur le cluster de management et le configurer pour qu’il puisse faire des requêtes sur une source IdP : https://docs.vmware.com/en/VMware-Tanzu-Kubernetes-Grid/1.2/vmware-tanzu-kubernetes-grid-12/GUID-extensions-dex.html. Une fois Dex installé, il faut créer des clusters de workload compatibles OIDC et déployer Kubeapps sur un cluster de préférence distinct (ou commencer par installer Kubeapps et le mettre à jour pour qu’il prenne en compte les nouveaux clusters).

Exporter les variables sur l’environnement du cluster DEX :

export AUTH_MGMT_CLUSTER=”auth-mgmt-cluster-admin@auth-mgmt-cluster” # nom de mon cluster de management
export OIDC_ISSUER_URL=https://172.20.7.10:30167 #IP et Port de mon cluster de management où est installé DEX
export OIDC_USERNAME_CLAIM=email
export OIDC_GROUPS_CLAIM=groups
export OIDC_DEX_CA=$(kubectl get secret dex-cert-tls -n tanzu-system-auth -o ‘go-template={{ index .data “ca.crt” }}’ –context $AUTH_MGMT_CLUSTER| base64 -d | gzip | base64) # certificat du cluster de management

Créer ensuite les clusters de workloads :

tkg create cluster usine-32 –enable-cluster-options oidc –plan dev –vsphere-controlplane-endpoint 172.20.7.17

Logs of the command execution can also be found at: /tmp/tkg-20210106T094128013610360.log
Validating configuration…
Creating workload cluster ‘usine-32’…
Waiting for cluster to be initialized…
Waiting for cluster nodes to be available…
Waiting for addons installation…
Workload cluster ‘usine-32’ created

 

Récupérer le context du cluster pour qu’il soit intégré dans le kubeconfig et ainsi récupérer l’url de l’API server: et le certificat certificateAuthorityData:

tkg get credentials usine-32
Credentials of workload cluster ‘usine-32’ have been saved
You can now access the cluster by running ‘kubectl config use-context usine-32-admin@usine-32’

 

Se connecter au cluster afin d’autoriser les utilisateurs à s’y connecter et de déployer des applications :

kubectl config use-context usine-32-admin@usine-32

cat << EOF | kubectl apply –
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: tkg-users
subjects:
  – kind: Group          # Donner le rôle au groupe, mettre User si vous souhaitez cibler un user en particulier
    name: tkg-users # Mettre le nom du groupe, tous les utilisateurs du groupe seront pris en compte
    apiGroup: “”
roleRef:
  kind: ClusterRole #this must be Role or ClusterRole
  name: cluster-admin # ClusterRole à avoir
  apiGroup: rbac.authorization.k8s.io
EOF

 

Une fois le cluster créé, les droits d’accès positionnés, l’url et le certificat récupérés (si besoin, reproduire les mêmes étapes pour d’autres clusters de workload), il reste deux fichiers à modifier, l’un concerne le fichier de valeurs de l’installation de Kubeapps et l’autre le fichier de configuration DEX.

Modification du fichier de valeurs pour l’installation de Kubeapps (Exemple provenant de mon collègue Michael Nelson : https://liveandletlearn.net/post/kubeapps-on-tkg-management-cluster/) :

# Dans mon exemple Kubeapps est accessible au travers d’un LoadBalancer
frontend:
  service:
    port: 80
    type: LoadBalancer
# Setup the oauth2-proxy running on the frontend to handle the OIDC authentication
authProxy:
  enabled: true
  provider: oidc
  clientID: auth-tools
  ## les deux Secrets ci-dessous sont à générer par vous-même (32 octets max)
  clientSecret: wPmp8+IrTxbGZbVF/yqPPeP4XZzw5mLt
  cookieSecret: fiUrXyEBQx7uWlcw55CxQkbYwZ4a/cC7
  additionalFlags:
    # C’est l’adresse IP et le port de DEX qui est installé sur le cluster de management
    – –oidc-issuer-url=https://172.20.7.10:30167
    # les clusters derrières le mot audience sont les clusters sur lesquels les déploiements seront autorisés, ils doivent aussi figurer en bas de ce fichier et dans le fichier de configuration Dex
    – –scope=openid email groups audience:server:client_id:workload-01 audience:server:client_id:workload-02 audience:server:client_id:usine-01 audience:server:client_id:usine-32
    # Comme j’ai des certificats autosignés, il ne faut pas les vérifier auprès d’une autorité
    – –ssl-insecure-skip-verify=true
    # Since Kubeapps is running without TLS, can’t use secure cookies
    – –cookie-secure=false
    # If you need to access the actual token in the frontend for testing, uncomment the following.
    # – –set-authorization-header=true
# Liste des clusters sur lesquels les déploiements seront autorisés, les mêmes renseignés un peu plus haut
# L’apiServiceURL et le certificateAuthorityData sont ceux récupérés dans le fichier kubeconfig un peu plus haut
# dans mon exemple j’ai 4 clusters de workload
clusters:
  – name: workload-01
  apiServiceURL: https://172.20.7.14:6443
  certificateAuthorityData: USUZJQ0FURS0tQkFRc0ZBREFWTVJNd0……..E9KOFhFQUI1aVBqVDQxWXZzeEE9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
  – name: workload-02
  apiServiceURL: https://172.20.7.15:6443
  certificateAuthorityData: LS0tLS1CRUdJTiBDRVJUSUZJQ0FBREFWTVJNd0…….wS1V1UUgvcCtjMWkvYW89Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
  – name: usine-01
  apiServiceURL: https://172.20.7.16:6443
  certificateAuthorityData: LS0TkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0….Es2RWpSNys2NkNlT2dpeHcxVUk9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
  – name: usine-32
  apiServiceURL: https://172.20.7.17:6443
  certificateAuthorityData: BTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0…cldORUNGb3FJelZkdXdKRGNFMTA9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K

 

Maintenant, on peut installer Kubeapps dans un namespace avec comme paramètre ce fichier de valeurs (ici, je l’ai appelé kubeapps-dex.yaml) :

kubectl create namespace kubeapps-system
helm install kubeapps bitnami/kubeapps –namespace kubeapps-system –values kubeapps-dex.yaml

Si vous êtes amené à modifier le fichier de configuration comme par exemple pour ajouter un autre cluster, vous pouvez utiliser cette commande :

helm upgrade kubeapps bitnami/kubeapps –namespace kubeapps-system –values kubeapps-dex.yaml

 

Maintenant, il faut dire à Dex qu’il y a de nouveaux clusters créés

cat ~/tkg/tkg-extensions-v1.2.0+vmware.1//extensions/authentication/dex/vsphere/ldap/dex-data-values.yaml

# Partie à modifier extraite du fichier de configuration utilisait par Dex : ~/tkg/tkg-extensions-v1.2.0+vmware.1//extensions/authentication/dex/vsphere/ldap/dex-data-values.yaml
  #@overlay/replace
  staticClients:
  – id: usine-01 # nom de mon cluster de workload, attention à garder le même nom que dans le fichier de valeurs utilisé par Kubeapps
    redirectURIs:
    – https://172.20.7.16:30166/callback # Adress IP de l’API du cluster de workload et le port normalement utilisé par Gangway
    name: usine-01
    secret: a1094138692761b8bd653e7af36c3d57 # Secret normalement utilisait par Gangway à mettre même si Gangway n’est pas installé, dans ce cas mettez ce que vous voulez
    trustedPeers:
    – auth-tools # nom du cluster Kubeapps
  – id: usine-32
    redirectURIs:
    – https://172.20.7.17:30166/callback
    name: usine-32
    secret: a1094138692721b8bd653e7af36c3d57
    trustedPeers:
    – auth-tools
  – id: workload-01
    redirectURIs:
    – https://172.20.7.14:30166/callback
    name: workload-01
    secret: e36a415d615ccbf37b4c4b8316be9740
    trustedPeers:
    – auth-tools
  – id: workload-02
    redirectURIs:
    – https://172.20.7.15:30166/callback
    name: workload-02
    secret: 85507bc84d6d26899aa9bf1c87600f81
    trustedPeers:
    – auth-tools
  – id: auth-tools
    redirectURIs:
    – http://172.20.7.130/oauth2/callback # Adresse IP de ma VIP qui pointe vers Kubeapps
    name: auth-tools # nom du cluster où j’ai installé Kubeapps, j’ai choisi de l’installer sur un cluster à part
    secret: wPmp8+IrTxbGZbVF/yqPPeP4XZzw5mLt #clé renseignée dans le fichier Kubeapps « clientSecret »

Une fois modifier, il faut dire à Dex de prendre en compte la nouvelle configuration, à faire à partir du cluster de management où Dex est installé :

kubectl create secret generic dex-data-values –from-file ~/tkg/tkg-extensions-v1.2.0+vmware.1/extensions/authentication/dex/vsphere/ldap/dex-data-values.yaml -n tanzu-system-auth -o yaml –dry-run | kubectl replace -f-

Voilà, maintenant Kubeapps est prêt à être utilisé sur les 4 clusters configurés :

A partir d’un navigateur entrez l’adresse où le nom de la VIP kubeapps obtenue et cliquez sur “LOGIN VIA OIDC PROVIDER:”

 

Vous êtes ensuite redirigé vers la page d’authentification DEX, vous remarquerez que l’IP et le port sont ceux renseignés dans le fichier de configuration DEX, entrez votre compte et votre mot de passe :

Vous arrivez ensuite sur la page du cluster et namespace par défaut, l’écran est vide car il n’y a pas eu de déployement via HELM ou via un Operator sur le namespace et cluster défault :

Vous pouvez changer de cluster et de namespace en cliquant sur “Current Context” en haut à droite :