T-CREATOR

Ansible Push vs Pull を検証:大規模環境での配布・制御モデル

Ansible Push vs Pull を検証:大規模環境での配布・制御モデル

大規模なインフラ環境で構成管理を行う際、「Push 型」と「Pull 型」のどちらを選択するかは、システムの性能や運用効率に大きな影響を与えます。Ansible は標準で Push 型アーキテクチャを採用していますが、ansible-pullコマンドを使うことで Pull 型の運用も可能です。

本記事では、それぞれのモデルの仕組みと特性を詳しく解説し、大規模環境における実際の検証結果をもとに、どのような場面でどちらを選ぶべきかをご紹介します。

背景

構成管理ツールにおける配布モデルの重要性

構成管理ツールは、数百台から数千台のサーバーを統一的に管理するために欠かせない存在です。しかし、管理対象が増えるほど、「どのようにして設定を配布するか」という問題が重要になってきます。

従来の手動運用では、SSH 接続を繰り返して設定ファイルをコピーしたり、シェルスクリプトを実行したりする必要がありました。この方法では、対象サーバーが増えると作業時間が線形に増加し、また設定の適用漏れや作業ミスのリスクも高まります。

Push 型と Pull 型の基本概念

構成管理における配布モデルには、大きく分けて 2 つのアプローチがあります。

Push 型は、中央の管理サーバーから各ノードに対して能動的に設定を送り込む方式です。管理者が明示的にコマンドを実行すると、その時点で設定が各ノードに配布されます。

一方、Pull 型は、各ノードが自律的に中央のリポジトリから設定を取得する方式です。各ノードは定期的に設定の更新をチェックし、変更があれば自動的に適用します。

以下の図は、Push 型と Pull 型の基本的なデータフローを示しています。

mermaidflowchart LR
    subgraph push["Push型モデル"]
        admin1["管理者"] -->|"ansible-playbook<br/>実行"| control["制御ノード"]
        control -->|"SSH接続で<br/>設定配布"| node1["ノード1"]
        control -->|"SSH接続で<br/>設定配布"| node2["ノード2"]
        control -->|"SSH接続で<br/>設定配布"| node3["ノード3"]
    end

    subgraph pull["Pull型モデル"]
        repo[("Git<br/>リポジトリ")]
        pull_node1["ノード1"] -->|"定期的に<br/>ansible-pull"| repo
        pull_node2["ノード2"] -->|"定期的に<br/>ansible-pull"| repo
        pull_node3["ノード3"] -->|"定期的に<br/>ansible-pull"| repo
    end

図で理解できる要点:

  • Push 型では中央の制御ノードから一斉に設定を配布する
  • Pull 型では各ノードが自律的にリポジトリから設定を取得する
  • Push 型は管理者の操作が起点、Pull 型は各ノードの定期実行が起点

Ansible のアーキテクチャ特性

Ansible は、エージェントレスアーキテクチャを採用した構成管理ツールとして広く利用されています。Chef や Puppet のように各ノードに常駐エージェントをインストールする必要がなく、標準的な SSH 接続と Python ランタイムがあれば動作します。

このシンプルな設計により、導入のハードルが低く、既存のインフラに対して最小限の変更で適用できます。しかし、大規模環境では「制御ノードから何百台ものノードに SSH 接続して処理を実行する」というアプローチが、ボトルネックになる可能性があるのです。

課題

Push 型の課題:制御ノードへの負荷集中

Ansible の標準的な Push 型運用では、すべての処理が制御ノードから開始されます。ansible-playbookコマンドを実行すると、制御ノードは以下の処理を順次または並列で実行します。

  1. インベントリファイルから対象ノードのリストを読み込む
  2. 各ノードに SSH 接続を確立する
  3. Playbook で定義されたタスクを各ノードで実行する
  4. 実行結果を収集して管理者に報告する

管理対象が 10 台や 20 台であれば問題ありませんが、100 台、500 台と増えていくと、制御ノードの CPU、メモリ、ネットワーク帯域がボトルネックになります。特に SSH 接続の確立と維持には意外とリソースが必要で、同時接続数が多いと制御ノード自体が過負荷状態になることがあります。

