クラウドエンジニアブログ

Azure Pipelines で実現する IaC - 第 2 回 Azure リソース プロビジョニング

鈴村 礼治

1. はじめに

こんにちは!鈴村です。
Azure Pipelines で実現する IaC シリーズの第 2 回になります。

今回は Azure リソース プロビジョニングについてご紹介したいと思います。


<目次>
  • [1. はじめに]
  • [2. Azure リソース プロビジョニング]
    • [2-1. 概要]
    • [2-2. アーキテクチャー]
  • [3. 実装]
    • [3-0. 事前準備]
    • [3-1. Repos の準備と VSCode との連携]
    • [3-2. ARM Template の準備]
    • [3-3. pipeline の作成]
      • [ポイント 1 pipeline 設定ファイルの構成]
    • [3-4. pipeline の改修]
      • [ポイント 2 GUI によるタスクの追加]
      • [ポイント 3 Azure サブスクリプションとの接続]
      • [ポイント 4 ARM Template テンプレート ファイルの parameter 上書き]
    • [3-5. ARM Template の outputs の参照]
      • [ポイント 5 pipeline で参照可能な変数の作成]
  • [3-6. PowerShell スクリプトの実行]
  • [3-7. 仮想マシンのデプロイ]
  • [4. まとめ]


Microsoft Azure でリソースを作成するにはいくつかの方法があります。

これらのうち ARM Template を使用する場合、プロビジョニングのために Azure PowerShell や Azure CLI のコマンドを実行する必要があります。
今回ご紹介する Azure リソース プロビジョニング では、Azure Pipelines を使用して ARM Template を実行することができます。

第 1 回でご紹介した構築フローのうち、今回の対象範囲は「Azure VM 構築作業」の部分になります。

1.はじめに



2. Azure リソース プロビジョニング

2-1. 概要

今回ご紹介する Azure リソース プロビジョニングでは、ARM Template を使用した Azure 仮想マシンの構築作業の自動化を目標とします。

Azure リソース プロビジョニングで使用する Azure DevOps の機能は以下になります。


Repos は Azure DevOps における Git リポジトリの役割を担い、ARM Template のバージョン管理に使用します。
Pipelines は ARM Template を実行する役割を担います。どの ARM Template を実行するか、どのタイミングで ARM Template を実行するか、どの[エージェント]上で ARM Template を実行するのかを管理します。
Pipelines には Repos と連携する機能があり、Repos への Push や Pull Request をトリガーとしてタスクを実行したり、Repos のソースコードを基にビルドやリリースを実行できます。
これらの機能を利用して、仮想マシンの構築作業を自動化します。

また、ソースコードをローカルで管理、編集するためのエディタとして [Visual Studio Code (VSCode) ]を使用します。


2-2. アーキテクチャー

Azure リソース プロビジョニングのアーキテクチャーを図式化してみました。

2-2


  1. ユーザーが Repos に更新を Push
  2. Pipelines が Repos への Push を検知
  3. Pipelines がエージェントにデプロイを指示
  4. エージェントが Repos から ARM Template のテンプレート ファイルとパラメーター ファイルを参照
  5. エージェントが仮想マシンをデプロイ


3. 実装

Azure リソース プロビジョニングを実行できる環境を構築します。
実装する上で重要な部分、躓きやすい部分を「ポイント」として詳しく説明しています。

3-0. 事前準備

Azure DevOps を使用するにあたり、Organization と Project が作成済みであることを前提としております。
作成されていない場合、以下のページを参考に作成してください。


3-1. Repos の準備と VSCode との連携

Project に移動し「Repos」を選択します。

3-1-1



画面上部にあるプルダウン リストを選択し、「+New Repository」から新しいリポジトリを作成します。
※初めてプロジェクトを作成した場合、画像とレイアウトが異なる場合があります。

3-1-2



リポジトリの詳細を設定するフォームが表示されます。
Repository type は「Git」を選択します。
Repository name には任意のリポジトリ名を入力します。
入力が完了したら、「Create」を選択します。

