簡単に始める障害対応訓練
この記事は Eureka Advent Calendar 2023の 12日目の記事です。
こんにちは。SRE & DataManagement Teamのyucattyです。
大規模な障害は、頻度は低いものの、起きた時の重大さに備えて日頃から訓練しておきたいものですよね。とはいえ、組織を巻き込み、工数を確保するのは大変なことです。今回の記事では、チーム内で行った簡単な障害対応訓練のお話をしたいと思います。
障害対応訓練の目的とアウトカム
今回の障害対応訓練は、大規模なシステム障害(外部・内部要因問わず)が発生した際のオペレーションとMTTR(平均復旧時間)をチーム内で共通認識を持つこと、そして、日頃から障害対応訓練を行うことで、技術的なシューティングを行える人の属人化を防ぐという目的で行いました。
また、訓練から得られることは以下を期待しました。
- 大規模な障害シナリオに対し、MTTRが予測できる
- 技術的なシューティングを行う人の属人化を防ぐ
- 障害対応訓練を今後も継続的に行える基盤や手法が整備される
- データ復旧等の手順がRunbookに落とし込めている
訓練の概要
今回は起こり得る障害を事前に予測し、想定される復旧手順を用意した演習を行いました。
やったこと
サービス内で特に重要なコンポーネントを対象に、コンポーネント毎に起きうる障害を洗い出しを行いました。その後、1コンポーネント毎に障害の結果として発生するオペレーションの確認と復旧時間の確認します。ペアーズにおける重要なコンポーネントはAurora、Elasticsearch、Redisなどのデータストアです。
初回は、Auroraに対象を絞り、データ欠損時の復旧とAZ障害によるフェイルオーバーで発生するオペレーションの確認を行うことにしました。
やらなかったこと
特定の障害事例を想定し、障害を再現した環境を用意し、インシデントコマンダーを実際に立てた障害対応訓練は今回は行っていません。
Auroraのデータ復旧方法
障害対応訓練の話をする前に、Auroraのデータ復旧方法を簡単に整理しようと思います。データ復旧方法は3パターンあります。(2023/12/12時点)
バックトラック
- 指定した時間まで DB クラスターを巻き戻す
- バックトラック機能を有効にして作成した DB クラスターでのみ使用可能
- バックトトラックウィンドウの上限は 72 時間
- 新しい DB クラスターを作成しないので高速
ポイントインタイムリカバリ(PITR)
- DB クラスターを特定の時点に復元し、新しい DB クラスターを作成する
- 自動バックアップはAuroraの場合デフォルトで有効
- バックアップ保持期間 (1 ~ 35 日)
- 最新の復元可能時刻は5分以内
スナップショット
- DB クラスターを特定の時点に復元し、新しい DB クラスターを作成する
- 保持期間に制限がない
- 手動スナップショットを作成する
PITRとスナップショットは新しいクラスタに対して任意の時点に一番近いバックアップを適用するので、仕組みとしては同様ですが、PITRは保持期間内であれば時刻指定が可能な点と、保持期間が異なります。停止点を取らずに、DBクラスターそのものを巻き戻しするバックトラックを利用するユースケースが思いつかなかったので、今回はPITRとスナップショットをオペレーション確認の対象としました。
訓練内容
それでは実際に行った訓練内容を見ていきたいと思います
①本番DBをポイントインタイムリカバリで復旧する手順と復旧時間の確認
terraformで復元するクラスターを定義し、terraform applyにかかる時間を計測しました。terraformのtimeoutと、apply中にIAM Roleのセッション切れが起こる可能性があるのでそれぞれ3時間に延長しました。
resource "aws_rds_cluster" "db_cluster_from_pitr_2023XXXX" {
### 略 ###
restore_to_point_in_time {
# 復元するクラスターID
source_cluster_identifier = aws_rds_cluster.main_db.id
restore_type = "copy-on-write"
# 復元したい地点のリカバリー時刻
restore_to_time = "2023-XX-XXT05:00:00Z"
}
### 略 ###
## timeoutを起こす可能性があるので180mに指定
timeouts {
create = "180m"
}
}
resource "aws_rds_cluster_instance" "instance_2023XXXX" {
### 略 ###
cluster_identifier = aws_rds_cluster.db_cluster_from_pitr_2023XXXX.id
identifier = "instance-2023XXXX"
### 略 ###
## timeoutを起こす可能性があるので180mに指定
timeouts {
create = "180m"
}
}
②本番DBをスナップショットで復旧する手順と復旧時間の確認
こちらも①と同様にterraform applyにかかる時間を計測しました。
## 復旧したいsnapshot名を指定する
data "aws_db_cluster_snapshot" "ss_2023XXXX" {
db_cluster_snapshot_identifier = "rds:main-db-2023-XX-XX-XX-XX"
}
resource "aws_rds_cluster" "db_cluster_from_snapshot_2023XXXX" {
### 略 ###
snapshot_identifier = data.aws_db_cluster_snapshot.ss_2023XXXX.id
### 略 ###
## timeoutを起こす可能性があるので180mに指定
timeouts {
create = "180m"
}
}
resource "aws_rds_cluster_instance" "instance_2023XXXX" {
### 略 ###
cluster_identifier = aws_rds_cluster.db_cluster_from_snapshot_2023XXXX.id
identifier = "instance-2023XXXX"
### 略 ###
## timeoutを起こす可能性があるので180mに指定
timeouts {
create = "180m"
}
}
③writerインスタンスがあるAZの障害発生を想定して発生するオペレーションを確認する(Stage環境)
事前準備
- 訓練用のDBクラスターとインスタンスをスナップショットから作成する
- 訓練用DBにStage環境のアプリケーションの接続先を変更する
- リクエストが定常的に来ている状態を再現するため、負荷試験ツール(昨日の記事でも紹介しています)で、Stage環境のアプリケーションに負荷をかける
実施内容
- writerインスタンスを削除し、AZ障害により接続できない状況を再現
- フェイルオーバーすることを確認
- エラーログの確認
- フェイルオーバー後のアプリケーションの動作の確認
結果
フェイルオーバーを確認した後、以下のようなエラーが発生したことを確認しました。
XExec: Error 1290 (HY000): The MySQL server is running with the --read-only option so it cannot execute this statement
これはアプリケーションのDNSキャッシュの影響で、フェイルオーバー後に古いライターに更新系のクエリが投げられてしまうために発生するものです。今回はAZ障害を再現するために、インスタンスの削除を行いましたが、削除中の場合も一度読み取り専用モードになることが確認できました。
mysql> show variables where variable_name='innodb_read_only';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| innodb_read_only | ON |
+------------------+-------+
1 row in set (0.01 sec)
参考:
そのため、フェイルオーバーのイベントトリガーでアプリケーションコンテナ洗い替えを行うイベントサブスクリプションを作成し、MTTRを向上させることにしました。
訓練を終えて
MTTRを計測することで、さらに短くするための改善に繋がったのがよかったです。
また、terraformのtimeoutや、IAM Roleのセッション切れなどは、実際にやってみないと気付きにくいポイントだと思いますが、障害対応訓練を通して考慮事項としてRunbookに落とし込むことができました。
Runbookの作成で技術的なシューティングを行う人の属人化を防ぎ、データのリカバリ手法がチーム内で共通の認識を持てていることで、実際の障害時においても初動のコミュニケーションがスムーズになりそうだと感じました。
まとめ
今回はAuroraに対象にしたデータ復旧手順とAZ障害を想定したフェイルオーバー時に発生するオペレーションについて紹介しました。データ復旧時間の計測に加え、Auroraのデータ復旧のパターンやフェイルオーバーの挙動について確認できる良い機会となりました。
チームメンバーの入れ替わりが起きた時に属人化を防ぐという観点でも、障害時のオペレーションの確認は定期的に行うことは重要です。
コンポーネント毎に分けて行うことで、障害対応訓練自体のハードルも下がると思うので、参考にしていただけたら幸いです。