AnsibleとシェルスクリプトSSHループの違い|構成管理に踏み出す判断

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Ansible > AnsibleとシェルスクリプトSSHループの違い|構成管理に踏み出す判断
「サーバーが10台を超えたあたりから、SSHループのシェルスクリプトが手に負えなくなってきた」
そういう相談を受けることが多くなりました。

シェルスクリプトでSSHを束ねる手法は、台数が少ないうちは確かに便利です。しかしある規模を超えると、スクリプトの複雑さ・冪等性の欠如・メンテナンスコストが一気に牙を剥いてきます。

この記事では、シェルスクリプトSSHループとAnsibleが「どこが違うのか」を概念レベルで整理し、どのタイミングでAnsibleに踏み出すべきかを判断できる知識を提供します。コマンド一覧のリファレンスではなく、「なぜAnsibleが必要なのか」という設計思想の解説を軸にしています。

この記事のポイント

・SSHループは「手順の自動化」、Ansibleは「状態の自動化」という根本的な違いがある
・冪等性(何度実行しても同じ結果になる性質)の有無が最大の分岐点
・サーバー台数が10台超・設定変更が月1回以上ならAnsibleへの移行が効果的
・inventoryとrole分離で、設定の再利用性と可読性が大幅に向上する


「このままじゃマズい」と感じていませんか?
参考書を開く気力もない、同年代に取り残される不安——
でも安心してください。プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
図解60P/登録10秒/解除も3秒 / 詳細はこちら

シェルスクリプトSSHループが抱える3つの限界

シェルスクリプトでSSHループを書く手法は、現場に長くいるエンジニアなら誰もが一度は使ったことがあるでしょう。hosts.txtにIPアドレスを並べ、whileループで回しながら各サーバーにsshコマンドを叩く、というパターンです。

しかしこのアプローチには、台数が増えるにつれて深刻になる3つの限界があります。

1. 冪等性がない
シェルスクリプトは「手順を実行する」ことしかできません。「パッケージAをインストールする」という処理を書いた場合、対象サーバーにすでにAがインストール済みであっても、スクリプトはそれを確認せずに再度インストールしようとします。場合によってはエラーが出て処理が止まったり、設定ファイルが上書きされたりします。この問題を回避するには、「すでにインストール済みか確認してからインストールする」という条件分岐を自分で書かなければなりません。台数が増えるほどこの条件分岐が膨らみ、スクリプトは複雑怪奇なものになっていきます。

2. 失敗時のリカバリが難しい
50台にSSHループで処理を流しているとき、25台目でエラーが発生したとします。残りの26台目以降に処理が届いているかどうか、スクリプトを読んで確認しなければなりません。失敗したサーバーだけをリトライする仕組みを作るには、成功・失敗をファイルに記録するロジックを自前で書く必要があります。これはかなりの手間で、かつバグを生みやすい部分です。

3. 並列実行とタイムアウト管理が煩雑
SSHをシリアルに叩くと、100台では1台あたり3秒でも5分以上かかります。xargsやGNU parallelで並列化するには別の工夫が必要ですし、タイムアウト設定やSSHのコントロールマスター(接続再利用)の管理も自前になります。Ansibleはこれらを設定ファイルで一元管理できます。

AnsibleはなぜSSHループと根本的に異なるのか

Ansibleが「構成管理ツール」と呼ばれる理由は、「手順を実行するツール」ではなく「インフラの状態を定義して、その状態に収束させるツール」だからです。

SSHループのシェルスクリプトと比べたとき、Ansibleの動作モデルは次のように異なります。

