NGW開発BLOG
← 記事一覧へ
·#086

仕上げは、レプリ設定で収まる一度きりの手順を、何度でも回せる一本にした

二台を組んだ「あと」の仕上げ ― 保管先を分ける、最初のバックアップ、預かり、監視を映す ― が、いくつものボタンと手作業に散らばっていた。それを一本にまとめた。肝は機能の多さではなく「何度でもやり直せる」ことのほうだった。今日はそこに二つ足した。複製が運んでくる大きすぎるメモリの取り分を直す「最適化」と、預かりの一日二回化。

二台を組んだ「あと」が、いつも散らかっていた

NGW のサーバは二台一組で動く。NGWメインNGWクローン。組むところ自体は、レプリケーションを張れば済む。困るのはいつも、そのあとだった。

保管先をシステムディスクから分ける。最初のバックアップを一回とる。メインに預ける。監視に映るよう状態を作り直す。この「仕上げ」のひとつひとつが、保守コンソールの別々のボタンや、手作業や、記憶に散らばっていた。組むたびに、どれをやったかを思い出す。

手順を工程順に案内するアプリは、少し前に別で作った(行ったり来たりで、よく忘れる)。だが案内と、仕上げの実体は別だ。案内はしてくれても、押す先はあちこちのままだった。

思い出せないものは、抜ける。抜けたまま緑になって、しばらくして気づく。

だから、仕上げのほうを一本にまとめた。レプリ設定という画面である。

NGWレプリ設定アプリの画面。ヘッダーは「NGWレプリ設定 ― NGWメインとNGWクローンをレプリで結ぶだけのアプリ」。冒頭の「このアプリができること」に、2台のIPを入れるとレプリが動くところまで通すこと、鍵の受け渡し・IP構成・役割ごとのcron・複製ユーザー・一貫ダンプの要否までまとめて面倒を見ること、そして「組む以外のことはしません。本番切替(promote)・フェイルバック(demote)・バックアップ・復元・データ移行はここにはありません」「仕上げに、クローンでバックアップを1回だけ取ります」と書かれている。① 2台を確認する ― NGWメインのIP 192.168.0.212、NGWクローンのIP 192.168.0.213、ユーザー administrator、ポート 2222 の入力欄。その下に二枚のカードで、NGWメインは server-id=1 / 書込可、NGWクローンは server-id=2 / 読取専用・追随中 IO=Yes/SQL=Yes と出ている。② 組み立てる ― 複製ユーザーのパスワード欄と、三つのチェックボックス。「掃除(任意)」「完全に初期化」、そして今日足した「最適化(既定ON)☑ buffer_pool を各機体のメモリに合わせ直す ― クローンは複製元(メイン)の値を引き継ぐため過大になりがち。過大な機体だけ下げます(メインは適正なら無変更)。失敗しても自動で元に戻します」。赤い「② 組み立てる」ボタンと、③ 組み上がりを確かめる欄が続く

まとめた肝は、機能の数ではなく「何度でも」

一本にして分かったのは、大事なのは「できることが多い」ことではなかった。何度回しても安全で、同じところへ収束すること ― それが肝だった。

現場では、一発で綺麗に決まることは少ない。クローンをイメージから作り直す。レプリを張り直す。バックアップの世代を作り直す。そのたびに仕上げをやり直す。だから仕上げは、冪等でなければならない。二回押しても壊れない。既に済んでいるところは黙って飛ばし、変わるところだけを直す

この性質があるから、「とりあえずもう一回レプリ設定を回す」で状態が揃う。覚えておくのは、画面の名前ひとつでいい。

接続先を指すのも IP だけだ。相手の二台へ IP で届くので、仕上げの最中に別のアプリや別の画面へ渡り歩かない。組んだら、そのまま最後まで収まる。

レプリ設定でできること

いま、この一本が受け持っているのはこれだけある。どれも何度でも回せる。