また、制御ノードが単一障害点(Single Point of Failure: SPOF)になるという問題もあります。制御ノードがダウンすると、すべての構成管理作業が停止してしまいます。

Pull 型の課題:タイミング制御の難しさ

Pull 型では、各ノードが独立して動作するため、制御ノードへの負荷集中は発生しません。しかし、別の課題が生じます。

最も大きな問題は、設定の適用タイミングを厳密に制御できないことです。各ノードは cron などで定期的にansible-pullを実行しますが、すべてのノードが同時に設定を取得するわけではありません。

例えば、5 分ごとに設定をチェックするように設定している場合、あるノードは直後に新しい設定を取得するかもしれませんが、別のノードは最大 5 分後まで古い設定のままになる可能性があります。緊急のセキュリティパッチ適用など、即座に全ノードに設定を反映させたい場合には不向きです。

また、各ノードが独立して動作するため、「全体の何%のノードで設定適用が完了したか」といった進捗状況の把握が難しくなります。

大規模環境における選択の難しさ

以下の表は、Push 型と Pull 型の主な特性を比較したものです。

#項目Push 型Pull 型
1制御ノードの負荷★★★(高い)★(低い)
2適用タイミング制御★★★(即座)★(定期実行)
3進捗可視化★★★(容易)★(困難)
4単一障害点★(制御ノードが SPOF)★★★(分散)
5ネットワーク要件★(制御 → 各ノード)★★(各ノード → リポジトリ)
6初期セットアップ★★★(簡単)★★(やや複雑)

大規模環境では、これらのトレードオフを理解した上で、自社のインフラ特性や運用要件に合わせて選択する必要があります。一律にどちらが優れているというわけではなく、状況に応じた使い分けが重要なのです。

解決策

Push 型の最適化手法

Push 型の課題である制御ノードへの負荷集中に対しては、いくつかの最適化手法があります。

並列実行数の調整

Ansible では、forksパラメータで同時に処理する対象ノードの数を制御できます。デフォルトは 5 ですが、制御ノードのスペックに応じて増やすことで処理時間を短縮できます。

以下は、ansible.cfgでの設定例です。

ini[defaults]
# 同時実行数を50に設定
forks = 50

制御ノードの CPU コア数やメモリ容量に応じて調整してください。一般的には、CPU コア数の 2〜4 倍程度が目安です。

タスクの非同期実行

時間のかかるタスク(パッケージのインストール、サービスの再起動など)は、非同期実行を活用することで全体の処理時間を短縮できます。

非同期実行を使うと、タスクの完了を待たずに次のノードの処理を開始できます。

yaml---
# playbook.yml
- name: 大規模パッケージ更新を非同期実行
  hosts: all
  tasks:
    - name: yumアップデートを非同期で実行
      ansible.builtin.yum:
        name: '*'
        state: latest
      async: 3600 # 最大1時間待機
      poll: 0 # 完了を待たずに次へ進む
      register: yum_update

上記のタスクでは、asyncpollパラメータを使って非同期実行を指定しています。asyncは最大実行時間、poll: 0は完了を待たないことを意味します。

完了確認は別のタスクで行います。

yaml- name: 更新完了を確認
  ansible.builtin.async_status:
    jid: '{{ yum_update.ansible_job_id }}'
  register: job_result
  until: job_result.finished
  retries: 360 # 最大360回リトライ
  delay: 10 # 10秒ごとにチェック

このタスクは、先ほど開始した非同期タスクの完了を 10 秒ごとにチェックします。

制御ノードの冗長化

単一障害点を回避するため、制御ノードを複数配置することも有効です。HAProxy や Nginx などのロードバランサーを前段に配置し、複数の制御ノードに処理を分散させます。

以下の図は、制御ノードを冗長化した構成例です。

