検索
連載

Azure Traffic Managerプロファイルを生成する方法(ARMテンプレート編)Tech TIPS

Azureでリージョンをまたいでアクセスを分散させて耐障害性向上あるいは負荷分散などを実現できるサービス「Traffic Manager」。これをAzureポータル(GUI)での手動操作ではなく、スクリプトで自動的にデプロイ(生成)できるようにするARM(Azure Resource Manager)テンプレートについて説明する。

PC用表示 関連情報
Share
Tweet
LINE
Hatena
「Tech TIPS」のインデックス

連載目次

Azure Traffic ManagerをBicepのテンプレートからデプロイする手順とコツ

対象:Azure Traffic Manager、ARMテンプレート(Bicep)


 Azureでリージョンをまたいでアクセスを分散させて耐障害性向上や負荷分散をしたい場合、DNS ベースのトラフィックロードバランサーの「Traffic Manager」を利用することが候補の一つになるだろう。

 このTraffic Managerは比較的シンプルなサービスとはいえ、複数生成しようとすると、AzureポータルのGUIではなかなかに面倒だ。ウィザードでうっかり選択肢を間違えることもあるだろう。

 そこで本Tech TIPSでは、ARM(Azure Resource Manager)テンプレートを使ってこのTraffic Managerを一発で生成する方法を紹介する。

■執筆時の各種ツール/APIのバージョン


Traffic Managerの名前やルーティング、DNSレコードを設定する

 Traffic ManagerをデプロイするためのARMテンプレートファイル(traf.azuredeploy.bicep)が長いため、以下では複数のセクションに分けて説明する。

 最初のセクションでは、Traffic Managerの名前やルーティング、DNSレコードに関する設定をパラメーターで受け取る。

// ファイル: traf.azuredeploy.bicep(1/6)

////////// Traffic Managerの名前やルーティング、DNSレコードを設定する //////////

param trafName string // Traffic Managerプロファイル名

///// ルーティング方法の選択

@allowed([
  'Geographic' // 地域
  'MultiValue' // 複数値
  'Performance' // パフォーマンス
  'Priority' // 優先度
  'Subnet' // サブネット
  'Weighted' // 重み付け
])
param trafficRoutingMethod string

///// DNSレコードに関する設定

// Traffic ManagerプロファイルのDNS名のサブドメイン部分
param relativeName string = '${trafName}-${uniqueString(utcNow())}'
// デフォルトは、プロファイル名とハイフン、一意な13桁文字列をつなげた名前

@minValue(0)
param dnsTTL int = 60 // DNSレコードのTTL(キャッシュ保持可能時間)。秒単位

// DNS設定まとめ
var dnsConfig = {
  relativeName: relativeName
  ttl: dnsTTL
}

【Bicep】Traffic Managerの名前やルーティング、DNSレコードを設定する
※Microsoftのレファレンス: Microsoft.Network trafficmanagerprofilesparamuniqueString()utcNow()var

 パラメーター「trafficRoutingMethod」で指定しているルーティングについては、Traffic Managerが複数のエンドポイント(オリジンサーバ)に対して振り分ける方式を6つの選択肢から選ぶ必要がある。耐障害性向上なら「Priority(優先度)」、負荷分散なら「Weighted(重み付け)」などが選択肢として挙がるだろう。ただ、「MultiValue(複数値)」については、Azureのサービスではない外部エンドポイントでしか利用できない、といった制限もあるので注意が必要だ。ルーティングの詳細については、Microsoft Learn「Traffic Manager のルーティング方法」「Traffic Manager についてよく寄せられる質問 (FAQ)」が参考になる。

 パラメーター「relativeName」には、生成するTraffic Managerプロファイルに付けられるドメイン名の「<サブドメイン>.trafficmanager.net」のうち、<サブドメイン>名を指定する。上記リストでは、デフォルトでTraffic Managerプロファイル名とユニークな13桁文字列をハイフンでつなげた名称にしている。

 パラメーター「dnsTTL」には、Traffic Managerプロファイルを指し示すDNSレコードのTTL(Time To Live:レコードをキャッシュに保持できる時間)を秒単位で指定する。これが長くなるほど、エンドポイントの切り替えにかかる実質的な時間が長くなる(障害発生時のダウンタイムが長くなる)。短くすると、エンドユーザーのデバイス(端末)でDNSへの名前解決要求が増える。未指定だと0秒、つまりキャッシュ禁止になる。

エンドポイントのモニタリング(監視)を設定する

 次のセクションでは、エンドポイントが正常か、それともダウンしていて応答できない異常な状態かを判定する「モニタリング(監視)」について設定する。

