Débutez avec Pulumi
Mise à jour :
Dans nos métiers, le provisionnement de l’infrastructure est devenue une partie essentielle du développement moderne. Les équipes de développement cherchent en permanence des moyens d’automatiser et de rationaliser la création, la configuration et la gestion de leurs ressources cloud. C’est là que l’infrastructure as code (IaC) entre en jeu et parmi les nombreux outils disponibles, Pulumi se distingue comme une solution puissante et polyvalente.
Qu’est-ce que Pulumi ?
Pulumi est bien plus qu’un simple outil d’infrastructure as code (IaC) ; il s’agit d’une plateforme complète qui vous permet de gérer votre infrastructure cloud à l’aide de langages de programmation familiers. Contrairement à de nombreux autres outils IaC, Pulumi n’est pas limité à un langage spécifique. Il prend en charge plusieurs langages populaires, notamment Python, TypeScript, Go, et bien d’autres. Cela signifie que vous pouvez écrire du code pour définir votre infrastructure en utilisant le langage que vous maîtrisez le mieux.
Pulumi vous offre également la possibilité de travailler avec de multiples fournisseurs de cloud, tels qu’Amazon Web Services (AWS), Microsoft Azure, Google Cloud Platform (GCP) et bien d’autres. Vous n’êtes donc pas lié à un fournisseur spécifique et pouvez déployer vos ressources sur la plateforme cloud qui correspond le mieux à vos besoins.
Concepts fondamentaux de Pulumi
Représentation déclarative
Pulumi adopte une approche déclarative pour la définition de l’infrastructure, ce qui signifie que vous spécifiez simplement l’état souhaité de votre infrastructure et Pulumi se charge de créer, mettre à jour ou supprimer les ressources pour atteindre cet état. Cette approche est plus intuitive que la programmation impérative, où vous devrez décrire les étapes pour atteindre l’état souhaité.
Stockage de l’état
Pulumi gère automatiquement l’état de votre infrastructure. Cela signifie qu’il garde une trace des ressources que vous avez créées, de leurs états actuels, et des dépendances entre elles. La gestion de l’état facilite la planification et l’exécution des mises à jour de votre infrastructure, tout en minimisant les risques d’incohérences.
Les Stacks
Un autre concept clé de Pulumi est celui des stacks. Les stacks vous permettent de gérer différents environnements, tels que ceux de développement, de pré-production et de production, en utilisant la même définition d’infrastructure.
Chaque stack a sa propre configuration, ce qui vous permet de déployer et de gérer votre infrastructure de manière cohérente, quelle que soit la phase l’environnement cible. Vous pouvez définir des variables spécifiques à chaque stack pour gérer les paramètres qui changent d’un environnement à l’autre.
La notion de plan et d’application des modifications
Avant d’appliquer des modifications à votre infrastructure, Pulumi génère un plan. Ce plan affiche les actions exactes que Pulumi va entreprendre pour mettre à jour votre infrastructure. Vous avez la possibilité de revoir le plan avant d’autoriser Pulumi à appliquer les modifications, ce qui vous permet de comprendre précisément ce qui va se passer.
Ce processus offre un niveau de sécurité supplémentaire, car il évite les modifications accidentelles ou non autorisées de votre infrastructure.
Gestion des dépendances entre les ressources
Lorsque vous définissez votre infrastructure en tant que code, il est courant d’avoir des dépendances entre différentes ressources. Par exemple, vous pourriez avoir besoin d’un serveur avant de créer une base de données qui lui est liée.
Pulumi gère automatiquement ces dépendances pour vous. Vous pouvez spécifier les dépendances entre les ressources dans votre code et Pulumi garantit que les ressources sont créées et mises à jour dans le bon ordre pour satisfaire ces dépendances.
Cela simplifie considérablement la gestion des infrastructures complexes, car vous n’avez pas à vous soucier de l’ordre d’exécution des opérations.
Installation de Pulumi
Pour commencer avec Pulumi, vous devrez installer l’outil sur votre système. L’installation est généralement simple et Pulumi est disponible pour les différentes plateformes, y compris Windows, macOS et Linux. Une fois installé, vous devrez configurer Pulumi pour qu’il utilise les informations d’authentification de votre fournisseur cloud.
Installation de Pulumi sur Linux
Dans une fenêtre de Terminal tapez la commande suivante :
curl -fsSL https://get.pulumi.com | sh
Installation de Pulumi sur MacOS
Dans une fenêtre Terminal tapez la commande suivante :
brew install pulumi/tap/pulumi
Installation de Pulumi sur Windows
Dans une fenêtre Powershell tapez la commande suivante :
winget install pulumi
Vérification de l’installation de Pulumi
Dans une fenêtre terminal tapez la commande suivante :
pulumi versionv3.92.0
Configuration de Pulumi
Le processus de configuration initiale peut varier en fonction de votre fournisseur de cloud, mais Pulumi fournit généralement des guides détaillés pour chacun d’eux. Assurez-vous de suivre ces guides pour configurer correctement votre environnement de développement. Exemple avec AWS ↗
Ecrire son premier code d’infrastructure avec Pulumi
Maintenant que nous avons une meilleure compréhension de ce qu’est Pulumi, plongeons plus profondément dans la manière dont vous pouvez définir votre infrastructure en tant que code avec cet outil puissant.
Utilisation du backend local
Pour éviter de créer un state dans le cloud de pulumi, je fais le choix d’utiliser le backend local :
pulumi login --localLogged in to internal as bob (file://~)
Création de notre première VM
Pour mieux comprendre comment Pulumi fonctionne, commençons par créer un nouveau projet :
pulumi newPlease choose a template (28/221 shown): aws-python A minimal AWS Python Pulumi programThis command will walk you through creating a new Pulumi project.
Enter a value or leave blank to accept the (default), and press <ENTER>.Press ^C at any time to quit.
project name (project): pulumi-aws-pythonproject description (A minimal AWS Python Pulumi program):Created project 'pulumi-aws-python'
stack name (dev):Created stack 'dev'Enter your passphrase to protect config/secrets:Re-enter your passphrase to confirm:
aws:region: The AWS region to deploy into (us-east-1): eu-west-2Saved config
Installing dependencies...
Creating virtual environment...Finished creating virtual environmentUpdating pip, setuptools, and wheel in virtual environment...Requirement already satisfied: pip in ./venv/lib/python3.10/site-packages (22.0.2)Collecting pip Using cached pip-23.3.1-py3-none-any.whl (2.1 MB)Requirement already satisfied: setuptools in ./venv/lib/python3.10/site-packages (59.6.0)Collecting setuptools Using cached setuptools-68.2.2-py3-none-any.whl (807 kB)Collecting wheel Using cached wheel-0.41.3-py3-none-any.whl (65 kB)Installing collected packages: wheel, setuptools, pip Attempting uninstall: setuptools Found existing installation: setuptools 59.6.0 Uninstalling setuptools-59.6.0: Successfully uninstalled setuptools-59.6.0 Attempting uninstall: pip Found existing installation: pip 22.0.2 Uninstalling pip-22.0.2: Successfully uninstalled pip-22.0.2Successfully installed pip-23.3.1 setuptools-68.2.2 wheel-0.41.3Finished updatingInstalling dependencies in virtual environment...Collecting pulumi<4.0.0,>=3.0.0 (from -r requirements.txt (line 1)) Using cached pulumi-3.94.2-py3-none-any.whl.metadata (11 kB)Collecting pulumi-aws<7.0.0,>=6.0.2 (from -r requirements.txt (line 2)) Downloading pulumi_aws-6.9.0-py3-none-any.whl.metadata (9.0 kB)Collecting protobuf~=4.21 (from pulumi<4.0.0,>=3.0.0->-r requirements.txt (line 1)) Using cached protobuf-4.25.1-cp37-abi3-manylinux2014_x86_64.whl.metadata (541 bytes)Collecting grpcio==1.56.2 (from pulumi<4.0.0,>=3.0.0->-r requirements.txt (line 1)) Using cached grpcio-1.56.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (4.0 kB)Collecting dill~=0.3 (from pulumi<4.0.0,>=3.0.0->-r requirements.txt (line 1)) Using cached dill-0.3.7-py3-none-any.whl.metadata (9.9 kB)Collecting six~=1.12 (from pulumi<4.0.0,>=3.0.0->-r requirements.txt (line 1)) Using cached six-1.16.0-py2.py3-none-any.whl (11 kB)Collecting semver~=2.13 (from pulumi<4.0.0,>=3.0.0->-r requirements.txt (line 1)) Using cached semver-2.13.0-py2.py3-none-any.whl (12 kB)Collecting pyyaml~=6.0 (from pulumi<4.0.0,>=3.0.0->-r requirements.txt (line 1)) Using cached PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (2.1 kB)Collecting parver>=0.2.1 (from pulumi-aws<7.0.0,>=6.0.2->-r requirements.txt (line 2)) Using cached parver-0.5-py3-none-any.whl.metadata (2.7 kB)Collecting arpeggio>=1.7 (from parver>=0.2.1->pulumi-aws<7.0.0,>=6.0.2->-r requirements.txt (line 2)) Using cached Arpeggio-2.0.2-py2.py3-none-any.whl.metadata (2.4 kB)Collecting attrs>=19.2 (from parver>=0.2.1->pulumi-aws<7.0.0,>=6.0.2->-r requirements.txt (line 2)) Using cached attrs-23.1.0-py3-none-any.whl (61 kB)Using cached pulumi-3.94.2-py3-none-any.whl (191 kB)Using cached grpcio-1.56.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.2 MB)Downloading pulumi_aws-6.9.0-py3-none-any.whl (7.9 MB) ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 7.9/7.9 MB 46.9 MB/s eta 0:00:00Using cached dill-0.3.7-py3-none-any.whl (115 kB)Using cached parver-0.5-py3-none-any.whl (15 kB)Using cached protobuf-4.25.1-cp37-abi3-manylinux2014_x86_64.whl (294 kB)Using cached PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (705 kB)Using cached Arpeggio-2.0.2-py2.py3-none-any.whl (55 kB)Installing collected packages: arpeggio, six, semver, pyyaml, protobuf, grpcio, dill, attrs, pulumi, parver, pulumi-awsSuccessfully installed arpeggio-2.0.2 attrs-23.1.0 dill-0.3.7 grpcio-1.56.2 parver-0.5 protobuf-4.25.1 pulumi-3.94.2 pulumi-aws-6.9.0 pyyaml-6.0.1 semver-2.13.0 six-1.16.0Finished installing dependenciesFinished installing dependencies
Your new project is ready to go!
To perform an initial deployment, run `pulumi up`
Pulumi nous propose de choisr parmi des templates existants. J’ai choisi
Aws-Python. Pulumi créé le nécessaire pour notre premier projet, avec un
environnement virtuel. Il nous invite à lancer la commande pulumi up
. Soyons
fou :
pulumi upEnter your passphrase to unlock config/secrets (set PULUMI_CONFIG_PASSPHRASE or PULUMI_CONFIG_PASSPHRASE_FILE to remember):Enter your passphrase to unlock config/secretsPreviewing update (dev):Downloading plugin: 176.66 MiB / 176.66 MiB [=======================] 100.00% 3s [resource plugin aws-6.9.0] installing Type Name Plan + pulumi:pulumi:Stack pulumi-aws-python-dev create + └─ aws:s3:Bucket my-bucket create
Outputs: bucket_name: output<string>
Resources: + 2 to create
Do you want to perform this update? [Use arrows to move, type to filter] yes> no details
Mince, il propose de créer un premier bucket ! Regardons en détail le contenu du dossier :
ls -alrttotal 36drwxrwxr-x 11 bob bob 4096 nov. 20 10:20 ..-rw-r--r-- 1 bob bob 46 nov. 20 11:06 requirements.txt-rw-r--r-- 1 bob bob 129 nov. 20 11:06 Pulumi.yaml-rw-r--r-- 1 bob bob 219 nov. 20 11:06 __main__.py-rw-r--r-- 1 bob bob 12 nov. 20 11:06 .gitignore-rw-r--r-- 1 bob bob 117 nov. 20 11:07 Pulumi.dev.yamldrwxrwxr-x 5 bob bob 4096 nov. 20 11:07 venvdrwxrwxr-x 2 bob bob 4096 nov. 20 11:10 __pycache__drwxrwxr-x 4 bob bob 4096 nov. 20 11:10 .
On y retrouve donc :
Pulumi.dev.yaml
: contient la configuration de la pile que vous initialisezPulumi.yaml
: Définit le projet- main.py : contient un exemple de programme avec les importations Pulumi et définit les ressources du programme.
requirements.txt
: contient les exigences de la version Pulumi- un dossier
venv
contenant un environnement virtuel Python
Le contenu du fichier main.py
:
"""An AWS Python Pulumi program"""
import pulumifrom pulumi_aws import s3
# Create an AWS resource (S3 Bucket)bucket = s3.Bucket('my-bucket')
# Export the name of the bucketpulumi.export('bucket_name', bucket.id)
Dans cet exemple, nous importons les modules nécessaires de Pulumi et d’AWS,
puis nous créons un objet Bucket
en lui donnant un nom (“my-bucket”). Pulumi
se charge ensuite de créer le bucket S3 correspondant dans votre compte AWS
lorsque vous exécutez ce code.
On relance le provisionnement en répondant yes
cette fois :
pulumi up 12:03:17Enter your passphrase to unlock config/secrets (set PULUMI_CONFIG_PASSPHRASE or PULUMI_CONFIG_PASSPHRASE_FILE to remember):Enter your passphrase to unlock config/secretsPreviewing update (dev): Type Name Plan pulumi:pulumi:Stack pulumi-aws-python-dev + └─ aws:s3:Bucket my-bucket create
Outputs: + bucket_name: output<string>
Resources: + 1 to create 1 unchanged
Do you want to perform this update? yesUpdating (dev): Type Name Status pulumi:pulumi:Stack pulumi-aws-python-dev + └─ aws:s3:Bucket my-bucket created (0.91s)
Outputs: + bucket_name: "my-bucket-5c4d53d"
Resources: + 1 created 1 unchanged
Duration: 2s
Pulumi affiche en sortie le nom du bucket, Vérifions avec la CLI d’AWS si le bucket a bien été créé avec ce nom :
aws s3 ls2023-11-20 12:03:28 my-bucket-5c4d53d
Je cherche la documentation sur ce provider AWS ↗. Chaque objet est largement détaillé avec pas mal d’exemples.
Je vois que je peux par exemple ajouter des tags. Je modifie le code.
"""An AWS Python Pulumi program"""
import pulumifrom pulumi_aws import s3
# Create an AWS resource (S3 Bucket)bucket = s3.Bucket( "my-bucket", tags={ "Environment": "Dev", "Name": "My bucket", },)
# Export the name of the bucketpulumi.export("bucket_name", bucket.id)
Avant de modifier je vérifie les tags actuels :
aws s3api get-bucket-tagging --bucket my-bucket-5c4d53d
An error occurred (NoSuchTagSet) when calling the GetBucketTagging operation: The TagSet does not exist
Aucun tag. Je lance la mise à jour :
pulumi upEnter your passphrase to unlock config/secrets (set PULUMI_CONFIG_PASSPHRASE or PULUMI_CONFIG_PASSPHRASE_FILE to remember):Enter your passphrase to unlock config/secretsPreviewing update (dev): Type Name Plan Info pulumi:pulumi:Stack pulumi-aws-python-dev ~ └─ aws:s3:Bucket my-bucket update [diff: +tags,tagsAll]
Resources: ~ 1 to update 1 unchanged
Do you want to perform this update? yesUpdating (dev): Type Name Status Info pulumi:pulumi:Stack pulumi-aws-python-dev ~ └─ aws:s3:Bucket my-bucket updated (0.65s) [diff: +tags,tagsAll]
Outputs: bucket_name: "my-bucket-5c4d53d"
Resources: ~ 1 updated 1 unchanged
Duration: 2s
On voit bien la différence avec diff: tags...
Vérifions les tags maintenant :
aws s3api get-bucket-tagging --bucket my-bucket-5c4d53d{ "TagSet": [ { "Key": "Environment", "Value": "Dev" }, { "Key": "Name", "Value": "My bucket" } ]}
Nickel. Chrome. On en reste là. Détruisons le tout.
pulumi destroyEnter your passphrase to unlock config/secrets (set PULUMI_CONFIG_PASSPHRASE or PULUMI_CONFIG_PASSPHRASE_FILE to remember):Enter your passphrase to unlock config/secretsPreviewing destroy (dev): Type Name Plan - pulumi:pulumi:Stack pulumi-aws-python-dev delete - └─ aws:s3:Bucket my-bucket delete
Outputs: - bucket_name: "my-bucket-5c4d53d"
Resources: - 2 to delete
Do you want to perform this destroy? yesDestroying (dev): Type Name Status - pulumi:pulumi:Stack pulumi-aws-python-dev deleted (0.00s) - └─ aws:s3:Bucket my-bucket deleted (0.42s)
Outputs: - bucket_name: "my-bucket-5c4d53d"
Resources: - 2 deleted
Duration: 1s
The resources in the stack have been deleted, but the history and configuration associated with the stack are still maintained.If you want to remove the stack completely, run `pulumi stack rm dev`.
Gestion des secrets
La sécurité et la gestion des secrets sont des aspects critiques de la gestion de l’infrastructure.
Pulumi reconnaît l’importance de la sécurité et offre des fonctionnalités intégrées pour gérer les informations sensibles telles que les mots de passe, les clés d’API, les jetons d’accès et d’autres données confidentielles.
Stockage sécurisé des secrets
Pulumi propose un coffre-fort de sécurité intégré qui permet de stocker de manière sécurisée les secrets, les clés API et autres données sensibles. Ces informations sont chiffrées au repos et lors de leur transmission.
Vous pouvez utiliser des variables secrètes dans votre code Pulumi pour accéder aux informations sensibles stockées dans le coffre-fort de sécurité. Ces variables ne sont jamais exposées en clair dans votre code ou dans les fichiers de configuration, ce qui renforce la sécurité de votre infrastructure.
Pulumi utilise des mécanismes de chiffrement solides pour garantir que vos secrets sont stockés en toute sécurité. Cela inclut le chiffrement des données en transit et au repos, ainsi que la gestion des clés de chiffrement.
Gestion des configurations spécifiques à chaque environnement
Outre la gestion des secrets, Pulumi vous permet de gérer des configurations spécifiques à chaque environnement. Cela signifie que vous pouvez personnaliser les paramètres de votre infrastructure en fonction de l’environnement dans lequel vous déploierez votre code.
Par exemple, vous pouvez avoir des configurations différentes pour le développement, la pré-production et la production. Pulumi vous permet de gérer ces configurations de manière centralisée et de les utiliser dans votre code.
Exemple d’utilisation de secrets et de configurations
Voici un exemple simple de la manière dont vous pouvez utiliser des secrets et des configurations dans votre code Pulumi :
On commence par créer un secret avec la CLI :
pulumi config set --secret my-secret-value testEnter your passphrase to unlock config/secrets (set PULUMI_CONFIG_PASSPHRASE or PULUMI_CONFIG_PASSPHRASE_FILE to remember):
Utilisons le dans notre exemple précédent pour créer un Objet avec son contenu :
import pulumifrom pulumi_aws import s3
config = pulumi.Config()
superSecret = config.require_secret("my-secret-value")
# Create a private bucketbucket = s3.Bucket('my-bucket', acl="private")
# Create an object from the secret valuebucketObject = s3.BucketObject("secret", bucket=bucket.id, key="secret", content=superSecret)
Dans cet exemple, nous utilisons pulumi.Config()
pour accéder aux
configurations spécifiques à l’environnement. Nous utilisons ensuite la fonction
config.require_secret
pour récuperer le secret. Ces éléments sont
ensuite utilisés pour créer un bucket S3 contenant un objet.
On lance la création :
pulumi upEnter your passphrase to unlock config/secrets (set PULUMI_CONFIG_PASSPHRASE or PULUMI_CONFIG_PASSPHRASE_FILE to remember):Enter your passphrase to unlock config/secretsPreviewing update (dev): Type Name Plan + pulumi:pulumi:Stack pulumi-aws-python-dev create + ├─ aws:s3:Bucket my-bucket create + └─ aws:s3:BucketObject secret create
Resources: + 3 to create
Do you want to perform this update? yesUpdating (dev): Type Name Status + pulumi:pulumi:Stack pulumi-aws-python-dev created (0.01s) + ├─ aws:s3:Bucket my-bucket created (1s) + └─ aws:s3:BucketObject secret created (0.14s)
Resources: + 3 created
Duration: 3s
On copie le fichier pour en voir le contenu :
aws s3 cp s3://my-bucket-d0d1147/secret .download: s3://my-bucket-d0d1147/secret to ./secret
cat secrettest
C’est la bonne valeur. L’exemple n’est pas génial mais montre que Pulumi gère parfaitement les secrets.
Conclusion
J’espére que cette introduction sur Pulumi vous a aidé à débuter avec Pulumi. N’oubliez pas que Pulumi évolue constamment, alors tenez-vous au courant avec les dernières fonctionnalités et les meilleures pratiques pour en tirer le meilleur parti.
Plus d’infos
- Site Officiel : Pulumi ↗
- Le projet ↗ : Ce site propose le code source de Pulumi, ainsi que des exemples d’utilisation et des contributions de la communauté.