本文要点
ansible是无需在目标机装代理的自动化工具,走 SSH 下发任务,用 YAML 描述"期望状态"- 主机清单
hosts.ini把机器分成组,ansible -m ping一条命令验证连通性 - ad-hoc 命令用
-m指定模块 +-a传参数,适合快速查询和临时操作 - Playbook 把多台主机的配置流程写成 YAML 剧本,天然幂等:重复执行结果一致
- 常用模块涵盖包管理(
apt)、服务(service)、文件(copy/template/file),组合起来就能完成完整的服务部署
为什么要用自动化运维
维护几台服务器时,SSH 上去敲命令还能应付。但机器一旦多起来,安装软件、改配置、启停服务这些重复动作就会越来越费时间,还会因为手滑导致两台机器配置不一致。自动化运维要解决的核心问题,就是把"用手敲"变成"用代码描述"——让同样的操作在任意数量的机器上稳定、可重复地执行。
本文用 Ansible 为例,从安装、主机清单、ad-hoc 临时命令到 Playbook 剧本,在一台真实的 Ubuntu 服务器上把一套 Nginx 服务从零部署起来,顺便验证它的幂等特性。
Ansible 是什么
Ansible 是一个无代理(agentless)的自动化工具:它不用在被管理机器上安装任何客户端,控制端通过 SSH 连接目标机,把要执行的模块下发过去运行,运行完就断开。这一点和远程执行脚本、Docker、盐堆等方案很不一样——你只要保证控制端能 SSH 到目标机即可。
它有三个关键设计:
- 声明式:你描述目标状态("这台机器上要装 nginx"),而不是一步步写"先执行 apt-get,再检查返回值"。
- 基于 YAML:任务清单直接就是给人看的文本,容易审核和版本管理。
- 幂等:同一份配置反复执行,结果一致;已经满足的状态会被跳过,不会重复搞坏系统。
安装 Ansible
在 Ubuntu 控制端上用 apt 一句命令装好:
sudo apt-get install -y ansible安装后确认核心组件可用:
ansible --version它由几个命令组成,后面都会用到:
| 命令 | 作用 |
|---|---|
ansible | 执行 ad-hoc 单条任务 |
ansible-playbook | 执行 Playbook 剧本 |
ansible-inventory | 查看主机清单 |
ansible-doc | 查阅模块文档(如 ansible-doc apt) |
主机清单:告诉 Ansible 管理哪些机器
Ansible 需要知道目标主机是谁、怎么连接,这份配置叫主机清单(Inventory),默认路径是 /etc/ansible/hosts,也可以启动时用 -i 指定。最简单的 INI 格式长这样:
# 主机清单 hosts.ini
[web_servers]
web01 ansible_host=192.168.1.10
web02 ansible_host=192.168.1.11
[db_servers]
db01 ansible_host=192.168.1.20
[local_host]
127.0.0.1 ansible_connection=local方括号里是主机组名,组下面的行是组内主机。ansible_host 指定连接地址,ansible_connection=local 表示直接在本机执行(不用 SSH),方便我们在同一台机器上演示。实际生产环境通常默认使用 SSH 连接,不写 ansible_connection 即可。
写好清单后,用一条命令验证连通性:
cat /root/ansible-demo/hosts.ini && ansible -i /root/ansible-demo/hosts.ini local_host -m ping
-i 指向清单文件,local_host 是要操作的组名,-m ping 指定模块。输出里 127.0.0.1 | SUCCESS 并且返回 "ping": "pong",说明清单配置正确、连接通畅。每个想到的目标主机会单独输出一行,多台机器时一眼就能看出哪些通、哪些挂。
ad-hoc 命令:一次性的快速操作
不需要写剧本、只想快速跑一条命令时,用 ansible 的 ad-hoc 模式。格式是 ansible <组名> -m <模块> -a "<参数>"。看两个例子:
ansible -i /root/ansible-demo/hosts.ini local_host -m command -a "hostname" -o && ansible -i /root/ansible-demo/hosts.ini local_host -m setup -a "filter=ansible_distribution,ansible_distribution_version,ansible_memtotal_mb" -o
第一段用 -m command 在目标机上执行 hostname,返回 127.0.0.1 | CHANGED | rc=0 | (stdout) 加主机名 demo。command 模块直接调用远端 shell 执行命令,是最基础的"远程执行"。
第二段用 -m setup 收集目标机的系统信息(叫 facts),filter 参数限制只返回我们关心的字段。这里能看到一台 Ubuntu 24.04、内存 1886 MB 的主机。facts 在执行 Playbook 时会被自动收集并当作变量使用,后面模板小节会用到。
其他常用的 ad-hoc 例子:
# 安装软件包(apt 模块)
ansible -i hosts.ini local_host -m apt -a "name=cowsay state=present"
# 复制文件
ansible -i hosts.ini local_host -m copy -a "src=/root/ansible-demo/welcome.txt dest=/tmp/ansible-welcome.txt"
# 创建目录
ansible -i hosts.ini local_host -m file -a "path=/tmp/ansible-test-dir state=directory mode=0750"state 参数是 Ansible 模块里最常见的设计:它声明"目标状态"。比如 apt 的 state=present 表示包要存在(没有就装),file 的 state=directory 表示目录要存在、state=absent 表示要删除。
Playbook:把流程写成剧本
ad-hoc 适合单条任务,要部署完整服务就得靠 Playbook。它是一个 YAML 文件,按顺序描述一组任务。下面是部署 Nginx 的完整示例:
---
- name: 部署 Nginx Web 服务器
hosts: local_host
gather_facts: yes
become: true
tasks:
- name: 安装 nginx
ansible.builtin.apt:
name: nginx
state: present
- name: 写入自定义首页
ansible.builtin.copy:
content: "<h1>Hello from Ansible</h1>\n<h2>Hostname: {{ ansible_hostname }}</h2>\n"
dest: /var/www/html/index.html
- name: 用模板生成登录欢迎信息
ansible.builtin.template:
src: motd.j2
dest: /etc/motd
owner: root
group: root
mode: "0644"
- name: 启动 nginx 并设置开机自启
ansible.builtin.service:
name: nginx
state: started
enabled: true
- name: 打印服务状态摘要
ansible.builtin.command:
cmd: systemctl is-active nginx
register: nginx_status
changed_when: false
- name: 显示 nginx 进程状态
ansible.builtin.debug:
msg: "nginx current state: {{ nginx_status.stdout }}, hostname: {{ ansible_hostname }}"结构拆解:
hosts——这组任务作用在哪个主机组上,这里是清单里的local_host。become: true——以 root 权限执行(command里那句systemctl需要)。gather_facts: yes——执行前自动收集目标机信息,供模板和变量使用。tasks——按顺序执行的任务列表,每个任务有名字和模块定义。register——把某条命令的返回值存进变量,供后续任务引用。
运行这个剧本:
cd /root/ansible-demo && ANSIBLE_NOCOWS=1 ansible-playbook -i hosts.ini nginx-setup.yml
输出里每个 TASK 一行,changed 表示本任务真正对系统产生了修改。首次运行时 安装 nginx、写入自定义首页、用模板生成登录欢迎信息 三个任务变成了 changed,说明它真的装了包、写了文件;而 启动 nginx 是 ok,因为服务已经处于运行状态。结尾的 PLAY RECAP 汇总了整轮结果:ok=7 changed=3 failed=0,代表部署成功、有 3 处实际改动、0 处失败。
部署完直接验证效果:
curl -s http://127.0.0.1/返回的就是 Playbook 里写入的 <h1>Hello from Ansible</h1>,而 /etc/motd 也和模板里的内容一致,Nginx 服务真实可用。
再跑一次会发现什么
同一份 Playbook 立刻再执行一遍:
ANSIBLE_NOCOWS=1 ansible-playbook -i hosts.ini nginx-setup.yml这次 PLAY RECAP 会变成 ok=7 changed=0——所有任务都已是期望状态,Ansible 判断"无需修改"全部跳过。这就是幂等:配置代码可以放心反复执行、可以被纳入 CI 定期核对,不会因为重复运行而出错。
模板与变量:配置随机器变化
直接写死配置适合固定内容,真实环境里往往需要"同一份模板、随机器不同渲染"的配置。template 模块基于 Jinja2 模板引擎,能读取收集到的 facts 并渲染。前面 Playbook 里的 motd.j2 模板:
===========================================
欢迎访问 {{ ansible_hostname }}
操作系统: {{ ansible_distribution }} {{ ansible_distribution_version }}
内存大小: {{ ansible_memtotal_mb }} MB
管理工具: Ansible
===========================================执行后 /etc/motd 被渲染为:
欢迎访问 demo
操作系统: Ubuntu 24.04
内存大小: 1886 MB{{ ansible_hostname }}、{{ ansible_distribution }} 这类双大括号语法就是变量占位。第一次运行时这些 facts 正是靠 gather_facts 收集的。用同样的思路,template 可以渲染 nginx 站点配置、systemd 单元文件、环境变量文件等,一套模板覆盖不同 IP、不同端口的机器。
常用模块速查
把零散需求映射到合适的模块,是写 Playbook 的基本功。这份速查覆盖了日常绝大部分场景:
| 模块 | 用途 | 典型参数 |
|---|---|---|
apt / yum / dnf | 安装、卸载软件包 | name、state=present/absent/latest |
service / systemd | 启停服务、设置开机自启 | name、state=started/stopped、enabled |
copy | 复制文件或将内容写入文件 | src/content、dest、mode、owner |
template | 用 Jinja2 模板渲染文件 | src(.j2)、dest、mode |
file | 创建/删除目录、文件、链接 | path、state=directory/file/absent、mode |
command / shell | 执行任意命令 | cmd(command)或直接命令串(shell) |
user / group | 管理用户和组 | name、state=present/absent |
lineinfile | 在配置文件中精确增改一行 | path、line、regexp |
debug | 打印变量/调试信息 | msg、var |
setup | 收集目标机 facts | filter |
查询某个模块的完整参数,随时用 ansible-doc <模块名>。
Playbook 设计建议
- 任务粒度要小:一个任务只做一件事,报错时定位准确,也能单独跳过。
- 坚持幂等:能用模块就用模块(
apt、service),少用裸command;command记得配changed_when,告诉 Ansible 什么情况下算"变了"。 - 把可变值提为变量:端口、路径、版本放
vars:或单独变量文件,模板内容才有意义。 - 敏感信息用 vault:密码、密钥不要明文写进剧本,Ansible 的 ansible-vault 可加密整个文件。
- 用
--check预演:ansible-playbook --check进入 dry-run 模式,只看"会改动什么"而不真改,上线前必跑。
小结
从手动敲命令到声明式自动化,核心转变是用代码描述期望状态而非操作步骤。本文的完整链路是:
- 用主机清单声明机器归属,
ansible -m ping验证连通; - 用 ad-hoc 命令做一次性查询和临时操作;
- 把 Nginx 部署写成 Playbook,用
apt/copy/template/service组合完成任务; - 靠幂等保证剧本可以反复执行、结果稳定。
当你需要把"装个 nginx、改个配置、起个服务"这类操作复制到十台、上百台机器时,这套方法就能把重复劳动变成一次提交。
评论 (0)
暂无评论,快来抢沙发吧!