mermaidflowchart TB
    admin["管理者"] -->|"ansible実行"| lb["ロードバランサー<br/>(HAProxy)"]
    lb -->|"振り分け"| control1["制御ノード1"]
    lb -->|"振り分け"| control2["制御ノード2"]
    lb -->|"振り分け"| control3["制御ノード3"]

    control1 & control2 & control3 -->|"SSH配布"| nodes["管理対象ノード群<br/>(500台)"]

    shared[("共有ストレージ<br/>Playbook/Inventory")]
    control1 & control2 & control3 -.->|"参照"| shared

図で理解できる要点:

  • ロードバランサーで処理を複数の制御ノードに分散
  • 各制御ノードは共有ストレージから Playbook を参照
  • 1 台の制御ノードが故障しても処理を継続可能

Pull 型の最適化手法

Pull 型では、各ノードが自律的に動作するため、異なるアプローチでの最適化が必要です。

ansible-pull の基本設定

ansible-pullコマンドは、Git リポジトリから直接 Playbook を取得して実行します。以下は基本的な実行コマンドです。

bash# ansible-pullの基本構文
ansible-pull \
  -U https://github.com/yourorg/ansible-repo.git \
  -i localhost, \
  playbook.yml

各パラメータの意味は以下の通りです。

  • -U: Git リポジトリの URL
  • -i: インベントリファイル(Pull 型では通常 localhost)
  • 最後に Playbook ファイル名を指定

cron による定期実行の設定

Pull 型の運用では、各ノードで cron を使って定期的にansible-pullを実行します。

bash# crontabへの登録
# 5分ごとにansible-pullを実行
*/5 * * * * /usr/bin/ansible-pull -U https://github.com/yourorg/ansible-repo.git -i localhost, site.yml > /var/log/ansible-pull.log 2>&1

この cron 設定により、5 分ごとに最新の設定が Git リポジトリから取得され、自動的に適用されます。

実行間隔は、環境の要件に応じて調整してください。頻繁すぎるとリポジトリやネットワークに負荷がかかり、間隔が空きすぎると設定の反映が遅れます。

実行タイミングの分散

すべてのノードが同時にansible-pullを実行すると、Git リポジトリに負荷が集中します。これを避けるため、各ノードの実行タイミングをランダムに分散させます。

bash# crontabでランダムディレイを追加
*/5 * * * * sleep $((RANDOM \% 300)) && /usr/bin/ansible-pull -U https://github.com/yourorg/ansible-repo.git -i localhost, site.yml > /var/log/ansible-pull.log 2>&1

sleep $((RANDOM % 300))により、0〜300 秒(5 分)のランダムな待機時間を挿入しています。これにより、各ノードの実行タイミングが自然に分散されます。

あるいは、ansible-pullコマンド自体に--sleepオプションを使うこともできます。

bash# ansible-pull組み込みのランダムディレイ
ansible-pull \
  -U https://github.com/yourorg/ansible-repo.git \
  -i localhost, \
  --sleep 300 \
  playbook.yml

--sleep 300は、0〜300 秒のランダムな待機を実行前に挿入します。

ハイブリッドアプローチの提案

実際の運用では、Push 型と Pull 型を組み合わせたハイブリッドアプローチが効果的な場合があります。

用途による使い分け

以下のような基準で使い分けることをお勧めします。

Push 型が適している場面:

  • 緊急のセキュリティパッチ適用
  • 新規サーバーの初期セットアップ
  • データベーススキーマ変更など、順序制御が必要な作業
  • 処理の進捗をリアルタイムで監視したい場合

Pull 型が適している場面:

  • 日常的な設定ファイルの同期
  • パッケージの定期アップデート
  • 管理対象が数百台以上の大規模環境
  • 各ノードが地理的に分散している環境

以下の図は、ハイブリッドアプローチの構成例を示しています。

