APC 技術ブログ

株式会社エーピーコミュニケーションズの技術ブログです。

株式会社 エーピーコミュニケーションズの技術ブログです。

【Microsoft Build速報】AKS 関連のアップデート、Draft を使ってみました

はじめに

こんにちは、ACS事業部の吉川です。
Microsoft Build、ご覧になられていますでしょうか。
私の所属するACS事業部では、Azure のコンテナサービスを中心にお客様の内製化を支援しています。

www.ap-com.co.jp

業務的に関連が深いこともあり、Microsoft Build においても特にコンテナ関連のアップデートに注目していました。
その中でこんな内容を目にしました。

Draft 2を使えば、開発者はアプリの作成、コンテナ化、Kubernetesへのデプロイを行うことができます。

news.microsoft.com

azure.microsoft.com

azure.microsoft.com

Draft 2 とはどういったものでしょうか?
試しに少し触ってみましたので、簡単にレポートします。
使用にあたっては公式の英語版ドキュメントを参考にしています。

docs.microsoft.com

Draft とは

Draft は2017年に Microsoft が公開したコンテナアプリケーションの構築ツールです。

mag.osdn.jp

開発言語を自動で判別してDockerfileを生成、Kubernetesへのデプロイができるなど、デベロッパーがよりアプリ開発に注力できるような支援ツールです。 Microsoft が買収したDeis社の技術をベースとして開発されていたものが、この度バージョン2としてリブートした模様です。

github.com

もともと https://github.com/Azure/draftv2 というリポジトリ名だったものが、https://github.com/Azure/draft に改名されたようです。v1 は draft-classic として以下のリポジトリで公開されています。

github.com

本記事では以降 Draft 2 のことを Draft と表記します。

Draft の利用準備

Draftは Azure CLI にプレビュー機能として統合されています。
プレビュー機能を有効にするために、以下のコマンドを実行します。

# Azure CLIの最新化
az upgrade
# プレビュー機能の有効化
az extension add --name aks-preview
# 過去にプレビュー機能を有効化していた場合は、以下のコマンドで更新する
az extension update --name aks-preview

GitHub CLIも必要です。事前にインストールしておきましょう。

cli.github.com

draft create - Dockerfile/Manifests の自動生成

環境準備が終わったら実際に Draft を試してみましょう。
サンプルとして以下の Python ファイルを準備しました。Python の http.server ドキュメント からの引用です。

import http.server
import socketserver

PORT = 8000

Handler = http.server.SimpleHTTPRequestHandler

with socketserver.TCPServer(("", PORT), Handler) as httpd:
    print("serving at port", PORT)
    httpd.serve_forever()

作業用にディレクトリを作り、この Python ファイルを配置します。合わせて requirements.txt も作成しておきます。(中身は空でOK)

vi app.py
touch requirements.txt

以下のようなファイル配置です。

.
├── app.py
└── requirements.txt

このディレクトリ内で以下のコマンドを実行します。

az aks draft create

対話形式でプロンプトが表示されます。必要な内容を入力していきましょう。

[Draft] --- Detecting Language ---
[Draft] --> Draft detected Python (100.000000%)

[Draft] --- Dockerfile Creation ---
# Dockerfile 内で EXPOSE するポート番号を入力
✔ Please Enter the port exposed in the application: 8000
[Draft] --> Creating Dockerfile...

[Draft] --- Deployment File Creation ---
Use the arrow keys to navigate: ↓ ↑ → ←
# Kubernetes のデプロイファイルの形式を選択。今回は manifests を選択しました。
? Select k8s Deployment Type:
    helm
    kustomize
  ▸ manifests
# Kubernetes の Pod の公開ポート番号を入力
✔ Please Enter the port exposed in the application: 8000
# Kubernetes 上でのアプリケーションの名前を入力
✔ Please Enter the name of the application: draftapp
[Draft] --> Creating manifests Kubernetes resources...

[Draft] Draft has successfully created deployment resources for your project 😃
[Draft] Use 'draft setup-gh' to set up Github OIDC.

コマンドの実行が完了すると、Dockerfileとマニフェストが生成されています。

.
├── .dockerignore
├── Dockerfile
├── app.py
├── manifests
│   ├── deployment.yaml
│   └── service.yaml
└── requirements.txt

Dockerfile

FROM python
ENV PORT 8000
EXPOSE 8000
WORKDIR /usr/src/app

COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

ENTRYPOINT ["python"]
CMD ["app.py"]

manifests/deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: draftapp
  labels:
    app: draftapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: draftapp
  template:
    metadata:
      labels:
        app: draftapp
    spec:
      containers:
        - name: draftapp
          image: draftapp
          ports:
            - containerPort: 8000

