今回は以下の記事でご紹介した Windows Server 2022 の日本語化イメージ作成を GitHubActions で実行できるようにしてみました。
事前準備
以下の記事を参考にGitHubActions から OpenID Connect で認証できるようにしておきます。
ワークフローを作成
課題もありますが、完成系はこんな感じです。
name: Use Packer to create a Japanese-language image of an Azure Windows VM
on:
# push:
# branches:
# - main
workflow_dispatch:
# inputs:
# image_version:
# description: "VM image version name for the semantic version pattern."
# required: true
# type: string
# default: "1.0.0"
permissions:
id-token: write
contents: read
env:
PKR_VAR_project: ${{ vars.PROJECT }}
PKR_VAR_location: ${{ vars.LOCATION }}
PKR_VAR_resource_group_name: ${{ vars.RESOURCE_GROUP_NAME }}
PKR_VAR_vm_size: ${{ vars.VM_SIZE }}
PKR_VAR_gallery_name: ${{ vars.GALLERY_NAME }}
PKR_VAR_image_definition: ${{ vars.IMAGE_DEFINITION }}
PKR_VAR_replication_regions: ${{ vars.REPLICATION_REGIONS }}
PKR_VAR_winrm_password: ${{ secrets.WINRM_PASSWORD }}
keep_latest_count: ${{vars.KEEP_LATEST_COUNT}}
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Get runner's Public IP
id: ip
uses: haythem/public-ip@v1.2
- name: Azure Login
uses: azure/login@v1
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
enable-AzPSSession: true
- name: packer validate
run: packer validate -var 'inbound_ip_addresses=["${{ steps.ip.outputs.ipv4 }}"]' .
- name: packer build
run: packer build -var 'inbound_ip_addresses=["${{ steps.ip.outputs.ipv4 }}"]' .
- name: Delete versions of images prior to the specified number
uses: Azure/powershell@v1
with:
inlineScript: |
$imageVersions = Get-AzGalleryImageVersion -ResourceGroupName ${{ env.PKR_VAR_resource_group_name }} -GalleryName ${{ env.PKR_VAR_gallery_name }} -GalleryImageDefinitionName ${{ env.PKR_VAR_image_definition }}
if ($imageVersions.Count -gt ${{ env.keep_latest_count }}) {
$sortedImageVersions = $imageVersions | Sort-Object { $_.PublishingProfile.PublishedDate } -Descending
for ($i = ${{ env.keep_latest_count }}; $i -lt $sortedImageVersions.Count; $i++) {
$imageVersion = $sortedImageVersions[$i]
Remove-AzGalleryImageVersion -ResourceGroupName ${{ env.PKR_VAR_resource_group_name }} -GalleryName ${{ env.PKR_VAR_gallery_name }} -GalleryImageDefinitionName ${{ env.PKR_VAR_image_definition }} -Name $imageVersion.Name -Force
}
}
azPSVersion: "latest"
- name: logout
run: |
az logout
ワークフローの解説
トリガー
今回は on.push
ではなく、 on.workflow_dispatch
を使って手動でワークフローを実行できるようにします。
この時、Azure Compute Galleryに保存するイメージのバージョン image_version
を手入力するようにしました。セマンティックバージョニングのよい管理方法がわからなかったので、とりあえず手入力で回避。
→ on.workflow_dispatch.inputs
をやめて、日付から image version
生成する形に修正しました。(例:2023.0330.1200)
locals {
timestamp = formatdate("YYYYMMDDhhmmss", timeadd(timestamp(), "9h"))
image_version = formatdate("YYYY.MMDD.hhmm", timeadd(timestamp(), "9h"))
}
...
shared_image_gallery_destination {
resource_group = var.resource_group_name
gallery_name = var.gallery_name
image_name = var.image_definition
image_version = local.image_version
replication_regions = var.replication_regions
}
Packerに渡す変数
auto.pkrvars.hcl
で渡す変数の値をどうしようか悩みました。
はじめは packer build -var key=value
で全部渡そうとしたのですが、ワークフローの中で auto.pkrvars.hcl
を作成したほうがスッキリしてわかりやすい気がしたのでヒアドキュメントで作成する方法にしました。このあたりのお作法はまだよくわかっていません。
→ PKR_VAR_name
で環境変数を指定すれば良いだけだったので修正しました。
環境変数は冒頭にまとめています。
-
vars.
でリポジトリの変数を参照 -
inputs.
で入力値を参照 -
secrets.
でリポジトリのシークレットを参照
env:
PKR_VAR_project: ${{ vars.PROJECT }}
PKR_VAR_location: ${{ vars.LOCATION }}
PKR_VAR_resource_group_name: ${{ vars.RESOURCE_GROUP_NAME }}
PKR_VAR_vm_size: ${{ vars.VM_SIZE }}
PKR_VAR_gallery_name: ${{ vars.GALLERY_NAME }}
PKR_VAR_image_definition: ${{ vars.IMAGE_DEFINITION }}
PKR_VAR_replication_regions: ${{ vars.REPLICATION_REGIONS }}
PKR_VAR_winrm_password: ${{ secrets.WINRM_PASSWORD }}
keep_latest_count: ${{vars.KEEP_LATEST_COUNT}}
Azureサインイン
必須ではありませんが、Azure PowerShellを使えるように enable-AzPSSession: true
を設定しています。ワークフローの最後にAzure PowerShellを使います。
- name: Azure Login
uses: azure/login@v1
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
enable-AzPSSession: true
Packerの処理
GitHubActionsのランナーのグローバルIPは haythem/public-ip@v1.2
アクションで取得して、packer validate
, packer build
の時に-var
で渡しています。
なお、ランナーのUbuntu環境ではデフォルトで packer
コマンドが使えるようになっていますが、Packerのバージョンを固定する場合は hashicorp/setup-packer アクションを使った方が良さそうです。
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Get runner's Public IP
id: ip
uses: haythem/public-ip@v1.2
- name: packer validate
run: packer validate -var 'inbound_ip_addresses=["${{ steps.ip.outputs.ipv4 }}"]' .
- name: packer build
run: packer build -var 'inbound_ip_addresses=["${{ steps.ip.outputs.ipv4 }}"]' .
イメージの世代管理
ここは任意ですが、keep_latest_count
で定義する数だけ残して、それより古いイメージを削除するようにしています。
- name: Delete versions of images prior to the specified number
uses: Azure/powershell@v1
with:
inlineScript: |
$imageVersions = Get-AzGalleryImageVersion -ResourceGroupName ${{ env.PKR_VAR_resource_group_name }} -GalleryName ${{ env.PKR_VAR_gallery_name }} -GalleryImageDefinitionName ${{ env.PKR_VAR_image_definition }}
if ($imageVersions.Count -gt ${{ env.keep_latest_count }}) {
$sortedImageVersions = $imageVersions | Sort-Object { $_.PublishingProfile.PublishedDate } -Descending
for ($i = ${{ env.keep_latest_count }}; $i -lt $sortedImageVersions.Count; $i++) {
$imageVersion = $sortedImageVersions[$i]
Remove-AzGalleryImageVersion -ResourceGroupName ${{ env.PKR_VAR_resource_group_name }} -GalleryName ${{ env.PKR_VAR_gallery_name }} -GalleryImageDefinitionName ${{ env.PKR_VAR_image_definition }} -Name $imageVersion.Name -Force
}
}
azPSVersion: "latest"
GitHubの変数とシークレットの登録
var.
で参照するリポジトリ変数をGitHubに登録します。
gh variable set -f .env
PROJECT="MyProject"
LOCATION="japaneast"
RESOURCE_GROUP_NAME="packer-rg""
VM_SIZE="Standard_DS1_v2"
GALLERY_NAME="windows_dev_sig"
IMAGE_DEFINITION="2022-datacenter-smalldisk-g2"
REPLICATION_REGIONS=["japaneast"]
KEEP_LATEST_COUNT=1
Azureサインインに必要なシークレットは事前準備の中で登録済みですが、winrm_password
にセットするパスワードのみ追加で登録します。パスワードは任意のものに置き換えてください。
gh secret set WINRM_PASSWORD --body "input_your_password"
ワークフロー実行
GitHubの Actions タブからワークフロー実行します。約33分で完了しました。
まとめ
今回はGitHubActions上でPackerを実行してVMイメージを作成できるようにしてみました。いちおう動く形にはなりましたが、ローカル実行と違ってCI/CDに組み込む場合は色々と考慮すべき点があることがわかり、良い気づきになりました。