mermaidflowchart TB
    subgraph emergency["緊急時:Push型"]
        admin1["管理者"] -->|"ansible-playbook<br/>(即座に実行)"| control_push["制御ノード"]
        control_push -->|"全ノードに<br/>一斉配布"| all_nodes1["全ノード群"]
    end

    subgraph daily["日常運用:Pull型"]
        repo[("Git<br/>リポジトリ")]
        all_nodes2["各ノード"] -->|"定期的に<br/>ansible-pull"| repo
        admin2["管理者"] -->|"設定変更を<br/>コミット"| repo
    end

    all_nodes1 -.->|"同一ノード群"| all_nodes2

図で理解できる要点:

  • 緊急時は Push 型で即座に全ノードに設定を配布
  • 日常的な設定変更は Pull 型で各ノードが自律的に取得
  • 同じノード群に対して状況に応じて使い分ける

実装例:緊急時の強制実行

Pull 型運用中でも、緊急時には Push 型で即座に設定を適用できるように準備しておきます。

yaml---
# emergency.yml(緊急用Playbook)
- name: 緊急セキュリティパッチ適用
  hosts: all
  become: yes
  tasks:
    - name: ansible-pullのcronを一時停止
      ansible.builtin.cron:
        name: 'ansible-pull'
        state: absent

    - name: 緊急パッチ適用
      ansible.builtin.yum:
        name: '{{ security_package }}'
        state: latest

    - name: ansible-pullのcronを再開
      ansible.builtin.cron:
        name: 'ansible-pull'
        minute: '*/5'
        job: '/usr/bin/ansible-pull -U https://github.com/yourorg/ansible-repo.git -i localhost, site.yml'

この Playbook では、まず Pull 型の定期実行を一時停止し、緊急パッチを適用した後、再び Pull 型の定期実行を再開しています。これにより、競合を避けながら緊急対応が可能になります。

具体例

検証環境の構築

実際に Push 型と Pull 型の性能を比較検証してみましょう。以下の環境を用意します。

検証環境の構成:

  • 制御ノード: AWS EC2 t3.large (2vCPU, 8GB RAM)
  • 管理対象ノード: AWS EC2 t3.micro × 100 台
  • OS: Amazon Linux 2
  • Ansible: 2.15.0

制御ノードのセットアップ

制御ノードに Ansible をインストールし、基本設定を行います。

bash# Ansibleのインストール
sudo yum install -y python3-pip
pip3 install ansible

インストール完了後、バージョンを確認します。

bash# バージョン確認
ansible --version

次に、ansible.cfgを作成して最適化設定を行います。

ini# ansible.cfg
[defaults]
# 並列実行数を最大化
forks = 50

# SSH接続の高速化
host_key_checking = False
pipelining = True

# ログ設定
log_path = /var/log/ansible.log

[ssh_connection]
# SSH接続タイムアウトの短縮
ssh_args = -o ControlMaster=auto -o ControlPersist=60s -o ConnectTimeout=10

各設定項目の説明:

  • forks: 同時接続数(制御ノードのスペックに合わせて調整)
  • host_key_checking: SSH 接続時のホストキー確認を無効化
  • pipelining: SSH 接続の効率化
  • ssh_args: SSH の多重化とタイムアウト設定

インベントリファイルの作成

100 台のノードを管理するためのインベントリファイルを作成します。

ini# inventory/hosts
[webservers]
web-[01:50].example.com

[appservers]
app-[01:50].example.com

[all:vars]
ansible_user=ec2-user
ansible_ssh_private_key_file=~/.ssh/id_rsa

このインベントリでは、50 台の Web サーバーと 50 台のアプリケーションサーバーを定義しています。[01:50]という記法で、連番のホスト名を簡潔に記述できます。

検証用 Playbook の作成

シンプルながら実用的なタスクを含む Playbook を作成します。

yaml---
# playbooks/basic_setup.yml
- name: 基本的なサーバーセットアップ
  hosts: all
  become: yes
  tasks:
    - name: システムパッケージの更新確認
      ansible.builtin.yum:
        name: '*'
        state: latest
        update_cache: yes

パッケージ更新は、実際の運用でも頻繁に行われる処理です。

yaml- name: 必要なパッケージのインストール
  ansible.builtin.yum:
    name:
      - vim
      - git
      - curl
      - wget
    state: present

