Azure Database for MySQLをARMテンプレートからデプロイする手順とコツ:Tech TIPS
Azure上でMySQLサーバが必要な場合、出来合いのサービスである「Azure Database for MySQL」を利用するのが最も簡単な方法だろう。ただ、そのデプロイには幾つか注意すべき点もある。ARMテンプレート(Bicep)に焦点を当てて、その手順とコツを説明する。
対象:Azure Database for MySQL、ARMテンプレート(Bicep)
Azureには「MySQL Server」を比較的容易に構築できる「Azure Database for MySQL」(以下、「Azure MySQL」と略)というサービスがある。仮想マシンやインストーラーなどを用意しなくても、Azureポータルからウィザードで設定していけば、簡単にポート3306で待ち受けるMySQL Serverを構築できる。
ただ、比較的容易とはいっても設定項目の数は一定数あるため、ウィザードで作成するには手間がかかるし、オプションの指定も間違いやすい。また警告(アラート)や診断など、Azure MySQLのウィザードとは別に設定しなければならない項目もある。
ARM(Azure Resource Manager)テンプレートでAzure MySQLをデプロイできれば、こうした問題を解決できる。1回の操作で特定の設定のAzure MySQLを構築可能だ。
そこで本Tech TIPSでは、Bicepで記述したARMテンプレートを使ってAzure MySQLをデプロイする基本的な方法、および「ハマりやすい」注意点を説明する。
対象は「フレキシブルサーバ」と呼ばれるLinuxベースのサーバとする(廃止が決まっているWindowsベースの「単一サーバ」は対象外)。また、仮想ネットワークやプライベートエンドポイントは使用せず、インターネット経由でアクセスできるようにする。
■執筆時の各種ツール/APIのバージョン
- Azure CLI: Ver. 2.58.0
- Bicep CLI: Ver. 0.26.54
- Bicepでのデプロイ時のAPIバージョン: 2023-10-01-preview(MySQLフレキシブルサーバ)
Azure MySQLのCPUコア数/メモリ容量を指定する
以下では、見やすくするためにARMテンプレートの単一ソースコードを分割して、それぞれ説明する。
Azure MySQLのCPUやメモリの性能を指定するには、そのベースとなる仮想マシン(VM)のサイズ名称を以下のように指定する。
param skuName string = 'Standard_B1s' // ベースの仮想マシン(VM)のサイズ名称
var skuTiers = {
// VMサイズの大枠(階層)を導出するオブジェクト
Standard_B: 'Burstable' // 「バースト可能」。性能を一時的に高められる。レプリケーション不可など制約あり
Standard_D: 'GeneralPurpose' // 「汎用(はんよう)」。一般的なワークロード向け
Standard_E: 'MemoryOptimized' // 「Business Critical」。汎用よりメモリを増量
}
var skuTierKey = substring(skuName, 0, length('Standard_X')) // サイズ名称から↑のキーを導出
var sku = {
name: skuName
tier: skuTiers[skuTierKey]
}
パラメーター「skuName」のデフォルト値としている「Standard_B1s」が、VMサイズを表す名称の一種である。VMサイズの名称とそのCPUコア数、メモリ容量は、Microsoft Learnの「サービス レベル、サイズ、サーバの種類」で確認できる。
オブジェクト「sku」の「tier」(sku.tier)には、下表のようにVMサイズの大枠(階層)を表す文字列を指定する必要がある(上のリストではVMサイズ名称から自動生成している)。
VMサイズ名称(skuName) | VMサイズの大枠(階層) | sku.tierに指定すべき文字列 |
---|---|---|
Standard_B〜 | バースト可能 | Burstable |
Standard_D〜 | 汎用(はんよう) | GeneralPurpose |
Standard_E〜 | Business Critical | MemoryOptimized |
上記リストのsku.tierに指定すべき文字列 |
以下のコマンドラインを実行すると、指定のリージョンで実際に作成可能なVMサイズの一覧を確認できる。
az mysql flexible-server list-skus -l <リージョン名> --query "[?zone=='none'].supportedFlexibleServerEditions[].supportedServerVersions[?name=='8.0.21'].supportedSkus[][].name" -o tsv
可用性ゾーンを特定したい場合は、「?zone=='none'」の「none」の代わりにゾーン番号を指定する。またMySQL Server 5.7の場合は、「?name=='8.0.21'」の「8.0.21」の代わりに「5.7」を指定すること。
※Microsoftのレファレンス:az mysql flexible-server list-skus、Azure CLIの--queryオプション
「アクセス制限」(後述)がかかっているリージョンの場合、上記コマンドの結果が空になる(一つもリストアップされない)。
Azure MySQLのストレージ容量や性能を指定する
Azure MySQLのストレージについては、上述のVMサイズとは別に設定する必要がある。具体的には、ストレージの容量と性能(IOPS: 1秒当たりの入出力処理数)を以下のように設定する。
@minValue(20)
@maxValue(16384)
param storageSizeGB int = 20 // ストレージ容量の最大値
@allowed([
'Enabled'
'Disabled'
])
param autoIoScaling string = 'Enabled' // ストレージのIOPSの自動スケーリングを有効化
@minValue(360) // 最大値の方は仮想マシンのサイズに左右される
param iops int = 360 // ストレージのIOPS(自動スケーリングしない場合)
var storage = {
storageSizeGB: storageSizeGB
autoGrow: 'Enabled' // ストレージの自動拡張
autoIoScaling: autoIoScaling
iops: iops
}
※Microsoftのレファレンス:storageプロパティ
ストレージの容量については、足りなくなると自動的に容量を増やす機能がデフォルトで有効になっている。つまり、上記のパラメーター「storageSizeGB」で指定する容量は、デプロイ時の初期容量にすぎない点に注意したい。
容量の自動拡張は以下のルールで実行される。
- 現容量が100GB以下: 空き容量が10%を下回ると、5GBが加えられる
- 現容量が100GBを超える: 空き容量が10GBを下回ると、現容量の5%が加えられる
IOPSの方もデフォルトで自動スケーリングが有効になっている。これは、実際のI/O処理数に応じてIOPSを自動的に増減させる機能だ。この場合、パラメーター「iops」で固定のIOPS値を指定する必要はない。
Azure MySQL(MySQL Server本体)のリソースを生成する
Azure MySQLの本体(MySQL Server)のリソースを生成するには、以下のように記述する。VMサイズやストレージ以外の設定についても指定している。
param mySQLName string // Azure MySQLのリソース名
param location string = resourceGroup().location // ↑の作成先リージョン
param administratorLogin string // 管理者アカウント名
@secure()
param administratorLoginPassword string // ↑のパスワード
@allowed([
'5.7'
'8.0.21'
])
param version string = '8.0.21' // MySQL Serverのバージョン
var network = {
// ネットワークの設定(ファイアウォールは別途)
publicNetworkAccess: 'Enabled' // インターネットからのアクセスを許可
}
param backupRetentionDays int = 7 // バックアップ保持日数
var backup = {
// バックアップの設定
backupRetentionDays: backupRetentionDays
geoRedundantBackup: 'Disabled' // リージョンをまたいだバックアップ。無効
}
var highAvailability = {
// 高可用性の設定
mode: 'Disabled' // 無効
}
// リソース生成: Azure MySQL(フレキシブルサーバ)
resource mySQLServer 'Microsoft.DBforMySQL/flexibleServers@2023-10-01-preview' = {
name: mySQLName
location: location
sku: sku
properties: {
storage: storage
administratorLogin: administratorLogin
administratorLoginPassword: administratorLoginPassword
version: version
network: network
backup: backup
highAvailability: highAvailability
replicationRole: 'None' // レプリケーションはしない
createMode: 'Default' // 標準のサーバ作成モード(復元やレプリカではない)
maintenanceWindow: {
customWindow: 'Disabled'
}
}
}
※Microsoftのレファレンス:Microsoft.DBforMySQL flexibleServers
バックアップは毎日全自動で実行される。パラメーター「backupRetentionDays」では、その履歴をどれくらい保持しているか、日数で指定できる。
デプロイ時にMySQLのサーバパラメーター(システム変数)を変更する
Azure MySQLでは、デプロイ時にサーバパラメーター(システム変数)を変更できる。以下では、サーバレベルの文字コードと照合順序、スロークエリログ、SQLモードを変更する例を記してみた。
param characterSetServer string = 'utf8mb4' // Azure MySQLの文字コード
param collationServer string = 'utf8mb4_0900_ai_ci' // ↑の照合順序
param slowQueryLog bool = false // スロークエリログを取得するか否か
param longQueryTime int = 10 // スロークエリかどうかのしきい値(秒)
param sqlModes array = [
// SQL Modeの一覧
'ONLY_FULL_GROUP_BY'
'STRICT_TRANS_TABLES'
'NO_ZERO_IN_DATE'
'NO_ZERO_DATE'
'ERROR_FOR_DIVISION_BY_ZERO'
]
var configs = [
{
name: 'character_set_server'
value: characterSetServer
}
{
name: 'collation_server'
value: collationServer
}
{
name: 'slow_query_log'
value: slowQueryLog ? 'ON' : 'OFF'
}
{
name: 'log_slow_admin_statements'
value: slowQueryLog ? 'ON' : 'OFF'
}
{
name: 'long_query_time'
value: string(longQueryTime)
}
{
name: 'sql_mode'
value: join(sqlModes, ',')
}
]
// リソース生成: サーバパラメーター(システム変数)の変更
resource configuration 'Microsoft.DBforMySQL/flexibleServers/configurations@2023-06-30' = [
for config in configs: {
parent: mySQLServer // ひも付けるAzure MySQLのリソース
name: config.name
properties: {
value: config.value
}
}
]
※Microsoftのレファレンス:Microsoft.DBforMySQL flexibleServers/configurations
システム変数を変更するにはそれぞれ、「Microsoft.DBforMySQL/flexibleServers/configurations」のリソースを生成する必要がある。上記リストでは複数のシステム変数をforループで変更している。
デプロイ時にファイアウォールルールを設定する
インターネット経由での着信(パブリックエンドポイントを介したアクセス)を有効にしている場合、不正アクセスを防ぐために、「ファイアウォールルール」を設定すべきだ。
ここでいうファイアウォールルールとは、ソースIPアドレスによるアクセス制限を指す。例えば、組織内のオンプレミスのシステムからAzure MySQLにアクセスする場合は、そのインターネット接続の発信元グローバルIPアドレスをファイアウォールルールとして登録する。このように登録したIPアドレスは許可される一方、未登録のIPアドレスからのアクセスは拒否される。
ファイアウォールルールも、以下のようにリソースとして1つずつ生成する。
param firewallRules array = [
{
// 任意のAzureサービスからのアクセスを許可(パブリックエンドポイント経由)
name: 'AllowAllAzureServicesAndResourcesWithinAzureIps' // ルール名
startIpAddress: '0.0.0.0'
endIpAddress: '0.0.0.0'
}
{
name: 'headquarters' // ルール名
startIpAddress: '192.0.2.17' // 始まりのIPアドレス
endIpAddress: '192.0.2.31' // 終わりのIPアドレス
}
{
name: 'branch1'
startIpAddress: '203.0.113.65'
endIpAddress: '203.0.113.65' // 範囲ではなく単一の場合は同一IPアドレスを指定
}
]
// リソース生成: ファイアウォールルールの追加
@batchSize(1) // 1つずつ生成する
resource firewallRule 'Microsoft.DBforMySQL/flexibleServers/firewallRules@2023-06-30' = [
for fwRule in firewallRules: {
parent: mySQLServer // ひも付けるAzure MySQLのリソース
name: fwRule.name
properties: {
startIpAddress: fwRule.startIpAddress
endIpAddress: fwRule.endIpAddress
}
}
]
※Microsoftのレファレンス:Microsoft.DBforMySQL flexibleServers/firewallRules
また、Azure内のAzureサービス(App Serviceや仮想マシンなど)からのアクセスを全面的に許可するなら、IPアドレス「0.0.0.0」をファイアウォールルールに設定すればよい。変更されることもあるAzureサービスのソースIPアドレスをいちいち指定しなくて済む。その一方で、全く無関係の第三者が生成したAzureリソースからアクセスされる危険性がある。
Azure MySQLのメトリックアラートを設定する
Azure MySQLには複数のメトリックアラートが用意されている。ここでは代表的なメトリックとして、接続中断(Aborted Connections)とメモリ使用量に関するアラートをセットアップする例を以下に記す。
param totalAbortConnections int = 0 // 接続中断の回数の上限
param maxMemCapPercent int = 70 // メモリ使用率の上限
var metricAlerts = [
{
name: 'Aborted Connections at ${mySQLName}' // 通知メールのサブジェクトになる
description: '${totalAbortConnections}回/5分 を超える接続中断が発生しました。${mySQLName}です。'
severity: 2 // 重要度は「警告」
evaluationFrequency: 'PT1M' // 1分ごとに確認
windowSize: 'PT5M' // 5分間監視
metricTitle: 'metric_total_aborted_connections_gt_${totalAbortConnections}count_in_5m'
threshold: totalAbortConnections
metricName: 'aborted_connections' // Aborted Connectionsのシグナル名
operator: 'GreaterThan'
timeAggregation: 'Total'
}
{
name: 'Host Memory Percent increasing at ${mySQLName}'
description: 'メモリ使用率が ${maxMemCapPercent}% を超えました。${mySQLName}です。'
severity: 3 // 重要度は「情報」
evaluationFrequency: 'PT1M'
windowSize: 'PT5M'
metricTitle: 'metric_max_memory_percent_gt_${maxMemCapPercent}percent_in_5m'
threshold: maxMemCapPercent
metricName: 'memory_percent' // Memory Percentのシグナル名
operator: 'GreaterThan'
timeAggregation: 'Maximum'
}
]
// 既存リソース: 通知用アクショングループ
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' = [
for ma in metricAlerts: {
name: ma.name
location: 'global'
properties: {
description: ma.description
severity: ma.severity
enabled: true
scopes: [mySQLServer.id] // 測定対象のAzure MySQLのリソースID
evaluationFrequency: ma.evaluationFrequency
windowSize: ma.windowSize
criteria: {
allOf: [
{
threshold: ma.threshold
name: ma.metricTitle
metricNamespace: mySQLServer.type // 測定対象のAzure MySQLのリソースタイプ
metricName: ma.metricName
operator: ma.operator
timeAggregation: ma.timeAggregation
criterionType: 'StaticThresholdCriterion'
}
]
'odata.type': 'Microsoft.Azure.Monitor.SingleResourceMultipleMetricCriteria'
}
autoMitigate: true
targetResourceType: mySQLServer.type // 測定対象のAzure MySQLのリソースタイプ
actions: [
{
actionGroupId: monitorActionGroup.id // 通知用アクショングループのリソースID
}
]
}
}
]
※Microsoftのレファレンス:Microsoft.Insights metricAlerts
メトリックアラート作成については、Tech TIPS「【Azure】大量のメトリックアラートを一発で作る方法(リソーステンプレート編)」で説明している。上記リストでも、メトリックの違いを除けば、特に変わっている点はない。そのため、他のメトリックについても、下表を参考にすれば割と簡単にアラートをセットアップできるだろう。
metricNameプロパティ | 概要 |
---|---|
Slow_queries | スロークエリの回数 |
active_connections | アクティブな接続数 |
io_consumption_percent | ストレージI/Oの使用率(%) |
storage_percent | ストレージ容量の使用率(%) |
cpu_percent | CPU使用率(%) |
Azure MySQLの主要なメトリック(上記リストの分を除く) |
Azure MySQLのログをストレージアカウントやLog Analyticsに送信する(診断設定)
Azure MySQLのスロークエリログと監査ログは、ストレージアカウントやLog Analytics Workspaceに送信できる。それには以下のように拡張リソースを生成する。ストレージアカウントやLog Analytics Workspaceは事前に生成しておくこと。
param diagLogNames array = [
// 取得可能なログ一覧
'mysqlslowlogs' // MySQL Slow Logs。スロークエリログ
//'mysqlauditlogs' // MySQL Audit Logs。監査ログ
]
// 既存リソース: ログ用ストレージアカウント
param logStorageRG string // リソースグループ名
param logStorageName string
resource logStgAccount 'Microsoft.Storage/storageAccounts@2022-09-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-storage-log-${mySQLName}' // この診断設定の名前
scope: mySQLServer // ひも付けるAzure MySQLのリソース
properties: {
storageAccountId: logStgAccount.id // ログ用ストレージアカウントのID
workspaceId: logAnalytics.id // Log Analytics WorkspaceのID
logs: [
for logName in diagLogNames: {
// 保存するログをループで1つずつ指定
category: logName // ログ名称
enabled: true
}
]
}
}
※Microsoftのレファレンス:Microsoft.Insights diagnosticSettings
【注意】メンテナンスウィンドウを指定するとデプロイに失敗する!?
Azure MySQLでは、更新プログラムの適用といった「メンテナンス」をいつ実施するか、特定の曜日と時間帯(60分)で指定できる。未指定の場合は、ランダムに選ばれた曜日の23時〜翌7時(Azure MySQLのあるリージョンのタイムゾーン)にメンテナンスが実行される。この機能の詳細は、Microsoft Learn「Azure Database for MySQL - フレキシブル サーバの予定メンテナンスの設定を管理する」を参照していただきたい。
ARMテンプレートにも、このメンテナンスの時間帯を指定するためのプロパティ「maintenanceWindow」が定義されている。しかし実際に指定すると、筆者の環境では確実に「The server '<リソース名>' does not exist or in unexpected status.」というエラーが発生してデプロイに失敗してしまう。
もしARMテンプレートにメンテナンスウィンドウについて記述していて、同じエラーに遭遇した場合は、その記述をコメントアウトして再デプロイを試してみるとよいだろう。
デプロイ後でも、以下のコマンドラインのようにAzure CLIでメンテナンスウィンドウを設定できる。
az mysql flexible-server update -g <リソースグループ名> -n <リソース名> --maintenance-window <曜日を表す3文字の英字>:<時>:<分>
<曜日を表す3文字の英字>:<時>:<分>は「Thu:17:00」のように指定する。時刻はUTCで表す必要がある(「17:00」と指定した場合、日本時間の午前2時になる)。
※Microsoftのレファレンス:az mysql flexible-server update
【注意】ファイアウォールルールを設定すると数分単位でデプロイ時間が延びていく
デプロイ時にファイアウォールルールを設定すると、分単位で時間がかかる。筆者の環境では、1ルール当たり1〜4分程度の時間が必要だった。たくさんのルールを設定しようとすると、デプロイに1時間以上かかりかねない。
そのため、開発中は最低限のルールだけにとどめておく、あるいはデプロイ後にAzure CLIなどで別途設定する、といった回避策を考えておくべきだろう。
【注意】リージョンによっては「制限」のためAzure MySQLを作成できないことがある
リソースがひっ迫している(データセンターでサーバなどが不足している)リージョンでは、MicrosoftによってMySQL Serverやその他のリソースの作成に「制限」がかけられている場合がある。
こうしたリージョンでは、Azure MySQLは生成できないけど、他のリソースなら作れるといった症状が発生する。また、前述したVMサイズの指定可能リストを出力するコマンド「az mysql flexible-server list-skus」を、対象のリージョンに対して実行すると、1つもVMサイズが返されない。
以前に同じリソースを作ったことがあり、現在運用中でも、新規作成では前述のエラーが生じることがある。さらに、サブスクリプションによって作成できたりできなかったりする。
このような症状に遭遇したらMicrosoftのサポートに相談して、Azure MySQLの作成に制限がかかっているかどうか確認するとよいだろう(筆者の場合は、西日本と韓国南、シンガポールの各リージョンで制限されていた)。
Copyright© Digital Advantage Corp. All Rights Reserved.