Ansible 自动化运维工具简单入门(四)
五、roles基本使用
-
了解roles
ansible从1.2版本引入的新特性,用于层次型,结构化的组织playbook。roles能够根据层次型结构自动装在变量文件、tasks一级handles等,要使用roles只需要在playbook内增加include指令即可,简单的说,roles就是通过分别将变量、文件、任务、模板及处理器放置于单独的目录中,并可以便捷的include他们的一种机制。角色一般用于基于主机构建服务的场景,但也可以是用于构建守护进程的场景中(类似于用nginx.conf内的include xxx.conf ,比较灵活应用,可以多个YML调用一个,思想就是模块化)。(include已经过时,现在使用 来替代)
-
复杂场景:建议使用roles,代码复用率高
变更制定主机或者主机组
如命名不规范维护和传承成本大
某些功能需多个playbook,通过includes即可实现
-
语法
roles:角色集合
roles/ #文件夹,官方默认路径在 /etc/ansible/roles,习惯放在/root/roles
mysql/
httpd/
nginx/
redis/
1、单个角色编排
需求:部署nginx(默认yum安装会自带用户,此时为了演示roles功能,自己创建)
思路:1、用户 nginx 2、 组:nginx 用户加入组内,3、安装nginx包 4、配置文件模板 5、启动建议:roles文件夹和执行该roles的YML文件放在同级目录,roles内放tasks,files,templated,handlers等
#整个roles列表
[root@ansible ansible]# tree roles/
roles/
└── nginx
├── tasks
│ ├── group.yml #创建组任务
│ ├── main.yml #主程序,调用其余tasks
│ ├── restart.yml #重启任务
│ ├── templ.yml #复制模板任务
│ ├── user.yml #创建用户
│ ├── start.yml #开启服务
│ └── yum.yml #安装任务
└── templates
└── nginx.conf.j2
#group
[root@ansible tasks]# cat group.yml
- name: create group
group: name=nginx
#main
[root@ansible tasks]# cat main.yml
- include: group.yml
- include: user.yml
- include: yum.yml
- include: templ.yml
- include: start.yml
#restart
[root@ansible tasks]# cat restart.yml
- name: restart service
service: name=nginx state=restarted
#templ
[root@ansible tasks]# cat templ.yml
- name: copy conf
template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
#user
[root@ansible tasks]# cat user.yml
- name: create user
user: name=nginx group=nginx system=yes shell=/sbin/nologin
#yum
[root@ansible tasks]# cat yum.yml
- name: install
yum: name=nginx
#nginx.conf.j2
[root@ansible nginx]# vim templates/nginx.conf.j2
worker_processes {{ ansible_processor_vcpus+2 }};
#nginx_role.yml
[root@ansible ansible]# pwd
/root/ansible #该YML在于roles同级目录下
[root@ansible ansible]# vim nginx_role.yml
- hosts: web
remote_user: root
roles:
- role: nginx #制定role角色名,就是roles下的目录
#验证后执行
[root@ansible ansible]# ansible-playbook nginx_role.yml
[root@ansible ansible]# ansible web -m shell -a 'ps -ef|grep nginx'
172.16.111.8 | SUCCESS | rc=0 >>
root 43057 1 0 22:01 ? 00:00:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx 43058 43057 0 22:01 ? 00:00:00 nginx: worker process
nginx 43059 43057 0 22:01 ? 00:00:00 nginx: worker process
nginx 43060 43057 0 22:01 ? 00:00:00 nginx: worker process
nginx 43061 43057 0 22:01 ? 00:00:00 nginx: worker process
root 43113 43108 0 22:02 pts/0 00:00:00 /bin/sh -c ps -ef|grep nginx
root 43115 43113 0 22:02 pts/0 00:00:00 grep nginx
172.16.111.7 | SUCCESS | rc=0 >>
root 38645 1 0 22:01 ? 00:00:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx 38646 38645 0 22:01 ? 00:00:00 nginx: worker process
nginx 38647 38645 0 22:01 ? 00:00:00 nginx: worker process
nginx 38648 38645 0 22:01 ? 00:00:00 nginx: worker process
nginx 38649 38645 0 22:01 ? 00:00:00 nginx: worker process
root 38700 38695 0 22:02 pts/0 00:00:00 /bin/sh -c ps -ef|grep nginx
root 38702 38700 0 22:02 pts/0 00:00:00 grep nginx
#虚拟机为双核,j2文件中变量是把CPU个数+2 所以nginx用户进程是4个
以上为roles基本使用,思想就是模块化,把多个任务拆分,然后统一调用,比较灵活,日后如果需要其他role ,只需要将需要的配置文件拷贝适当修改就可以直接使用。
对于编译安装的程序,一般是在控制端编译安装好后打包调用copy模块发送到被控端然后解压执行即可
2、多个角色编排
增加一个httpd的角色,
思路 创建apache用户 yum安装httpd服务 启动服务
过程和上面nginx基本一样
(需要删除之前创建的nginx和apache用户,卸载nginx和httpd)
[root@ansible httpd]# ansible all -m shell -a 'yum remove httpd -y'
[root@ansible httpd]# ansible all -m shell -a 'userdel apache -r'
[root@ansible httpd]# ansible all -m shell -a 'yum remove nginx -y'
[root@ansible httpd]# ansible all -m shell -a 'userdel nginx -r'
[root@ansible httpd]# tree
.
├── files
│ └── httpd.conf #复制在文件放在tasks同级的files内,可以直接写文件名调用
└── tasks
├── copy.yml
├── main.yml
└── user.yml
#copy
[root@ansible tasks]# vim copy.yml
- name: copy files
copy: src=httpd.conf dest=/data/ owner=apache
如果两个不同功能的角色(此处只是为演示举例说明)都需要被调用 ,只需要在yml文件内roles内增加即可 类似字典
[root@ansible ansible]# vim test_roles1.yml
---
- hosts: web
remote_user: root
roles:
- role: httpd
- role: nginx
#测试执行验证 略
3、角色之间调用tasks
如果一个角色执行期间需要调用另外一个角色的任务
还是以上为基础,nginx的role需要调用httpd中的copy.yml任务
[root@ansible tasks]# pwd
/root/ansible/roles/nginx/tasks
[root@ansible tasks]# vim main.yml
- include: group.yml
- include: user.yml
- include: yum.yml
- include: templ.yml
- include: start.yml
- include: roles/httpd/tasks/copy.yml
#跨角色之间调用任务,只需要在main.yml文件内增加 - include: 后面加上该任务的路径,从roles开始
#执行后验证 注意执行的是nginx_role.yml
[root@ansible ansible]# ansible-playbook nginx_role.yml
[root@ansible ansible]# ansible web -m shell -a 'ls -l /data/httpd.conf'
172.16.111.7 | SUCCESS | rc=0 >>
-rw-r--r--. 1 apache root 11755 Oct 28 23:00 /data/httpd.conf
172.16.111.8 | SUCCESS | rc=0 >>
-rw-r--r--. 1 apache root 11755 Oct 28 23:00 /data/httpd.conf
4、根据tags标签选择性执行
可以很对不同角色加不同标签tags,标签可以都个 tags: ['tag1','tag2']
[root@ansible ansible]# vim test_roles2.yml
---
- hosts: web
remote_user: root
roles:
- role: { httpd,tags: ['web','httpd'] }
- role: { nginx,tags: ['web','nginx'] }
- role: { php, tags: 'php' } #需要提前创建,否则无法执行
[root@ansible ansible]# ansible-playbook -t web test_roles2.yml -C #-t制定标签执行
此时执行剧本的时候就可以选择性的执行标签,此时只会执行带有web标签的role
5、使用when来判断条件执行
[root@ansible ansible]# vim test_roles3.yml
---
- hosts: web
remote_user: root
roles:
- { role: httpd, tags: ['web','httpd'] }
- { role: nginx, tags: ['web','nginx'],when: nsible_hostname == "node3" }
- { role: php, tags: "php" }
#加入when判断条件
6、综合示例
综合以上模块,实现以下功能
创建php角色
创建用户名php uid10010
创建组php gid 10010
安装服务(使用httpd代替效果明显) httpd
启动服务
拷贝配置文件 :模板和copy两种
拷贝文件后出发handlers重启服务
准备工作
[root@ansible ansible]# tree roles/php/
roles/php/
├── files
│ └── file.conf.j2
├── handlers
│ └── main.yml
├── tasks
│ ├── copyfile.yml
│ ├── group.yml
│ ├── main.yml
│ ├── start.yml
│ ├── templ.yml
│ ├── user.yml
│ └── yum.yml
├── templates
│ └── httpd.conf.j2
└── vars
└── main.yml
# file.conf.j2为空文件,只为看效果
#注意handlers和vars下面的文件必须有一个main.yml文件 默认调用
#templates/httpd.conf.j2 修改模板文件
[root@ansible php]# vim templates/httpd.conf.j2
Listen {{ ansible_processor_vcpus+990 }} #调用setup自带变量端口=CPU数+990
User {{ username}} #调用变量username,在vars/main.yml内定义
Group {{ groupname}} #调用变量groupname,在vars/main.yml内定义
#vars/main.yml 定义变量
[root@ansible php]# vim vars/main.yml
username: php
groupname: php
#handlers/main.yml 触发器执行操作
[root@ansible php]# vim handlers/main.yml
- name: restart service
service: name=httpd state=restarted
#user.yml 创建用户
[root@ansible tasks]# vim user.yml
- name: create user
user: name=php group=php system=yes shell=/sbin/nologin uid=10010
#group.yml 创建组
[root@ansible tasks]# vim group.yml
- name: create group
group: name=php system=yes gid=10010
#yum.yml 安装软件
[root@ansible tasks]# vim yum.yml
- name: install php
yum: name=httpd
#start.yml 启动httpd并设置为开机自启动
[root@ansible tasks]# vim start.yml
- name: start service
service: name=httpd state=started enabled=true
#templ.yml 使用模板模块执行conf文件拷贝并使用notify触发器调用handlers
[root@ansible tasks]# vim templ.yml
- name: copy conf
template: src=httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
notify: restart service
#copyfile.yml 调用copy磨块实现文件拷贝,此处该文件file.conf没有实际用处,只为熟悉操作
[root@ansible tasks]# vim copyfile.yml
- name: copy file
copy: src=file.conf.j2 dest=/data/httpd1.conf onwer=php
#main.yml 主调用文件 调用其他模块 注意顺序
[root@ansible tasks]# vim main.yml
- include: group.yml
- include: user.yml
- include: yum.yml
- include: templ.yml
- include: copyfile.yml
- include: start.yml
#php_role.yml 调用角色
[root@ansible ansible]# vim php_role.yml
- hosts: web
remote_user: root
roles:
- php
#-C 测试 执行 查看端口 查看 文件是否复制 等
#根据进程查看
[root@ansible ansible]# ansible all -m shell -a 'ps -ef|grep httpd'
172.16.111.9 | SUCCESS | rc=0 >>
root 13556 13555 0 23:20 pts/0 00:00:00 /bin/sh -c ps -ef|grep httpd
root 13558 13556 0 23:20 pts/0 00:00:00 grep httpd
172.16.111.8 | SUCCESS | rc=0 >>
root 53970 1 0 00:34 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
php 53971 53970 0 00:34 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
php 53972 53970 0 00:34 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
php 53973 53970 0 00:34 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
php 53974 53970 0 00:34 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
php 53975 53970 0 00:34 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
root 54411 54406 0 00:35 pts/0 00:00:00 /bin/sh -c ps -ef|grep httpd
root 54413 54411 0 00:35 pts/0 00:00:00 grep httpd
172.16.111.7 | SUCCESS | rc=0 >>
root 50027 1 0 00:34 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
php 50028 50027 0 00:34 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
php 50029 50027 0 00:34 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
php 50030 50027 0 00:34 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
php 50031 50027 0 00:34 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
php 50032 50027 0 00:34 ? 00:00:00 /usr/sbin/httpd -DFOREGROUND
root 50465 50460 0 00:35 pts/0 00:00:00 /bin/sh -c ps -ef|grep httpd
root 50467 50465 0 00:35 pts/0 00:00:00 grep httpd
#根据服务查看端口
[root@ansible ansible]# ansible all -m shell -a 'netstat -lntup|grep httpd'
172.16.111.9 | FAILED | rc=1 >>
non-zero return code
172.16.111.8 | SUCCESS | rc=0 >>
tcp6 0 0 :::992 :::* LISTEN 53970/httpd
172.16.111.7 | SUCCESS | rc=0 >>
tcp6 0 0 :::992 :::* LISTEN 50027/httpd
#根据端口990+CPU个数查询
[root@ansible ansible]# ansible all -m shell -a 'lsof -i:992'
172.16.111.9 | FAILED | rc=1 >>
non-zero return code
172.16.111.7 | SUCCESS | rc=0 >>
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
httpd 50027 root 4u IPv6 356735 0t0 TCP *:telnets (LISTEN)
httpd 50028 php 4u IPv6 356735 0t0 TCP *:telnets (LISTEN)
httpd 50029 php 4u IPv6 356735 0t0 TCP *:telnets (LISTEN)
httpd 50030 php 4u IPv6 356735 0t0 TCP *:telnets (LISTEN)
httpd 50031 php 4u IPv6 356735 0t0 TCP *:telnets (LISTEN)
httpd 50032 php 4u IPv6 356735 0t0 TCP *:telnets (LISTEN)
172.16.111.8 | SUCCESS | rc=0 >>
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
httpd 53970 root 4u IPv6 375561 0t0 TCP *:telnets (LISTEN)
httpd 53971 php 4u IPv6 375561 0t0 TCP *:telnets (LISTEN)
httpd 53972 php 4u IPv6 375561 0t0 TCP *:telnets (LISTEN)
httpd 53973 php 4u IPv6 375561 0t0 TCP *:telnets (LISTEN)
httpd 53974 php 4u IPv6 375561 0t0 TCP *:telnets (LISTEN)
httpd 53975 php 4u IPv6 375561 0t0 TCP *:telnets (LISTEN)