こんにちは!インフラの世界へようこそ。
大規模なシステムを支えるSREの世界では、サーバーが10台、100台から、やがて数千台へとスケールしていくにつれて、かつては「動けば正義」だったシンプルな自動化スクリプトが、徐々に牙をむき始める瞬間がやってきます。
特に、サーバーの構成管理ツールとして広く使われている Puppet において、「ノード数が数千台」の壁を突破するとき、多くのエンジニアが最初に直面するのが 「Catalog(カタログ)コンパイルのCPU枯渇問題」 です。
今回は、この巨大な負荷を華麗にいなし、何千台ものサーバーが同時に押し寄せてきてもビクともしない、R10KとPuppet Serverのスケールアウト戦略 について、基礎から実践まで優しく、そしてディープに解説していきます。
これをマスターすれば、深夜に「サーバーの収束が終わらない!」と冷や汗をかくようなトラブルから解放され、あなたの管理するインフラは圧倒的な安定性を手に入れることができますよ。
—
1. そもそもPuppetの「コンパイル負荷」とは何か?
Puppetは、マスター・エージェント型の構成管理ツールです。
エージェント(管理対象のサーバー)が定期的にマスター(Puppet Server)にアクセスし、「今の私の状態はこれです。正しい状態の設計図(カタログ)をください!」と要求します。
Puppet Serverはこの要求を受けると、Rubyのコード(Manifest)を解釈し、そのノード専用の「カタログ(JSON形式の設計図)」をその場で動的に生成(コンパイル)します。
- 問題の核心: このコンパイル処理、実はCPUとメモリを猛烈に消費します。
ノード数が500台、1000台を超えてくると、毎朝の定期実行のタイミング(Thundering Herd現象)でPuppet ServerのCPU使用率が100%に張り付き、コンパイルがタイムアウト。エージェントがエラーを吐きまくる……というのが、大規模環境における「お約束の悲劇」です。
これを解決するためのキーワードが、「コード配信の効率化(R10K)」 と 「サーバーの水平分散(ロードバランシング)」 です。
—
2. R10Kとは?:コードデプロイを秒速で自動化する仕組み
まずは、Puppetのコード(Puppetfileやマニフェスト)を複数のPuppet Serverに綺麗に、かつ高速に同期・デプロイするためのツール R10K の基礎から入りましょう。
R10Kの役割
R10Kは、Gitのブランチ(`production` や `staging` など)とPuppetの環境(Environment)を完全に対応付け、依存関係にあるモジュール(Forgeから取得するモジュールなど)も含めて一発でビルド・同期してくれるデプロイメントツールです。
インストールと基本セットアップ
Puppet Serverが稼働するノード上で、R10Kを導入します。PuppetのGem環境を使ってサクッとインストールするのがお作法です。
Puppet公式のGemコマンド経由でr10kをインストール
/opt/puppetlabs/puppet/bin/gem install r10k
次に、`/etc/puppetlabs/r10k/r10k.yaml` に設定ファイルを記述します。これがR10Kの心臓部です。
—
Puppetfileで管理するモジュールのキャッシュディレクトリ
cachedir: ‘/var/cache/r10k’
デプロイ先のPuppet環境ディレクトリ
sources:
# ‘my-org’という名前でGitリポジトリを定義
git:
remote: ‘https://github.com/your-org/puppet-control-repo.git’
basedir: ‘/etc/puppetlabs/code/environments’
この設定を行った上で、以下のコマンドを実行するだけで、Git上の最新コードと外部モジュールが魔法のように適切なディレクトリへデプロイされます。
全環境(ブランチ)のコードを一括デプロイ
/opt/puppetlabs/puppet/bin/r10k deploy environment -p
※これをWebhookと組み合わせることで、GitHubへのプッシュをトリガーに自動デプロイが走る仕組みが完成します。素晴らしいですね!
—
3. なぜスケールアウトが必要なのか?(複数台構成への布石)
R10Kによって「常に最新で綺麗なコード」が配信されるようになったとしても、1台のPuppet Serverが全てのコンパイルリクエストを処理している構造が変わっていなければ、数千台のスケールには耐えられません。
そこで登場するのが、「複数台のPuppet Server + Load Balancer(LB)」 というモダンなスケールアウト・アーキテクチャです。
スケールアウト構成の全体像
[数千台のPuppet Agents]
│
▼ (HTTPS / Port 8140)
+————————–+
| Load Balancer (Nginx/ALB)|
+————————–+
│
├─────────────────┬─────────────────┐
▼ ▼ ▼
[Puppet Server 1] [Puppet Server 2] [Puppet Server 3]
│ │ │
└─────────────────┴─────────────────┘
│
▼ (R10Kで同期)
[Git / Control Repo]
複数のPuppet Serverを並べ、その前段にロードバランサーを置くことで、コンパイル負荷を美しく分散させます。ここで重要なのが、どのPuppet Serverがリクエストを受けても、同じ結果(カタログ)が返るようにコードベースが同期されていること(ここでR10Kが活きてきます)。
—
4. 精度高い「HelloWorld」的動作確認:LB経由の疎通テスト
それでは、この分散アーキテクチャが正しく機能しているか、最小限にして精度の高い手順で動作確認(HelloWorld)を行いましょう。
ここでは、ロードバランサー(例:NginxやAWS ALBなど)が構築されており、`puppet.example.com:8140`へのリクエストが、背面の複数台のPuppet Serverにルーティングされている前提で話を進めます。
ステップ1:エージェントの設定変更
管理対象ノード(エージェント)の `puppet.conf` を書き換え、接続先を単体のマスターではなく「ロードバランサーの向き先」に変更します。
[main]
個別のサーバーではなく、Load BalancerのDNS名を指定する
server = puppet.example.com
environment = production
ステップ2:最初の「HelloWorld」マニフェストを書く
コントロールリポジトリの `environments/production/manifests/site.pp` に、次のようなシンプルなテストコードを書きます。これがすべてのノードで実行される基本のコードです。
精度高いHelloWorld:ファイルが正しく配置されるかをテストする
node default {
file { ‘/tmp/puppet_hello.txt’:
ensure => present,
mode => ‘0644’,
content => “Hello from Puppet Server! Compiled safely via Load Balancer.\n”,
}
}
ステップ3:エージェントを手動実行して確認!
エージェント側からPuppetを手動でキックし、ロードバランサー経由で背面のPuppet Serverのいずれかにヒットさせます。
–test オプションをつけてフォアグラウンドで実行
puppet agent –test
成功時の出力イメージ:
Info: Using cached certificate
Info: Retrieving pluginfacts
Info: Retrieving plugin
Info: Loading facts
Info: Applying configuration version ‘1682938400’
Notice: /Stage[main]/Main/Node[default]/File[/tmp/puppet_hello.txt]/ensure: created
Notice: Finished catalog run in 2.14 seconds
`/tmp/puppet_hello.txt` を覗いてみましょう。
cat /tmp/puppet_hello.txt
出力結果:
Hello from Puppet Server! Compiled safely via Load Balancer.
おめでとうございます! ロードバランサーを経由して背面のPuppet Serverがリクエストを受け付け、見事にカタログをコンパイルしてエージェントに適用しました。複数台にサーバーを増やしても、この仕組みは全く同じようにスケールします。
—
5. 現場のプロから送る、さらなる高みへのアドバイス
この構成を本番運用するにあたり、SREとして知っておくべき「現場の知見」をいくつか置いておきます。
1. SSL証明書の共有(Puppet CAの設計):
Puppetは通信の暗号化に厳格なSSL(独自CA)を使用します。複数台構成にする場合、すべてのPuppet Serverが同じCA(Certificate Authority)を信頼しているか、あるいは1台を専任のCAサーバーにし、残りをコンパイル専用サーバー(Compile Master)として切り出す「CAスプリット構成」を検討してください。数千台規模では、コンパイル専用ノードを横に並べるのが王道です。
2. JRubyインスタンスのチューニング:
Puppet Serverの内部はJava(Clojure/JRuby)で動いています。`puppetserver.conf` 内の `max-active-instances` の値を、サーバーのCPUコア数に合わせて適切にチューニングすることで、1台あたりのコンパイルスループットが劇的に向上します。
—
まとめ
今回は、大規模Puppet環境におけるコンパイル負荷の軽減と、R10K・ロードバランサーを組み合わせたスケールアウト戦略について解説しました。
- R10K でコードのデプロイを自動化・高速化し、
- Load Balancer + 複数台のPuppet Server でコンパイル負荷を水平分散させる。
このアーキテクチャを理解し構築できれば、インフラストラクチャがどれほど巨大になろうとも、あなたは常に余裕を持ってシステムをコントロールし続けることができます。
毎日の運用が劇的に楽になるこの設計、ぜひあなたの環境でも試してみてくださいね。それでは、素晴らしいインフラライフを!