3-1-3



リポジトリを作成すると、自動的に Repos に移動します。
「Clone in VS Code」を選択しローカルの PC にリポジトリをクローンします。

3-1-4


3-1-5



3-2. ARM Template の準備

Azure リソース プロビジョニングに使用する ARM Template を準備します。
ARM Template の作成は今回のスコープから外れてしまうので、このプロジェクト用に作成したものを使用したいと思います。

Sample Files
ダウンロード リンク

※スマートフォンからダウンロードした場合、機種によっては正常に閲覧できないことがあります。その場合は、PC のブラウザからダウンロードしてください。

上記のダウンロード リンクにあるファイルを、先ほどクローンしたリポジトリ(ローカル リポジトリ)に配置します。

3-2-1



3-2-2

parameters ディレクトリには ARM Template のパラメーター ファイルがまとめられています。
templates ディレクトリには ARM Template のテンプレート ファイルがまとめられています。
これらの ARM Template は仮想マシンに必要な Azure リソースを作成するものです。
sample ディレクトリと scripts ディレクトリ については後ほど説明します。

配置が完了したら、Repos に Commit と Push を行います。
ここでは master ブランチに Push します。

3-2-3



Repos を更新すると、Push した内容が反映されています。

3-2-4



以上で、ARM Template の準備は完了です。

3-3. pipeline の作成

Azure リソース プロビジョニングを実行する pipeline を作成する前に、まず pipeline の構造、動作をご紹介します。
Pipelines でデフォルトで生成される Hello world を出力する pipeline を使用します。

Repos の Files から「Set up build」を選択します。

3-3-1



pipeline の作成画面に移動します。
まず、pipeline の作成元を選択します。ここでは「Starter pipeline」を選択します。
※「Existing Azure Pipelines YAML file」を選択すると、リポジトリにある pipeline の設定ファイルを作成元に指定できます。

3-3-2



「Starter pipeline」を選択すると、pipeline の設定ファイルが自動で作成され、確認画面に移動します。


ポイント 1 pipeline 設定ファイルの構成
  
yaml
trigger:
- master

pool:
  vmImage: 'ubuntu-latest'

steps:
- script: echo Hello, world!
  displayName: 'Run a one-line script'

- script: |
    echo Add other tasks to build, test, and deploy your project.
    echo See https://aka.ms/yaml
  displayName: 'Run a multi-line script'  

pipeline の設定ファイルは [YAML] というフォーマットで書かれています。
trigger ではどのブランチに変更が加えられたタイミングで pipeline を実行するかを指定します。


yaml
trigger:
- master

この設定の場合、master ブランチに Push したタイミングで pipeline が実行されます。

pool では pipeline の各タスクを実行するエージェントの種類を指定します。
下でご紹介するタスクはこの**エージェント上で実行**されます。

  
yaml
pool:
  vmImage: 'ubuntu-latest'  

この設定の場合、エージェントは Ubuntu の最新バージョンになります。
指定可能な値は [こちら] を参照してください。

steps 以下に pipeline で実行するタスクを記述します。
※ [YAML] のページにある stages や jobs は省略可能です。

  
yaml
steps:
- script: echo Hello, world!
  displayName: 'Run a one-line script'

- script: |
    echo Add other tasks to build, test, and deploy your project.
    echo See https://aka.ms/yaml
  displayName: 'Run a multi-line script'  

ここでは 2 つのタスクを実行しています。
1 つ目のタスク


yaml
- script: echo Hello, world!
  displayName: 'Run a one-line script'  

2 つ目のタスク

  
yaml
- script: |
    echo Add other tasks to build, test, and deploy your project.
    echo See https://aka.ms/yaml
  displayName: 'Run a multi-line script'  

script はコマンドラインを実行するタスクです。コロン ( : ) 以降にコマンドを記述します。パイプ ( | ) を使用することで複数行のコマンドを記述できます。
echo は文字を出力するコマンドです。echo 以降に書かれた文字列を出力します。1 つ目のタスクの場合、「Hello, world!」が出力されます。
displayName は pipeline を実行した際のログに表示されるタスク名です。


