こんにちは!鈴村です。
Azure Pipelines で実現する IaC シリーズの第 2 回になります。
今回は Azure リソース プロビジョニングについてご紹介したいと思います。
Microsoft Azure でリソースを作成するにはいくつかの方法があります。
これらのうち ARM Template を使用する場合、プロビジョニングのために Azure PowerShell や Azure CLI のコマンドを実行する必要があります。
今回ご紹介する Azure リソース プロビジョニング では、Azure Pipelines を使用して ARM Template を実行することができます。
第 1 回でご紹介した構築フローのうち、今回の対象範囲は「Azure VM 構築作業」の部分になります。
今回ご紹介する 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) ]を使用します。
Azure リソース プロビジョニングのアーキテクチャーを図式化してみました。
Azure リソース プロビジョニングを実行できる環境を構築します。
実装する上で重要な部分、躓きやすい部分を「ポイント」として詳しく説明しています。
Azure DevOps を使用するにあたり、Organization と Project が作成済みであることを前提としております。
作成されていない場合、以下のページを参考に作成してください。
Project に移動し「Repos」を選択します。
画面上部にあるプルダウン リストを選択し、「+New Repository」から新しいリポジトリを作成します。
※初めてプロジェクトを作成した場合、画像とレイアウトが異なる場合があります。
リポジトリの詳細を設定するフォームが表示されます。
Repository type は「Git」を選択します。
Repository name には任意のリポジトリ名を入力します。
入力が完了したら、「Create」を選択します。
リポジトリを作成すると、自動的に Repos に移動します。
「Clone in VS Code」を選択しローカルの PC にリポジトリをクローンします。
Azure リソース プロビジョニングに使用する ARM Template を準備します。
ARM Template の作成は今回のスコープから外れてしまうので、このプロジェクト用に作成したものを使用したいと思います。
※スマートフォンからダウンロードした場合、機種によっては正常に閲覧できないことがあります。その場合は、PC のブラウザからダウンロードしてください。
上記のダウンロード リンクにあるファイルを、先ほどクローンしたリポジトリ(ローカル リポジトリ)に配置します。
parameters ディレクトリには ARM Template のパラメーター ファイルがまとめられています。
templates ディレクトリには ARM Template のテンプレート ファイルがまとめられています。
これらの ARM Template は仮想マシンに必要な Azure リソースを作成するものです。
sample ディレクトリと scripts ディレクトリ については後ほど説明します。
配置が完了したら、Repos に Commit と Push を行います。
ここでは master ブランチに Push します。
Repos を更新すると、Push した内容が反映されています。
以上で、ARM Template の準備は完了です。
Azure リソース プロビジョニングを実行する pipeline を作成する前に、まず pipeline の構造、動作をご紹介します。
Pipelines でデフォルトで生成される Hello world を出力する pipeline を使用します。
Repos の Files から「Set up build」を選択します。
pipeline の作成画面に移動します。
まず、pipeline の作成元を選択します。ここでは「Starter pipeline」を選択します。
※「Existing Azure Pipelines YAML file」を選択すると、リポジトリにある pipeline の設定ファイルを作成元に指定できます。
「Starter pipeline」を選択すると、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」を選択します。
設定ファイルを保存するフォームが表示されます。
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」を選択します。
自動的に pipeline が実行され、Summary 画面に移動します。
Jobs にある「Job」を選択すると、実行中の pipeline の詳細を確認することができます。
Job は複数のタスクから構成されています。この画面では、各タスクのログを確認することができます。
「Initialize job」「Checkout ...」「Post-job ...」「Finalize Job」「Report build ...」は Pipelines によって自動的に作成されたタスクです。
先ほど作成された設定ファイルに含まれるタスクは「Run a one-line...」と「Run a multi-lin...」です。
設定ファイルの **displayName** の設定値が表示されています。
「Run a one-line...」を選択すると、そのタスクの実行結果のログが表示されます。
タスクは
yaml
- script: echo Hello, world!
なので、「Hello, world!」が出力されています。
他のタスクのログも確認してみてください。
確認が完了したら Repos に戻ります。
リポジトリ名の右にあるドロップダウン リストからブランチを「azure-pipelines」に変更します。
先ほど作成した pipeline の設定ファイル(azure-pipelines.yml)があることを確認します。
以上で pipeline の作成および動作確認は完了です。
先ほど作成した pipeline を改修し、Azure リソース プロビジョニングを行う pipeline を作成します。
いきなり仮想マシンを作成する pipeline を作るのは大変ですので、まずはリソース グループを作成する pipeline を作ってみましょう。
まず、VSCode で「azure-pipelines ブランチ」をチェックアウトします。
azure-pipelines.yml を開いて以下のように修正します。
yaml
trigger:
- azure-pipelines
こうすることで、azure-pipelines ブランチに Push したタイミングで pipeline が実行されるようになります。
修正が完了したら Commit と Push を行います。
Azure DevOps の Pipelines を確認します。
3-1. で作成したリポジトリの名前の pipeline を選択します。
Push を行ったタイミングで pipeline が実行されていることがわかります。
これで、pipeline を実行するトリガーを変更することができました。また、自動的に pipeline が実行されることを確認できました。
タスクの追加は pipeline の設定ファイルを編集することで可能です。Pipelines には、GUI でタスクを簡単に追加する機能があります。
まずは、Repos に配置した ARM Template の中から、resourceGroup.json を使用してリソース グループを作成するタスクを追加します。
pipeline の「Edit」を選択します。
pipeline 設定ファイルを編集するためのエディタが表示されます。まず、「azure-pipelines ブランチ」を選択していることを確かめます。
次に、不要なタスクなどを削除します。ファイルの先頭にあるコメントアウトの部分と steps: 以降のタスクを削除します。
画面の右側にあるリストが Pipelines で実行可能なタスクの一覧です。この中から実行したいタスクを選択します。
今回は ARM Template を使用したリソース プロビジョニングを実行したいので、検索ボックスに「ARM」と入力し、検索結果にある「ARM template deployment」を選択します。
それぞれのタスクを選択すると、タスクの実行に必要な情報を指定するためのフォームが表示されます。
ARM template deployment タスクの場合、デプロイ先の Azure の情報とデプロイに使用する ARM Template の情報を指定します。
まず、Azure の情報を Azure Details 以下に入力します。
Deployment scope は「Subscription」を選択します。
Azure Resource Manager connection は 「デプロイ先のサブスクリプション」を選択します。
サブスクリプションを選択すると、「Authorize」ボタンが押せるようになります。
この「Authorize」ボタンを押すと次の内容が実行されます。
これらの操作は、現在ログインしているユーザーの権限によって実行されるため、適切な権限を持っていなければエラーになってしまいます。
既にあるサービス プリンシパルを使用したい場合などは、Project Settings の Service connections から service connection を作成し、Azure Resource Manager connection で選択することもできます。
詳しい作成方法は [こちら] を参照してください。
Authorize が完了したら、残りの項目を埋めます。
Subscription は「デプロイ先のサブスクリプション」を選択します。
Location は「Japan East」を選択します。
次に、ARM Template の情報を Template 以下に入力します。
Template location は「Linked artifact」を選択します。Linked artifact では Repos にあるファイルを、「URL of the file」では指定した URL にあるファイルをデプロイに使用します。
Template には「Repos のテンプレート ファイルのパス」を入力します。
Template parameters には「Repos のパラメーター ファイルのパス」を入力します。
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」を選択します。
指定した情報が pipeline の設定ファイルに書き込まれます。
確認後、右上の「Save」を選択します。
デフォルトのまま「Save」を選択します。
これで、azure-pipelines ブランチにある azure-pipelines.yml の内容が更新され、pipeline が実行されます。
Pipelines を確認してみます。
pipeline の詳細を確認し、実行が完了するのを見守ります。
ここで唐突な 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」という名前のリソース グループが作成されます。
これで、Azure リソース プロビジョニングを行う pipeline を作成することができました。
ARM Template には作成したリソースの ID などを出力するための [outputs] があります。
この outputs を利用することで、後続のタスクに作成されたリソースの情報を渡すことができます。
用意した ARM Template では、仮想マシン作成に NIC のリソース ID が必要になったり、NIC の作成に サブネット と パブリック IP アドレス のリソース ID が必要になるので、この outputs が重要になります。
Azure Pipelines の ARM template deployment タスクでは、Deployment outputs の設定をすることで、指定した変数に outputs の値を格納することができます。
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 で使用できる変数として出力します。
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)
readOutputs.ps1 を実行するタスクを pipeline に追加します。
pipeline の設定ファイルの編集画面に移動します。
今回は、PowerShell スクリプトを実行したいので、検索ボックスに「PowerShell」と入力します。
検索結果から、「Azure PowerShell」を選択します。
以下を参考に値を入力します。
Script Arguments は所謂コマンドライン引数です。リソース グループを作成するタスクの outputs を文字列として渡すため、シングル クォーテーションで囲っています。
設定が完了したら、カーソルの位置がファイルの末尾にあることを確認し、「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 と名前が出力されます。
これで、ARM Template の outputs を Azure Pipelines の変数として出力することができました。
これまでの説明を元に、仮想マシンのデプロイを行う pipeline を作成してみましょう。
作成が面倒な方は _sample ディレクトリ にある azure-pipelines.yml を使用してください。
variables の armConnectionName と subscriptionId** の値を、これまでに作成した pipeline の azureResourceManagerConnection と subscriptionId からコピペすれば使用できます。
仮想マシンへの接続には公開鍵認証の SSH を使用するため、公開鍵 / 秘密鍵をご用意ください。
また、ARM Template で変更が必要な箇所は以下になります。
pipeline を実行すると、以下のリソースが作成されます。
また、Tera Term などで以下の情報を使用し仮想マシンに接続できます。
以上で、Azure リソース プロビジョニングの目標としていた、Azure 仮想マシンの構築作業の自動化が実現できました!
今回は Azure リソース プロビジョニングについてご紹介しました。
ハンズオン形式の内容になってしまいましたが、Azure DevOps の Pipelines の基本的な使い方の理解の一助になれば幸いです。
今回はここまでとなります。
第 3 回をお楽しみに!
関連ページ
Azure Pipelines で実現する IaC - 第 1 回 Introduction |