news 2026/1/3 20:43:15

Ansible Playbook,轻松搞定运维自动化

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Ansible Playbook,轻松搞定运维自动化

前言

在如今的IT运维工作中,重复的服务器配置、软件安装、服务启停等工作占用了大量时间,而且人工操作容易出错。Ansible作为一款轻量级自动化工具,无需在目标主机安装代理,只需通过SSH即可实现远程管理,而Playbook则是Ansible的核心——它用简单的YAML格式,把复杂的运维任务写成“剧本”,让基础设施管理实现“代码化”,既高效又可靠。

本文将从基础概念到实战案例,一步步教你编写和使用Ansible Playbook,即使是运维新手也能轻松上手。

一、Playbook 基础概念

1.1 Playbook 结构概述

Playbook 本质是一个YAML格式的文件,里面可以包含多个“剧本(Play)”,每个Play专门针对一组主机执行一系列任务。一个完整的Playbook通常由以下5个核心部分组成,就像搭建房子需要不同的建材一样:

  • Tasks(任务):最核心的部分,每个任务调用一个Ansible模块(比如安装软件、启动服务),在目标主机上执行具体操作。
  • Variables(变量):相当于“万能占位符”,可以定义重复使用的值(比如软件名称、端口号),让Playbook更灵活,不用重复修改代码。
  • Templates(模板):基于Jinja2引擎的配置文件模板,能把变量动态替换成实际值,比如不同主机的Apache配置可以用同一个模板生成。
  • Handlers(处理器):专门响应任务变更的“触发器”,比如配置文件修改后,通过它触发服务重启,而且不管触发多少次,最后只执行一次,避免重复操作。
  • Roles(角色):把任务、变量、模板等按功能拆分到不同目录,形成模块化结构,比如把“Apache配置”“MySQL安装”做成独立角色,方便重复使用和维护。

二、Playbook 示例解析

2.1 基础Playbook示例

下面用一个完整的示例,带你看懂Playbook的基本结构——这个剧本会在目标主机上关闭防火墙、安装Apache、配置文件并启动服务:

# 文件名:test1.yaml---# 标记YAML文件开始,可省略-name:部署Apache服务# 剧本名称,方便识别,可省略gather_facts:false# 不收集主机信息,加快执行速度,可省略hosts:webservers# 目标主机组(在Ansible主机清单中定义)remote_user:root# 用root用户在目标主机执行操作tasks:# 任务列表,按顺序执行-name:测试主机连通性# 任务名称,自定义ping:# 调用ping模块,测试SSH连接是否正常-name:关闭SELinuxcommand:'/sbin/setenforce 0'# command模块执行系统命令,无需key=value格式ignore_errors:True# 忽略命令执行失败(比如SELinux已关闭),避免剧本中断-name:关闭防火墙service:name=firewalld state=stopped enabled=no# service模块管理系统服务,key=value格式传参-name:安装Apacheyum:name=httpd state=latest# yum模块安装最新版httpd-name:复制Apache配置文件copy:src=/opt/httpd.conf dest=/etc/httpd/conf/httpd.conf# 复制本地配置文件到目标主机notify:"重启Apache"# 若该任务执行后配置文件有变更,触发名为“重启Apache”的处理器-name:启动Apache服务service:name=httpd state=started enabled=yes# 启动服务并设置开机自启handlers:# 处理器列表,仅在被notify触发时执行-name:重启Apache# 名称必须和notify中的一致service:name=httpd state=restarted# 重启Apache服务

这里有个关键知识点:Handlers不会立即执行,要等当前剧本中所有普通任务都完成后,才会统一执行被触发的Handlers。这样即使多次修改配置文件触发notify,也只会重启一次服务,效率更高。

再补充一个安装MySQL的简单示例,帮你巩固基础:

# 文件名:install_mysql.yaml----name:安装MariaDB数据库hosts:dbservers# 目标主机组为数据库服务器tasks:-name:安装MariaDB服务yum:name:[mariadb,mariadb-server]# 安装两个软件包state:latest-name:启动MariaDB服务service:name:mariadbstate:startedenabled:yes

三、Playbook 执行与管理

3.1 命令行运行 Playbook

