Red Hat Certified Engineer (RHCE) #4 ad-hoc コマンド: モジュールを即席で実行する
#3 で ansible.cfg と SSH、become によって control node が managed node にどう接続するのかを押さえました。接続ができたら、次は実際にコマンドを送ってみる番です。プレイブックを書く前に、1 行でモジュールを即席で実行する ad-hoc コマンド から身につけます。ad-hoc は素早い点検と一回限りの作業に使うツールであり、同時に各モジュールが何をするのかを手に覚える最も速い道です。
ad-hoc コマンドとは #
ad-hoc コマンドは、プレイブックファイルを作らずに ansible コマンド 1 行でモジュールを 1 つ呼び出す実行方式です。「今すぐすべての web サーバーが生きているか確認」「特定のグループにパッケージを 1 つインストール」「ファイルを 1 つ配布」といった単発の作業に向いています。同じ作業を毎回繰り返したり複数の task をまとめたりする必要があるならプレイブックが適切ですが、一度見て終わる点検には ad-hoc のほうがずっと速いです。
ad-hoc コマンドの基本構造は次のとおりです。
ansible <pattern> -m <module> -a "<arguments>"各要素の意味は次のとおりです。
| 要素 | 意味 |
|---|---|
<pattern> | 対象ホストパターン。inventory のホスト名、グループ名、またはワイルドカード |
-m <module> | 実行するモジュール名。省略すると既定のモジュール (command) が使われる |
-a "<args>" | モジュールに渡す引数。key=value 形式が一般的 |
-b | become で権限を昇格 (既定は root) |
-i <inventory> | inventory ファイルを指定 |
最も単純な例として、web グループのすべてのホストに ping モジュールを送るコマンドは次のとおりです。
ansible web -m pingここでの ping は ICMP ではなく、Ansible が managed node に接続して Python を実行できるかを確認するモジュールです。応答として pong が返ってくれば、SSH 接続と Python 環境がともに正常だという意味です。
ホストパターン #
ad-hoc であれプレイブックであれ、最初の引数は常に 対象ホストパターン です。試験では「このグループにだけ適用せよ」のような要求がよく出るので、パターンの文法を正確に覚えておきます。
| パターン | 対象 |
|---|---|
all または * | inventory のすべてのホスト |
web | web グループに属するホスト |
web:db | web または db グループ (和集合) |
web:&db | web でありながら db にも属するホスト (積集合) |
web:!staging | web に属するが staging は除外 (差集合) |
192.168.* | パターンに合致するホスト名/IP |
web[0:2] | グループ内でインデックス範囲で選択 |
たとえば web グループから staging を除いたホストにだけコマンドを送るには次のように書きます。シェルが ! を解釈しないようにシングルクォートで囲みます。
ansible 'web:!staging' -m ping対象が実際にどのホストに解決されるのかを事前に確認するには --list-hosts を付けます。
ansible 'web:!staging' --list-hostsよく使うモジュール #
ad-hoc で最もよく使うモジュールを整理します。同じモジュールをプレイブックでもそのまま使うので、ここでオプションを身につけておくと #5 以降が楽になります。
ping #
接続と Python 実行を点検します。引数はありません。
ansible all -m pingcommand と shell の違い #
どちらも managed node でコマンドを実行しますが、動作が異なります。
command。既定のモジュールです。シェルを経由せずコマンドを直接実行します。そのためパイプ (|)、リダイレクト (>)、変数展開 ($HOME) といったシェル機能は使えません。セキュリティ上より安全なので、シェル機能が不要ならこちらが推奨されます。shell。/bin/shを経由して実行するので、パイプとリダイレクト、環境変数展開がすべて動作します。
# command: シェル機能なしで直接実行
ansible web -m command -a "uptime"
# command が既定のモジュールなので -m は省略可能
ansible web -a "id"
# shell: パイプとリダイレクトが必要なとき
ansible web -m shell -a "ps aux | grep nginx"command でパイプを使うと | がコマンドの引数として渡されて失敗するので、そのときだけ shell を使います。
copy #
control node のファイルを managed node にコピーするか、内容を直接書き込みます。
# ファイルをコピー
ansible web -m copy -a "src=/etc/motd dest=/etc/motd owner=root mode=0644" -b
# content で内容を直接作成
ansible web -m copy -a 'content="Managed by Ansible\n" dest=/etc/motd' -bfile #
ファイルとディレクトリの状態 (存在、権限、所有者、リンク) を管理します。
# ディレクトリを作成
ansible web -m file -a "path=/opt/app state=directory owner=app mode=0755" -b
# ファイルを削除
ansible web -m file -a "path=/tmp/old.log state=absent" -b
# シンボリックリンクを作成
ansible web -m file -a "src=/opt/app/current dest=/opt/app/live state=link" -bstate の主な値は directory (ディレクトリ)、touch (空ファイル)、absent (削除)、link (シンボリックリンク) です。
package と dnf #
パッケージをインストールまたは削除します。dnf は RHEL 系専用で、package はディストリビューションに合ったパッケージマネージャーを自動で選ぶ汎用モジュールです。
# dnf でインストール
ansible web -m dnf -a "name=httpd state=present" -b
# package でインストール (汎用)
ansible web -m package -a "name=httpd state=present" -b
# 最新に更新
ansible web -m dnf -a "name=httpd state=latest" -b
# 削除
ansible web -m dnf -a "name=httpd state=absent" -bservice と systemd #
サービスを起動・停止したり、起動時の自動起動を設定したりします。
# 起動して起動時の自動起動を有効化
ansible web -m service -a "name=httpd state=started enabled=yes" -b
# systemd モジュールで再起動
ansible web -m systemd -a "name=httpd state=restarted" -bstate は started、stopped、restarted、reloaded を受け取り、enabled で起動時の自動起動の有無を決めます。
user #
ユーザーアカウントを作成または削除します。
# ユーザーを作成
ansible web -m user -a "name=deploy groups=wheel state=present" -b
# ユーザーを削除 (ホームディレクトリを含む)
ansible web -m user -a "name=deploy state=absent remove=yes" -blineinfile #
ファイル内の特定の行を保証したり置換したりします。設定ファイルの 1 行だけを変えなければならないときに便利です。
ansible web -m lineinfile -a 'path=/etc/ssh/sshd_config regexp="^#?PermitRootLogin" line="PermitRootLogin no"' -bregexp に合致する行があれば line で置換し、なければファイルの末尾に追加します。
become で権限を昇格する #
パッケージのインストールやシステムファイルの修正のように root 権限が必要な作業は、-b (または --become) を付けて権限を昇格させます。特定のユーザーに昇格するには --become-user を一緒に使います。
# root に昇格してパッケージをインストール
ansible web -m dnf -a "name=vim state=present" -b
# 特定のユーザーに昇格
ansible web -m command -a "whoami" -b --become-user=app#3 で ansible.cfg に become=true を指定しておいたなら -b なしでも昇格されますが、ad-hoc では明示的に -b を付けるほうが意図が明確です。
ansible-doc でモジュールのオプションを探す #
試験会場にはインターネットがないので、モジュールのオプションは ansible-doc で探します。モジュール名と主なオプション、そしてドキュメント下部の EXAMPLES を素早く読む習慣が時間を節約します。
# モジュール全体のドキュメント
ansible-doc copy
# 一行要約のみ
ansible-doc -s copy
# インストール済みモジュールの一覧
ansible-doc -lansible-doc -s <module> はオプションを key=value の骨格で見せてくれるので、引数をどう書くかを素早く確認するのに向いています。モジュール名を思い出せないときは ansible-doc -l | grep <キーワード> で候補を絞ります。
試験のポイント #
- command vs shell。パイプ・リダイレクト・変数展開が必要なら
shell、そうでなければcommand(既定のモジュール) を使います。シェル機能が不要なのにshellを使うと、不要にリスクを高めます。 - 冪等性のないモジュールに注意。
commandとshellは冪等性がなく、実行するたびに changed として表示されます。同じ結果を保証する必要があるなら、copy、file、dnf、serviceのような状態ベースのモジュールを使うのが RHCE の採点基準に合います。 - become は明示的に。権限が必要な作業は
-bを抜かすと権限エラーで失敗するので、習慣のように付けます。 - ansible-doc が唯一の参考書。オプション名が紛らわしいときは推測せず
ansible-doc -sで確認します。 - ad-hoc より playbook 中心。試験はほとんどプレイブックで答えを求めますが、ad-hoc は接続確認とモジュール動作の点検に有用なので、両方の方式を手に覚えておきます。
ad-hoc と playbook の境界 #
ad-hoc は速くて軽いですが、2 つ以上の task を順番にまとめたり、変数・ハンドラー・条件を使ったりするには限界があります。複数の task を順番に実行したり、変数と Jinja2 テンプレートでホストごとに異なる構成にしたり、変更が生じたときだけサービスを再起動するハンドラーが必要だったり、同じ作業を繰り返してバージョン管理しなければならないなら、プレイブックに移るのが適切です。つまり ad-hoc は「今、一度確認・実行」であり、繰り返して再現しなければならない構成はプレイブックの役目です。
まとめ #
この記事で押さえたこと:
- ad-hoc の構造。
ansible <pattern> -m <module> -a "args"でモジュールを 1 つ即席で実行します。 - ホストパターン。
all、グループ名、:(和集合)、:&(積集合)、:!(差集合)、*(ワイルドカード) で対象を選びます。 - よく使うモジュール。ping、command/shell、copy、file、package/dnf、service/systemd、user、lineinfile を例で身につけました。
- become。権限が必要な作業には
-bを付けます。 - command vs shell。シェル機能が必要なときだけ shell を使い、command と shell は冪等性がないことを覚えておきます。
- ansible-doc。インターネットのない環境では
ansible-doc -s <module>が唯一の参考書です。
次へ — Playbook 基礎 #
ad-hoc でモジュールを 1 つ即席で実行する方法を押さえました。次は同じモジュールたちをファイルにまとめて、繰り返し可能にする段階です。
#5 Playbook 基礎: task、handler、冪等性 では、プレイブックの基本構造 (play、task、module)、変更が生じたときだけ回る handler、そして RHCE 採点の核心である冪等性を直接書いて 2 回回して検証する流れまで整理します。