Pulumi par la pratique : Kubernetes
Grâce au premier article de la série, le fonctionnement interne de Pulumi n'a plus de secret pour nous. Il est désormais temps de s’intéresser à son utilisation au travers d’un premier exemple concret. Nous allons découvrir comment Pulumi peut à la fois faciliter le déploiement d’un cluster Kubernetes mais aussi le déploiement des ressources à l’intérieur d’un cluster. Nous serons donc dans une approche plutôt orientée infrastructure pure.
body .gist .highlight { background: #202020; } body .gist tr:nth-child(2n+1) { background: #202020; } body .gist tr:nth-child(2n) { background: #202020; } body .gist .gist-meta { display:none; } body .gist .highlight { background: #141414; } body .gist .blob-num, body .gist .blob-code-inner, body .gist .highlight, body .gist .pl-enm, body .gist .pl-ko, body .gist .pl-mo, body .gist .pl-mp1 .pl-sf, body .gist .pl-ms, body .gist .pl-pdc1, body .gist .pl-scp, body .gist .pl-smc, body .gist .pl-som, body .gist .pl-va, body .gist .pl-vpf, body .gist .pl-vpu, body .gist .pl-mdr { color: #aab1bf; } body .gist .pl-mb, body .gist .pl-pdb { font-weight: 700; } body .gist .pl-c, body .gist .pl-c span, body .gist .pl-pdc { color: #5b6270; font-style: italic; } body .gist .pl-sr .pl-cce { color: #56b5c2; font-weight: 400; } body .gist .pl-ef, body .gist .pl-en, body .gist .pl-enf, body .gist .pl-eoai, body .gist .pl-kos, body .gist .pl-mh .pl-pdh, body .gist .pl-mr { color: #61afef; } body .gist .pl-ens, body .gist .pl-vi { color: #be5046; } body .gist .pl-enti, body .gist .pl-mai .pl-sf, body .gist .pl-ml, body .gist .pl-sf, body .gist .pl-sr, body .gist .pl-sr .pl-sra, body .gist .pl-src, body .gist .pl-st, body .gist .pl-vo { color: #56b5c2; } body .gist .pl-eoi, body .gist .pl-mri, body .gist .pl-pds, body .gist .pl-pse .pl-s1, body .gist .pl-s, body .gist .pl-s1 { color: #97c279; } body .gist .pl-k, body .gist .pl-kolp, body .gist .pl-mc, body .gist .pl-pde { color: #c578dd; } body .gist .pl-mi, body .gist .pl-pdi { color: #c578dd; font-style: italic; } body .gist .pl-mp, body .gist .pl-stp { color: #818896; } body .gist .pl-mdh, body .gist .pl-mdi, body .gist .pl-mdr { font-weight: 400; } body .gist .pl-mdht, body .gist .pl-mi1 { color: #97c279; background: #020; } body .gist .pl-md, body .gist .pl-mdhf { color: #df6b75; background: #200; } body .gist .pl-corl { color: #df6b75; text-decoration: underline; } body .gist .pl-ib { background: #df6b75; } body .gist .pl-ii { background: #e0c184; color: #fff; } body .gist .pl-iu { background: #e05151; } body .gist .pl-ms1 { color: #aab1bf; background: #373b41; } body .gist .pl-c1, body .gist .pl-cn, body .gist .pl-e, body .gist .pl-eoa, body .gist .pl-eoac, body .gist .pl-eoac .pl-pde, body .gist .pl-kou, body .gist .pl-mm, body .gist .pl-mp .pl-s3, body .gist .pl-mq, body .gist .pl-s3, body .gist .pl-sok, body .gist .pl-sv, body .gist .pl-mb { color: #d19965; } body .gist .pl-enc, body .gist .pl-entc, body .gist .pl-pse .pl-s2, body .gist .pl-s2, body .gist .pl-sc, body .gist .pl-smp, body .gist .pl-sr .pl-sre, body .gist .pl-stj, body .gist .pl-v, body .gist .pl-pdb { color: #e4bf7a; } body .gist .pl-ent, body .gist .pl-entl, body .gist .pl-entm, body .gist .pl-mh, body .gist .pl-pdv, body .gist .pl-smi, body .gist .pl-sol, body .gist .pl-mdh, body .gist .pl-mdi { color: #df6b75; }
L’outil Pulumi sera nécessaire pour déployer les exemples. Des instructions d’installation sont disponibles à cette adresse : https://pulumi.io/quickstart/install.html. L’ensemble des exemples de code est présent à cette adresse: https://github.com/Tirke/try-pulumi/tree/master/kubernetes
Les exemples de code fournis ne sont pas adaptés à une utilisation dans un environnement de production. La plupart des exemples utilisent des ressources cloud préconfigurées avec des valeurs raisonnables, mais toutefois éloignées des besoins réels d’un système en production.
Dans le monde des OPS
Dans cet exemple, nous allons découvrir comment déployer un cluster Kubernetes sur Amazon Elastic Container Service for Kubernetes (EKS) avec Pulumi. Nous déploierons ensuite NGINX sur le cluster pour démontrer certaines fonctionnalités de Pulumi.
Pour déployer le cluster EKS, nous utiliserons le package @pulumi/eks. Ce package contient le composant Cluster. Un composant en Pulumi est simplement un regroupement de plusieurs ressources cloud de plus bas niveau. Parfois le composant contient aussi une partie de logique permettant d’interagir avec ses ressources. Cette logique peut être exposée permettant ainsi d’obtenir des composants autoportants. Ces composants sont ensuite souvent packagés et partagés sur les gestionnaires de paquet (npm, pip, ...) classiques des langages. Ce workflow permet de favoriser la réutilisation et d’abstraire une partie des difficultés.
La première étape consiste à créer un VPC (Virtual Private Cloud) pour notre cluster. Le VPC est un service d’AWS permettant de gérer la partie réseau de notre cluster. L’opération est simplifiée grâce au package aws-infra qui est lui aussi un composant haut niveau de Pulumi.
Une fois que le VPC est déclaré dans le code, il devient possible de le référencer lors du paramétrage d’autres ressources. Cela tombe bien, car notre cluster EKS va avoir besoin de ce VPC.
Le code qui suit permet de déclarer un cluster EKS dans notre VPC. Le cluster contient deux instances EC2 de type t2.medium, une StorageClass sur AWS EBS avec des volumes de type gp2. Le flag deployDashboard indique aussi que le dashboard Kubernetes sera déployé automatiquement.
Finalement nous allons exporter la configuration du cluster afin de pouvoir plus tard facilement interagir avec le cluster grâce à kubectl.
Il est désormais possible de déployer le cluster simplement en utilisant la commande pulumi update et de confirmer le déploiement après l’étape de preview. Le déploiement d’un cluster EKS étant plutôt long (10-12 min) c’est le moment idéal pour prendre un petit café.
Le JSON correspondant au fichier kubeconfig propre à notre cluster est disponible dans notre stack après le déploiement. Il est possible de l’exporter pour pouvoir utiliser kubectl pour interagir directement avec notre cluster.
Nous pouvons maintenant vérifier l’état du cluster avec la commande kubectl get nodes.
Même si rien ne nous empêchait d’écrire le code pour déployer NGINX sur le cluster k8s dès le départ, j’ai décidé de le faire en deux temps pour démontrer la fonctionnalité de suivi en temps réel qu’apporte Pulumi.
La deuxième partie du programme permet donc de déployer NGINX tout en exposant une IP publique.
C’est le moment de faire à nouveau l’opération pulumi update. On constate rapidement que le déploiement nous fournit des informations sur le déploiement en temps réel. C’est un des véritables avantages de Pulumi par rapport à l’utilisation plus basique de kubectl create. Grâce à ce suivi, le feedback en cas de succès ou d’échec est bien plus rapide. Pulumi fournit aussi des diffs en JSON (vs en texte brut avec kubectl) pour chaque changement sur le code de déploiement, ce qui permet de les appréhender plus facilement.
Une fois le déploiement terminé on obtient l’adresse de notre service exposant le NGINX !
N’oubliez pas la commande pulumi destroy -y pour supprimer le cluster à la fin de vos expérimentations, la facture peut vite devenir un peu salée.
L’exemple est terminé, et il est facile de voir en quoi Pulumi amène un workflow plus agréable, moins fastidieux pour les développeurs. Il est possible de remplacer le YAML par un langage de programmation qui sera plus expressif. Nous avons pu déployer un cluster sur EKS avec un service Nginx en moins de 50 lignes de code ! La boucle de feedback est globalement plus rapide et il est très pratique de pouvoir profiter de l'écosystème massif des langages de programmation.
Pour aller plus loin sur l’utilisation de Pulumi avec Kubernetes, je recommande l’excellent article du blog de Pulumi : 11 Kubernetes Pulumi Pearls. On peut y découvrir des uses-cases plus avancés (envoy sidecars, helm charts, ...) avec certains exemples qui sont souvent plus complexes à exprimer avec les outils classiques. Le prochain article abordera la problématique du déploiement d’une architecture Serverless avec Pulumi.