概览
掌握Ansible一些基础模块以及一些高级用法,再配合简单的Ansible复用知识,我们已经能管理一些基础的服务。不过如果我们决定生产环境服务部署全套都通过Ansible来管理,那么简单靠上面这些知识去组织Ansible Playbook目录结构是比较乱的,搞不好类似俄罗斯套娃那样,一层又一层,没什么规律,难以维护。组织管理大批量playbook,这就需要用到Ansible Roles
一个简单易上手的实例
Ansible Roles本身并没有引入太多新的知识,相当于一套合理的组织我们的playbook的方式,事实上在Ansible Roles没有出现之前,很多人已经开始形成自己的playbook组织方式,后来Ansible推出了Roles功能,这就有了统一的规范
# https://gitee.com/as4k/ysansible/tree/master/lamp_simple_rhel7
➜ ysansible git:(master) tree lamp_simple_rhel7
lamp_simple_rhel7
├── group_vars
│ ├── all
│ └── dbservers
├── hosts
├── roles
│ ├── common
│ │ ├── handlers
│ │ │ └── main.yml
│ │ ├── tasks
│ │ │ └── main.yml
│ │ └── templates
│ │ └── ntp.conf.j2
│ ├── db
│ │ ├── handlers
│ │ │ └── main.yml
│ │ ├── tasks
│ │ │ └── main.yml
│ │ └── templates
│ │ └── my.cnf.j2
│ └── web
│ ├── tasks
│ │ ├── copy_code.yml
│ │ ├── install_httpd.yml
│ │ └── main.yml
│ └── templates
│ └── index.php.j2
└── site.yml
观察上面的目录结构,我们看到有一个hosts
文件,这个是主机清单,为方便测试我们直接放到当前文件夹,使用-i
参数即可指定主机清单文件
site.yml
这份playbook是入口文件,里面调用了相关角色,执行该playbook的方法是,移动到当前目录,并执行下面的命令
ansible-playbook -i hosts site.yml --limit 192.168.31.101
我们前面讲过的 主机变量和组变量 Host and Group variables ,在这里依然适用
├── group_vars #该目录名字是固定的,位置和主机清单在同一个目录
│ ├── all #all表示所有分组(即所有机器)都可使用的变量
│ └── dbservers #分组是dbservers可以使用的变量
roles里面的目录结构相似,每一个目录名表示一个角色,目录名既可以认为是角色名称,我们举一个例子来说
├── roles #该目录固定
│ ├── common #角色名称,可以任意起
│ │ ├── handlers #该目录固定
│ │ │ └── main.yml #该文件名固定,里面专门存放需要触发执行的操作,在tasks/main.yml可直接使用
│ │ ├── tasks #该目录固定
│ │ │ └── main.yml #该文件名固定,是一个角色的入口,角色其它资源都从这里调用,里面的内容跟普通的playbook一样,不过可以看到已经没有类似匹配主机这样的,已经被抽出去的指令了
│ │ └── templates #该目录固定,里面存放的都是模板原始文件,在tasks/main.yml可直接使用
│ │ └── ntp.conf.j2 #模板文件
有了上面这些文字对目录结构的解释,如果大家也有仔细去看每个文件里的内容,相信上面这套playbook(其中包含角色)的功能已经很清晰了,即安装LHMP(httpd、mysql、php)
上面的角色服务我已在CentOS7执行验证过,大家也可以自己操作去看看 Ansible的角色、主机清单位置都可以在配置文件中配置,这个我们后面说
大家如果成功执行上面的playbook,基本对Ansible角色有个初步的概念了,可以看到角色本身并没有多少内容要学习,要想读懂、用好一套使用角色来书写的playbook服务,更多的还是要熟悉相关的模块、模板等这些playbook本身的内容
Ansible Roles非常重要,一坨playbook堆在一块没有用角色管理、复用起来,那基本没法维护了,也非常不专业
角色目录结构
上面我们列举了一个简单的Ansible实例,可以看到从形式上来说,Ansible Roles就是一套行之有效的目录结构,目录的名称和目录的第一个文件main.yml
都是固定的,本质来就是定义了一套通用的规范,来帮助我们更好的复用playbook
那么我们不仅想找到,一共有哪些目录我们可以用?使用下面的命令可以直接生成一份完整的Ansible Roles模板
[root@192_168_31_106 /tmp/xtest]# ansible-galaxy init my_role_name
- Role my_role_name was created successfully
[root@192_168_31_106 /tmp/xtest]# tree my_role_name/
my_role_name/
├── defaults
│ └── main.yml #这里放变量,这里的变量优先级最低
├── files #放普通文件,如脚本文件等
├── handlers
│ └── main.yml #顾名思义,handlers放这里
├── meta
│ └── main.yml #定义了一些元数据信息,方便在ansible galaxy上分享
├── README.md
├── tasks
│ └── main.yml #入口文件
├── templates #模板文件
├── tests #顾名思义,测试用
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml #这里也是放变量,这里的变量优先级比较高,通常是我们不希望被轻易改动的变量
8 directories, 8 files
上面的目录是最全的,如果说最小的话拥有一个tasks目录即可 ansible galaxy是官方提供的存放roles的仓库,方便大家分享,我们后面还会说到 vars/main.yml 与 defaults/main.yml 都可以存放变量,它们的区别不是强制性的,只是一般惯例
角色搜索路径
- 去
roles
目录里找(相对于当前playbook) - 去
/etc/ansible/roles
目录里找(可以改动配置文件修改)
继续上实例
https://gitee.com/as4k/ysansible/tree/master/wordpress-nginx-rhel7
https://gitee.com/as4k/ysansible/tree/master/geerlingguy_nginx/roles/nginx
#这两个实例,都是我亲测,可以在CentOS7上执行的
生产环境playbook目录架构
如果我们准备把公司全套的软件部署、更新,全都通过Ansible管理,显然我们需要有一个整体的目录规划,不能随意的写一个playbook,加几个文件直接就跑,这样时间一常基本就无法维护
首先我们得使用代码管理工具,如git,全面对Ansible的playbook等资源文件进行管理,每次先提交git,再执行部署,这样我们后人或者说过一段时间我们自己只要检查类似git log
,即可了解自己之前干了啥,改了什么东西,从而方便问题的定位和追踪
对于太大的二进制文件,尽量做成RPM包,或者放到专门的地方管理
关于规划我们Ansible Playbook的目录结构,最根本的问题是解决,资源合理复用的问题,比如在很多企业里,拿到一台新机器,都要进行初始化,都需要配置一些很基础的操作,诸如SSH配置、软件仓库配置、相关用户创建、定时任务时间同步等,这一类操作显然需要抽象出来单独放到一个roles里,以供其它playbook调用
在定义一个角色供后面的playbook复用的时候,我们需要考虑这个角色的功能哪些可以变动,哪些不能变动,用编程语言来说,就是暴露出哪些接口给用户使用,比如我们定义一个角色用来安装docker,为保证统一我们把docker的版本号做成变量,放到vars/main.yml
里,含义就是docker版本号,尽量不要改动,而把docker的数据存放目录,也定义为一个变量,放到defaults/main.yml
,表示这里的变量可以被覆盖
回顾前面我们讲到的
角色目录结构
,介绍了每个角色每个目录大致的功能
下面我们看下,整体的一个目录结构参考
#https://gitee.com/as4k/ysansible/tree/master/nginx_core
#这是nginx官方提供的,nginx Ansible 部署
➜ ysansible git:(master) tree -L 2 nginx_core
nginx_core
├── LICENSE
├── README.md
├── docs
├── playbooks #这里的playbook,去调用roles目录里的角色
│ ├── deploy-nginx-app-protect.yml
│ ├── deploy-nginx-plus-app-protect-web-server-proxy.yml
│ ├── deploy-nginx-plus-app-protect.yml
│ ├── deploy-nginx-plus.yml
│ ├── deploy-nginx-web-server-proxy.yml
│ ├── deploy-nginx-web-server.yml
│ └── deploy-nginx.yml
├── plugins
└── roles
├── nginx
├── nginx_app_protect
└── nginx_config
我们再来看下,具体一个playbook如何引入变量,去覆盖默认值,已达到更好的复用角色
# cat deploy-nginx-app-protect.yml
---
- hosts: all
roles:
- role: nginx_app_protect
vars:
nginx_app_protect_license:
certificate: <path/to/certificate>
key: <path/to/key>
nginx_app_protect_remove_license: false
nginx_app_protect_install_signatures: true
nginx_app_protect_install_threat_campaigns: true
nginx_app_protect_configure: true
nginx_app_protect_security_policy_template_enable: true
nginx_app_protect_security_policy_enforcement_mode: blocking
nginx_app_protect_log_policy_template_enable: true
nginx_app_protect_log_policy_filter_request_type: all
nginx_app_protect_conf_template_enable: false
再来看一份完整的全目录架构参考
inventories/
production/
hosts # inventory file for production servers
group_vars/
group1.yml # here we assign variables to particular groups
group2.yml
host_vars/
hostname1.yml # here we assign variables to particular systems
hostname2.yml
staging/
hosts # inventory file for staging environment
group_vars/
group1.yml # here we assign variables to particular groups
group2.yml
host_vars/
stagehost1.yml # here we assign variables to particular systems
stagehost2.yml
library/
module_utils/
filter_plugins/
playbooks/
site.yml
webservers.yml
dbservers.yml
roles/
common/
webtier/
monitoring/
fooapp/
Ansible Pull 工作模式
Ansible 默认工作模式是Push,即主机通过SSH远程推送相关资源到目标机器,目标机器执行
具体示例参考如下:
*/20 * * * * root /usr/local/bin/ansible-pull -o -C 2.1.0 -d /srv/www/king-gw/ -i /etc/ansible/hosts -U git:// git.kingifa.com/king-gw-ansiblepull >> /var/log/ansible-pull.log 2>&1
ansible-pull通常在配置大批量机器的场景下会使用,灵活性稍有欠缺,但效率几乎可以无限提升,对运维人员的技术水平和前瞻性规划有较高要求
参考资料
https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse_roles.html
https://docs.ansible.com/ansible/latest/user_guide/playbooks_reuse.html
https://docs.ansible.com/ansible/latest/user_guide/sample_setup.html
https://docs.ansible.com/ansible/latest/cli/ansible-pull.html
https://medium.com/splunkuserdeveloperadministrator/using-ansible-pull-in-ansible-projects-ac04466643e8
https://github.com/vincesesto/ansible-pull-example