設定ファイルを確認したら「Save and run」を選択します。

3-3-3



設定ファイルを保存するフォームが表示されます。
Commit message と Optional extended description はそのままで問題ありません。
Commit directly to the master branch を指定すると、master ブランチに pipeline の設定ファイルが保存されます。
Create a new branch for this commit を指定すると、新しいブランチに pipeline の設定ファイルが保存されます。
ここでは「Create a new branch for this commit」を選択し、デフォルトの「azure-pipelines」というブランチを指定しています。
「Start a pull request」のチェックを外して**「Save and run」を選択します。

3-3-4



自動的に pipeline が実行され、Summary 画面に移動します。
Jobs にある「Job」を選択すると、実行中の pipeline の詳細を確認することができます。

3-3-4



Job は複数のタスクから構成されています。この画面では、各タスクのログを確認することができます。

3-3-5



「Initialize job」「Checkout ...」「Post-job ...」「Finalize Job」「Report build ...」は Pipelines によって自動的に作成されたタスクです。
先ほど作成された設定ファイルに含まれるタスクは「Run a one-line...」と「Run a multi-lin...」です。
設定ファイルの **displayName** の設定値が表示されています。

「Run a one-line...」を選択すると、そのタスクの実行結果のログが表示されます。

3-3-6



タスクは

  
yaml
- script: echo Hello, world!  

なので、「Hello, world!」が出力されています。
他のタスクのログも確認してみてください。

確認が完了したら Repos に戻ります。

3-3-7



リポジトリ名の右にあるドロップダウン リストからブランチを「azure-pipelines」に変更します。

3-3-8



先ほど作成した pipeline の設定ファイル(azure-pipelines.yml)があることを確認します。

3-3-9



以上で pipeline の作成および動作確認は完了です。

3-4. pipeline の改修

先ほど作成した pipeline を改修し、Azure リソース プロビジョニングを行う pipeline を作成します。
いきなり仮想マシンを作成する pipeline を作るのは大変ですので、まずはリソース グループを作成する pipeline を作ってみましょう。

まず、VSCode で「azure-pipelines ブランチ」をチェックアウトします。

3-4-1



azure-pipelines.yml を開いて以下のように修正します。

 
yaml
trigger:
- azure-pipelines

こうすることで、azure-pipelines ブランチに Push したタイミングで pipeline が実行されるようになります。
修正が完了したら Commit と Push を行います。

3-4-2



Azure DevOps の Pipelines を確認します。
3-1. で作成したリポジトリの名前の pipeline を選択します。

3-4-3



Push を行ったタイミングで pipeline が実行されていることがわかります。

3-4-4



これで、pipeline を実行するトリガーを変更することができました。また、自動的に pipeline が実行されることを確認できました。


ポイント 2 GUI によるタスクの追加

タスクの追加は pipeline の設定ファイルを編集することで可能です。Pipelines には、GUI でタスクを簡単に追加する機能があります。
まずは、Repos に配置した ARM Template の中から、resourceGroup.json を使用してリソース グループを作成するタスクを追加します。

pipeline の「Edit」を選択します。

3-4-5



pipeline 設定ファイルを編集するためのエディタが表示されます。まず、「azure-pipelines ブランチ」を選択していることを確かめます。

3-4-6



次に、不要なタスクなどを削除します。ファイルの先頭にあるコメントアウトの部分と steps: 以降のタスクを削除します。

3-4-7



画面の右側にあるリストが Pipelines で実行可能なタスクの一覧です。この中から実行したいタスクを選択します。

3-4-8



今回は ARM Template を使用したリソース プロビジョニングを実行したいので、検索ボックスに「ARM」と入力し、検索結果にある「ARM template deployment」を選択します。

3-4-9



それぞれのタスクを選択すると、タスクの実行に必要な情報を指定するためのフォームが表示されます。
ARM template deployment タスクの場合、デプロイ先の Azure の情報とデプロイに使用する ARM Template の情報を指定します。

