前回、「JenkinsがじわじわGitクローンできなくなっていった話」と「プロビジョンドスループットで1万円使った反省」の2つの記事で、EFSのメタデータIOPS枯渇問題とその対応について書きました。

月曜の朝にJenkinsが重くなり、調査の結果、Git一時ファイル(tmp_pack_*)が約15GB蓄積していたことが原因だと突き止めました。応急処置としてプロビジョンドスループットを300 MiB/sに変更し、その後Elastic Throughputに切り替えて、定期クリーンアップジョブも作成しました。

「これで解決だ」と思っていました。

でも実は、まだ終わっていませんでした。


グラフが語る「本当の始まり」

トラブル対応後、念のためEFSのBurst Credit Balanceのグラフを確認していたところ、1/13頃から明確な減少トレンドが始まっていることに気づきました。

EFS Burst Credit Balanceの推移 - 1/13から減少が始まり、1/26に最低レベルに到達

問題が顕在化したのは1/26-1/27でしたが、根本原因は2週間前の1/13前後に発生していたことになります。

つまり、前回の記事で書いた「tmp_pack_*の蓄積」は症状の悪化であり、真の根本原因は別にあるということです。

正直ここで詰まりました。1/13前後で何が変わったのか、思い当たる節がいくつかありましたが、確定的な情報ではありません。


1/13前後の変更を洗い出す

思い当たる変更点は2つありました。

1. エージェント方式の変更

1/13前後に、Jenkinsエージェントの運用方式を大きく変更していました。

従来の方式: 共有エージェント

新しい方式: 使い捨てエージェント

コスト削減のための変更でしたが、これがメタデータIOPSに与える影響は考えていませんでした。

2. 年始の開発加速

年始なので各チームの開発が加速し、Jenkins全体の負荷が上がった可能性もあります。


仮説: 使い捨て方式がメタデータIOPSを激増させた

ここで立てた仮説は、使い捨てエージェント方式への変更が、メタデータIOPSを激増させたのではないかというものでした。

簡単な計算をしてみます:

ビルド回数: 50回/日(推定)
1クローンあたりのファイル作成: 5,000個

共有エージェント方式:
  初回のみクローン = 5,000回のメタデータ操作

使い捨てエージェント方式:
  50ビルド × 5,000ファイル = 250,000回のメタデータ操作/日

50倍のメタデータIOPS増加です。

年始で開発が加速すれば、この数字はさらに増えます。コスト最適化のつもりが、別の問題を引き起こしていた可能性が高いと思いました。


キャッシュディレクトリの謎

調査を進める中で、/mnt/efs/jenkins/caches/ というディレクトリに気づきました。

/mnt/efs/jenkins/caches/git-3e9b32912840757a720f39230c221f0e

このようなディレクトリが大量にあります。これは何でしょうか?

実は、これはJenkinsのGitプラグインがリポジトリをキャッシュするためのbare repositoryです。

Gitキャッシュの仕組み

JenkinsのGitプラグインは、効率化のために以下のような仕組みを持っています:

  1. リモートリポジトリを /mnt/efs/jenkins/caches/git-{hash}/ にbare repositoryとしてキャッシュ
  2. 各ジョブのワークスペースには、このキャッシュから git clone --reference でクローン
  3. ハッシュ値はリポジトリURL + ブランチなどから生成

ここで新たな疑問が浮かびました: 使い捨てエージェント方式に変更したことで、このキャッシュが無効化されているのではないか?


tmp_pack_*の正体を再確認

前回の記事で見つけた tmp_pack_* ファイルの場所を改めて確認してみます:

jobs/sample-job/jobs/sample-pipeline/builds/104/libs/
  └── 335abf.../root/.git/objects/pack/
      └── tmp_pack_WqmOyE  ← 100-300MB

これはビルドごとのディレクトリに存在しています。つまり:

jobs/sample-job/jobs/sample-pipeline/
└── builds/
    ├── 104/
    │   └── libs/.../tmp_pack_WqmOyE
    ├── 105/
    │   └── libs/.../tmp_pack_XYZ123
    └── 106/
        └── libs/.../tmp_pack_ABC456

