Ansible配置自动化
作用:掌握Ansible配置自动化工具,能实现多服务器批量管理!
一、Ansible环境搭建
1. 自动化运维
问题:假设我要去1000台服务器上做一个操作(如MySQL数据库服务器修改配置文件my.cnf里的某一个参数), 下面两种方法缺点明显:
第一种方案:按传统的方法, 一台连着一台服务器的ssh上去手动操作。
缺点: 效率太低。
第二种方案:写个Shell脚本来做。(最多只能部署几百台服务器)
缺点: 管理的机器平台(cnetos/ubuntu/kylin/rocky)不一致,脚本可能不具备通用性。传密码麻烦(在非免密登录的环境下, 需要expect来传密码),效率较低,循环1000次也需要一个一个的完成,如果用&符放到后台执行,则会产生1000个进程。
第三种方案:自动化运维
将日常IT运维中大量的重复性工作,小到简单的日常检查、配置变更和软件安装,大到整个变更流程的组织调度,由过去的手工执行转为自动化操作,从而减少乃至消除运维中的延迟,实现"零延时"的IT运维。
2. 自动化运维需要关注内容
假如管理很多台服务器,主要关注以下几个方面:
-
管理机与被管理机的连接(管理机如何将管理指令发送给被管理机)
-
服务器信息收集 (如果被管理的服务器有centos外还有其它linux发行版,如suse,ubuntu,kylin等。当你要做的事情在不同OS上有所不同,你需要收集信息,并将其分开处理)
-
服务器分组:因为有些时候我要做的事情不是针对所有服务器,可能只针对某一个分组
-
管理内容的主要分类
-
文件目录管理 (包括文件的创建,删除,修改,查看状态,远程拷贝等)
-
用户和组管理
-
cron 时间任务管理
-
yum 源配置与通过yum管理软件包
-
服务管理
-
远程执行脚本
-
远程执行命令
-
3. 常见运维工具对比
-
puppet:基于ruby语言,成熟稳定。适合于大型架构,相对于ansible和saltstack会复杂些。
-
saltstack:基于python语言,简单、并发能力比ansible要好, 需要维护被管理端的服务。如果服务断开,连接就会出问题。
-
**ansible:**基于python语言。简单快捷,被管理端不需要启服务。直接走ssh协议,需要验证所以机器多的话速度会较慢。
4. Ansible概述

ansible是一种由Python开发的自动化运维工具,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。
特点:
-
部署简单
-
默认使用ssh进行管理,基于python里的paramiko模块开发
-
管理端和被管理端不需要启动服务
-
配置简单,功能强大,扩展性强
-
能过playbook(剧本)进行多个任务的编排(第一步、第二步、第三步...)