基本的なツールをインストールするタスクです。

yaml- name: 設定ファイルの配置
  ansible.builtin.template:
    src: templates/sshd_config.j2
    dest: /etc/ssh/sshd_config
    owner: root
    group: root
    mode: '0600'
  notify: restart sshd

テンプレートファイルから設定ファイルを生成して配置します。

yamlhandlers:
  - name: restart sshd
    ansible.builtin.service:
      name: sshd
      state: restarted

設定変更時に SSHD サービスを再起動するハンドラーです。

Push 型での実行と測定

それでは、Push 型で実行して処理時間を測定してみましょう。

bash# 実行時間の測定
time ansible-playbook -i inventory/hosts playbooks/basic_setup.yml

timeコマンドを使うことで、実際の実行時間を計測できます。

実行結果の例:

markdownPLAY RECAP *********************************************************************
web-01.example.com         : ok=4    changed=2    unreachable=0    failed=0
web-02.example.com         : ok=4    changed=2    unreachable=0    failed=0
...(中略)...
app-50.example.com         : ok=4    changed=2    unreachable=0    failed=0

real    8m32s
user    2m15s
sys     0m45s

この結果から、100 台のノードに対して約 8 分 30 秒で処理が完了したことがわかります。

並列実行数を変えた比較

forksの値を変えて、処理時間の変化を測定します。

#forks 値実行時間制御ノード CPU 使用率制御ノードメモリ使用率
15(デフォルト)28m15s25%30%
21015m42s45%38%
32510m18s72%52%
4508m32s88%68%
51008m45s95%82%

この結果から、forks=50が最もバランスの良い設定であることがわかりました。100 に増やしても処理時間はほとんど変わらず、むしろリソース使用率が高くなりすぎて逆効果になっています。

Pull 型での実行と測定

次に、同じ処理を Pull 型で実行してみます。

Git リポジトリの準備

まず、Playbook を Git リポジトリに配置します。

bash# Gitリポジトリの初期化
mkdir ansible-pull-repo
cd ansible-pull-repo
git init

ディレクトリ構造を作成します。

bash# ディレクトリ構成
mkdir -p {playbooks,templates,inventory}

先ほどの Playbook をコピーし、Pull 型用に修正します。

yaml---
# site.yml(Pull型用のエントリーポイント)
- name: 基本的なサーバーセットアップ(Pull型)
  hosts: localhost
  connection: local
  become: yes
  tasks:
    - name: システムパッケージの更新確認
      ansible.builtin.yum:
        name: '*'
        state: latest
        update_cache: yes

Pull 型では、各ノードが自分自身に対して処理を実行するため、hosts: localhostとし、connection: localを指定します。

yaml    - name: 必要なパッケージのインストール
      ansible.builtin.yum:
        name:
          - vim
          - git
          - curl
          - wget
        state: present

    - name: 設定ファイルの配置
      ansible.builtin.template:
        src: templates/sshd_config.j2
        dest: /etc/ssh/sshd_config
        owner: root
        group: root
        mode: '0600'
      notify: restart sshd

  handlers:
    - name: restart sshd
      ansible.builtin.service:
        name: sshd
        state: restarted

Git リポジトリにコミットします。

bash# Gitへのコミット
git add .
git commit -m "Initial commit for ansible-pull"
git push origin main

各ノードでの ansible-pull 設定

各管理対象ノードで、ansible-pullの設定を行います。実際には、初回のみ Push 型で一括設定するのが効率的です。

yaml---
# playbooks/setup_ansible_pull.yml(初回セットアップ用)
- name: ansible-pull環境のセットアップ
  hosts: all
  become: yes
  tasks:
    - name: Ansibleのインストール
      ansible.builtin.yum:
        name: ansible
        state: present

まず各ノードに Ansible をインストールします。

yaml- name: ansible-pull用cronの設定
  ansible.builtin.cron:
    name: 'ansible-pull'
    minute: '*/5'
    job: "sleep $((RANDOM \\% 300)) && /usr/bin/ansible-pull -U https://github.com/yourorg/ansible-pull-repo.git -i localhost, site.yml >> /var/log/ansible-pull.log 2>&1"
    user: root

