ControlPersist と Pipelining を活用した Ansible パフォーマンスの最大化
Ansible は IT インフラストラクチャの自動化に強力なツールであり、構成管理とアプリケーションデプロイメントを大規模に実現します。しかし、高ボリューム環境や多数のノードを管理する場合、タスクごとに SSH 接続を確立する際のオーバーヘッドが大きなボトルネックとなることがあります。これにより、プレイブックの実行時間が非常に遅くなる可能性があります。幸いなことに、Ansible には ControlPersist と Pipelining という 2 つの強力な機能があり、管理対象ノードとの通信方法を最適化することでパフォーマンスを劇的に向上させることができます。
このガイドでは、ControlPersist と Pipelining の理解と実装について説明します。これらのテクニックを活用することで、実行時間を大幅に短縮し、特に数百または数千ホストが存在する環境で Ansible 自動化をより効率的かつ応答性の高いものにすることができます。これらの最適化を習得することは、Ansible デプロイメントを効果的にスケールさせたい人にとって不可欠です。
Ansible のデフォルト接続動作の理解
デフォルトでは、Ansible はプレイブック内で実行される各タスクに対して、各管理対象ホストに新しい SSH 接続を確立します。接続ごとに、いくつかのステップを実行します。
- SSH 接続の開始: 新しい SSH 接続が確立されます。
- モジュールの転送: Ansible は必要な Python モジュール(またはその他の関連ファイル)をリモートホストに転送します。
- モジュールの実行: モジュールがリモートホストで実行されます。
- 出力の受信: Ansible は実行結果を取得します。
- 接続のクローズ: SSH 接続が終了します。
このアプローチは堅牢であり、各タスクのクリーンな状態を保証しますが、繰り返しの接続とモジュール転送プロセスは、特に多数のタスクや大規模なインベントリを扱う場合に considerable な時間を消費します。
ControlPersist による接続の最適化
ControlPersist は、初期コマンドが終了した後も指定された期間 SSH 接続を開いたままにできる SSH 機能です。これにより、同じホストを対象とする後続の Ansible タスクは、新しい接続を確立するのではなく、既存の開いた接続を再利用できます。これにより、SSH セッションのセットアップに伴う遅延が大幅に削減されます。
ControlPersist の仕組み
有効にすると、ControlPersist は SSH クライアントに制御マスター接続を維持するように指示します。同じ資格情報とオプションを使用して同じホストへの後続の SSH 接続は、このマスター接続を介して多重化できます。Ansible は、SSH 設定で ControlPath と ControlPersist オプションを設定することでこれを活用します。
Ansible で ControlPersist を有効にする
ControlPersist はいくつかの方法で有効にできます。
-
ansible.cfg経由(グローバルまたはプロジェクト固有の設定に推奨):
ansible.cfgファイル(Ansible プロジェクトディレクトリ、~/.ansible.cfg、または/etc/ansible/ansible.cfgにあります)を編集または作成します。以下の設定を[ssh_connection]セクションに追加します。ini [ssh_connection] ssh_args = -o ControlMaster=auto -o ControlPersist=600 -o ControlPath=~/.ssh/ansible_control_%r@%h:%p-o ControlMaster=auto: 接続共有を有効にします。マスター接続が存在する場合はそれを使用し、存在しない場合は作成します。-o ControlPersist=600: 制御接続を 600 秒(10 分)間開いたままにします。この値は、ワークフローとセキュリティポリシーに基づいて調整してください。期間が長いほど再利用の可能性が高まりますが、より多くのリソースが開いたままになります。-o ControlPath=~/.ssh/ansible_control_%r@%h:%p: 制御ソケットのパスを定義します。%rはリモートユーザー名、%hはホスト名、%pはポートです。これにより、異なる接続に対して一意のソケットが保証されます。
-
環境変数経由:
SSH 引数を環境変数で直接設定できます。bash export ANSIBLE_SSH_ARGS='-o ControlMaster=auto -o ControlPersist=600 -o ControlPath=~/.ssh/ansible_control_%r@%h:%p' ansible-playbook your_playbook.yml -
プレイブック経由(この設定では一般的ではない):
可能ですが、接続レベルの設定であるため、プレイブック自体に永続的な SSH オプションを設定することは一般的に推奨されません。ただし、完全を期すために、ansible.builtin.set_factのようなものを使用して影響を与えることもできますが、ansible.cfgが優先されます。
ControlPersist に関する考慮事項
- セキュリティ: 制御ソケットへのアクセスは、承認されたユーザーのみが行えるように
ControlPathを保護してください。例のデフォルトパスは、ユーザーレベルの設定では一般的に安全です。 - リソース使用量: 接続を開いたままにすると、制御ノードと管理対象ノードの両方でリソースが消費されます。多数の永続接続がある場合は、リソース使用量を監視してください。
- 接続リセット: 中間ネットワークデバイスまたはリモート SSH サーバーが
ControlPersistよりも短い接続タイムアウトを強制する場合、接続がドロップする可能性があります。ControlPersistは、安定したネットワーク環境で最も効果的です。
Pipelining によるモジュール実行の効率化
Pipelining は、タスク実行のオーバーヘッドをさらに削減するもう 1 つの強力な Ansible 最適化です。リモートホストにモジュールを転送し、実行し、出力を取得するのではなく、pipelining は SSH 接続を介してコマンドを直接ストリーミングします。これは、Ansible がリモートファイルシステムにモジュールを配置したり、出力用のテンポラリファイルを生成したりする必要がないことを意味します。
Pipelining の仕組み
Pipelining が有効になっている場合、Ansible はリモートホストで ssh を介してモジュールを直接実行します。モジュールの標準出力と標準エラーは、同じ SSH 接続を介して Ansible にパイプバックされます。これにより、Ansible がリモートファイルシステム(/usr/bin/ansible_module_name やテンポラリファイルなど)にファイルを書き込んでから実行する必要がなくなります。これは、権限昇格やリモートファイルシステムへの大幅な操作を必要としないモジュールに特に効果的です。
Ansible で Pipelining を有効にする
Pipelining は ansible.cfg ファイルまたは環境変数経由で有効になります。
-
ansible.cfg経由:
[ssh_connection]セクションを追加または変更します。ini [ssh_connection] pipelining = True -
環境変数経由:
bash export ANSIBLE_PIPELINING=True ansible-playbook your_playbook.yml
Pipelining に関する考慮事項
- 権限昇格: Pipelining は、権限昇格(例:
become: yesまたはsudoの使用)を必要としないモジュールで最も効果的です。becomeが使用される場合、Ansible は通常、リモートシステムにファイルをコピーする必要があります。頻繁にbecomeを使用する場合、pipelining はそれほど多くのメリットをもたらさないか、特定のモジュールタイプで問題を引き起こす可能性があります。 - モジュール互換性: ほとんどの組み込み Ansible モジュールは、pipelining とうまく連携します。ただし、カスタムモジュールやリモートファイルシステム操作に大きく依存するモジュールは、異なる動作をする可能性があります。十分にテストしてください。
- 接続の安定性: Pipelining が正しく機能するには、安定した SSH 接続が不可欠です。
requirettySSH 設定: Pipelining は、リモートサーバー上のrequirettySSH オプションと互換性がありません。SSH サーバーの/etc/sudoersにDefaults requirettyが設定されている場合、それを無効にするか、Ansible が接続するユーザーに対して!requirettyを使用する必要がある場合があります。
ControlPersist と Pipelining を組み合わせてパフォーマンスを最大化する
最も大幅なパフォーマンス向上を得るには、ControlPersist と Pipelining の両方を有効にすることが強く推奨されます。この組み合わせは、接続確立とモジュール実行という 2 つの主要なオーバーヘッドに対処します。
両方が有効な場合の ansible.cfg の例を以下に示します。
[ssh_connection]
ssh_args = -o ControlMaster=auto -o ControlPersist=600 -o ControlPath=~/.ssh/ansible_control_%r@%h:%p
pipelining = True
両方がアクティブな場合:
- Ansible は SSH 接続を開始し、存在しない場合は ControlMaster を確立します(ControlPersist)。
- 後続のタスクでは、既存の開いた接続が再利用されます。
- モジュールは、ファイルシステムへのコピーを必要とせずにストリーム経由で直接実行されます(Pipelining)。
この相乗効果により、Ansible が各管理対象ノードと通信する時間が劇的に短縮され、プレイブックの実行がはるかに高速になります。
実践的なシナリオ例
100 ホストで 10 個の単純なタスクを実行する必要があるプレイブックを想像してみましょう。
最適化なし:
各タスクには新しい SSH 接続、モジュール転送、実行、接続クローズが必要です。これは 100 ホスト * 10 タスク * (接続時間 + モジュール転送時間) に相当します。接続時間 が 0.5 秒で モジュール転送時間 が 0.2 秒の場合、実際のモジュール実行時間を除くと、通信と転送だけのオーバーヘッドは 100 * 10 * 0.7 = 700 秒になります。
ControlPersist と Pipelining を有効にした場合:
- 各ホストでの最初のタスクは、初期接続を確立し、ControlMaster をセットアップします。
- そのホストでの後続の 9 つのタスクすべてが、開いた接続を再利用し、モジュール実行をストリーミングします。
ホストあたりのオーバーヘッドは 接続時間 + (9 * 最小ストリーミングオーバーヘッド) に近くなります。総時間は大幅に削減され、プレイブック実行時間のほとんどは、通信のメカニズムではなく、モジュールが実行する実際の作業に費やされます。
注意が必要な場合
これらの最適化は強力ですが、考慮なしに普遍的に適用できるわけではありません。
- 厳格なファイアウォールまたはネットワーク制限のある環境: 頻繁な接続ドロップやステートフルインスペクションが ControlPersist を妨げる可能性があります。
- 高セキュリティ環境: 長期間続く SSH 接続は、高度に規制された環境ではセキュリティ上の懸念となる可能性があります。
ControlPersistの期間を適切に調整してください。 becomeおよびファイル操作に大きく依存するプレイブック:becomeが一貫して使用される場合、ファイル操作が必要になることが多いため、pipelining の効果は低下します。パフォーマンスへの影響をテストしてください。
結論
Ansible と管理対象ノード間の通信を最適化することは、効率的でスケーラブルな自動化への重要なステップです。ControlPersist と Pipelining を理解し実装することで、プレイブックの実行時間を劇的に短縮できます。ControlPersist は SSH 接続を維持して接続オーバーヘッドを削減し、Pipelining はモジュール実行をストリーミングしてファイル転送の必要性をなくします。これら 2 つの設定を、主に ansible.cfg を通じて組み合わせることは、多数のホストを管理したり、複雑なプレイブックを実行したりするすべての Ansible ユーザーにとってベストプラクティスです。常に、ご自身の環境でこれらの設定をテストしてパフォーマンスを微調整し、互換性を確保してください。