自作のWindowsアプリをAKSに載せるキホン技 #Azure リレー

先週の櫻井さんの スケーラブルな負荷テスト環境をPipelineで必要なときに必要な量だけ作る! – JMeter / ACI / Terraform / Azure Pipeline - #Azure リレー に引き続き、 毎週水曜日にAzure関連の記事を挙げる Azure リレー第6回を担当します。

こんにちは、名古屋事業所勤務の松枝です。

Azure Kubernetes Service(以降、AKS)はWindowsコンテナの使用できる構成を作成することができます。
(記事公開時点ではパブリックプレビュー)
Windowsコンテナが使えるAKSを用意して、アプリを動かしてみましょう。

アプリの作成からインフラの作成まで一通り必要な手順を書いてみましたので、この記事をベースにWindowsコンテナの世界に入門していただけたらと思います。
また、アプリ開発、コンテナ作成、AKS作成を一通り記載しているので、例えばアプリ開発は知識があるけどインフラはちょっと・・・という場合に部分的に参照していただけると嬉しいです。

Azure Cloud Shellとはなんぞや?などの細かい説明は省いていますので、適宜調べながら読み進めていただけたらと思います。

概要

  • (Windows環境でしか動作しない)アプリケーションを作成します
  • アプリケーションを載せたコンテナイメージを作成します
  • コンテナイメージをコンテナレジストリ(ACR)に格納します
  • Windowsコンテナが動作するAKSを作成します
  • マニフェストファイルを使用して、AKS上でコンテナを動かします

Webアプリの作成

<作業環境の想定:手元のWindows PC>

Web上に公開されているサンプルアプリを使っても良いんですが、現実は自社で作成したアプリなどを使用すると思うので、Webアプリの作成からサラッと見てみましょう。
Windowsコンテナが必要なケースは、Windowsでしか動作しないアプリ、例えば.NET Frameworkのアプリを使用している場合だと思われます。.NET FrameworkのASP.NET MVCアプリを作っておきましょう。

下記サイトからVisual Studioのインストーラをダウンロードします。
https://visualstudio.microsoft.com/ja/downloads/

インストーラを起動し、「ASP.NETとWeb開発」を選択してインストールします。

インストールが成功したら、新規プロジェクトを起動して、C#のASP.NET MVCアプリを作成しましょう。

ちょっと古めのアプリを載せる想定だと思いますので、.NET Frameworkは「4.5.2」辺りが良いでしょうか。プロジェクト名は適当で良いので、「MVC」のアプリを作成してください。

アプリが作成されたら、Visual Studioのソリューションエクスプローラーから、Views/Home/Index.cshtmlを開き、適当な加工を加えて実行してみてください。例えば下記のような感じでザックリいきましょう。

@{
    ViewBag.Title = "コンテナアプリのデモ";
}

<div class="jumbotron">
    <h1>ASP.NET</h1>
    <p class="lead">コンテナでWebアプリを動かしてみよう</p>
</div>

F5キーでアプリの正常動作を確認したら、アプリケーションを発行しましょう。

Webアプリケーションのプロジェクトを右クリックし、「発行」を選ぶと、「公開先の選択」の画面が出ます。
ここで公開先に「フォルダ―」を選び、表示される通り「bin\Release\Publish」に公開する状態で「プロファイルの作成」を押してください。

プロファイルの作成が終わったら画面上に発行用のビューが出ているはずなので、「発行」ボタンを押してください。
これでアプリケーションの準備が完了しました!

サービスプリンシパルの作成

<作業環境の想定:Azure Cloud Shell>

VMでの作業用に、権限を限定したサービスプリンシパルを作成して進めます。

下記のコマンドを実行し、AKSを作成する対象のサブスクリプションIDでのContributor権限を持つサービスプリンシパルを作成します。

az ad sp create-for-rbac --role="Contributor" --scopes="/subscriptions/【サブスクリプションID】"

コマンドを実行すると、自動で生成されたIDやパスワードが表示されますので、表示された値を安全な方法で保管してください。

作業用VMの作成

<作業環境の想定:Azureポータル、作業用VM>

コンテナイメージの作成をするためにVMを用意しましょう。
ちなみに記事執筆時点では、AKS上で動作するWindowsコンテナはWindows Server 2019系列のものだけです。
記事執筆時点ではAKSはプロセス分離モードしか使用できないため、Windows Server 2019 Datacenter辺りのVMを用意することが必要です。
Azureポータルから適当なWindows Server 2019のVMを作成します。あまり性能は要らないはずですが、D2s v3くらいのサイズにしておくと後悔が無いかと思います。設定はデフォルトで良いと思いますが、診断ログや自動停止などはお好みで。

VMが作成できたら、 VMのWindows Updateを実施してください。

