見出し画像

Azure Bicepって何?簡単に使ってみました。CICDと同時に利用してみた。


Azure Bicepとは

初めに

こんにちは。痛快技術のテッ ミャッ トゥーと申します。今回皆さんに説明して頂きたいのはAzure Bicepの利用方法と何で利用するか教えていただきます。Azure Resource Manager (ARM) テンプレートを使ったことがある方なら、何百行ものJSONコードと括弧、引用符と格闘した経験があるでしょう。私も何時間もARMテンプレートのデバッグに費やし、最後にカンマや括弧が1つ抜けていただけだったということが何度もありました。

そこで登場するのがAzure Bicepです。Azureインフラストラクチャのデプロイを大きく変えるツールです。

このブログでは、私のBicep使用経験を共有します。最初のテンプレート作成から、デプロイまで解説します。

このブログで学べること:

  • Bicepとは何か、なぜ重要か

  • 最初のBicepテンプレートの書き方

  • Bicep Storageの実践的なパターン

  • Azure DevOpsとのCI/CD統合

Azure Bicepとは?

ARMテンプレートの問題点

まず、簡単な例を見てみましょう。ストレージアカウントのARMテンプレートです:

{
  "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "storageAccountName": {
      "type": "string",
      "metadata": {
        "description": "ストレージアカウントの名前"
      }
    },
    "location": {
      "type": "string",
      "defaultValue": "[resourceGroup().location]",
      "metadata": {
        "description": "ストレージアカウントの場所"
      }
    }
  },
  "resources": [
    {
      "type": "Microsoft.Storage/storageAccounts",
      "apiVersion": "2023-01-01",
      "name": "[parameters('storageAccountName')]",
      "location": "[parameters('location')]",
      "sku": {
        "name": "Standard_LRS"
      },
      "kind": "StorageV2",
      "properties": {
        "minimumTlsVersion": "TLS1_2",
        "supportsHttpsTrafficOnly": true
      }
    }
  ],
  "outputs": {
    "storageAccountId": {
      "type": "string",
      "value": "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageAccountName'))]"
    }
  }
}

問題点:

  • シンプルなストレージアカウントで40行以上のコード

  • 読みにくく、メンテナンスが難しい

  • 構文エラーが発生しやすい

  • IntelliSenseや型チェックがない

  • モジュール化が難しい

Bicepの登場

同じストレージアカウントをBicepで書くと:

param storageAccountName string
param location string = resourceGroup().location

resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
  name: storageAccountName
  location: location
  sku: {
    name: 'Standard_LRS'
  }
  kind: 'StorageV2'
  properties: {
    minimumTlsVersion: 'TLS1_2'
    supportsHttpsTrafficOnly: true
  }
}

output storageAccountId string = storageAccount.id

 メリット:

Bicepを使う理由(メリット)

  1. 大幅に簡略化された構文

  2.  優れたツールサポート

  3. モジュール性と再利用性

  4. シンプルで読みやすい構文 - 型安全性

始め方

前提条件

  1. Azure CLI(バージョン2.20.0以降)

  2. Visual Studio Code

  3. Bicep VS Code拡張機能

  4. Azureサブスクリプション

インストール

Windows powershell:

# Azure CLIのインストール(まだインストールしていない場合)
winget install Microsoft.AzureCLI

# BicepはAzure CLIに含まれていますが、最新版にアップデート
az bicep install
az bicep upgrade

# インストールの確認
az bicep version

Linux/macOS bash:

# Azure CLIのインストール
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash

# Bicepのインストール/アップグレード
az bicep install
az bicep upgrade

# 確認
az bicep version

VS Codeのセットアップ

  1. https://code.visualstudio.com/ からVS Codeをインストール

  2. Bicep拡張機能をインストール:

    • Ctrl+Shift+X(Windows/Linux)またはCmd+Shift+X(Mac)を押す

    • "Bicep"を検索

    • 公式のMicrosoft拡張機能をインストール

最初のデプロイ

1. リソースグループの作成:

az group create \
  --name rg-bicep-demo \
  --location eastus

2. 最初のBicepファイルを作成(storage.bicep):

param storageAccountName string
param location string = resourceGroup().location

resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
  name: storageAccountName
  location: location
  sku: {
    name: 'Standard_LRS'
  }
  kind: 'StorageV2'
}

output storageAccountId string = storageAccount.id

3. デプロイ:

az deployment group create \
  --resource-group rg-bicep-demo \
  --template-file storage.bicep \
  --parameters storageAccountName=mystorageacct001

4. 確認:

az storage account show \
  --name mystorageacct001 \
  --resource-group rg-bicep-demo

参考:パラメータファイルでデプロイする場合

az deployment group create \
  --resource-group rg-bicep-demo \
  --template-file storage.bicep \
  --template-parameter-file param.json