// ファイル: traf.azuredeploy.bicep(2/6)

////////// エンドポイントのモニタリング(監視)を設定する //////////

// プローブ: 正常かどうかを調べるためにエンドポイントへ送信されるリクエストのこと

param healthCheckPath string // 監視するファイルのパス

@allowed([
  'HTTP'
  'HTTPS'
  'TCP'
])
param monitorProtocol string = 'HTTPS' // 監視に用いるプロトコル

param monitorPort int = 443 // 監視に用いる通信ポート

@allowed([
  10
  30
])
param intervalInSeconds int = 30 // 監視の間隔。秒単位

@minValue(0)
@maxValue(9)
param toleratedNumberOfFailures int = 5 // 障害と判断する最小発生回数

@minValue(5)
param timeoutInSeconds int = 7 // 障害と判断する最短応答時間。秒単位
// intervalInSecondsより5秒以上、短くする必要あり

// モニタリング(監視)の設定まとめ
var monitorConfig = {
  protocol: monitorProtocol
  port: monitorPort
  path: healthCheckPath
  intervalInSeconds: intervalInSeconds
  toleratedNumberOfFailures: toleratedNumberOfFailures
  timeoutInSeconds: timeoutInSeconds
}

【Bicep】エンドポイントのモニタリング(監視)を設定する
※Microsoftのレファレンス: Microsoft.Network trafficmanagerprofiles

 パラメーター「healthCheckPath」では、例えば「/health.html」というように、監視するファイルのパスを指定する。デフォルトでは、このファイルへのリクエストに対してHTTPステータスコード200が返されれば、正常と診断される。また、このファイルにアクセスする際のプロトコルと通信ポート番号は、パラメーター「monitorProtocol」「monitorPort」でそれぞれ指定する必要がある。

 監視中に障害が発生したかどうか、その判断を左右するのがパラメーター「intervalInSeconds」「toleratedNumberOfFailures」「timeoutInSeconds」の3つだ。これらの設定値はエンドポイントの性能(監視するファイルの平均応答速度など)に依存するので、調整が必要になるだろう。詳細はMicrosoft Learn「Traffic Manager エンドポイントの監視」が参考になる。

エンドポイントを設定する

 次のセクションでは、エンドポイント(オリジンサーバ)を設定する。ここでは、同じAzureのApp Serviceを東日本リージョンと西日本リージョンにそれぞれ1台ずつ配置済みとし、それらをエンドポイントとして登録している。

// ファイル: traf.azuredeploy.bicep(3/6)

////////// エンドポイントを設定する //////////

// エンドポイントの定義。ここではApp Serviceを前提としている
param endpoints array = [
  {
    // 1つ目のApp Service
    name: '<1つ目のApp Serviceの名前>'
    type: 'azureEndpoints' // Azureのサービスの場合
    // 外部エンドポイントなら「externalEndpoints」を指定
    endpointStatus: 'Enabled'
    resourceGroup: '<1つ目のApp Serviceのリソースグループ名>'
    FQDN: '<1つ目のApp ServiceのFQDN>' // 名前解決に利用
    priority: 2 // 優先順位。小さいほど優先される
    weight: 1 // 重み。大きいほどアクセスが増える
    alwaysServe: 'Disabled' // Enabledにすると、障害を検知しても切り替えない
  }
  {
    // 2つ目のApp Service
    name: '<2つ目のApp Serviceの名前>'
    type: 'azureEndpoints'
    endpointStatus: 'Enabled'
    resourceGroup: '<2つ目のApp Serviceのリソースグループ名>'
    FQDN: '<2つ目のApp ServiceのFQDN>'
    priority: 4
    weight: 1
    alwaysServe: 'Disabled'
  }
]

// エンドポイントであるApp Serviceの既存リソース
resource webApp 'Microsoft.Web/sites@2022-03-01' existing = [
  for endpoint in endpoints: {
    name: endpoint.name
    scope: resourceGroup(endpoint.resourceGroup)
  }
]