観点 シェルスクリプトSSHループ Ansible
思想 手順の逐次実行 状態の宣言と収束
冪等性 自前で条件分岐を書く必要あり モジュールが冪等性を保証
接続方式 sshコマンドを毎回起動 SSHを再利用(コントロールマスター相当)
並列実行 xargs/parallel等で自前実装 forks設定で一元管理
失敗時の扱い スクリプト設計に依存 failed_when・ignore_errors・retryで制御
対象の選択 hosts.txtのリスト管理 inventoryでグループ・変数を統合管理
Ansibleが接続先のサーバーに送るのは「コマンド」ではなく「Pythonモジュール」です。このモジュールが対象サーバー上で現在の状態を確認し、望ましい状態と異なる場合のみ変更を加えます。すでに目的の状態であれば何もしない(changed=Falseとして報告される)。これが冪等性の実装です。

「冪等性」と「宣言的記述」が変えるもの

冪等性と宣言的記述は抽象的に聞こえますが、現場での実感は具体的です。

冪等性が変えること
たとえば「Nginxをインストールして設定ファイルを配置する」というPlaybookを書いたとします。このPlaybookを本番サーバーに対して月1回の定期メンテナンスで流す運用にしていた場合、シェルスクリプトでは「すでにインストール済みのNginxを再度インストールしようとして設定が上書きされた」というインシデントが起きる可能性があります。Ansibleのyumモジュール(またはdnfモジュール)はインストール済みを確認してからスキップするため、このリスクがありません。

本番にPlaybookを流すことへの心理的ハードルが下がり、「定期的に状態を揃え直す」という運用スタイルが定着します。これはシェルスクリプトSSHループでは実現しにくい運用文化です。

宣言的記述が変えること
「Nginxのバージョンは1.26.x、設定ファイルはこの内容、サービスは起動状態、firewallの80番は開放」という状態をPlaybook(YAMLファイル)として記述します。これは「手順書」ではなく「仕様書」です。誰が読んでもサーバーの望ましい姿が一目でわかります。

シェルスクリプトのSSHループは手順の塊であり、読み解くには「このコマンドを実行した結果どういう状態になるか」を頭の中で追いかけなければなりません。Ansibleのplaybookは状態の定義であり、コードがそのままドキュメントとして機能します。

Ansibleをゼロから体系的に学びたい方はAnsible入門講座をご覧ください。

inventory設計とrole分離で保守性を高める

AnsibleがSSHループと決定的に異なる2点目が、inventoryとroleという概念です。

inventoryとは
inventoryはAnsibleが操作する対象サーバーの一覧と、そのグループ定義・変数をまとめたファイルです。シェルスクリプトのhosts.txtに相当しますが、グループ化・変数定義・グループの入れ子が可能です。

# inventory/production の例 [webservers] web01.example.com web02.example.com [dbservers] db01.example.com [webservers:vars] # webserversグループ全体に適用する変数 nginx_version=1.26.3 listen_port=80

これにより「webserversグループだけに対してPlaybookを流す」「本番とステージングでinventoryを切り替える」という操作が設定ファイルのレベルで制御できます。シェルスクリプトでこれを実現しようとすると、if文や引数処理が増え、スクリプト本体が膨らんでいきます。

roleとは
roleはPlaybookの「機能単位」を独立したディレクトリ構造にパッケージ化したものです。たとえば「Nginxのセットアップ」というroleは以下のようなディレクトリ構成になります。

roles/ nginx/ tasks/ main.yml # タスク定義(インストール・設定・起動) handlers/ main.yml # 設定変更後にnginxをreloadするハンドラ templates/ nginx.conf.j2 # Jinja2テンプレートで変数を埋め込む設定ファイル defaults/ main.yml # デフォルト変数(上書き可)

roleを使うと「このサーバーにはnginx roleとphp roleを当てる」という組み合わせ指定がPlaybookの数行で表現できます。シェルスクリプトなら関数として切り出すことはできますが、変数スコープ・テンプレート処理・ハンドラ(変更があった時だけ実行する処理)という仕組みはシェルにはありません。