PowerShellデプロイスクリプト

ローカルまたはカスタムデプロイ用:
What-Ifは、実際にデプロイする前に「何が変更されるか」を確認できる機能です。 本番環境に影響を与えずに、リソースの追加・変更・削除を事前にチェックできます。

# deploy.ps1
param(
    [Parameter(Mandatory=$true)]
    [ValidateSet('dev', 'test', 'prd')]
    [string]$Environment,
    
    [Parameter(Mandatory=$false)]
    [switch]$WhatIf
)

$ErrorActionPreference = 'Stop'

# 設定
$subscriptionId = 'your-subscription-id'
$resourceGroupName = "rg-dataplatform-$Environment"
$location = 'eastus'
$templateFile = './infrastructure/main.bicep'
$parametersFile = "./infrastructure/parameters/$Environment.json"

Write-Host "$Environment 環境へのデプロイを開始します" -ForegroundColor Cyan

# Azureに接続
Write-Host "Azureに接続中..." -ForegroundColor Yellow
Connect-AzAccount
Set-AzContext -SubscriptionId $subscriptionId

# リソースグループが存在しない場合は作成
Write-Host "リソースグループを確認中..." -ForegroundColor Yellow
$rg = Get-AzResourceGroup -Name $resourceGroupName -ErrorAction SilentlyContinue
if (-not $rg) {
    Write-Host "リソースグループを作成中: $resourceGroupName" -ForegroundColor Green
    New-AzResourceGroup -Name $resourceGroupName -Location $location
}