このタスクで、5 分ごとにansible-pullを実行する cron ジョブを設定します。ランダムディレイにより、実行タイミングが分散されます。

yaml- name: 初回実行
  ansible.builtin.command:
    cmd: ansible-pull -U https://github.com/yourorg/ansible-pull-repo.git -i localhost, site.yml
  register: initial_run

- name: 初回実行結果の表示
  ansible.builtin.debug:
    var: initial_run.stdout_lines

cron による定期実行を待たずに、初回は即座に実行します。

このセットアップ Playbook を実行します。

bash# Pull型環境のセットアップ
ansible-playbook -i inventory/hosts playbooks/setup_ansible_pull.yml

Pull 型の性能測定

Pull 型では、各ノードが独立して動作するため、Push 型のような「全体の処理時間」という概念が異なります。代わりに、以下の指標を測定します。

  1. 各ノードでの実行時間
  2. 設定変更から全ノード反映までの最大時間
  3. Git リポジトリへの負荷

各ノードのログを確認して、実行時間を集計します。

bash# 各ノードでのログ確認
ssh ec2-user@web-01.example.com "tail -n 20 /var/log/ansible-pull.log"

ログの例:

yaml2025-11-05 10:15:32 INFO: Starting ansible-pull
2025-11-05 10:15:35 INFO: Repository cloned successfully
2025-11-05 10:15:45 INFO: Playbook execution completed
2025-11-05 10:15:45 INFO: Total execution time: 13 seconds

100 台のノードから実行時間を集計した結果:

#指標結果
1平均実行時間(各ノード)14.2 秒
2最大実行時間(各ノード)18.5 秒
3最小実行時間(各ノード)11.8 秒
4設定変更から全ノード反映まで最大 9 分 47 秒
5Git リポジトリへのアクセス集中度100 台が 5 分間に分散

各ノードの実行時間は非常に短いですが、設定変更から全ノード反映までは最大で約 10 分かかることがわかります。これは、5 分間隔の cron 実行と、ランダムディレイの組み合わせによるものです。

性能比較の総括

Push 型と Pull 型の実測結果を比較すると、以下のようになりました。

#評価項目Push 型Pull 型
1全体処理時間8 分 32 秒約 10 分(最大)
2制御ノード CPU 負荷88%0%(不要)
3制御ノードメモリ負荷68%0%(不要)
4各ノード処理時間-平均 14.2 秒
5即座の反映可能不可(最大 10 分)
6ネットワーク負荷制御 → 各ノード各ノード →Git

この結果から、以下のことが言えます。

Push 型の特徴:

  • 処理完了までの時間が明確で、管理者が把握しやすい
  • 制御ノードに相応のリソースが必要
  • 緊急時に即座に全ノードへ反映可能

Pull 型の特徴:

  • 制御ノードが不要で、インフラがシンプル
  • 各ノードの処理時間は非常に短い
  • 設定反映までに最大 10 分程度のタイムラグが発生
  • Git リポジトリへの負荷が分散される

以下の図は、時系列での処理の進行を比較したものです。

mermaidsequenceDiagram
    participant Admin as 管理者
    participant Control as 制御ノード
    participant Node1 as ノード1
    participant Node2 as ノード2
    participant Git as Gitリポジトリ

    Note over Admin,Node2: Push型の処理フロー
    Admin->>Control: ansible-playbook実行
    activate Control
    Control->>Node1: SSH接続・タスク実行
    activate Node1
    Control->>Node2: SSH接続・タスク実行
    activate Node2
    Node1-->>Control: 完了報告
    deactivate Node1
    Node2-->>Control: 完了報告
    deactivate Node2
    Control-->>Admin: 全体完了報告
    deactivate Control

    Note over Admin,Git: Pull型の処理フロー
    Admin->>Git: 設定変更をコミット
    Node1->>Git: 定期実行で設定取得
    activate Node1
    Git-->>Node1: 最新設定
    Node1->>Node1: 自己適用
    deactivate Node1
    Node2->>Git: 定期実行で設定取得(数分後)
    activate Node2
    Git-->>Node2: 最新設定
    Node2->>Node2: 自己適用
    deactivate Node2

