1、MySQL的高可性解决方案MHA实战
10.0.0.7 CentOS7 MHA管理端
10.0.0.8 CentOS8 Master
10.0.0.18 CentOS8 Slave1
10.0.0.28 CentOS8 Slave2
1.1在管理节点安装两个包
mha4mysql-manager
mha4mysql-node
[root@mha-manager ~]# yum -y install epel-release
[root@mha-manager ~]# ls
anaconda-ks.cfg mha4mysql-manager-0.56-0.el6.noarch.rpm mha4mysql-node-0.56-0.el6.noarch.rpm
[root@mha-manager ~]# yum -y install mha*.rpm
1.2在被管理节点安装 mha4mysql-node
[root@master ~]# dnf -y install mha4mysql-node-0.56-0.el6.noarch.rpm
[root@slave1 ~]# dnf -y install mha4mysql-node-0.56-0.el6.noarch.rpm
[root@slave2 ~]# dnf -y install mha4mysql-node-0.56-0.el6.noarch.rpm
1.3 在所有节点实现相互之间ssh key验证
[root@centos7 ~]# ssh-keygen
[root@mha-manager ~]# ssh-copy-id 127.0.0.1
[root@mha-manager ~]# rsync -av .ssh 10.0.0.8:/root/
[root@mha-manager ~]# rsync -av .ssh 10.0.0.18:/root/
[root@mha-manager ~]# rsync -av .ssh 10.0.0.28:/root/
1.4在管理节点建立配置文件
[root@mha-manager ~]# mkdir /etc/mastermha/
[root@mha-manager ~]# vim /etc/mastermha/app1.cnf
[server default]
user=mhauser
password=123456
manager_workdir=/data/mastermha/app1/
manager_log=/data/mastermha/app1/manager.log
remote_workdir=/data/mastermha/app1/
ssh_user=root
repl_user=repluser
repl_password=123456
ping_interval=1
[server1]
hostname=10.0.0.8
candidate_master=1
[server2]
hostname=10.0.0.18
candidate_master=1
[server3]
hostname=10.0.0.28
1.5实现Master
[root@master ~]# yum -y install mariadb-server
[root@master ~]# vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
log-bin
server-id=8
skip_name_resolve=1
[root@master ~]# systemctl start mariadb.service
[root@master ~]# mysql
MariaDB [(none)]> show master logs;
+--------------------+-----------+
| Log_name | File_size |
+--------------------+-----------+
| mariadb-bin.000001 | 28243 |
| mariadb-bin.000002 | 344 |
+--------------------+-----------+
2 rows in set (0.000 sec)
MariaDB [(none)]> grant replication slave on *.* to repluser@'10.0.0.%' identified by '123456';
Query OK, 0 rows affected (0.000 sec)
MariaDB [(none)]> grant all on *.* to mhauser@'10.0.0.%' identified by '123456';
Query OK, 0 rows affected (0.000 sec)
1.6实现slave
[root@slave1 ~]# vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=18
log-bin
read_only
relay_log_purge=0
skip_name_resolve=1
[root@slave1 ~]# systemctl start mariadb.service
MariaDB [(none)]> CHANGE MASTER TO
-> MASTER_HOST='10.0.0.8',
-> MASTER_USER='repluser',
-> MASTER_PASSWORD='123456',
-> MASTER_PORT=3306,
-> MASTER_LOG_FILE='mariadb-bin.000003',
-> MASTER_LOG_POS=344;
Query OK, 0 rows affected (0.012 sec)
MariaDB [(none)]> start slave;
Query OK, 0 rows affected (0.001 sec)
[root@slave2 ~]# vim /etc/my.cnf.d/mariadb-server.cnf
[mysqld]
server-id=28
log-bin
read_only
relay_log_purge=0
skip_name_resolve=1
[root@slave2 ~]# systemctl start mariadb.service
MariaDB [(none)]> CHANGE MASTER TO
-> MASTER_HOST='10.0.0.8',
-> MASTER_USER='repluser',
-> MASTER_PASSWORD='123456',
-> MASTER_PORT=3306,
-> MASTER_LOG_FILE='mariadb-bin.000003',
-> MASTER_LOG_POS=344;
Query OK, 0 rows affected (0.003 sec)
MariaDB [(none)]> start slave;
Query OK, 0 rows affected (0.001 sec)
1.7 检查Mha的环境
[root@centos7 ~]# masterha_check_ssh --conf=/etc/mastermha/app1.cnf
Sun May 16 04:42:32 2021 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Sun May 16 04:42:32 2021 - [info] Reading application default configuration from /etc/mastermha/app1.cnf..
Sun May 16 04:42:32 2021 - [info] Reading server configuration from /etc/mastermha/app1.cnf..
Sun May 16 04:42:32 2021 - [info] Starting SSH connection tests..
Sun May 16 04:42:33 2021 - [debug]
Sun May 16 04:42:32 2021 - [debug] Connecting via SSH from [email protected](10.0.0.8:22) to [email protected](10.0.0.18:22)..
Sun May 16 04:42:33 2021 - [debug] ok.
Sun May 16 04:42:33 2021 - [debug] Connecting via SSH from [email protected](10.0.0.8:22) to [email protected](10.0.0.28:22)..
Sun May 16 04:42:33 2021 - [debug] ok.
Sun May 16 04:42:34 2021 - [debug]
Sun May 16 04:42:33 2021 - [debug] Connecting via SSH from [email protected](10.0.0.18:22) to [email protected](10.0.0.8:22)..
Sun May 16 04:42:33 2021 - [debug] ok.
Sun May 16 04:42:33 2021 - [debug] Connecting via SSH from [email protected](10.0.0.18:22) to [email protected](10.0.0.28:22)..
Sun May 16 04:42:34 2021 - [debug] ok.
Sun May 16 04:42:35 2021 - [debug]
Sun May 16 04:42:33 2021 - [debug] Connecting via SSH from [email protected](10.0.0.28:22) to [email protected](10.0.0.8:22)..
Sun May 16 04:42:34 2021 - [debug] ok.
Sun May 16 04:42:34 2021 - [debug] Connecting via SSH from [email protected](10.0.0.28:22) to [email protected](10.0.0.18:22)..
Sun May 16 04:42:34 2021 - [debug] ok.
Sun May 16 04:42:35 2021 - [info] All SSH connection tests passed successfully.
[root@centos7 ~]# masterha_check_repl --conf=/etc/mastermha/app1.cnf
Sun May 16 05:13:27 2021 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Sun May 16 05:13:27 2021 - [info] Reading application default configuration from /etc/mastermha/app1.cnf..
Sun May 16 05:13:27 2021 - [info] Reading server configuration from /etc/mastermha/app1.cnf..
Sun May 16 05:13:27 2021 - [info] MHA::MasterMonitor version 0.56.
Sun May 16 05:13:28 2021 - [info] GTID failover mode = 0
Sun May 16 05:13:28 2021 - [info] Dead Servers:
Sun May 16 05:13:28 2021 - [info] Alive Servers:
Sun May 16 05:13:28 2021 - [info] 10.0.0.8(10.0.0.8:3306)
Sun May 16 05:13:28 2021 - [info] 10.0.0.18(10.0.0.18:3306)
Sun May 16 05:13:28 2021 - [info] 10.0.0.28(10.0.0.28:3306)
Sun May 16 05:13:28 2021 - [info] Alive Slaves:
Sun May 16 05:13:28 2021 - [info] 10.0.0.18(10.0.0.18:3306) Version=10.3.28-MariaDB-log (oldest major version between slaves) log-bin:enabled
Sun May 16 05:13:28 2021 - [info] Replicating from 10.0.0.8(10.0.0.8:3306)
Sun May 16 05:13:28 2021 - [info] Primary candidate for the new Master (candidate_master is set)
Sun May 16 05:13:28 2021 - [info] 10.0.0.28(10.0.0.28:3306) Version=10.3.28-MariaDB-log (oldest major version between slaves) log-bin:enabled
Sun May 16 05:13:28 2021 - [info] Replicating from 10.0.0.8(10.0.0.8:3306)
Sun May 16 05:13:28 2021 - [info] Current Alive Master: 10.0.0.8(10.0.0.8:3306)
Sun May 16 05:13:28 2021 - [info] Checking slave configurations..
Sun May 16 05:13:28 2021 - [info] Checking replication filtering settings..
Sun May 16 05:13:28 2021 - [info] binlog_do_db= , binlog_ignore_db=
Sun May 16 05:13:28 2021 - [info] Replication filtering check ok.
Sun May 16 05:13:28 2021 - [info] GTID (with auto-pos) is not supported
Sun May 16 05:13:28 2021 - [info] Starting SSH connection tests..
Sun May 16 05:13:31 2021 - [info] All SSH connection tests passed successfully.
Sun May 16 05:13:31 2021 - [info] Checking MHA Node version..
Sun May 16 05:13:31 2021 - [info] Version check ok.
Sun May 16 05:13:31 2021 - [info] Checking SSH publickey authentication settings on the current master..
Sun May 16 05:13:31 2021 - [info] HealthCheck: SSH to 10.0.0.8 is reachable.
Sun May 16 05:13:32 2021 - [info] Master MHA Node version is 0.56.
Sun May 16 05:13:32 2021 - [info] Checking recovery script configurations on 10.0.0.8(10.0.0.8:3306)..
Sun May 16 05:13:32 2021 - [info] Executing command: save_binary_logs --command=test --start_pos=4 --binlog_dir=/var/lib/mysql,/var/log/mysql --output_file=/data/mastermha/app1//save_binary_logs_test --manager_version=0.56 --start_file=mariadb-bin.000004
Sun May 16 05:13:32 2021 - [info] Connecting to [email protected](10.0.0.8:22)..
Creating /data/mastermha/app1 if not exists.. Creating directory /data/mastermha/app1.. done.
ok.
Checking output directory is accessible or not..
ok.
Binlog found at /var/lib/mysql, up to mariadb-bin.000004
Sun May 16 05:13:32 2021 - [info] Binlog setting check done.
Sun May 16 05:13:32 2021 - [info] Checking SSH publickey authentication and checking recovery script configurations on all alive slave servers..
Sun May 16 05:13:32 2021 - [info] Executing command : apply_diff_relay_logs --command=test --slave_user='mhauser' --slave_host=10.0.0.18 --slave_ip=10.0.0.18 --slave_port=3306 --workdir=/data/mastermha/app1/ --target_version=10.3.28-MariaDB-log --manager_version=0.56 --relay_log_info=/var/lib/mysql/relay-log.info --relay_dir=/var/lib/mysql/ --slave_pass=xxx
Sun May 16 05:13:32 2021 - [info] Connecting to [email protected](10.0.0.18:22)..
Creating directory /data/mastermha/app1/.. done.
Checking slave recovery environment settings..
Opening /var/lib/mysql/relay-log.info ... ok.
Relay log found at /var/lib/mysql, up to mariadb-relay-bin.000002
Temporary relay log file is /var/lib/mysql/mariadb-relay-bin.000002
Testing mysql connection and privileges.. done.
Testing mysqlbinlog output.. done.
Cleaning up test file(s).. done.
Sun May 16 05:13:32 2021 - [info] Executing command : apply_diff_relay_logs --command=test --slave_user='mhauser' --slave_host=10.0.0.28 --slave_ip=10.0.0.28 --slave_port=3306 --workdir=/data/mastermha/app1/ --target_version=10.3.28-MariaDB-log --manager_version=0.56 --relay_log_info=/var/lib/mysql/relay-log.info --relay_dir=/var/lib/mysql/ --slave_pass=xxx
Sun May 16 05:13:32 2021 - [info] Connecting to [email protected](10.0.0.28:22)..
Creating directory /data/mastermha/app1/.. done.
Checking slave recovery environment settings..
Opening /var/lib/mysql/relay-log.info ... ok.
Relay log found at /var/lib/mysql, up to mariadb-relay-bin.000002
Temporary relay log file is /var/lib/mysql/mariadb-relay-bin.000002
Testing mysql connection and privileges.. done.
Testing mysqlbinlog output.. done.
Cleaning up test file(s).. done.
Sun May 16 05:13:32 2021 - [info] Slaves settings check done.
Sun May 16 05:13:32 2021 - [info]
10.0.0.8(10.0.0.8:3306) (current master)
+--10.0.0.18(10.0.0.18:3306)
+--10.0.0.28(10.0.0.28:3306)
Sun May 16 05:13:32 2021 - [info] Checking replication health on 10.0.0.18..
Sun May 16 05:13:32 2021 - [info] ok.
Sun May 16 05:13:32 2021 - [info] Checking replication health on 10.0.0.28..
Sun May 16 05:13:32 2021 - [info] ok.
Sun May 16 05:13:32 2021 - [warning] master_ip_failover_script is not defined.
Sun May 16 05:13:32 2021 - [warning] shutdown_script is not defined.
Sun May 16 05:13:32 2021 - [info] Got exit code 0 (Not master dead).
MySQL Replication Health is OK.
1.8 启动MHA
[root@centos7 ~]# nohup masterha_manager --conf=/etc/mastermha/app1.cnf &> /dev/null
[root@centos7 ~]# masterha_manager --conf=/etc/mastermha/app1.cnf
Sun May 16 05:16:29 2021 - [warning] Global configuration file /etc/masterha_default.cnf not found. Skipping.
Sun May 16 05:16:29 2021 - [info] Reading application default configuration from /etc/mastermha/app1.cnf..
Sun May 16 05:16:29 2021 - [info] Reading server configuration from /etc/mastermha/app1.cnf..
[root@centos7 ~]# masterha_check_status --conf=/etc/mastermha/app1.cnf
app1 (pid:2041) is running(0:PING_OK), master:10.0.0.8
2、Ansible常用模块总结
2.1 Command 模块
功能:在远程主机执行命令,此为默认模块,可忽略-m选项
注意:此命令不支持 $VARNAME < > | ; & 等,用shell模块实现
module_args:
-
creates
如果目标文件已经存在则不会执行动作
chdir
切换执行动作的目录
-
removes
如果目标文件存在则会执行动作
-
CMD
跟上要执行的动作
如下
# 当-a后的module_args为单引号时候 强引用 原样输出
root@7 ~]# ansible all -m command -a 'echo $HOSTNAME'
10.0.0.7 | CHANGED | rc=0 >>
$HOSTNAME
10.0.0.28 | CHANGED | rc=0 >>
$HOSTNAME
10.0.0.18 | CHANGED | rc=0 >>
$HOSTNAME
# 当-a后的module_args为双引号时候 弱引用 但执行的是ansible本机的命令
root@7 ~]# ansible all -m command -a "echo $HOSTNAME"
10.0.0.7 | CHANGED | rc=0 >>
7
10.0.0.28 | CHANGED | rc=0 >>
7
10.0.0.18 | CHANGED | rc=0 >>
7
# 我们看到hostname命令显示的是被控端的主机名
root@7 ~]# ansible all -m command -a "hostname"
10.0.0.7 | CHANGED | rc=0 >>
7
10.0.0.28 | CHANGED | rc=0 >>
28
10.0.0.18 | CHANGED | rc=0 >>
18
command用法
root@7 ~]# ansible-doc -s command
- name: Execute commands on targets
command:
argv: # Passes the command as a list rather than a string. Use `argv' to avoid quoting values that would otherwise be interpreted incorrectly (for example "username"). Only the string or the list form can be provided, not both. One or the other must be provided.
chdir: # Change into this directory before running the command.
cmd: # The command to run.
creates: # A filename or (since 2.0) glob pattern. If it already exists, this step *won't* be run.
#如果文件存在 则不执行CMD
free_form: # The command module takes a free form command to run. There is no actual parameter named 'free form'.
removes: # A filename or (since 2.0) glob pattern. If it already exists, this step *will* be run.
#如果文件不存在 则执行CMD操作
stdin: # Set the stdin of the command directly to the specified value.
stdin_add_newline: # If set to `yes', append a newline to stdin data.
strip_empty_ends: # Strip empty lines from the end of stdout/stderr in result.
warn: # Enable or disable task warnings.
# ansible Host_Pattern -m Module_name -a 'chdir=xxx cmd'
root@7 ~]# ansible dbsrvs -m command -a 'chdir=/mysql ls'
10.0.0.28 | CHANGED | rc=0 >>
3306
10.0.0.18 | CHANGED | rc=0 >>
3306
# ansible Host_Pattern -m Module_name -a 'chdir=xxx cmd'
# chdir进到目录里 执行CMD操作
root@7 ~]# ansible dbsrvs -m command -a 'chdir=/mysql cp /etc/fstab .'
10.0.0.28 | CHANGED | rc=0 >>
10.0.0.18 | CHANGED | rc=0 >>
root@7 ~]# ansible dbsrvs -m command -a 'chdir=/mysql ls'
10.0.0.28 | CHANGED | rc=0 >>
3306
fstab
10.0.0.18 | CHANGED | rc=0 >>
3306
fstab
2.2 shell模块
功能:和command相似,用shell执行命令
root@7 ~]# ansible-doc -s shell
- name: Execute shell commands on targets
shell:
chdir: # Change into this directory before running the command.
cmd: # The command to run followed by optional arguments.
creates: # A filename, when it already exists, this step will *not* be run.
executable: # Change the shell used to execute the command. This expects an absolute path to the executable.
free_form: # The shell module takes a free form command to run, as a string. There is no actual parameter named 'free form'. See the examples on how to use this module.
removes: # A filename, when it does not exist, this step will *not* be run.
stdin: # Set the stdin of the command directly to the specified value.
stdin_add_newline: # Whether to append a newline to stdin data.
warn: # Whether to enable task warnings.
root@7 ~]# ansible dbsrvs -m shell -a 'echo $HOSTNAME'
10.0.0.28 | CHANGED | rc=0 >>
28
10.0.0.18 | CHANGED | rc=0 >>
18
root@7 ~]# ansible dbsrvs -m shell -a "echo $HOSTNAME" # 弱引用 执行的ansible本机
10.0.0.28 | CHANGED | rc=0 >>
7
10.0.0.18 | CHANGED | rc=0 >>
7
root@7 ~]# ansible dbsrvs -m shell -a 'echo "hello" > ~/1.txt;cat ~/1.txt'
10.0.0.28 | CHANGED | rc=0 >>
hello
10.0.0.18 | CHANGED | rc=0 >>
hello
# ansible Host_Pattern -m Module_name -a 'removes=xxx CMD'
# 判断文件是否存在 存在则不执行CMD..
root@7 ~]# ansible all -m shell -a 'creates=/etc/xxx rm -rf 2.txt'
[WARNING]: Consider using the file module with state=absent rather than running 'rm'. If you need to use command because file is insufficient you can add 'warn: false' to this command
task or set 'command_warnings=False' in ansible.cfg to get rid of this message.
10.0.0.7 | CHANGED | rc=0 >>
10.0.0.28 | CHANGED | rc=0 >>
10.0.0.18 | CHANGED | rc=0 >>
# ansible Host_Pattern -m Module_name -a 'removes=xxx CMD'
# 判断文件是否存在 不存在则不执行CMD 存在则执行..
root@7 ~]# ansible all -m shell -a 'removes=/etc/fstab touch 2.txt'
[WARNING]: Consider using the file module with state=touch rather than running 'touch'. If you need to use command because file is insufficient you can add 'warn: false' to this command
task or set 'command_warnings=False' in ansible.cfg to get rid of this message.
10.0.0.7 | CHANGED | rc=0 >>
10.0.0.28 | CHANGED | rc=0 >>
10.0.0.18 | CHANGED | rc=0 >>
2.3 Script模块
功能:在远程主机上运行ansible服务器上的脚本(无需执行权限)
区别:执行的是ansible主控端本地的脚本 运行结果在被控制端上 不能执行被控制端的脚本
root@7 ~]# ansible-doc -s script
- name: Runs a local script on a remote node after transferring it
script:
chdir: # Change into this directory on the remote node before running the script.
cmd: # Path to the local script to run followed by optional arguments.
creates: # A filename on the remote node, when it already exists, this step will *not* be run.
decrypt: # This option controls the autodecryption of source files using vault.
executable: # Name or path of a executable to invoke the script with.
free_form: # Path to the local script file followed by optional arguments.
removes: # A filename on the remote node, when it does not exist, this step will *not* be run.
# ansible本机编辑脚本
# 脚本就是在/tmp目录下写个1.sh的文件
root@7 ~]# cat /root/echo.sh
echo > /tmp/1.sh
#如果/etc/fstab文件存在则执行
ansible all -m script -a 'echo.sh removes=/etc/fstab'
#所以在所有主机下都生成了 ansible主机定义的脚本的文件/tmp/1.sh
2.4 Copy模块
功能:从ansible服务器主控端复制文件到远程主机
module_args:
-
backup:
如果目标文件存在那么会对该文件进行备份,然后再进行覆盖操作
-
owner、group、mode
拷贝到远程主机后文件的属主属组和权限
-
content
命令行中代替src定义文本内容 且拷贝过去dest必须是文件 而不能是文件夹
-
src
当remote_src=no时候(默认就是no) 表示ansible本机的源文件或者目录 当remote_src=yes时候为目标机器的源文件或目录
-
dest
远程端的文件或者目录 当源是单个文件时dest可以是文件或者目录;当源是多个文件时dest必须是目录;当源是目录时候dest必须是目录
-
remote_src
remote_src:remote_src=yes ansible会在远程主机上寻找src文件进行copy操作; remote_src=no ansible会在自身主机寻找src文件拷贝到目标主机去 默认remote_src=no
# 如果目标存在则先备份后覆盖
# 复制ansible主机/etc/fstab文件到所有主机/tmp/下 属主wang 权限600
ansible all -m copy -a 'src=/etc/fstab dest=/tmp/fstab backup=yes owner=wang mode=600'
# 由于幂等性 再次操作不会执行 我们另外选个文件 /etc/init.d/functions复制到远程主机 目标存在则先按照时间戳备份该文件 后覆盖生成新文件 backup=yes 看看什么样子
ansible all -m copy -a 'src=/etc/init.d/functions dest=/tmp/fstab backup=yes owner=wang mode=600'
root@7 ~]# ansible all -m shell -a 'ls /tmp/fstab*'
10.0.0.7 | CHANGED | rc=0 >>
/tmp/fstab
/tmp/fstab.15716.2021-01-27@17:02:04~
10.0.0.28 | CHANGED | rc=0 >>
/tmp/fstab
/tmp/fstab.17605.2021-01-27@17:02:00~
10.0.0.18 | CHANGED | rc=0 >>
/tmp/fstab
/tmp/fstab.29573.2021-01-27@17:02:04~
# 带有时间戳的是原来的/etc/fstab的内容 /tmp/fstab这个是functions的内容
# 指定内容,直接生成目标文件
ansible all -m copy -a 'content="hello ansible\nHow are you" dest=/tmp/hello.txt'
root@7 tmp]# ansible all -m shell -a 'cat /tmp/hello.txt'
10.0.0.7 | CHANGED | rc=0 >>
hello ansible
How are you
10.0.0.28 | CHANGED | rc=0 >>
hello ansible
How are you
10.0.0.18 | CHANGED | rc=0 >>
hello ansible
How are you
# 复制目录下的文件到目标主机的文件夹下 而不复制目录本身
ansible all -m copy -a 'src=/etc/sysconfig/network-scripts/ dest=/tmp'
ansible all -m shell -a 'ls /tmp/ -d'
# 复制目录本身和下面的文件 #注意/etc/sysconfig/network-scripts后面没有/ 表示带目录复制
ansible all -m copy -a 'src=/etc/sysconfig/network-scripts dest=/tmp'
# 拷贝目标主机的/etc/passwd 到/tmp/下
ansible all -m copy -a 'remote_src=yes src=/etc/passwd dest=/tmp'
2.5 fetch模块
功能:从远程主机提取文件至ansible的主控端,copy相反,目前不支持目录
# ansible主机操作 注意此时src是目标主机的文件 desc是ansible自己的目录或者文件
root@7 ~]# ansible all -m fetch -a 'src=/etc/centos-release dest=/tmp'
root@7 ~]# tree /tmp/
/tmp/
├── 10.0.0.18
│ └── etc
│ └── centos-release
├── 10.0.0.28
│ └── etc
│ └── centos-release
├── 10.0.0.7
└── etc
└── centos-release
2.6 file模块
功能:设置文件属性 创建软连接等
module_args:
-
name
操作的对象和path一样
-
state
state must be one of: absent, directory, file, hard, link, touch
-
group、owner、mode
属组、属主、权限
-
recurse
This applies only when
state' is set todirectory
递归设置目录的权限 相当于shell的-R recurse=yes
-
path
(required) Path to the file being managed.
操作的对象 -
src
Path of the file to link to. This applies only to
state=link' andstate=hard'.
如果需要为被管理端创建链接文件 src代表原文件 path代表链接文件
# 创建目录并设置权限为1777 即STUID sticky权限
ansible all -m file -a 'path=/tmp mode=1777 state=directory'
# 创建空文件 设置权限400属主只读 属主为mysql 此处没说属组
ansible all -m file -a 'path=/tmp/test.file state=touch mode=600 owner=mysql'
# 创建软链接
ansible all -m file -a 'src=/etc/fstab state=link path=/tmp/fstab.link'
# 创建硬链接同理 state=hard
# 设置已经存在的文件权限和属主属组
ansible all -m file -a 'path=/tmp/test.file owner=mysql group=mysql mode=644'
# 创建目录
ansible all -m file -a 'path=/tmp/test state=directory'
ansible all -m file -a 'path=/tmp/test/1 state=touch'
# 递归设置目录属主为mysql
ansible all -m file -a 'path=/tmp/test recurse=yes owner=mysql group=mysql'
#删除文件夹
root@7 ansible]# ansible all -m file -a 'name=/app/php74 state=absent'
10.0.0.17 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"path": "/app/php74",
"state": "absent"
}
2.7 user模块和group模块
module_args:
-
name
组名或者用户名
-
state
state=present 创建
state=absent删除
-
remove
remove=yes
user模块中使用 删除与用户有关的目录 比如家目录 邮件目录
-
system
system=yes 创建系统用户或组
-
group
user模块中使用 指定主组primary group
-
groups
user模块中使用 指定附加组
-
home
user模块中使用 指定用户家目录路径
-
create_home
create_home=yes 创建家目录
uid
gid
-
shell
user模块中使用 指定shell类型
# 首先创建组mysql 组id306
root@7 ~]# ansible 10.0.0.7 -m group -a 'name=mysql state=present system=yes gid=306'
root@7 ~]# id mysql
id: mysql: no such user
# 创建用户 用户属主是mysql
root@7 ~]# ansible 10.0.0.7 -m user -a 'name=mysql state=present system=yes create_home=no uid=306 group=mysql'
root@7 ~]# id mysql
uid=306(mysql) gid=306(mysql) groups=306(mysql)
playbook
vim user_group.yaml
---
- hosts: all
remote_user: root
gather_facts: yes
tasks:
- name: del user
user: name=t1 state=absent
- name: create group
group: name=t1 state=present system=yes gid=2000
- name: create user
user: name=t1 state=present system=yes uid=2000 create_home=no group=t1
# 检查语法
ansible-playbook --syntax-check user_group.yaml
# 测试执行
ansible-playbook -C user_group.yaml
# 执行剧本
ansible-play user_group.yaml
2.8 unarchive模块
功能:解包和解压缩
实现有两种方法:
- 将ansible主机上的压缩包传到远程主机后解压缩至特定目录,设置copy=yes(把本地的包拷贝到远程主机然后解压缩)
- 将远程主机上的某个压缩包解压缩到指定路径下,设置copy=no(远程过去解包目标主机已经存在的包)
module_args:
-
copy
copy:默认为yes,当copy=yes,拷贝的文件是从ansible主机复制到远程主机上,如果设置为
copy=no,会在远程主机上寻找src源文件
-
remote_src
remote_src:和copy功能一样且互斥,yes表示在远程主机,不在ansible主机,no表示文件在
ansible主机上
-
src
源路径,可以是ansible主机上的路径,也可以是远程主机(被管理端或者第三方主机)上的路径,如果是远程主机上的路径,则需要设置copy=no
-
mode
设置解压缩后的文件权限
# 复制ansible本机的/root/a.tar.gz文件到目标主机的/tmp目录下并解压 设置权限和属主 默认就是copy=yes
# unarchive模块 使用默认copy=yes 即从本ansible主机copy压缩文件到远程被控制端主机目录下并解压缩
ansible all -m unarchive -a 'src=/root/a.tar.gz dest=/tmp owner=wang mode=600 copy=yes'
ansible all -m unarchive -a 'src=/tmp/a.tar.gz dest=/tmp copy=yes'
# 从互联网的包解压到被控制端主机 remote_src=yes表示包不在本ansible copy=no也同样表示包不在ansible
ansible all -m unarchive -a 'src=https://releases.ansible.com/ansible/ansible-2.1.6.0-0.1.rc1.tar.gz dest=/tmp owner=wang remote_src=yes'
2.9 Archive模块
功能:打包压缩保存在被管理节点
ansible all -m archive -a 'path=/var/log/ dest=/data/log.tar.bz2 format=bz2 owner=wang mode=0600'
2.10 hostname模块
功能:管理主机名
注意:永久修改 会修改配置文件。
centos6在/etc/sysconfig/network
ubuntu centos7 centos8 在/etc/hostname
ansible 10.0.0.18 -m hostname -a 'name=node18.magedu.com'
playbook
root@localhost playbook]# cat hostname.yaml
---
- hosts: all
gather_facts: yes
tasks:
- name: change remote host's hostname
hostname: name={{ ansible_default_ipv4["address"] }}
#这俩写法是一样的 调用ansible_default_ipv4数组的元素address为主机名
root@localhost playbook]# cat hostname.yaml
---
- hosts: all
remote_user: root
gather_facts: yes
tasks:
- name: changed remote_host's hostname
hostname: name={{ ansible_default_ipv2.address }}
root@localhost playbook]# cat hostname.yaml
- hosts: all
remote_user: root
gather_facts: yes
tasks:
- name: changed remote_host's hostname
hostname : name=db{{ ansible_default_ipv2.address.split('.')[-1] }}
#这个就是取IP最后八位 比如10.0.0.8 取8 主机名为db8
# 检查语法
ansible-playbook --syntax-check hostname.yaml
# 测试执行
ansible-playbook -C hostname.yaml
# 执行剧本
ansible-play hostname.yaml
2.11 Cron模块
功能:计划任务
支持时间:minute,hour,day,month,weekday
module_args:
-
minute
0-59 * */2
-
hour
0-23 * */2
-
day
1-31 * */2
-
month
1-12 * */2
-
weekday
0-6 for Sunday-Saturday *
-
job
要周期执行的命令 必须state=present
The command to execute or, if env is set, the value of environment variable. The command should not contain line breaks. Required if `state=present'
-
env
环境变量
If set, manages a crontab's environment variable. New variables are added on top of crontab.
name' and
value' parameters are the name and the value of environment variable -
disabled
状态为state=present的任务 当disabled设置为yes时 会被注释掉 即禁用任务执行
If the job should be disabled (commented out) in the crontab. Only has effect if `state=present'.
-
state
state=present |absent 确保环境变量和任务存在与否
Whether to ensure the job or environment variable is present or absent.
-
user
默认定时任务执行人root
The specific user whose crontab should be modified. When unset, this parameter defaults to using `root'.
#周一到周五每天凌晨2:30执行备份脚本
# 各个节点复制过去准备脚本
ansible all -m copy -a 'content="echo $PATH > /tmp/2.file\n" dest=/tmp/1.sh'
# 配置脚本的属主和执行权限
ansible all -m file -a 'mode=775 path=/tmp/1.sh owner=root'
# 配置定时任务 每个主机crontab -l都能看到该任务
ansible all -m cron -a 'hour=15 minute=1 weekday=4 name="backup" job=/tmp/1.sh'
# 创建时间同步计划任务
ansible websrvs -m cron -a "minute=*/2 job='/usr/bin/chronyc makestep &>/dev/null' name=Synctime"
#禁用计划任务
ansible websrvs -m cron -a "minute=*/5 job='/usr/sbin/ntpdate 172.20.0.1
&>/dev/null' name=Synctime disabled=yes"
#启用计划任务
ansible websrvs -m cron -a "minute=*/5 job='/usr/sbin/ntpdate 172.20.0.1
&>/dev/null' name=Synctime disabled=no"
#删除任务
ansible websrvs -m cron -a "name='backup mysql' state=absent"
ansible websrvs -m cron -a 'state=absent name=Synctime'
2.12 yum 和 apt 模块
功能:
yum 管理软件包,只支持RHEL,CentOS,fedora,不支持Ubuntu其它版本
apt 模块管理 Debian 相关版本的软件包
module_args:
disablerepo
enablerepo
-
name
安装的包名
-
state
install (
present' or 'installed',
latest'), or remove (`absent' or 'removed') a package
ansible websrvs -m yum -a 'name=httpd state=present' #安装
ansible websrvs -m yum -a 'name=httpd state=absent' #删除
playbook
vim packet_manager.yaml
---
- hosts: all
remote_user: root
gather_facts: yes
tasks:
- name: install httpd
yum: name=httpd state=present
when: ansible_distribution_file_variety=="RedHat"
- name: install apache2
apt: name=apache2 state=present
when: ansible_distribution_file_variety=="Debian"
#注意 两个等号表示相等 否则为赋值 且后面是字符串所以加双引号
# 此处这个 ansible_distribution_file_variety和ansible_os_family一样
# 检查语法
ansible-playbook --syntax-check packet_manager.yaml
# 测试执行
ansible-playbook -C packet_manager.yaml
# 执行剧本
ansible-play packet_manager.yaml
2.13 Service模块
功能:
管理服务
module_args:
-
enabled
enabled=yes 开机自启动
-
name
服务名称
-
runlevel
在什么级别启动运行服务 2345 0关机 1单用户 23多用户模式 4待定义 5图形化 6重启
-
state
started
stopped
reloaded
restarted
# 10.0.0.9是ubuntu 所以没有httpd
# 启动服务
ansible 'all:!10.0.0.9' -m service -a 'name=httpd state=started enabled=yes'
# 修改配置文件端口为8080
ansible 'all:!10.0.0.9' -m shell -a "sed -ri '/^Listen 80/s/(Listen).*/\1 8080/' /etc/httpd/conf/httpd.conf"
# 重启服务
ansible 'all:!10.0.0.9' -m service -a 'name=httpd state=restarted'
playbook
vim service.yaml
---
- hosts: all
remote_user: root
gather_facts: yes
tasks:
- name: start httpd
service: name=httpd state=started
when: ansible_distribution_file_variety=="RedHat"
- name: change conf port centos
shell: sed -ri '/^Listen 80/s/(Listen).*/\1 80/' /etc/httpd/conf/httpd.conf
when: ansible_distribution_file_variety=="RedHat"
- name: change conf port ubuntu
shell: sed -ri '/^Listen 80/s/(Listen).*/\1 8080/' /etc/apache2/ports.conf
when: ansible_distribution_file_variety=="Debian"
- name: start apache2
service: name=apache2 state=started
when: ansible_distribution_file_variety=="Debian"
#此变量和ansible_os_family一样
# 检查语法
ansible-playbook --syntax-check service.yaml
# 测试执行
ansible-playbook -C service.yaml
# 执行剧本
ansible-play service.yaml
2.14 Lineinfile模块
在ansible自身提供了两个模块:lineinfile模块和replace模块,可以方便的进行替换
作用:
相当于sed功能。
ansible在使用sed进行替换时,经常会遇到需要转义的问题,而且ansible在遇到特殊符号进行替换时,
存在问题,无法正常进行替换 。其实在ansible自身提供了两个模块:lineinfile模块和replace模块,可
以方便的进行替换
一般在ansible当中去修改某个文件的单行进行替换的时候需要使用lineinfile模块
lineinfile不能用分组替换
module_args:
-
path
(required) The file to modify. Before Ansible 2.3 this option was only usable as
dest',
destfile' and `name'. 要修改的文件 ; 这个选项在ansible2.3以前叫做dest或者name -
regexp
regexp参数 :使用正则表达式匹配对应的行,当替换文本时,如果有多行文本都能被匹配,则只有最
后面被匹配到的那行文本才会被替换,当删除文本时,如果有多行文本都能被匹配,这么这些行都会被
删除。
如果想进行多行匹配进行替换需要使用replace模块 -
line
The line to insert/replace into the file. Required for
state=present'. If
backrefs' is set, may contain backreferences that will get expanded with the `regexp' capture groups if the regexp matches.要被替换的行 需要state=present
# 拷贝测试文件
ansible all -m copy -a 'remote_src=yes src=/etc/fstab dest=/tmp'
# 删除regexp匹配到的内容 这里是删除#号开头的行
ansible all -m lineinfile -a 'path=/tmp/fstab regexp="^#" state=absent'
#path和dest或者name都是一个道理
ansible all -m lineinfile -a 'dest=/etc/fstab state=absent regexp="^#"'
# 拷贝测试文件
ansible 'all:!10.0.0.9' -m copy -a 'remote_src=yes src=/etc/selinux/config dest=/tmp'
# 替换
ansible 'all:!10.0.0.9' -m lineinfile -a 'path=/tmp/config regexp="^SELINUX=" line="SELINUX=disabled"'
playbook
vim lineinfile.yaml
---
- hosts: all:!10.0.0.9
remote_user: root
gather_facts: yes
tasks:
- name: enforcing selinux config
lineinfile: path=/tmp/config regexp="^SELINUX=" line="SELINUX=disabled"
when: ansible_os_family=="RedHat"
- name: copy testfile
copy: remote_src=yes src=/etc/default/grub dest=/tmp
- name: change eth0
lineinfile: path=/tmp/grub regexp='^GRUB_CMDLINE_LINUX=.*"$' line='GRUB_CMDLINE_LINUX="crashkernel=auto spectre_v2=retpoline rhgb quiet net.ifnames=0"'
# 检查语法
ansible-playbook --syntax-check lineinfile.yaml
# 测试执行
ansible-playbook -C lineinfile.yaml
# 执行剧本
ansible-play lineinfine.yaml
2.15 Replace模块
作用:进行多行匹配
该模块有点类似于sed命令,主要也是基于正则进行匹配和替换,建议使用
也支持分组
Replace模块没有state选项 所以无法像上面lineinfile一样state=absent删除regexp匹配到的内容
# 把UUID开头的行加# 注释掉
ansible all -m replace -a "path=/tmp/fstab regexp='^(UUID.*)' replace='#\1'"
ansible all -m replace -a "path=/tmp/fstab regexp='^#(UUID.*)' replace='\1'"
2.16 Setup模块
只在剧本中手动选择gather_facts: yes
才会收集主机的系统信息
ansible命令需要调用setup模块搜集facts信息
作用:setup 模块来收集主机的系统信息,这些 facts 信息可以直接以变量的形式使用,但是如果主机较多,会影响执行速度,可以使用 gather_facts: no
来禁止 Ansible 收集 facts 信息
module_args
-
filter
# 采集信息 系统家族ansible_os_family root@10 playbook]# ansible all -m setup -a 'filter=ansible_os_family' 10.0.0.7 | SUCCESS => { "ansible_facts": { "ansible_os_family": "RedHat", "discovered_interpreter_python": "/usr/bin/python" }, "changed": false } 10.0.0.18 | SUCCESS => { "ansible_facts": { "ansible_os_family": "RedHat", "discovered_interpreter_python": "/usr/libexec/platform-python" }, "changed": false } 10.0.0.9 | SUCCESS => { "ansible_facts": { "ansible_os_family": "Debian", "discovered_interpreter_python": "/usr/bin/python3" }, "changed": false }
playbook
# 模版
---
- hosts: all
remote_user: root
gather_facts: yes # 默认不写gather_facts就是yes
tasks:
- name: xxx
module_name: module_name_args
############
---
- hosts: all
gather_facts: yes
tasks:
- name: change remote host's hostname
hostname: name={{ ansible_default_ipv4["address"] }}
#这俩写法是一样的 调用ansible_default_ipv4数组的元素address
---
- hosts: all
remote_user: root
gather_facts: yes # 默认不写gather_facts就是yes
tasks:
- name: echo ip > file
copy: content="{{ ansible_eth0.ipv2.address }}\n" dest=/tmp/a.txt
# 检查语法
ansible-playbook --syntax-check setup.yaml
# 测试执行
ansible-playbook -C setup.yaml
# 执行剧本
ansible-play setup.yaml
3、Ansible playbook实现zabbix-agent批量部署(主机名不同)
3.1 编写安装脚本
ansible 10.0.0.7
client1 10.0.0.17
client2 10.0.0.27
[root@ansible ~]# vim zabbix-agent.sh
#!/bin/bash
HN=$(ifconfig |sed -nr "2s/[^0-9]+([0-9.]+).*/\1/p")
if [ ! -f /etc/yum.repos.d/zabbix.repo ]
then
rpm -Uvh https://repo.zabbix.com/zabbix/5.0/rhel/7/x86_64/zabbix-release-5.0-1.el7.noarch.rpm
fi
rpm -q zabbix-agent &>/dev/null
[ $? -ne 0 ] && yum -y install zabbix-agent
cp /etc/zabbix/zabbix_agentd.conf{,-$(date +%F%T)}
sed -i 's/Server=127.0.0.1/Server=10.0.0.7/g' /etc/zabbix/zabbix_agentd.conf
sed -i 's/ServerActive=127.0.0.1/ServerActive=10.0.0.7/g' /etc/zabbix/zabbix_agentd.conf
sed -i 's/Hostname=Zabbix server/Server='$HN'/g' /etc/zabbix/zabbix_agentd.conf
systemctl restart zabbix-agent
[root@ansible ~]# vim zabbix-agent.yml
- hosts: zabbixagent
remote_user: root
tasks:
- name: install yum
copy: src=/root/zabbix-agent.sh dest=/root/zabbix-agent.sh mode=777
notify:
- script agent
handlers:
- name: script agent
command: /root/zabbix-agent.sh
3.2 安装ansible
# 安装absible
[root@ansible ~]# yum -y install epel-release.noarch
[root@ansible ~]# yum -y install ansible
[root@ansible ~]# vim /etc/ansible/hosts
...
[zabbixagent]
10.0.0.17
10.0.0.27
...
#给主机配置密钥
[root@ansible ~]# ssh-keygen
[root@ansible ~]# ssh-copy-id 127.0.0.1
[root@ansible ~]# rsync -av .ssh 10.0.0.17:/root/
[root@ansible ~]# rsync -av .ssh 10.0.0.27:/root/
3.3 执行脚本查看安装状态
[root@ansible ~]# ansible-playbook -C zabbix-agent.yml
[root@ansible ~]# ansible-playbook zabbix-agent.yml
[root@ansible ~]#
[root@client1 ~]# netstat -anpt |grep 10050
tcp 0 0 0.0.0.0:10050 0.0.0.0:* LISTEN 2348/zabbix_agentd
tcp6 0 0 :::10050 :::* LISTEN 2348/zabbix_agentd
[root@client2 ~]# netstat -anpt |grep 10050
tcp 0 0 0.0.0.0:10050 0.0.0.0:* LISTEN 2371/zabbix_agentd
tcp6 0 0 :::10050 :::* LISTEN 2371/zabbix_agentd