---
id: config-ansible
title: "Ansible: inventory và ad-hoc"
shortTitle: "Ansible"
track: config
trackTitle: "Configuration Management"
order: 1
level: core
status: published
estimatedMinutes: 40
prerequisites:
  - iac-terraform
next: config-playbook
reviewedAgainst: 2026-10-12
sources:
  - title: "Ansible — inventory introduction"
    url: https://docs.ansible.com/ansible/latest/inventory_guide/intro_inventory.html
  - title: "Ansible — ad hoc commands"
    url: https://docs.ansible.com/ansible/latest/command_guide/intro_adhoc.html
---

# Ansible: inventory và ad-hoc

Terraform tạo resource. Ansible chỉnh những gì bên trong máy: package, file, user. Lab chỉ chạy vào `localhost`, không cần server thật. Cài Ansible theo [hướng dẫn cài](https://docs.ansible.com/ansible/latest/installation_guide/index.html) của OS bạn. `ansible --version` phải chạy được.

Puppet, Chef, Salt làm cùng lớp việc này, mỗi thứ một bài phía sau. Gặp manifest Puppet hoặc cookbook Chef thì biết đó là config management, không phải Terraform.

## Để làm gì

Bạn viết một inventory, chạy một module vào đúng nhóm máy, và đọc output `ok` / `changed` / `failed`. Chưa cần playbook.

## Gồm những gì

- Inventory INI: host, group, biến.
- `ansible -m ping`, `ansible -m command`.
- `connection: local` cho lab.

Playbook, handler, và `--check` ở bài sau.

## Dùng khi nào

Cùng một việc phải làm trên nhiều máy, và làm lần hai không được ra kết quả khác lần đầu nếu trạng thái đã đúng. Đó là idempotence. `command: apt install nginx` không idempotent theo cách Ansible muốn. Module `ansible.builtin.package` thì có: đã cài thì `ok`, chưa cài thì `changed`.

Một máy, một lần, thì SSH và chạy lệnh còn nhanh hơn. Đừng mở Ansible cho việc đó.

## Kiến thức cốt lõi

Inventory là danh sách host. INI đơn giản:

```ini
[web]
web1.example ansible_host=10.0.0.11

[db]
db1.example ansible_host=10.0.0.21
```

Tên trước khoảng trắng là tên Ansible dùng. `ansible_host` là địa chỉ thật để SSH. Không có `ansible_host` thì Ansible SSH vào đúng cái tên đó.

`-m ping` không phải ICMP. Module ping của Ansible SSH vào (hoặc connection local), chạy một Python nhỏ trên máy đích, trả `pong`. Máy đích cần Python. Docs ad hoc nói rõ: ping này kiểm tra Ansible nói chuyện được với host, không kiểm tra ICMP.

`command` và `shell` chạy lệnh. `shell` qua shell nên có pipe. `command` không qua shell. Cùng lý do với `subprocess` list và `execFile`: đừng đưa input lạ vào `shell`.

Mỗi task in một trong các trạng thái: `ok` không đổi gì, `changed` có đổi, `failed` lỗi, `unreachable` không vào được host.

## Lệnh và code mẫu

```bash
mkdir -p "$HOME/devops-lab/ansible"
cd "$HOME/devops-lab/ansible"
cat > inventory.ini <<'EOF'
[lab]
localhost ansible_connection=local
EOF

ansible -i inventory.ini lab -m ping
ansible -i inventory.ini lab -m command -a "uname -s"
```

## Thực hành

1. `ansible --version`.
2. Chạy hai lệnh trên. `ping` phải `pong` và `ok=1`.
3. Chạy `command` hai lần. Cả hai lần `changed` vì `command` không biết lệnh có làm đổi hệ thống hay không. Ansible vẫn in `changed` cho `command`.
4. Thêm một host giả `10.255.255.1 ansible_connection=ssh` vào group `lab` rồi chạy ping. Host đó `unreachable`. Localhost vẫn `ok`. Một host chết không chặn host kia, trừ khi bạn đặt `any_errors_fatal`.
5. Xoá host giả trước khi sang bài playbook.

## Kết quả mong đợi

- `ping` in `"ping": "pong"`.
- `uname` in tên kernel, thường là `Linux`.
- Host giả báo `UNREACHABLE`, exit code của Ansible khác 0.

## Checklist

- [ ] Tách tên host và `ansible_host`.
- [ ] Biết ping của Ansible không phải ICMP.
- [ ] Dùng module có sẵn trước khi dùng `command`.
- [ ] Đọc được `ok`, `changed`, `failed`, `unreachable`.
- [ ] Không chạy Ansible vào production từ inventory nháp còn host giả.

## Lỗi thường gặp

**`ping` thất bại vì tưởng cần root.** Module ping không cần root. `UNREACHABLE` là SSH hoặc Python trên máy đích. `FAILED` mới là module chạy rồi lỗi.

**Nhét `rm -rf` vào `-m command`.** Ad-hoc không có review, không có `--check` theo kiểu playbook. Lệnh phá huỷ để trong playbook đã commit, hoặc đừng chạy.

**Inventory commit kèm mật khẩu.** `ansible_password=` trong file là secret. Dùng SSH key, hoặc Ansible Vault. Lab `local` không cần mật khẩu.

## Nguồn

1. [How to build your inventory](https://docs.ansible.com/ansible/latest/inventory_guide/intro_inventory.html) — Ansible, INI, group, `ansible_host`.
2. [Ad hoc commands](https://docs.ansible.com/ansible/latest/command_guide/intro_adhoc.html) — `-m`, module ping.

## Tiếp theo

[Ansible playbook](./02-playbook.md)
