Azure Automationを利用してSQL Databaseをオートスケールしコスト削減させた話

f:id:vasilyjp:20190605184924p:plain

こんにちは、開発部の鶴見です。
ZOZOTOWNのリプレースを担当しています。

ZOZOTOWNリプレースですが、オンプレからクラウドに単純に置き換えるのでなく「運用が楽になる」などメリットを考えながら作り替えています。
主にデータベースは、AzureのRDBであるSQL Databaseを利用しています。
先日までSQL Databaseのパフォーマンスとコストがネックになっていました。そこでAzure Automationを利用しSQL Databaseを定期的にスケールアップ/ダウンさせリソース、コストの最適化をしました。
その方法をご紹介します。

はじめに

パブリッククラウドで利用できるサービスのほとんどが従量課金であり、SQL Databaseも時間単位で課金されています。
コスト、リソースが最適となるようSQL Databaseに対して定期的なスケールアップ/ダウンを行いました。改善にあたり達成目標は次の通りです。

  • スケールアップ/ダウンの自動化
  • 適切なリソースの確保
  • 適切なコスト
  • ダウンタイム最小化

対応内容は次の2つです。

環境 対応内容
本番環境 時間帯や負荷に合わせて自動でスケールアップ/ダウンする対応。
開発環境 業務時間外に自動でスケールダウンし、業務時間内にスケールアップする対応。

上記の内容に加え「SQL Databaseは、どのようにスケールアップ/ダウンしているのか」「SQL Databaseのモデル選び」もご紹介します。 AWSやGCPでも同じような考えでRDBをスケールアップ/ダウンできると思います。

リプレースにあたりインフラ全体で「システムが安全、構成がシンプル、スケール可能、そしてコストが安い」状態を目指しています。

スケールアップ/ダウンについて

SQL DatabaseをCPU4コアから8コアにスケールアップした場合、下図のような仕組みでSQL Databaseのコア数が変わります(スケールダウンの場合も同様)。

f:id:vasilyjp:20190606183707p:plain

  1. スケールアップ実行
  2. 新インスタンス起動、旧インスタンスから新インスタンスにデータコピー
  3. 新インスタンス準備完了、エンドポイント切替え

多数のモデルが存在するSQL Database

SQL Databaseは、様々なモデルがあります。
チーム内でもモデル選びに迷いましたので、一覧にします。
どれもがSQL Serverと互換性のあるPaaSです。

種類 特徴 備考
DTUモデル CPU、メモリ、ディスクI/OなどをまとめてDTUという単位で表現されます。DTUとは、Database Throughput Unitの略です。リソースはDTUで管理されます。 簡単にDatabaseを扱いたい方にはオススメですが、CPUコア数やメモリ数の指定はできないため、細かく管理したい場合は不向きです。
vCOREモデル CPUコア数を指定できます。メモリ数は指定できませんが、CPUコア数と比例して増えます。 CPUコア数にてDatabaseを管理したい場合に向いています。
ハイパースケール ストレージが自動で拡張され、読み取り専用(セカンダリ)のスケールアウトは4台まで可能です。CPUコア数も指定できます。 Amazon Auroraに近いアーキテクチャーです。柔軟にスケールアウト/インできます。
Managed Instance SQL Serverとほぼ100%の互換性があります。CPUコア数も指定できます。 他のモデルではジョブが作成できない。などの制限があります。SQL Serverのフル機能が必要な場合、Managed Instanceを利用します。
サーバレス CPUコア数の最大と最小を指定することでスケールアップ/ダウンできます(2019年5月に発表されプレビューです)。 プレビューのためスケールアップは最大CPU4コアの制限があります。今後に期待します。

モデル選定

DTUモデルはCPU、メモリが管理できないことから採用しませんでした。
正確にはリプレース当初(2017年後半)はDTUモデルしかありませんでした。そのためリプレース当初はDTUモデルを利用していましたが、DTUに馴染めず、その後発表されたCPUコア数を管理できるモデルに乗り換えました。
ハイパースケールについては2018年12月にプレビューを検証した結果、当時はまだ性能面で不安があったので利用を見送りました。最近GAとなったため、また時期を見て再検証してみます。
サーバレスについては、求めていた自動のスケールアップ/ダウンを実現してくれるモデルですが、まだ発表されたばかりで最大CPU4コアの制限もあるため、採用を見送ります。
Managed Instanceは、SQL Serverのほぼ全ての機能を使えるのが売りですが、リプレースに於いて使いたい機能が特にありませんでした。性能に関してはvCOREモデルと同程度でした。
DTUモデル、vCOREモデルはGAから時間が経っていることありプロダクトとして安定しています。