写好Playbook后,通过ansible-playbook命令执行,常用参数如下,直接套用即可:

# 1. 直接运行Playbookansible-playbook test1.yaml# 2. 检查语法错误(编写后必做,避免执行失败)ansible-playbook test1.yaml --syntax-check# 3. 查看剧本中的所有任务,不实际执行ansible-playbook test1.yaml --list-task# 4. 查看剧本会影响哪些主机ansible-playbook test1.yaml --list-hosts# 5. 从指定任务开始执行(比如前面任务已完成,无需重复执行)ansible-playbook test1.yaml --start-at-task='安装Apache'

执行后会显示每个任务的结果:ok(无变更)、changed(有变更)、failed(失败),一目了然。

3.2 认证相关参数

如果目标主机需要SSH密码登录,或者执行任务需要sudo权限(非root用户),可以用以下参数:

# 提示输入SSH登录密码ansible-playbook test1.yaml -k# 提示输入sudo密码(执行sudo命令时需要)ansible-playbook test1.yaml -K

四、变量定义与使用

变量能让Playbook摆脱“硬编码”,一次编写多次复用,比如换个软件名称、端口号,不用修改任务,只需改变量即可。

4.1 变量定义方法

最常用的是在Playbook中用vars关键字定义,直接看示例:

# 文件名:test2.yaml----name:用变量创建用户和组hosts:dbserversremote_user:rootvars:# 定义变量groupname:mysql# 组名变量username:nginx# 用户名变量tasks:-name:创建mysql组group:name:"{{ groupname }}"# 引用变量,用{{ 变量名 }}格式system:yes# 系统组gid:306# 组ID-name:创建nginx用户user:name:"{{ username }}"uid:306group:"{{ groupname }}"# 引用组名变量-name:保存主机IP到文件copy:content:"{{ ansible_default_ipv4.address }}"# 引用Ansible内置变量(获取主机IP)dest:/opt/host_ip.txt

Ansible还有很多内置变量(比如主机名、内存大小等),可以通过ansible 主机名 -m setup命令查看所有内置变量。

4.2 命令行传递变量

如果临时需要修改变量值,不用改Playbook,直接用-e参数在命令行传递,优先级最高:

# 临时将用户名改为tom,覆盖Playbook中定义的nginxansible-playbook test2.yaml -e"username=tom"

这里要提一下Ansible的幂等性:不管执行多少次Playbook,结果都是一致的,不会出现重复创建用户、重复安装软件的问题,非常安全。

五、条件判断与循环

5.1 条件判断 when

有时候我们需要“满足特定条件才执行任务”,比如只给IP为192.168.10.14的主机重启,或者内存大于4G才安装数据库。Ansible中用when指令实现条件判断,值为true时执行任务。

常用场景示例:
  1. 按IP地址执行任务
----name:只重启指定IP的主机hosts:allremote_user:roottasks:-name:重启主机command:/sbin/shutdown-r nowwhen:ansible_default_ipv4.address == "192.168.10.14"# 变量不用加{{ }}
  1. 按主机配置执行任务(比如内存≥4G装MariaDB,CPU≥2核装Apache):
----name:按主机配置安装软件hosts:allgather_facts:true# 必须开启(默认开启),才能获取内存、CPU等信息remote_user:roottasks:-name:内存≥4G安装MariaDByum:name=[mariadb,mariadb-server]state=presentwhen:ansible_memtotal_mb>= 4096# ansible_memtotal_mb是内置变量,代表总内存(MB)-name:内存不足提示debug:msg="内存只有{{ansible_memtotal_mb}}MB,不安装MariaDB"when:ansible_memtotal_mb < 4096-name:CPU≥2核安装Apacheyum:name=httpd state=presentwhen:ansible_processor_cores>= 2# 内置变量,CPU核心数-name:CPU核心不足提示debug:msg="CPU只有{{ansible_processor_cores}}核,不安装Apache"when:ansible_processor_cores < 2
  1. 按主机名执行任务
# 需先在Ansible主机清单中配置主机名映射when:inventory_hostname == "web01"# inventory_hostname是内置变量,代表主机名

5.2 迭代循环 with_items 和 loop