3-4-10



まず、Azure の情報を Azure Details 以下に入力します。

3-4-11



Deployment scope は「Subscription」を選択します。
Azure Resource Manager connection は 「デプロイ先のサブスクリプション」を選択します。
サブスクリプションを選択すると、「Authorize」ボタンが押せるようになります。



ポイント 3 Azure サブスクリプションとの接続

この「Authorize」ボタンを押すと次の内容が実行されます。

  • デプロイ先サブスクリプションの Azure Active Directory にサービス プリンシパルを作成する
  • 作成したサービス プリンシパルにサブスクリプション スコープで共同作成者のロールを割り当てる

これらの操作は、現在ログインしているユーザーの権限によって実行されるため、適切な権限を持っていなければエラーになってしまいます。
既にあるサービス プリンシパルを使用したい場合などは、Project Settings の Service connections から service connection を作成し、Azure Resource Manager connection で選択することもできます。
詳しい作成方法は [こちら] を参照してください。




Authorize が完了したら、残りの項目を埋めます。
Subscription は「デプロイ先のサブスクリプション」を選択します。
Location は「Japan East」を選択します。

3-4-12



次に、ARM Template の情報を Template 以下に入力します。

3-4-13



Template location は「Linked artifact」を選択します。Linked artifact では Repos にあるファイルを、「URL of the file」では指定した URL にあるファイルをデプロイに使用します。
Template には「Repos のテンプレート ファイルのパス」を入力します。
Template parameters には「Repos のパラメーター ファイルのパス」を入力します。


ポイント 4 ARM Template テンプレート ファイルの parameter 上書き

Override template parameters では、テンプレート ファイルの parameters で宣言されている変数の値を上書きする設定ができます。例えば、テンプレート ファイルの parameters が以下のようになっているとします。