毎ビルドごとにPipeline Shared Libraryが再チェックアウトされ、それぞれで tmp_pack_* が残っている状態です。

ここで新しい疑問が出てきます: なぜ毎ビルドごとにShared Libraryが再チェックアウトされているのか?

通常、Shared Libraryもキャッシュされるはずです。


根本原因の発見: キャッシュ設定がOFFだった

Jenkinsの設定を確認したところ、決定的な設定ミスを見つけました。

Shared Libraryの設定で、Cache fetched versions on controller for quick retrieval のチェックが外れていました。

つまり:

これで点と点が線になりました:

  1. 使い捨てエージェント方式への変更(1/13)→ エージェント側で毎回フルクローン
  2. Shared Libraryキャッシュ無効(以前から)→ Controller側で毎回フルフェッチ
  3. 年始の開発加速 → ビルド回数増加

この3つが重なり、メタデータIOPSが激増。2週間かけてBurst Creditが枯渇し、1/26に症状が顕在化しました。


対策: キャッシュを有効化する

すぐに設定を変更しました:

  1. Cache fetched versions on controller for quick retrievalON
  2. Refresh time in minutes180分に設定

Refresh timeをどう決めたか

ここは意外と肝です。選択肢としては:

今回は**180分(3時間)**を選びました。理由は:

  1. 1日8回程度の更新チェック(9時、12時、15時、18時...)
  2. Shared Libraryの変更は通常半日以内に反映されれば問題ない
  3. IOPSを大幅に削減できる(毎ビルド → 3時間に1回)
  4. 緊急時は手動でキャッシュクリアも可能

実は、Jenkinsには「強制的にリフレッシュ」する機能があるので、急ぎの変更があっても問題ありません。ただ、その存在を忘れてしまいそうなので、運用ドキュメントに書いておくことにしました。


設定変更後の効果測定

設定変更後、以下のタイムラインで効果を確認する予定です:

短期(24-48時間後)

中期(1週間後)

長期(1ヶ月後)


振り返りと学び

根本原因は複合的だった

今回の問題は、単一の原因ではなく、複数の要因が重なって発生していました:

  1. Shared Libraryキャッシュ無効化(以前から存在)
  2. 使い捨てエージェント方式への変更(1/13前後)
  3. 年始の開発加速(ビルド回数増加)

それぞれ単体では大きな問題にならなかったかもしれませんが、3つが重なることで、メタデータIOPSが臨界点を超えました。

症状と根本原因の時期は異なる

グラフを時系列で見る重要性を痛感しました。目の前の症状だけを見て対応すると、表面的な修正に終わってしまいます。

アーキテクチャ変更のリスク

使い捨てエージェント方式への変更は、コスト最適化が目的でした。確かにEC2のコストは削減できましたが、別の場所でコストとパフォーマンスの問題を引き起こしていました

アーキテクチャを変更する際は:

これらが重要だと改めて感じました。

メタデータIOPSの特性

EFSのメタデータIOPSについて、重要な特性がわかりました:

特に、.git/objects/ 配下のような「小さなファイルが大量にある」ケースでは、通常のファイルI/Oとは全く異なる挙動を示します。


次の問い

今回の対応で、Shared Libraryのキャッシュを有効にしました。しかし、使い捨てエージェント方式自体は継続しています。

エージェント側のGitキャッシュは、使い捨て方式でも有効活用できるのか?

これについては、もう少し調査が必要です。可能性としては:

  1. EFS上のGitキャッシュを全エージェントで共有する
  2. エージェントのライフサイクルを少し長くして、複数ジョブで再利用する
  3. S3などにキャッシュを配置し、起動時に同期する

コストとパフォーマンスのバランスをどう取るか。これは次の課題として残ります。


関連記事

この記事は、以下の記事の続編です:

/ja/tech/sre/jenkins-efs-metadata-iops-issue

/ja/tech/sre/efs-provisioned-throughput-cost-reflection


関連書籍

今回のようなインフラ運用やトラブルシューティングについてさらに学びたい方におすすめの書籍です。

[📦 商品リンク: moshimo-book-sre-google]

[📦 商品リンク: moshimo-book-jenkins-jissen]

[📦 商品リンク: moshimo-book-aws-operations]