AnsibleのLookupプラグイン設計入門|ファイル・環境変数・外部データを変数として動的取得する実践パターン

宮崎智広 この記事の監修:宮崎智広(Linux実務・教育歴20年以上・受講者3,100名超)
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Ansible > AnsibleのLookupプラグイン設計入門|ファイル・環境変数・外部データを変数として動的取得する実践パターン
「AnsibleのPlaybookを書いていると、SSH公開鍵の内容やAPIキーをどう渡すか迷うことがある。vars_filesに直書きすればgitにコミットするたびに秘密情報が漏れるし、環境ごとに別Playbookを用意するのも管理が煩雑だ…」

こうした「Playbookの外にある情報をその場で取ってきたい」という要求に答えるのが、Lookupプラグインです。ファイルの内容・環境変数・CSVから値を検索・コマンドの出力・パスワード生成まで、多彩な外部データをPlaybook変数として動的に取り込めます。

この記事では、AnsibleのLookupプラグインの仕組みと代表的なプラグイン(file・env・csvfile・pipe・password)の使い方を、実際のPlaybookコードと出力例を交えて解説します。設計パターンまで解説するので、現場で即使えるPlaybookの「柔軟性」が身につきます。

動作確認環境:Ansible 2.16 / Rocky Linux 9.4(コントロールノード・管理対象ノード共通)

この記事のポイント

・Lookupプラグインはコントロールノードで評価され、外部データを変数に変換する仕組み
・file・env・csvfile・pipe・passwordの5種で現場の大半のユースケースを網羅できる
・query()を使うとLookupをリスト形式で返せてloopと組み合わせやすくなる
・pipeプラグインは外部入力をそのまま渡すとシェルインジェクションのリスクがある


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

LookupプラグインはPlaybookに「外側」の情報を引き込む仕組みです

Ansibleのvarsで変数を定義するとき、通常は「値を直接書く」か「vars_filesで別ファイルに記載する」のが基本です。しかし実際の現場では、こんな場面に遭遇します。

・SSH公開鍵の内容をそのままauthorized_keysに登録したい
・実行環境(dev/prod)はCI/CDの環境変数で切り替えたい
・サーバーごとの設定値がCSVで管理されており、そこから読み込みたい
・初回実行時にパスワードを自動生成してファイルに保存したい

これらをvarsに手書きしようとすると「Playbookをコミットするたびに秘密情報が漏れる」「環境ごとに別のPlaybookを用意しなければならない」という問題が生じます。

Lookupプラグインはこうした問題を解決する仕組みです。Lookupはコントロールノード(Ansibleを実行するPC・サーバー)上で評価されるため、「ファイルを読む」「環境変数を取る」「コマンドを実行する」といった操作が変数展開のタイミングで自動的に行われます。

基本的な書き方は次の形です。

・変数定義でlookup関数を使う: myvar: "{{ lookup('プラグイン名', '引数') }}"
・モジュール引数の中で直接使う: content: "{{ lookup('file', '/path/to/key.pub') }}"

Lookupは通常、リストを返す場合も「最初の1要素」として扱われます。リスト全体が必要な場合は後述するquery()を使います。

よく使うLookupプラグインと基本的な書き方

Ansibleには60以上のLookupプラグインが組み込まれています。現場でよく使う5種類を実際のコードと出力例で解説します。

1. fileプラグイン — ローカルファイルの内容を読む

コントロールノード上のファイル内容を文字列として取得します。SSH公開鍵の登録や設定ファイルの内容をそのまま渡す用途に最も多く使われます。

# playbook例 - name: authorized_keysにSSH公開鍵を登録する hosts: webservers vars: pub_key: "{{ lookup('file', '/home/ansible/.ssh/id_rsa.pub') }}" tasks: - name: deploy user の authorized_keys に公開鍵を追加 ansible.posix.authorized_key: user: deploy state: present key: "{{ pub_key }}"

複数ファイルを読み込む場合はカンマ区切りで指定します。

# 複数ファイルを一度に取得(改行区切りの文字列として連結される) vars: multi_keys: "{{ lookup('file', '/home/ansible/.ssh/id_rsa.pub', '/home/jenkins/.ssh/id_rsa.pub') }}"

注意点:fileプラグインはコントロールノードのファイルを読みます。管理対象ノードのファイルを取得したい場合は、slurpモジュールやfetchモジュールを使ってください。

2. envプラグイン — 環境変数を変数として取得する

