一日でLightsailサーバを最新イメージに移行して、フィード生成を10倍速くした話 – Claude Code実践録(インフラ編)

lightsail migration 2026 Network

このブログのサーバを、最新のイメージに移行しました。ダウンタイムはゼロ、RSSフィードの生成は8秒から0.78秒に、記事ページの転送量は3分の1になりました。かかったのは一日です。

きっかけは、サイトが落ちていたことでした。Claude Codeと原因を調べていくと、自分の思い込みが次々に覆されていきます。最終的に、設定の手直しではなくイメージごと移行することを決めました。

コーディングにAIを使った話は以前書きました。今回はインフラ編です。

コードを一行も書かずにAudio Unitプラグインを2週間で完成させた話 - Claude Code実践録
最近、YMulator-SynthというYM2151(OPM)FM音源のシンセサイザープロジェクトをリリースしました。このプロジェクトの特徴は、私がコードを直接書いた回数がゼロ だということです。すべてClaude Codeというツールを使ったAIコーディングで実装しました。本記事ではそのAIコーディングの記録と考察を述べます。

一日でやったこと

RSSフィード生成8.0秒 / 646KB0.78秒 / 362KB
記事ページ(gzip後)115KB42KB
サーバ側の記事描画8,156ms833ms
500エラー率46%0%
OS / PHPDebian 11 / 8.1.18Debian 12 / 8.2.33
月額$7.95(1GB/1vCPU)$12.00(2GB/2vCPU)

やったのは、落ちた原因の究明、サーバイメージの移行、性能改善、セキュリティ強化、そして監視の設置です。月額はプランを増強したぶん上がっていますが、旧プランで繰り返していたメモリ枯渇ごと解消しています。

なぜ触ることになったか

きっかけは、サイトが「データベース接続確立エラー」で落ちていたことでした。しかも私はそれに気づいていませんでした

CloudFront 5xxエラー率
2026-08-29 18:25   74.0%
2026-08-29 20:25   84.1%
2026-08-30 19:25   68.5%
2026-08-30 20:25    3.6%   ← 対処開始

26時間以上、7〜8割のリクエストが失敗していました。この数字はCloudFrontが無料でずっと記録していたものです。見ていなかっただけでした。

監視を入れていなかったわけではありません。Jetpackのダウンタイム監視を有効にして、通知はスマホアプリで受け取っていました。ところが、そのアプリがいつの間にか自分のブログの購読を解除していて、通知が届かなくなっていたのです。さらにDBを調べると、Jetpack自体の同期も止まっていました。

jp_sync_last_success_sync → 2026-07-03 22:21 JST

7月3日を最後に58日間、一度も同期していません。通知の経路と監視本体が、二重に沈黙していたことになります。そしてどちらも、止まったことを知らせてはくれませんでした。後日、CloudWatchに残っていた日次データ(1時間粒度なら15ヶ月遡れます)を掘り直すと、疑いは確定に変わりました。7月4日から8月29日までの57日間、日平均の5xxエラー率が20%を下回った日は一日もなく、大半の日は5〜8割。このブログは実質2ヶ月落ちていたのです。

AIに何をどこまでやらせたか

準備

Claude Codeは手元のターミナルで動き、私が普段打つコマンドをそのまま実行します。渡したのは二つだけです。まず~/.ssh/configに接続設定を書き、「ssh blogでサーバに入れます」と伝える。調査はこれで始まります。移行を頼む段階になってから、AWS CLIのプロファイルを追加で渡しました。静的IPの付け替えやRoute53の修正はこちらの経路です。

認証は有効期限つきなので、切れるたびに私が再ログインします。手間ではありますが、AIが持つ権限はその時々で自分が渡したものだけ、という安心感があります。準備はこれだけです。ここから先は、すべて会話で進みました。

まず全部読ませて、当たりをつけさせる

最初の指示は「WordPressをホストしているサーバが最近不安定。原因を探って」程度の曖昧なものでした。そこからAIは、メモリの状態、journal、Apacheのログ、監視プロセスのログを順にさらっていき、数分で当たりを二つ挙げてきました。

  • journalに、OOM KillerがMariaDBを殺した記録が6回
  • 231MBある監視ログの中に、一行だけ残っていた決定的な記録
"mariadb was unmonitored after 5 failed tries"

監視プロセス(gonit)は再起動に5回失敗すると、そのサービスの監視自体をやめる仕様でした。つまり6月21日以降、DBが死んでも誰も起こさない状態だったのです。落ちたままだった理由はこれでした。