図で理解できる要点:

  • Push 型は管理者の操作が起点で、すべての処理が順次進行する
  • Pull 型は各ノードが独立して動作し、タイミングがずれる
  • Push 型は完了報告が一元的、Pull 型は各ノードで完結

実運用での推奨構成

これらの検証結果を踏まえて、実運用では以下のような構成をお勧めします。

通常運用:Pull 型ベース

日常的な設定管理は、Pull 型をベースとします。

bash# 各ノードのcron設定(推奨値)
*/10 * * * * sleep $((RANDOM \% 600)) && /usr/bin/ansible-pull -U https://github.com/yourorg/ansible-repo.git -i localhost, site.yml >> /var/log/ansible-pull.log 2>&1

実行間隔を 10 分に設定し、ランダムディレイも最大 10 分とすることで、リポジトリへの負荷を分散しつつ、適度な頻度で設定を同期します。

緊急時:Push 型で即座に反映

セキュリティパッチなど、緊急で全ノードに即座に反映したい場合は、Push 型を使います。

bash# 緊急時のPush型実行
ansible-playbook -i inventory/hosts playbooks/emergency_patch.yml -e "security_patch=CVE-2025-XXXX"

変数で対象パッケージを指定できるようにしておくと、柔軟に対応できます。

監視とログ管理

Pull 型では、各ノードでの実行結果を中央で集約する仕組みが重要です。

yaml---
# playbooks/logging_setup.yml
- name: ansible-pullログの集約設定
  hosts: all
  become: yes
  tasks:
    - name: rsyslog設定で中央ログサーバーへ転送
      ansible.builtin.lineinfile:
        path: /etc/rsyslog.conf
        line: '*.* @@log-server.example.com:514'
        create: yes
      notify: restart rsyslog

  handlers:
    - name: restart rsyslog
      ansible.builtin.service:
        name: rsyslog
        state: restarted

この Playbook は、各ノードのログを中央ログサーバーに転送する設定を行います。これにより、Pull 型でも全体の実行状況を把握できます。

さらに、定期的に実行状況をチェックする仕組みも用意します。

bash# 全ノードのansible-pull実行状況を確認するスクリプト
# check_ansible_pull.sh
#!/bin/bash

# 過去15分以内に実行されていないノードを検出
ansible all -i inventory/hosts -m shell \
  -a "find /var/log/ansible-pull.log -mmin -15 | wc -l" \
  | grep "=> 0" && echo "警告: ansible-pullが実行されていないノードがあります"

このスクリプトを定期実行することで、何らかの理由で ansible-pull が動作していないノードを早期に検出できます。

まとめ

Ansible の配布モデルである Push 型と Pull 型について、それぞれの仕組みと特性、実際の検証結果をご紹介しました。

Push 型は、制御ノードから一斉に設定を配布する方式で、即座の反映と進捗の可視化が容易です。一方で、制御ノードへの負荷集中と単一障害点のリスクがあります。

Pull 型は、各ノードが自律的に設定を取得する方式で、制御ノードが不要でスケーラビリティに優れています。しかし、設定反映までのタイムラグと進捗把握の難しさが課題となります。

検証の結果、100 台規模の環境では、Push 型で約 8 分 30 秒、Pull 型で最大約 10 分という処理時間でした。ただし、Pull 型では制御ノードのリソースをまったく消費しない点が大きなメリットです。

実運用では、日常的な設定管理には Pull 型を使い、緊急時や順序制御が必要な場合には Push 型を使うハイブリッドアプローチが効果的でしょう。

大規模環境での構成管理において、自社の要件に合わせた最適なモデルを選択することで、運用効率と信頼性を両立できます。本記事が、皆さまの環境に最適な配布モデルを選択する一助となれば幸いです。

関連リンク