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.

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 :

 

 

 

Webinar déployer Kubernetes à l’échelle sur tous les clouds

 

Mon collègue Erwan et moi-même avons animé un webinar en Français sur la gestion du cycle de vie des cluster Kubernetes.

Vous trouverez ci le lien : Vidéo gestion du cycle de vie des cluster Kubernetes

 Ci-dessous le découpage par thématique et par solution  :

    • De 0 à 23:00 Présentation générale des attentes autour de Kubernetes
    • De 23:00 à 34:35 Introduction à TKG (Tanzu Kubernetes Grid), runtime Kubernetes multi-cloud ainsi que la gestion de son cycle de vie
    • De 34:15 à 55:30 Démonstration (TKG)
    • De 55:30 à 1:03:35 Introduction à vSphere with Kubernetes (aka Projet Pacific), plate-forme pour fournir nativement des PODs Kubenetes et les services associés (réseaux, firewall, loadbalancer, stockage, …)
    • De 1:03:35 à 1:21:07 démonstration de vSphere with Kubernetes
    • De 1:21:07 à 1:26:01 Introduction à Tanzu Mission Control (TMC), solution de management unifiée de runtine kubernetes multi-cluster, multi-cloud et multi-vendors
    • De 1:26:01 à 1:36:00 Démonstration de TMC
    • De 1:36:00 à 1:42:06 Introduction et démonstration à Tanzu Service Mesh (TSM), solution de service réseau au niveau applicatif, multi-cluster, multi-cloud et multi-vendor
    • De 1:42:06 à 1:44:04 Présentation de Tanzu Observability (TO), solution de monitoring de l’infrastructure et des applications hébergées
    • De 1:44:04 à 1:50:37 Démonstration de TO
    • De 1:50:37 Conclusion

Une solution Kubernetes as a Service pour tous les Clouds

Kubernetes est l’orchestrateur de containers en vogue. Il est disponible sous différentes formes, à installer et à gérer soit même ou complètement géré par un tiers comme c’est le cas pour les solutions Google GKE, Microsoft AKS ou Amazon EKS.

Comme pour les anciennes applications qui étaient majoritairement monolithiques et difficile à faire évoluer, elles deviennent maintenant micro-services pour être plus agile dans leur cycle de vie. Les clusters Kubernetes “historiques” déjà en place ont une stratégie monolithique avec un gros cluster compliqué à déployer et à faire évoluer. De ce constat VMware a adopté une toute autre stratégie. Avoir une solution simple à déployer, simple à maintenir, simple à faire évoluer modulaire et ce sans être verrouillé à une plate-forme. De cette manière, il est possible d’avoir un cluster Kubernetes en 5 mn sur du OnPremise ou dans le cloud public. (Aujourd’hui sur vSphere et AWS, les autres plateformes telles qu’Azure ou GCP vont rapidement arriver).

Cette stratégie a été élaborée sous l’impulsion des équipes issues du rachat de la société Heptio en 2018. Heptio a été fondée par 2 des créateurs de Kubernetes et font toujours parti des effectifs de VMware. L’ADN d’Heptio était exclusivement basée sur Kubernetes, vendre du conseil, développer des outils open source, contribuer à des projets open source existants et dispenser gratuitement des formations en ligne. Cette ADN a été conservée et VMware est désormais le deuxième contributeur sur Kubernetes, juste derrière Google. Une partie de ces contributions figure ici : https://github.com/vmware-tanzu.

C’est avec cet esprit que la solution Tanzu Kubernetes Grid (TKG) est née, à base d’open source, elle est dotée du moteur Kubertenes upstream et du gestionnaire Cluster API pour gérer le cycle de vie. Les binaires sont vérifiés par VMware pour parer aux failles de sécurité et pour une meilleure stabilité afin d’être en mesure d’en assurer le support. Plutôt que d’avoir une grosse solution tout intégrée difficile à maintenir, TKG est modulaire, vous pouvez y ajouter les modules que vous voulez, qu’ils soient développés par un tiers ou ceux développés par VMware.

Modules intégrables non exhaustifs. (En gris projet où VMware était à l’origine ou est principal contributaire)

Le Life-cycle Manager Cluster API fait partie intégrante de TKG