Windows Updateの適用が完了したら、Docker EEの導入のため、PowerShellで下記のコマンドを実行します(VMが再起動します)。

Install-Module -Name DockerMsftProvider -Repository PSGallery -Force
Install-Package -Name Docker -ProviderName DockerMsftProvider -Force
Restart-Computer -Force

また、Azureが操作できるよう、az cliをインストールしましょう。下記のコマンドを実行します。

Invoke-WebRequest -Uri https://aka.ms/installazurecliwindows -OutFile .\AzureCLI.msi; Start-Process msiexec.exe -Wait -ArgumentList '/I AzureCLI.msi /quiet'

Dockerfileの作成

<作業環境の想定:作業用VM>

作成したVMに下記のDockerfileを用意します。

# escape=`

FROM mcr.microsoft.com/dotnet/framework/runtime:4.8-windowsservercore-ltsc2019

SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

RUN Add-WindowsFeature Web-Server; `
    Add-WindowsFeature NET-Framework-45-ASPNET; `
    Add-WindowsFeature Web-Asp-Net45; `
    Remove-Item -Recurse C:\inetpub\wwwroot\*; `
    Invoke-WebRequest -Uri https://dotnetbinaries.blob.core.windows.net/servicemonitor/2.0.1.6/ServiceMonitor.exe -OutFile C:\ServiceMonitor.exe