manifests/service.yaml

apiVersion: v1
kind: Service
metadata:
  name: draftapp
spec:
  type: LoadBalancer
  selector:
    app: draftapp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8000

ファイルが生成されました!

draft setup-gh - GitHub Actions 用 OIDC 自動設定

続いての機能 setup-gh は、GitHub Actions の OpenID Connect の設定を自動で行ってくれます。
Azure AD へのアプリ/サービスプリンシパルの登録と、GitHub への認証情報の登録を 1 コマンドで実行してくれるのでとっても便利です。

が、現状では draft のバイナリにバグがありうまく動きません。(当方が試した限り v0.0.20 ではサービスプリンシパルの作成あたりでエラーになってしまいます)
以下の Pull Request で修正されており main ブランチにマージ済みのため、まもなく修正版バイナリがリリースされると思われます。

github.com

早く試したかったので、バイナリをビルドして動かしてみます。ビルドには Go 1.18.x が必要です。

git clone git@github.com:Azure/draft.git
cd draft
make
# Azure CLI が利用している draft バイナリを置き換え
cp draft ~/.aksdraft/draft-linux-amd64

あらかじめ Azure のリソースグループと GitHub のリポジトリを作成しておく必要があります。以下のように作成しておきましょう。

# Azure リソースグループ作成
az group create -n rg-draft -l japaneast
# draft-sample という名前のプライベート リポジトリを作成
gh repo create draft-sample --private

準備ができたら draft setup-gh を実行してみましょう。

az aks draft setup-gh

以下のように対話形式で進んでいきます。

# draft のバイナリを新しいもので置き換えるか。上記手順でビルドしたものを利用するので N を選択する。
We have detected a newer version of Draft. Would you like to download it? (y/N):
# Azure AD に登録するアプリの名前を入力
✔ Enter app registration name: for-gh-workflow
# Azure サブスクリプションを選択する
Use the arrow keys to navigate: ↓ ↑ → ←
✔ ########-####-####-####-############
? Please choose the subscription ID you would like to use.:
# Azure リソースグループの名前を入力
✔ Enter resource group name: rg-draft
# GitHub リポジトリの名前を入力
✔ Enter github organization and repo (organization/repoName): <GitHub ユーザー名>/draft-sample

[Draft] Draft has successfully set up Github OIDC for your project 😃
[Draft] Use 'draft generate-workflow' to generate a Github workflow to build and deploy an application on AKS.

完了すると Azure AD 側ではアプリの作成とフェデレーション情報の登録が完了しており、
GitHub 側では Secret が登録されています。

割と面倒な OpenID Connect の登録がサクサク行えるのはとてもイイですね!

draft generate-workflow - GitHub Actions のワークフロー生成

最後に紹介する機能は GitHub Actions のワークフロー生成機能です。

事前に Azure Container Registry(ACR) と AKS クラスターを作成しておきます。

# ACR 作成
az acr create -g rg-draft -n drafttestregistry --sku Basic
# AKS クラスター作成
az aks create -g rg-draft -n draft-test-cluster --node-count 1

先ほど az aks draft create を実行したディレクトリ内で、以下のコマンドを実行してみましょう。

az aks draft generate-workflow

対話式のプロンプトが開始されますので、順に入力していきます。

# draft のバイナリを新しいもので置き換えるか。上記でビルドしたものを利用するので N を選択する。
We have detected a newer version of Draft. Would you like to download it? (y/N):
# ACR 名を入力
✔ Please enter container registry name: drafttestregistry
# ビルドするコンテナの名前を入力
✔ Please enter container name: draftapp
# AKS クラスターのリソースグループ名を入力
✔ Please enter cluster resource group name: rg-draft
# AKS クラスター名を入力
✔ Please enter AKS cluster name: draft-test-cluster
# ワークフローの対象とするブランチ名を入力。今回は main としています。
✔ Please enter name of the repository branch to deploy from, usually main: main

[Draft] Draft has successfully generated a Github workflow for your project 😃

完了すると、以下のようにワークフローファイルが生成されています。

.
├── .dockerignore
├── .github
│   └── workflows
│       └── azure-kubernetes-service.yml
├── Dockerfile
├── app.py
├── manifests
│   ├── deployment.yaml
│   └── service.yaml
└── requirements.txt

.github/workflows/azure-kubernetes-service.yml

name: Build and deploy an app to AKS
"on":
    push:
        branches:
            - main
    workflow_dispatch: null
env:
    AZURE_CONTAINER_REGISTRY: 'drafttestregistry'
    CLUSTER_NAME: draft-test-cluster
    CONTAINER_NAME: draftapp
    DEPLOYMENT_MANIFEST_PATH: ./manifests
    IMAGE_PULL_SECRET_NAME: drafttestregistry secret
    RESOURCE_GROUP: rg-draft