如果需要重复执行同一个任务(比如创建多个目录、多个用户),不用写多个任务,用循环就能搞定。Ansible支持with_itemsloop,功能完全一样,loop是较新的推荐用法。

常用场景示例:
  1. 创建多个目录
----name:批量创建目录hosts:dbserversremote_user:roottasks:-name:创建/tmp/test1和/tmp/test2目录file:path:"{{ item }}"# item代表循环中的每个值state:directory# 状态为目录loop:# 循环列表-/tmp/test1-/tmp/test2
  1. 创建多个用户(带不同组)
----name:批量创建用户hosts:dbserversremote_user:roottasks:-name:创建test1和test2用户user:name:"{{ item.name }}"# 引用循环中的name字段state:presentgroups:"{{ item.groups }}"# 引用循环中的groups字段loop:-name:test1groups:wheel# test1用户加入wheel组-name:test2groups:root# test2用户加入root组

执行后,目标主机上会成功创建两个用户,且所属组符合配置。

六、模板系统 Templates

有时候不同主机的配置文件只有少数参数不同(比如端口号、网站根目录),如果每个主机写一个配置文件,维护起来很麻烦。这时用Jinja2模板就能解决——一个模板文件,配合变量,自动生成不同主机的配置文件。

6.1 Jinja2 模板引擎

Jinja2是基于Python的模板引擎,核心作用是“变量替换”:在模板文件中用{{ 变量名 }}标记需要替换的内容,Ansible执行时会把变量换成实际值,生成最终的配置文件。

6.2 模板使用示例

以Apache配置文件为例,步骤如下:

第一步:创建Jinja2模板文件

先复制默认的Apache配置文件,改名为.j2后缀(标识为模板文件):

# 复制默认配置文件到/opt目录,并重命名cp/etc/httpd/conf/httpd.conf /opt/httpd.conf.j2

编辑模板文件,把需要动态修改的参数换成变量:

vim/opt/httpd.conf.j2# 42行:监听端口,替换为{{ http_port }}Listen{{http_port}}# 95行:服务器名,替换为{{ server_name }}ServerName{{server_name}}# 119行:网站根目录,替换为{{ root_dir }}DocumentRoot"{{ root_dir }}"
第二步:在主机清单中定义变量

编辑Ansible主机清单(默认路径/etc/ansible/hosts),给webservers组的主机指定变量值:

vim/etc/ansible/hosts[webservers]192.168.10.14http_port=80server_name=www.test.com:80root_dir=/etc/httpd/htdocs192.168.10.15http_port=8080server_name=www.demo.com:8080root_dir=/opt/htdocs

这样不同主机的变量值不同,生成的配置文件也会不一样。

第三步:编写Playbook使用模板
# 文件名:template_demo.yaml----hosts:webserversremote_user:rootvars:service:httpd# 定义服务名变量tasks:-name:安装Apacheyum:name={{service}}state=latest-name:部署动态配置文件template:src:/opt/httpd.conf.j2# 模板文件路径dest:/etc/httpd/conf/httpd.conf# 目标主机的配置文件路径notify:重启Apache# 配置文件变更后触发重启-name:创建网站根目录file:path={{root_dir}}state=directory# 引用主机清单中的root_dir变量-name:启动Apache服务service:name={{service}}state=started enabled=yeshandlers:-name:重启Apacheservice:name={{service}}state=restarted
第四步:执行并验证
ansible-playbook template_demo.yaml# 验证配置文件是否生效(以192.168.10.14为例)ansible192.168.10.14 -a'grep -E "Listen|ServerName|DocumentRoot" /etc/httpd/conf/httpd.conf'

执行后会看到,配置文件中的变量已经被替换成主机清单中定义的值,实现了“一个模板,多机复用”。

七、Tags 模块

如果Playbook中有很多任务,而你只想执行其中几个(比如只更新配置文件,不安装软件),用Tags就能实现——给任务打标签,执行时指定标签即可。

7.1 Tags 的作用

  • 给单个或多个任务打标签,执行Playbook时可指定只运行带该标签的任务;
  • 特殊标签always:无论指定哪个标签,带always的任务都会执行(比如备份文件)。

7.2 Tags 使用示例