231MBのログから一行を拾うのは、人力ではまずやりません。まず全体をさらわせて当たりをつけさせ、それから深掘りする。探索のコストがほぼゼロになるのが、インフラ作業でAIがいちばん効くところだと思います。

当たりは「測って」潰す

ただし、探索で出てきた仮説をそのまま信じないことも大事でした。「なぜ遅いか調べて」ではなく、実際に走らせて数字を出させます。

たとえば復旧後もフィードの生成に8秒かかっていた件では、WordPressのthe_contentに登録されている26個のコールバックを1つずつ計測させました。

      ms   callback
  3308.4   do_shortcode
    68.9   replace_anchor_links
    28.0   do_blocks
     7.9   url_to_external_blog_card

1つのコールバックが96%を占めていました。さらにショートコードを1種類ずつ分離して計測させ、原因を1個に絞り込む。正体は、障害中に利用資格が失効した外部APIを、全ページで1件150msかけて呼び続けていたことでした。失敗を1時間キャッシュする仕組みを入れて、8.0秒が0.78秒になりました。

フィード以外も同じ進め方です。記事ページの転送量が3分の1になったのは、テーマの設定で全ページのHTMLに埋め込まれていた671KBのCSS(116種類のブロック向け。実際に使っていたのは7種類でした)を外部ファイルに戻したことと、数式ライブラリ(約400KB)を数式を含む1記事だけで読み込むようにしたことが主です。どちらも、何が重いかを測って初めて見つかったものでした。

ログをさらうのも、測るのも、要は事実に基づいて進めるということです。これにはもうひとつ効用がありました。AIは時々、自信満々に間違えます(Lightsailの課金をEC2と混同して説明された、などがありました)。それでも判断を事実に紐付けていれば、間違いは次の計測で露見します。「そう思う」ではなく「こう出た」で進める限り、AIの間違いは致命傷になりませんでした。

既定値も信じすぎない

そもそもなぜOOMが起きるのか。調べると、搭載975MBのインスタンスに対してPHPの同時実行数が45に設定されていました。1プロセス66〜77MB(実測)なので、最大3GB相当です。

私はここを疑ったことがありませんでした。AWSが公式に配っているイメージなのだから、サイズに見合った設定のはずだと思っていたからです。ところが移行先の新イメージ(Lightsail公式)を実測すると、同じ「1GB向け」でこうでした。

1GB向け既定値BitnamiLightsail公式
PHP同時実行数455
Apache MaxRequestWorkers2565
PHP memory_limit512M128M

9倍の開きです。しかも新イメージの中には、AWS自身のこんなコメントがありました。

# WordPress instances that come with micro memory size (< 1.5 GB) OOM under
# common plugin workloads; a small swap file mitigates this.

「1.5GB未満のWordPressは一般的なプラグイン構成でOOMする」と認めた上で、小さいプランのときだけスワップを自動作成する作りです。今回は実測に基づいて同時実行数を8に下げました。この時点ではまだ旧の1GBインスタンスでしたが、それでも40並列を投げて空きメモリ354MBを維持できています。3年間「なんとなく重い」で済ませていた問題でした。

同じ種類の思い込みがもうひとつありました。ログのローテーションです。当然されているものだと思っていましたが、Bitnami自身の監視ログ(gonit.log)にはローテーション設定が存在せず、2023年の構築以来育ち続けて231MBになっていました。探索のところに出てきた「231MBのログ」はこれです。journaldも上限が未設定で3.9GB。合わせて約4GBを整理し、ディスク使用率は23%から13%に下がりました。

配布イメージは「動く」ようには作られていますが、「運用され続ける」ことまでは面倒を見てくれない。既定値を信じすぎない、というのはチューニング値だけでなくログにも当てはまりました。

移行そのものをAIに任せる

土台も古くなっていました。Debian 11、PHP 8.1.18(2023年4月ビルド)、bullseye-backportsは消滅済み。加えてAWSが2026年11月19日にBitnami版WordPressブループリントを廃止すると告知しています(既存インスタンスは動き続け、スナップショットからの再作成も可能です)。

