ansible批量部署mysql
创建role
Roles各目录作用
roles/project/:项目名称,有以下子目录
files/:存放由copy或script模块等调用的文件
templates/:temple模块查找所需要模块文件的目录
tasks/:定义task,role的基本元素,至少应该包含一个名为main.yml的文件,其他文件需要在此文件中通过include进行包含
handlers/:至少应该包含一个名为main.yml的文件,其他文件需要在此文件中通过include进行包含
vars/:定义变量,至少应该包含一个名为main.yml的文件,其他的文件需要在此文件中通过include进行包含
meta/:定义当前角色的特殊设定以及其依赖关系,至少应该包含一个名为main.yml的文件,其他文件需要通过include进行包含
default/:设定默认变量时使用此目录的main.yml文件,比vars的优先地
创建role的步骤
(1)创建以roles命名的目录
(2)在roles目录中分别创建以角色名称命令的目录,如webservers等
(3)在每个角色的目录中分别创建files、handlers、meta、tasks、templates和vars目录;用不到的目录可以创建为空目录,但是不可以不创建
(4)在playbook文件中,调用各角色
针对大型项目使用Roles进行编排
条件判断循环
循环类型 关键字
标准循环 with_items
嵌套循环 with_nested
遍历字典 with_dict
并行遍历列表 with_together
遍历列表和索引 with_indexed_items
遍历文件列表的内容 with_file
遍历目录文件 with_fileglog
重试循环 until
查找第一个匹配文件 with_first_found
随机选择 with_random_choice
在序列中循环 with_sequence
种类一, 标准循环
---
- hosts: nginx
tasks:
- name: add serveral users
user: name={{ item.name }} state=present groups={{ item.groups }}
with_items:
- { name: 'testuser1',groups: 'wheel' }
- { name: 'testuser2',groups: 'root' }
种类二, 遍历字典
---
- hosts: nginx
remote_user: root
tasks:
- name: add serveral users
user: name={{ item.key }} state=present groups={{ item.value }}
with_dict:
{ 'testuser3':'wheel','testuser4':'root' }
种类三, 遍历目录中内容
---
- hosts: nginx
remote_user: root
tasks:
- file: dest=/tmp/aa state=directory
- copy: src={{ item }} dest=/tmp/bb owner=root mode=600
with_fileglob:
- aa/*n
条件语句结合循环语句使用场景,when的条件判断
---
- hosts: nginx
remote_user: root
tasks:
- debug: msg="{{ item.key }} is the winner"
with_dict: {'jeson':{'english':60,'chinese':30},'tom':{'english':20,'chinese':30}}
when: item.value.english >= 30 #满足条件才执行,不满足就跳过。
[root@ansible ~]# ansible-playbook when.yml
PLAY [dbserver] **************************************************************************************************
TASK [Gathering Facts] *******************************************************************************************
ok: [192.128.232.200]
TASK [debug] *****************************************************************************************************
ok: [192.128.232.200] => (item={u'key': u'jeson', u'value': {u'chinese': 30, u'english': 60}}) => {
"msg": "jeson is the winner"
}
skipping: [192.128.232.200] => (item={u'key': u'tom', u'value': {u'chinese': 30, u'english': 20}})
PLAY RECAP *******************************************************************************************************
192.128.232.200 : ok=2 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
异常处理
1.忽略错误
默认会检查命令和模块的返回状态,遇到错误就中断playbook的执行
加入参数: ignore_errors: yes
---
- hosts: nginx
remote_user: root
tasks:
- name: ignore false
command: /bin/false
ignore_errors: yes
- name: touch a file
file: path=/tmp/test22 state=touch mode=0700 owner=root group=root
如果你有一个很大的playbook,而你只想run其中的某个task,这个时候tags是你的最佳选择。
一、最常见的使用形式:
---
- hosts: nginx
remote_user: root
tasks:
- yum: name={{ item }} state=installed
with_items:
- httpd
- memcached
tags:
- packages
- template: src=templates/src.j2 dest=/etc/foo.conf
tags:
- configuration
#此时若你希望只run其中的某个task,这run 的时候指定tags即可
ansible-playbook example.yml --tags "configuration,packages" #run 多个tags
ansible-playbook example.yml --tags packages # 只run 一个tag
二、failed_when关键字
其实,还有另一种方法可以实现类似的效果,我们可以借助’failed_when’关键字来完成类似功能,
'failed_when’的作用就是,当对应的条件成立时,将对应任务的执行状态设置为失败,这样说可能不是特别容易理解,
不如先来看一个小示例,如下:
[root@server4 ~]# vim fail2.yml
[root@server4 ~]# cat fail2.yml
---
- hosts: testB
remote_user: root
tasks:
- debug:
msg: "I execute normally"
- shell: "echo 'This is a string for testing error'"
register: return_value
failed_when: ' "error" in return_value.stdout'
- debug:
msg: "I never execute,Because the playbook has stopped"
上例中,一共有三个任务,第一个任务通过debug模块输出 “I execute normally”,第二个任务调用shell模块,
echo了’This is a string for testing error’这句话,并且将返回值注册到了’return_value’变量中,
’ failed_when’关键字与shell关键字对齐,表示其对应的条件是针对shell模块的,’ failed_when’对应的条件是
’ “error” in return_value.stdout’,表示"error"字符串如果存在于shell模块执行后的标准输出中,则条件成立,
当条件成立后,shell模块的执行状态将会被设置为失败,由于shell模块的执行状态被设置为失败,所以playbook会终止运行,
于是,最后的debug模块并不会被执行
三. handlers 与 notify
可以理解成另一种tasks,handlers是另一种’任务列表‘,handlers的任务会被tasks中的任务进行”调用“,但是,
被”调用“并不意味着一定会执行,只有当tasks中的任务”真正执行“以后,handlers中被调用的任务才会执行,
如果tasks中的任务并没有做出任何实际的操作,那么handlers中的任务即使被’调用‘,也并不会执行。
handlers执行的顺序与handlers在playbook中定义的顺序是相同的
---
- name: test.yml just for test
hosts: testserver
vars:
region: ap-southeast-1
tasks:
- name: template configuration
template: src=template.j2 dest=/etc/foo.conf
notify:
- restart memcached
- restart apache
handlers:
- name: restart memcached
service: name=memcached state=restarted
- name: restart apache
service: name=apache state=restarted
1:添加主机
[root@ansible ~]# vi /etc/ansible/hosts
[dbserver]
192.128.232.200
2.创建roles角色 "mysql_install"
[root@ansible ~]# cd /etc/ansible/roles/
[root@ansible roles]# mkdir -p mysql_install/{default,files,handlers,meta,tasks,templates,vars}
3.下载安装包
[root@ansible roles]# cd mysql_install/files/
[root@ansible files]# wget https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.28-linux-glibc2.12-x86_64.tar.gz
4.创建mysql的配置模板
[root@ansible files]# vi /etc/ansible/roles/mysql_install/templates/my.cnf.j2
[mysql]
prompt="\u@\h [\d]>"
no-auto-rehash
default_character_set=utf8
[mysqld]
user=mysql
character_set_server = utf8
server-id = 26
open_files_limit = 65535
collation-server=utf8_general_ci
explicit_defaults_for_timestamp=true
datadir={{ data_dir }}
basedir={{ install_dir }}
port={{ mysql_port }}
symbolic-links=0
log-error=/data/mysql/logs/mysqld.log
pid-file=/data/mysql/run/mysqld.pid
max_connections=2000
max_allowed_packet=16M
#gtid
gtid_mode = ON
enforce_gtid_consistency = ON
############### slow log ###############
log-output=file
slow_query_log = 1
slow_query_log_file = /data/mysql/logs/slow.log
log_warnings = 2
long_query_time = 2
log-queries-not-using-indexes = 0
log-slow-slave-statements = 1
max_allowed_packet = 256M
############## binlog #################
binlog_format = row
log-bin = /data/mysql/logbin/mysql-bin
max_binlog_size = 524M
sync_binlog = 1
expire_logs_days = 7
#procedure
log_slave_updates = ON #只有开启log_slave_updates,从库binlog才会记录主库同步的操作日志。
#指定用于索引的缓冲区大小,增加它可得到更好的索引处理性能。
key_buffer_size = 256M
max_allowed_packet = 128M
table_open_cache = 3000
#查询排序时所能使用的缓冲区大小。注意:该参数对应的分配内存是每连接独占
sort_buffer_size = 16M
net_buffer_length = 64K
#读查询操作所能使用的缓冲区大小。和sort_buffer_size一样,该参数对应的分配内存也是每连接独享。
read_buffer_size = 16M
read_rnd_buffer_size = 16M
myisam_sort_buffer_size = 16M
##指定MySQL允许的最大连接进程数
max_connections=2000
interactive_timeout=300
#指定一个请求的最大连接时间,对于4GB左右内存的服务器可以设置为5-10。
wait_timeout=300
#指定MySQL查询缓冲区的大小。可以通过在MySQL控制台观察
query_cache_size=256M
##禁止MySQL对外部连接进行DNS解析,使用这一选项可以消除MySQL进行DNS解析的时间
skip_name_resolve
##联合查询操作所能使用的缓冲区大小,和sort_buffer_size一样,该参数对应的分配内存也是每连接独享。
join_buffer_size = 128M
thread_cache_size=1024
sql_mode=NO_ENGINE_SUBSTITUTION
tmp_table_size=2048M
max_heap_table_size=2048M
#############################################################################
[root@ansible files]# vi /etc/ansible/roles/mysql_install/templates/mysql_install.sh.j2
#!/bin/bash
INSTALL_DIR={{ install_dir }}
DATADIR={{ data_dir }}
SOURCE_DIR={{ source_dir }}
install_mysql(){
PASSWD='123456'
if [ ! -d $DATADIR ];then
mkdir -p $INSTALL_DIR/{data,run,logs,logbin}
fi
id mysql &>/dev/null
if [ $? -ne 0 ];then
useradd mysql -s /sbin/nologin -M
fi
#MySQL initialization and startup
cp -p $INSTALL_DIR/support-files/mysql.server /etc/init.d/mysqld
if [ -d $INSTALL_DIR/logs ];then
touch $INSTALL_DIR/logs/mysqld.log
touch $INSTALL_DIR/logs/slow.log
chown -R mysql:mysql $INSTALL_DIR/logs/
else
echo "No logs directory and mysqld.log file!"
exit $?
fi
chown -R mysql:mysql $INSTALL_DIR
chmod -R 755 $INSTALL_DIR
rm -f $DATADIR/*
$INSTALL_DIR/bin/mysqld --initialize --basedir=$INSTALL_DIR --datadir=$DATADIR --user=mysql
/etc/init.d/mysqld start
if [ $? -ne 0 ];then
echo "mysql start is failed!"
exit $?
fi
chkconfig --add mysqld
chkconfig mysqld on
root_pass=`grep 'temporary password' $INSTALL_DIR/logs/mysqld.log | awk '{print $11}'`
$INSTALL_DIR/bin/mysql --connect-expired-password -uroot -p$root_pass -e "alter user 'root'@'localhost' identified by '$PASSWD';"
if [ $? -eq 0 ];then
echo "+---------------------------+"
echo "+------mysql安装完成--------+"
echo "+---------------------------+"
fi
#add path
echo "export PATH=$PATH:$INSTALL_DIR/bin" >> /etc/profile
source /etc/profile
}
install_mysql
5.创建调用 "mysql_install"的roles的playbook文件
[root@ansible files]# vi /etc/ansible/roles/mysql_install.yml
- hosts: dbserver
remote_user: root
gather_facts: false
roles:
- mysql_install
6.创建变量vars定义文件
[root@ansible files]# vi /etc/ansible/roles/mysql_install/vars/main.yml
mysql_version: mysql-5.7.28-linux-glibc2.12-x86_64
install_dir: /data/mysql
data_dir: /data/mysql/data
source_dir: /tmp
mysql_port: 3306
7.创建任务文件
[root@ansible files]# vi /etc/ansible/roles/mysql_install/tasks/copy.yml
- name: 分发mysql安装包
copy: src={{ item }} dest={{ source_dir }}
with_fileglob:
- /etc/ansible/roles/mysql_install/files/*
- name: 分发mysql配置文件 my.cnf
template: src=my.cnf.j2 dest=/etc/my.cnf
- name: 分发mysql_install.sh 自动安装文件
template: src=mysql_install.sh.j2 dest={{ source_dir }}/mysql_install.sh
- name: 解压包mysql安装包,
unarchive:
src: /tmp/{{ mysql_version }}.tar.gz
dest: "{{ source_dir }}"
copy: no
- name: 移动mysql解压后的文件夹到指定位置,并重新命名
shell: "mv {{ source_dir }}/{{ mysql_version }} {{ install_dir }}"
8.创建mysql的安装任务文件
[root@ansible files]# vi /etc/ansible/roles/mysql_install/tasks/install.yml
- name: install mysql
shell: bash {{ source_dir }}/mysql_install.sh
9.创建tasks的main.yml文件,定义任务执行顺序。
[root@ansible files]# vi /etc/ansible/roles/mysql_install/tasks/main.yml
- include: copy.yml
- include: install.yml
10.检查playbook,是否有错误
[root@ansible roles]# ansible-playbook -C mysql_install.yml
PLAY [dbserver] **************************************************************************************************************
TASK [mysql_install : 分发mysql安装包] **************************************************************************************************************
changed: [192.128.232.200] => (item=/etc/ansible/roles/mysql_install/files/mysql-5.7.28-linux-glibc2.12-x86_64.tar.gz)
TASK [mysql_install : 分发mysql配置文件 my.cnf] **************************************************************************************************************
changed: [192.128.232.200]
TASK [分发mysql_install.sh 自动安装文件] **************************************************************************************************************
changed: [192.128.232.200]
#下面这行解压错误,是因为远程主机还没有安装包。所以提示安装包不存在,可以忽略。
TASK [mysql_install : 解压包mysql安装包] **************************************************************************************************************
fatal: [192.128.232.200]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "msg": "Source '/tmp/mysql-5.7.28-linux-glibc2.12-x86_64.tar.gz' does not exist"}
PLAY RECAP **************************************************************************************************************
192.128.232.200 : ok=3 changed=3 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
11.执行playbook
[root@ansible roles]# ansible-playbook mysql_install.yml
PLAY [dbserver] **************************************************************************************************************
TASK [mysql_install : 分发mysql安装包] **************************************************************************************************************
changed: [192.128.232.200] => (item=/etc/ansible/roles/mysql_install/files/mysql-5.7.28-linux-glibc2.12-x86_64.tar.gz)
TASK [mysql_install : 分发mysql配置文件 my.cnf] **************************************************************************************************************
changed: [192.128.232.200]
TASK [分发mysql_install.sh 自动安装文件] **************************************************************************************************************
changed: [192.128.232.200]
TASK [mysql_install : 解压包mysql安装包] **************************************************************************************************************
changed: [192.128.232.200]
TASK [mysql_install : 移动mysql解压后的文件夹到指定位置,并重新命名] **************************************************************************************************************
changed: [192.128.232.200]
TASK [mysql_install : install mysql] **************************************************************************************************************
changed: [192.128.232.200]
PLAY RECAP **************************************************************************************************************
192.128.232.200 : ok=6 changed=6 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
12.去192.128.232.200主机上,查看安装mysql是否成功
[root@hdss7-22 ~]# ps -ef |grep mysql
root 51985 1 0 16:43 ? 00:00:00 /bin/sh /data/mysql/bin/mysqld_safe --datadir=/data/mysql/data --pid-file=/data/mysql/run/mysqld.pid
mysql 52658 51985 0 16:43 ? 00:00:02 /data/mysql/bin/mysqld --basedir=/data/mysql --datadir=/data/mysql/data --plugin-dir=/data/mysql/lib/plugin --user=mysql --log-error=/data/mysql/logs/mysqld.log --open-files-limit=65535 --pid-file=/data/mysql/run/mysqld.pid --port=3306
root 53466 29864 0 17:06 pts/0 00:00:00 grep --color=auto mysql
[root@hdss7-22 ~]# ss -lnt |grep 3306
LISTEN 0 128 [::]:3306 [::]:*