handlerは「設定ファイルを変更したときだけnginxをreloadする」という処理を、Playbook全体で1回だけ実行させる仕組みです。10個のtaskが同じハンドラをnotifyしても、実行されるのは1回だけです。シェルスクリプトでこれを同等に実装するのはかなり手間がかかります。

どのタイミングでAnsibleに移行すべきか

「いつAnsibleに移行すべきか」という問いへの答えは、シェルスクリプトSSHループのコストが見えてきたタイミング、具体的には以下の条件が重なった時です。

移行を検討すべき状況
・管理対象サーバーが10台を超えた
・設定変更作業が月1回以上発生する
・複数人でサーバー管理を担当している(属人化の排除が必要)
・本番に同じ設定変更を適用するのが怖い(冪等性がないことへの不安)
・SSHループのスクリプトが200行を超えて読みにくくなった

逆に、以下の状況ならシェルスクリプトSSHループのままでも十分です。

・管理対象が5台以下で増える予定もない
・設定変更は年に数回程度の単発作業
・1人で全サーバーを管理しており、ナレッジ共有の必要がない

移行の進め方としては、いきなり全サーバーに適用しようとするのではなく「まず1つのroleを作る」ことをお勧めします。既存のSSHループで行っていた処理(たとえば「Nginxのインストールと設定」)を1つのroleとして書き直し、ステージング環境で動作を確認します。成功したら本番に当てる。この繰り返しで、シェルスクリプトをAnsibleに置き換えていく方法が最もリスクが低くなります。

移行前に確認すべき技術的前提
・管理対象サーバーにPythonがインストールされていること(RHEL/CentOS/Ubuntu系はデフォルトでOK)
・Ansibleを実行するPC(コントロールノード)からSSHで各サーバーに接続できること
・SSHの公開鍵認証が設定されていること(パスワード認証でも動くが実用上は公開鍵が必須)

AnsibleはSSHさえ通っていれば追加のエージェントインストールは不要です。この「エージェントレス」な設計が、既存のSSH環境からの移行コストを下げている理由の一つです。

まとめ

シェルスクリプトSSHループとAnsibleの違いを整理します。

項目 シェルスクリプトSSHループ Ansible
実行モデル 手順の逐次実行 状態への収束(宣言的)
冪等性 なし(自前実装が必要) モジュールが担保
適正規模 5台以下、単発作業 10台超、定期的な設定変更
保守性 台数増加で急激に悪化 role分離で高い再利用性
ドキュメント性 手順書と乖離しやすい Playbookが仕様書を兼ねる
移行コスト エージェントレスで低い
シェルスクリプトSSHループは「今すぐ動けばいい」という状況では有効な手段です。しかし規模が拡大し、複数人での管理・定期的な設定変更・本番環境への安全な適用が求められる段階になったとき、Ansibleへの移行は開発・運用のコスト削減に直接つながります。

「まず1つのroleを作ってみる」という小さな一歩から、構成管理の世界に踏み出してみてください。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、20年以上の運用経験を持つ現役エンジニアが基礎から教えます。
Ansible実践ハンズオンの詳細を見る >>

無料メルマガで学習を続ける

Linuxの実践スキルをメールで毎週お届け。
登録は1分、解除もいつでも可。

登録無料・いつでも解除できます

暗記不要・1時間後にはサーバーが動く

3,100名以上が実践した「型」を無料で公開中

プロのエンジニアはコマンドを暗記していません。
「現場で使える型」を効率よく使いこなしているだけです。
その「型」を図解60Pにまとめた入門マニュアルを、完全無料でプレゼントしています。

登録10秒/合わなければ解除3秒 / 詳細はこちら

Linux無料マニュアル(図解60P) 名前とメールで30秒登録
宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として20年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

趣味は、キャンプにカメラ、トラウト釣り。好きな食べ物は、ラーメンにお酒。休肝日が作れない、酒量を減らせないのが悩み。最近、ドラマ「フライトエンジェル」を観て涙腺が崩壊しました。