ansible的高级应用-roles
在之前我们知道了playbook,类似于shell的脚本,playbook适用于一些不太麻烦的部署任务,比如说使用playbook安装mysql,那么我们直接写一个playbook文件即可。可是如果我们还要搭建mysql的主从架构呢?一个playbook就会显得会力不从心,这个时候我们可以使用roles。roles就是有相互关联功能的集合。相对于playbook,roles更适合于大项目的编排和架构。
在使用roles之前,简单说明一下include的用法,在playbook中可以引入另外的playbook脚本,这时候可以使用include命令。
- include test.yml
整体架构
roles主要依赖于目录命名和摆放,默认tasks/main.yml是所有任务的入口,所以使用roles的过程可以理解为目录规范化命名的过程。roles的目录架构是确定的,如下:
roles/ #roles目录下面存放对应的role
└── master_slave_mysql #目录名以role名命名,目录下面是每个role都包含的文件,若是对应的文件没有使用可以不创建
├── files #files用于文件传输,一些压缩包可以放在这里,在playbook中直接调用即可
├── handlers #role项目所有使用的handlers写在这里
├── tasks #主要的逻辑文件,也就是playbook文件执行的任务
├── templates #templates也用于文件的传输,但是这里的文件可以使用jija2模板语法,而files传输的文件不能使用jija2模板语法
└── vars #定义变量 #角色下面的每个文件中【files和templates目录下面不需要】,都必须需要一个main.yml文件,作为该模块的调度入口。而对应的逻辑文件可以写在对应的模块下面,
#然后在main.yml文件中使用include语句引入。
先来看一下一个完整role的所有目录结构:
[root@docker5 ~]# tree roles/
roles/
└── master_slave_mysql
├── files
│ ├── initmysql7.sh #MySQL安装的初始化脚本
│ └── mysql-5.7.-linux-glibc2.-x86_64.tar.gz #MySQL安装包
├── handlers
│ ├── all_handlers.yml #roles所有的handlers,若是所需handlers可以分多个文件写入,
│ └── main.yml #在main.yml文件使用include语句,引入所有的handlers文件
├── tasks #
│ ├── add_repl_user.yml #添加复制用户的playbook文件
│ ├── change_passwd.yml #MySQL5.7初始化后,需要修改密码,这里是修改密码的playbook文件
│ ├── install_mysql.yml #安装mysql的playbook
│ ├── main.yml #在main中引入对应的playbook,注意引入的顺序
│ └── set_replication.yml #配置主从复制的playbook
├── templates
│ ├── my.cnf.j2 #MySQL的配置文件模板
│ ├── test.retry #后面这两个是我测试的时候的文件,不用管
│ └── test.yml
└── vars #定义变量
└── main.yml #定义变量文件,也可以单独写成playbook的形式,然后再引入,因为这里变量比较少,就直接写入了main.yml directories, files
在和roles同级目录的结构中,我们还需要定义个yml文件,作为项目的调度入口。
[root@docker5 ~]# cat site.yml
---
# 该项目的调度入口
- hosts: all
remote_user: root roles:
- master_slave_mysql
[root@docker5 ~]# lsroles site.yml #执行的时候直接执行入口文件即可, 注意需要定义inventory文件。
[root@docker5 ~]# ansible-playbook site.yml
下面我们来一个个解析这个简单的项目。
inventory文件
默认是读取/etc/ansible/hosts中的内容,其内容如下:【需要说明的是,这里虽然定义了多个分组,但是在后面代码中没怎么使用】
[root@docker5 ~]# cat /etc/ansible/hosts
[all]
10.0.102.212
10.0.102.200
10.0.102.162 [master]
10.0.102.162 [slave]
10.0.102.200
10.0.102.212
files模块
这各模块主要用于文件的传输,这个项目中我们在里面放了一个初始化脚本和mysql5.7的安装包。初始化脚本就是一条很简单的命令,写在这里是为了说明files的用法。
初始化脚本如下:
[root@docker5 files]# cat !$
cat initmysql7.sh
#!/bin/bash
./bin/mysqld --user=mysql --datadir=/data/mysql --initialize
[root@docker5 files]# #在playbook中引用时,可以直接引用,而不是使用绝对路径
- name: copy the mysql install pkg
copy: src={{ install_pkg_name }}.tar.gz dest=/usr/local/src #src直接引用即可
- name: init mysql
script: chdir={{ basedir_name }} initmysql7.sh #执行这个脚本,而不是使用绝对路径
handlers模块
handlers的作用不再说明,这里只说明handlers在roles中的编排。
[root@docker5 files]# cd ../handlers/
[root@docker5 handlers]# ls
all_handlers.yml main.yml
[root@docker5 handlers]# cat all_handlers.yml #直接写入对应的handlers即可,
---
- name: start mysql
service: name=mysqld state=started - name: restart mysql
service: name=mysqld state=restarted - name: flush privileges
shell: chdir=/usr/local/mysql/bin ./mysql -u{{ login_user }} -p{{ login_passwd }} -e "flush privileges"
[root@docker5 handlers]# cat main.yml
---
- include: all_handlers.yml
---
- name: start mysql
service: name=mysqld state=started - name: restart mysql
service: name=mysqld state=restarted - name: flush privileges
shell: chdir=/usr/local/mysql/bin ./mysql -u{{ login_user }} -p{{ login_passwd }} -e "flush privileges"
all_handlers.yml
---
- include: all_handlers.yml
main.yml
tasks模块
tasks是roles主要的逻辑文件,所有的play都在这里执行,先来看一下main文件。
[root@docker5 tasks]# cat main.yml #包含了四个playbook文件,要注意文件的逻辑顺序
---
- include:
install_mysql.yml
change_passwd.yml
add_repl_user.yml
set_replication.yml
install_mysql.yml文件主要用来安装MySQL,拷贝配置文件并且启动mysql,内容如下。
---
- name: copy the mysql install pkg
copy: src={{ install_pkg_name }}.tar.gz dest=/usr/local/src - name: uncompress the pkg
unarchive: src=/usr/local/src/{{ install_pkg_name }}.tar.gz dest=/usr/local/ copy=no - name: create a soft link
#shell: ln -s /usr/local/{{ install_pkg_name }} /usr/local/mysql
file: src=/usr/local/{{ install_pkg_name }} dest={{ basedir_name }} state=link - name: create the mysql user
user: name={{ mysql_user }} - name: create the datadir
file: path={{ datadir_name }} state=directory owner={{ mysql_user }} group={{ mysql_user }} - name: init mysql
script: chdir={{ basedir_name }} initmysql7.sh - name: copy the manage script
shell: cp -p /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld - name: change the start script
#shell: sed -i "s/^datadir=/datadir=\/data\/mysql/" /etc/init.d/mysqld
replace: path=/etc/init.d/mysqld replace="datadir={{ datadir_name }}" regexp="^datadir=" backup=yes - name: copy the mysql config
template: src=my.cnf.j2 dest=/etc/my.cnf
notify:
- start mysql
install_mysql.yml
change_passwd.yml文件主要用来更改密码,因为MySQL5.7的密码属性,因此需要更改密码才能使用。这里没有使用ansible的相关模块,而是直接使用了sql命令。
---
- name: 设置数据库密码
shell: chdir={{ mysql_path }} ./mysql -e "update mysql.user set authentication_string=password("")" - name: 开启权限认证
replace:
path=/etc/my.cnf
regexp="^skip-grant-tables$"
replace="#skip-grant-tables"
notify:
restart mysql - name: 设置密码
shell: chdir={{ mysql_path }} ./mysql -uroot -p123456 --connect-expired-password -e 'alter user "root"@"localhost" identified by "123456"'
change_passwd.yml
add_repl_user.yml文件用来在master上添加复制用户,同样的也没有使用ansible相关的模块,而是使用了sql命令。
---
- name: add the user to replication
shell: chdir=/usr/local/mysql/bin ./mysql -uroot -p123456 -e 'grant all privileges on *.* to "repl"@"%" identified by "123456"'
notify:
flush privileges
when: ansible_eth0.ipv4.address == "10.0.102.162"
add_repl_user.yml
set_replication.yml文件用来在从上设置复制步骤,然后开启复制,这里使用了mysql_replication的模块。因为这里是全新的mysql,因此在change master时没有指定二进制日志名和日志位置点。
---
- name: Get the current master servers replication status
mysql_replication:
login_user=root
login_password=
login_unix_socket=/tmp/mysql.sock
mode=getmaster
register: repl_stat
when: ansible_eth0.ipv4.address == "10.0.102.162" - name: test
mysql_replication:
login_user={{ login_user }}
login_password={{ login_passwd }}
login_unix_socket={{ sock_path }}
mode=changemaster
master_host="10.0.102.162"
master_user="repl"
master_password=""
when: ansible_eth0.ipv4.address != "10.0.102.162" - name: start slave in slave to start the replication
mysql_replication:
login_user=root
login_password=
login_unix_socket=/tmp/mysql.sock
mode=startslave
when: ansible_eth0.ipv4.address != "10.0.102.162"
set_replication.yml
这个文件中的when语句可以换位委托语句delegate_to。另外需要说明的是when语句引用变量时会报如下错误:
[WARNING]: when statements should not include jinja2 templating delimiters such as {{ }} or {% %}. Found: ansible_eth0.ipv4.address == {{ master_host }}
fatal: [10.0.102.200]: FAILED! => {"msg": "The conditional check 'ansible_eth0.ipv4.address == {{ master_host }}' failed. The error was: error while evaluating conditional (ansible_eth0.ipv4.address == {{ master_host }}): float object has no element 102\n\nThe error appears to have been in '/root/roles/master_slave_mysql/tasks/set_replication.yml': line 2, column 4, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n---\n - name: Get the current master servers replication status\n ^ here\n"}
解决办法:http://blog.sina.com.cn/s/blog_704836f40102xbkt.html
就是把when后面的语句先用单引号括起来,里面对应的变量再使用双引号。
在这里应用的时候还有一个问题,如果在changge master的时候指定日子文件名和日志位置点,如下!我自己调用的时候总是报错。
- name: Change the master in slave to start the replication
mysql_replication:
login_user=root
login_password=
login_unix_socket=/tmp/mysql.sock
master_log_file={{ repl_stat.File }} #加上这两句,再执行的时候总是报错
master_log_pos={{ repl_stat.Position }}
mode=changemaster
master_host="10.0.102.162"
master_user="repl"
master_password=""
when: ansible_eth0.ipv4.address != "10.0.102.162" - name: start slave in slave to start the replication
mysql_replication:
login_user=root
login_password=
login_unix_socket=/tmp/mysql.sock
mode=startslave
when: ansible_eth0.ipv4.address != "10.0.102.162"
报错提示如下:【求哪位知道怎么解决了,告诉一下】
fatal: [10.0.102.200]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'dict object' has no attribute 'File'\n\nThe error appears to have been in '/root/roles/master_slave_mysql/tasks/set_replication.yml': line 16, column 4, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: test\n ^ here\n"}
报错提示
但是因为这里我们的mysql都是全新安装的,因此不需要指定日志名和日志位置掉,因此不需要加入这两句,也就没有报错。
templates模块
这个模块与files模块都可以用于文件传输,最大的不同是,templates可以使用jija2语法。譬如这里,我们使用这个模块传输mysql的配置文件,我们知道在主从集群中在主上需要开通二进制日志,并且三个服务器的server_id要不一样。这个时候如果我们使用files模块就需要三个不同的配置模板,而是用templates模块,则只需要一个配置模板即可。
[root@docker5 templates]# cat my.cnf.j2
[mysqld]
datadir={{ datadir_name }}
socket={{ sock_path }}
symbolic-links=
skip-grant-tables
server_id={{ ansible_eth0.ipv4.address| regex_search("([0-9]{1,3})$") }} {% if ansible_eth0.ipv4.address == master_host %}
log-bin=
{% endif %} [mysqld_safe]
log-error={{ datadir_name }}/{{ ansible_hostname }}.err
pid-file={{ datadir_name }}/mysql.pid
在templates模板中可以使用定义变量,在这个模板中我们定义了server_id为每个每个服务器ip地址的最后一部分【如果服务器跨网段,那么这个数字可能重复,但是这里是在同一网段的,因此数字是唯一的】
使用了if条件判断,判断若是当前主机ip和master对应主机相等,则设置log-bin参数,否则不设置。这就是一个简单的模板。
vars模块
vars模板主要是写入roles中定义的变量,当然变量也可以定义在inventory文件中。定义的变量最好加上注释性的说明,这样方便后续更改。
--- #数据库安装包的名字
install_pkg_name: mysql-5.7.-linux-glibc2.-x86_64 #初始化脚本的名字
init_mysql: initmysql.sh #mysql用户名
mysql_user: mysql #数据库数据目录
datadir_name: /data/mysql
basedir_name: /usr/local/mysql #mysql命令的绝对路径
mysql_path: /usr/local/mysql/bin/ #连接mysql的变量
login_user: root
login_passwd:
sock_path: /tmp/mysql.sock #服务器主机变量
master_host: "10.0.102.162"
slave1: "10.0.102.200"
slave2: "10.0.102.212"
设置完如上的文件之后,一个简单的roles已经完成。接下来直接只要设置好ssh认证,那么久可以执行。
ansible的高级应用-roles的更多相关文章
- Ansible Playbooks高级使用
文件操作 文件创建 file 用于设置文件/链接/目录的属性,或者删除文件/链接/目录 ### state如果是directory当目录不存在时会自动创建:如果是file当文件不存在时不会自动创建 - ...
- ansible入门六(roles)
一.什么场景下会用roles? 假如我们现在有3个被管理主机,第一个要配置成httpd,第二个要配置成php服务器,第三个要配置成MySQL服务器.我们如何来定义playbook? 第一个play用到 ...
- ansible学习笔记三:playbook和roles
参考博客: Ansible 系列之 Playbooks 剧本 -飞走不可(博客园) linux运维学习之ansible的playbook及roles的使用 - 51CTO博客 nginx 基于uwsg ...
- ansible安装配置及最佳实践roles
ansible是什么? ansible是一款轻量级配置管理工具,用于远程批量部署.安装.配置.类似的还有puppet.saltstack,各有所长,任君自选. 官方文档:http://docs.ans ...
- ansible roles 目录规范
我的ansible roles项目的目录结构: (ansible_venv) [root@localhost ansible_home]# tree ansible_playbooks/ ansibl ...
- Ansible Roles角色
Roles小技巧: 1.创建roles目录结构,手动或使用ansible-galaxy init test roles 2.编写roles的功能,也就是tasks. nginx rsyncd memc ...
- ansible roles 介绍和使用
目录 roles roles 介绍 创建role的步骤 role内个目录中可用的文件 案例 roles roles 介绍 ansible 自1.2版本引入的新特性,用于层次性.结构化地组织playbo ...
- Ansible的roles标准化与Jenkins持续集成(三)
Ansible的roles标准化与Jenkins持续集成(三) 链接:https://pan.baidu.com/s/1A3Iq3gGkGS27L_Gt37_I0g 提取码:ncy2 复制这段内容后打 ...
- Ansible安装配置Nginx
一.思路 现在一台机器上编译安装好nginx.打包,然后在用ansible去下发 cd /etc/ansible 进入ansible配置文件目录 mkdir roles/{common,install ...
随机推荐
- 后渗透神器Empire的简单使用
1.安装 1.1.系统环境: Debian系Linux:例如Ubuntu和Kali(本文使用Kali作为环境) 1.2.安装命令: 安装最后需要输入用户名.密码 wget https://raw.gi ...
- python DBUtils 线程池 连接 Postgresql(多线程公用线程池,DB-API : psycopg2)
一.DBUtils DBUtils 是一套允许线程化 Python 程序可以安全和有效的访问数据库的模块,DBUtils提供两种外部接口: PersistentDB :提供线程专用的数据库连接,并自动 ...
- python 接口自动化测试(五)其他-认证&代理&超时配置
有了前面几节的介绍,基本的接口测试是可以满足了.本节一些其它的高级技巧: 一.认证 1.基本认证: # -*- coding:utf-8 -*- import requests url = " ...
- Linux 的基本操作(初识linux)
linux世界 [Linux 系统启动过程] Linux的启动其实和windows的启动过程很类似,不过windows我们是无法看到启动信息的,而linux启动时我们会看到许多启动信息,例如某个服务是 ...
- Angel - MemoryDataBlock - angel.task.estimize.sample.number
angel.task.estimize.sample.number val validData = new MemoryDataBlock[LabeledData](isVali) trainData ...
- Python学习之旅(十)
Python基础知识(9):函数(Ⅰ) Python中函数的定义:是逻辑结构和过程化的一种编程方法 定义方法: def test(x): #def:定义函数的关键字 test:函数名 x:形参,也可以 ...
- ssm项目中KindEditor的图片上传插件,浏览器兼容性问题
解决办法: 原因:使用@ResponseBody注解返回java对象,在浏览器中是Content-Type:application/json;charset=UTF-8 我们需要返回字符串(Strin ...
- HTML、CSS知识点,面试开发都会需要--No.6 设置背景
No.6 设置背景 1.background (1)如何设置背景:背景可通过color.image.gradient渐变或者组合方法设置. (2)background-color:颜色格式可以是十六进 ...
- angularjs使用BUG收集和解决办法
此文章涉及到时1.X的版本.请注意! 1.关于checkbox和bootstrap不能选中BUG 在使用angularjs的时候,有个比较明显的bug ng-disabled无效的情况 这里是一种情况 ...
- 项目实战03:Keepalived 实现高可用
目录 实验一:实现keepalived主从方式高可用基于LVS-DR模式的应用实战: 1.环境准备: 2.在lvs-server-master 主上 3.在lvs-server-backup 从上 4 ...