Lookup Plugins คือกลไกที่ใช้ดึงข้อมูลจากแหล่งภายนอก Playbook ณ เวลาที่รัน ไม่ว่าจะเป็นไฟล์ในระบบ, environment variables, password ที่สร้างแบบ dynamic หรือผลลัพธ์จาก command แล้วนำมาใช้เป็น variable โดยตรง
บทความนี้อธิบาย lookup plugins ที่ใช้บ่อยที่สุดในทางปฏิบัติ ตั้งแต่ file, env, password, template, ไปจนถึง dict และ items พร้อมวิธีใช้งานที่ถูกต้อง
ไวยากรณ์พื้นฐานของ Lookup
Lookup เรียกใช้ผ่าน lookup('plugin_name', 'argument') หรือ query('plugin_name', 'argument') ความต่างคือ lookup() return string ส่วน query() return list เสมอ
---
- name: Basic lookup syntax
hosts: localhost
tasks:
- name: Read file content
debug:
msg: "{{ lookup('file', '/etc/hostname') }}"
- name: Get environment variable
debug:
msg: "{{ lookup('env', 'HOME') }}"
- name: Use query() for list result
debug:
msg: "{{ query('fileglob', '/etc/*.conf') }}"
file Lookup: อ่านเนื้อหาจากไฟล์
file lookup อ่านเนื้อหาไฟล์บน control node (เครื่องที่รัน playbook) และนำมาใช้เป็น variable
---
- name: File lookup examples
hosts: all
tasks:
- name: Read SSH public key
authorized_key:
user: deploy
key: "{{ lookup('file', '~/.ssh/id_ed25519.pub') }}"
state: present
- name: Read multi-line config file
debug:
msg: "{{ lookup('file', 'files/app.conf') }}"
- name: Read multiple files
debug:
msg: "{{ lookup('file', 'file1.txt', 'file2.txt') }}"
# return ค่าจากทั้งสองไฟล์รวมกัน
env Lookup: ดึง Environment Variable
env lookup ดึงค่า environment variable จาก control node มีประโยชน์มากใน CI/CD pipelines ที่ inject secrets ผ่าน environment
---
- name: Environment variable lookup
hosts: all
vars:
db_password: "{{ lookup('env', 'DB_PASSWORD') }}"
api_key: "{{ lookup('env', 'API_KEY') | default('', true) }}"
tasks:
- name: Configure app with env vars
template:
src: templates/app.conf.j2
dest: /etc/myapp/app.conf
vars:
password: "{{ db_password }}"
- name: Fail if required env var missing
fail:
msg: "DB_PASSWORD environment variable is not set"
when: db_password == ""
ข้อควรระวัง: env lookup อ่านค่าจาก control node เท่านั้น ไม่ใช่จาก remote host ถ้าต้องการ environment variable จาก remote host ต้องใช้ shell module แทน
password Lookup: สร้าง Password แบบ Random
password lookup สร้าง random password และบันทึกลงไฟล์อัตโนมัติ ครั้งต่อไปที่รันจะอ่านค่าเดิมจากไฟล์ ทำให้ password ไม่เปลี่ยนทุกครั้ง
---
- name: Password lookup examples
hosts: dbservers
tasks:
- name: Generate and store MySQL root password
mysql_user:
name: root
password: "{{ lookup('password', '/etc/ansible/passwords/mysql_root length=20 chars=ascii_letters,digits') }}"
host: localhost
no_log: true
- name: Create app database user
mysql_user:
name: myapp
password: "{{ lookup('password', '/etc/ansible/passwords/myapp_db') }}"
priv: "myapp.*:ALL"
no_log: true
ไฟล์ที่ระบุจะถูกสร้างบน control node ใน path ที่กำหนด ถ้าไฟล์มีอยู่แล้วจะอ่านค่าเดิม ถ้ายังไม่มีจะสร้าง password ใหม่และบันทึกไว้
template Lookup: Render Template เป็น String
template lookup render Jinja2 template และ return ผลลัพธ์เป็น string แทนที่จะเขียนลงไฟล์โดยตรง ใช้เมื่อต้องการ inline config string
---
- name: Template lookup example
hosts: all
vars:
app_name: myservice
app_port: 8080
tasks:
- name: Set config from template string
set_fact:
nginx_config: "{{ lookup('template', 'templates/nginx_block.j2') }}"
- name: Use rendered template in another task
debug:
msg: "{{ nginx_config }}"
csvfile Lookup: อ่านข้อมูลจาก CSV
csvfile lookup ค้นหาแถวในไฟล์ CSV และดึงค่าจาก column ที่ระบุ เหมาะสำหรับ mapping ข้อมูลเช่น server → IP หรือ user → role
# ไฟล์ servers.csv:
# hostname,ip,role
# web01,192.168.1.10,webserver
# db01,192.168.1.20,database
---
- name: CSV lookup example
hosts: all
tasks:
- name: Get server IP from CSV
debug:
msg: "IP for web01: {{ lookup('csvfile', 'web01 file=servers.csv delimiter=, col=1') }}"
- name: Get role from CSV
set_fact:
server_role: "{{ lookup('csvfile', inventory_hostname + ' file=servers.csv delimiter=, col=2') }}"
pipe Lookup: ดึงผลลัพธ์จาก Command
pipe lookup รัน shell command บน control node และ return stdout เป็น string ใช้ดึงข้อมูล dynamic ที่ไม่มี lookup plugin รองรับโดยตรง
---
- name: Pipe lookup examples
hosts: all
vars:
git_commit: "{{ lookup('pipe', 'git rev-parse HEAD') }}"
current_user: "{{ lookup('pipe', 'whoami') }}"
date_stamp: "{{ lookup('pipe', 'date +%Y%m%d') }}"
tasks:
- name: Tag deployment with git commit
debug:
msg: "Deploying commit: {{ git_commit[:8] }}"
- name: Create versioned backup
file:
path: "/backup/{{ date_stamp }}"
state: directory
ข้อควรระวัง: pipe lookup รัน command บน control node เท่านั้น และรันตอน Playbook กำลัง parse variables ไม่ใช่ตอน task execute จึงไม่ควรใช้กับ command ที่มี side effects
Lookup กับ loop: ใช้ with_* Syntax
Lookup plugins หลายตัวถูกออกแบบมาใช้คู่กับ loop หรือ with_* syntax เพื่อวน iterate ข้อมูล
---
- name: Lookup with loop
hosts: all
tasks:
# วนอ่านหลายไฟล์
- name: Deploy multiple config files
copy:
content: "{{ lookup('file', item) }}"
dest: "/etc/myapp/{{ item | basename }}"
loop:
- files/app.conf
- files/db.conf
- files/cache.conf
# ใช้ with_fileglob แทน loop + fileglob
- name: Deploy all .conf files
copy:
src: "{{ item }}"
dest: /etc/myapp/
with_fileglob:
- "files/*.conf"
สรุป
Lookup plugins เป็นสะพานเชื่อมระหว่าง Playbook กับแหล่งข้อมูลภายนอก ทำให้ไม่ต้อง hardcode ค่าสำคัญลงใน variable files โดยตรง Pattern ที่ควรจำ: ใช้ file สำหรับอ่านไฟล์ key หรือ cert, ใช้ env ใน CI/CD pipeline, ใช้ password สำหรับ random credentials ที่ต้องการ consistency, และใช้ pipe สำหรับ dynamic values จาก command
Lookup ทั้งหมดรันบน control node เสมอ ถ้าต้องการข้อมูลจาก remote host ต้องใช้ register + fact แทน