できること中身局面
二台の確認相手が本当に別の二台か、組める状態かを見る毎回
個体化複製で重なった server-id / UUID を割り直す複製直後
レプリ構築複製を張る。中身がズレている時だけ、元をまるごと写し直す毎回
保管先の分離バックアップをシステムディスクと別の場所へ毎回
最適化buffer_pool を機体のメモリに合わせ直す(今日追加毎回
最初のバックアップクローンで一回とる毎回
預かりメインが from-clone に一回。以後は自動で追従(今日2回/日に毎回
監視の再生成両機の見張りを走らせ、モニターを即座に緑へ毎回
掃除 / 完全初期化古い世代を退避 / 0から作り直す(任意・開発ペア向け)頼んだ時

重いのは「元をまるごと写し直す」ところだけで、それは本当に要るときだけ走る。中身がズレていないのに毎回まるごと写す、ということはしない。だから「もう一回」が軽い。

今日、二つ足した

最適化 ― 複製が運んでくる「大きすぎる取り分」

クローンのメモリが 87%(3.3GB 中 2.8GB)まで来ていて、しかもスワップに 2GB 逃がしていた。中を見たら、MySQL 一つで 2.4GB を抱えている。原因は innodb_buffer_pool_size2176MB になっていたことだった。

なぜそんな値か。クローンはメインをイメージ複製して作る。メインは搭載メモリが大きいので 2176MB は適正だ。ところが複製すると、その設定ファイルごとクローンへ運ばれる。クローンの仮想マシンは 3.3GB しか積んでいない。3.3GB に 2176MB を渡せば、OS と Web の分が残らず、スワップに落ちる。

面白いのは、これが落ちない誤りだったことだ。当初は「メモリが尽きて MySQL が殺されるところまで放置して、復旧手順を記録しよう」と考えていた。だが実測したら、OOM(メモリ不足による強制終了)の記録は起動以来ずっとゼロ。8GB のスワップが過大な取り分を吸収していて、落ちない。ただ、ずっと重い。予定していた「観察」の前提が、測ってみたら崩れた。

直し方は、既にあった。保守コンソールの「最適化」は、その機体のメモリから渡してよい上限(実測に基づき割当の 30%)を出して buffer_pool を書き換える。クローンに向けて回せば、推奨は 896MB。当てたら、こうなった。

使用メモリ  2.8G → 1.5G
mysqld     2.4G → 1.16G
スワップ    2.0G → 75M

レプリも再起動から自動で復帰し、遅延ゼロ。

問題は、これが手作業だったことだ。複製するたびに、誰かがクローンで最適化を回さないと直らない。回さなければ気づかない。だから、レプリ設定の仕上げに組み込んだ。組む流れの中で各機体を測り直し、過大な機体だけ下げる。メインは適正なので何も起きず、クローンだけが下がる。失敗しても自動で元に戻すので、レプリ本体は壊さない。

これで、次からは複製してレプリ設定を回すだけで、この誤りが構造ごと消える。今日の手作業が、明日から要らなくなった。

預かりを、一日二回に

もう一つ。メインが「預かる」(クローンのバックアップを引いて手元にも置く)タイミングが、深夜 01:10 の一日一回だけだった。クローンは一日四回とる。だから預かりは、クローンの最新から最大で丸一日遅れる。

ここに 12:45 を足して二回にした。01:10 は前夜の世代を、12:45 は昼の世代を拾う。遅れが半日以内に収まる。

日中にも走らせるので、「重くないか」を先に測った。一回46秒。しかも預かりは、生きているデータベースを止めて何かをするわけではなく、クローンが取り終えたファイルを引いてくるだけの背景仕事だ。日中に走っても利用者に響かない。測ってから足した。

線引き ― 「立ち上げに要ること」だけを入れる

一本にまとまってくると、つい「あれもここで」と足したくなる。そこで自分に線を引いた。

仕上げに入れるのは、「組んだ直後に一度やれば、その機体が正しくなる」ものだけ。

buffer_pool は入れる。なぜなら機体のメモリに依存する値で、複製すると壊れるからだ。一方で、REDO ログや一時表の大きさ、I/O の見積りといった他のつまみは、両機で同じで、複製しても壊れない。これらは「最適化」タブに置いたまま、仕上げには持ち込まない。仕上げが最適化タブの丸写しになった時点で、線が消える。

恒久的な運用 ― バックアップの日々の実行、本番切替、無人運用 ― も、仕上げには入れない。それぞれの持ち場(保守コンソール、Mac設定)がある。レプリ設定は「一組を正しく立ち上げるまで」で収まる。

この線を守るかぎり、「できることは全部ここ」ではなく「立ち上げに要ることは全部ここ」になる。多すぎて濁る、を避けられる。

これからも育てる

まだ足せる余地はある。預かりをクローンの四回すべてに追従させるか(いまは二回で「半日以内」を担保している)、実態と対処を並べる診断をどこまで仕上げに含めるか。だが方針は決まっている ― 足す前に必ず「これは立ち上げに要るか、それとも運用か」を問う。要るものだけが入る。

覚えておくことは、これで一つ増えたのではなく、むしろ減った。組んだらレプリ設定を回す。それで収まる。

AIとの協働作業での学び

今日いちばん効いたのは、新しい機能を思いついたことではなく、測ってから決めたことだった。

クローンのメモリを「いずれ尽きるはず」と決めつけて、復旧手順を書く段取りに入りかけていた。だが AI と一緒に実際に測ったら、OOM はゼロで、スワップが吸っていて落ちない。予定していた物語のほうが、事実と違った。そこで話を無理に通さず、「前提が崩れた」と言い直せたのが良かった。真因は runaway なメモリ増ではなく、複製で運ばれた静的な設定過大 ― 直し方は既にある機能を、仕上げに繋ぐだけだった。

もう一つ、正直に書いておく。仕上げの「監視を即座に映す」処理で、私(と AI)は一度、間違ったファイルを更新するコードを足していた。モニターが実際に読むのは機体ごとの公開状態なのに、別名の内部ファイルのほうを書いていた。画面には映らない。気づいて、余計なほうを消し、既にあった正しい経路に一本化した。足したものを、あとで引くのも仕事のうちだ。

通底しているのは、構築ナビの日に書いたのと同じ一行だと思う。「気をつけよう」で終われば、また踏む。踏めない形にするしかない。今日の最適化を仕上げに埋め込んだのは、まさにそれだった。複製するたびに人が思い出して直す、では必ずいつか忘れる。思い出さなくても直る形にして、初めて収まる。