ほりひログ

所属組織の製品 (Azure とか) に関連する内容が多めだけど、個人の見解であって、所属組織を代表する公式情報ではないです。

Azure App Serviceのマルチコンテナーを試してみた

ちょっと前のブログに、Azure App Service (Linux)でSidecarパターンが実装できる、という記事がポストされてた。

techcommunity.microsoft.com

Microsoft Build 2024のこのセッションでも紹介されてた(21:42から)。

build.microsoft.com

Sidecarパターン

ザックリSidecarパターンというのは、

  1. メインであるWeb アプリケーション
  2. 他のサービスとのやり取りとかログ記録とかのユーティリティ的な機能

というような機能を、それぞれ別のコンテナとして実装して、1.のコンテナーから2.のコンテナーを呼び出す設計パターンのこと。

learn.microsoft.com

これまで、App Serviceにデプロイできるカスタムコンテナーは基本的には一つだけだったけど、冒頭のブログ/Buildのセッションでは、App Serviceで複数のコンテナーをデプロイする仕組みの紹介してる。

# 実際はKuduやEasyAuth用途などのマネージドなコンテナーがアプリとは別にある。
# 後述するようにマルチコンテナーを動かす方法もある。

Bicep

仕組みとしては、ARMのレベルでいろいろ追加しているらしい。
ブログ内ではJSONのARMテンプレートが紹介されている。

BicepでSidecarパターンのApp Serviceを書くと、例えばメインコンテナー1つ、サイドカーコンテナー2つ、計3つのコンテナーをを動かす場合、こんな感じなる。

resource webApp 'Microsoft.Web/sites@2021-02-01' = {
  name: webAppName
  location: location
  properties: {
    serverFarmId: appServicePlan.id
    siteConfig: {
      linuxFxVersion: 'sitecontainers'                                   // ・・・ (a)
    }
  }
  resource mainApplicationContainer 'sitecontainers@2021-02-01' = {      // ・・・ (b)
    name: 'mainContainer'
    properties: {
      image: '<メインコンテナー>'                                        // ・・・ (c)
      targetPort: 80
      isMain: true                                                       // ・・・ (d)   trueなので、これがメインコンテナー
    }
  }
  resource sidecarContainer1 'sitecontainers@2021-02-01' = {
    name: 'sidecar1'
    properties: {
      image: '<サイドカーコンテナー1>'
      targetPort: 4000
      isMain: false                                                      // falseなのでサイドカーコンテナー 
    }
  }
  resource sidecarContainer2 'sitecontainers@2021-02-01' = {
    name: 'sidecar2'
    properties: {
      image: '<サイドカーコンテナー2>'
      targetPort: 5000
      isMain: false                                                      // falseなので サイドカーコンテナー
    }
  }
}

これまでのApp Serviceのテンプレートでは見ない点がいくつかある。

linuxFxVersion = sitecontainers

まずMicrosoft.Web/sites リソースの linuxFxVersion プロパティの値(上記Bicep内のa)が新しい。

これまでここには、コンテナーイメージやランタイムの情報、例えばnginx:latestとかNODE|20-ltsなどの値が入っていた。
今回のマルチコンテナーのApp Serviceの場合は、ここにsitecontainersという文字列が入る。

ちなみに、この sitecontainersを設定したApp ServiceをAzureポータルで開くとこう表示される。

Runtime Stackの値が-から始まっていたり、Publishing modelCodeになっているのは、まだポータルの対応が追い付いていないだけだろうか。

※既定のランタイムやカスタムコンテナー

  1. 既定のランタイムの場合 (例: Node.js 20 LTS)
  2. カスタムコンテナーの場合(例: nginxのイメージ)

サブリソースタイプ Microsoft.Web/sites/sitecontainers

次に、新しいMicrosoft.Web/sitesサブリソースタイプ sitecontainers(同b)。

この"Microsoft.Web/sites/sitecontainers"リソース (長い。以降はsitecontainersリソース)がコンテナーのイメージ名やタグ、待ち受けしているポートの情報を持っている(同c)。
メインのアプリケーションコンテナー含め、App Serviceの中で動かしたいそれぞれのコンテナーに対応している。

また sitecontainers リソースには、isMain プロパティがある(同d)。
App Service へのリクエストは、このisMaintrueになっているsitecontainersリソースのコンテナーへルーティングされる。
その他のsitecontainersリソース(Sidecarとして使われるコンテナー)では、isMainfalseにする。

スケーリング

sitecontainerリソースを使ったマルチコンテナーの場合、1つのインスタンスの中では、メインのアプリコンテナ含めsitecontainerリソースの数だけコンテナが動く。
なので、App Service (Plan)をスケールアウトしてインスタンスを追加すると、追加されたインスタンスの中でまたsitecontainerリソースに対応したコンテナが動き出す。

上記のBicepの例の場合は、1つのApp Serviceリソースにsitecontainersリソースを3つ定義しているので、1インスタンスに3つのコンテナーが動く。
さらに、3インスタンスにスケールアウトすると、それぞれのインスタンスで3つのコンテナーが動くことになる。

App Service Planへの影響

App Service Planの各SKUは、一応そのプラン上で動かすアプリ数の上限目安がある。
learn.microsoft.com App Service on Linuxの場合、コンテナ数に置き換えて案内してた。

sitecontainersリソースを使ったマルチコンテナーの場合、sitecontainersの数だけそのApp Service Plan上でコンテナーが動きSidecar用途のコンテナーとはいえメモリーもCPUも使うので、このアプリ数にも影響が出るだろう。

ところでマルチコンテナーと言えば

Docker ComposeとかKubernetesとかだけど、両方ともプレビューながらApp Serviceで動かすことができる*1

App Serviceのマルチコンテナー対応は割と歴史があり、調べてみると2018年にはプレビューリリースされていた。
azure.github.io

「Docker Composeの設定ファイルをbase64エンコード済みで4000文字まで」というなかなかピンと来ない制限はあるものの、公式ドキュメントもまだあるので今でも動くはず。

この文字数制限は、自分がサポートエンジニアしてた頃から「もっと拡大してほしい」という要望がでてた。
でも、あれから5年以上経っても拡大する気配はないので、たぶん永遠のプレビューなんだろう。

learn.microsoft.com

そういうマイクロサービス的なマルチコンテナーは、今回のApp Serviceでのマルチコンテナー対応のターゲットではない、というのは注意。
AKS/ACAを使おう。


*1:どれだけの人が知ってるだろうか。