AzureのApp Serviceで「運用」「ステージング」といった「デプロイスロット」をスワップする際、アプリケーション設定やDB接続文字列の一部は入れ替えずにスロットとひも付けておきたいことがある。この「デプロイスロットの設定」をリソーステンプレートに記述してデプロイする方法は?
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
対象:Azure App Service(サービスレベルは「Standard」「Premium」「isolated」のいずれか)、Bicep
本Tech TIPSでは、リソーステンプレートを使ってAzure App Serviceをデプロイする際、その記述箇所がやや分かりにくい「デプロイメントの設定」について説明する。
AzureのApp Serviceには、複数の「デプロイスロット」を作成する機能が備わっている(サービスレベルは「Standard」「Premium」「isolated」のいずれかが必要)。「デプロイスロット」とはWebアプリを固有のホスト名で実行できる環境のことだ。
デフォルトの設定でApp Serviceをデプロイすると、1つの「運用スロット」が生成される。さらに「ステージング」「開発」といったデプロイスロットを追加し、それぞれに別々のホスト名を割り当てつつ、固有のWebアプリをデプロイすることが可能だ。
また、運用スロットとステージングスロットを「スワップ」することで、ステージングスロットでテストしていた新バージョンのアプリを速やかにライブサイトで公開することもできる。スワップすることで、コンテンツ(ファイル)や多くの設定が運用とステージングの間で入れ替わることになる。
さて、このスワップの際、設定項目によってはスロット間で入れ替えたくない、つまりスロットにひも付けておきたい場合がある。
例えばWebアプリのプログラムに対し、環境変数を介してスロットの種別を伝えるために、「アプリケーション設定」に設定項目を追加したとしよう(後述のスクリーンショットにある「SiteType」)。すると、デフォルトではスワップ時に入れ替わるため、運用(Production)スロットなのに「stage」という値が設定されてしまう。
また、スロットごとにデータベースを変えなければいけない場合、「接続文字列」に設定してあるデータベース接続文字列も、デフォルトの設定のままスワップすると、運用スロットなのにステージング用データベースに接続されてしまうことになる。
そこでApp Serviceには、「アプリケーション設定」「接続文字列」の設定項目ごとに、スロットにひも付ける(スワップ時に入れ替えない)ように指定する機能がある。
Azureポータルの場合、App Serviceの[構成]−[アプリケーション設定]タブを開き、「アプリケーション設定」「接続文字列」の一覧で対象の設定項目の「名前」をクリックする。編集/追加の画面が表示されるので、そこにある[デプロイスロットの設定]チェックボックスにチェックを入れて「オン」にして、[OK]ボタンをクリックして設定を反映する。これで対象の設定項目はスワップ時に入れ替わらなくなる。
上記のスクリーンショットのような設定でスワップしたときの挙動を下図に記す。
それでは、リソーステンプレートを使ってApp Serviceをデプロイする場合、どのように「デプロイスロットの設定」をリソーステンプレートにを記せばよいのだろうか?
「アプリケーション設定」そのものは以下のいずれかのリソースに記述する。
「接続文字列」は以下のいずれかに記述する。
となると、「デプロイスロットの設定」も上記リソースに記述すればよさそうに思える。
しかし実際には、以下のように別のリソースに記述しなければならない。
以下にBicepでのリソーステンプレートの例を記す(前述のスクリーンショットや図に合わせている)。まずは「アプリケーション設定」を変数「appSettings」に、また「接続文字列」を「connectionStrings」にそれぞれ代入している。このとき、スロットにひも付けるかどうかを表す「sticky」というプロパティを追加している。
// ライブ: prod、ステージング: stage、開発: dev
param appEnv string = 'prod'
// アプリケーション設定
var appSettings = [
{
name: 'APIKey'
value: 'aaaaBBBBccccDDDD'
sticky: false // スロットにひも付けない
}
{
name: 'SiteType'
value: appEnv
sticky: true // スロットにひも付ける
}
]
// 接続文字列
var dbServer = '<DBサーバのFQDN>'
var auditDBConnStr = 'mysql:host=${dbServer};dbname=auditdb,user,password'
// ↓のデータベース名はスロットごとに変えたいので、スロットとのひも付けが必要
var mainDBConnStr = 'mysql:host=${dbServer};dbname=maindb_${appEnv},user,password'
var connectionStrings = [
{
connectionString: auditDBConnStr
name: 'AuditDB'
type: 'MySql'
sticky: false // スロットにひも付けない
}
{
connectionString: mainDBConnStr
name: 'MainDB'
type: 'MySql'
sticky: true // スロットにひも付ける
}
]
リソースを生成する際には、「for」構文で変数「appSettings」「connectionStrings」の内容を列挙している。「Microsoft.Web/sites/config」かつ「name: 'slotConfigNames'」のリソースにおいては、論理演算子「<条件式> ? <真の値> : <偽の値>」も併用して、「sticky」が真である項目のみ、その「name」を列挙している。
param location string = resourceGroup().location
// リソース生成: App Service本体
resource webApp 'Microsoft.Web/sites@2022-03-01' = {
name: '<アプリ名>'
location: location
properties: { serverFarmId: <App Serviceプランのリソース>.id }
}
// リソース生成: App ServiceのWeb設定
resource webConfig 'Microsoft.Web/sites/config@2022-03-01' = {
parent: webApp // 親となるApp Serviceのリソース
name: 'web' // 必ず「web」とする
properties: {
// stickyに関係なく全項目を列挙
appSettings: [for appSet in appSettings: {
name: appSet.name
value: appSet.value
// ここにstickyは記さない
}]
connectionStrings: [for connStr in connectionStrings: {
connectionString: connStr.connectionString
name: connStr.name
type: connStr.type
// ここにstickyは記さない
}]
}
}
// リソース生成: App Serviceのデプロイスロット設定
resource slotConfig 'Microsoft.Web/sites/config@2022-03-01' = {
parent: webApp // 親となるApp Serviceのリソース
name: 'slotConfigNames' // 必ず「slotConfigNames」とする
properties: {
// stickyが真である項目だけ、そのnameを列挙
appSettingNames: [for appSet in appSettings: appSet.sticky ? appSet.name : null]
connectionStringNames: [for connStr in connectionStrings: connStr.sticky ? connStr.name : null]
}
}
注意が必要なのは、「デプロイスロットの設定」をスロットのリソースに対して設定できないという点だ(する必要もない)。「name: 'slotConfigNames'」の親(「parent」の値)は「Microsoft.Web/sites」のリソースに限られ、スロットである「Microsoft.Web/sites/slots」のリソースは設定できない(強行するとエラーになる)。
「name: 'slotConfigNames'」のリソースでは、「azureStorageConfigNames」というプロパティでストレージアカウントとスロットのひも付けも設定できる。詳しくはMicrosoft Learnのレファレンスを参照していただきたい。
■関連リンク
Copyright© Digital Advantage Corp. All Rights Reserved.