ansible role zabbix相关话题
- 1. ansible 常用指令总结,并附有相关示例。
- 1.1 Ansible相关工具
- 1.1.1 ansible-doc
- 1.1.2 ansible 命令用法
- 1.1.3 ansible-console
- 1.1.4 ansible-playbook
- 1.1.5 ansible-vault
- 1.1.5 ansible-galaxy
- 2. 总结ansible playbook目录结构及文件用途。
- 2.1 Playbook 核心组件
- 2.1.1 hosts 组件
- 2.1.2 remote_user 组件
- 2.1.3 task列表和action组件
- 2.1.4 其它组件说明
- 2.1.5 ShellScripts VS Playbook 案例
- 3. 使用ansible playbook实现一个mysql角色。
- 3.1 目录结构
- 3.1.1 host
- 3.1.3 task
- 3.1.4 handlers
- 3.1.5 template
- 4. 基于角色完成部署LNMP架构,并支持一键发布,回滚应用。同时基于zabbix角色批量部署zabbix。
- 4.1 基于角色完成部署LNMP架构
- 4.1.1 目录结构
- 4.1.2 hosts信息
- 4.1.3 总入口yml文件信息
- 4.1.4 task代码
- 4.1.5 template文件内容
- 4.1.6 handlers文件内容
- 4.1.7 meta文件内容
- 4.1.8 开始展示安装WordPress
- 4.2 基于zabbix角色批量部署zabbix(依赖于原先部署好的LNMP)
- 4.2.1 zabbix_server、zabbix_agent2增加角色
- 4.2.2 host、role文件展示
- 4.2.3 task代码展示
- 4.2.4 最后template、handlers展示
- 4.2.5 执行展示
- 4.2.6 测试
1. ansible 常用指令总结,并附有相关示例。
1.1 Ansible相关工具
- /usr/bin/ansible 主程序,临时命令执行工具
- /usr/bin/ansible-doc 查看配置文档,模块功能查看工具,相当于man
- /usr/bin/ansible-playbook 定制自动化任务,编排剧本工具,相当于脚本
- /usr/bin/ansible-pull 远程执行命令的工具
- /usr/bin/ansible-vault 文件加密工具
- /usr/bin/ansible-console 基于Console界面与用户交互的执行工具
- /usr/bin/ansible-galaxy 下载/上传优秀代码或Roles模块的官网平台
利用ansible实现管理的主要方式:
- Ansible Ad-Hoc 即利用ansible命令,主要用于临时命令使用场景
- Ansible playbook 主要用于长期规划好的,大型项目的场景,需要有前期的规划过程
ansible 使用前准备
ansible 相关工具大多数是通过ssh协议,实现对远程主机的配置管理、应用部署、任务执行等功能
建议:使用此工具前,先配置ansible主控端能基于密钥认证的方式联系各个被管理节点
范例:利用sshpass批量实现基于key验证脚本1
vim /etc/ssh/ssh_config
#修改下面一行
StrictHostKeyChecking no
[root@centos8 ~]#cat hosts.list
10.0.0.18
10.0.0.28
[root@centos8 ~]#cat push_ssh_key.sh
#!/bin/bash
rpm -q sshpass &> /dev/null || yum -y install sshpass
[ -f /root/.ssh/id_rsa ] || ssh-keygen -f /root/.ssh/id_rsa -P ''
export SSHPASS=magedu
while read IP;do
sshpass -e ssh-copy-id -o StrictHostKeyChecking=no $IP
done < hosts.list
1.1.1 ansible-doc
此工具用来显示模块帮助,相当于man
格式
ansible-doc [options] [module…]
-l, --list #列出可用模块
-s, --snippet #显示指定模块的playbook片段
范例:
#列出所有模块
ansible-doc -l
#查看指定模块帮助用法
ansible-doc ping
#查看指定模块帮助用法
ansible-doc -s ping
范例: 查看指定的插件
[root@ansible ~]#ansible-doc -t connection -l
[root@ansible ~]#ansible-doc -t lookup -l
1.1.2 ansible 命令用法
格式:
ansible [-m module_name] [-a args]
选项说明:
--version #显示版本
-m module #指定模块,默认为command
-v #详细过程 -vv -vvv更详细
--list-hosts #显示主机列表,可简写 --list
-C, --check #检查,并不执行
-T, --timeout=TIMEOUT #执行命令的超时时间,默认10s
-k, --ask-pass #提示输入ssh连接密码,默认Key验证
-u, --user=REMOTE_USER #执行远程执行的用户,默认root
-b, --become #代替旧版的sudo实现通过sudo机制实现提升权限
--become-user=USERNAME #指定sudo的runas用户,默认为root
-K, --ask-become-pass #提示输入sudo时的口令
-f FORKS, --forks FORKS #指定并发同时执行ansible任务的主机数
-i INVENTORY, --inventory INVENTORY #指定主机清单文件
范例:
#以wang用户执行ping存活检测
ansible all -m ping -u wang -k
#以wang sudo至root执行ping存活检测
ansible all -m ping -u wang -k -b
#以wang sudo至mage用户执行ping存活检测
ansible all -m ping -u wang -k -b --become-user=mage
#以wang sudo至root用户执行ls
ansible all -m command -u wang -a 'ls /root' -b --become-user=root -k -K
范例: 并发执行控制
#分别执行下面两条命令观察结果
[root@ansible ~]#ansible all -a 'sleep 5' -f1
[root@ansible ~]#ansible all -a 'sleep 5' -f10
范例: 使用普能用户进行远程管理
#在所有控制端和被控制端创建用户和密码
[root@rocky8 ~]#useradd wang
[root@rocky8 ~]#echo wang:123456 | chpasswd
#在所有被控制端对用户sudo授权
[root@rocky8 ~]#visudo
wang ALL=(ALL) NOPASSWD: ALL
[root@rocky8 ~]#visudo -c
/etc/sudoers: parsed OK
#实现从控制端到被控制端的基于key验证
[root@ansible ~]#su - wang
wang@ansible:~$ssh-keygen -f ~/.ssh/id_rsa -P ''
wang@ansible:~$$ssh-copy-id wang@'10.0.0.8'
#使用普通用户测试连接,默认连接权限不足失败
wang@ansible:~$ ansible 10.0.0.8 -m shell -a 'ls /root'
10.0.0.8 | FAILED | rc=2 >>
ls: cannot open directory '/root': Permission deniednon-zero return code
#使用普通用户通过-b选项连接实现sudo提权后连接成功
wang@ansible:~$ ansible 10.0.0.8 -m shell -a 'ls /root' -b --become-user root
10.0.0.8 | CHANGED | rc=0 >>
anaconda-ks.cfg
#修改配置文件指定sudo机制
[root@ansible ~]#vim /etc/ansible/ansible.cfg
#取消下面行前面的注释
[privilege_escalation]
become=True
become_method=sudo
become_user=root
become_ask_pass=False
#再次测试
[root@ansible ~]#su - wang
wang@ansible:~$ ansible 10.0.0.8 -m shell -a 'ls /root'
10.0.0.8 | CHANGED | rc=0 >>
anaconda-ks.cfg
范例: 使用普通用户连接远程主机执行代替另一个用户身份执行操作
[root@centos8 ~]#useradd wang
[root@centos8 ~]#echo wang:123456 | chpasswd
#先在被控制端能过sudo对普通用户授权
[root@centos8 ~]#grep wang /etc/sudoers
wang ALL=(ALL) NOPASSWD: ALL
#以wang的用户连接用户,并利用sudo代表mage执行whoami命令
[root@ansible ~]#ansible 10.0.0.8 -m shell -a 'whoami' -u wang -k -b --becomeuser=mage
SSH password: #输入远程主机wang用户ssh连接密码
10.0.0.8 | CHANGED | rc=0 >>
mage
ansible的Host-pattern
用于匹配被控制的主机的列表
All :表示所有Inventory中的所有主机
范例
ansible all -m ping
*:通配符
ansible "*" -m ping
ansible 192.168.1.* -m ping
ansible "srvs" -m ping
ansible "10.0.0.6 10.0.0.7" -m ping
或关系
ansible "websrvs:appsrvs" -m ping
ansible "192.168.1.10:192.168.1.20" -m ping
逻辑与
#在websrvs组并且在dbsrvs组中的主机
ansible "websrvs:&dbsrvs" -m ping
逻辑非
#在所有主机,但不在websrvs组和dbsrvs组中的主机
#注意:此处为单引号
ansible 'all:!dbsrvs:!websrvs' -m ping
综合逻辑
ansible 'websrvs:dbsrvs:&appsrvs:!ftpsrvs' -m ping
正则表达式
ansible "websrvs:dbsrvs" -m ping
ansible "~(web|db).*\.magedu\.com" -m ping
范例:
[root@kube-master1 ~]#ansible 'kube*:etcd:!10.0.0.101' -a reboot && reboot
范例:
[root@centos8 ~]#ansible all --list-hosts
hosts (3):
10.0.0.6
10.0.0.7
10.0.0.8
[root@centos8 ~]#ansible websrvs --list-hosts
hosts (3):
10.0.0.6
10.0.0.7
10.0.0.8
[root@centos8 ~]#ansible appsrvs --list-hosts
hosts (2):
10.0.0.7
10.0.0.8
[root@centos8 ~]#ansible "appsrvs:dbsrvs" --list-hosts
hosts (3):
10.0.0.7
10.0.0.8
10.0.0.6
[root@centos8 ~]#ansible "dbsrvs" --list-hosts
hosts (2):
10.0.0.6
10.0.0.7
[root@centos8 ~]#ansible appsrvs --list-hosts
hosts (2):
10.0.0.7
10.0.0.8
[root@centos8 ~]#ansible "appsrvs:dbsrvs" --list-hosts
hosts (3):
10.0.0.7
10.0.0.8
10.0.0.6
[root@centos8 ~]#ansible "appsrvs:&dbsrvs" --list-hosts
hosts (1):
10.0.0.7
#引用!号时,不要用双引号,而使用单引号
[root@centos8 ~]#ansible "appsrvs:!dbsrvs" --list-hosts
-bash: !dbsrvs: event not found
[root@centos8 ~]#ansible 'appsrvs:!dbsrvs' --list-hosts
hosts (1):
10.0.0.8
ansible 命令的执行过程
- 加载自己的配置文件,默认/etc/ansible/ansible.cfg
- 查找主机清单中对应的主机或主机组
- 加载自己对应的模块文件,如:command
- 通过ansible将模块或命令生成对应的临时py文件,并将该文件传输至远程服务器的对应执行用户
$HOME/.ansible/tmp/ansible-tmp-数字/XXX.PY文件 - 给文件+x执行
- 执行并返回结果
- 删除临时py文件,退出
ansible 命令的执行状态
[root@centos8 ~]#grep -A 14 '\[colors\]' /etc/ansible/ansible.cfg
[colors]
#highlight = white
#verbose = blue
#warn = bright purple
#error = red
#debug = dark gray
#deprecate = purple
#skip = cyan
#unreachable = red
#ok = green
#changed = yellow
#diff_add = green
#diff_remove = red
#diff_lines = cyan
- 绿色:执行成功并且对目标主机不需要做改变的操作
- 黄色:执行成功并且对目标主机做变更
- 红色:执行失败
1.1.3 ansible-console
此工具可交互执行命令,支持tab,ansible 2.0+新增
提示符格式:
执行用户@当前操作的主机组 (当前组的主机数量)[f:并发数]$
常用子命令:
- 设置并发数: forks n 例如: forks 10
- 切换组: cd 主机组 例如: cd web
- 列出当前组主机列表: list
- 列出所有的内置命令: ?或help
范例
[root@ansible ~]#ansible-console
Welcome to the ansible console.
Type help or ? to list commands.
root@all (3)[f:5]$ ping
10.0.0.7 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
10.0.0.6 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
10.0.0.8 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/libexec/platform-python"
},
"changed": false,
"ping": "pong"
}
root@all (3)[f:5]$ list
10.0.0.8
10.0.0.7
10.0.0.6
root@all (3)[f:5]$ cd websrvs
root@websrvs (2)[f:5]$ list
10.0.0.7
10.0.0.8
root@websrvs (2)[f:5]$ forks 10
root@websrvs (2)[f:10]$ cd appsrvs
root@appsrvs (2)[f:5]$ yum name=httpd state=present
root@appsrvs (2)[f:5]$ service name=httpd state=started
1.1.4 ansible-playbook
此工具用于执行编写好的 playbook 任务
范例:
ansible-playbook hello.yml
cat hello.yml
---
#hello world yml file
- hosts: websrvs
remote_user: root
gather_facts: no
tasks:
- name: hello world
command: /usr/bin/wall hello world
1.1.5 ansible-vault
此工具可以用于加密解密yml文件
格式:
ansible-vault [create|decrypt|edit|encrypt|rekey|view]
范例:
ansible-vault encrypt hello.yml #加密
ansible-vault decrypt hello.yml #解密
ansible-vault view hello.yml #查看
ansible-vault edit hello.yml #编辑加密文件
ansible-vault rekey hello.yml #修改口令
ansible-vault create new.yml #创建新文件
#执行加密的playbook,交互式输入密码
chmod 600 hello.yml
ansible-playbook --ask-vault-pass hello.yml
#从pass.txt文件中读取密码
ansible-playbook --vault-password-file pass.txt hello.yml
#从配置文件中取得密码
#vi /etc/ansible/ansible.cfg
[defaults]
ault-password-file=pass.txt
#可以直接执行加密文件
ansible-playbook hello.yml
1.1.5 ansible-galaxy
Galaxy 是一个免费网站, 类似于github网站, 网站上发布了很多的共享的roles角色。
Ansible 提供了ansible-galaxy命令行工具连接 https://galaxy.ansible.com 网站下载相应的roles, 进行
init(初始化、search( 查拘、install(安装、 remove(移除)等操作。
范例:
#搜索项目
[root@ansible ~]#ansible-galaxy search lamp
#列出所有已安装的galaxy
ansible-galaxy list
#安装galaxy,默认下载到~/.ansible/roles下
ansible-galaxy install geerlingguy.mysql
ansible-galaxy install geerlingguy.redis
#删除galaxy
ansible-galaxy remove geerlingguy.redis
2. 总结ansible playbook目录结构及文件用途。
- 一个 playbook(剧本)文件是一个YAML语言编写的文本文件
- 通常一个playbook只包括一个play
- 一个 play的主要包括两部分: 主机和tasks. 即实现在指定一组主机上执行一个tasks定义好的任务列表。
- 一个tasks中可以有一个或多个task任务
- 每一个Task本质上就是调用ansible的一个module
- 在复杂场景中,一个playbook中也可以包括多个play,实现对多组不同的主机执行不同的任务
2.1 Playbook 核心组件
官方文档
https://docs.ansible.com/ansible/latest/reference_appendices/playbooks_keywords.html#playbook-keywords
一个playbook 中由多个组件组成,其中所用到的常见组件类型如下:
- Hosts 执行的远程主机列表
- Tasks 任务集,由多个task的元素组成的列表实现,每个task是一个字典,一个完整的代码块功能需最
少元素需包括 name 和 task,一个name只能包括一个task - Variables 内置变量或自定义变量在playbook中调用
- Templates 模板,可替换模板文件中的变量并实现一些简单逻辑的文件
- Handlers 和 notify 结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
- tags 标签 指定某条任务执行,用于选择运行playbook中的部分代码。ansible具有幂等性,因此
会自动跳过没有变化的部分,即便如此,有些代码为测试其确实没有发生变化的时间依然会非常地
长。此时,如果确信其没有变化,就可以通过tags跳过此些代码片断
2.1.1 hosts 组件
Hosts:playbook中的每一个play的目的都是为了让特定主机以某个指定的用户身份执行任务。hosts
用于指定要执行指定任务的主机,须事先定义在主机清单中
one.example.com
one.example.com:two.example.com
192.168.1.50
192.168.1.*
Websrvs:dbsrvs #或者,两个组的并集
Websrvs:&dbsrvs #与,两个组的交集
webservers:!dbsrvs #在websrvs组,但不在dbsrvs组
案例:
- hosts: websrvs:appsrvs
2.1.2 remote_user 组件
remote_user: 可用于Host和task中。也可以通过指定其通过sudo的方式在远程主机上执行任务,其可
用于play全局或某任务;此外,甚至可以在sudo时使用sudo_user指定sudo时切换的用户
- hosts: websrvs
remote_user: root
tasks:
- name: test connection
ping:
remote_user: magedu
sudo: yes #默认sudo为root
sudo_user:wang #sudo为wang
2.1.3 task列表和action组件
play的主体部分是task list,task list中有一个或多个task,各个task 按次序逐个在hosts中指定的所有主
机上执行,即在所有主机上完成第一个task后,再开始第二个task
task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着
多次执行是安全的,因为其结果均一致
每个task都应该有其name,用于playbook的执行结果输出,建议其内容能清晰地描述任务执行步骤。
如果未提供name,则action的结果将用于输出
task两种格式:
action: module arguments #示例: action: shell wall hello
module: arguments #建议使用 #示例: shell: wall hello
注意:shell和command模块后面跟命令,而非key=value
范例:
[root@ansible ansible]#cat hello.yml
---
#first yaml文件
#
- hosts: websrvs
remote_user: root
gather_facts: no
tasks:
- name: task1
debug: msg="task1 running"
- name: task2
debug: msg="task2 running"
- hosts: appsrvs
remote_user: root
gather_facts: no
tasks:
- name: task3
debug: msg="task3 running"
- name: task4
debug: msg="task4 running"
范例:
[root@ansible ansible]#cat hello.yaml
---
# first yaml file
- hosts: websrvs
remote_user: root
gather_facts: no #不收集系统信息,提高执行效率
tasks:
- name: test network connection
ping:
- name: excute command
command: wall "hello world!"
范例:
---
- hosts: websrvs
remote_user: root
gather_facts: no
tasks:
- name: install httpd
yum: name=httpd
- name: start httpd
service: name=httpd state=started enabled=yes
2.1.4 其它组件说明
某任务的状态在运行后为changed时,可通过"notify"通知给相应的handlers任务
还可以通过"tags"给task 打标签,可在ansible-playbook命令上使用-t指定进行调用
2.1.5 ShellScripts VS Playbook 案例
#SHELL脚本实现
#!/bin/bash
# 安装Apache
yum install --quiet -y httpd
# 复制配置文件
cp /tmp/httpd.conf /etc/httpd/conf/httpd.conf
cp/tmp/vhosts.conf /etc/httpd/conf.d/
# 启动Apache,并设置开机启动
systemctl enable --now httpd
#Playbook实现
---
- hosts: websrvs
remote_user: root
gather_facts: no
tasks:
- name: "安装Apache"
yum: name=httpd
- name: "复制配置文件"
copy: src=/tmp/httpd.conf dest=/etc/httpd/conf/
- name: "复制配置文件"
copy: src=/tmp/vhosts.conf dest=/etc/httpd/conf.d/
- name: "启动Apache,并设置开机启动"
service: name=httpd state=started enabled=yes
3. 使用ansible playbook实现一个mysql角色。
3.1 目录结构
tree roles/mysql/
roles/mysql/
├── files
│ └── mysql-8.0.20-linux-glibc2.12-x86_64.tar.xz
├── handlers
│ └── main.yml
├── tasks
│ ├── main.yml
│ ├── main.yml_changed_when
│ └── main.yml_when
└── templates
├── my.cnf.j2
└── mysql_auth_sql.j2
3.1.1 host
host 跟role.yml总入口在一级在role目录的上级
cat hosts_mysql
[dbservers]
10.1.10.113
10.1.10.114
[dbservers:vars]
uid=306
user=mysql
gid=306
group=mysql
basedir="/usr/local"
datadir="/data/mysql"
mysql_version="8.0.20"
mysql_file="mysql-{{mysql_version}}-linux-glibc2.12-x86_64.tar.xz"
mysql_root_password=123456
cat mysql_role.yml
- hosts: dbservers
remote_user: root
roles:
- mysql
3.1.3 task
mysql创建用户授权相关操作我用的shell模块导入sql文件,后期改成pymysql的mysql_db、mysql_user相关模块操作了
- name: create {{ group }}
group:
name: "{{ group }}"
gid: "{{ gid }}"
- name: create {{ user }}
user:
name: "{{ user }}"
uid: "{{ uid }}"
group: "{{ group }}"
system: yes
shell: /sbin/nologin
create_home: yes
home: "{{ datadir }}"
- name: install packages
yum:
name: "{{ item }}"
loop:
- ncurses-compat-libs
- name: copy tar to remote host and file mode
unarchive:
src: "{{ mysql_file }}"
dest: "{{ basedir }}"
group: "{{ group }}"
owner: "{{ user }}"
creates: "{{ basedir }}/mysql-{{ mysql_version }}-linux-glibc2.12-x86_64"
- name: create linkfile {{ basedir }}/mysql
file:
src: "{{ basedir }}/mysql-{{ mysql_version }}-linux-glibc2.12-x86_64"
dest: "{{ basedir }}/mysql"
state: link
- name: data dir
shell:
cmd: "{{ basedir }}/mysql/bin/mysqld --initialize-insecure --user={{ user }} --datadir={{ datadir }}"
creates: "{{ datadir }}/mysql"
tags: data
- name: config my.cnf
template:
src: my.cnf.j2
dest: /etc/my.cnf
notify:
- restart mysqld
- name: config mysql_auth_sql
template:
src: mysql_auth_sql.j2
dest: "{{ basedir }}/mysql/mysql_auth_sql"
- name: service script
copy:
src: "{{ basedir }}/mysql/support-files/mysql.server"
dest: /etc/init.d/mysqld
remote_src: yes
mode: preserve
- name: PATH variable
copy:
content: 'PATH={{ basedir }}/mysql/bin:$PATH'
dest: /etc/profile.d/mysql.sh
- name: start mysql
shell:
cmd: chkconfig --add mysqld;/etc/init.d/mysqld start
tags: service
- name: check whether mysql has remote access enabled
shell:
cmd: "{{ basedir }}/mysql/bin/mysql -uroot -e 'select user,host from mysql.user where user=\"root\" and host=\"localhost\";'"
ignore_errors: yes
register: check_mysql_remote
- name: debug var
debug:
var=check_mysql_remote
- name: mysql set remote
shell:
cmd: "{{ basedir }}/mysql/bin/mysql < {{ basedir }}/mysql/mysql_auth_sql"
when: check_mysql_remote.rc ==0
3.1.4 handlers
cat main.yml
- name: restart mysqld
service:
name: mysqld
state: restarted
3.1.5 template
cat my.cnf.j2
[mysqld]
server-id=1
log-bin
datadir={{ datadir }}
socket={{ datadir }}/mysql.sock
log-error={{ datadir }}/mysql.log
pid-file={{ datadir }}/mysql.pid
max_connections=1500
skip_name_resolve=on
[client]
socket={{ datadir }}/mysql.sock
cat mysql_auth_sql.j2
ALTER USER "root"@"localhost" IDENTIFIED BY "{{ mysql_root_password }}";
use mysql;
update user set host = "%" where user = "root";
flush privileges;
ll files/
总用量 479420
-rw-r--r-- 1 root root 490922012 10月 31 05:43 mysql-8.0.20-linux-glibc2.12-x86_64.tar.xz
4. 基于角色完成部署LNMP架构,并支持一键发布,回滚应用。同时基于zabbix角色批量部署zabbix。
4.1 基于角色完成部署LNMP架构
4.1.1 目录结构
ll
总用量 52
-rw-r--r-- 1 root root 19973 10月 29 21:23 ansible.cfg
-rw-r--r-- 1 root root 1234 10月 31 05:44 hosts_mysql
-rw-r--r-- 1 root root 1217 11月 15 23:41 hosts_redis
-rw-r--r-- 1 root root 1327 10月 29 21:28 hosts_shopxo
-rw-r--r-- 1 root root 1305 10月 29 21:24 hosts_wordpress
-rw-r--r-- 1 root root 63 10月 31 06:37 mysql_role.yml
-rw-r--r-- 1 root root 58 11月 15 17:17 redis_role.yml
drwxr-xr-x 11 root root 137 10月 29 21:23 roles
-rw-r--r-- 1 root root 64 10月 29 21:23 shopxo_role.yml
-rw-r--r-- 1 root root 0 10月 29 21:23 tomcat_role.yml
-rw-r--r-- 1 root root 67 10月 29 21:23 wordpress_role.yml
4.1.2 hosts信息
mysql
[dbservers]
10.1.10.113
10.1.10.114
[dbservers:vars]
uid=306
user=mysql
gid=306
group=mysql
basedir="/usr/local"
datadir="/data/mysql"
mysql_version="8.0.20"
mysql_file="mysql-{{mysql_version}}-linux-glibc2.12-x86_64.tar.xz"
mysql_root_password=123456
redis
[redis]
10.1.10.113
10.1.10.114
[redis:vars]
uid=6379
user=redis
gid=6379
group=redis
redis_version="6.0.15"
redis_file="redis-{{redis_version}}.tar.gz"
redis_data_dir="/data/redis"
redis_base_dir="/usr/local"
redis_password=123456
nginx
hosts_wordpress
[webservers]
10.1.10.113
10.1.10.114
[webservers:vars]
[webservers]
10.1.10.113
10.1.10.114
[webservers:vars]
uid=88
user=www
gid=88
group=www
version="1.20.2"
url="http://nginx.org/download/nginx-{{ version }}.tar.gz"
install_dir="/apps/nginx"
root_path=/data/wordpress
fqdn=www.wang.org
app=wordpress-6.0-zh_CN
shopxo
[webservers]
10.1.10.113
10.1.10.114
[webservers:vars]
uid=88
user=www
gid=88
group=www
version="1.20.2"
url="http://nginx.org/download/nginx-{{ version }}.tar.gz"
install_dir="/apps/nginx"
root_path=/data/shopxo
fqdn=eshop.wang.org
app_version=2.2.3
app=shopxo-v{{ app_version }}
4.1.3 总入口yml文件信息
mysql
cat mysql_role.yml
- hosts: dbservers
remote_user: root
roles:
- mysql
redis
cat redis_role.yml
- hosts: redis
remote_user: root
roles:
- redis
nginx
cat wordpress_role.yml
- hosts: webservers
remote_user: root
roles:
- wordpress
cat shopxo_role.yml
- hosts: webservers
remote_user: root
roles:
- shopxo
4.1.4 task代码
以下代码都是可复用,tags替换配置文件、重启服务
mysql (开启远程)
其目录结构
tree roles/mysql/
roles/mysql/
├── files
│ └── mysql-8.0.20-linux-glibc2.12-x86_64.tar.xz
├── handlers
│ └── main.yml
├── tasks
│ ├── main.yml
│ ├── main.yml_changed_when
│ └── main.yml_when
└── templates
├── my.cnf.j2
└── mysql_auth_sql.j2
4 directories, 7 files
cat roles/mysql/tasks/main.yml
- name: create {{ group }}
group:
name: "{{ group }}"
gid: "{{ gid }}"
- name: create {{ user }}
user:
name: "{{ user }}"
uid: "{{ uid }}"
group: "{{ group }}"
system: yes
shell: /sbin/nologin
create_home: yes
home: "{{ datadir }}"
- name: install packages
yum:
name: "{{ item }}"
loop:
- ncurses-compat-libs
- name: copy tar to remote host and file mode
unarchive:
src: "{{ mysql_file }}"
dest: "{{ basedir }}"
group: "{{ group }}"
owner: "{{ user }}"
creates: "{{ basedir }}/mysql-{{ mysql_version }}-linux-glibc2.12-x86_64"
- name: create linkfile {{ basedir }}/mysql
file:
src: "{{ basedir }}/mysql-{{ mysql_version }}-linux-glibc2.12-x86_64"
dest: "{{ basedir }}/mysql"
state: link
- name: data dir
shell:
cmd: "{{ basedir }}/mysql/bin/mysqld --initialize-insecure --user={{ user }} --datadir={{ datadir }}"
creates: "{{ datadir }}/mysql"
tags: data
- name: config my.cnf
template:
src: my.cnf.j2
dest: /etc/my.cnf
notify:
- restart mysqld
- name: config mysql_auth_sql
template:
src: mysql_auth_sql.j2
dest: "{{ basedir }}/mysql/mysql_auth_sql"
- name: service script
copy:
src: "{{ basedir }}/mysql/support-files/mysql.server"
dest: /etc/init.d/mysqld
remote_src: yes
mode: preserve
- name: PATH variable
copy:
content: 'PATH={{ basedir }}/mysql/bin:$PATH'
dest: /etc/profile.d/mysql.sh
- name: start mysql
shell:
cmd: chkconfig --add mysqld;/etc/init.d/mysqld start
tags: service
- name: check whether mysql has remote access enabled
shell:
cmd: "{{ basedir }}/mysql/bin/mysql -uroot -e 'select user,host from mysql.user where user=\"root\" and host=\"localhost\";'"
ignore_errors: yes
register: check_mysql_remote
- name: debug var
debug:
var=check_mysql_remote
- name: mysql set remote
shell:
cmd: "{{ basedir }}/mysql/bin/mysql < {{ basedir }}/mysql/mysql_auth_sql"
when: check_mysql_remote.rc ==0
redis
cat roles/redis/tasks/main.yml
- name: yum install packages
yum:
name: "{{ item }}"
loop:
- gcc
- make
- jemalloc-devel
- systemd-devel
- name: create group {{ group }}
group:
name: "{{ group }}"
gid: "{{ gid }}"
- name: create user {{ user }}
user:
name: "{{ user }}"
uid: "{{ uid }}"
group: "{{ group }}"
system: yes
shell: /sbin/nologin
create_home: yes
home: "{{ redis_data_dir }}"
- name: create redis rdb_data log directory
file:
path: "{{ redis_data_dir }}/{{ item }}"
state: directory
group: "{{ group }}"
owner: "{{ user }}"
mode: '0755'
loop:
- "data"
- "log"
- name:
unarchive:
src: "{{ redis_file }}"
dest: "{{ redis_base_dir }}/src"
creates: "{{ redis_base_dir }}/src/redis-{{ redis_version }}"
- name: install redis-{{ redis_version }}
shell:
chdir: "{{ redis_base_dir }}/src/redis-{{ redis_version }}"
cmd: "make -j 2 USE_SYSTEMD=yes PREFIX={{ redis_base_dir }}/redis install"
creates: "{{ redis_base_dir }}/redis"
- name: Create an etc directory for storing redis.conf
file:
path: "{{ redis_base_dir }}/redis/etc"
state: directory
mode: '0755'
- name: Copy the compiled redis.conf file to etc
template:
src: redis.conf.j2
dest: "{{ redis_base_dir }}/redis/etc/redis.conf"
tags: redis_conf
notify:
- restart redis
- name: chown {{ user }} {{ redis_base_dir}}/redis
shell:
cmd: "chown -R {{ redis_base_dir}}/redis;chmod 755 -R {{ redis_data_dir }}"
- name: copy redis.service
template:
src: redis.service.j2
dest: /lib/systemd/system/redis.service
notify:
- daemon-reload
- name: redis PATH variable
copy:
content: 'PATH={{ redis_base_dir }}/redis/bin:$PATH'
dest: /etc/profile.d/redis.sh
- name: Chanage net.core.somaxconn
sysctl:
name: net.core.somaxconn
value: '1024'
sysctl_set: yes
state: present
- name: vm.overcommit_memory
sysctl:
name: vm.overcommit_memory
value: '1'
sysctl_set: yes
state: present
- name: set transparent_hugepage
shell:
cmd: "echo never > /sys/kernel/mm/transparent_hugepage/enabled"
- name: start redis
service:
name: redis
state: started
enabled: yes
nginx
cat roles/nginx/tasks/main.yml
- name: install packages
yum:
name: "{{ item }}"
loop:
- gcc
- make
- pcre-devel
- openssl-devel
- zlib-devel
- perl-ExtUtils-Embed
- name: get nginx source
unarchive:
src: "{{ url }}"
dest: "/usr/local/src"
remote_src: yes
- name: compile and install
shell:
cmd: "./configure --prefix={{ install_dir }} --user=nginx --group=nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --with-stream_realip_module && make && make install"
chdir: "/usr/local/src/nginx-{{ version }}"
creates: "{{install_dir}}/sbin/nginx"
- name: create {{ group }}
group:
name: "{{ group }}"
gid: "{{ gid}}"
- name: create {{ user }}
user:
name: "{{ user }}"
uid: "{{ uid }}"
group: "{{ group }}"
system: yes
- name: copy config
template:
src: nginx.conf.j2
dest: "{{install_dir}}/conf/nginx.conf"
notify:
- restart nginx
- name: config dir
file:
path: "{{install_dir}}/conf.d"
state: directory
- name: config file mode
file:
path: "{{install_dir}}"
owner: "{{ user }}"
group: "{{ group }}"
recurse: yes
- name: check nginx config
shell:
cmd: "{{install_dir}}/sbin/nginx -t"
register: check_nginx_config
changed_when:
- check_nginx_config.stdout.find('successful')
- false
- name: service file
template:
src: nginx.service.j2
dest: /lib/systemd/system/nginx.service
- name: start nginx
service:
name: nginx
state: started
enabled: yes
php-fpm
cat roles/php-fpm/tasks/main.yml
- name: install packages
yum:
name: "{{ item }}"
loop:
- php-fpm
- php-mysqlnd
- php-json
- php-xml
- php-gd
- php-pecl-zip
- name: php path
file:
path: /var/lib/php/
owner: "{{ user }}"
group: "{{ group }}"
recurse: yes
- name: config php.ini
template:
src: php.ini.j2
dest: /etc/php.ini
notify: restart php-fpm
- name: config www.conf
template:
src: w.conf.j2
dest: /etc/php-fpm.d/www.conf
notify: restart php-fpm
- name: config nginx
template:
src: php-fpm.conf.j2
dest: "{{ install_dir }}/conf.d/php-fpm.conf"
notify: restart nginx
- name: start php-fpm
service:
name: php-fpm
state: started
enabled: yes
WordPress
cat roles/wordpress/tasks/main.yml
- name: mkdir wordpress directory
file:
path: /data/
state: directory
owner: "{{ user }}"
group: "{{ group }}"
- name: down wordpress
unarchive:
src: "{{app}}.tar.gz"
dest: /data/
owner: "{{ user }}"
group: "{{ group }}"
shopxo
- name: down {{ app }}
unarchive:
src: "{{app}}.tar.gz"
dest: /data/
owner: "{{ user }}"
group: "{{ group }}"
- name: link dir
file:
src: "/data/shopxo-{{ app_version }}"
path: "{{ root_path }}"
state: link
4.1.5 template文件内容
mysql
cat roles/mysql/templates/my.cnf.j2
[mysqld]
server-id=1
log-bin
datadir={{ datadir }}
socket={{ datadir }}/mysql.sock
log-error={{ datadir }}/mysql.log
pid-file={{ datadir }}/mysql.pid
max_connections=1500
[client]
socket={{ datadir }}/mysql.sock`
cat roles/mysql/templates/mysql_auth_sql.j2
ALTER USER "root"@"localhost" IDENTIFIED BY "{{ mysql_root_password }}";
use mysql;
update user set host = "%" where user = "root";
flush privileges;
redis
cat roles/redis/templates/redis.conf.j2
bind 0.0.0.0
requirepass {{ redis_password }}
masterauth {{ redis_password }}
protected-mode yes
port 6379
tcp-backlog 511
timeout 0
tcp-keepalive 300
daemonize yes
supervised no
pidfile {{ redis_base_dir }}/bin/redis.pid
loglevel notice
logfile "{{ redis_data_dir }}/log/redis.log"
databases 16
always-show-logo yes
save 900 1
save 300 10
save 60 10000
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
dbfilename dump.rdb
dir {{ redis_data_dir }}/data
replica-serve-stale-data yes
replica-read-only yes
repl-diskless-sync no
repl-diskless-sync-delay 5
repl-disable-tcp-nodelay no
replica-priority 100
lazyfree-lazy-eviction no
lazyfree-lazy-expire no
lazyfree-lazy-server-del no
replica-lazy-flush no
appendonly yes
appendfilename "appendonly.aof"
appendfsync everysec
no-appendfsync-on-rewrite no
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
aof-load-truncated yes
aof-use-rdb-preamble yes
lua-time-limit 5000
slowlog-log-slower-than 10000
slowlog-max-len 128
latency-monitor-threshold 0
notify-keyspace-events ""
hash-max-ziplist-entries 512
hash-max-ziplist-value 64
list-max-ziplist-size -2
list-compress-depth 0
set-max-intset-entries 512
zset-max-ziplist-entries 128
zset-max-ziplist-value 64
hll-sparse-max-bytes 3000
stream-node-max-bytes 4096
stream-node-max-entries 100
activerehashing yes
client-output-buffer-limit normal 0 0 0
client-output-buffer-limit replica 256mb 64mb 60
client-output-buffer-limit pubsub 32mb 8mb 60
hz 10
dynamic-hz yes
aof-rewrite-incremental-fsync yes
rdb-save-incremental-fsync yes
cat roles/redis/templates/redis.service.j2
[Unit]
Description=Redis persistent key-value database
After=network.target
[Service]
ExecStart={{redis_base_dir}}/redis/bin/redis-server {{redis_base_dir}}/redis/etc/redis.conf --supervised systemd
ExecStop=/bin/kill -s QUIT $MAINPID
Type=forking
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755
LimitNOFILE=1000000
[Install]
WantedBy=multi-user.target
nginx
cat roles/nginx/templates/nginx.conf.j2
user {{ user }};
worker_processes auto;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
keepalive_timeout 65;
include {{install_dir}}/conf.d/*.conf;
}
cat roles/nginx/templates/nginx.service.j2
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target
[Service]
Type=forking
PIDFile={{ install_dir }}/logs/nginx.pid
ExecStartPre=/usr/bin/rm -f {{ install_dir }}/logs/nginx.pid
ExecStartPre={{ install_dir }}/sbin/nginx -t
ExecStart={{ install_dir }}/sbin/nginx
ExecReload=/bin/kill -s HUP $MAINPID
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=mixed
PrivateTmp=true
[Install]
WantedBy=multi-user.target
php-fpm
cat roles/php-fpm/templates/php-fpm.conf.j2
##
server {
listen 80;
server_name {{ fqdn }};
root {{ root_path }};
index index.php;
location ~ \.php$ {
root {{ root_path }} ;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
grep -vE "^;|^$" roles/php-fpm/templates/php.ini.j2
[PHP]
engine = On
short_open_tag = Off
precision = 14
output_buffering = 4096
zlib.output_compression = Off
implicit_flush = Off
unserialize_callback_func =
serialize_precision = -1
disable_functions =
disable_classes =
zend.enable_gc = On
expose_php = On
max_execution_time = 360
max_input_time = 600
memory_limit = 128M
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
display_errors = Off
display_startup_errors = Off
log_errors = On
log_errors_max_len = 1024
ignore_repeated_errors = Off
ignore_repeated_source = Off
report_memleaks = On
html_errors = On
variables_order = "GPCS"
request_order = "GP"
register_argc_argv = Off
auto_globals_jit = On
post_max_size = 80M
auto_prepend_file =
auto_append_file =
default_mimetype = "text/html"
default_charset = "UTF-8"
doc_root =
user_dir =
enable_dl = Off
file_uploads = On
upload_max_filesize = 80M
max_file_uploads = 20
allow_url_fopen = On
allow_url_include = Off
default_socket_timeout = 60
[CLI Server]
cli_server.color = On
[Date]
date.timezone = Asia/Shanghai
[filter]
[iconv]
[intl]
[sqlite3]
[Pcre]
pcre.jit=0
[Pdo]
[Pdo_mysql]
pdo_mysql.cache_size = 2000
pdo_mysql.default_socket=
[Phar]
[mail function]
sendmail_path = /usr/sbin/sendmail -t -i
mail.add_x_header = On
[ODBC]
odbc.allow_persistent = On
odbc.check_persistent = On
odbc.max_persistent = -1
odbc.max_links = -1
odbc.defaultlrl = 4096
odbc.defaultbinmode = 1
[Interbase]
ibase.allow_persistent = 1
ibase.max_persistent = -1
ibase.max_links = -1
ibase.timestampformat = "%Y-%m-%d %H:%M:%S"
ibase.dateformat = "%Y-%m-%d"
ibase.timeformat = "%H:%M:%S"
[MySQLi]
mysqli.max_persistent = -1
mysqli.allow_persistent = On
mysqli.max_links = -1
mysqli.cache_size = 2000
mysqli.default_port = 3306
mysqli.default_socket =
mysqli.default_host =
mysqli.default_user =
mysqli.default_pw =
mysqli.reconnect = Off
[mysqlnd]
mysqlnd.collect_statistics = On
mysqlnd.collect_memory_statistics = Off
[PostgreSQL]
pgsql.allow_persistent = On
pgsql.auto_reset_persistent = Off
pgsql.max_persistent = -1
pgsql.max_links = -1
pgsql.ignore_notice = 0
pgsql.log_notice = 0
[bcmath]
bcmath.scale = 0
[browscap]
[Session]
session.save_handler = files
session.use_strict_mode = 0
session.use_cookies = 1
session.use_only_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.serialize_handler = php
session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.referer_check =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.sid_length = 26
session.trans_sid_tags = "a=href,area=href,frame=src,form="
session.sid_bits_per_character = 5
[Assertion]
zend.assertions = -1
[mbstring]
[gd]
[exif]
[Tidy]
tidy.clean_output = Off
[soap]
soap.wsdl_cache_enabled=1
soap.wsdl_cache_dir="/tmp"
soap.wsdl_cache_ttl=86400
soap.wsdl_cache_limit = 5
[sysvshm]
[ldap]
ldap.max_links = -1
[dba]
[curl]
[openssl]
grep -vE "^;|^$" roles/php-fpm/templates/www.conf.j2
[www]
user = {{ user }}
group = {{ group }}
listen = 127.0.0.1:9000
listen.acl_users = apache,nginx
listen.allowed_clients = 127.0.0.1
pm = dynamic
pm.max_children = 50
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 35
slowlog = /var/log/php-fpm/www-slow.log
php_admin_value[error_log] = /var/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on
php_value[session.save_handler] = files
php_value[session.save_path] = /var/lib/php/session
php_value[soap.wsdl_cache_dir] = /var/lib/php/wsdlcache
4.1.6 handlers文件内容
handlers文件内容基本一致就不展开编写了
cat roles/mysql/handlers/main.yml
- name: restart mysqld
service:
name: mysqld
state: restarted
4.1.7 meta文件内容
WordPress shopxo 需要依赖mysql、redis、nginx、php-fpm
files目录下文件在hosts文件里的变量有说明就不展开说明了
cat roles/wordpress/meta/main.yml
dependencies:
- role: mysql
vars:
uid: 306
user: mysql
gid: 306
group: mysql
basedir: "/usr/local"
datadir: "/data/mysql"
mysql_version: "8.0.20"
mysql_file: "mysql-{{mysql_version}}-linux-glibc2.12-x86_64.tar.xz"
mysql_root_password: 123456
- role: redis
vars:
uid: 6379
user: redis
gid: 6379
group: redis
redis_version: "6.0.15"
redis_file: "redis-{{redis_version}}.tar.gz"
redis_data_dir: "/data/redis"
redis_base_dir: "/usr/local"
redis_password: 123456
- role: nginx
vars:
user: www
group: www
uid: 88
gid: 88
- role: php-fpm
4.1.8 开始展示安装WordPress
这里我手动把2台被控端服务都停了,部署的文件也保留
ansible-playbook -i hosts_wordpress wordpress_role.yml
PLAY [webservers] ******************************************************************************************************************************
TASK [Gathering Facts] *************************************************************************************************************************
ok: [10.1.10.113]
ok: [10.1.10.114]
TASK [mysql : create www] **********************************************************************************************************************
ok: [10.1.10.114]
ok: [10.1.10.113]
TASK [mysql : create www] **********************************************************************************************************************
changed: [10.1.10.113]
changed: [10.1.10.114]
TASK [mysql : install packages] ****************************************************************************************************************
ok: [10.1.10.113] => (item=ncurses-compat-libs)
ok: [10.1.10.114] => (item=ncurses-compat-libs)
TASK [mysql : copy tar to remote host and file mode] *******************************************************************************************
skipping: [10.1.10.113]
skipping: [10.1.10.114]
TASK [mysql : create linkfile /usr/local/mysql] ************************************************************************************************
ok: [10.1.10.113]
ok: [10.1.10.114]
TASK [mysql : data dir] ************************************************************************************************************************
ok: [10.1.10.114]
ok: [10.1.10.113]
TASK [mysql : config my.cnf] *******************************************************************************************************************
ok: [10.1.10.114]
ok: [10.1.10.113]
TASK [mysql : config mysql_auth_sql] ***********************************************************************************************************
ok: [10.1.10.113]
ok: [10.1.10.114]
TASK [mysql : service script] ******************************************************************************************************************
ok: [10.1.10.114]
ok: [10.1.10.113]
TASK [mysql : PATH variable] *******************************************************************************************************************
ok: [10.1.10.113]
ok: [10.1.10.114]
TASK [mysql : start mysql] *********************************************************************************************************************
changed: [10.1.10.114]
changed: [10.1.10.113]
TASK [mysql : check whether mysql has remote access enabled] ***********************************************************************************
fatal: [10.1.10.113]: FAILED! => {"changed": true, "cmd": "/usr/local/mysql/bin/mysql -uroot -e 'select user,host from mysql.user where user=\"root\" and host=\"localhost\";'", "delta": "0:00:00.357809", "end": "2022-12-02 23:39:25.215392", "msg": "non-zero return code", "rc": 1, "start": "2022-12-02 23:39:24.857583", "stderr": "ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)", "stderr_lines": ["ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)"], "stdout": "", "stdout_lines": []}
...ignoring
fatal: [10.1.10.114]: FAILED! => {"changed": true, "cmd": "/usr/local/mysql/bin/mysql -uroot -e 'select user,host from mysql.user where user=\"root\" and host=\"localhost\";'", "delta": "0:00:00.352758", "end": "2022-12-02 23:39:25.285422", "msg": "non-zero return code", "rc": 1, "start": "2022-12-02 23:39:24.932664", "stderr": "ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)", "stderr_lines": ["ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)"], "stdout": "", "stdout_lines": []}
...ignoring
TASK [mysql : debug var] ***********************************************************************************************************************
ok: [10.1.10.113] => {
"check_mysql_remote": {
"changed": true,
"cmd": "/usr/local/mysql/bin/mysql -uroot -e 'select user,host from mysql.user where user=\"root\" and host=\"localhost\";'",
"delta": "0:00:00.357809",
"end": "2022-12-02 23:39:25.215392",
"failed": true,
"msg": "non-zero return code",
"rc": 1,
"start": "2022-12-02 23:39:24.857583",
"stderr": "ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)",
"stderr_lines": [
"ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)"
],
"stdout": "",
"stdout_lines": []
}
}
ok: [10.1.10.114] => {
"check_mysql_remote": {
"changed": true,
"cmd": "/usr/local/mysql/bin/mysql -uroot -e 'select user,host from mysql.user where user=\"root\" and host=\"localhost\";'",
"delta": "0:00:00.352758",
"end": "2022-12-02 23:39:25.285422",
"failed": true,
"msg": "non-zero return code",
"rc": 1,
"start": "2022-12-02 23:39:24.932664",
"stderr": "ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)",
"stderr_lines": [
"ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: NO)"
],
"stdout": "",
"stdout_lines": []
}
}
TASK [mysql : mysql set remote] ****************************************************************************************************************
skipping: [10.1.10.113]
skipping: [10.1.10.114]
TASK [redis : yum install packages] ************************************************************************************************************
ok: [10.1.10.113] => (item=gcc)
ok: [10.1.10.114] => (item=gcc)
ok: [10.1.10.113] => (item=make)
ok: [10.1.10.114] => (item=make)
ok: [10.1.10.114] => (item=jemalloc-devel)
ok: [10.1.10.113] => (item=jemalloc-devel)
ok: [10.1.10.113] => (item=systemd-devel)
ok: [10.1.10.114] => (item=systemd-devel)
TASK [redis : create group www] ****************************************************************************************************************
ok: [10.1.10.113]
ok: [10.1.10.114]
TASK [redis : create user www] *****************************************************************************************************************
changed: [10.1.10.114]
changed: [10.1.10.113]
TASK [redis : create redis rdb_data log directory] ********************************************************************************************
changed: [10.1.10.113] => (item=data)
changed: [10.1.10.114] => (item=data)
changed: [10.1.10.113] => (item=log)
changed: [10.1.10.114] => (item=log)
TASK [redis : unarchive] ***********************************************************************************************************************
skipping: [10.1.10.113]
skipping: [10.1.10.114]
TASK [redis : install redis-6.0.15] ************************************************************************************************************
ok: [10.1.10.114]
ok: [10.1.10.113]
TASK [redis : Create an etc directory for storing redis.conf] **********************************************************************************
ok: [10.1.10.113]
ok: [10.1.10.114]
TASK [redis : Copy the compiled redis.conf file to etc] ****************************************************************************************
ok: [10.1.10.113]
ok: [10.1.10.114]
TASK [redis : chown www /usr/local/redis] ******************************************************************************************************
changed: [10.1.10.113]
changed: [10.1.10.114]
TASK [redis : copy redis.service] **************************************************************************************************************
ok: [10.1.10.113]
ok: [10.1.10.114]
TASK [redis : redis PATH variable] *************************************************************************************************************
ok: [10.1.10.113]
ok: [10.1.10.114]
TASK [redis : Chanage net.core.somaxconn] ******************************************************************************************************
ok: [10.1.10.113]
ok: [10.1.10.114]
TASK [redis : vm.overcommit_memory] ************************************************************************************************************
ok: [10.1.10.114]
ok: [10.1.10.113]
TASK [redis : set transparent_hugepage] ********************************************************************************************************
changed: [10.1.10.113]
changed: [10.1.10.114]
TASK [redis : start redis] *********************************************************************************************************************
changed: [10.1.10.114]
changed: [10.1.10.113]
TASK [nginx : install packages] ****************************************************************************************************************
ok: [10.1.10.113] => (item=gcc)
ok: [10.1.10.114] => (item=gcc)
ok: [10.1.10.114] => (item=make)
ok: [10.1.10.113] => (item=make)
ok: [10.1.10.113] => (item=pcre-devel)
ok: [10.1.10.114] => (item=pcre-devel)
ok: [10.1.10.113] => (item=openssl-devel)
ok: [10.1.10.114] => (item=openssl-devel)
ok: [10.1.10.113] => (item=zlib-devel)
ok: [10.1.10.114] => (item=zlib-devel)
ok: [10.1.10.114] => (item=perl-ExtUtils-Embed)
ok: [10.1.10.113] => (item=perl-ExtUtils-Embed)
TASK [nginx : get nginx source] ****************************************************************************************************************
ok: [10.1.10.114]
ok: [10.1.10.113]
TASK [nginx : compile and install] *************************************************************************************************************
ok: [10.1.10.113]
ok: [10.1.10.114]
TASK [nginx : create www] *********************************************************************************************************************
ok: [10.1.10.113]
ok: [10.1.10.114]
TASK [nginx : create www] **********************************************************************************************************************
ok: [10.1.10.113]
ok: [10.1.10.114]
TASK [nginx : copy config] *********************************************************************************************************************
ok: [10.1.10.114]
ok: [10.1.10.113]
TASK [nginx : config dir] **********************************************************************************************************************
ok: [10.1.10.113]
ok: [10.1.10.114]
TASK [nginx : config file mode] ****************************************************************************************************************
ok: [10.1.10.114]
ok: [10.1.10.113]
TASK [nginx : check nginx config] **************************************************************************************************************
ok: [10.1.10.113]
ok: [10.1.10.114]
TASK [nginx : service file] ********************************************************************************************************************
ok: [10.1.10.113]
ok: [10.1.10.114]
TASK [nginx : start nginx] *********************************************************************************************************************
changed: [10.1.10.114]
changed: [10.1.10.113]
TASK [php-fpm : install packages] **************************************************************************************************************
ok: [10.1.10.113] => (item=php-fpm)
ok: [10.1.10.114] => (item=php-fpm)
ok: [10.1.10.114] => (item=php-mysqlnd)
ok: [10.1.10.113] => (item=php-mysqlnd)
ok: [10.1.10.113] => (item=php-json)
ok: [10.1.10.114] => (item=php-json)
ok: [10.1.10.113] => (item=php-xml)
ok: [10.1.10.114] => (item=php-xml)
ok: [10.1.10.113] => (item=php-gd)
ok: [10.1.10.114] => (item=php-gd)
ok: [10.1.10.113] => (item=php-pecl-zip)
ok: [10.1.10.114] => (item=php-pecl-zip)
TASK [php-fpm : php path] **********************************************************************************************************************
ok: [10.1.10.114]
ok: [10.1.10.113]
TASK [php-fpm : config php.ini] ****************************************************************************************************************
ok: [10.1.10.113]
ok: [10.1.10.114]
TASK [php-fpm : config www.conf] ***************************************************************************************************************
ok: [10.1.10.114]
ok: [10.1.10.113]
TASK [php-fpm : config nginx] ******************************************************************************************************************
ok: [10.1.10.113]
ok: [10.1.10.114]
TASK [php-fpm : start php-fpm] *****************************************************************************************************************
ok: [10.1.10.113]
ok: [10.1.10.114]
TASK [wordpress : mkdir wordpress directory] ***************************************************************************************************
ok: [10.1.10.113]
ok: [10.1.10.114]
TASK [wordpress : down wordpress] **************************************************************************************************************
ok: [10.1.10.114]
ok: [10.1.10.113]
PLAY RECAP *************************************************************************************************************************************
10.1.10.113 : ok=46 changed=9 unreachable=0 failed=0 skipped=3 rescued=0 ignored=1
10.1.10.114 : ok=46 changed=9 unreachable=0 failed=0 skipped=3 rescued=0 ignored=1
回滚的话是根据templates下配置文件手动进行替换然后调度handlers重启服务
4.2 基于zabbix角色批量部署zabbix(依赖于原先部署好的LNMP)
4.2.1 zabbix_server、zabbix_agent2增加角色
tree roles/zabbix_*
roles/zabbix_agent2
├── defaults
│ └── main.yml
├── files
│ └── zabbix_agent2.d
│ ├── mem.conf
│ ├── nginx_state.conf
│ ├── not_allow_ip.conf
│ ├── script
│ │ └── not_allow_ip_count.sh
│ ├── tcp.state.conf
│ └── user_login_count.conf
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── README.md
├── tasks
│ └── main.yml
├── templates
│ └── zabbix_agent2.conf.j2
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml
roles/zabbix_server
├── defaults
│ └── main.yml
├── files
├── handlers
│ └── main.yml
├── meta
│ └── main.yml
├── README.md
├── tasks
│ └── main.yml
├── templates
│ ├── zabbix.conf.j2
│ ├── zabbix_ngx.conf.j2
│ └── zabbix_server.conf.j2
├── tests
│ ├── inventory
│ └── test.yml
└── vars
└── main.yml
18 directories, 26 files
pwd
/data/ansible
# #ansible-galaxy init roles/zabbix_server/
# #ansible-galaxy init roles/zabbix_agent2/
4.2.2 host、role文件展示
cat zabbix_role.yml
- hosts: zabbix_server
remote_user: root
roles:
- zabbix_server
- hosts: zabbix_agent2
remote_user: root
roles:
- zabbix_agent2
[root@shudun ansible]# cat hosts_zabbix
[zabbix_server]
10.1.10.115
[zabbix_server:vars]
ansible_python_interpreter="/usr/bin/python3"
zabbix_server_domain="www.zabbixtest_v2.com"
[zabbix_agent2]
#10.1.10.65
#10.1.10.71
10.1.10.113
10.1.10.114
10.1.10.115
[zabbix_agent2:vars]
zabbix_server_ip="10.1.10.115"
zabbix_ver="5.0"
4.2.3 task代码展示
!注意:mysql_db使用了pymysql的模块需要在两端安装对应模块,而且运行过程中可能出现已经创建库了再执行报错情况,可以ignore_errors
zabbix-server
cat roles/zabbix_server/tasks/main.yml
- name: install zabbix-server
dnf:
name: " {{ item }}"
loop:
- zabbix-server-mysql
- zabbix-web-mysql
- zabbix-get
- name: create zabbix-server database
mysql_db:
login_host: "localhost"
login_user: "root"
login_password: "{{ mysql_root_password }}"
login_port: "3306"
name: "zabbix"
encoding: "utf8"
state: "present"
tags: test_pymysql #适配mysql模块
- name: create zabbix-server user
mysql_user:
login_host: "localhost"
login_user: "root"
login_password: "{{ mysql_root_password }}"
name: zabbix ##用户名
host: "%"
password: "{{ mysql_root_password }}" #用户密码,这里设立变量不给明文更安全
priv: 'zabbix.*:ALL' #将zabbix数据库的权限给出
state: present
- name: init zabbix-server db
mysql_db:
login_host: "localhost"
login_user: "root"
login_password: "{{ mysql_root_password }}"
name: zabbix
state: import
target: /usr/share/doc/zabbix-server-mysql/create.sql.gz
ignore_errors: yes
tags: import_db
- name: copy zabbix_server.conf template
template:
src: zabbix_server.conf.j2
dest: /etc/zabbix/zabbix_server.conf
mode: 0600
owner: "{{ user }}"
group: "{{ group }}"
notify:
- restart zabbix-server
tags: restart_zabbix-server
- name: chown {{ user }} zabbix-web
file:
path: /etc/zabbix/web
state: directory
owner: "{{ user }}"
group: "{{ group }}"
recurse: yes
- name: copy zabbix-ngx.conf template
template:
src: zabbix_ngx.conf.j2
dest: "{{ install_dir }}/conf.d/zabbix_ngx.conf"
owner: "{{ user }}"
group: "{{ group }}"
notify:
- restart nginx
- name: copy zabbix.conf template substitute yum install
template:
src: zabbix.conf.j2
dest: "/etc/php-fpm.d/zabbix.conf"
notify:
- restart php-fpm
- name: start zabbix server service
service:
name: zabbix-server
state: restarted
enabled: yes
依赖meta(!注意的是引用别的角色作为依赖的时候需要把相关vars写进去)
cat roles/zabbix_server/meta/main.yml
dependencies:
- role: mysql
vars:
uid: 306
user: mysql
gid: 306
group: mysql
basedir: "/usr/local"
datadir: "/data/mysql"
mysql_version: "8.0.20"
mysql_file: "mysql-{{mysql_version}}-linux-glibc2.12-x86_64.tar.xz"
mysql_root_password: 123456
- role: nginx
vars:
user: www
group: www
uid: 88
gid: 88
version: "1.20.2"
url: "http://nginx.org/download/nginx-{{ version }}.tar.gz"
install_dir: "/apps/nginx"
- role: php-fpm
root_path: /data/wordpress
fqdn: www.wang.org
app: wordpress-6.0-zh_CN
zabbix-agent2
cat roles/zabbix_agent2/tasks/main.yml
- name: install repo package for CentOS 7
yum:
name: "https://repo.zabbix.com/zabbix/{{ zabbix_ver }}/rhel/{{ ansible_distribution_major_version }}/x86_64/zabbix-release-{{ zabbix_ver }}-1.el{{ ansible_distribution_major_version }}.noarch.rpm"
when:
- ansible_facts['distribution'] == "CentOS"
- ansible_facts['distribution_major_version'] == "7"
- name: install repo package for CentOS 8
dnf:
name: "https://repo.zabbix.com/zabbix/{{ zabbix_ver }}/rhel/{{ ansible_distribution_major_version }}/x86_64/zabbix-release-{{ zabbix_ver }}-1.el{{ ansible_distribution_major_version }}.noarch.rpm"
disable_gpg_check: yes
#shell:
# cmd: "yum -y install https://repo.zabbix.com/zabbix/{{ zabbix_ver }}/rhel/{{ ansible_distribution_major_version }}/x86_64/zabbix-release-{{ zabbix_ver }}-1.el{{ ansible_distribution_major_version }}.noarch.rpm"
# register: check_zabbix_agent2_url
#- name: debug zabbix_agent2_url
# debug:
# meg: "{{ check_zabbix_agent2_url }}"
when:
- ansible_facts['distribution'] == "CentOS"
- ansible_facts['distribution_major_version'] == "8"
- name: download repo package for Ubuntu 18.04
get_url:
url: "https://repo.zabbix.com/zabbix/{{ zabbix_ver }}/ubuntu/pool/main/z/zabbix-release/zabbix-release_{{ zabbix_ver }}-1+{{ ansible_distribution_release }}_all.deb"
dest: /opt/
when:
- ansible_facts['distribution'] == "Ubuntu"
- ansible_facts['distribution_major_version'] == "18"
- name: install repo package for ubuntu 18.04
shell: "dpkg -i /opt/zabbix-release_{{ zabbix_ver }}-1+{{ ansible_distribution_release }}_all.deb"
when:
- ansible_facts['distribution'] == "Ubuntu"
- ansible_facts['distribution_major_version'] == "18"
- name: aliyun repo for CentOS
replace:
path: /etc/yum.repos.d/zabbix.repo
regexp: 'repo.zabbix.com'
replace: 'mirrors.aliyun.com/zabbix'
when: ansible_facts['distribution'] == "CentOS"
- name: aliyun repo for Ubuntu 18.04
replace:
path: /etc/apt/sources.list.d/zabbix.list
regexp: 'repo.zabbix.com'
replace: 'mirrors.aliyun.com/zabbix'
when:
- ansible_facts['distribution'] == "Ubuntu"
- ansible_facts['distribution_major_version'] == "18"
- name: install zabbix agent packages for CentOS 7
yum:
name: zabbix-agent2
when:
- ansible_facts['distribution'] == "CentOS"
- ansible_facts['distribution_major_version'] == "7"
- name: install zabbix agent packages for CentOS 8
dnf:
name: zabbix-agent2
when:
- ansible_facts['distribution'] == "CentOS"
- ansible_facts['distribution_major_version'] == "8"
- name: install zabbix agent packages for ubuntu 18.04
apt:
name: zabbix-agent2
update_cache: yes
when:
- ansible_facts['distribution'] == "Ubuntu"
- ansible_facts['distribution_major_version'] == "18"
- name: zabbix agent config file
template:
src: zabbix_agent2.conf.j2
dest: /etc/zabbix/zabbix_agent2.conf
mode: 0644
notify:
- restart zabbix-agent2
- name: copy zabbix-agten2.d dir
copy:
src: zabbix_agent2.d
dest: /etc/zabbix
preserver: yes
notify:
- restart zabbix-agent2
tags: agent2.d
- name: start zabbix agent2 service
service:
name: zabbix-agent2
state: restarted
enabled: yes
4.2.4 最后template、handlers展示
zabbix-server template
cat roles/zabbix_server/templates/zabbix_ngx.conf.j2
server {
listen 80;
server_name {{ zabbix_server_domain }};
root /usr/share/zabbix;
index index.php;
location = /favicon.ico {
log_not_found off;
}
location / {
try_files $uri $uri/ =404;
}
location /assets {
access_log off;
expires 10d;
}
location ~ /\.ht {
deny all;
}
location ~ /(api\/|conf[^\.]|include|locale|vendor) {
deny all;
return 404;
}
location ~ [^/]\.php(/|$) {
fastcgi_pass 127.0.0.1:9000;
#fastcgi_pass unix:/run/php-fpm/zabbix.sock;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_index index.php;
fastcgi_param DOCUMENT_ROOT /usr/share/zabbix;
fastcgi_param SCRIPT_FILENAME /usr/share/zabbix$fastcgi_script_name;
fastcgi_param PATH_TRANSLATED /usr/share/zabbix$fastcgi_script_name;
include fastcgi_params;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_intercept_errors on;
fastcgi_ignore_client_abort off;
fastcgi_connect_timeout 60;
fastcgi_send_timeout 180;
fastcgi_read_timeout 180;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
}
}
cat roles/zabbix_server/templates/zabbix_
zabbix_ngx.conf.j2 zabbix_server.conf.j2
[root@shudun ansible]# cat roles/zabbix_server/templates/zabbix_server.conf.j2
LogFile=/var/log/zabbix/zabbix_server.log
LogFileSize=0
PidFile=/var/run/zabbix/zabbix_server.pid
SocketDir=/var/run/zabbix
DBName=zabbix
DBUser=zabbix
DBHost={{ ansible_default_ipv4.address }}
#DBSocket={{ datadir }}/mysql.sock
SNMPTrapperFile=/var/log/snmptrap/snmptrap.log
Timeout=4
AlertScriptsPath=/usr/lib/zabbix/alertscripts
ExternalScripts=/usr/lib/zabbix/externalscripts
LogSlowQueries=3000
StatsAllowedIP=127.0.0.1
DBPassword={{ mysql_root_password }}
zabbix-server handlers
cat roles/zabbix_server/handlers/main.yml
- name: restart zabbix-server
service:
name: zabbix-server
state: restarted
- name: restart nginx
service:
name: nginx
state: reloaded
- name: restart php-fpm
service:
name: php-fpm
state: restarted
zabbix-agent2 template
cat roles/zabbix_agent2/templates/zabbix_agent2.conf.j2
##
PidFile=/var/run/zabbix/zabbix_agent2.pid
LogFile=/var/log/zabbix/zabbix_agent2.log
LogFileSize=0
Server={{ zabbix_server_ip }}
ServerActive={{ zabbix_server_ip }}
Hostname={{ ansible_default_ipv4.address }}
Include=/etc/zabbix/zabbix_agent2.d/*.conf
ControlSocket=/tmp/agent.sock
zabbix-agent2 handlers
cat roles/zabbix_agent2/handlers/main.yml
- name: restart zabbix-agent2
service:
name: zabbix-agent2
state: restarted
4.2.5 执行展示
4.2.6 测试
pwd
/etc/zabbix
[root@shudun zabbix]# cat zabbix_agent2.d/mem.conf
UserParameter=mem_use_percent,free | awk 'NR==2{print $3/$2*100}'
UserParameter=mem_unuse_percent,free | awk 'NR==2{print 100-($3/$2*100)}'
[root@shudun zabbix]# zabbix_get -s 10.1.10.113 -k mem_use_percent
9.77897
[root@shudun zabbix]# zabbix_get -s 10.1.10.114 -k mem_use_percent
9.10477
[root@shudun zabbix]# zabbix_get -s 10.1.10.115 -k mem_use_percent
11.1653
[root@shudun zabbix]# cat zabbix_agent2.d/tcp.state.conf
UserParameter=tcp_state[*], netstat -nat | grep -c $1
zabbix_get -s 10.1.10.115 -k tcp_state[ESTABLISHED]
56
我会将代码传到Gitee,有兴趣的小伙伴可以自行down下来
gitee地址