# Install Roslyn compilers and ngen binaries
RUN Invoke-WebRequest https://api.nuget.org/packages/microsoft.net.compilers.2.9.0.nupkg -OutFile c:\microsoft.net.compilers.2.9.0.zip; `
    Expand-Archive -Path c:\microsoft.net.compilers.2.9.0.zip -DestinationPath c:\RoslynCompilers; `
    Remove-Item c:\microsoft.net.compilers.2.9.0.zip -Force; `
    &C:\Windows\Microsoft.NET\Framework64\v4.0.30319\ngen.exe install c:\RoslynCompilers\tools\csc.exe /ExeConfig:c:\RoslynCompilers\tools\csc.exe | `
    &C:\Windows\Microsoft.NET\Framework64\v4.0.30319\ngen.exe install c:\RoslynCompilers\tools\vbc.exe /ExeConfig:c:\RoslynCompilers\tools\vbc.exe | `
    &C:\Windows\Microsoft.NET\Framework64\v4.0.30319\ngen.exe install c:\RoslynCompilers\tools\VBCSCompiler.exe /ExeConfig:c:\RoslynCompilers\tools\VBCSCompiler.exe | `
    &C:\Windows\Microsoft.NET\Framework\v4.0.30319\ngen.exe install c:\RoslynCompilers\tools\csc.exe /ExeConfig:c:\RoslynCompilers\tools\csc.exe | `
    &C:\Windows\Microsoft.NET\Framework\v4.0.30319\ngen.exe install c:\RoslynCompilers\tools\vbc.exe /ExeConfig:c:\RoslynCompilers\tools\vbc.exe | `
    &C:\Windows\Microsoft.NET\Framework\v4.0.30319\ngen.exe install c:\RoslynCompilers\tools\VBCSCompiler.exe  /ExeConfig:c:\RoslynCompilers\tools\VBCSCompiler.exe

ENV ROSLYN_COMPILER_LOCATION c:\RoslynCompilers\tools

WORKDIR C:\inetpub\wwwroot
COPY ${source:-Publish} .

EXPOSE 80

ENTRYPOINT ["C:\ServiceMonitor.exe", "w3svc"]

WindowsコンテナでIISを使用するシンプルなDockerfileです。

.NET Frameworkを動かすため、Windows ServerCoreのベースイメージを使用します。
IISを使用するため、必要な機能を追加し、ENTRYPOINTで使用するServiceMonitorを導入しています。

C:\Work\Dockerfile に保存しましょう。

コンテナイメージの作成

<作業環境の想定:作業用VM>

ビルドしたアプリをDockerfileと同じ場所(C:\Work)にコピーしましょう。
Visual Studioのソリューションエクスプローラーでプロジェクトを右クリックし、「エクスプローラーでフォルダを開く」を選ぶと、プロジェクトの場所が表示されます。bin/Release/Publishフォルダをコピーし、VMのC:\Work内に貼り付けしてください。

PowerShell等で下記のコマンドを実行したら、testcontainer というイメージ名のコンテナイメージが作成されます。

cd C:\Work
docker build -t testcontainer .

結構時間がかかりますが、処理が終わったら完了です。
正常終了なら、メッセージの最後に下記のような内容が出るはずです。

Successfully built xxxxxxxx
Successfully tagged testcontainer:latest

軽くコンテナの動作を確認してみましょう。
下記のコマンドを実行し、コンテナイメージからコンテナを作成します。

docker run -itd testcontainer

コマンドから復帰したら、下記のコマンドで実行中のコンテナのIPアドレスを取得しましょう。

docker exec -it (docker ps -q -f "ancestor=testcontainer") powershell ipconfig

このコマンドで、docker ps で実行中のコンテナを検索し、そのIDを取得し、そのIDのコンテナにログインして ipconfig コマンドを実行しています。

得られたIPv4 Addressの値にVMのブラウザからアクセスしてみましょう。
Visual Studioからデバッグ実行した時と同じ画面が見れましたか?

ACRの作成

<作業環境の想定:Azureポータル>

AzureポータルからACRを作成します。
管理者ユーザーは無効、SKUはBasicで構いません。

ACRへのイメージのプッシュ

<作業環境の想定:作業用VM>

コンテナイメージを作成したVMに戻り、ACRにコンテナイメージをPushします。

ACRにアクセスする場合、azコマンドに対して認証情報を設定する必要があります。
下記のPowerShellを実行してください。

az login --service-principal --username 【サービスプリンシパルのappIdの値】 --password 【サービスプリンシパルのpasswordの値】 --tenant 【サービスプリンシパルのtenantの値】
az acr login --name 【作成したACRのレジストリ名】

成功したら、下記のコマンドを実行し、ACRへイメージをプッシュします。

docker tag testcontainer:latest 【作成したACRのレジストリ名】.azurecr.io/testcontainer:latest
docker push 【作成したACRのレジストリ名】.azurecr.io/testcontainer

AzureポータルでACRを開くと、リポジトリのビューにプッシュしたイメージが表示されます。
と言っても文字情報なので、今は「ふ~ん・・」としか言えないですね。

Windowsコンテナが使用可能なAKSの作成

<作業環境の想定:Azure Cloud Shell>

下記の記事に従い、Windowsコンテナが使用可能なAKSを作成しましょう。
https://docs.microsoft.com/ja-jp/azure/aks/windows-container-cli

手順を転記するとあまりに冗長なので省略します。
下記の記事まで、ほぼそのままAzure Cloud Shellで実行してください。

https://docs.microsoft.com/ja-jp/azure/aks/windows-container-cli#connect-to-the-cluster

kubectl get nodes を実行してノードの一覧が表示されること、 kubectl get pods を実行してPodが何もデプロイされていないことを確認します。

続いて、AKSがACRからコンテナイメージをダウンロードできるよう、ACRをAKSにアタッチします。

 az aks update -n myAKSCluster -g myResourceGroup --attach-acr 【ACR名】

マニフェストファイルの作成

<作業環境の想定:Azure Cloud Shell>

Webアプリを使用するためのマニフェストファイルを用意します。
Azure Cloud Shell上でそのままviコマンド等を使って作成してください。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: application
  labels:
    app: application
spec:
  replicas: 1
  template:
    metadata:
      name: application
      labels:
        app: application
    spec:
      nodeSelector:
        "beta.kubernetes.io/os": windows
      containers:
        - name: application
          image: 【作成したACRのレジストリ名】.azurecr.io/testcontainer:latest
          resources:
            limits:
              cpu: 400m
              memory: 800M
            requests:
              cpu: 400m
              memory: 800M
          ports:
            - containerPort: 80
  selector:
    matchLabels:
      app: application
---
apiVersion: v1
kind: Service
metadata:
  name: application
spec:
  type: LoadBalancer
  ports:
    - protocol: TCP
      port: 80
  selector:
    app: application

マニフェストファイルの適用と確認

<作業環境の想定:Azure Cloud Shell>

マニフェストファイルの適用をするため、Azure Cloud Shellから下記のコマンドを実行します。

kubectl apply -f 【作成したマニフェストファイル】

成功するとPodが作成されますので、 kubectl get pods で作成したPodのSTATUSを確認しましょう。

10分くらいしてPodのSTATUSがContainerCreatingからRunningになったら、Webアプリが見れることを確認しましょう。
下記のコマンドで、Podに外からアクセスするためのServiceの情報が取得できます。

kubectl get services

EXTERNAL-IPに記載されたグローバルIPに、手元のPCのブラウザからアクセスしてみてください。

上手くいきましたか?

まとめ

サクッとやれることを示したかったんですが、結構長大になってしまいました。
覚えることは多いですが、一つひとつの技術的な難易度はお試しで使う分にはあまり高くありませんので、まずはこの記事を参考に動くものを見ていただいて、それから順に深堀して勉強していただけたらと思います。
Windowsコンテナの使えるAKSを活用していただける方が増えると嬉しいです。

FIXER Inc. 松枝 宏樹
  • FIXER Inc. 松枝 宏樹
  • 名古屋事業所所属。
    得意分野はC#、ASP.NET、terraformなど。
    最近はdocker、K8s関連を勉強中。

%d人のブロガーが「いいね」をつけました。