实验环境
网络环境
底层系统
系统都为:Red Hat Enterprise Linux release 8.0 (Ootpa)
ansible主机清单
Playbook
playbook 剧本是由一个或多个“play”组成的列表。
play的主要功能在于将预定义的一组主机,装扮成事先通过ansible中的task定义好的角色。Task实际是调用ansible的一个module,将多个play组织在一个playbook中,即可以让它们联合起来,按事先编排的机制执行预定义的动作。
Playbook 文件是采用YAML语言编写的。
执行配置文件
playbook配置文件使用YAML语法,具有简洁明了、结构清晰等特点。playbook配置文件类似于shell脚本,是一个YAML格式的文件,用于保存针对特定需求的任务列表。上面介绍的ansible命令虽然可以完成各种任务,但是当配置一些复杂任务时,逐条输入就显得效率非常低下。
更有效的方案是在playbook配置文件中放置所有的任务代码,利用ansible-playbook命令执行该文件,可以实现自动化运维。YAML文件的扩展名通常为.yaml或.yml。
核心元素
首先介绍剧本的核心元素,编写一个简单的yml文件能更清楚明了的说明:
列出主机列表,确认无误
[root@ansible /]# grep -v ^# /etc/ansible/hosts |grep -v ^$ [web1] 192.168.26.2 192.168.26.3 [web2] 192.168.26.4
编写剧本文件
[root@ansible /]# vi /etc/ansible/test.yml --- - hosts: web1 <!--针对web1组中的操作--> remote_user: root <!--远端执行用户身份为root--> tasks: <!--任务列表--> - name: "创建组" <!--任务名称--> group: name=wlclass system=yes <!--执行group模块,创建组--> tags: group <!--创建tag标签--> - name: "创建用户" user: name=wl1 state=present password=123456 group=wlclass tags: user - hosts: web2 remote_user: root tasks: - name: "传输文件" copy: src=/data/test.txt dest=/data tags: file
实现的效果:在web1组中创建wlclass组并创建wl1用户添加至该组;在web2组中将ansible服务器中的test.txt文件传输至web2组的data文件夹内
按照剧本文件开始介绍核心元素
- hosts: 任务的目标主机,多个主机用冒号分隔,一般调用/etc/ansible/hosts中的分组信息;
- remote_user:远程主机上,运行此任务的默认身份为root;
- tasks: 任务,即定义的具体任务,由模块定义的操作列表;
- handlers: 触发器,类似tasks,只是在特定的条件下才会触发的任务。某任务的状态在运行后为changed时,可通过“notify”通知给相应的handlers进行触发执行;
- roles: 角色,将hosts剥离出去,由tasks、handlers等所组成的一种特定的结构集合;
剧本用法
playbook文件定义的任务需要通过ansible-playbook命令进行调用并执行。ansible-playbook命令用法如下:
ansible-playbook [option] [yml]
常用选项:
- –syntax-check: 检测yaml文件的语法;
- -C(—check): 预测试,不会改变目标主机的任何设置;
- –list-hosts: 列出yaml文件影响的主机列表;
- –list-tasks: 列出yaml文件的任务列表;
- –list-tags: 列出yaml文件中的标签;
- -t TAGS(—tags=TAGS): 表示只执行指定标签的任务;
- –skip-tags=SKIP_TAGS: 表示除了指定标签的任务,执行其他任务;
- –start-at-task=START_AT: 从指定的任务开始往下运行;
示例:
检查语法是否有问题
[root@ansible /]# ansible-playbook --syntax-check /etc/ansible/test.yml playbook: /etc/ansible/test.yml 这样子表示就没有问题
执行任务!!!
[root@ansible /]# ansible-playbook /etc/ansible/test.yml
列出剧本内的主机
[root@ansible /]# ansible-playbook --list-hosts /etc/ansible/test.yml playbook: /etc/ansible/test.yml play #1 (web1): web1 TAGS: [] pattern: ['web1'] hosts (2): 192.168.26.2 192.168.26.3 play #2 (web2): web2 TAGS: [] pattern: ['web2'] hosts (1): 192.168.26.4
触发器
需要触发才能执行的任务,当之前定义在tasks中的任务执行成功后,若希望在此基础上触发其他任务,这时就需要定义handlers。例如,当通过ansible的模块对目标主机的配置文件进行修改之后,如果任务执行成功,可以触发一个触发器,在触发器中定义目标主机的服务重启操作,以使配置文件生效。handlers触发器具有以下特点:
- handlers是Ansible提供的条件机制之一。
- handlers和task很类似,但是它只在被task通知的时候才会触发执行。
- handlers只会在所有任务执行完成后执行。
- 而且即使被通知了很多次,它也只会执行一次。
- handlers按照定义的顺序依次执行。
示例
监听一下web1组80端口
[root@ansible /]# ansible web1 -m shell -a "netstat -anpt |grep 80" 192.168.26.3 | CHANGED | rc=0 >> tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 192.168.26.2 | CHANGED | rc=0 >> tcp6 0 0 :::80 :::* LISTEN
可以看出两台机都处于80端口监听状态,接下来开始编写yml剧本,用触发器使得web1组的httpd默认监听8080端口
[root@ansible /]# vi /etc/ansible/web1.yml --- - hosts: web1 remote_user: root tasks: - name: "修改端口" shell: sed -i 's/Listen\ 80/Listen\ 8080/g' /etc/httpd/conf/httpd.conf notify: <!--配置触发条件--> - restart httpd <!--完成该任务后调用名为“restart httpd”的触发器--> handlers: <!--配置触发器--> - name: restart httpd <!--触发器名称为“restart httpd”--> service: name=httpd state=restarted <!--触发任务为重启httpd服务-->
检查语法
[root@ansible /]# ansible-playbook --syntax-check /etc/ansible/web1.yml
执行脚本
[root@ansible /]# ansible-playbook /etc/ansible/web1.yml
监听一下8080端口查看是否成功
[root@ansible /]# ansible web1 -m shell -a "netstat -anpt |grep 8080" 192.168.26.3 | CHANGED | rc=0 >> tcp6 0 0 :::8080 :::* LISTEN 23728/httpd 192.168.26.2 | CHANGED | rc=0 >> tcp6 0 0 :::8080 :::* LISTEN 19886/httpd 成功,8080端口都起来了
角色
roles目录结构
将多种不同的tasks的文件集中存储在某个目录下,则该目录就是角色。角色一般存放在 /etc/ansible/roles/ 目录,可通过ansible的配置文件来调整默认的角色目录,/etc/ansible/roles/ 目录下有很多子目录,其中每一个子目录对应一个角色,每个角色也有自己的目录结构,如下图所示:
/etc/ansible/roles/为角色集合,该目录下有自定义的各个子目录:
- mariadb:mysql角色;
- Apache:httpd角色;
- Nginx:Nginx角色;
Roles各目录作用
每个角色的定义,以特定的层级目录结构进行组织。以mariadb(mysql角色)为例:
- files: 存放由copy或script等模块调用的文件;
- templates: 存放template模块查找所需要的模板文件的目录,如mysql配置文件模板;
- tasks: 任务存放的目录;
- handlers: 存放相关触发执行的目录;
- vars: 变量存放的目录;
- meta: 用于存放此角色元数据;
- default: 默认变量存放的目录,文件中定义了此角色使用的默认变量;
上述目录中,tasks、handlers、vars、meta、default至少应该包含一个main.yml文件,该目录下也可以有其他.yml文件,但是需要在main.yml文件中用include指令将其他.yml文件包含进来。
创建 role
- 创建以roles命名的目录
- 在roles目录中分别创建以各角色名称命名的目录,如webservers等
- 在每个角色命名的目录中分别创建files、handlers、meta、tasks、templates和vars目录;用不到的目录可以创建为空目录,也可以不创建
- 在playbook文件中,调用各角色
范例:roles的目录结构
nginx-role.yml roles/ └── FTP ├── files │ └── main.yml ├── tasks │ ├── groupadd.yml │ ├── install.yml │ ├── main.yml │ ├── restart.yml │ └── useradd.yml └── vars └── main.yml
playbook调用角色
编辑yml文件
[root@ansible /]# vi /etc/ansible/test2.yml --- - hosts: web1 remote_user: root roles: <!--调用角色名--> - mysql - nginx - ftp
项目实战
实现httpd角色
[root@ansible /]# mkdir -p /etc/ansible/roles/httpd/{tasks,handlers,files} 创建角色相关记录 [root@ansible /]# cd /etc/ansible/roles/httpd/
配置http模板
[root@ansible httpd]# vi files/test.conf <virtualhost *:80> documentroot /web/web1 servername 192.168.26.2 <Directory "/web/web1"> Require all granted </virtualhost> <virtualhost *:80> documentroot /web/web2 servername 192.168.26.3 <Directory "/web/web2"> Require all granted </virtualhost> :wq
配置网页文件
[root@ansible httpd]# vi files/index1.html web1 :wq [root@ansible httpd]# vi files/index2.html web2 :wq
编写剧本
[root@ansible httpd]# vi tasks/main.yml - include: group.yml - include: user.yml - include: install.yml - include: config.yml - include: index.yml - include: service.yml :wq [root@ansible httpd]# vi tasks/user.yml - name: "创建用户" user: name=apache system=yes shell=/sbin/nologin home=/home/ uid=80 group=apache :wq [root@ansible httpd]# vi tasks/group.yml - name: "创建用户组" group: name=apache system=yes gid=80 :wq [root@ansible httpd]# vi tasks/install.yml - name: "安装http服务" yum: name=httpd :wq [root@ansible httpd]# vi tasks/config.yml - name: "传输配置文件" copy: src=test.conf dest=/etc/httpd/conf.d/test.conf backup=yes notify: restart :wq [root@ansible httpd]# vi tasks/index.yml - name: "创建目录1" file: path=/web/web1 state=directory - name: "创建目录2" file: path=/web/web2 state=directory - name: "传输网页1" copy: src=index1.html dest=/web/web1/index.html - name: "传输网页2" copy: src=index2.html dest=/web/web2/index.html :wq [root@ansible httpd]# vi tasks/service.yml - name: "启动服务" service: name=httpd state=started enabled=yes :wq [root@ansible httpd]# vi handlers/main.yml - name: restart service: name=httpd state=restarted :wq #检查文件目录 [root@ansible httpd]# tree /etc/ansible/roles/httpd/ /etc/ansible/roles/httpd/ ├── files │ ├── test.conf │ ├── index1.html │ └── index2.html ├── handlers │ └── main.yml └── tasks ├── config.yml ├── group.yml ├── index.yml ├── install.yml ├── main.yml ├── service.yml └── user.yml 3 directories, 10 files #在playbook中调用角色 [root@ansible httpd]# vi /etc/ansible/role_httpd.yml --- - hosts: web1 remote_user: root roles: - httpd :wq
检查语法
[root@ansible tasks]# ansible-playbook --syntax-check /etc/ansible/role_httpd.yml playbook: /etc/ansible/role_httpd.yml
执行脚本
[root@ansible tasks]# ansible-playbook /etc/ansible/role_httpd.yml PLAY [web1] ******************************************************************** TASK [Gathering Facts] ********************************************************* ok: [192.168.26.2] ok: [192.168.26.3] TASK [httpd : 创建用户组] *********************************************************** changed: [192.168.26.3] changed: [192.168.26.2] TASK [httpd : 创建用户] ************************************************************ changed: [192.168.26.3] changed: [192.168.26.2] TASK [httpd : 安装http服务] ******************************************************** changed: [192.168.26.3] changed: [192.168.26.2] TASK [httpd : 传输配置文件] ********************************************************** changed: [192.168.26.3] changed: [192.168.26.2] TASK [httpd : 创建目录1] *********************************************************** changed: [192.168.26.2] changed: [192.168.26.3] TASK [httpd : 创建目录2] *********************************************************** changed: [192.168.26.3] changed: [192.168.26.2] TASK [httpd : 传输网页1] *********************************************************** changed: [192.168.26.3] changed: [192.168.26.2] TASK [httpd : 传输网页2] *********************************************************** changed: [192.168.26.3] changed: [192.168.26.2] TASK [httpd : 启动服务] ************************************************************ changed: [192.168.26.2] changed: [192.168.26.3] RUNNING HANDLER [httpd : restart] ********************************************** changed: [192.168.26.2] changed: [192.168.26.3] PLAY RECAP ********************************************************************* 192.168.26.2 : ok=11 changed=10 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 192.168.26.3 : ok=11 changed=10 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 [root@ansible httpd]#
访问测试,成功
厉害呀