上記のことからZOZOTOWNでは安定していて、CPUコア数も指定できるvCOREモデルを採用しています。

オートスケールを考える

vCOREモデルを利用していますが、その他モデルも含めてスケールアップ/ダウンを考えます。

種類 方法
DTUモデル DTUを変更することでスケールできます。※DTUを変えたことでCPU、メモリがどの程度増えるのか分からないため、どのくらいDTUを上げればシステムとして足りていると判断するのか難しいです。
vCOREモデル CPUコア数を変更することでスケールできます。
Managed Instance CPUコア数を変更することでスケールできます。
ハイパースケール CPUコア数の変更に加えて、読み込み専用レプリカ追加(0~4台まで)によるスケールイン/アウトもできます。
サーバレス CPUコア数の最小と最大を設定することで自動的に変更してくれます。

上記のように、どのモデルを利用したとしても動的にスケールアップ/ダウンできそうです。

実装はAzure AutomationでサポートされているPowerShellを利用しました。PowerShellにてAzureを操作(リソースの削除、追加、変更)できます。
下記、vCOREモデルでスケールアップ/ダウンを考えた場合のサンプルです。

サンプル(CPUコア数変更)

$resourceGroup = "XXXXXXXX"
$databaseName = "XXXXXXXX"
$serverName = "XXXXXXXX"
$serverEdition = "XXXXXXXX"
$computeGeneration = "XXXXXXXX"
$vCore = "XXXXXXXX"
$environmentName = "XXXXXXXX"
$connectionName = "XXXXXXXX"

$servicePrincipalConnection = Get-AutomationConnection -Name $connectionName
$environment = Get-AzEnvironment -Name $environmentName

Add-AzAccount `
    -Environment $environment `
    -ServicePrincipal `
    -TenantId $servicePrincipalConnection.TenantId `
    -ApplicationId $servicePrincipalConnection.ApplicationId `
    -CertificateThumbprint $servicePrincipalConnection.CertificateThumbprint 

Set-AzSqlDatabase -ResourceGroupName $resourceGroup `
    -DatabaseName $databaseName `
    -ServerName $serverName `
    -Edition $serverEdition `
    -ComputeGeneration $computeGeneration `
    -VCore $vCore

上記、PowerShellコードは簡易版のためエラーハンドリングは含まれていません。
他にも「CPU、メモリを動的管理ビューで確認し閾値を超えたらスケールアップ」や「時間帯で読み取り専用(セカンダリ)追加によるスケールアウト」なども行うことが可能です。

サンプル(クエリ発行)

$query = " SELECT * FROM XXXX "

Invoke-Sqlcmd -ServerInstance $serverInstance
    –Username $userName
    –Password $password
    -Database $database
    -Query $query
    -ErrorAction Stop
    -QueryTimeout $queryTimeout

PowerShellからSQL Databaseに接続しクエリを実行できます。 CPU、メモリの値を動的管理ビューから取得することも可能です。

参考情報(スケールアウト)

ハイパースケール以外でもGeoレプリケーションを利用したスケールアウトができます。 Geoレプリケーションはディザスターリカバリの目的で違う地域にデータを保持できるのですが、読み取り専用(セカンダリ)としても利用できます。

サンプル(Geoレプリケーション設定)

$database = Get-AzSqlDatabase -ResourceGroupName $resourceGroupName -ServerName $serverName -DatabaseName $databaseName

New-AzSqlServer -ResourceGroupName $resourceGroupName `
    -Location $database.Location `
    -ServerName $serverName `
    -SqlAdministratorCredentials $(New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $user, $(ConvertTo-SecureString -String $pass -AsPlainText -Force))

$database | New-AzSqlDatabaseSecondary `
    -PartnerResourceGroupName $resourceGroupName `
    -PartnerServerName $serverName `
    -AllowConnections $allowConnections `
    -SecondaryVCore $vCore `
    -SecondaryComputeGeneration $computeGeneration

Geoレプリケーションを利用して読み取り専用(セカンダリ)を追加する場合は、ファイヤフォールと仮想ネットワークの設定・脅威の検出・監査設定なども必要に応じて設定します。

サンプル(ファイヤフォール設定)

New-AzSqlServerFirewallRule -ResourceGroupName $resourceGroupName `
    -ServerName $serverName `
    -FirewallRuleName $firewallRuleName `
    -StartIpAddress "XXX.XXX.XXX.XXX" `
    -EndIpAddress "XXX.XXX.XXX.XXX"

サンプル(脅威の検出・監査設定)

