構成管理ツールを調べ始めると、必ずこの3つの名前にぶつかります。どれも「サーバーの設定をコードで管理する」ツールですが、動く仕組みも、導入にかかる工数も、運用で必要になる知識もまったく違います。この違いを理解しないまま選ぶと、検証環境を組む段階で止まってしまいます。
この記事では、Ansible・Puppet・Chefを「エージェントの有無」「push型とpull型」「記述言語」の3軸で比較し、どんな現場でどれを選ぶべきかの判断基準を整理します。RHEL 9.4 / Rocky Linux 9 / Ubuntu 24.04 LTS で動作確認した実際の出力例を交えて解説します。
この記事のポイント
・Ansibleはエージェント不要。SSHとPython 3があれば即動く
・PuppetとChefはターゲットに常駐エージェントを入れるpull型
・記述言語はAnsibleがYAML、Puppetが独自DSL、ChefがRuby
・数十台規模で変更頻度が中程度なら、Ansibleが最短で回り始める
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
なぜ構成管理ツールの選定でつまずくのか
サーバーが3台までなら、手順書を見ながらSSHで入って設定しても運用は回ります。ところが10台、30台と増えた瞬間に、同じ作業の繰り返しが破綻し始めます。・作業ミス:30台のうち1台だけ設定ファイルの1行が抜けている、という事故が起きる
・状態の不明化:「このサーバーは今どういう設定なのか」を誰も正確に言えなくなる
・再現不能:サーバーを作り直したいのに、当時の手順が手順書のどこにも残っていない
構成管理ツールは、この3つを「コードで定義した状態に収束させる」という発想で解決します。ここまでは3ツールとも同じ目的です。分かれるのは、その状態をどうやってサーバーに届けるかという実装方法のほうです。
選定でつまずく人の多くは、機能の一覧表を眺めて比較しています。しかし実際に効いてくるのは「導入初日に何台のサーバーへ何をインストールする必要があるか」という、極めて泥臭い部分です。まずはそこから見ていきます。
Ansible・Puppet・Chefの設計思想を比較する
1. エージェントレス(Ansible)とエージェント型(Puppet・Chef)
最大の違いはここです。Ansibleはエージェントレスです。管理される側(ターゲットノード)に専用ソフトウェアを入れません。SSHで接続し、Pythonのモジュールをその場に転送して実行し、終わったら片付けます。ターゲット側に必要なのはSSHデーモンとPython 3だけで、これは現行のLinuxディストリビューションならほぼ標準で入っています。
PuppetとChefはエージェント型です。ターゲットノードに常駐プロセス(Puppetは puppet agent、Chefは Chef Infra Client)をインストールし、それが管理サーバーへ定期的に問い合わせて設定を取りにきます。
この差は「導入初日の工数」に直結します。Ansibleは自分のPCまたは踏み台サーバー1台にインストールすれば、その時点で既存の全サーバーを管理下に置けます。エージェント型は、管理したいサーバーすべてにエージェントを配って証明書を発行し、管理サーバーと通信できる状態にするところから始まります。
一方で、エージェント型には「管理サーバーに接続できない環境でも、エージェント側が自律的に設定を維持する」という強みがあります。ここは後述の判断基準で効いてきます。
2. push型(Ansible)とpull型(Puppet・Chef)
エージェントの有無は、そのまま設定の流れる向きの違いになります。・push型(Ansible):人がコマンドを実行した瞬間に、コントロールノードからターゲットへ設定を押し込む
・pull型(Puppet・Chef):ターゲット上のエージェントが定期的に管理サーバーへ問い合わせ、自分の設定を取りにいく
push型は「いつ変更が走るか」を人間が完全に制御できます。メンテナンス時間帯に、決めた順序で、決めた台数ずつ流せます。逆に言えば、誰もコマンドを実行しなければ設定は永遠に古いままです。
pull型は放っておいても収束します。誰かが手でサーバーの設定ファイルを書き換えても、次の実行タイミングで元に戻ります(Puppetのエージェントは既定で30分間隔)。これは大規模環境で「設定のドリフト(ズレ)」を防ぐ強力な仕組みですが、裏を返すと「意図しないタイミングで勝手に変更が走る」ことでもあります。緊急でサービスを止めている最中にエージェントが起動して設定を戻してしまった、というのは現場でよくある事故です。
3. 通信経路とファイアウォール設計の違い
通信の向きが逆になるため、開けるべきポートも変わります。| ツール | 通信の向き | 既定の待受ポート |
|---|---|---|
| Ansible | コントロールノード > ターゲット | ターゲットの22/tcp(SSH) |
| Puppet | エージェント > Puppet Server | Puppet Serverの8140/tcp |
| Chef | クライアント > Chef Infra Server | Chef Infra Serverの443/tcp |
エージェント型では、管理サーバー側に新しい待受ポートが立ちます。導入時には実際に待受状態になっているかを確認する必要がありますが、その手順はLinux ポート確認の全コマンドで解説しているコマンドがそのまま使えます。
4. 記述言語:YAML・独自DSL・Ruby
同じ「nginxをインストールして起動する」という処理を、3つのツールで書き比べてみます。Ansible(YAML)の場合です。
# playbooks/web.yml - name: Web server setup hosts: web become: true tasks: - name: Install nginx ansible.builtin.package: name: nginx state: present - name: Enable and start nginx ansible.builtin.service: name: nginx state: started enabled: true
# manifests/web.pp package { 'nginx': ensure => installed, } service { 'nginx': ensure => running, enable => true, require => Package['nginx'], }
# cookbooks/web/recipes/default.rb package 'nginx' do action :install end service 'nginx' do action [:enable, :start] end
AnsibleのYAMLは、設定ファイルであってプログラミング言語ではありません。条件分岐やループはYAMLのキー(when・loop)として表現し、値の加工はJinja2テンプレートに任せます。読む側にとって理解しやすい反面、複雑なロジックを書こうとすると急に窮屈になります。
PuppetのDSLは宣言的で、リソース間の依存関係(require・before・notify)を明示的に書けます。「AをやってからB」を確実に保証したい大規模環境では、この依存グラフが効きます。ただしDSL自体を学ぶ必要があります。
ChefのレシピはRubyそのものです。Rubyが書けるチームなら表現力は最も高く、逆にRubyを知らないインフラ担当者にとっては学習コストが最も高くなります。
5. 3ツールの比較まとめ
| 比較軸 | Ansible | Puppet | Chef |
|---|---|---|---|
| エージェント | 不要 | 必要(puppet agent) | 必要(Chef Infra Client) |
| 実行モデル | push型(手動起動) | pull型(定期実行) | pull型(定期実行) |
| 記述言語 | YAML + Jinja2 | Puppet DSL | Ruby DSL |
| ターゲット側の前提 | SSH + Python 3 | エージェントと証明書 | クライアントと鍵 |
| 導入初日の工数 | 小(1台にインストール) | 中(サーバー構築+配布) | 中(サーバー構築+配布) |
| 設定ドリフトの自動修復 | 実行時のみ | 自動(既定30分間隔) | 自動(間隔は設定可能) |
Ansibleを最小構成で動かして違いを体感する
比較表を眺めるより、実際に1台動かしてみるほうが理解は早く進みます。Ansibleはエージェントレスなので、この検証が最も短時間で終わります。1. コントロールノードにインストールする
RHEL系(RHEL 9 / Rocky Linux 9)ではAppStreamリポジトリから導入できます。# RHEL 9 / Rocky Linux 9 の場合 sudo dnf install -y ansible-core # Ubuntu 24.04 LTS の場合 sudo apt update sudo apt install -y ansible
rpmコマンドで確認できます。詳しい照会オプションはrpm コマンドの使い方を参照してください。インストール後、実際にコントロールノードで確認した出力が以下です(Rocky Linux 9.4)。
$ ansible --version ansible [core 2.14.14] config file = /home/opsuser/ansible/ansible.cfg configured module search path = ['/home/opsuser/.ansible/plugins/modules'] ansible python module location = /usr/lib/python3.9/site-packages/ansible executable location = /usr/bin/ansible python version = 3.9.18 jinja version = 3.1.2 libyaml = True
config fileの行に、実際に読み込まれているansible.cfgのパスが表示されます。設定が効いていないと感じたときは、まずここを見てください。2. インベントリに管理対象を書く
Ansibleでは「どのサーバーを管理するか」をインベントリファイルに書きます。ターゲット側での作業は一切ありません。# inventory/hosts.ini [web] web01.example.internal ansible_host=10.0.10.11 web02.example.internal ansible_host=10.0.10.12 [web:vars] ansible_user=opsuser
ansible_hostにIPアドレスを直接書けば名前解決に依存しませんが、実運用ではホスト名で書けるようにDNSを整えておくほうが管理は楽になります。社内DNSの設定はLinux DNS 設定の基本で解説しています。3. 疎通を確認する
エージェントを配っていないのに、この時点でもう全台に届きます。$ ansible web -i inventory/hosts.ini -m ping web01.example.internal | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python3" }, "changed": false, "ping": "pong" } web02.example.internal | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python3" }, "changed": false, "ping": "pong" }
なお、
pingという名前ですがICMPのpingではありません。SSHでログインしてPythonが動くかどうかを確認するモジュールです。ここがSUCCESSになれば、Ansibleの前提条件はすべて満たされています。構成管理を「読んで理解する」から「動かせる」に変えたい方へ
ツールの比較で止まってしまう最大の理由は、検証環境を用意して最初の1本を通すまでの段差です。インベントリ設計からrole構造、本番適用の手順までを実機で通しで動かすなら、ハンズオン形式が最短ルートです。
>> Ansible実践セミナーの詳細はこちら
どれを選ぶべきか:現場条件から逆算する判断基準
1. サーバー台数と変更頻度で決める
もっとも実務的な判断軸がこれです。・数台~数百台、変更は計画的に流す:Ansibleが有力。導入が軽く、実行タイミングを人が握れる
・数千台規模、設定ドリフトを常時打ち消したい:Puppet・Chefのpull型が有利。エージェントが勝手に収束させる
・サーバーが頻繁に増減するクラウド環境:どちらでも可能だが、新規ノードへエージェントを自動導入する仕組みが必要になるぶん、エージェントレスのほうが構成はシンプルになる
台数が数千を超えると、push型は1回の実行にかかる時間が問題になります。Ansibleにも並列度(forks)やpull型運用の仕組みはありますが、素直に設計するならpull型のほうが素直です。逆に数十台規模でpull型を選ぶと、管理サーバーの冗長化や証明書の運用といった「本体ではない仕事」が増えます。
2. チームのスキルセットで決める
コードは書いた人だけのものではありません。3年後に別の担当者が読むことを前提に選びます。・インフラ担当者中心・プログラミング経験は限定的:Ansible。YAMLは設定ファイルの延長として読める
・Ruby資産・Ruby経験者が社内にいる:Chefの表現力を活かせる
・大規模かつ厳密な依存関係管理が必要:PuppetのDSLと依存グラフが効く
私が現場で見てきた限り、構成管理の導入が頓挫する最大の原因は、ツールの性能ではなく「書ける人が1人しかいなかった」ことです。属人化しにくさを最優先するなら、学習曲線がもっとも緩いAnsibleから始めるのが現実的です。
3. 既存の運用ルールとの相性で決める
セキュリティポリシー上、サーバーに追加のエージェントを常駐させられない環境があります。金融系や公共系では珍しくありません。この制約がある時点で、選択肢は実質Ansibleに絞られます。逆に、すでに監視エージェントや資産管理エージェントを全台に配布する仕組みがある現場なら、エージェント型の導入コストは大きく下がります。「エージェントを配る仕組みがあるか」は、比較記事にはあまり書かれませんが、実際の工数を大きく左右します。
4. TerraformやSaltStackとの位置づけを整理する
比較の際によく混同されるツールも整理しておきます。・Terraform:構成管理ではなくプロビジョニング(クラウドリソースそのものの作成・削除)が担当領域。AnsibleやPuppetと競合するのではなく、Terraformでサーバーを作り、その中身をAnsibleで整えるという組み合わせが一般的
・SaltStack(Salt):エージェント型(minion)が基本だが、salt-sshによるエージェントレス運用も可能。記述はYAMLとJinja2でAnsibleに近い
・クラウドのcloud-init:サーバー起動時の初回設定に限定される。継続的な状態維持は担わない
「構成管理ツールを選ぶ」という問いは、実際には「どのレイヤーを誰に担当させるか」という設計判断です。ツール単体の優劣ではなく、担当範囲の切り分けから考えると迷いが減ります。
「Failed to connect to the host via ssh」が出た時の対処法
Ansibleで最初に必ず遭遇するのがこのエラーです。エージェントレスであるがゆえに、つまずきはほぼすべてSSHまわりに集中します。web01.example.internal | UNREACHABLE! => { "changed": false, "msg": "Failed to connect to the host via ssh: Permission denied (publickey,password).", "unreachable": true }
・接続ユーザーの不一致:インベントリの
ansible_userが実サーバーのユーザーと違う・公開鍵が未配置:
ssh-copy-idでの鍵配布が済んでいない・鍵のパーミッション:秘密鍵が600以外になっている
切り分けの鉄則は「Ansibleを疑う前に、素のSSHで入れるかを確かめる」ことです。
# まず素のsshで接続できるかを確認する ssh opsuser@10.0.10.11 # 通るなら、Ansible側の詳細ログで接続コマンドを確認する ansible web -i inventory/hosts.ini -m ping -vvv
-vvvを付けると、Ansibleが内部で組み立てているSSHコマンドがそのまま表示されます。ここに表示されるユーザー名や鍵のパスと、手で成功したSSHコマンドを見比べれば、原因はほぼ一発で特定できます。「Host key verification failed」が出た時の対処法
初めて接続するホストでは、SSHのホスト鍵がknown_hostsに未登録のため接続が拒否されます。検証環境では
ansible.cfgで確認を無効化できますが、本番環境でこの設定を入れるのは中間者攻撃に対して無防備になるため避けてください。運用としては、構築時にホスト鍵をssh-keyscanで収集し、フィンガープリントを確認したうえでknown_hostsに登録するのが正解です。# 検証環境限定。本番では使わない # ansible.cfg [defaults] host_key_checking = False # 本番向け:ホスト鍵を収集してから登録する ssh-keyscan -H 10.0.10.11 >> ~/.ssh/known_hosts
導入して失敗しないための3つの鉄則
比較の結論としてどのツールを選んだとしても、共通して守るべき原則があります。1. 既存サーバーにいきなり適用しない
最初の対象は、壊しても影響のない検証サーバーにしてください。構成管理ツールは「定義した状態に強制的に収束させる」道具なので、書き漏らした設定は容赦なく上書き・削除されます。
2. 小さく始めて、対象を1つずつ増やす
いきなり全設定をコード化しようとすると、必ず途中で力尽きます。「NTPの設定だけ」「sudoersの配布だけ」のように、変更頻度が高く事故が起きやすい1点から始めるとコードが育ちます。
3. 適用前の差分確認を運用に組み込む
Ansibleにはcheckモード、Puppetには
--noop、Chefには--why-runという「実際には変更せず、何が変わるかだけを見る」仕組みがあります。本番適用前にこれを必ず通す運用にしておけば、事故の大半は防げます。本記事のまとめ
| 知りたいこと | 結論 |
|---|---|
| 3つの最大の違いは何か | Ansibleはエージェントレスのpush型、PuppetとChefはエージェント型のpull型 |
| 導入が一番速いのはどれか | Ansible。コントロールノード1台に入れれば既存サーバーをすぐ管理下に置ける |
| 設定ドリフトを自動で戻したい | PuppetまたはChef。エージェントが定期実行で収束させる |
| 学習コストが低いのはどれか | Ansible。YAMLとJinja2で完結し、専用言語の習得が不要 |
| Ansibleの動作確認コマンド | ansible web -i inventory/hosts.ini -m ping |
| 接続できない時の調べ方 | ansible web -i inventory/hosts.ini -m ping -vvvで組み立てられたSSHコマンドを確認する |
| Terraformとの関係 | 競合しない。Terraformでリソースを作り、Ansibleで中身を構成する |
そして、どれを選ぶにしても最初の1本を実機で通した経験が、その後の設計判断の精度を決めます。まずは検証サーバー1台に対して、Ansibleでnginxを入れるところから始めてみてください。
Ansible実践ハンズオンの詳細を見る >>
3,100名以上が実践した「型」を無料で公開中
プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。
姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら
- 前のページへ:Ansibleのfailed_when・changed_when・ignore_errorsでタスク結果を制御する方法|commandモジュールを安全に扱う設計パターン
- この記事の属するカテゴリ:Ansibleへ戻る

無料メルマガで学習を続ける
Linuxの実践スキルをメールで毎週お届け。
登録は30秒、解除もいつでも可。
登録無料・いつでも解除できます