# 文件名:tags_demo.yaml----hosts:webserversremote_user:roottasks:-name:备份原有配置文件copy:src=/etc/httpd/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf.baktags:always# 始终执行,不管指定哪个标签-name:安装Apacheyum:name=httpd state=latesttags:install# 标签名为install-name:更新Apache配置文件copy:src=/opt/httpd.conf dest=/etc/httpd/conf/httpd.conftags:config# 标签名为config-name:重启Apacheservice:name=httpd state=restartedtags:restart# 标签名为restart

7.3 执行指定Tags

# 1. 只执行带config标签的任务(备份任务会自动执行,因为有always标签)ansible-playbook tags_demo.yaml --tags="config"# 2. 执行install和restart两个标签的任务ansible-playbook tags_demo.yaml --tags="install,restart"# 3. 只执行always标签的任务(仅备份配置文件)ansible-playbook tags_demo.yaml --tags="always"

Tags在大型Playbook中非常实用,能节省执行时间,避免不必要的操作。

八、Roles 模块

当你的Playbook越来越复杂(比如要管理Web、数据库、缓存等多种服务),把所有任务都写在一个文件里,维护起来会非常困难。Roles就是为了解决这个问题——把不同服务的配置拆分成独立的“角色”,结构清晰,可重复使用。

8.1 Roles 概念与优势

Roles 是Ansible的模块化组织方式,把任务、变量、模板等按功能拆分到固定目录中,优势很明显:

  • 结构清晰:每个角色负责一个具体功能(比如httpd角色管Apache,mysql角色管数据库);
  • 复用性高:一个角色可以在多个项目中使用,不用重复写代码;
  • 易于维护:修改某个服务的配置,只需改对应的角色目录,不影响其他部分。

8.2 Roles 目录结构

每个角色都有固定的目录结构,创建后如下(以web和db两个角色为例):

roles/ # 总角色目录(默认路径/etc/ansible/roles) ├── web/ # Apache角色目录 │ ├── files/ # 存放copy/script模块需要的文件(比如静态配置文件) │ ├── templates/ # 存放Jinja2模板文件 │ ├── tasks/ # 任务目录,必须有main.yml(定义角色的任务) │ ├── handlers/ # 处理器目录,必须有main.yml │ ├── vars/ # 变量目录,main.yml中定义角色专属变量 │ ├── defaults/ # 默认变量目录,优先级低于vars │ └── meta/ # 依赖关系目录,main.yml中定义角色依赖 └── db/ # MySQL角色目录 ├── files/ ├── templates/ ├── tasks/ ├── handlers/ ├── vars/ ├── defaults/ └── meta/

核心是tasks/main.yml(角色的任务入口)和vars/main.yml(角色的变量定义),其他目录用不到可以为空或不创建。

8.3 使用Roles的步骤

  1. 创建总角色目录(yum安装Ansible后默认已有):mkdir -p /etc/ansible/roles
  2. 创建具体角色目录(比如httpd、mysql、php);
  3. 在每个角色目录下创建子目录(files、tasks、vars等);
  4. 在tasks、vars等目录下创建main.yml文件,编写任务和变量;
  5. 编写site.yml文件,调用不同角色;
  6. 执行site.yml。

8.4 Roles 实战案例

下面通过部署LAMP(Linux+Apache+MySQL+PHP)环境,带你实战Roles的使用。

8.4.1 创建项目目录

先创建三个角色(httpd、mysql、php)的目录和必要文件:

# 创建角色目录和子目录mkdir-p /etc/ansible/roles/{httpd,mysql,php}/{files,templates,tasks,handlers,vars,defaults,meta}# 在每个角色的tasks、vars等目录创建main.ymltouch/etc/ansible/roles/httpd/{tasks,vars,handlers}/main.ymltouch/etc/ansible/roles/mysql/{tasks,vars,handlers}/main.ymltouch/etc/ansible/roles/php/{tasks,vars,handlers}/main.yml
8.4.2 编写httpd模块(Apache角色)
  1. 编写任务文件(定义安装、启动Apache):
vim/etc/ansible/roles/httpd/tasks/main.yml - name: 安装Apache软件 yum:name={{pkg}}state=latest - name: 启动Apache服务并设置开机自启 service:name={{svc}}state=startedenabled=yes
  1. 编写变量文件(定义软件名和服务名):