En résumé, s’il y a une chose à retenir : TKG c’est du Kubernetes As a Service, modulaire et multi-cloud, basé sur des solutions Opensources upstream.

Bénéfice principal : Avoir une infrastructure de développement et d’hébergement de container aussi agile que les applications qui y vont être développées et hébergées !

 

je vais maintenant rentrer un peu dans la technique.


Comment TKG fonctionne ?

C’est vraiment très simple à installer et à utiliser et c’est assez bluffant.

A partir d’un point d’administration (Linux, Mac ou Windows) vous installez le binaire TKG CLI pour initialiser le cluster Kubernetes management de TKG, ça prend environ 10 minutes. Une fois initialiser, toujours via TKG CLI, vous créez des clusters Kubenetes TKG pour les worloads applicatifs, ça prend environ 5 minutes.

 

Ensuite, il est très simple de faire évoluer à chaud (à la baisse ou à la hausse) la taille des clusters kubernetes de workload, ça prend environ 2 minutes.

TKG intègre nativement la CSI (Container Storage Interface) pour pouvoir provisionner des PVC (Persistent Volume Claim) utiles aux PODs statefull. Ces volumes seront automatiquement fournis par l’infrastructure sur laquelle réside TKG.

 

J’ai testé TKG sur une palte-forme vSphere à partir de laquelle je fais des démonstrations à mes clients. J’ai mis ci-dessous les étapes à respecter.

Il faut télécharger à partir du site VMware, le binaire TKG CLI et deux images (OVA). L’une des images servira pour les serveurs Kubernetes (Control Plane et Workers) et l’autre pour le serveur de Load Balancer HA Proxy pour servir les Control Planes.

A partir d’un cluster vSphere 6.7U3 minimum, activez DRS, créez un Ressource Pool et un VM Folder, chargez les deux images OVA.

Une fois les deux OVA chargées, faire un snapshot (étape nécessaire pour pouvoir utiliser les Instant Clone) et les convertir en template.

C’est tout ce qu’il y a à faire coté vSphere.

A partir d’un point d’administration Windows, Linux ou Mac (Linux dans mon exemple), copier le binaire TKG CLI puis lancer la commande : tkg init –infrastructure=vsphere –ui et remplir les champs demandés comme dans l’exemple ci-dessous, cette étape peut aussi se faire en ligne de commande en configurant le fichier config.yaml à placer de préférence dans le répertoire $HOME/.tkg :

(Screenshots issues de la version beta que j’ai testée)

Choix de la plate-forme (vSphere et AWS pour la première version les autres suivront très vite)

 

Information de connexion à la plateforme

 

Type de plan de deploiement et localisation du cluster de management

 

CIDR du réseau Kubernetes et type d’OS pour les control plane et worker nodes

 

Récapitulatif des informations renseignées

 

Suivi du déploiement

 

Une fois le cluster de management déployé, vous pouvez créer des clusters de wokload via la commande ci-dessous :

$ tkg create cluster prod1 -p prod -w 5 (5 pour 5 workers)

En moins de 5mn vous avez un cluster à votre disposition, vous pouvez “scaler” à chaud en modifiant à la hausse ou à la baisse le nombre de control plane ou de worker via la commande ci-dessous :

$ tkg scale cluster prod1 -w 4 -c3 (-w pour les workers et -c pour le control plane)

TKG surveille les VMs Kubernetes, si une est amenée à s’arrêter, TKG va la redémarrer automatiquement.

Pour utiliser un cluster déployé, il faut utiliser la commande Kubernetes kubectl :

Lancer la commande sans changer de contexte :

$ kubectl <commande> –context <context-tkg>

Pour changer de context et lancer les commandes sans spécifier de contexte :

$ kubectl config get-contexts (pour connaitre le nom du contexte)

$ kubectl config use-context <context-tkg>

Pour effacer le cluster :

$ tkg delete cluster prod1

C’est vraiment très simple à utiliser.

 

Pour en savoir un peu plus, je vous invite à consulter les articles d’Alex et Mika, deux personnes avec qui j’ai plaisir à travailler quotidiennement :

Alex : https://hackmd.io/@ac09081979

Mika : https://myvmworld.fr/vmware-tanzu/

Déployer Kubeapps

