Infrastructure as Code avec Pulumi : l’infra dans le monde des développeurs

**L’infrastructure cloud **n’est plus un simple décor autour de nos applications. Elle est devenue un vrai morceau du produit. Quand on manipule des Functions, du Service Bus, du Cosmos DB, du Storage, de l’APIM ou n’importe quelle brique Azure, on se rend rapidement compte que l’infra fait partie du métier, qu’elle influence les choix techniques, la sécurité, la performance et même le ROI.Dans mon quotidien de consultant Azure et développeur .NET , j’ai trop souvent vu des équipes coincées entre des Templates ARM interminables qui se complexifie au fil du temps, ou du Terraform devenu rigide dès qu’on veut factoriser, "refactorer" ou tester sérieusement.**Pulumi **prend le problème à contre-pied
et si on écrivait l’infrastructure comme on écrit une application ?## Pulumi : l’IaC qui parle enfin notre languePulumi fait un choix radical : laisser tomber les DSL spécialisés et revenir à des langages de programmation classiques.
Tu écris ton infra en C#, TypeScript, Python ou Go.Et évidemment, dès que tu reviens dans ton environnement .NET, tout prend une autre dimension.
Tu retrouves le confort du typage fort, **l’IntelliSense **qui t’accompagne, la **compilation **qui te protège des erreurs, le **refactoring **naturel, les **tests unitaires **qui sécurisent ton travail, la **modularisation **qui va de soi, et toute la puissance de ton IDE.En somme, tu restes dans ton écosystème habituel.
L’infrastructure devient simplement une partie du code, intégrée à ton quotidien de développeur. Pas plus compliquée, pas plus exotique. Une extension logique de ta solution.## Provisionner une Function App Azure en C#Avec Pulumi, créer une Function App ressemble davantage à coder une fonctionnalité qu’à assembler des blocs déclaratifs.```
using Pulumi;
using Pulumi.AzureNative.Resources;
using Pulumi.AzureNative.Web;
using Pulumi.AzureNative.Storage;
class MyStack : Stack { public MyStack() { var rg = new ResourceGroup("rg-demo");
var storage = new StorageAccount("saPulumiDemo", new StorageAccountArgs
{
ResourceGroupName = rg.Name,
Sku = new Pulumi.AzureNative.Storage.Inputs.SkuArgs
{
Name = Pulumi.AzureNative.Storage.SkuName.Standard_LRS
},
Kind = Pulumi.AzureNative.Storage.Kind.StorageV2
});
var plan = new AppServicePlan("planDemo", new AppServicePlanArgs
{
ResourceGroupName = rg.Name,
Kind = "FunctionApp",
Sku = new Pulumi.AzureNative.Web.Inputs.SkuDescriptionArgs
{
Tier = "Dynamic",
Name = "Y1"
}
});
var function = new WebApp("fa-demo", new WebAppArgs
{
ResourceGroupName = rg.Name,
ServerFarmId = plan.Id,
SiteConfig = new Pulumi.AzureNative.Web.Inputs.SiteConfigArgs
{
AppSettings =
{
new Pulumi.AzureNative.Web.Inputs.NameValuePairArgs {
Name = "FUNCTIONS_EXTENSION_VERSION",
Value = "~4"
},
new Pulumi.AzureNative.Web.Inputs.NameValuePairArgs {
Name = "AzureWebJobsStorage",
Value = storage.PrimaryEndpoints.Apply(e => e.Blob)
}
}
}
});
this.Endpoint = function.DefaultHostName;
}
[Output]
public Output<string> Endpoint { get; set; }
}
Tu installes **Pulumi**, tu te connectes à ton backend d’état (Azure Blob recommandé), puis tu lances :```
pulumi preview
pulumi up --yes
```Le `preview` est un allié puissant :
il montre **exactement** ce que **Pulumi va faire** — créations, modifications, suppressions — ***avant la moindre action sur ton cloud***.Tu maîtrises totalement l’impact du changement.## Quand Pulumi devient indispensableÀ partir du moment où ton infrastructure cesse d’être un simple bloc unique pour devenir un véritable écosystème — avec des API .NET qui se répondent, une gestion centralisée via APIM, des Functions qui orchestrent les flux, un Service Bus qui véhicule les messages, des bases Cosmos DB, du stockage distribué, de l’observabilité AppInsights et plusieurs environnements qui doivent rester alignés — la complexité explose naturellement.C’est précisément là que Pulumi agit comme un catalyseur de cohérence.
Tu peux aborder ton infrastructure comme une architecture logicielle à part entière : façonner tes abstractions, factoriser les schémas récurrents, imposer une discipline commune, vérifier ton travail avec des tests, et maintenir le tout sans t’épuiser à recoller les morceaux à la main.Pulumi transforme un ensemble hétérogène en un système maîtrisable. Un cadre où tu reprends le contrôle.## Du code au cloud, structurer Pulumi comme une architecture logicielle[](https://xavierraboteur.wordpress.com/wp-content/uploads/2025/11/image-11.png)Quand ton infrastructure commence à ressembler à un vrai système, Pulumi te permet d’aller beaucoup plus loin qu’une simple description de ressources.### Modules métierTu peux découper ton infra en vraies briques :- Module `Messaging` (ServiceBus, topics, règles…)
- Module `Backend` (APIs, Functions, App Service…)
- Module `Data` (Cosmos DB, SQL, Storage…)
- Module `Security` (Key Vault, RBAC, identités managées…)
- Module `Monitoring` (dashboards, logs, alerting…)Ta stack devient claire, lisible, maintenable.### Multi-environnements sans duplication**Un module** = une logique.
**Une stack** = une configuration (dev, prod, staging).
Pas besoin de dupliquer ce qui existe déjà.### Pulumi PolicyTu peux imposer des règles globales :
“aucune ressource sans tag compliance”, “diagnostics activés sur toutes les bases”.La qualité est standardisée.### Tests d’infrastructureTu peux écrire des tests unitaires en C# qui valident ta configuration.
Oui, l’infrastructure devient testable.## Anti-Pattern Iac - quelques erreurs à éviterDans l’**Infrastructure as Code**, les dérapages arrivent vite, souvent parce que l’on reproduit des réflexes issus d’outils plus anciens. L’un des pièges les plus fréquents consiste à vouloir ***tout regrouper dans une seule stack***. Sur le moment, cela paraît pratique ; avec le temps, on se retrouve ***prisonnier d’un monolithe où la moindre modification déclenche une réaction en chaîne***. À l’inverse, ***lorsque l’infrastructure est découpée par domaines, chaque partie respire et évolue à son propre rythme***.Un autre travers classique vient du ***copier-coller***. On duplique une ressource, on change un nom, et tout semble tenir… jusqu’au jour où ce patchwork devient impossible à suivre. ***Extraire des abstractions claires, créer des modules ou des fabriques***, c’est souvent ce qui ***permet à l’ensemble de rester lisible et cohérent***.***La gestion des environnements*** peut également basculer dans la complexité si l’on commence à parsemer le code de conditions du type *si on est en prod alors…*. On croit gérer un détail, mais on construit un labyrinthe dans lequel plus personne ne se retrouve. Les ***fichiers de configuration dédiés à chaque stack*** évitent ce piège et ***clarifient immédiatement l’intention***.Un écueil plus subtil consiste à ***déclarer son infrastructure sans jamais la tester***. Pourtant, du code non testé finit inévitablement par rompre au moment le moins opportun. ***Pulumi offre les outils pour vérifier ses déploiements***, et s’en priver revient à avancer sans filet.Il arrive aussi que l***’infrastructure se mélange à la logique métier***, parfois directement dans le code applicatif. C’est le meilleur moyen de ***brouiller les responsabilités***. Garder ***un projet Pulumi séparé***, clairement identifié dans la solution, permet à ***chaque couche de jouer son rôle***.Enfin, certaines équipes continuent d’utiliser un*** backend local pour stocker l’état***. C’est une solution tentante en solo, mais catastrophique dès qu’on travaille à plusieurs. ***Un backend partagé — qu’il s’agisse d’Azure Blob ou du service managé de Pulumi*** — apporte la stabilité nécessaire. Et tant qu’à fiabiliser le déploiement, autant activer ***l’observabilité*** dès la création des ressources : une infrastructure silencieuse est souvent celle qui surprendra le plus.Au fond, toutes ces erreurs ont un point commun : elles naissent de compromis rapides. Les éviter, c’est s’offrir une **IaC **plus claire, plus robuste, et surtout plus sereine au quotidien.## GitHub ActionsPour intégrer **Pulumi **dans un flux **CI/CD GitHub**, on cherche quelque chose de simple, lisible, mais surtout prévisible.
L’objectif n’est pas de construire une usine à gaz : pose un cadre propre pour déployer ton infrastructure automatiquement **à chaque push sur `main`**, ou à **chaque validation de Pull Request** si tu veux l’utiliser en “plan-only”.Le pipeline ci-dessous installe **.NET**, installe le **CLI Pulumi**, se connecte au backend d’état (dans cet exemple un **container Azure Blob**), puis exécute le déploiement de la stack choisie.L’idée, c’est que l’**IaC** soit traitée comme ton code applicatif : ***versionnée, revue, testée, appliquée par une pipeline, jamais manuellement***.
Une stack **Pulumi **devient alors un composant vivant du projet, raccordé à son cycle de livraison.```
name: Deploy Infrastructure
on:
push:
branches: ["main"]
workflow_dispatch:
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Setup .NET SDK
uses: actions/setup-dotnet@v3
with:
dotnet-version: "8.0.x"
- name: Install Pulumi CLI
uses: pulumi/actions-install-pulumi-cli@v2
- name: Azure Login via Service Principal
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
- name: Pulumi Login (Azure Blob backend)
run: pulumi login "azblob://${{ secrets.PULUMI_STATE_CONTAINER }}"
- name: Select Stack
run: pulumi stack select ${{ secrets.PULUMI_STACK }}
- name: Install Infra Dependencies
run: dotnet restore ./src/Infra/Infra.csproj
- name: Preview Infrastructure Changes
run: pulumi preview --stack ${{ secrets.PULUMI_STACK }}
- name: Deploy Infrastructure
run: pulumi up --yes --stack ${{ secrets.PULUMI_STACK }}
```**Secrets à ajouter dans GitHub
**
*Dans Settings → Secrets → Actions :*
**AZURE\_CREDENTIALS **→ JSON du service principal (Azure AD)
**PULUMI\_STACK **→ nom de la stack (ex. dev, prod)
**PULUMI\_STATE\_CONTAINER** → URL du container d’état Pulumi (ex. pulumi-state)## Pulumi change profondément notre façon de travailler l’infrastructureOn sort enfin d’une logique de templates opaques, de copier-coller et de pipelines fragiles pour revenir à quelque chose de plus sain : **du vrai code**, versionné, testé, relu, pensé comme un composant à part entière du produit.Dans un écosystème Azure riche et vivant, cette approche fait la différence.
On construit des plateformes cohérentes, on capitalise sur les patterns, on partage les bonnes pratiques, et surtout on développe une infra qui respire au même rythme que l’application elle-même.Et quand on est développeur .NET, l’expérience est encore plus naturelle, ***Pulumi*** s’intègre parfaitement dans notre environnement, nos outils, notre façon d’aborder les projets.
Le fossé entre “dev” et “infra” se referme, et l’équipe gagne une vision plus globale du système.Si tu veux partir sur de bonnes bases, j’ai préparé un squelette complet : structure propre, modules, stacks, tests, et pipeline GitHub Actions. Tu peux le télécharger ici :**Télécharger le sample Pulumi C# sur GitHub**
**https://github.com/xraboteu/pulumi-csharp-sample**