Set-AzSqlServerThreatDetectionPolicy -ResourceGroupName $resourceGroupName `
    -ServerName $serverName `
    -NotificationRecipientsEmails "XXXX@XXXX" `
    -EmailAdmins $False `
    -ExcludedDetectionType "Sql_Injection_Vulnerability","SQL_Injection","Access_Anomaly" `
    -StorageAccountName $storageAccountName

Set-AzSqlServerAuditing -State Enabled `
    -ResourceGroupName $resourceGroupName `
    -ServerName $serverName `
    -StorageAccountName $storageAccountName

スケール変更注意点

  • サービスレベルやモデル、容量にもよりますが、スケールアップ/ダウンに数分~数時間掛かります(図②)。どの程度時間が掛かるか検証してから利用してください。
  • スケールアップ/ダウン切り替えのタイミングで数秒~数十秒の切断が発生します(図③)。リトライ処理などの考慮が必要です。
  • スケールアップ/ダウン切り替え直後は、キャッシュクリアされているためパフォーマンスが一時的に劣化する可能性があります。
  • 大幅にスケールダウンすると、主要データがメモリにのらずパフォーマンス劣化となる可能性があります。

f:id:vasilyjp:20190606183707p:plain

その他、SQL Databaseでは定期的にreconfigurationがあり一時的に接続できなくなることがあります。この場合もリトライ処理など考慮が必要になります。

メリット・デメリットありますがZOZOTOWNでは開発環境・本番環境にスケールアップ/ダウン(定期的なCPUコア数変更)を入れており、問題なく動作しています。
参考までにGeoレプリケーションを利用したスケールアウトを記載していますが自動化はしておらず、必要に応じて手動設定しています。

Azure AutomationでSQL Databaseをスケールアップ/ダウン

次にAzure Automationを利用して自動化します。
Azure Automationの実態は、PowerShellを定期的(または一時的)に動かすことが出来るジョブです。
SQL Databaseのスケールアップ/ダウンに限らず「Azure上の環境構築を自動化」「定期的なデータ作成」など様々な用途で利用できます。
最初にAzure Automation設定で躓いたところが2点あったのでお伝えます。

モジュールのインストール

Azure AutomationからPowerShellを実行したところ必要なモジュールが入っておらず実行できないことがありました。
各リソース毎にモジュールが用意されており、まず必要なモジュールをインストールする必要があります。「SQL Databaseを操作するモジュール」「Application Gatewayを操作するモジュール」と言った具合です。
初回実行でエラーとなった場合、モジュールがインストールされているかを疑います。

また、Azure操作はAzure Resource Manager(以下ARMと略します)というモジュールを使うことが多かったのですが、今後はAzモジュールに切り替わっていきます。
AzモジュールはARMモジュールの代わりになるものです。最新機能はAzモジュールに追加されていきます(AzモジュールがGAされたのは2018年9月頃です)。
世の中の記事を見るとARMモジュールで書かれれていることが多いので、Azコマンドに置き換えての実装することをオススメします。
ARMモジュールは2020年12月まではサポートされるようです。

Azモジュールについてはこちらを参照ください。

Azure Automationの実行アカウント

Azure Automationアカウントを作成すると自動で、Azure Active Directoryにアプリケーションが登録され、この権限に基づき実行されます。
また、デフォルトではアカウントの有効期限が作成から1年で設定されるため、気を付けないと1年後に実行できなくなります。
実際にあった話ですが、組織のチームメンバー変更により当初設定した人がチームを外れて数か月後、有効期限切れで動かなくなりました。
特に本番環境で定期的にAzure Automationで処理を実行している場合は、障害になりかねないので実行アカウントには注意が必要です。

f:id:vasilyjp:20190604133247p:plain

上記のことに気を付けてPowerShellを用意し、Runbookに登録します。
次にスケジュールを決めて設定完了です。
スケジュールは曜日や時間などで設定できます。

試しにAzure Automationを実行してSQL DatabaseをCPU8コアに変更してみます。

f:id:vasilyjp:20190604134609p:plain

正常終了を確認したので、SQL DatabaseでCPUコア数を確認します。

f:id:vasilyjp:20190604134320p:plain

問題なくCPUコア数が変更されていることを確認できました。
このAzure Automationを定期的に動かすことでスケールアップ/ダウンさせています。

まとめ

今回はAzure Automationを利用してSQL Databaseをスケールアップ/ダウンさせた事例をご紹介しました。結果、開発環境・本番環境で問題なくスケールアップ/ダウンできておりコストを40%削減できました。
コストの詳細はSQL Database 節約術に記載しています。

ZOZOテクノロジーズでは、このような問題を1つずつ改善しています。
一緒に前向きなチーム作りを盛り上げてくれるエンジニアを大募集中です。
ご興味のある方は、こちらからぜひご応募ください。

カテゴリー