大規模Puppetインフラを「爆速」に変える:SREが教えるパフォーマンスチューニングの極意
Puppetを導入して数年、ノード数が数百から数千に膨れ上がったとき、多くのチームが「Puppet ServerのCPU負荷が異常に高い」「カタログコンパイルがタイムアウトする」という壁にぶつかる。
多くのエンジニアは「スペックを上げれば解決する」と安易なスケールアップに逃げるが、それは根本解決ではない。Puppetの真の性能を引き出すには、JRubyの深淵を理解し、カタログのライフサイクルを制御する技術が必要だ。
本稿では、数千ノードを管理する大規模環境で、インフラの応答速度を限界まで高めるための「プロのチューニング術」を伝授する。
—
1. サーバー負荷の真因を突き止める
Puppet Serverの負荷が高い場合、疑うべきは「カタログコンパイルの非効率性」と「JRubyのコンテンション(競合)」だ。
まずは、以下のコマンドで現状をプロファイリングせよ。
Puppet Serverのメトリクスを叩いて、コンパイル時間を可視化する
curl -s http://localhost:8140/status/v1/services/puppet-profiler | jq .
もし `compile` の時間が異常に長いなら、コード内で `inline_template` や重い外部スクリプトの実行を繰り返していないか確認しろ。それはPuppetのアンチパターンだ。
2. JRubyインスタンスとメモリの最適化
Puppet Serverの心臓部は `jruby-puppet` プールだ。ここがボトルネックの主戦場である。
`/etc/puppetlabs/puppetserver/conf.d/puppetserver.conf` を開け。
jruby-puppet の設定
jruby-puppet {
# 物理コア数に合わせて調整。一般的に (物理コア数 – 1) が最適
max-active-instances = 8
# メモリ不足によるGC地獄を防ぐため、物理メモリの30-40%を割り当てる
max-requests-per-instance = 5000
}
極意: `max-requests-per-instance` は低すぎるとJRubyの再起動オーバーヘッドでCPUが溶ける。5,000〜10,000程度に設定し、メモリリークの兆候がないか監視しつつ調整するのが実務の勘所だ。
3. PostgreSQLのチューニング:PuppetDBの背骨を鍛える
Puppet Serverのカタログ保存先であるPuppetDBのDB負荷を侮るな。特に `fact` の更新頻度が高いと、PostgreSQLは悲鳴を上げる。
`postgresql.conf` で以下の値をチューニングし、I/O待ちを極限まで減らせ。
メモリの25%を共有バッファに割り当て
shared_buffers = 4GB
大規模書き込みに備えてチェックポイントの間隔を広げる
max_wal_size = 4GB
checkpoint_timeout = 15min
同時接続数を適切に制御
max_connections = 200
また、`maintenance_work_mem` を増やすことで、日次のVACUUM処理を高速化させろ。これが遅いと、インデックスの肥大化で検索が数秒遅れる。
4. Agentのランダムスリープ(Splay)設定
数千台のノードが一斉にチェックイン(Puppet Run)を開始すると、Puppet ServerはDDoS攻撃を受けたのと同じ状態になる。これを防ぐのが `splay` 設定だ。
`/etc/puppetlabs/puppet/puppet.conf` に以下を記述せよ。
[agent]
ランダムに開始時間を30分ずらすことで負荷を平準化する
splay = true
splaylimit = 30m
runinterval = 30m
この設定により、サーバーの負荷スパイクは劇的に解消される。
—
現場で役立つ「神」ツールと効率化術
1. 開発スピードを加速させる神プラグイン
- [VS Code] Puppet Extension: シンタックスハイライトはもちろん、`puppet-lint` との連携は必須。
- [Puppet Development Kit (PDK)]: モジュールのテスト(rspec-puppet)を爆速で行うための標準ツール。これを使わずにモジュールを書くのは素人だ。
2. チーム開発の共有化ルール
設定ファイルを管理する際は、YAMLの階層構造を統一しろ。`hiera.yaml` の階層を深くしすぎると、カタログコンパイル時にマージ計算の負荷が激増する。
- ルール: 階層は最大5つ以内。データは `lookup_options` を使ってマージ戦略(deep/first)を明示的に指定すること。
3. 設定ファイルのベストプラクティス(Hiera)
common.yaml
—
複雑なロジックはコードに書かず、データとして分離する
lookup_options:
‘profiles::firewall::rules’:
merge: ‘deep’ # ハッシュをマージしてルールを積み上げる設計
profiles::firewall::rules:
‘allow_ssh’:
port: 22
proto: ‘tcp’
—
最後に:テックリードからの提言
インフラのパフォーマンスチューニングは、単なる数値調整ではない。「何がボトルネックで、なぜその値にするのか」という論理的根拠をチーム全員が語れるようにすることだ。
Puppetは「冪等性」を保証する強力な武器だが、使い手次第で鈍器にも名刀にもなる。今日伝えた設定を適用し、カタログコンパイル時間を計測してみろ。数秒の短縮が、チームのデプロイ頻度を劇的に変えるはずだ。
さあ、次は君たちの番だ。この設定を検証し、さらなる高みへインフラを導いてくれ。