地方エンジニアの学習日記

興味ある技術の雑なメモだったりを書いてくブログ。たまに日記とガジェット紹介。

【RDS】RDSでBlue/Greenデプロイ!すごい!!すごい!!!!(色々修正版)

qiita.com

この記事は「MySQL Advent Calendar 2022」の20日目の記事です!前に書いたやつ(機能発表された数時間後に書いた)の加筆修正版になります!

dev.classmethod.jp

AWS re:Invent 2022で発表されていた機能。最初見た瞬間「???」となった。謎技術だすごい!!となった。

仕組み的な話

docs.aws.amazon.com

公式ですでに詳しく書かれている。とてもわかり易いのが下の図でコンソールをポチポチするだけでこんな環境が用意される。上が既存の本番環境で下のgreenが新しく変更を加えるstaging環境と読んでいるものになる。既存のPrimaryにレプリカとして1台追加してそのレプリカにさらにスタンバイとリードレプリカを構築している。(binlog仕組みを使う。例ではbinlog_formatはMIXEDで設定されている)。構築した時点でStaging環境へはアクセス(read/write)が可能(Green 環境の DB インスタンスはデフォルトで読み取り専用なので変更は設定必要)になっているのでスキーマの変更などを行うことも可能になる。

Stagingで色々やった後にスイッチオーバーを実行することでStagingが本番環境へ昇格する。図は下のようなイメージで新本番が旧本番の識別子を引き継いで旧本番にはoldというsuffixがついている。アプリケーションは旧本番と新本番で設定変更が不要で接続を切り替えることが出来る(コネクション永続化とかアプリ独自のDNSキャッシュとか持ってるケースだとそうは行かないけど...)。

これ前から出来たよね..??

図を見た瞬間気づいたがこれは前から同じことを手動で行うことは可能だった。というのもRDSは多段レプリケーションを公式で提供しており同じ仕組みをGUIポチポチ+MySQLにログインして色々やってDNS切り替えてとかをやれば可能ではあった。(ちなみにこの機能が提供されたのは2013年だった。それはそれですごい。。。AWS Release Notes)。今回はそのへんがマネージドでやれるようになってくれたので便利だよねという感じ。特に記載にもあるガードレール(Switchover guardrails)なんかはレプリカの状態とかを目視で確認する部分をRDS側が吸収してくれるのでめっちゃよさそう。

本番でやるの大変そう..??

スイッチオーバーのタイミングで1分間くらいダウンタイムが必要となっている。これは静止点を取るために内部では多分テーブルロックなんかをやってるんじゃないかと思う(未検証なのでわからない)。スイッチオーバーのアクションのうち気になったものを書いてみる

1. 両方の環境でプライマリ DB インスタンスでの新しい書き込み操作を停止する
2. 接続をすべて切って新規接続の受付を停止する
3. Green 環境でレプリケーションが追いつくのを待つ
4. DBの名前変更
6. 新規接続を受け付ける

時間がかかりそうなのは1,3辺りで例えば書き込みが10分のクエリがあったらその間テーブルロックが取れたテーブルについてはクエリが刺さったりしそう。時間がかかるDDLとかもメタデータロックの問題が発生しそう。そこからさらにレプリカでも実行するのを待つのでダウンタイムは結構読むの難しい?スイッチオーバーのベストプラクティスには運用環境でトラフィックが最も少ない時間を特定しその時間にやることを進められている。writeがそこそこある環境だとサービスメンテ入れるなりをしないとオンラインではやれなそうだなと...スキーマ変更に限って言えば条件さえ揃ってしまえばMySQLのオンラインDDLなりpt-online-schema-changeのほうがよさそうに思える。スキーマの検証は本番環境しかDBが無い場合を除いて本番以外(dev環境とかintegrationとかローカルとか)でもやれると思うのでこの用途はあまり見えないかなという感じか

サービスをメンテナンスをいれる前提でのMySQLエンジンのアップデート時には工数がめっちゃ省けるのでよさそう。後はGreen環境を作るだけ作ってそこで負荷テストとかやるみたいな用途も。本番にいれるのは怖い設定とかレプリカラグがどれくらい出るか読めないようなDMLとかをそっちで流してからBlueで実行してスイッチオーバーはしないみたいなのもできそう。(ただこれめっちゃお金かかるよな...)

感想

前から出来たけど自動でかつ安全に実行できるようになったのでMySQLのアップデートは間違いなくかんたんに出来るようになったので便利!!

その他

ベストプラクティスにバイナリログの最適化をしましょうね書かれている

Optimize read replicas for binary log replication.

For example, if your DB engine version supports it, consider using GTID replication, parallel replication, and crash-safe replication in your production environment before deploying your blue/green deployment. These options promote consistency and durability of your data before you switch over your blue/green deployment. For more information about GTID replication for read replicas, see Using GTID-based replication for Amazon RDS for MySQL.

GTIDとパラレルレプリケーションはよいとして「crash-safe replication」ってなんだろと思って調べた。

nippondanji.blogspot.com

昔のMySQLのレプリカはクラッシュセーフじゃなかったらしい。IOスレッドとSQLスレッドはそれぞれどこまで適用したかを管理ファイルに書き込んでいたためSQLスレッドがトランザクションを実行してコミットした後にサーバがクラッシュするとSQLスレッドはどこまでbinlogを適用したかを管理ファイルに書き込むこと無く終了してしまう。サーバの再起動時にトランザクションが2回実行されて不整合が起きてしまうという。これを解決するのがrelay_log_info_repositoryをTABLEにするというもの。TABLEにすることでトランザクション内でテーブルの更新が走るためサーバクラッシュのタイミングがどこであろうと不整合は起きない。(管理ファイルへのfsync(2)をトランザクションに入れればいいじゃんと思ったがパフォーマンスとか的にだめだったのだろうか..??)

Terraformも早くもあるっぽい

github.com

applyすればGreen作ってスイッチオーバーまでやってくれる。MySQLアップデートめっちゃ楽になりそう