移行を頼んでからの進み方が、個人的には今回のハイライトでした。設定ファイルをコピーして回るような作業ではありません。私が伝えたのは「移行しよう」だけで、あとはAIが自律的に、問題を見つけては解決策を考えながら進めていきます。実際の流れはこうでした。

  1. 移行先を実測する。検証用にインスタンスを1台起動し、新ブループリントの中身を調査。docrootもSSHユーザーも違い、cronも入っていない構成でした
  2. 差分を踏まえた移行手順書を作る。切り替え手段(静的IPの付け替え)と切り戻し手段までこの時点で確定
  3. データを移送する。WP-CLIでDBごと移し、URLの正規化も移送前に済ませる
  4. 本番に触らず検証する。hostsの書き換えでCloudFrontと同じ形の接続を再現し、切り替え前に新環境を一通り確認
  5. 公式手順の穴を塞ぐ。AWS公式の移行手順は「切り替え後に証明書を再取得」ですが、この順序だと数分のダウンタイムが出ます。AIは証明書を先に旧サーバからコピーする手順に組み替え、無停止で切り替えました

環境の差分を把握し、手順を組み、事前に検証してから切り替える。進め方は人間のインフラエンジニアと同じで、違うのは速度だけでした。ダウンタイムゼロはその結果です。

実際には、細かいハマりどころがいくつもありました。静的IPを付け替えてもAAAAレコード(IPv6)は旧サーバを指したまま残る、Bitnamiのwp-contentはシンボリックリンクなのでtarが中身を固めない、新イメージにはcronが入っていない。いずれも、AIがその場の環境を調べて見つけたものです。この種の差分は、次のバージョンでは変わっているかもしれません。だからこそ、個々のTipsを覚えておくより、移行のたびに、その場の環境をLLMに走査してもらう方が確実だと思います。

3年前の記事が、チェックリストになった

Lightsailの移行は今回で3回目です。

Amazon Lightsail WordPressイメージを最新版に更新する
このブログはAWSのLightsail上で動作していますが、構築してから2年経ったためイメージの更新を行うことにしました。2年も経つとイメージの中身も結構変わっていたので、備忘含めて記載します。
2021年2023年2026年
移行手段エクスポート/インポート移行プラグインWP-CLIでDBごと移送
ダウンタイムありありゼロ
後始末記録なしURL一括置換不要
チューニング記録なし勘と経験プロファイリング

今回、移行計画を立てる前にAIへ過去記事を読ませました。これが想像以上に働きました。

2023年の記事には「データ移行で一部のURLがIPアドレス表記になって壊れ、後から一括置換した」と書いてあります。それを踏まえてAIが移送前にDBを照合したところ、当時の残骸がそのまま見つかりましたsiteurlhomeが旧IPのままでした。表示上はwp-config.phpの定義が上書きしていて、3年間誰も気づけない状態です。移送前に1,243箇所を正規化し、同じ破損の再発を未然に防ぎました。

AAAAレコード(IPv6)が移行の邪魔をするという罠も、実は2023年の記事に書いてありました。

AAAAレコード(IPv6)が設定されているとうまくいかなかったので、一旦外しておく必要があり、地味に面倒でした。

私はすっかり忘れていましたが、今回も形を変えて現れています(当時は証明書ツールが躓く話、今回は静的IP付け替え後にレコードが取り残される話)。

備忘録のつもりで書いた過去記事が、AIの参照資料としてチェックリストのように機能する。自分は忘れていても、AIは照合してくれます。ブログは書いておくものだと思いました。

まとめ

サーバ運用でAIを使ってみて、コーディングのとき以上に「実行して数字を出せること」の価値が大きいと感じました。ログを引く、プロファイラを回す、設定を変えて測り直す。この往復が速いほど原因に近づきますし、何より効果が目に見えない作業に、手応えが生まれます

技術的な教訓は3つでした。

  • 公式配布物でも既定値は自分の環境で検証する。同じ「1GB向け」でPHPの同時実行数に9倍の差があり、ログのローテーション設定は存在しませんでした
  • 監視や自動復旧が生きているかを、別の手段で確認する。どちらも静かに止まりますし、止まったことは誰も教えてくれません
  • 監視はサイトの外側に置く。サイト内のプラグインで監視すると、サイトごと壊れたときに一緒に黙ります

最後にアラームを2つ設定しました。CloudWatchのアラームは10個まで無料、CloudFrontのメトリクスも無料です。閾値5%に対して今回は74%だったので、これがあれば10分で気づけていました。

Bitnamiブループリントをお使いの方は、2026年11月19日の廃止までに移行の検討をおすすめします。

コメント

タイトルとURLをコピーしました