【Bicep】エンドポイントを設定する
※Microsoftのレファレンス: Microsoft.Network trafficmanagerprofilesfor

 パラメーター「endpoints」内のハッシュの「FQDN」キーには、そのエンドポイントに到達できるFQDNを指定する。App Serviceならデフォルトの「<App Service名>.azurewebsites.net」を指定すればよい。

 パラメーター「trafficRoutingMethod」でルーティング方式として「Priority」を選択した場合には、各エンドポイントに優先度を数値で指定する必要がある。それが「priority」キーである。この数値が最も小さいエンドポイントが、正常時に100%のアクセスが振り向けられる。例えば、普段は東日本リージョンのエンドポイントにアクセスを振り向けつつ、東日本側が停止した場合は西日本リージョンに振り向けたい場合は、東日本側のpriorityを小さくし、西日本側のpriorityはそれより大きくする必要がある。

 「weight」キーは「重み付け」のルーティングをする場合に、各エンドポイントへのアクセス数を配分するのに用いられる。この数値が大きいほどアクセスが増える。デフォルトでは全エンドポイントに「1」が設定される。

 「alwaysServe」キーを「Enabled」に設定すると、プローブが無効になり、そのエンドポイントには障害発生時でも必ずルーティングに従ってアクセスが配分されるようになる。

 上記リストで「webApp」という既存リソースを定義しているのは、次のセクションでエンドポイントのリソースIDが必要になるからだ(後述)。

Traffic Managerプロファイルのリソースを生成する

 次のセクションでTraffic Managerプロファイルを実際に生成する。

// ファイル: traf.azuredeploy.bicep(4/6)

////////// Traffice Managerプロファイルのリソースを生成する //////////

resource trafficManagerProfile 'Microsoft.Network/trafficmanagerprofiles@2022-04-01' = {
  name: trafName
  location: 'global' // 必ず「global」を指定
  properties: {
    profileStatus: 'Enabled'
    trafficRoutingMethod: trafficRoutingMethod
    dnsConfig: dnsConfig
    monitorConfig: monitorConfig
    endpoints: [
      // ループでエンドポイントを1つずつ設定
      for (endpoint, i) in endpoints: {
        name: 'tme-${endpoint.name}'
        type: 'Microsoft.Network/trafficManagerProfiles/${endpoint.type}'
        properties: {
          endpointStatus: endpoint.endpointStatus
          targetResourceId: webApp[i].id
          target: endpoint.FQDN
          priority: endpoint.priority
          weight: endpoint.weight
          endpointLocation: webApp[i].location
          alwaysServe: endpoint.alwaysServe
        }
      }
    ]
    trafficViewEnrollmentStatus: 'Disabled'
  }
}

【Bicep】Traffice Managerプロファイルのリソースを生成する
※Microsoftのレファレンス: Microsoft.Network trafficmanagerprofiles

 注意すべきは「location」に必ず「global」すなわちグローバルリージョンを指定することだ。東日本などその他のリージョンを指定すると、エラーが発生して生成に失敗する。従ってリソースグループの配置先リージョンとは必ず異なるので、デプロイのスクリプトなどでは例外として扱わなければならない場合もあるだろう。

診断設定をTraffic Managerに加える

 次のセクションでは、Traffic ManagerのログをAzure Log Analyticsで分析したり、ストレージアカウントに自動保存したりするための診断設定を追加する。

// ファイル: traf.azuredeploy.bicep(5/6)

////////// 診断設定をTraffic Managerに加える //////////

param diagLogs array = [
  // 診断に加えるログ一覧
  'ProbeHealthStatusEvents' // Traffic Manager Probe Health Results Event
]
param diagMetrics array = [] // 診断に加えるメトリック一覧

// ログ用ストレージアカウントの既存リソース
param logStorageRG string
param logStorageName string

resource logStgAccount 'Microsoft.Storage/storageAccounts@2023-01-01' existing = {
  name: logStorageName
  scope: resourceGroup(logStorageRG)
}

// Log Analytics Workspaceの既存リソース
param logAnalyticsRG string
param logAnalyticsName string

resource logAnalytics 'Microsoft.OperationalInsights/workspaces@2022-10-01' existing = {
  name: logAnalyticsName
  scope: resourceGroup(logAnalyticsRG)
}

// 診断設定の拡張リソース生成
resource diagSetting 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = {
  name: 'diag-${trafName}'
  scope: trafficManagerProfile // 診断対象のTraffic Managerプロファイルのリソース
  properties: {
    storageAccountId: logStgAccount.id
    workspaceId: logAnalytics.id
    logs: [
      for log in diagLogs: {
        category: log
        enabled: true
      }
    ]
    metrics: [
      for metric in diagMetrics: {
        category: metric
        enabled: true
      }
    ]
  }
}

【Bicep】診断設定をTraffic Managerに加える
※Microsoftのレファレンス: Microsoft.Storage storageAccountsMicrosoft.OperationalInsights ワークスペースMicrosoft.Insights diagnosticSettings

 Log Analyticsワークスペースとストレージアカウントは、あらかじめ別途生成しておき、それらの名前とリソースグループをパラメーターで指定する必要がある。

 執筆時点でTraffic Managerのログは「ProbeHealthStatusEvents」(Azureポータルでは「Traffic Manager Probe Health Results Event」)という、プローブに異常が生じたときや正常に戻ったときに生じるイベントを記録するログだけだ。詳細はMicrosoft Learn「Microsoft.Network/trafficManagerProfiles でサポートされているログ」が参考になる。

