最初に疑ったのはCPUクレジット
Jenkinsのエージェントに AWS スポットインスタンス(t系)を使っているのですが、起動から1時間ほど経つと処理が突然重くなる現象がありました。
CPUもメモリも余っているのに、なぜか遅い。
最初はCPUクレジットを疑ったんですが、調べていくうちに「あ、ネットワークか」と気づいて、原因が特定できたのでメモしておきます。
t系インスタンスを使っているので、まずCPUクレジットの枯渇を疑いました。unlimited モードで動いているとはいえ、念のため残高を確認しようとしたのがきっかけです。
CLIでCPUクレジット残高を確認する
#!/bin/bash
# IMDSv2でインスタンスIDとリージョンを取得
TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" \
-H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
INSTANCE_ID=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" \
http://169.254.169.254/latest/meta-data/instance-id)
REGION=$(curl -s -H "X-aws-ec2-metadata-token: $TOKEN" \
http://169.254.169.254/latest/meta-data/placement/region)
# CPUクレジット残高を取得
CREDIT=$(aws cloudwatch get-metric-statistics \
--region $REGION \
--namespace AWS/EC2 \
--metric-name CPUCreditBalance \
--dimensions Name=InstanceId,Value=$INSTANCE_ID \
--start-time $(date -u -d '10 minutes ago' +%Y-%m-%dT%H:%M:%SZ) \
--end-time $(date -u +%Y-%m-%dT%H:%M:%SZ) \
--period 300 \
--statistics Average \
--query 'sort_by(Datapoints, &Timestamp)[-1].Average' \
--output text)
echo "Instance: $INSTANCE_ID / CPU Credit Balance: $CREDIT"
macOSで実行する場合は
date -u -d '10 minutes ago'→date -u -v-10Mに変えてください。
CPUSurplusCreditBalance が積み上がっていることに気づく
CloudWatchを見ると、CPUSurplusCreditsCharged はほぼゼロなのに CPUSurplusCreditBalance がじわじわ増えていました。
「これ、課金されてるの?」と一瞬焦ったのですが、整理するとこういう状態でした。
CPUSurplusCreditBalance が上昇中
→ unlimited モードでバーストし続けている「借り」が積み上がっている
CPUSurplusCreditsCharged = 0
→ まだ返済も課金も発生していない
CPUSurplusCreditsCharged が計上されるのは、補充クレジットで「借り」を返し切れなかったとき、もしくはインスタンスが終了したときです。今は「借りたまま走っている」段階で、特に問題ない状態でした。
スポットインスタンスだと終了時に注意
ひとつ気をつけておきたいのは、スポットインスタンスが突然終了したとき。CPUSurplusCreditBalance に残っている借り残高がそのまま CPUSurplusCreditsCharged に計上されます。
ただ、コストへの影響はかなり小さいです。正確な計算式はこうなります。
1 vCPU-hour = 60クレジット = $0.05
→ 1クレジット ≈ $0.00083
ちなみに t3.medium の CPUSurplusCreditBalance 上限は 576クレジット(24クレジット/時間 × 24時間分)。上限まで使い切っても 576 × $0.00083 ≈ 約48セント。「コストが跳ね上がる」ほどの話ではなかったので、CPUクレジットは今回の問題の主因ではなさそうでした。
EBSのI/Oクレジット枯渇を疑ったが…
次に疑ったのはEBSのI/Oクレジット枯渇。gp2はCPUと同様にI/Oにもバーストクレジットがあって、Jenkinsのビルドは依存ライブラリのダウンロードやコンパイルでI/Oを多用するので枯渇しやすいはずです。
ただ、確認したらEBSはgp3を使っていました。gp3はクレジット方式ではなくプロビジョンドIOPS方式なので、I/Oクレジット枯渇は関係ないということでこちらも外れ。
NetworkOut のグラフを見て「あ、これだ」となった
行き詰まったので CloudWatch で NetworkOut のグラフを眺めていたら、起動から約1時間後に急激に下がっているのが見えました。

グラフを見ると NetworkPacketsOut(パケット数)も同じタイミングで落ちています。パケット数まで落ちているということは、帯域クレジットの枯渇でほぼ確定です。
t系インスタンスにはネットワークにもバーストクレジットがある
これ、知らなかったんですが t系のネットワーク帯域もCPUと同じバースト構造になっています。
起動直後
→ ネットワークバーストクレジットが満タン
→ 最大帯域(t3.medium なら最大5Gbps)でフルに使える
1時間前後
→ クレジット枯渇
→ ベースライン帯域に絞られる(t3.medium なら約256Mbps)
Jenkinsのエージェントは起動直後にDockerイメージのプルや依存ライブラリのダウンロードで一気にネットワークを使います。なのでクレジットが早く枯渇して、その後のビルドで帯域が絞られていたわけです。CPUもメモリも余っているのに遅い、という症状と完全に一致します。
CPUクレジットと違って「設定で対策できない」
CPUクレジットには unlimited モードという設定があって、クレジットが枯渇してもバーストし続けられます。「じゃあネットワークも同じように設定できないの?」と思って調べたら、ネットワークバーストクレジットにはunlimitedに相当する設定が存在しません。
| CPUクレジット | ネットワーククレジット | |
|---|---|---|
| unlimitedモード | ✅ ある | ❌ ない |
| サイズアップで緩和 | ✅ | ✅ |
| 設定で無効化 | ✅ | ❌ |
AWS の仕様として、インスタンスタイプで決まっているパラメータで、ユーザー側では変更できないとのことです。
現時点で考えている対策
原因は特定できたので、対策はこれから検討します。優先度順にまとめると以下の感じです。
1. 依存ライブラリ・Dockerイメージのキャッシュ整備
起動直後の大量通信を減らしてクレジット枯渇を遅らせる。コスト増なしで試せるので、まずここから手をつけたいと思っています。
2. インスタンスサイズのアップ
サイズが上がればベースライン帯域自体が増えるので、枯渇後も耐えやすくなります。スポット料金との兼ね合いで検討。
3. m系・c系への変更
ネットワークバーストクレジットの概念がなくなるので根本解決。ただしスポット料金は上がります。
Jenkinsエージェントをビルドのたびに使い捨てにしているなら、キャッシュの整備が最もコスパよく効く対策だと思っています。実施したら続きを書きます。
参考:今回調べた AWS 公式ドキュメント
| テーマ | URL |
|---|---|
| バーストパフォーマンスインスタンス概要 | https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/burstable-performance-instances.html |
| CPUクレジットの基本概念 | https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/burstable-credits-baseline-concepts.html |
| Unlimitedモードの概念 | https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/burstable-performance-instances-unlimited-mode-concepts.html |
| スポットインスタンスでのUnlimitedモードの注意事項 | https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/burstable-performance-instances-unlimited-mode.html |
| EC2のネットワーク帯域幅(バーストクレジットについての記載あり) | https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-network-bandwidth.html |
参考書籍
AWS のインスタンス運用やインフラの基礎を体系的に学びたい方には、以下の書籍が参考になります。
[📦 商品リンク: moshimo-book-aws-operations]
[📦 商品リンク: moshimo-book-server-infra]
[📦 商品リンク: moshimo-book-jenkins-jissen]