こんにちは。MackerelチームSREのid:heleeenです。
Mackerelでは、2020年10月14日に計画メンテナンスを実施しました。今回は告知ブログに記載の通り、Mackerelが利用しているRedisをAmazon ElastiCache for Redis(以下、ElastiCache)へ移行しました。
本記事では、この10月の計画停止の裏側を紹介します。
どのようにElastiCacheへ移行するか
まず、RedisをElastiCacheへ移行した背景から説明します。
MackerelではこれまでいくつかのRedisおよびRedis Clusterを、Amazon EC2(以下、EC2)上に構築して運用していました。
しかし運用負荷が高いことと、ElastiCacheの機能拡張により、Mackerelで使用しているすべてのRedisをElastiCacheへ移行することにしました。
大半のRedisを無停止で移行
データストアの移行手法の1つとして、アプリケーションから移行前後の両方のデータストアに対して書き込む方法があります。Mackerelの時系列データベースにおけるRedis Clusterの移行では、この二重書き込みを採用し、アプリケーションを改修して、ユーザへの影響なしに、無停止で移行することができました。
この詳細は、AWSによるオンラインイベントAWS Purpose-Built Databases Weekにおいて、弊社のid:astjが発表しています。次の資料を参照してください。
また、その他のRedisは、データとアプリケーションの特性上、サービスを停止することなくElastiCacheへ移行することが可能なものが大半でした。
そしてこの10月の計画メンテナンスで、ついに最後のRedisがEC2からElastiCacheへ移されることになりました。
最後はElastiCacheへのオンライン移行を使用
上記の通り、これまでのRedisでは、二重書き込みの採用やデータの特性により、サービスの停止なしにElastiCacheへ移行することができました。
一方で、最後のRedisだけは保存しているデータの特性と、二重書き込み時に整合性の担保が難しいことから、同じように移行するのは厳しいものがありました。そこでご利用の皆さまにはご迷惑をおかけすることになってしまいますが、より安全に移行するためにも停止メンテナンスを選択しました。
このため今回だけは、ElastiCacheのオンライン移行を使用しています。
▶ Redis 用 Amazon ElastiCache ユーザーガイド - ElastiCache へのオンライン移行
この機能は、2019年10月にElastiCacheへのレプリケーションをサポートし、移行をより短時間で行うことができるようになりました。2020年10月現在、2.8.21以上のRedisを、5.0.5以上のクラスターモードが無効のElastiCacheへ移行することができます。
最後に残ったRedisでは、書き込みを停止してからのフェイルオーバーや、アプリケーションが参照するエンドポイントの切り替えもあり、サービスの停止なく移行することは厳しいのですが、このオンラインマイグレーションによってメンテナンス時間を短くし、安全に移行する計画を立てることができました。
メンテナンスに向けたさまざまな準備
Mackerelでは、メンテナンスの準備として以下を実施しています。
メンテナンス手順書のチーム内レビュー
Mackerelでは、サービスが稼働している環境の運用を主にSREが行っています。そのためメンテナンスもSREが主導していますが、今回のようにアプリケーションと密接に関わるものについては、アプリケーションエンジニアに協力を仰ぐこともよくあります。
アプリケーションエンジニアやSREなど、職種ごとにレビューの観点が異なることで気付ける部分もあるため、メンテナンス手順書は職種に関わらずレビューするようにしています。
メンテナンス手順は基本的にコマンドベースにしていて、メンテナンス当日は主にコマンドを実行してメンテナンスを進めていきます。以下は実際に実行したコマンドの一例です。
AWS_PROFILE=production CACHE_CLUSTER_ID=sample-redis aws --profile="${AWS_PROFILE}" \ elasticache complete-migration \ --replication-group-id "${CACHE_CLUSTER_ID}"
メンテンス実施中の役割分担
メンテナンス時の役割を明確にしており、具体的には以下を用意しています。
- メインオペレーター
- メンテナンスの手順を実施する
- メインチェッカー
- メインオペレーターの実施内容を1コマンドずつ確認する
- タイムキーパー
- メンテナンス中、各手順を実施した時刻を記録する
- 外部告知&コミュニケーション
- メンテナンス作業中の外部とのコミュニケーション窓口となり、Mackerel Statusの更新や、Twitterでの告知も実施する
タイムキーパーが記録した時刻は、次回のメンテナンス時間の見積もりや、振り返りに使っています。この役割は、前回のメンテナンスから用意するようにしました。
なぜタイムキーパーが必要になったのか
メンテナンスを告知する際に、メンテナンスにかかる時間を見積もる必要があります。事前に検証もしますが、検証環境のスペックが違っていたり、緊急事態のリカバリを考慮したりと、正確に見積もることはとても難しいです。
より正確にメンテナンス時間を見積もるため、コマンドを実行した時刻を記録しています。すべてのメンテナンスが同じ手順や内容ではありませんが、共通する部分について実際にかかった時間の記録があることで、次のメンテナンスではより適切に時間を見積もることができます。
メンテナンス中にも、前回の所要時間と比較することで、時間が異常にかかってしまっていないかの判断材料としています。
また、告知しているメンテナンス時間を超えてしまわないように、何時までにどこまで終わらせている必要があるかを事前に決めています。例えば今回のメンテナンスでは、サービス停止時間を最大2時間としました、その時間内でサービスを再開させるため、最初の1時間でこのラインまでは終わらせておきたいなど、時間を割り振ります。
このように、何が何時までに終わっている必要があるかの認識を揃えておくことで、順調に進んでいるかを把握できたり、もし作業に多少の遅延が発生したとしても、切り戻す必要があるかどうかを素早く判断できたりします。
リモートで停止メンテナンスを実施する方法
はてなでは、新型コロナウイルス感染症(COVID-19)の拡大に伴い、在宅勤務をしているメンバーも多くいます。Mackerelチームでは、これまで開発メンバーの多い京都オフィスに集まってメンテナンス作業を実施していましたが、今回初めて一拠点に集まらず実施することになりました。
オンラインでは、一度に発話できる人数が限られていたり、隣に座っていて画面を見せることも難しかったり、個人の在宅環境やマシンの調子に左右されてしまうこともあります。メンテナンスのメインオペレーターやチェッカーなどの役割を決めておけば、オンラインの通話が混線して作業を滞らせることもなくなります。
当日には、環境が不安定になってしまったメンバーがいたので役割の交代もありましたが、事前に手順をしっかりレビューして、検証していたことで、役割を交代してもつつがなくメンテナンスを進めることができました。
なお、メンテナンス時の状況確認として、自分の見ている情報を共有するため、グラフを通知チャンネルへ投稿する機能も活用していました。詳細は次のヘルプを参照してください。
検証環境を利用して事前にリハーサルも実施
Mackerelでも、本番でサービスを提供する前に検証する環境を用意しています。本番に比べると小さいのですが、本番と同様の構成にしています。この検証環境を利用して、本番でメンテナンスを実施するより少し前の時期に、本番相当の手順で移行のリハーサルを行いました。
これはメンテナンス手順を確認する目的もありますが、本番のメンテナンスを迎える前に同様の手順を一度実施し、課題点を見つけたり、手順を検証しておくことで本番メンテナンスへの不安感を減らしたりすることに繋げられていると思います。
今回の事前検証では、サービスを再開する前にMackerelチームのみにアクセスを許可して動作検証を行う段階で、アクセスができないという事象が起こりました。原因は、リモートでのメンテナンス実施が初ということもあり、リモートで使用していたVPNがアクセス許可されていないことでした。
これが当日起こってしまうと混乱の元になっていたはずなので、事前に解消できてよかったです。
Redisを安全に効率よく切り替えるために
今回のRedisの切り替えでは、前述したようにElastiCacheへのオンライン移行を採用しましたが、具体的には以下のような方法で実施しました。
参照するRedisをDNSで切り替える
移行前のRedisはVIPで参照されていましたが、これがElastiCacheの提供するエンドポイントへ変更になります。
参照するRedisを切り替えるためにアプリケーションのビルドとデプロイを行うと、時間がかかってメンテナンス時間が長引いてしまいます。
これを回避するため、今回の切り替えでRedisを参照しているアプリケーションでは、あらかじめRedisのVIPではなく、Amazon Route 53に用意したプライベートホストゾーンに登録したレコードを参照するよう変更しておきました。
これによって当日は、アプリケーションの設定ではなくDNSレコードを変更すればよく、参照を短時間で切り替えることができました。
オンラインマイグレーションの実施
オンラインマイグレーションでは、まずElastiCacheをEC2のRedisのレプリカとして設定する必要があります。そのため、メンテナンス日より数日前にEC2のRedisからElastiCacheへのマイグレーションを開始しました。
マイグレーションはCLIでもコンソールからも開始可能で、キーの多いRedisでも1分ほどで最初のレプリケーションを完了しました。
▶ 移行の開始 - Redis 用 Amazon ElastiCache ユーザーガイド
メンテナンス日には、サービスを停止してクライアントの準備ができたら、マイグレーションの完了処理を実行します。これによってレプリケーションが停止され、プライマリに昇格します。これも同様にCLIまたはコンソールから実行可能で、数分で完了されました。
▶ データ移行の完了 - Redis 用 Amazon ElastiCache ユーザーガイド
切り替えの事故防止のために
メンテナンスを実施するにあたって、Redisを参照している箇所を調べたり、Redisの参照をDNSに切り替えた場合のDNSキャッシュの設定を確認したりして、問題は起きないはずということを確認していました。
しかし、切り替え完了後にEC2側のRedisを意図せず参照や更新してしまうと、不具合を起こしてしまう可能性があります。これを防ぐため、ElastiCacheへのオンラインマイグレーションを完了したのち、EC2側のRedisはセキュリティグループを変更して、sshのみを許可するようにしました。これによって、アプリケーションがEC2側のRedisへ直接接続することはできなくなります。
sshのみを許可しているのは、もし移行作業中やメンテナンス後にEC2側のRedisを確認する必要ができたときなどに、サーバにログインして確認できるようにする意図があります。
メンテナンス後の振り返りとまとめ
メンテナンス終了後に振り返りを実施しています。今回は、タイムキーパーに記録してもらった時間を元にメンテナンス中の時間経過を振り返ったり、GKPT形式でメンテナンス参加者の意見をまとめました。
今回のメンテナンスのよかったところとして、次のような点が上がりました。
- 初めてリモートによる停止メンテナンスを実施したが、順調に終えることができた
- 当日に発生した役割分担の交代や、切り替え後の動作検証をスムーズに実施することができた
一方、改善点としては、次のような点が上がりました。
- 動作検証の項目で曖昧な部分があり、確認者に委ねられてしまった
- より停止時間を短くするためにできることをしていきたい
こういった課題を今後の改善点としてタスクに積んだり、メンテナンス準備や振り返りの内容を元にメンテナンスのドキュメントや手順のテンプレートを更新したりしています。
ElastiCacheへ移行して得られたもの
今回の切り替えにより、Mackerelで運用していたRedisはすべてElastiCacheへ移行されました。
これまでは自前で冗長構成にしていたものがマネージドになったことで、フェイルオーバーやスナップショットが自動で行われるようになりました。SREチームとしては不定期に発生する作業が減り、開発に当てる時間が増えたことを体感しています。
また、移行したのは障害の起こりやすい箇所であったため、よりサービスが安定して稼働させられるようになったと考えています。オペレーションがAPIやCLIで実施できるようになり、とても簡略化されたことも大きいです。
12月にも計画メンテナンスを予定しています
10月に実施した計画メンテナンスについて、その準備から次回に向けた振り返りまでを紹介しました。
Mackerelでは、12月にも計画停止を予定しています。次回は、より時間のかかる作業があり、ご利用の皆さまにはご迷惑をおかけしますが、サービスの品質改善と安定稼働のため、ご理解のほどよろしくお願いいたします。
id:heleeen
Mackerel開発チーム SRE。2019年9月入社時より現職。HashiTalks: Japan 2020に登壇。
GitHub: heleeen
blog: helen's blog