Kubeapps est un projet Bitnami. Bitnami a été racheté par VMware en 2019 et fait partie maintenant de la gamme Tanzu et se nomme Tanzu Application Catalog. Kubeapps est un catalogue de déploiement et de management d’applications et de services. Il arrive déjà connecté à la marketplace bitnami et il est possible de synchroniser une registry type docker. https://bitnami.com/kubernetes/kubeapps

La documentation d’installation est assez bien faite, je n’ai trouvé de complexité, juste un peu de vigilance au niveau des rôles si vous êtes en production. Un utilisateur peut avoir un accès en lecture seul et/ou en lecture/écriture (nécessaire pour déployer des applications), le scope des droits peut être le cluster et/ou le namespace. L’utilisateur à la possibilité de créer des namespaces pour y déployer des applications. https://github.com/kubeapps/kubeapps

Installation via Helm (version 3 dans mon exemple)

$ helm repo add bitnami https://charts.bitnami.com/bitnami

$ kubectl create namespace kubeapps

(attention il y a deux tirets normalement, je ne sais pas pourquoi WordPress en affiche qu’un. Si vous faites un copié/collé, enlever le tiret et en mettre deux à la place)

$ helm install kubeapps –namespace kubeapps bitnami/kubeapps –set useHelm3=true –set frontend.service.type=LoadBalancer

 

Créer un compte et le rôle pourvoir accéder à Kubeapps et pour installer des applications, créer des namespace directement depuis l’interface. Récupérez le token pour se logger à l’interface

$ kubectl create -n default serviceaccount loeilduse

$ kubectl create clusterrolebinding loeilduse –clusterrole cluster-admin –serviceaccount=default:loeilduse

 

$ kubectl get -n default secret $(kubectl get -n default serviceaccount loeilduse -o jsonpath='{.secrets[].name}’) -o go-template='{{.data.token | base64decode}}’ && echo

Récupérer le token, il sera demandé lors de la connexion à Kubeapps via le navigateur (ci-dessous un exemple)

eyJhbGciOiJSUzI1NiIsImtpZCI6IkV5bEdwMDU2dkVqTld5dFJtR03RHNVSmhmd09rc1licnJFSm81Nm1EZ3MifQ.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJkZWZhdWx0Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9zZWNyZXQubmFtZSI6ImxvZWlsZHVzZS10b2tlbi1yOGJiZyIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZShY2NvdW50Lm5hbWUiOiJsb2VpbGR1c2UiLCJrdWJlcm5ldGVzLmlvL3NlcnZpY2VhY2NvdW50L3NlcnZpY2UtYWNjb3VudC51aWQiOiI5NTMwZjZmNy1jMzEzLTQ5MzctODY2ZS1mMDUwNzY0YmI0MDEiLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDpb2VpbGR1c2UifQ.kTZhrfFXrOS-S2a3x6oiyO6mqi7d62lrsmy-pTLpFX-XsjAK8NZQ95WaKqJ1gHkQfJa4ah-gvSQOVeI0y8-TueS24iAbrMfFwuocbHOJa6d9x9dfBSNGfxgW2DZaA22TokAVm_VT_DmFbV7uqsOSdFNRC6GnogoUmaO0P2-X1A8HHXuur04zRU5pH-8kNUrmIclIlpUPIaDlkRV1v94nZfn1S0RswG4wzTY1IeqQn4Nn5vh9XKfavp7l42vSWH7F0AHnkpTpY94GN8TNVoninPBkl5ktcF6PZJ7qbYlEK4wz5Y_cEgJFArGYn3kaihzZ aZsAH7a6scVsk7KcTuYRQ

Récupérer l’IP fournit par le service Load Balancer

$ Kubectl get svc -n kubeapps

 

 

Ouvrir la page web avec l’IP fourni par le load balancer et renseigner le token récupéré :

 

Si vous avez le message ci-dessous, revoyez la partie création user/droit décrite juste avant

 

Vous devriez avoir ces types d’écrans

 

Lorsque vous déployez des applications depuis le catalogue Kubeapps, n’oubliez pas de modifier le fichier yaml si vous voulez y accéder depuis l’extérieur de votre cluster Kubernetes. Ci-dessous, un exemple de déploiement de Dokuwiki pour qu’il soit accessible via un load balancer (voir tout en bas) :