Young Leaves

Azure Kubernetes Service 関連のGitHub Actions カスタムアクションを使ってデプロイをする

Azure Kubernetes Service (以下AKS) のデプロイについて、手動でkubectl のようなコマンドをあれこれ準備するのは大変です。今回はMicrosoft が提供している公式のカスタムアクションを利用し、既存のAKS にマニフェストを適用する方法について説明します。

若葉 香月
4 January, 2026

実施環境

Azure CLI

2.81.0

Kubernetes

1.34.1

前提条件

  • Azure アカウントおよびAzure CLI の実行環境があること
  • GitHub アカウントがあること
  • 認証用のGitHub Apps のトークンがあること

Azure Kubernetes Service におけるGitHub Actions のカスタムアクション

Azure Kubernetes Service (以下AKS) 関連のGitHub Actions カスタムアクションについて、2026年1月現在では以下のカスタムアクションがあります。ドキュメントでは azure/aks-github-runner というリポジトリも触れていますが、こちらはTerraform やHelm を使ってセルフホステッドランナーを設定するサンプルのため除外します。また、一部アクションは現時点で更新されていないアクションもあるため、利用する場合はこの点も考慮した上で利用してください。

アクション名

概要

azure/aks-set-context

AKS 用のKubernetes コンテキストを設定するアクション。内部の処理ではaz aks get-credentials で資格情報を取得しkubeconfig を作成している。Azure CLI が必要となるため、セルフホステッドランナーで利用する場合は事前にインストールが必要。

azure/k8s-set-context

AKS 以外のKubernetes (Azure VM やAzure Arc on Kubernetes など) の資格情報を設定するアクション。aks-set-context と違い、シークレットの値を直接指定してkubeconfig を設定する。Base64、サービスアカウント、サービスプリンシパルの3種類で設定可能。

azure/k8s-bake

Helm チャート、Kustomize、Kompose のファイルをAKS 用のマニフェストに変換するアクション。アクション実行時に各種ツールをダウンロードするため、特定のバージョンを使いたい場合はバージョン指定を行う。マニフェストの変換のみとなるため、デプロイには別途デプロイ用のアクションかコマンドが必要。

azure/k8s-create-secret

Kubernetes クラスター用の汎用またはDocker レジストリ用のシークレットを作成するアクション。ストレージアカウントの接続文字列やKey Vault のシークレットをコンテキストに設定したり、Docker レジストリのユーザー名、パスワードからDocker レジストリ用のシークレットも作成可能。内部的な処理はKubernetes のAPI を使いkubeconfig にシークレットを設定するため、azure/aks-set-context またはazure/k8s-set-context のようなアクションでコンテキストを設定していないとエラーになる。

azure/k8s-deploy

AKS にコンテナアプリケーションをデプロイするアクション。デプロイは基本的なkubectl apply を行うbasic に加え、カナリアデプロイ、ブルーグリーンデプロイも可能。カナリアデプロイ、ブルーグリーンデプロイを行う場合、切り替え用のロードバランサー、各種オプションの指定が必要。デプロイはマニフェストの適用に加え、マニフェスト内のイメージ置換も可能。private-cluster をtrue に指定すれば、プライベートクラスターへのデプロイも可能 (内部的にはaz aks invoke コマンドでデプロイを実行している)

azure/k8s-lint

Kubernetes のマニフェストに対し、kubectl のdry-run またはkubeconform を使い構文などの検証を実施するアクション。単一または複数のマニフェストを指定可能。内部的にはdry-run はkubectl apply コマンドにdry-run=server を指定して実行し、kubeconform は実行直前にGitHub 上からインストールし実行している。kubeconform はwith 句でオプションを指定でき、実行結果のダウンロードも可能。

azure/setup-helm

特定のバージョンのHelm をダウンロードしパスを設定するアクション。内部の処理ではInput で指定したHelm のバージョンをダウンロードし、actions/core のaddPath 関数でパスを設定する。GitHub ホステッドランナーに導入されているHelm のバージョンより最新のバージョンを使いたい、指定したバージョンを使いたい場合に使用する。

azure/setup-kubectl

特定のバージョンのkubectl をダウンロードしパスを設定するアクション。内部の処理ではInput で指定したkubectl のバージョンをダウンロードし、actions/core のaddPath 関数でパスを設定する。GitHub ホステッドランナーに導入されているkubectl のバージョンより最新のバージョンを使いたい、特定のバージョンを使いたい場合に使用する。

azure/k8s-artifact-substitute