コントロールノードの環境変数をPlaybook変数として取り込みます。CI/CDパイプラインからAPIキーや環境識別子を受け取るときに重宝します。

# 環境変数を変数として利用する例 - name: 環境変数からデプロイ環境を取得する hosts: all vars: deploy_env: "{{ lookup('env', 'DEPLOY_ENV') | default('staging', true) }}" aws_region: "{{ lookup('env', 'AWS_DEFAULT_REGION') }}" tasks: - name: 環境名を表示 debug: msg: "デプロイ先: {{ deploy_env }}"

実行時に環境変数をセットする場合の実行例と出力です。

$ DEPLOY_ENV=production ansible-playbook deploy.yml TASK [環境名を表示] ***** ok: [web01] => { "msg": "デプロイ先: production" } ok: [web02] => { "msg": "デプロイ先: production" }

環境変数が未設定のときlookup('env', 'VAR')は空文字を返します。default()フィルタと組み合わせてデフォルト値を設定するのが実用的なパターンです。

3. csvfileプラグイン — CSVから値を検索する

CSVファイルから特定の行・列の値を取得します。サーバーごとのポート番号やユーザーIDなど、スプレッドシートで管理されている設定値をPlaybookに取り込む用途に使えます。

例として以下のCSVファイル(/etc/ansible/server_config.csv)を用意します。

# /etc/ansible/server_config.csv の内容 hostname,app_port,db_user,max_conn web01,8080,webapp,100 web02,8081,webapp,100 db01,5432,dbadmin,200

# csvfileプラグインでホスト名をキーに値を検索する - name: CSVからアプリポートを取得して確認する hosts: webservers vars: app_port: "{{ lookup('csvfile', inventory_hostname + ' file=/etc/ansible/server_config.csv col=1 delimiter=,') }}" tasks: - name: アプリケーションポートを確認 debug: msg: "{{ inventory_hostname }} のポート: {{ app_port }}" # 実行結果 TASK [アプリケーションポートを確認] ***** ok: [web01] => {"msg": "web01 のポート: 8080"} ok: [web02] => {"msg": "web02 のポート: 8081"}

col=は0始まりのカラムインデックスです。col=1はapp_port(2列目)を取得します。

4. pipeプラグイン — コマンド実行結果を変数にする

コントロールノードでシェルコマンドを実行し、その標準出力を文字列変数として取得します。gitのコミットハッシュをデプロイ情報に含めたい場合などに使います。

# gitのコミットハッシュとデプロイ日時を変数として取得する - name: デプロイ情報を記録する hosts: appservers vars: git_commit: "{{ lookup('pipe', 'git -C /home/ansible/myapp rev-parse --short HEAD') }}" deploy_time: "{{ lookup('pipe', 'date +%Y%m%d-%H%M%S') }}" tasks: - name: /var/www/myapp/deploy_info.txt を生成 copy: content: "commit={{ git_commit }}\ndeployed_at={{ deploy_time }}\n" dest: /var/www/myapp/deploy_info.txt # 管理対象ノード(app01)上のdeploy_info.txtの内容 commit=a3f92d1 deployed_at=20260922-113500

注意点:pipeプラグインはコントロールノードでシェルを実行します。引数に外部入力をそのまま渡すとシェルインジェクションのリスクがあるため、コマンド引数は固定値か信頼できる内部変数に限定してください。

5. passwordプラグイン — ランダムパスワードを生成・保存する

ランダムな文字列を生成し、指定ファイルに保存します。初回実行時に生成したパスワードを以降の実行でも再利用できるのが特徴です。

# DBユーザーのパスワードを自動生成して保存する - name: MariaDBの初期パスワードを設定する hosts: dbservers vars: db_root_password: "{{ lookup('password', '/etc/ansible/credentials/db_root length=20 chars=ascii_letters,digits') }}" tasks: - name: MariaDB root パスワードを設定 community.mysql.mysql_user: name: root password: "{{ db_root_password }}" login_unix_socket: /var/lib/mysql/mysql.sock update_password: on_create

/etc/ansible/credentials/db_rootというファイルが存在しない場合は新規生成して保存し、次回からはそのファイルの内容を読み返します。本番の認証情報は.gitignoreに追加してリポジトリにコミットしないこと、さらにAnsible Vaultと組み合わせてファイル自体を暗号化することを推奨します。

lookupとquery・with_loopの使い分け