メトリックアラートをTraffic Managerに加える

 最後のセクションでは、メトリックアラート(アラートルール)をTraffic Managerに追加する。

// ファイル: traf.azuredeploy.bicep(6/6)

////////// メメトリックアラートをTraffic Managerに加える //////////

param endpointStatus int = 1 // Endpoint Status by Endpoint(1を切ったら異常)

var metricAlertParams = [
  {
    name: 'Endpoint Status Falls Down at ${trafName}'
    description: '${trafName} で「Endpoint Status」の最小値が ${endpointStatus} を下回りました'
    severity: 2
    evaluationFrequency: 'PT1M'
    windowSize: 'PT5M'
    metricTitle: 'metric_min_endpoint_status_lt_${endpointStatus}_in_1m'
    threshold: endpointStatus
    metricName: 'ProbeAgentCurrentEndpointStateByProfileResourceId'
    operator: 'LessThan'
    timeAggregation: 'Minimum'
  }
]

// モジュール: メトリックアラートのリソース生成
param monitorActionGroupRG string
param monitorActionGroupName string

module MetricAlertsModule './metricalert.azuredeploy.bicep' = [
  for (metricAlert, i) in metricAlertParams: {
    name: '${deployment().name}-metricAlert-${i+1}'
    params: {
      parent: {
        id: trafficManagerProfile.id
        name: trafficManagerProfile.name
        type: trafficManagerProfile.type
      }
      ma: metricAlert
      monitorActionGroupRG: monitorActionGroupRG
      monitorActionGroupName: monitorActionGroupName
    }
  }
]

【Bicep】メトリックアラートをTraffic Managerに加える(モジュール側)
※Microsoftのレファレンス: Microsoft.Insights actionGroupsmodule

 上記リストでは、モジュールでパラメーターを指定しつつ、この後に記している「metricalert.azuredeploy.bicep」という別のBicepファイルを呼び出して、実際にアラートルールを生成させている。この生成の詳細については、Tech TIPS「【Azure】大量のメトリックアラートを一発で作る方法(リソーステンプレート編)」を参照していただきたい。

 また通知のためのMonitorアクショングループは、あらかじめ別途生成しておき、その名前とリソースグループをパラメーターで指定する必要がある。Monitorアクショングループの生成についても、前出のTIPSを参照していただきたい。

// ファイル: metricalert.azuredeploy.bicep

////////// メトリックアラートを実際に生成する //////////

param parent object // 親リソース(メトリック提供)の情報
param ma object // メトリックアラートの主要なパラメーターを収めたオブジェクト

///// Monitorのアクショングループの既存リソース

param monitorActionGroupRG string
param monitorActionGroupName string

resource monitorActionGroup 'Microsoft.Insights/actionGroups@2023-01-01' existing = {
  name: monitorActionGroupName
  scope: resourceGroup(monitorActionGroupRG)
}

///// アラートルールのリソース生成

resource metricAlert 'Microsoft.insights/metricalerts@2018-03-01' = {
  name: ma.name
  location: 'global' // 必ず「global」にする
  properties: {
    description: ma.description
    severity: ma.severity
    enabled: true
    scopes: [parent.id]
    evaluationFrequency: ma.evaluationFrequency
    windowSize: ma.windowSize
    criteria: {
      allOf: [
        {
          threshold: ma.threshold
          name: ma.metricTitle
          metricNamespace: parent.Type
          metricName: ma.metricName
          operator: ma.operator
          timeAggregation: ma.timeAggregation
          criterionType: 'StaticThresholdCriterion'
        }
      ]
      'odata.type': 'Microsoft.Azure.Monitor.SingleResourceMultipleMetricCriteria'
    }
    autoMitigate: true
    targetResourceType: parent.Type
    actions: [
      {
        actionGroupId: monitorActionGroup.id
      }
    ]
  }
}

【Bicep】メトリックアラートを実際に生成する
※Microsoftのレファレンス: Microsoft.Insights metricAlerts

 上記リストのファイル「metricalert.azuredeploy.bicep」は、前述の「traf.azuredeploy.bicep」と同じフォルダに配置する必要がある。

「Tech TIPS」のインデックス

Tech TIPS

Copyright© Digital Advantage Corp. All Rights Reserved.

ページトップに戻る