Kubernetes マニフェスト内のコンテナイメージタグを一括で置換するアクション。単一または複数のマニフェストを指定可能。内部的にはforeach でマニフェスト内の指定したイメージタグをループして置換するため、特定の箇所だけイメージタグを更新することは不可。また、タグの置換をするだけのため、置換したタグのコンテナイメージが存在しなくても置換されるため注意。置換後のマニフェストのパスはoutput のmanifest に出力される。

azure/aks-create-action

Terraform またはPulumi を実行してAKS クラスターを作成するアクション。ARM (Bicep) は利用できない。デフォルトではTerraform が指定されている。最初にsetup 用スクリプトでリソースグループ、ストレージアカウント、サービスプリンパルの作成が必要となる。tfstate ファイルがストレージアカウントに配置され変更できない。内部的にはDocker カスタムアクションで、「terraform init」→「terraform plan」「terraform apply」を実行している。dev かtest のフォルダにあるtf ファイルを実行している。事前にディレクトリを配置しCLUSTER_SIZE でフォルダ名を指定すれば、特定のディレクトリ内のテンプレートファイルを実行できる。

azure/acr-build

Dockerfile からコンテナイメージを作成しAzure Container Registry に公開するアクション。Docker カスタムアクションを使い、コンテナ上でaz acr build コマンドを実行しACR に格納する。Azure へのログインやACR へアクセス、GitHub リポジトリ取得を行うため、サービスプリンシパルの情報とGitHub Apps のようなトークンが必要。ACR のタスク機能を使うため、サービスプリンシパルに対象ACR のContributor 権限またはタスク実行用の権限を設定したカスタムロールが必要となる。

今回の構成

今回は事前に作成したAzure Container Registry (以下ACR) にコンテナイメージを格納し、格納したコンテナイメージをAKS クラスターにデプロイするところまでを行います。本構成のフォルダ構成は以下となります。

.
├── .github
│   └── workflows
│        └── aks-build-and-deploy.yaml
├── Dockerfile
├── README.md
├── html
│   └── index.html
├── manifests
│   └── aks-demo.yaml
└── nginx
    └── nginx.conf

今回使うDockerfile とサンプルHTML ファイル、Nginx 設定ファイル、Kubernetes マニフェストは以下となります。

FROM nginx:alpine

# HTML、Nginx設定ファイルを配置する
COPY html /usr/share/nginx/html
COPY nginx/nginx.conf /etc/nginx/nginx.conf

# 80番ポートで待ち受けする
EXPOSE 80

# Nginxを起動する
CMD ["nginx", "-g", "daemon off;"]
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hello World</title>
</head>
<body>
    <h1>Hello World!</h1>
</body>
</html>
user  nginx;
worker_processes auto;