Host1 ~ HostN:被管理机(不需要额外安装任何服务,Ansible直接走SSH协议)
Ansible => Connection Plugins(连接插件)=> 连接所有的被管理机(走SSH协议)
Host Inventory:主机清单(就是通过一个配置文件把所有被管理机进行分组,如分成web组、mysql组、redis组等等)
Modules:Core Modules(核心模块)、Custom Modules(自定义模块)=> 重点学习内容 => 通过模块实现管理被管理机(copy模块 => 文件上传、user模块可以进行用户管理、yum模块实现管理安装卸载...)
Plugins:插件,连接被管理机,结合email邮件、logging日志等实现一些额外功能
Playbook:剧本(演电影都要有剧本),把我们管理工作变成剧本,可以让Ansible可以有逻辑的执行(高级)
Users:用户管理,由于Ansible底层走SSH协议,所以连接被管理机,要么通过账号+密码,要么通过(Public/Private)免密操作
大致流程:Ansible首先需要配置主机清单(配置要连接机器以及进行提前分组),然后通过Connection连接插件连接所有的被管理机,底层走SSH协议,连接后,可以通过模块以及插件的方式对所有被管理机进行管理操作。针对于复杂的业务场景,还可以配合Playbook、Roles实现任务编排(让任务有逻辑的执行),这个就是Ansible核心原理了。
5. Ansible环境搭建
实验准备: 三台机器,一台管理,两台被管理
| 编号 | IP | 角色 |
|---|---|---|
| node1 | 192.168.88.101 | 管理机master |
| node2 | 192.168.88.102 | 被管理机1 |
| node3 | 192.168.88.103 | 被管理机2 |
配置说明:
-
静态ip
-
主机名及IP互相绑定=>/etc/hosts
-
关闭防火墙, selinux
-
时间同步
-
确认和配置yum源
全服务器时间同步:
shell
# 安装 EPEL(Extra Packages for Enterprise Linux)软件源 安装扩展库
dnf install epel-release -y
# 安装 NTPsec(Network Time Protocol Secure)服务
dnf install ntpsec -y
# 立即同步系统时间到中国 NTP 服务器(cn.ntp.org.cn)
ntpdate cn.ntp.org.cn
第1步: 管理机上安装ansible,被管理节点必须打开ssh服务
注意:ansible不需要再每一台机器上安装,只需要在node1主节点安装即可。
shell
# yum install ansible -y
# ansible --version
ansible [core 2.14.17]
config file = /etc/ansible/ansible.cfg
configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/lib/python3.9/site-packages/ansible
ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/bin/ansible
python version = 3.9.19 (main, Aug 23 2024, 00:00:00) [GCC 11.5.0 20240719 (Red Hat 11.5.0-2)] (/usr/bin/python3)
jinja version = 3.1.2
libyaml = True
第2步: 实现master对agent的免密登录,只在master上做。(如果这一步不做,则在后面操作agent时都要加-k参数传密码;或者在主机清单里传密码)
shell
master# ssh-keygen
master# ssh-copy-id 192.168.88.102
master# ssh-copy-id 192.168.88.103
如果是CentOS7采用ssh-copy-id -i IP地址,如果CentOS Stream 9系列,要去掉-i参数,否则报错!!!
第3步: 在master上定义主机组(主机清单),并测试连接性
powershell
master# vim /etc/ansible/hosts
# 表示被管理的机器
[group1]
192.168.88.102 # 可以用IP也可以使用主机名
192.168.88.103
-m 代表模块 => module
master# ansible -m ping group1
192.168.88.103 | SUCCESS => {
"changed": false,
"ping": "pong"
}
192.168.88.102 | SUCCESS => {
"changed": false,
"ping": "pong"
}
powershell
master# ansible -m ping all
192.168.88.103 | SUCCESS => {
"changed": false,
"ping": "pong"
}
192.168.88.102 | SUCCESS => {
"changed": false,
"ping": "pong"
}
6. 服务器分组(重点理解)
https://docs.ansible.com/ansible/latest/inventory*guide/intro*inventory.html
Ansible通过一个"主机清单"功能来实现服务器分组。
Ansible的默认主机清单配置文件为/etc/ansible/hosts
案例1:
起始值:结束值\],包含起始值也包含结束值(记住) ```powershell [nginx] 组名 apache[1:10].aaa.com 表示apache1.aaa.com到apache10.aaa.com这10台机器 nginx[a:z].aaa.com 表示nginxa.aaa.com到nginxz.aaa.com共26台机器 192.168.88.[161:165] 表示192.168.88.161到192.168.88.165这5台机器 ``` 案例2:如果底层ssh协议更改端口,需要在主机清单中进行指定(默认ssh走22端口) ```powershell [nginx] 10.1.1.13:2222 表示10.1.1.13这台,但ssh端口为2222 ``` 案例3:定义10.1.1.13:2222这台服务器的别名为nginx1 ```powershell nginx1 ansible_ssh_host=10.1.1.13 ansible_ssh_port=2222 ``` 案例4:没有做免密登录的服务器可以指定用户名与密码 =\> paramiko模块(记住) ```powershell nginx1 ansible_ssh_host=10.1.1.13 ansible_ssh_port=2222 ansible_ssh_user=root ansible_ssh_pass="123456" 注意: nginx1别名 ansible_ssh_host:要连接的主机的IP地址 ansible_ssh_port:ssh对应的端口号 ansible_ssh_user:用户名 ansible_ssh_pass:密码 ``` > 补充: > > 临时:ANSIBLE_HOST_KEY_CHECKING=False ansible -m ping nginx1 > > 永久:ssh-keyscan -H 192.168.88.104 \>\> \~/.ssh/known_hosts 案例5: ```powershell nginx1 ansible_ssh_host=10.1.1.13 ansible_ssh_port=2222 ansible_ssh_user=root ansible_ssh_pass="123456" nginx2 ansible_ssh_host=10.1.1.12 ansible_ssh_port=3333 ansible_ssh_user=root ansible_ssh_pass="123456" [nginx] nginx1 nginx2 ``` 小结: /etc/ansible/hosts =\> 主机清单 =\> Ansible是通过主机清单实现服务器分组 主机清单的作用: 服务器分组。 主机清单的常见功能: ① 可以通过IP范围来分, 主机名名字的范围来分 ② 如果ssh端口不是22的,可以传入新的端口。 ③ 没有做免密登录,可以传密码。 ## 二、Ansible模块 ### **1.** 求帮助 ```shell # ansible-doc -l fortios_router_community_list Configure community lists... azure_rm_devtestlab_info Configure community lists... ecs_taskdefinition Configure community lists... avi_alertscriptconfig Configure community lists... tower_receive Configure community lists... netapp_e_iscsi_target Configure community lists... azure_rm_acs Configure community lists... ...... ``` 如果要查看ping模块的用法,使用下面命令(其它模块以此类推) ```shell # ansible-doc ping ``` 官网模块文档:https://docs.ansible.com/ansible/2.9/modules/list*of*all_modules.html 中文文档:https://ansible-tran.readthedocs.io/en/latest/docs/modules.html ### **2**. file模块(重点) 作用:file模块用于对文件相关的操作(创建, 删除, 软链接等) https://docs.ansible.com/ansible/latest/modules/file_module.html#file-module ① path=文件或文件夹路径 ② state=状态(touch文件、directory文件夹、absent删除、recurse递归) 案例1:创建一个目录 ```powershell master# ansible group1 -m file -a 'path=/test state=directory' # group1表示哪个组 # path表示文件路径 # state=directory表示创建的文件类型是一个目录 ``` 案例2:创建一个文件 ```powershell master# ansible group1 -m file -a 'path=/test/111 state=touch' # 文件不存在自动创建 ``` 案例3:递归修改owner,group,mode ```powershell master# ansible group1 -m file -a 'path=/test recurse=yes owner=bin group=daemon mode=0777' ansible:调用 Ansible 的命令行工具。 group1:目标主机组,表示对在 Ansible 主机清单(inventory)中定义的名为 group1 的所有主机执行操作。 -m file:指定使用 file 模块。该模块用于管理文件、目录、软链接等的属性,如权限、属主、属组,也可用于创建或删除目录/文件。 -a '...':传递给 file 模块的参数(arguments),用空格分隔的键值对。 参数详解: path=/test:指定要操作的目标路径为 /test(可以是文件或目录)。 recurse=yes:如果 /test 是一个目录,则递归地将权限和属主/属组应用到其所有子目录和文件。 owner=bin:将 /test(及其内容,若为目录且 recurse=yes)的所有者设置为用户 bin。 group=daemon:将 /test(及其内容)的所属组设置为 daemon。 mode=0777:将 /test(及其内容)的权限设置为 0777(即 rwxrwxrwx)。 ⚠️ 注意:此命令不会创建 /test 路径(除非你额外加上 state=directory 或 state=file)。 默认情况下,file 模块只修改已存在路径的属性。如果 /test 不存在,Ansible 会报错。 ``` 案例4:删除目录(连同目录里的所有文件) ```powershell master# ansible group1 -m file -a 'path=/test state=absent' ``` 案例5:创建文件并指定owner,group,mode等 ```shell master# ansible group1 -m file -a 'path=/tmp/111 state=touch owner=bin group=daemon mode=0777' ``` 案例6:删除文件 ```shell master# ansible group1 -m file -a 'path=/tmp/111 state=absent' ``` 案例7:创建软链接文件 ```shell master# ansible group1 -m file -a 'src=/etc/fstab path=/tmp/fstab state=link' 参数位置 src:源文件 path:快捷方式路径 state=link:代表创建软链接 state=file 判断文件是否存在且是否为普通文件,是的,正常;反之就会报错 ``` 小结: Ansible中与文件管理相关的模块为(-m file) 基于file模块,我们可以创建文件、目录、软连接,也可以删除文件 state=touchfile有区别:touch代表创建文件,file代表判断文件,判断文件是否存在且是否为普通文件 ### **3.** copy模块(重点) 作用:copy模块用于对文件的远程拷贝操作(如把本地的文件拷贝到远程的机器上) 本机:nginx.conf,copy模块:分发到所有web节点 https://docs.ansible.com/ansible/latest/modules/copy_module.html#copy-module 在master上准备一个文件,拷贝此文件到group1的所有机器上 ```shell master# echo master > /tmp/file1 master# ansible group1 -m copy -a 'src=/tmp/file1 dest=/tmp/file2' src:原路径 dest:目标路径 ``` 使用content参数直接往远程文件里写内容(会覆盖原内容) ```shell master# ansible group1 -m copy -a 'content="ansible\n" dest=/tmp/file3' ``` 注意:ansible中-a后面的参数里也有引号时,记得要单引双引交叉使用,如果都为双引会出现问题 使用force参数控制是否强制覆盖 如果目标文件已经存在,则不覆盖 ```shell master# ansible group1 -m copy -a 'src=/tmp/file2 dest=/tmp/file3 force=no' force=no 表示不覆盖 ``` 如果目标文件已经存在,则会强制覆盖 ```shell master# ansible group1 -m copy -a 'src=/tmp/file2 dest=/tmp/file3 force=yes' force=no 表示覆盖 ``` 使用backup参数控制是否备份文件 backup=yes表示如果拷贝的文件内容与原内容不一样,则会备份一份 group1的机器上会将/tmp/file3备份一份(备份文件命名加上时间),再远程拷贝新的文件为/tmp/file3 ```shell master# ansible group1 -m copy -a 'src=/etc/fstab dest=/tmp/file3 backup=yes owner=daemon group=daemon mode=0777' backup=yes 表示覆盖之前备份 owner=daemon group=daemon mode=0777 表示文件所属者,所属组,具有的权限 ``` > 简单理解:就是对目标文件进行备份操作 copy模块拷贝时要注意拷贝目录后面是否带"/"符号 /etc/yum.repos.d后面不带/符号,则表示把/etc/yum.repos.d整个目录拷贝到/tmp/目录下 ```shell master# ansible group1 -m copy -a 'src=/etc/yum.repos.d dest=/tmp/' ``` /etc/yum.repos.d/后面带/符号,则表示把/etc/yum.repos.d/目录里所有文件拷贝到/tmp/目录下 ```powershell master# ansible group1 -m copy -a 'src=/etc/yum.repos.d/ dest=/tmp/' ``` 小结: Ansible有一个特殊模块,用于把本地文件拷贝到远程服务器,这个模块(copy) copy模块有两个常用的参数:(src)、(dest) > 拷贝的时候注意本地的文件是否存在,否则容易报错!!! *** ** * ** *** 扩展: Ansible copy模块:把本地文件拷贝到远程服务器,底层基于SSH协议,所以每个拷贝文件都需要走SSH协议,建立连接,进行认证,然后实现文件传输,如果一个目录下有多个文件,则copy模块执行会比较缓慢。 Ansible synchronize模块:把本地文件拷贝到远程服务器,底层基于RSYNC实现文件传输,可以全量传输也可以增量传输,所以相对而言速度要快一些,但是要求机器上必须要提前安装rsync服务。(传输很多文件的时候这个模块效率比copy快) ```powershell dnf install rsync -y ``` synchronize模块其参数几乎与copy模块一模一样,都有src与dest参数,src代表源文件位置,dest代表目标文件位置。 ```powershell ansible group1 -m synchronize -a "src=/etc/yum.repos.d dest=/tmp/" ``` ### **4.** yum/dnf模块(重点) yum模块用于使用yum命令来实现软件包的安装与卸载。 https://docs.ansible.com/ansible/latest/modules/yum_module.html#yum-module 使用yum安装一个软件(前提:group1的机器上的yum配置都已经OK) ```powershell master# ansible group1 -m yum -a 'name=vsftpd state=present' 或 master# ansible group1 -m dnf -a 'name=vsftpd state=present' ``` 使用yum安装httpd,httpd-devel软件,state=latest表示安装最新版本 ```shell master# ansible group1 -m yum -a 'name=httpd,httpd-devel state=latest' 或 master# ansible group1 -m dnf -a 'name=httpd,httpd-devel state=latest' ``` 使用yum卸载httpd,httpd-devel软件 ```shell master# ansible group1 -m yum -a 'name=httpd,httpd-devel state=absent' 或 master# ansible group1 -m dnf -a 'name=httpd,httpd-devel state=absent' ``` ### **5.** service模块(重点) 作用:service模块用于控制服务的启动,关闭,开机自启动等。 https://docs.ansible.com/ansible/latest/modules/service_module.html#service-module 启动vsftpd服务,并设为开机自动启动 ```powershell master# ansible group1 -m service -a 'name=httpd state=started enabled=true' ``` state服务管理可以选参数:"reloaded"、"restarted"、"started"、"stopped" 关闭vsftpd服务,并设为开机不自动启动 ```shell master# ansible group1 -m service -a 'name=httpd state=stopped enabled=false' ``` 小结: yum/dnf模块:主要负责(安装或卸载软件) service模块:主要负责(服务的管理、启动、停止、重启、开机自启、开机不自启) ## 三、Ansible Playbook 作用:Playbook(剧本),主要用于实现一些较为复杂的自动化部署操作。软件安装配置,如Keepalived、MySQL集群、Redis集群、大数据集群、K8S集群。 ### **1.** Playbook概述 playbook(剧本): 是ansible用于配置,部署,和管理被控节点的剧本。用于ansible操作的编排。 参考: https://docs.ansible.com/ansible/latest/user*guide/playbooks*intro.html 使用的格式为yaml格式(saltstack,elk,docker,docker-compose,kubernetes等也都会用到yaml格式) ### **2.** yaml格式 * 以.yaml或.yml结尾 * 文件的第一行以 "---"开始,表明YMAL文件的开始(可选的) * 以#号开头为注释 * 列表中的所有成员都开始于相同的缩进级别, 并使用一个"- "作为开头(一个横杠和一个空格) * 一个字典是由一个简单的 键(key): 值(value)的形式组成(这个冒号后面必须是一个空格) 注意: 写这种文件不要使用Tab键,都使用空格 参考: https://docs.ansible.com/ansible/latest/reference_appendices/YAMLSyntax.html#yaml-syntax 看一个官方案例: ```yaml --- # 一位职工记录 name: Example Developer job: Developer skill: Elite employed: True foods: - Apple - Orange - Strawberry - Mango languages: ruby: Elite python: Elite dotnet: Lame ``` ### **3.** Playbook入门案例 https://docs.ansible.com/ansible/latest/playbook*guide/playbooks*intro.html#playbook-syntax 先直接来看一个实例,在Linux系统中安装Apache软件:① yum安装软件 ② 编辑httpd.conf配置文件 ```powershell # 安装httpd (Apache软件) yum install httpd -y # 更改httpd软件配置,比如更改监听端口为8080 vim /etc/httpd/conf/httpd.conf 47行(监听端口)Listen 8080 124行 (项目目录) DocumentRoot "/var/www/html" # 启动httpd软件 systemctl start httpd # 在浏览器访问http://192.168.194.128:8080 ``` 第1步: 创建一个存放playbook的目录(路径自定义) ```shell master# mkdir /etc/ansible/playbook -p ``` 第2步:准备httpd配置文件,并修改成你想要的配置 ```shell master# yum install httpd -y ``` 按需要修改你想要的配置(为了测试可以随意改动标记一下) ```shell master# vim /etc/httpd/conf/httpd.conf 47行(监听端口)Listen 8080 ``` 第3步:写一个playbook文件(后缀为.yml或.yaml) ```yaml # vim /etc/ansible/playbook/example.yaml --- - hosts: group1 remote_user: root tasks: - name: ensure apache is at the latest version yum: name: httpd,httpd-devel state: latest - name: write the apache config file ansible.builtin.copy: # 也可以省略为copy src: /etc/httpd/conf/httpd.conf dest: /etc/httpd/conf/httpd.conf notify: - restart apache - name: ensure apache is running (and enable it at boot) service: name: httpd state: started enabled: yes handlers: - name: restart apache service: name: httpd state: restarted ``` 注意:task任务格式 ```shell - name: 任务执行时,打印的文本信息,可以是英文也可以是中文(类似注释,但是会打印输出) ansible模块,如file、copy、yum 参数 notify:与ansible模块是同级关系 - restart apache,这个地方的名称与 handlers:中name标签同名,代表调用handlers中定义好的任务操作 ``` Playbook格式说明:  第4步: 执行写好的palybook 会显示出执行的过程,并且执行的每一步都有ok,changed,failed等标识 执行如果有错误(failed)会回滚,解决问题后,直接再执行这条命令即可,并会把failed改为changed(幂等性) ```shell # ansible-playbook /etc/ansible/playbook/example.yaml ``` 小结: Playbook剧本就是按照配置的Task任务流程,按顺序执行。 在工作中,主要编写Task任务,一定要完全按照Task任务格式,具体每个模块如何使用,可以参考官网文档。 ## 四、Ansible Roles 作用:把变量、任务、handlers分别作为角色,按文件夹来实现分离编写过程! 把Playbook进一步细化:原来所有操作都是放置于一个yaml文件,有了Roles,可以把变量、任务、handlers分别单独编写,适合团队实现Ansible脚本开发。 ### 1. roles介绍 roles(角色): 就是通过分别将variables, tasks及handlers等放置于单独的目录中,并可以便捷地调用它们的一种机制。 假设我们要写一个playbook来安装管理lamp(Linux+Apache+mysql+PHP=\>wordpress博客)环境,那么这个playbook就会写很长。所以我们希望把这个很大的文件分成多个功能拆分, 分成apache管理,php管理,mysql管理,然后在需要使用的时候直接调用就可以了,以免重复写。就类似编程里的模块化的概念,以达到代码复用的效果。 ### 2. 创建roles的目录结构 ```powershell files:用来存放由copy模块或script模块调用的文件。 tasks:至少有一个main.yml文件,定义各tasks。 handlers:有一个main.yml文件,定义各handlers。 templates:用来存放jinjia2模板。 vars:有一个main.yml文件,定义变量。 meta:有一个main.yml文件,定义此角色的特殊设定及其依赖关系,类似说明书。 ``` **注意:** 在每个角色的目录中分别创建files, tasks,handlers,templates,vars和meta目录,用不到的目录可以创建为空目录. ### 3. 通过roles实现lamp 需定制三个角色: httpd,mysql,php=\>没有roles=\>lamp.yml(写的很长,很复杂) 有了roles以后,三个角色httpd,mysql,php(每个人开发一个角色)=\>每个角色下都需要有6个文件夹 **第1步: 创建roles目录及文件,并确认目录结构** ```shell master# cd /etc/ansible/roles/ master# mkdir -p {httpd,mysql,php}/{files,tasks,handlers,templates,vars,meta} master# touch {httpd,mysql,php}/{tasks,handlers,vars,meta}/main.yml master# yum install tree -y master# tree /etc/ansible/roles/ /etc/ansible/roles/ ├── httpd │ ├── files │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ ├── templates │ └── vars │ └── main.yml ├── mysql │ ├── files │ ├── handlers │ │ └── main.yml │ ├── meta │ │ └── main.yml │ ├── tasks │ │ └── main.yml │ ├── templates │ └── vars │ └── main.yml └── php ├── files ├── handlers │ └── main.yml ├── meta │ └── main.yml ├── tasks │ └── main.yml ├── templates └── vars └── main.yml ``` **第2步: 准备httpd服务器的主页文件,php测试页和配置文件等** ```shell master# echo "test main page" > /etc/ansible/roles/httpd/files/index.html master# echo -e "" > /etc/ansible/roles/httpd/files/test.php master# yum install httpd -y 按需求修改配置文件后,拷贝到httpd角色目录里的files子目录 master# vim /etc/httpd/conf/httpd.conf master# cp /etc/httpd/conf/httpd.conf /etc/ansible/roles/httpd/files/ ``` **第3步: 编写httpd角色的main.yml文件** ```yaml master# vim /etc/ansible/roles/httpd/tasks/main.yml --- - name: 安装httpd yum: name=httpd,httpd-devel state=present - name: 同步httpd配置文件 copy: src=/etc/ansible/roles/httpd/files/httpd.conf dest=/etc/httpd/conf/httpd.conf notify: restart httpd - name: 同步主页文件 copy: src=/etc/ansible/roles/httpd/files/index.html dest=/var/www/html/index.html - name: 同步php测试页 copy: src=/etc/ansible/roles/httpd/files/test.php dest=/var/www/html/test.php - name: 启动httpd并开机自启动 service: name=httpd state=started enabled=yes ``` **第4步: 编写httpd角色里的handler** ```yaml master# vim /etc/ansible/roles/httpd/handlers/main.yml --- - name: restart httpd service: name=httpd state=restarted ``` **第5步: 编写mysql角色的main.yml文件** ```yaml master# vim /etc/ansible/roles/mysql/tasks/main.yml --- - name: 安装mysql yum: name=mariadb,mariadb-server state=present - name: 启动mysql并开机自启动 service: name=mariadb state=started enabled=yes 说明: mariadb-server:mysql服务器端 mariadb:mysql客户端 ``` **第6步: 编写php角色的main.yml文件** ```yaml master# vim /etc/ansible/roles/php/tasks/main.yml --- - name: 安装php及依赖包 yum: name=php,php-gd,php-ldap,php-odbc,php-pear,php-xml,php-mbstring,php-snmp,php-soap,curl,curl-devel,php-bcmath,php-mysqlnd state=present notify: restart httpd 说明: php:核心包 php-xxx:扩展包,比如php连接mysql,需要php-mysqlnd包,php实现模拟发送http请求,curl模块 ``` php软件在lamp架构中,并不是独立存在的,而是依赖httpd软件,安装时会自动集成在httpd软件中。安装完成后,只需要重启httpd软件即可。 **第7步:编写lamp的playbook文件调用前面定义好的三个角色** ```yaml master# vim /etc/ansible/playbook/lamp.yaml --- - hosts: group1 remote_user: root roles: - httpd - mysql - php ``` **第8步: 执行lamp的playbook文件** ```shell master# ansible-playbook /etc/ansible/playbook/lamp.yaml ``` 小结: Ansible Roles:把大的yaml文件拆解为若干个小的main.yml文件,好处:方便调试,每个文件都比较小 缺点:文件夹太多,过于冗余 常见问题: 问题1:YAML语法有错误,千万不要按Tab键,如果出错了,可以借助于YAML校检工具 https://www.bejson.com/validators/yaml_editor/index.html 问题2:Roles脚本是一个整体,不要单独执行某个yaml文件应该统一执行最终的yaml,如lamp.yaml 单独执行某个main.yml,报错信息如下:  以上其实不是错误,而是也能为main.yml文件不完整导致的!