json
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"variables": {},
"parameters": {
    "resourceName": {
        "type": "string",
    }
},
"resources": [
  {
    "name": "[parameters('resourceName')]",
    ...省略...
  }
],
"outputs": {}
```
Override template parameters に以下のように入力することで、 resourceName の値を上書きできます。  

-resourceName "hogehoge"  

設定ファイルでの記述例は以下になります。

  
yaml
- task: AzureResourceManagerTemplateDeployment@3
  inputs:
    ...省略...
    overrideParameters: '-resourceName "hogehoge"'
    ...省略...  

pipeline の変数を使用する場合の記述例は以下になります。
変数の設定方法については [こちら] を参照してください。

  
yaml
- task: AzureResourceManagerTemplateDeployment@3
  inputs:
    ...省略...
    overrideParameters: '-resourceName $(hoge)'
    ...省略...  



Deployment mode は「Incremental」を選択します。

入力が完了したら、エディタで steps: の下にカーソルがあることを確認し、「Add」を選択します。

3-4-14



指定した情報が pipeline の設定ファイルに書き込まれます。

確認後、右上の「Save」を選択します。

3-4-15



デフォルトのまま「Save」を選択します。

3-4-16



これで、azure-pipelines ブランチにある azure-pipelines.yml の内容が更新され、pipeline が実行されます。
Pipelines を確認してみます。

3-4-17



pipeline の詳細を確認し、実行が完了するのを見守ります。

3-4-18



ここで唐突な Tips ですが、この ARM template deployment タスクは Azure DevOps や Pipelines が実行しているわけではありません。タスクを実行するのは pipeline の設定ファイルの pool で指定したエージェントが実行します。ですので、resourceGroup.json もエージェントに送られ、このエージェントが New-AzDeployment なり az group deployment create なりのコマンドを実行しているということになります。
エージェントの種類によっては実行できないタスクもあります。
ここでは Microsoft が用意したエージェント (Microsoft Hosted Agent) を使用していますが、ご自分で用意したエージェント (Self-hosted Agent) を使用することもできます。詳細は [こちら] を参照してください。

実行が完了したら、デプロイ先のサブスクリプションでリソース グループの一覧を確認します。
「devops-pipelines-rg001」という名前のリソース グループが作成されます。

3-4-19



これで、Azure リソース プロビジョニングを行う pipeline を作成することができました。


3-5. ARM Template の outputs の参照

ARM Template には作成したリソースの ID などを出力するための [outputs] があります。
この outputs を利用することで、後続のタスクに作成されたリソースの情報を渡すことができます。
用意した ARM Template では、仮想マシン作成に NIC のリソース ID が必要になったり、NIC の作成に サブネット と パブリック IP アドレス のリソース ID が必要になるので、この outputs が重要になります。
Azure Pipelines の ARM template deployment タスクでは、Deployment outputs の設定をすることで、指定した変数に outputs の値を格納することができます。

3-5-1

  
yaml
steps:
- task: AzureResourceManagerTemplateDeployment@3
  inputs:
    deploymentScope: 'Subscription'
    azureResourceManagerConnection: 'hogehoge'
    subscriptionId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
    location: 'Japan East'
    templateLocation: 'Linked artifact'
    csmFile: 'templates/resourceGroup.json'
    csmParametersFile: 'parameters/resourceGroup.json'
    deploymentMode: 'Incremental'
    deploymentOutputs: 'rgOutputs'

- pwsh: Write-Host '''$(rgOutputs)'''  

しかし、この変数に格納される値は JSON 形式の文字列になっています。

  
json
{"resourceGroupResourceId":{"type":"String","value":"/subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/providers/MicrosMicrosoft.Resources/resourceGroups/devops-pipelines-rg001"},"resourceGroupName":{"type":"String","value":"devops-pipelines-rg001"}}  

この値を ARM template deployment タスクの **Override template parameters** に与えると、テンプレート ファイル側で追加の処理が必要になってしまいます。
そこで、この outputs を一つ一つの変数(key = value)に分割するのが scripts ディレクトリ にある「readOutputs.ps1」です。
このスクリプトは、コマンドライン引数として与えられた outputs から、key と value を取得し、key の先頭に「Output_」を付けた変数に value を格納し、 Azure Pipelines で使用できる変数として出力します。


ポイント 5 pipeline で参照可能な変数の作成

Azure Pipelines で参照可能な変数をタスクから作成するには、以下の文字列を標準出力に出力します。作成した変数は、$(<変数名>)で参照できます。

  
vso[task.setvariable variable=<変数名>]<値>  

PowerShell の場合

  
yaml
- pwsh: Write-Host "##vso[task.setvariable variable=hoge]ほげ"
- pwsh: Write-Host $(hoge)

Bash の場合


yaml
- bash: echo '##vso[task.setvariable variable=hoge]ほげ'
- bash: echo $(hoge)

この方法で作成した変数は steps 内であれば参照することができます。
job をまたいで参照可能な変数を作成する場合、「isOutput」オプションを付けること、出力を行うタスクに名前を付けることが必要になります。また、参照の方法が異なります。

詳細は [こちら] を参照してください。


yaml
jobs:
- job: Pre
  steps:
  - pwsh: Write-Host "##vso[task.setvariable variable=hoge;isOutput=true]fuga"
    name: setVar

- job: Main
  dependsOn: Pre
  variables:
    preVar: $[dependencies.Pre.outputs['setVar.hoge']]
  steps:
  - pwsh: Write-Host $(preVar)  


3-6. PowerShell スクリプトの実行

readOutputs.ps1 を実行するタスクを pipeline に追加します。
pipeline の設定ファイルの編集画面に移動します。
今回は、PowerShell スクリプトを実行したいので、検索ボックスに「PowerShell」と入力します。
検索結果から、「Azure PowerShell」を選択します。

3-6-1



以下を参考に値を入力します。
Script Arguments は所謂コマンドライン引数です。リソース グループを作成するタスクの outputs を文字列として渡すため、シングル クォーテーションで囲っています。

3-6-2



設定が完了したら、カーソルの位置がファイルの末尾にあることを確認し、「Add」を選択します。
出力された変数を確認する PowerShell のタスクも追加しておきます。
最終的な設定ファイルは以下になります。
※azureResourceManagerConnection, subscriptionId, azureSubscription はそれぞれの環境により異なります。


yaml
trigger:
- azure-pipelines

pool:
  vmImage: 'ubuntu-latest'

steps:
- task: AzureResourceManagerTemplateDeployment@3
  inputs:
    deploymentScope: 'Subscription'
    azureResourceManagerConnection: 'hogehoge'
    subscriptionId: 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
    location: 'Japan East'
    templateLocation: 'Linked artifact'
    csmFile: 'templates/resourceGroup.json'
    csmParametersFile: 'parameters/resourceGroup.json'
    deploymentMode: 'Incremental'
    deploymentOutputs: 'rgOutputs'

- task: AzurePowerShell@5
  inputs:
    azureSubscription: 'hogehoge'
    ScriptType: 'FilePath'
    ScriptPath: 'scripts/readOutputs.ps1'
    ScriptArguments: '''$(rgOutputs)'''
    azurePowerShellVersion: 'LatestVersion'

- pwsh: |
    Write-Host $(Output_resourceGroupResourceId)
    Write-Host $(Output_resourceGroupName)  

設定ファイルの変更を「Save」し、pipeline のログを確認します。
PowerShell のタスクのログに ARM template deployment タスクで作成されたリソース グループの ID と名前が出力されます。

3-6-3



これで、ARM Template の outputs を Azure Pipelines の変数として出力することができました。


3-7. 仮想マシンのデプロイ

これまでの説明を元に、仮想マシンのデプロイを行う pipeline を作成してみましょう。

作成が面倒な方は _sample ディレクトリ にある azure-pipelines.yml を使用してください。
variables の armConnectionName と subscriptionId** の値を、これまでに作成した pipeline の azureResourceManagerConnection と subscriptionId からコピペすれば使用できます。

仮想マシンへの接続には公開鍵認証の SSH を使用するため、公開鍵 / 秘密鍵をご用意ください。

また、ARM Template で変更が必要な箇所は以下になります。

  • parameters/virtualNetwork.json
    • addressPrefixes … サブスクリプション内で既に使用しているアドレス空間と重複しない値を指定
  • parameters/subnet.json
    • addressPrefix … 仮想ネットワークのアドレス空間に収まる値を指定
  • parameters/publicIPAddress.json
    • domainNameLabel … 東日本リージョン内で一意になるような DNS 名ラベルを指定
  • parameters/networkSecurityGroup.json
    • sourceAddressPrefix … 仮想マシンへの SSH 接続を許可する IP アドレス(CIDR 表記)
  • parameters/virtualMachine.json
    • keyData … SSH 認証に使用する公開鍵

pipeline を実行すると、以下のリソースが作成されます。

3-7-1



また、Tera Term などで以下の情報を使用し仮想マシンに接続できます。

  • ホスト:<DNS 名ラベル>.japaneast.cloudapp.azure.com
  • TCPポート:22
  • ユーザ名:devops

3-7-2



3-7-3



3-7-4



以上で、Azure リソース プロビジョニングの目標としていた、Azure 仮想マシンの構築作業の自動化が実現できました!


4. まとめ

今回は Azure リソース プロビジョニングについてご紹介しました。
ハンズオン形式の内容になってしまいましたが、Azure DevOps の Pipelines の基本的な使い方の理解の一助になれば幸いです。

今回はここまでとなります。
第 3 回をお楽しみに!



関連ページ

Azure Pipelines で実現する IaC - 第 1 回 Introduction
Azure Pipelines で実現する IaC - 第 3 回 Azure リソース テスト
Azure Pipelines で実現する IaC - 第 4 回 OS・MW コンフィグレーション

【総合】お問い合わせ

製品・サービスに関するお問い合わせはお気軽にご相談ください

ピックアップ

セミナー情報
クラウドエンジニアブログ
clouXion
メールマガジン登録