LookupをPlaybook内で使う方法は3種類あり、戻り値の型と使い所が異なります。

lookup() — 文字列として1要素を返す
{{ lookup('file', 'a.txt', 'b.txt') }}のように複数引数を渡した場合、デフォルトでは改行区切りの文字列として返ります(リストではない)。モジュールのcontent:key:に単純な文字列を渡す場面で使います。

query() — リストを返す
{{ query('file', 'a.txt', 'b.txt') }}は必ずリストを返します。loop:で繰り返し処理したい場合はquery()を使うとコードの意図が明確です。

# query()でリストとして取得してloopで処理する例 - name: 複数の設定ファイルの内容を一覧表示 debug: msg: "{{ item }}" loop: "{{ query('file', '/etc/ansible/conf/app.conf', '/etc/ansible/conf/db.conf') }}"

with_<lookup> — 旧形式(後方互換)
with_file:with_items:のようなwith_プレフィックスはLookupプラグインを内部で呼び出す旧記法です。Ansible 2.5以降はloop: "{{ query(...) }}"形式が推奨されており、新規記述ではloopを使うのが現在の主流です。

実践的な設計パターン3選

1. SSH公開鍵をファイルから読んでauthorized_keysに登録する

サーバー台数が増えてくると、デプロイユーザーやオペレーターのSSH公開鍵を全ホストに配布する作業が発生します。Lookupのfileプラグインとauthorized_keyモジュールを組み合わせると、鍵ファイルをPlaybookにハードコードせずに配布できます。

# roles/ssh_keys/tasks/main.yml - name: チームメンバーの公開鍵を配布する ansible.posix.authorized_key: user: deploy state: present key: "{{ lookup('file', item) }}" loop: - /home/ansible/keys/alice_id_rsa.pub - /home/ansible/keys/bob_id_rsa.pub - /home/ansible/keys/charlie_id_rsa.pub # 実行結果(10台のwebserversグループに一括適用) TASK [チームメンバーの公開鍵を配布する] ***** changed: [web01] => (item=/home/ansible/keys/alice_id_rsa.pub) ok: [web01] => (item=/home/ansible/keys/bob_id_rsa.pub) changed: [web01] => (item=/home/ansible/keys/charlie_id_rsa.pub) ...(10台分繰り返し) PLAY RECAP **** web01 : ok=3 changed=2 ... web02 : ok=3 changed=2 ...

鍵ファイルを/home/ansible/keys/ディレクトリにまとめておけば、新メンバーの追加・退職者の削除も鍵ファイルの追加・削除とPlaybookの1行変更だけで完結します。

2. 環境変数で本番・ステージングを切り替えるenv lookup設計

GitHub ActionsやJenkinsなどのCI/CDツールからPlaybookを呼び出す場合、デプロイ先環境の識別子(dev/staging/production)をCI側の環境変数として設定し、Playbook側はそれをlookupで受け取る設計が実践的です。

# group_vars/all.yml env_name: "{{ lookup('env', 'TARGET_ENV') | default('staging', true) }}" # roles/app_config/templates/app.conf.j2 [server] environment = {{ env_name }} log_level = {% if env_name == 'production' %}warn{% else %}debug{% endif %} max_connections = {% if env_name == 'production' %}200{% else %}50{% endif %} # CI/CDからの実行(GitHub Actions の step 例) # - run: TARGET_ENV=production ansible-playbook -i inventories/production/ deploy.yml # ローカル確認時(staging) # $ TARGET_ENV=staging ansible-playbook -i inventories/staging/ deploy.yml

この設計のポイントは「環境の切り替え情報をPlaybookに持たせない」ことです。Playbook自体はgitリポジトリで管理し、環境依存の値はCI/CDパイプラインの変数機能で注入するとセキュリティと変更履歴の分離が実現できます。

3. CSVからサービス設定値を取得して複数ホストに展開する

ホストごとのアプリポートやDB接続情報がExcelで管理されている現場では、CSVエクスポートしたファイルをlookup('csvfile')で直接読み込む設計が有効です。Inventoryのhost_varsにすべて書き起こす手間が省けます。