jobs:
    buildImage:
        permissions:
            contents: read
            id-token: write
        runs-on: ubuntu-latest
        steps:
            - uses: actions/checkout@v3
            - name: Azure login
              uses: azure/login@v1.4.3
              with:
                client-id: ${{ secrets.AZURE_CLIENT_ID }}
                subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
                tenant-id: ${{ secrets.AZURE_TENANT_ID }}
            - name: Build and push image to ACR
              run: |
                az acr build --image ${{ env.AZURE_CONTAINER_REGISTRY }}.azurecr.io/${{ env.CONTAINER_NAME }}:${{ github.sha }} --registry ${{ env.AZURE_CONTAINER_REGISTRY }} -g ${{ env.RESOURCE_GROUP }} .
    createSecret:
        permissions:
            contents: read
            id-token: write
        runs-on: ubuntu-latest
        steps:
            - name: Azure login
              uses: azure/login@v1.4.3
              with:
                client-id: ${{ secrets.AZURE_CLIENT_ID }}
                subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
                tenant-id: ${{ secrets.AZURE_TENANT_ID }}
            - name: Get K8s context
              uses: azure/aks-set-context@v2.0
              with:
                cluster-name: ${{ env.CLUSTER_NAME }}
                resource-group: ${{ env.RESOURCE_GROUP }}
            - id: get-acr-creds
              name: Get ACR credentials
              run: |
                az acr update -n ${{ env.AZURE_CONTAINER_REGISTRY }} -g ${{ env.RESOURCE_GROUP }} --admin-enabled true
                ACR_USERNAME=$(az acr credential show -g ${{ env.RESOURCE_GROUP }} -n ${{ env.AZURE_CONTAINER_REGISTRY }} --query username -o tsv)
                ACR_PASSWORD=$(az acr credential show -g ${{ env.RESOURCE_GROUP }} -n ${{ env.AZURE_CONTAINER_REGISTRY }} --query passwords[0].value -o tsv)
                echo "::add-mask::${ACR_USERNAME}"
                echo "::set-output name=username::${ACR_USERNAME}"
                echo "::add-mask::${ACR_PASSWORD}"
                echo "::set-output name=password::${ACR_PASSWORD}"
            - name: Create K8s secret for pulling image from ACR
              uses: Azure/k8s-create-secret@v1.1
              with:
                container-registry-password: ${{ steps.get-acr-creds.outputs.password }}
                container-registry-url: ${{ env.AZURE_CONTAINER_REGISTRY }}.azurecr.io
                container-registry-username: ${{ steps.get-acr-creds.outputs.username }}
                secret-name: ${{ env.IMAGE_PULL_SECRET_NAME }}
    deploy:
        permissions:
            actions: read
            contents: read
            id-token: write
        runs-on: ubuntu-latest
        needs:
            - buildImage
            - createSecret
        steps:
            - uses: actions/checkout@v3
            - name: Azure login
              uses: azure/login@v1.4.3
              with:
                client-id: ${{ secrets.AZURE_CLIENT_ID }}
                subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
                tenant-id: ${{ secrets.AZURE_TENANT_ID }}
            - name: Get K8s context
              uses: azure/aks-set-context@v2.0
              with:
                cluster-name: ${{ env.CLUSTER_NAME }}
                resource-group: ${{ env.RESOURCE_GROUP }}
            - name: Deploys application
              uses: Azure/k8s-deploy@v3.1
              with:
                action: deploy
                imagepullsecrets: ${{ env.IMAGE_PULL_SECRET_NAME }}
                images: |
                    ${{ env.AZURE_CONTAINER_REGISTRY }}.azurecr.io/${{ env.CONTAINER_NAME }}:${{ github.sha }}
                manifests: ${{ env.DEPLOYMENT_MANIFEST_PATH }}

リポジトリにPushして、動作を確認してみます。

git init
git add -A
git commit -m "first commit"
git branch -M main
git remote add origin git@github.com:<GitHubユーザー名>/draft-sample.git
git push -u origin main

Push をトリガーにジョブが起動し、
コンテナイメージのビルド&ACR への Push が行われ、
AKS へのデプロイまで行われます。

超・簡・単!

おわりに

Draft を使うことで、コンテナイメージの作成/AKS へデプロイがとっても簡単になります。
対話形式で必要情報を入力していくので、使い方もわかり易く Kubernetes に自信のない方でも比較的使いやすい形で提供されています。
まだプレビューということで一部動作に不安もありますが、今後に期待できそうな機能です。ぜひ使ってみてください!