1
0

More than 1 year has passed since last update.

【Packer】GitHubActionsでAzure VMのイメージをビルドする

Last updated at Posted at 2023-03-28

今回は以下の記事でご紹介した Windows Server 2022 の日本語化イメージ作成を GitHubActions で実行できるようにしてみました。

事前準備

以下の記事を参考にGitHubActions から OpenID Connect で認証できるようにしておきます。

ワークフローを作成

課題もありますが、完成系はこんな感じです。

.github\workflows\main.yml
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 を手入力するようにしました。セマンティックバージョニングのよい管理方法がわからなかったので、とりあえず手入力で回避。
image.png

on.workflow_dispatch.inputs をやめて、日付から image version 生成する形に修正しました。(例:2023.0330.1200)

azure-winvm-image.pkr.hcl
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
.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

image.png

Azureサインインに必要なシークレットは事前準備の中で登録済みですが、winrm_password にセットするパスワードのみ追加で登録します。パスワードは任意のものに置き換えてください。

gh secret set WINRM_PASSWORD --body "input_your_password"

image.png

ワークフロー実行

GitHubの Actions タブからワークフロー実行します。約33分で完了しました。
image.png
image.png

まとめ

今回はGitHubActions上でPackerを実行してVMイメージを作成できるようにしてみました。いちおう動く形にはなりましたが、ローカル実行と違ってCI/CDに組み込む場合は色々と考慮すべき点があることがわかり、良い気づきになりました。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0