Le langage Bicep
Introduction
Créer des ressources depuis le portail Azure permet de découvrir les services et de configurer rapidement un environnement. Cependant, lorsque plusieurs environnements doivent être maintenus, reproduire manuellement les mêmes configurations devient fastidieux et augmente le risque d’erreur.
L’Infrastructure as Code (IaC), consiste à décrire une infrastructure dans des fichiers que l’on peut versionner, relire et utiliser pour automatiser les déploiements. Dans Microsoft Azure, le langage Bicep est un conçu pour dans ce but.
Présentation
Bicep est un langage déclaratif permettant de décrire les ressources Azure à déployer et leur configuration. Ses fichiers portent l’extension .bicep.
Avec une approche déclarative, nous décrivons le résultat attendu : un compte de stockage, un réseau virtuel ou une application Web avec certaines propriétés. Azure Resource Manager prend ensuite en charge leur déploiement et l’ordonnancement des dépendances.
Bicep sert à décrire l’infrastructure qui accueille une application ; le code métier reste écrit dans un langage comme C#.
Bicep et Azure Resource Manager
Azure Resource Manager (ARM) est le service de gestion et de déploiement des ressources Azure.
Les modèles ARM peuvent être écrits en JSON. Cependant, le langage Bicep propose une syntaxe plus concise pour exprimer ces mêmes descriptions. Lors du déploiement, le fichier Bicep est compilé en modèle ARM JSON, puis traité par ARM.
Les rôles sont donc complémentaires :
- Bicep permet de rédiger la description de l’infrastructure.
- Le modèle ARM JSON constitue le résultat de la compilation.
- Azure Resource Manager exécute le déploiement.
Les principaux éléments du langage
Un fichier Bicep peut contenir plusieurs types de déclarations :
| Élément | Rôle |
|---|---|
param |
Définir une valeur fournie au déploiement, éventuellement avec une valeur par défaut. |
var |
Définir une valeur calculée ou réutilisée dans le fichier. |
resource |
Déclarer une ressource Azure. |
module |
Utiliser un autre fichier Bicep pour déployer un ensemble de ressources. |
output |
Retourner une information après le déploiement, comme l’identifiant d’une ressource. |
Bicep dispose également de conditions et de boucles pour adapter les ressources déployées aux besoins de l’environnement.
Exemple : déployer un compte de stockage
Le fichier suivant, nommé main.bicep, décrit un compte de stockage Azure :
targetScope = 'resourceGroup'
@description('Région dans laquelle déployer le compte de stockage.')
param location string = resourceGroup().location
@description('Environnement de déploiement.')
@allowed([
'dev'
'test'
'prod'
])
param environment string = 'dev'
var storageAccountName = 'st${environment}${uniqueString(resourceGroup().id)}'
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-05-01' = {
name: storageAccountName
location: location
kind: 'StorageV2'
sku: {
name: 'Standard_LRS'
}
tags: {
environment: environment
}
properties: {
supportsHttpsTrafficOnly: true
minimumTlsVersion: 'TLS1_2'
allowBlobPublicAccess: false
}
}
output storageAccountId string = storageAccount.id
output blobEndpoint string = storageAccount.properties.primaryEndpoints.blob
Les paramètres et les variables
Le paramètre location utilise par défaut la région du groupe de ressources. Il reste possible de fournir une autre valeur au déploiement.
Le paramètre environment accepte uniquement les valeurs dev, test et prod, grâce au décorateur @allowed.
La variable storageAccountName construit un nom à partir de l’environnement et d’un suffixe déterministe calculé depuis l’identifiant du groupe de ressources. Ce suffixe aide à respecter l’exigence d’unicité mondiale du nom d’un compte de stockage.
La ressource
Dans cette déclaration :
storageAccountest le nom symbolique utilisé dans le fichier.Microsoft.Storage/storageAccountsdésigne le type de ressource Azure.2023-05-01désigne la version de l’API utilisée pour décrire et déployer cette ressource.
Le nom symbolique se distingue du nom réel de la ressource, défini dans la propriété name.
La configuration choisit un compte StorageV2, avec une réplication locale Standard_LRS. Elle impose HTTPS et TLS 1.2 au minimum, et interdit l’accès anonyme aux conteneurs et aux blobs. Cette dernière propriété ne désactive pas, à elle seule, l’accès réseau public au compte.
Les sorties
Les déclarations output retournent l’identifiant du compte de stockage et l’adresse de son service Blob. Ces informations peuvent ensuite être utilisées par un script ou une chaîne de déploiement.
Déployer avec Azure CLI
L’exemple suivant utilise Azure CLI dans un terminal Bash. Il suppose que le fichier main.bicep se trouve dans le répertoire courant et que le compte connecté possède les autorisations nécessaires.
Se connecter et sélectionner l’abonnement
Créer le groupe de ressources
Dans cet exemple, le groupe de ressources est créé séparément : le fichier Bicep déploie le compte de stockage à l’intérieur de ce groupe.
Prévisualiser les modifications
az deployment group what-if \
--resource-group rg-demo-bicep \
--template-file main.bicep \
--parameters environment=dev
L’opération what-if prédit les modifications du déploiement sans les appliquer. Elle permet de les examiner avant l’exécution, même si certaines expressions peuvent rendre ses résultats imprécis.
Exécuter le déploiement
az deployment group create \
--name deploy-storage-dev \
--resource-group rg-demo-bicep \
--template-file main.bicep \
--parameters environment=dev
Azure CLI compile le fichier Bicep et transmet le modèle à Azure Resource Manager. Les sorties sont disponibles dans le résultat du déploiement.
Séparer la description et les paramètres
Pour conserver les valeurs propres à un environnement, nous pouvons créer un fichier dev.bicepparam :
Puis lancer le déploiement :
az deployment group create \
--name deploy-storage-dev \
--resource-group rg-demo-bicep \
--parameters dev.bicepparam
L’instruction using associe le fichier de paramètres au fichier Bicep. Cette organisation permet de réutiliser une même description avec différentes configurations.
Organiser une infrastructure avec des modules
Lorsque l’infrastructure s’enrichit, les modules permettent de répartir sa description entre plusieurs fichiers : réseau, stockage, hébergement ou supervision.
Par exemple, un fichier principal peut appeler un module de stockage :
module storage './modules/storage.bicep' = {
name: 'deploy-storage'
params: {
location: location
environment: environment
}
}
Le fichier storage.bicep doit déclarer les paramètres transmis. Ses sorties peuvent ensuite être consultées avec une expression comme storage.outputs.storageAccountId.