events { worker_connections 1024; }

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    sendfile      on;
    keepalive_timeout 65;

    include /etc/nginx/conf.d/*.conf;

    server {
        listen 80;
        server_name localhost;

        location / {
            root /usr/share/nginx/html;
            index index.html;
        }
    }
}
apiVersion: apps/v1
kind: Deployment
metadata:
  name: aks-demo
  namespace: default
  labels:
    app: aks-demo
spec:
  replicas: 2
  selector:
    matchLabels:
      app: aks-demo
  template:
    metadata:
      labels:
        app: aks-demo
    spec:
      containers:
      - name: aks-demo
        image: acraksghatest.azurecr.io/repos/aks-demo:latest
        imagePullPolicy: Always
        ports:
        - containerPort: 80

---
apiVersion: v1
kind: Service
metadata:
  name: aks-demo-svc
spec:
  type: LoadBalancer
  selector:
    app: aks-demo
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

今回作成するGitHub Actions ワークフローの処理の流れは以下となります。

  1. コンテナイメージをビルドしACR に格納する (acr-build)
  2. AKS の資格情報を取得する (aks-set-context)
  3. Kubernetes マニフェストのイメージタグを書き換える (k8s-artifact-substitute)
  4. kubeconform、dry-run で動作に問題が無いか確認する (k8s-lint)
  5. AKS にKubernetes マニフェストをデプロイする (k8s-deploy)

GitHub Actions 用の各種リソースの作成

初めに、GitHub Actions でAKS およびACR 関連のタスクを実行するために必要なAzure リソースを作成します。

# 各種変数を定義する
RESOURCE_GROUP_NAME="rg-aksghatest"
CONTAINER_REGISTRY_NAME="acraksghatest"
KUBERNETES_SERVICE_NAME="aks-aksghatest"
SERVICE_PRINCIPAL_NAME="sp-aksghatest"
LOCATION="japaneast"

# リソースグループを作成する
az group create --name $RESOURCE_GROUP_NAME --location $LOCATION

# ACRを作成する
ACR_ID=$(az acr create \
    --resource-group $RESOURCE_GROUP_NAME \
    --name $CONTAINER_REGISTRY_NAME \
    --sku Basic \
    --location $LOCATION \
    --query id -o tsv)

# AKSクラスターを作成する
# ACRからイメージを取得するためAKS作成時にアタッチしAcrPull権限を付与する
AKS_ID=$(az aks create \
    --resource-group $RESOURCE_GROUP_NAME \
    --name $KUBERNETES_SERVICE_NAME \
    --kubernetes-version 1.34.1 \
    --node-count 1 \
    --enable-cluster-autoscaler \
    --min-count 1 \
    --max-count 1 \
    --node-vm-size Standard_D4s_v4 \
    --nodepool-name nodepool1 \
    --vm-set-type VirtualMachineScaleSets \
    --generate-ssh-keys \
    --attach-acr $CONTAINER_REGISTRY_NAME \
    --query id -o tsv)

リソース作成後、GitHub Actions で利用するサービスプリンシパルを作成します。今回はACR へのイメージ格納のためにACR の共同作成者とAKS デプロイのためにAKS 共同作成者を付与します。

# GitHub Actions用のサービスプリンシパルを作成する
# appId、password、tenantの値が表示されるためメモする
SUBSCRIPTION_ID=$(az account show --query id -o tsv)
RESOURCEGROUP_SCOPE="/subscriptions/${SUBSCRIPTION_ID}/resourceGroups/${RESOURCE_GROUP_NAME}"
az ad sp create-for-rbac \
    --name "$SERVICE_PRINCIPAL_NAME" \
    --role Reader \
    --scopes "$RESOURCEGROUP_SCOPE" \
    --query "{appId: appId, password: password, tenant: tenant}" \
    -o json
APP_ID="<appIdで出力された値>"

# ACR、AKSのリソースIDを取得する
CONTAINER_REGISTRY_SCOPE=$(az acr show \
  --resource-group "$RESOURCE_GROUP_NAME" \
  --name "$CONTAINER_REGISTRY_NAME" \
  --query id -o tsv)

KUBERNETES_SERVICE_SCOPE=$(az aks show \
  --resource-group "$RESOURCE_GROUP_NAME" \
  --name "$KUBERNETES_SERVICE_NAME" \
  --query id -o tsv)

# コンテナイメージをACRにPull/Pushするための権限を付与する
# ArcPushではACRのタスクを実行できないため、ACRを指定してContributor権限を付与する
az role assignment create \
  --assignee "${APP_ID}" \
  --role "Contributor" \
  --scope "${CONTAINER_REGISTRY_SCOPE}"

# AKSクラスターへデプロイするための権限を付与する
az role assignment create \
    --assignee "${APP_ID}" \
    --role "Azure Kubernetes Service Cluster User Role" \
    --scope "${KUBERNETES_SERVICE_SCOPE}"

デプロイ用のGitHub Actions ワークフローを作成

Azure リソース、リポジトリの準備後、GitHub Actions のワークフローを作成します。今回はコンテナイメージのビルド、Push とAKS へのデプロイでジョブを分割します。

name: Build and Deploy to AKS

on:
  workflow_dispatch:
    inputs:
      image_tag:
        description: 'Image tag'
        required: true
env:
  AZURE_CREDENTIALS: '{"clientId":"${{ secrets.AZURE_CLIENT_ID }}","clientSecret":"${{ secrets.AZURE_CLIENT_SECRET }}","subscriptionId":"${{ secrets.AZURE_SUBSCRIPTION_ID }}","tenantId":"${{ secrets.AZURE_TENANT_ID }}"}'

jobs:
  image-build:
    name: Build and Push Docker Image to ACR
    runs-on: ubuntu-latest
    timeout-minutes: 10
    steps:
      - name: Checkout repository
        uses: actions/checkout@v6

      # コンテナイメージをビルドしACRに格納する
      # Dockerカスタムアクション内でAzureのログインをするため事前のログインは不要
      - name: Build and Push Docker Image to ACR
        uses: azure/acr-build@v1
        with:
          service_principal: ${{ secrets.AZURE_CLIENT_ID }}
          service_principal_password: ${{ secrets.AZURE_CLIENT_SECRET }}
          tenant: ${{ secrets.AZURE_TENANT_ID }}
          registry: "acraksghatest"
          repository: "repos"
          image: "aks-demo"
          tag: ${{ github.event.inputs.image_tag }}
          dockerfile: ./Dockerfile
          git_access_token: ${{ secrets.GIT_ACCESS_TOKEN }}
          folder: ./
          branch: main
          
  deploy:
    name: Deploy to AKS
    runs-on: ubuntu-latest
    needs: image-build
    env:
      RESOURCE_GROUP_NAME: 'rg-aksghatest'
      AKS_CLUSTER_NAME: 'aks-aksghatest'
    timeout-minutes: 10
    steps:
      - name: Checkout repository
        uses: actions/checkout@v6

      # サービスプリンシパルを使いAzure にログインする
      - name: Azure Login
        uses: azure/login@v2
        with:
          creds: ${{ env.AZURE_CREDENTIALS }}

      # AKSの資格情報を取得する
      - name: Set AKS context
        uses: azure/aks-set-context@v4
        with:
          resource-group: ${{ env.RESOURCE_GROUP_NAME }}
          cluster-name: ${{ env.AKS_CLUSTER_NAME }}

      # Kubernetesマニフェストのタグを書き換える
      - name: Update image tag in Kubernetes manifest
        id: update-manifest
        uses: Azure/k8s-artifact-substitute@v2
        with:
          manifests: |
            manifests/aks-demo.yaml
          images: |
            acraksghatest.azurecr.io/repos/aks-demo:${{ github.event.inputs.image_tag }}

      # 書き換え後のKubernetesマニフェストをチェックする
      # azure/k8s-lintはkubeconformとdry-runを同時実行できないため分割する
      - name: Check updated Kubernetes manifest with kubeconform
        uses: azure/k8s-lint@v3
        with:
          lintType: kubeconform
          manifests: |
            ${{ steps.update-manifest.outputs.manifests }}
          kubeconformOpts: -summary

      - name: Dry-run updated Kubernetes manifest
        uses: azure/k8s-lint@v3
        with:
          lintType: dryrun
          manifests: |
            ${{ steps.update-manifest.outputs.manifests }}

      # AKSにデプロイする
      - name: Deploy to AKS
        uses: azure/k8s-deploy@v5
        with:
          resource-group: ${{ env.RESOURCE_GROUP_NAME }}
          name: ${{ env.AKS_CLUSTER_NAME }}
          action: deploy
          strategy: basic
          manifests: |
            ${{ steps.update-manifest.outputs.manifests }}

Azure へログインするためのシークレットにつきましては、GitHub リポジトリのシークレットとして登録しています。各シークレットには以下の値を登録してください。また、今回はACR のビルドアクションを利用するため、GitHub Apps のトークンを作成しておいてください。

シークレット名

AZURE_CLIENT_ID

サービスプリンシパルのappID の値

AZURE_CLIENT_SECRET

サービスプリンシパルのpassword の値

AZURE_TENANT_ID

サービスプリンシパルのtenant の値

AZURE_SUBSCRIPTION_ID

サブスクリプションのID

GIT_ACCESS_TOKEN

GitHub Apps のトークン

もしコンテナイメージの取得やPod が正常に起動しない場合、以下の項目を確認してみてください。

  • 各種設定ファイルの内容を適切に設定できているか?
  • ACR をAKS にアタッチできているか?
  • ACR のサーバー名、リポジトリ名、タグが適切に設定できているか?

動作検証

デプロイ後、ServiceのIPアドレスでアクセスすると、デプロイしたHTML ファイルが表示されます。

リソースのクリーンアップ

AKS のコンテナイメージ作成からデプロイまで確認後、リソースが不要な方は検証で使ったリソースを削除します。

# サービスプリンシパルを削除する
az ad sp delete --id $(az ad sp list --display-name "$SERVICE_PRINCIPAL_NAME" --query "[0].appId" -o tsv)

# リソースグループを削除する
az group delete --name $RESOURCE_GROUP_NAME --yes

まとめ

  • GitHub Actions ではMicrosoft が提供するAzure Container Registry のビルドやAzure Kubernetes Service のデプロイに関するカスタムアクションが提供されている
  • カスタムアクションを利用することで、GitHub Actions ワークフローの記述を簡素化できる
  • az acr build はAzure Container Registry のタスク機能を利用しているため、AcrPull ではなくContributor 権限が必要となる
  • AKS のデプロイアクションでは、基本的なkubectl apply だけでなくカナリアやブルーグリーンといったデプロイもできる

参考資料