vim/etc/ansible/roles/httpd/vars/main.yml pkg: httpd# 软件包名svc: httpd# 服务名
8.4.3 编写mysql模块(MySQL角色)
  1. 编写任务文件:
vim/etc/ansible/roles/mysql/tasks/main.yml - name: 安装MariaDB软件 yum:name={{pkg}}state=latest - name: 启动MariaDB服务并设置开机自启 service:name={{svc}}state=startedenabled=yes
  1. 编写变量文件:
vim/etc/ansible/roles/mysql/vars/main.yml pkg: - mariadb# MariaDB客户端- mariadb-server# MariaDB服务端svc: mariadb# 服务名
8.4.4 编写php模块(PHP角色)
  1. 编写任务文件:
vim/etc/ansible/roles/php/tasks/main.yml - name: 安装PHP软件 yum:name={{pkg}}state=latest - name: 启动php-fpm服务并设置开机自启 service:name={{svc}}state=startedenabled=yes
  1. 编写变量文件:
vim/etc/ansible/roles/php/vars/main.yml pkg: - php# PHP核心- php-fpm# PHP进程管理器svc: php-fpm# 服务名
8.4.5 编写roles剧本(调用角色)

创建site.yml文件,指定哪些主机调用哪些角色:

vim/etc/ansible/site.yml --- - name: 部署LAMP环境 hosts: webservers# 目标主机组(需要在/etc/ansible/hosts中定义)remote_user: root roles: - httpd# 调用Apache角色- mysql# 调用MySQL角色- php# 调用PHP角色
执行并验证
# 进入Ansible配置目录执行cd/etc/ansible ansible-playbook site.yml# 验证服务是否正常运行(在目标主机执行)systemctl is-active httpd# 输出active表示正常systemctl is-active mariadb systemctl is-active php-fpm

执行成功后,目标主机就部署好了LAMP环境,整个过程结构清晰,后续要修改Apache配置,只需改httpd角色的相关文件即可。

总结

Ansible Playbook 是运维自动化的“瑞士军刀”,通过YAML格式的简单语法,把复杂的运维任务变成可复用、可维护的“代码”。本文从基础结构入手,逐步讲解了变量、条件判断、循环、模板、Tags和Roles等核心功能,每个部分都配有实战示例,新手也能跟着操作。

核心要点回顾:

  • Playbook的核心是“任务”,通过模块实现具体操作;
  • 变量、模板让Playbook更灵活,避免重复代码;
  • Tags能精准执行指定任务,提高效率;
  • Roles是模块化的关键,适合管理复杂环境。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/27 4:26:43

R语言使用reshape2包的melt函数进行dataframe变形将dataframe数据从宽表变换为长表、dcast函数把melt函数处理后的数据、基于一个自定义公式(formula)从长表到宽表

R语言使用reshape2包的melt函数进行dataframe变形将dataframe数据从宽表变换为长表、dcast函数把melt函数处理后的数据、基于一个自定义公式(formula)从长表到宽表 目录 R语言使用reshape2包的melt函数进行dataframe变形将dataframe数据从宽表变换为长表、dcast函数把melt函…

作者头像 李华
网站建设 2025/12/26 12:04:43

Lucy-Edit-Dev:开源视频指令编辑新突破

Lucy-Edit-Dev&#xff1a;开源视频指令编辑新突破 【免费下载链接】Lucy-Edit-Dev 项目地址: https://ai.gitcode.com/hf_mirrors/decart-ai/Lucy-Edit-Dev 导语 DecartAI团队近日开源了首个基于文本指令的视频编辑模型Lucy-Edit-Dev&#xff0c;以50亿参数规模实现纯…

作者头像 李华
网站建设 2025/12/27 7:11:55

Langchain-Chatchat装修设计方案:根据户型推荐风格搭配

Langchain-Chatchat装修设计方案&#xff1a;根据户型推荐风格搭配 在现代家装咨询中&#xff0c;客户常常面临一个尴尬的现实&#xff1a;想要一套“温馨又不失格调”的设计&#xff0c;却说不清具体要什么&#xff1b;而设计师则疲于应对重复性问题&#xff0c;难以兼顾效率与…

作者头像 李华