# 指定された場合はwhat-ifを実行
if ($WhatIf) {
    Write-Host "What-If分析を実行中..." -ForegroundColor Yellow
    $whatIfResult = Get-AzResourceGroupDeploymentWhatIfResult `
        -ResourceGroupName $resourceGroupName `
        -TemplateFile $templateFile `
        -TemplateParameterFile $parametersFile
    
    $whatIfResult
    
    $continue = Read-Host "デプロイを続行しますか? (Y/N)"
    if ($continue -ne 'Y') {
        Write-Host "デプロイがキャンセルされました" -ForegroundColor Red
        exit
    }
}

# Bicepテンプレートのデプロイ
Write-Host "Bicepテンプレートをデプロイ中..." -ForegroundColor Green
$deploymentName = "deploy-$(Get-Date -Format 'yyyyMMdd-HHmmss')"

$deployment = New-AzResourceGroupDeployment `
    -Name $deploymentName `
    -ResourceGroupName $resourceGroupName `
    -TemplateFile $templateFile `
    -TemplateParameterFile $parametersFile `
    -Verbose

if ($deployment.ProvisioningState -eq 'Succeeded') {
    Write-Host "デプロイが成功しました!" -ForegroundColor Green
    
    # 出力を表示
    if ($deployment.Outputs.Count -gt 0) {
        Write-Host "`nデプロイの出力:" -ForegroundColor Cyan
        $deployment.Outputs | Format-Table -AutoSize
    }
} else {
    Write-Host "デプロイが失敗しました!" -ForegroundColor Red
    exit 1
}

使用方法:環境変数を渡して、What if 確認とデプロイ

# what-if確認してから開発環境にデプロイ
.\deploy.ps1 -Environment dev -WhatIf

# Whatif確認なして、本番環境にデプロイ
.\deploy.ps1 -Environment prd

CI/CD統合

CI/CDとは?なぜBicepで使うべきか?

CI/CD(Continuous Integration/Continuous Deployment) は、コードの変更を自動的にテスト・検証・デプロイするプロセスです。

CI/CDパイプラインは、Bicepコードの変更を自動的にテスト・検証・デプロイする仕組みです。開発者がGitリポジトリにBicepファイルをプッシュすると、パイプラインが自動的に起動し、コードの品質チェックからAzure環境へのデプロイまでを実行します。


Azure DevOpsパイプライン

データプラットフォームインフラストラクチャのデプロイに使用している完全なパイプラインです:

# azure-pipelines.yml
trigger:none

variables:
  azureSubscription: 'Azure-ServiceConnection'
  location: 'eastus'

stages:
- stage: Validate
  displayName: 'Bicepテンプレートの検証'
  jobs:
  - job: ValidateBicep
    displayName: 'Bicep検証'
    pool:
      vmImage: 'windows-latest'
    steps:
    - task: AzureCLI@2
      displayName: 'Bicepのインストール'
      inputs:
        azureSubscription: $(azureSubscription)
        scriptType: 'bash'
        scriptLocation: 'inlineScript'
        inlineScript: |
          az bicep install
          az bicep version

    - task: AzureCLI@2
      displayName: 'Bicepビルド(検証)'
      inputs:
        azureSubscription: $(azureSubscription)
        scriptType: 'bash'
        scriptLocation: 'inlineScript'
        inlineScript: |
          az bicep build --file infrastructure/main.bicep

    - task: AzureCLI@2
      displayName: 'Bicep Linter'
      inputs:
        azureSubscription: $(azureSubscription)
        scriptType: 'bash'
        scriptLocation: 'inlineScript'
        inlineScript: |
          az bicep lint --file infrastructure/main.bicep

- stage: DeployDev
  displayName: '開発環境へのデプロイ'
  dependsOn: Validate
  condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/develop'))
  jobs:
  - deployment: DeployInfrastructure
    displayName: '開発インフラストラクチャのデプロイ'
    environment: 'dev'
    pool:
      vmImage: 'windows-latest'
    variables:
      resourceGroupName: 'rg-dataplatform-dev'
      environment: 'dev'
    strategy:
      runOnce:
        deploy:
          steps:
          - checkout: self

          - task: AzureCLI@2
            displayName: 'リソースグループの作成'
            inputs:
              azureSubscription: $(azureSubscription)
              scriptType: 'bash'
              scriptLocation: 'inlineScript'
              inlineScript: |
                az group create \
                  --name $(resourceGroupName) \
                  --location $(location)

          - task: AzureCLI@2
            displayName: 'What-Ifデプロイ'
            inputs:
              azureSubscription: $(azureSubscription)
              scriptType: 'bash'
              scriptLocation: 'inlineScript'
              inlineScript: |
                az deployment group what-if \
                  --resource-group $(resourceGroupName) \
                  --template-file infrastructure/main.bicep \
                  --parameters infrastructure/parameters/dev.json

          - task: AzureCLI@2
            displayName: 'Bicepテンプレートのデプロイ'
            inputs:
              azureSubscription: $(azureSubscription)
              scriptType: 'bash'
              scriptLocation: 'inlineScript'
              inlineScript: |
                az deployment group create \
                  --resource-group $(resourceGroupName) \
                  --template-file infrastructure/main.bicep \
                  --parameters infrastructure/parameters/dev.json \
                  --name "deploy-$(Build.BuildId)" \
                  --verbose

ベストプラクティス {#best-practices}

1. 命名規則

一貫性があり、読みやすい名前を使用:

bicep

// 悪い例
resource sa 'Microsoft.Storage/storageAccounts@2023-01-01' = {
  name: 'mystorageacct123'
}

// 良い例
var storageAccountName = '${appName}st${environment}'
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
  name: replace(storageAccountName, '-', '')  // ハイフンを削除
}
```

**推奨される命名パターン:**
```
{リソースタイプ}-{アプリ名}-{環境}-{リージョン}

例:
- func-datamonitor-prod-eus
- asp-datamonitor-dev-eus
- st-datamonitor-prod-eus(ハイフンを削除)

2. 一貫性のために変数を使用

param appName string
param environment string
param location string = resourceGroup().location

// 命名プレフィックスを一度定義
var namingPrefix = '${appName}-${environment}'

// テンプレート全体で使用
var functionAppName = '${namingPrefix}-func'
var appServicePlanName = '${namingPrefix}-asp'
var storageAccountName = replace('${namingPrefix}-st', '-', '')
var logAnalyticsName = '${namingPrefix}-law'
var appInsightsName = '${namingPrefix}-appi'

3. 適切なリソースタグ付け

// 共通タグを変数として定義
var commonTags = {
  Environment: environment
  Application: appName
  ManagedBy: 'Bicep'
  CostCenter: 'IT-DataPlatform'
  Owner: 'platform-team@company.com'
  DeployedBy: 'AzureDevOps'
  DeployedOn: utcNow('yyyy-MM-dd')
}

// すべてのリソースに適用
resource functionApp 'Microsoft.Web/sites@2023-01-01' = {
  name: functionAppName
  location: location
  tags: commonTags
  // ... プロパティ
}

resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {
  name: storageAccountName
  location: location
  tags: union(commonTags, {
    DataClassification: 'Confidential'
  })
  // ... プロパティ
}

4. 最新の安定したAPIバージョンを使用

//  悪い例 - 古いAPIバージョン
resource storageAccount 'Microsoft.Storage/storageAccounts@2021-01-01' = {

//  良い例 - 最新の安定版
resource storageAccount 'Microsoft.Storage/storageAccounts@2023-01-01' = {

参考リンク:

最後に

Bicepはまだ進化しています。定期的にドキュメントをチェックし、新機能を試し、コミュニティに貢献してください。Azureインフラストラクチャの管理がこれほど簡単になったことはありません!

私のブログから、BicepやCI/CDに関する少しの知識を学べると思います。、一緒にAzureインフラストラクチャをより良くしていきましょう!



いいなと思ったら応援しよう!