# /etc/ansible/server_config.csv hostname,app_port,max_workers,db_host app01,8080,4,db-primary.internal app02,8081,4,db-primary.internal app03,8082,2,db-replica.internal # playbook(server_config.csvの値を使ってアプリ設定を構成する) - name: アプリケーションの設定ファイルを生成する hosts: appservers vars: app_port: "{{ lookup('csvfile', inventory_hostname + ' file=/etc/ansible/server_config.csv col=1 delimiter=,') }}" max_workers: "{{ lookup('csvfile', inventory_hostname + ' file=/etc/ansible/server_config.csv col=2 delimiter=,') }}" db_host: "{{ lookup('csvfile', inventory_hostname + ' file=/etc/ansible/server_config.csv col=3 delimiter=,') }}" tasks: - name: /etc/app/app.conf を生成 template: src: app.conf.j2 dest: /etc/app/app.conf notify: restart app # app01上の /etc/app/app.conf 生成後の内容確認 [root@app01 ~]# cat /etc/app/app.conf [app] port = 8080 workers = 4 database_host = db-primary.internal

AnsibleのPlaybook設計を現場で体系的に学びたい方へ

LookupプラグインはAnsibleの変数設計を理解していることで真価を発揮します。vars優先順位・インベントリ変数・Vault連携まで含めた設計を体系的に身につけたい方は、現役エンジニアによる実践ハンズオンを活用してください。
>> Ansible実践セミナーの詳細はこちら

トラブルシュート — よくあるエラーと対処法

「lookup('file')でファイルが見つからない」

# エラーメッセージの例 TASK [authorized_keyに公開鍵を追加] fatal: [web01]: FAILED! => { "msg": "An unhandled exception occurred while running the lookup plugin 'file'. Error was a , original message: could not locate file in lookup: /home/ansible/keys/alice_id_rsa.pub" }

原因と対処:
・fileプラグインはコントロールノードのファイルを読みます。管理対象ノードのパスを指定していないか確認してください
・相対パスで指定した場合、Playbookのディレクトリからの相対パスとして解釈されます
・絶対パスか{{ playbook_dir }}/keys/alice_id_rsa.pubのようなPlaybook変数を使うと確実です

「lookup('env')が常に空文字を返す」

Lookupはコントロールノード上の環境変数を参照します。sudosu -経由で実行した場合、元ユーザーの環境変数が引き継がれないケースがあります。ansible-playbookを実行するシェルでecho $TARGET_ENVを確認し、正しく設定されているかチェックしてください。

「lookup('password')で毎回別のパスワードが生成される」

保存先のファイルパスに誤字がある場合、既存ファイルが読み込まれず毎回新規生成が起きます。ファイルパスの末尾にスペースや改行が混入していないか確認してください。また、複数のコントロールノードからPlaybookを実行する環境では、パスワードファイルをNFSや共有ストレージ上に置いて全ノードが同一ファイルを参照できるようにする必要があります。

「with_fileとwith_itemsを混在させて意図しない動作になる」

with_file:はリストの各要素をファイルパスとして解釈してファイル内容を返します。単純なリスト反復にはwith_items:(またはloop:)を使い、ファイル内容が欲しい場合のみwith_file:(またはloop: "{{ query('file', ...) }}")を使うよう使い分けると混乱を防げます。

本記事のまとめ

プラグイン 用途 典型的な使い方
file ローカルファイル内容を取得 lookup('file', '/path/to/key.pub')
env 環境変数を取得 lookup('env', 'TARGET_ENV') | default('staging')
csvfile CSVから値を検索 lookup('csvfile', 'host file=c.csv col=1 delimiter=,')
pipe コマンド出力を取得 lookup('pipe', 'git rev-parse --short HEAD')
password ランダム文字列の生成・保存 lookup('password', '/path/to/cred length=20')
query() リスト形式でlookupを呼ぶ loop: "{{ query('file', 'a.pub', 'b.pub') }}"
Lookupプラグインは「Playbookをコードとして管理しながら、実行時の外部情報を柔軟に取り込む」ための仕組みです。fileとenvを使いこなすだけでも、SSH鍵配布・CI/CD連携・環境切り替えといった現場の典型的な要件をすっきり解決できます。まずは1つのPlaybookにlookup('file', ...)を取り入れるところから始めてみてください。
現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、AnsibleのLookupプラグインをはじめとする変数設計・Playbook設計をゼロから体系的に教えます。20年以上の運用経験を持つ現役エンジニアによるハンズオン形式のセミナーです。
Ansible実践ハンズオンの詳細を見る >>

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

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

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

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

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

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

姓・名・メールの3つだけ/30秒/解除は3秒 / 詳細はこちら

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

この記事を書いた人

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

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

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