ansible 自动化运维工具——ansible Ad-Hoc 使用
CentOS7下使用ansible远程连接被管理主机
前提都是关闭防火墙以及selinux
准备阶段
准备三台纯新的 CentOS7 服务器,一台安装 ansible1 ,其他2台可以不安装ansible。分别为ansible2和ansible3.
hostname ip地址 用途
ansible1 192.168.32.7 ansible1 管理端
ansible2 192.168.32.17 ansible2 远程被管理主机
ansible3 192.168.32.27 ansible3 远程被管理主机
[root@ansible3 ~]#yum install ansible -y 安装过程省略...... [root@ansible1 ~]#ansible --version ansible 2.9.1 config file = /etc/ansible/ansible.cfg configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules'] ansible python module location = /usr/lib/python2.7/site-packages/ansible executable location = /usr/bin/ansible python version = 2.7.5 (default, Aug 7 2019, 00:51:29) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)] #ansible 主机上配置被管理远程服务器信息 [root@ansible1 ~]#vi /etc/ansible/hosts [root@ansible1 ~]#grep -Ev '^#|^$' /etc/ansible/hosts [websrvs] #管理的组名 192.168.32.17 #管理的主机IP 192.168.32.27 [appsrvs] 192.168.32.27 [root@ansible1 ~]#
使用 ansible 命令进行 ping 其他被控的测试
ansible 命令行使用格式 ansible 被管理主机 选项 -m 模块名称
192.168.32.27 [root@ansible1 ~]#ansible all -m ping The authenticity of host '192.168.32.27 (192.168.32.27)' can't be established. ECDSA key fingerprint is SHA256:f1DfAjEhgKwDKY3RyCy9Yu1HVakT5g3S2877lDSI8Dc. ECDSA key fingerprint is MD5:77:35:51:be:5d:71:b5:0a:0c:8a:2f:c2:3f:eb:d8:7e. Are you sure you want to continue connecting (yes/no)? The authenticity of host '192.168.32.17 (192.168.32.17)' can't be established. ECDSA key fingerprint is SHA256:f1DfAjEhgKwDKY3RyCy9Yu1HVakT5g3S2877lDSI8Dc. ECDSA key fingerprint is MD5:77:35:51:be:5d:71:b5:0a:0c:8a:2f:c2:3f:eb:d8:7e. Are you sure you want to continue connecting (yes/no)? yes 192.168.32.27 | UNREACHABLE! => { "changed": false, "msg": "Failed to connect to the host via ssh: Warning: Permanently added '192.168.32.27' (ECDSA) to the list of known hosts.\r\nPermission denied (publickey,gssapi-keyex,gssapi-with-mic,password).", "unreachable": true } 192.168.32.17 | UNREACHABLE! => { "changed": false, "msg": "Failed to connect to the host via ssh: Host key verification failed.", "unreachable": true } [root@ansible1 ~]#
上面的执行过程默认使用的 ssh 秘密验证登录方式,由于我们没有配置,因此 ping 操作失败
下面我们使用 -k 选项指明要求输入密码进行登录验证
[root@ansible1 ~]#ansible all -k -m ping SSH password: #输入远程被控主机密钥 192.168.32.17 | FAILED! => { "msg": "Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this. Please add this host's fingerprint to your known_hosts file to manage this host." } 192.168.32.27 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": false, "ping": "pong" } [root@ansible1 ~]#
可以看到,对于 -k 选择密钥ssh连接只是连接多主机中的一个。所以成功一个,一个依旧失败。
如果是管理单个主机,输入一次密码之后系统会自动记住,下次不用输入密码。
在删除 ansible 本地配置信息后,密码失效
SSH免密配置
配置免密登录秘钥进行主机访问
[root@ansible1 ~]#ssh-keygen Generating public/private rsa key pair. Enter file in which to save the key (/root/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /root/.ssh/id_rsa. Your public key has been saved in /root/.ssh/id_rsa.pub. The key fingerprint is: SHA256:43qdRpMhKltu4AH1x7Ag0LC4Dyajkovg/99xni1ww0M root@centos7mini The keys randomart image is: +---[RSA 2048]----+ |o+ | |..o o . | |o o o + | | .. o + .E | |=. . oS.oo | |+= + o. o+= | |= .. B .+o+o | |=. o o.o B.o | |o....ooo o o.. | +----[SHA256]-----+ [root@ansible1 ~]#vi /etc/ssh/ssh_config StrictHostKeyChecking no #这项不修改会导致先回答yes [root@ansible1 ~]#NET=192.168.32; for i in 17 27 ;do sshpass -p centos ssh-copy-id $NET.$i ;done #编辑一个循环语句把公钥拷贝到被管理的主机 /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub" /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys Number of key(s) added: 1 Now try logging into the machine, with: "ssh '192.168.32.17'" and check to make sure that only the key(s) you wanted were added. /usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub" /usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed /usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys Number of key(s) added: 1 Now try logging into the machine, with: "ssh '192.168.32.27'" and check to make sure that only the key(s) you wanted were added. [root@ansible1 ~]# 测试是否免密钥ssh连接: [root@ansible1 ~]#ssh 192.168.32.17 Last login: Wed Dec 4 21:35:17 2019 from 192.168.32.7 [root@ansible2 ~]#exit logout Connection to 192.168.32.17 closed. [root@ansible1 ~]#ssh 192.168.32.27 Last login: Wed Dec 4 21:38:44 2019 from 192.168.32.7 [root@ansible3 ~]#exit logout Connection to 192.168.32.27 closed. [root@ansible1 ~]# #测试 ansible1 访问 全部的受控主机 all代表所有 也可以只是管理组[wsbsrvs]或者[appsrvs] [root@ansible1 ~]#ansible all -m ping 192.168.32.27 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": false, "ping": "pong" } 192.168.32.17 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": false, "ping": "pong" } [root@ansible1 ~]#
CentOS7下 ansible 常用模块介绍
ansible-doc 模块
使用 ansible-doc 命令查看指定模块的帮助信息
使用 ansible-doc -s 可以查看简略的帮助信息
ansible-doc [options] [module…]
-l, --list #列出可用模块
-s, --snippet #显示指定模块的playbook片段
#列出所有模块
ansible-doc -l
#查看指定模块帮助用法
ansible-doc ping
#查看指定模块帮助用法
ansible-doc -s ping
[root@ansible1 ~]#ansible-doc ping [root@ansible1 ~]#ansible-doc -s ping - name: Try to connect to host, verify a usable python and return `pong' on success ping: data: # Data to return for the `ping' return value. If this parameter is set to `crash', the module will cause an exception.
使用 ansible-doc --list 可以查看所有支持的 ansible 模块
[root@ansible1 ~]#ansible-doc --list
setup 模块使用
setup 模块可以获取被管理主机的系统信息和变量
[root@ansible1 ~]#ansible websrvs -m setup [root@ansible1 ~]#ansible websrvs -m setup|wc -l 1306
范例:
ansible srv -m setup ansible srv -m setup -a "filter=ansible_nodename" ansible srv -m setup -a "filter=ansible_hostname" ansible srv -m setup -a "filter=ansible_domain" ansible srv -m setup -a "filter=ansible_memtotal_mb" ansible srv -m setup -a "filter=ansible_memory_mb" ansible srv -m setup -a "filter=ansible_memfree_mb" ansible srv -m setup -a "filter=ansible_os_family" ansible srv -m setup -a "filter=ansible_distribution_major_version" ansible srv -m setup -a "filter=ansible_distribution_version" ansible srv -m setup -a "filter=ansible_processor_vcpus" ansible srv -m setup -a "filter=ansible_all_ipv4_addresses" ansible srv -m setup -a "filter=ansible_architecture"
由于默认获取全部信息,我们可以使用 filter 进行过滤显示指定信息:
[root@ansible1 ~]#ansible websrvs -m setup -a 'filter=ansible_*_mb' 192.168.32.17 | SUCCESS => { "ansible_facts": { "ansible_memfree_mb": 399, "ansible_memory_mb": { "nocache": { "free": 1018, "used": 472 }, "real": { "free": 399, "total": 1490, "used": 1091 }, "swap": { "cached": 0, "free": 2047, "total": 2047, "used": 0 } }, "ansible_memtotal_mb": 1490, "ansible_swapfree_mb": 2047, "ansible_swaptotal_mb": 2047, "discovered_interpreter_python": "/usr/bin/python" }, "changed": false } 192.168.32.27 | SUCCESS => { "ansible_facts": { "ansible_memfree_mb": 630, "ansible_memory_mb": { "nocache": { "free": 1195, "used": 295 }, "real": { "free": 630, "total": 1490, "used": 860 }, "swap": { "cached": 0, "free": 2047, "total": 2047, "used": 0 } }, "ansible_memtotal_mb": 1490, "ansible_swapfree_mb": 2047, "ansible_swaptotal_mb": 2047, "discovered_interpreter_python": "/usr/bin/python" }, "changed": false } [root@ansible1 ~]# [root@ansible1 ~]#ansible websrvs -m setup -a 'filter=*ipv4*' #查看包含IPV4的管理主机信息 192.168.32.27 | SUCCESS => { "ansible_facts": { "ansible_all_ipv4_addresses": [ "192.168.32.167", "192.168.32.27" ], "ansible_default_ipv4": { "address": "192.168.32.167", "alias": "eth0", "broadcast": "192.168.32.255", "gateway": "192.168.32.2", "interface": "eth0", "macaddress": "00:0c:29:70:06:c4", "mtu": 1500, "netmask": "255.255.255.0", "network": "192.168.32.0", "type": "ether" }, "discovered_interpreter_python": "/usr/bin/python" }, "changed": false } 192.168.32.17 | SUCCESS => { "ansible_facts": { "ansible_all_ipv4_addresses": [ "192.168.32.166", "192.168.32.17" ], "ansible_default_ipv4": { "address": "192.168.32.166", "alias": "eth0", "broadcast": "192.168.32.255", "gateway": "192.168.32.2", "interface": "eth0", "macaddress": "00:0c:29:ce:40:a9", "mtu": 1500, "netmask": "255.255.255.0", "network": "192.168.32.0", "type": "ether" }, "discovered_interpreter_python": "/usr/bin/python" }, "changed": false }
command 模块
功能:在远程主机执行命令,此为默认模块,可忽略-m选项
注意:此命令不支持 $VARNAME < > | ; & 等,用shell模块实现
[root@ansible1 ~]#ansible appsrvs -m command -a 'ip a' 192.168.32.27 | CHANGED | rc=0 >> 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:70:06:c4 brd ff:ff:ff:ff:ff:ff inet 192.168.32.167/24 brd 192.168.32.255 scope global noprefixroute dynamic eth0 valid_lft 1621sec preferred_lft 1621sec inet 192.168.32.27/24 brd 192.168.32.255 scope global secondary noprefixroute eth0 valid_lft forever preferred_lft forever inet6 fe80::d503:83cc:5e5:94fc/64 scope link noprefixroute valid_lft forever preferred_lft forever [root@ansible1 ~]#
command 命令并非使用 shell 执行,因此变量 和 shell 的特殊符号无法使用,比如管道 重定向等等
[root@ansible1 ~]#ansible appsrvs -m command -a 'ip a > ip_info.txt' 192.168.32.27 | FAILED | rc=255 >> Command ">" is unknown, try "ip address help".non-zero return code
shell 模块
该模块将在远程主机上使用 /bin/sh 执行命令
[root@ansible1 ~]#ansible appsrvs -m shell -a 'ip a > ip_info.txt' 192.168.32.27 | CHANGED | rc=0 >> [root@ansible1 ~]#ansible appsrvs -m shell -a 'cat ip_info.txt' 192.168.32.27 | CHANGED | rc=0 >> 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:70:06:c4 brd ff:ff:ff:ff:ff:ff inet 192.168.32.167/24 brd 192.168.32.255 scope global noprefixroute dynamic eth0 valid_lft 1452sec preferred_lft 1452sec inet 192.168.32.27/24 brd 192.168.32.255 scope global secondary noprefixroute eth0 valid_lft forever preferred_lft forever inet6 fe80::d503:83cc:5e5:94fc/64 scope link noprefixroute valid_lft forever preferred_lft forever [root@ansible1 ~]#
这里由于shell模块比默认的command模块更加的方便使用,所以可以把shell模块改为默认使用的模块
[root@ansible1 ~]#vi /etc/ansible/ansible.cfg 114 #module_name = shell [root@ansible1 ~]#ansible appsrvs -a 'cat ip_info.txt' #省略-m shell 调用模块 192.168.32.27 | CHANGED | rc=0 >> 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host valid_lft forever preferred_lft forever 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether 00:0c:29:70:06:c4 brd ff:ff:ff:ff:ff:ff inet 192.168.32.167/24 brd 192.168.32.255 scope global noprefixroute dynamic eth0 valid_lft 1452sec preferred_lft 1452sec inet 192.168.32.27/24 brd 192.168.32.255 scope global secondary noprefixroute eth0 valid_lft forever preferred_lft forever inet6 fe80::d503:83cc:5e5:94fc/64 scope link noprefixroute valid_lft forever preferred_lft forever [root@ansible1 ~]#
注意:调用bash执行命令 类似 cat /tmp/test.md | awk -F‘|’ ‘{print 2}’ &> /tmp/example.txt 这些复
杂命令,即使使用shell也可能会失败,解决办法:写到脚本时,copy到远程,执行,再把需要的结果
拉回执行命令的机器
script 模块
script 模块可以将本地脚本在远程服务器上执行
[root@ansible1 ~]# [root@ansible1 ~]#mkdir /data/ansible [root@ansible1 ~]#cd /data/ansible/ [root@ansible1 ansible]#vi shellscript.sh [root@ansible1 ansible]#bash shellscript.sh hello world!!! centos7mini [root@ansible1 ansible]# [root@ansible1 ansible]#ansible all -m script -a shellscript.sh 192.168.32.27 | CHANGED => { "changed": true, "rc": 0, "stderr": "Shared connection to 192.168.32.27 closed.\r\n", "stderr_lines": [ "Shared connection to 192.168.32.27 closed." ], "stdout": "hello world!!!\r\ncentos7mini\r\n", "stdout_lines": [ "hello world!!!", "centos7mini" ] } 192.168.32.17 | CHANGED => { "changed": true, "rc": 0, "stderr": "Shared connection to 192.168.32.17 closed.\r\n", "stderr_lines": [ "Shared connection to 192.168.32.17 closed." ], "stdout": "hello world!!!\r\ncentos7mini\r\n", "stdout_lines": [ "hello world!!!", "centos7mini" ] } [root@ansible1 ansible]#
copy 模块
使用 copy 模块拷贝本地文件到远程服务器
范例:
#如目标存在,默认覆盖,此处指定先备份 ansible srv -m copy -a “src=/root/test1.sh dest=/tmp/test2.sh owner=wang mode=600 backup=yes” #指定内容,直接生成目标文件 ansible srv -m copy -a “content='test content\n' dest=/tmp/test.txt” #复制/etc/下的文件,不包括/etc/目录自身 ansible srv -m copy -a “src=/etc/ dest=/backup”
[root@ansible1 ansible]#ansible appsrvs -m copy -a "src=/data/ansible/shellscript.sh dest=/data/shells.sh" 192.168.32.27 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "checksum": "2c8081b9c69fb8bd841d0dcd7115856ca7077239", "dest": "/data/shells.sh", "gid": 0, "group": "root", "md5sum": "1baab4bf9f632e509e980f74ed68ed2e", "mode": "0644", "owner": "root", "size": 52, "src": "/root/.ansible/tmp/ansible-tmp-1575469525.0-102991088187458/source", "state": "file", "uid": 0 } [root@ansible1 ansible]#ansible appsrvs -m command -a 'ls -l /data' 192.168.32.27 | CHANGED | rc=0 >> total 4 -rw-r--r-- 1 root root 52 Dec 4 22:25 shells.sh [root@ansible1 ansible]#
fetch 模块
fetch 模块可以将远程服务器的文件复制到本地 ansible1 主机中,目前不支持目录
[root@ansible1 ansible]#ansible appsrvs -m fetch -a "src=/etc/issue dest=/data/ansible/issue.bak" 192.168.32.27 | CHANGED => { "changed": true, "checksum": "5c76e3b565c91e21bee303f15c728c71e6b39540", "dest": "/data/ansible/issue.bak/192.168.32.27/etc/issue", "md5sum": "f078fe086dfc22f64b5dca2e1b95de2c", "remote_checksum": "5c76e3b565c91e21bee303f15c728c71e6b39540", "remote_md5sum": null } [root@ansible1 ansible]#ll total 4 drwxr-xr-x 3 root root 27 Dec 4 22:28 issue.bak -rw-r--r-- 1 root root 52 Dec 4 22:20 shellscript.sh [root@ansible1 ansible]#
file 模块
管理远程主机上的文件属性和软硬连接功能
范例:
#创建空文件 ansible srv -m file -a 'path=/data/test.txt state=touch' ansible srv -m file -a 'path=/data/test.txt state=absent' ansible srv -m file -a "path=/root/test.sh owner=wang mode=755“ #创建目录 ansible srv -m file -a "path=/data/mysql state=directory owner=mysql group=mysql" #创建软链接 ansible srv -m file -a ‘src=/data/testfile dest=/data/testfile-link state=link’
修改文件属性
[root@ansible1 ~]#ansible appsrvs -a 'ls -l /data' 192.168.32.27 | CHANGED | rc=0 >> total 4 -rw-r--r-- 1 root root 52 Dec 4 22:25 shells.sh [root@ansible1 ~]# [root@ansible1 ~]#ansible appsrvs -m file -a 'path=/data/shells.sh mode=777' 192.168.32.27 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "gid": 0, "group": "root", "mode": "0777", "owner": "root", "path": "/data/shells.sh", "size": 52, "state": "file", "uid": 0 } [root@ansible1 ~]#ansible appsrvs -a 'ls -l /data' 192.168.32.27 | CHANGED | rc=0 >> total 4 -rwxrwxrwx 1 root root 52 Dec 4 22:25 shells.sh
创建软连接
[root@ansible1 ~]#ansible appsrvs -m file -a 'src=/data/shells.sh dest=/data/filelink state=link' 192.168.32.27 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "dest": "/data/filelink", "gid": 0, "group": "root", "mode": "0777", "owner": "root", "size": 15, "src": "/data/shells.sh", "state": "link", "uid": 0 } [root@ansible1 ~]#ansible appsrvs -a 'ls -l /data' 192.168.32.27 | CHANGED | rc=0 >> total 4 lrwxrwxrwx 1 root root 15 Dec 5 09:29 filelink -> /data/shells.sh -rwxrwxrwx 1 root root 52 Dec 4 22:25 shells.sh [root@ansible1 ~]#
archive 模块
archive 可以完成打包压缩功能
[root@ansible1 ~]#ansible all -m archive -a "path=/etc/issue dest=/data/issue.tar.gz format=gz mode=0777" 192.168.32.27 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "archived": [ "/etc/issue" ], "arcroot": "/etc/", "changed": true, "dest": "/data/issue.tar.gz", "expanded_exclude_paths": [], "expanded_paths": [ "/etc/issue" ], "gid": 0, "group": "root", "missing": [], "mode": "0777", "owner": "root", "size": 53, "state": "file", "uid": 0 } 192.168.32.17 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "archived": [ "/etc/issue" ], "arcroot": "/etc/", "changed": true, "dest": "/data/issue.tar.gz", "expanded_exclude_paths": [], "expanded_paths": [ "/etc/issue" ], "gid": 0, "group": "root", "missing": [], "mode": "0777", "owner": "root", "size": 53, "state": "file", "uid": 0 } [root@ansible1 ~]#ansible all -a 'ls -l /data' 192.168.32.27 | CHANGED | rc=0 >> total 8 lrwxrwxrwx 1 root root 15 Dec 5 09:29 filelink -> /data/shells.sh -rwxrwxrwx 1 root root 53 Dec 5 09:32 issue.tar.gz -rwxrwxrwx 1 root root 52 Dec 4 22:25 shells.sh 192.168.32.17 | CHANGED | rc=0 >> total 4 -rwxrwxrwx 1 root root 53 Dec 5 09:32 issue.tar.gz [root@ansible1 ~]#
unarchive 模块
解压文件模块
当选项中的 copy 为 yes 时 将解压 ansible 服务器端的压缩包到远程服务器上
本地解压然后发送到被管理主机逻辑
实现有两种用法: 1、将ansible主机上的压缩包传到远程主机后解压缩至特定目录,设置copy=yes 2、
将远程主机上的某个压缩包解压缩到指定路径下,设置copy=no
常见参数:
copy:默认为yes,当copy=yes,拷贝的文件是从ansible主机复制到远程主机上,如果设置为
copy=no,会在远程主机上寻找src源文件
remote_src:和copy功能一样且互斥,yes表示在远程主机,不在ansible主机,no表示文件在
ansible主机上
src:源路径,可以是ansible主机上的路径,也可以是远程主机上的路径,如果是远程主机上的路
径,则需要设置copy=no
dest:远程主机上的目标路径
mode:设置解压缩后的文件权限
范例:
ansible srv -m unarchive -a 'src=/data/foo.tgz dest=/var/lib/foo' ansible srv -m unarchive -a 'src=/tmp/foo.zip dest=/data copy=no mode=0777' ansible srv -m unarchive -a 'src=https://example.com/example.zip dest=/data copy=no'
解压的时候需要保证被控机器里面有解压的工具命令。
[root@ansible1 ~]#ll total 4 -rw-------. 1 root root 1572 Dec 3 13:25 anaconda-ks.cfg [root@ansible1 ~]#tar zcvf file.tar.gz anaconda-ks.cfg anaconda-ks.cfg [root@ansible1 ~]#ll total 8 -rw-------. 1 root root 1572 Dec 3 13:25 anaconda-ks.cfg -rw-r--r-- 1 root root 977 Dec 5 09:35 file.tar.gz [root@ansible1 ~]#tar zcvf code.tar.gz index.html index.html [root@ansible1 ~]#ll total 16 -rw-------. 1 root root 1572 Dec 3 13:25 anaconda-ks.cfg -rw-r--r-- 1 root root 139 Dec 5 09:38 code.tar.gz -rw-r--r-- 1 root root 977 Dec 5 09:35 file.tar.gz -rw-r--r-- 1 root root 18 Dec 5 09:37 index.html [root@ansible1 ~]#ansible appsrvs -m unarchive -a 'src=/root/code.tar.gz dest=/data copy=yes' 192.168.32.27 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "dest": "/data", "extract_results": { "cmd": [ "/usr/bin/gtar", "--extract", "-C", "/data", "-z", "-f", "/root/.ansible/tmp/ansible-tmp-1575510019.76-203687970200065/source" ], "err": "", "out": "", "rc": 0 }, "gid": 0, "group": "root", "handler": "TgzArchive", "mode": "0755", "owner": "root", "size": 77, "src": "/root/.ansible/tmp/ansible-tmp-1575510019.76-203687970200065/source", "state": "directory", "uid": 0 } [root@ansible1 ~]#ansible appsrvs -m unarchive -a 'src=/root/file.tar.gz dest=/data copy=yes' 192.168.32.27 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "dest": "/data", "extract_results": { "cmd": [ "/usr/bin/gtar", "--extract", "-C", "/data", "-z", "-f", "/root/.ansible/tmp/ansible-tmp-1575510030.18-177824913187722/source" ], "err": "", "out": "", "rc": 0 }, "gid": 0, "group": "root", "handler": "TgzArchive", "mode": "0755", "owner": "root", "size": 100, "src": "/root/.ansible/tmp/ansible-tmp-1575510030.18-177824913187722/source", "state": "directory", "uid": 0 } [root@ansible1 ~]#ansible appsrvs -a 'ls -l /data' 192.168.32.27 | CHANGED | rc=0 >> total 16 -rw------- 1 root root 1572 Dec 3 13:25 anaconda-ks.cfg lrwxrwxrwx 1 root root 15 Dec 5 09:29 filelink -> /data/shells.sh -rw-r--r-- 1 root root 18 Dec 5 09:37 index.html -rwxrwxrwx 1 root root 53 Dec 5 09:32 issue.tar.gz -rwxrwxrwx 1 root root 52 Dec 4 22:25 shells.sh [root@ansible1 ~]#
当 copy 为 no 时,将解压远程主机上的压缩包到远程主机指定路径下
让远程主机中的压缩包解压到远程被管理主机中
hostname 模块
这样在一个管理组中的机器都会改为一样的名字,这个和生产中不一致,后面会学到如何改为不同主机名的方法
[root@ansible1 ~]#ansible-doc -s hostname - name: Manage hostname hostname: name: # (required) Name of the host use: # Which strategy to use to update the hostname. If not set we try to autodetect, but this can be problematic, specially with containers as they can present misleading information. [root@ansible1 ~]#ansible 192.168.32.17 -m hostname -a "name=node-1" 192.168.32.17 | CHANGED => { "ansible_facts": { "ansible_domain": "", "ansible_fqdn": "node-1", "ansible_hostname": "node-1", "ansible_nodename": "node-1", "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "name": "node-1" } [root@ansible1 ~]#ansible 192.168.32.17 -a 'hostname' 192.168.32.17 | CHANGED | rc=0 >> node-1 [root@ansible1 ~]#
cron 模块
用于设置远程主机计划任务功能,支持时间:minute,hour,day,month,weekday
范例:
#备份数据库脚本 [root@centos8 ~]#cat mysql_backup.sh mysqldump -A -F --single-transaction --master-data=2 -q -uroot |gzip > /data/mysql_`date +%F_%T`.sql.gz #创建任务 ansible 192.168.39.28 -m cron -a 'hour=2 minute=30 weekday=1-5 name="backup mysql" job=/root/mysql_backup.sh' ansible srv -m cron -a "minute=*/5 job='/usr/sbin/ntpdate 172.20.0.1 &>/dev/null' name=Synctime" #禁用计划任务 ansible srv -m cron -a "minute=*/5 job='/usr/sbin/ntpdate 172.20.0.1 &>/dev/null' name=Synctime disabled=yes" #启用计划任务 ansible srv -m cron -a "minute=*/5 job='/usr/sbin/ntpdate 172.20.0.1 &>/dev/null' name=Synctime disabled=no" #删除任务 ansible srv -m cron -a "name='backup mysql' state=absent" ansible srv -m cron -a ‘state=absent name=Synctime’
[root@ansible1 ~]#ansible-doc -s cron - name: Manage cron.d and crontab entries cron: backup: # If set, create a backup of the crontab before it is modified. The location of the backup is returned in the `backup_file' variable by this module. cron_file: # If specified, uses this file instead of an individual user's crontab. If this is a relative path, it is interpreted with respect to `/etc/cron.d'. If it is absolute, it will typically be `/etc/crontab'. Many linux distros expect (and some require) the filename portion to consist solely of upper- and lower-case letters, digits, underscores, and hyphens. To use the `cron_file' parameter you must specify the `user' as well. day: # Day of the month the job should run ( 1-31, *, */2, etc ) disabled: # If the job should be disabled (commented out) in the crontab. Only has effect if `state=present'. env: # If set, manages a crontab's environment variable. New variables are added on top crontab. `name' and `value' parameters are the name and the value of environment variable. hour: # Hour when the job should run ( 0-23, *, */2, etc ) insertafter: # Used with `state=present' and `env'. If specified, the environment variable will inserted after the declaration of specified environment variable. insertbefore: # Used with `state=present' and `env'. If specified, the environment variable will inserted before the declaration of specified environment variable. job: # 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'. minute: # Minute when the job should run ( 0-59, *, */2, etc ) month: # Month of the year the job should run ( 1-12, *, */2, etc ) name: # Description of a crontab entry or, if env is set the name of environmenvariable. Required if `state=absent'. Note that if name is not set and `state=present', then a new crontab entry will always be created, regardless of existing ones. This parameter will always be required in future releases. reboot: # If the job should be run at reboot. This option is deprecated. Users should use special_time. special_time: # Special time specification nickname. state: # Whether to ensure the job or environment variable is present or absent. user: # The specific user whose crontab should be modified. When unset, this parameter defaults to using `root'. weekday: # Day of the week that the job should run ( 0-6 for Sunday-Saturday, *, etc ) [root@ansible1 ~]#ansible all -m cron -a "minute=*/2 job='/etc/fstab >> /data/fstab.bak' name=cron_test" 192.168.32.27 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "envs": [], "jobs": [ "cron_test" ] } 192.168.32.17 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "envs": [], "jobs": [ "cron_test" ] } [root@ansible1 ~]#ansible all -a "crontab -l" 192.168.32.27 | CHANGED | rc=0 >> #Ansible: cron_test */2 * * * * /etc/fstab >> /data/fstab.bak 192.168.32.17 | CHANGED | rc=0 >> #Ansible: cron_test */2 * * * * /etc/fstab >> /data/fstab.bak [root@ansible1 ~]#ansible all -a "ls -l /data" 192.168.32.17 | CHANGED | rc=0 >> total 8 -rw-r--r-- 1 root root 0 Dec 5 10:10 fstab.bak -rwxrwxrwx 1 root root 23 Dec 5 09:32 issue.tar -rwxrwxrwx 1 root root 53 Dec 5 09:58 issue.tar.gz 192.168.32.27 | CHANGED | rc=0 >> total 16 -rw------- 1 root root 1572 Dec 3 13:25 anaconda-ks.cfg lrwxrwxrwx 1 root root 15 Dec 5 09:29 filelink -> /data/shells.sh -rw-r--r-- 1 root root 0 Dec 5 10:10 fstab.bak -rw-r--r-- 1 root root 18 Dec 5 09:37 index.html -rwxrwxrwx 1 root root 53 Dec 5 09:58 issue.tar.gz -rwxrwxrwx 1 root root 52 Dec 4 22:25 shells.sh [root@ansible1 ~]#
删除一个远程主机的计划任务
[root@ansible1 ~]#ansible all -m cron -a "name=cron_test state=absent" 192.168.32.27 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "envs": [], "jobs": [] } 192.168.32.17 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "envs": [], "jobs": [] } [root@ansible1 ~]#ansible all -a "crontab -l" 192.168.32.17 | CHANGED | rc=0 >> 192.168.32.27 | CHANGED | rc=0 >> [root@ansible1 ~]#
yum 模块
功能:管理软件包
范例:
ansible srv -m yum -a 'name=httpd state=present' #安装 ansible srv -m yum -a 'name=httpd state=absent' #删除
[root@ansible1 ~]#ansible all -m yum -a "name=httpd state=present" 192.168.32.27 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "changes": { "installed": [ "httpd" ] }, "msg": "", "rc": 0, "results": [ "Loaded plugins: fastestmirror\nLoading mirror speeds from cached hostfile\nResolving Dependencies\n-- 省略...... 192.168.32.17 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "changes": { "installed": [ "httpd" ] }, "msg": "Repository epel is listed more than once in the configuration\n", "rc": 0, "results": [ "Loaded plugins: fastestmirror\nLoading mirror speeds from cached hostfile\nResolving Dependencies\n--> 省略...... [root@ansible1 ~]#
卸载刚安装的 httpd:
[root@ansible1 ~]#ansible all -m yum -a "name=httpd state=absent" 192.168.32.27 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "changes": { "removed": [ "httpd" ] }, "msg": "", "rc": 0, "results": [ "Loaded plugins: fastestmirror\nResolving Dependencies\n--> Running transaction check\n---> Package httpd.x86_64 省略...... ] } 192.168.32.17 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "changes": { "removed": [ "httpd" ] }, "msg": "Repository epel is listed more than once in the configuration\n", "rc": 0, "results": [ 省略...... ] } [root@ansible1 ~]#
service 模块
管理服务的启动和关闭
[root@ansible1 ~]#ansible-doc -s service - name: Manage services service: arguments: # Additional arguments provided on the command line. enabled: # Whether the service should start on boot. *At least one of state and enabled are required.* name: # (required) Name of the service. pattern: # If the service does not respond to the status command, name a substring to look for as would be found in the output of the `ps' command as a stand-in for a status result. If the string is found, the service will be assumed to be started. runlevel: # For OpenRC init scripts (e.g. Gentoo) only. The runlevel that this service belongs to. sleep: # If the service is being `restarted' then sleep this many seconds between the stop and start command. This helps to work around badly- behaving init scripts that exit immediately after signaling a process to stop. Not all service managers support sleep, i.e when using systemd this setting will be ignored. state: # `started'/`stopped' are idempotent actions that will not run commands unless necessary. `restarted' will always bounce the service. `reloaded' will always reload. *At least one of state and enabled are required.* Note that reloaded will start the service if it is not already started, even if your chosen init system wouldn't normally. use: # The service module actually uses system specific modules, normally through auto detection, this setting can force a specific module. Normally it uses the value of the 'ansible_service_mgr fact and falls back to the old 'service' module when none matching is found. [root@ansible1 ~]# 先安装一个 httpd: [root@ansible1 ~]#ansible 192.168.32.27 -m yum -a "name=httpd state=present" 安装提示代码省略...... 查看端口: [root@ansible1 ~]#ansible 192.168.32.27 -a 'ss -ntl' 192.168.32.27 | CHANGED | rc=0 >> State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 100 127.0.0.1:25 *:* LISTEN 0 128 *:22 *:* LISTEN 0 100 [::1]:25 [::]:* LISTEN 0 128 [::]:22 [::]:* 启动服务: [root@ansible1 ~]#ansible 192.168.32.27 -m service -a "name=httpd enabled=yes state=started" 192.168.32.27 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "enabled": true, "name": "httpd", "state": "started", "status": { "ActiveEnterTimestampMonotonic": "0", "ActiveExitTimestampMonotonic": "0", 省略...... 查看端口: [root@ansible1 ~]#ansible 192.168.32.27 -a 'ss -ntl' 192.168.32.27 | CHANGED | rc=0 >> State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 100 127.0.0.1:25 *:* LISTEN 0 128 *:22 *:* LISTEN 0 100 [::1]:25 [::]:* LISTEN 0 128 [::]:80 [::]:* LISTEN 0 128 [::]:22 [::]:* 停止服务: [root@ansible1 ~]#ansible 192.168.32.27 -m service -a "name=httpd state=stopped" 192.168.32.27 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "name": "httpd", "state": "stopped", "status": { "ActiveEnterTimestamp": "Thu 2019-12-05 10:44:31 CST", "ActiveEnterTimestampMonotonic": "13285420044", "ActiveExitTimestampMonotonic": "0", 省略...... 查看端口: [root@ansible1 ~]#ansible 192.168.32.27 -a 'ss -ntl' 192.168.32.27 | CHANGED | rc=0 >> State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 100 127.0.0.1:25 *:* LISTEN 0 128 *:22 *:* LISTEN 0 100 [::1]:25 [::]:* LISTEN 0 128 [::]:22 [::]:* 重新启动服务: [root@ansible1 ~]#ansible 192.168.32.27 -m service -a "name=httpd state=restarted" 192.168.32.27 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "name": "httpd", "state": "started", "status": { "ActiveEnterTimestamp": "Thu 2019-12-05 10:44:31 CST", "ActiveEnterTimestampMonotonic": "13285420044", "ActiveExitTimestamp": "Thu 2019-12-05 10:45:41 CST", 省略...... 查看端口: [root@ansible1 ~]#ansible 192.168.32.27 -a 'ss -ntl' 192.168.32.27 | CHANGED | rc=0 >> State Recv-Q Send-Q Local Address:Port Peer Address:Port LISTEN 0 100 127.0.0.1:25 *:* LISTEN 0 128 *:22 *:* LISTEN 0 100 [::1]:25 [::]:* LISTEN 0 128 [::]:80 [::]:* LISTEN 0 128 [::]:22 [::]:*
user 模块
用于管理远程主机的操作系统用户功能
范例:
#创建用户 ansible srv -m user -a 'name=user1 comment=“test user” uid=2048 home=/app/user1 group=root‘ ansible srv -m user -a 'name=nginx comment=nginx uid=88 group=nginx groups="root,daemon" shell=/sbin/nologin system=yes create_home=no home=/data/nginx non_unique=yes' #删除用户及家目录等数据 ansible srv -m user -a 'name=nginx state=absent remove=yes'
创建用户:
[root@ansible1 ~]# [root@ansible1 ~]#ansible appsrvs -m user -a "name=duanxin system=yes" 192.168.32.27 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "comment": "", "create_home": true, "group": 995, "home": "/home/duanxin", "name": "duanxin", "shell": "/bin/bash", "state": "present", "system": true, "uid": 997 } [root@ansible1 ~]# [root@ansible1 ~]#ansible appsrvs -a "id duanxin" 192.168.32.27 | CHANGED | rc=0 >> uid=997(duanxin) gid=995(duanxin) groups=995(duanxin)
删除用户:
[root@ansible1 ~]#ansible appsrvs -m user -a "name=duanxin remove=yes state=absent" 192.168.32.27 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "force": false, "name": "duanxin", "remove": true, "state": "absent", "stderr": "userdel: duanxin mail spool (/var/spool/mail/duanxin) not found\n", "stderr_lines": [ "userdel: duanxin mail spool (/var/spool/mail/duanxin) not found" ] } [root@ansible1 ~]#ansible appsrvs -a "id duanxin" 192.168.32.27 | FAILED | rc=1 >> id: duanxin: no such usernon-zero return code [root@ansible1 ~]#
group 模块
管理远程主机操作系统用户组功能
[root@ansible1 ~]#ansible-doc -s group - name: Add or remove groups group: gid: # Optional `GID' to set for the group. local: # Forces the use of "local" command alternatives on platforms that implement it. This is useful in environments that use centralized authentication when you want to manipulate the local groups. (e.g. it uses `lgroupadd' instead of `groupadd'). This requires that these commands exist on the targeted host, otherwise it will be a fatal error. name: # (required) Name of the group to manage. non_unique: # This option allows to change the group ID to a non-unique value. Requires `gid'. Not supported on macOS or BusyBox distributions. state: # Whether the group should be present or not on the remote host. system: # If `yes', indicates that the group created is a system group. [root@ansible1 ~]# 查看组信息: [root@ansible1 ~]#ansible appsrvs -a "tail -10 /etc/group" 192.168.32.27 | CHANGED | rc=0 >> systemd-network:x:192: dbus:x:81: polkitd:x:998: ssh_keys:x:997: sshd:x:74: postdrop:x:90: postfix:x:89: kaivi:x:1000:kaivi chrony:x:996: apache:x:48: 创建likai组: [root@ansible1 ~]#ansible appsrvs -m group -a "name=likai system=yes state=present" 192.168.32.27 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "gid": 995, "name": "likai", "state": "present", "system": true } [root@ansible1 ~]#ansible appsrvs -a "tail -10 /etc/group" 192.168.32.27 | CHANGED | rc=0 >> dbus:x:81: polkitd:x:998: ssh_keys:x:997: sshd:x:74: postdrop:x:90: postfix:x:89: kaivi:x:1000:kaivi chrony:x:996: apache:x:48: likai:x:995:
删除likai组:
[root@ansible1 ~]#ansible appsrvs -m group -a "name=likai state=absent" 192.168.32.27 | CHANGED => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": true, "name": "likai", "state": "absent" } [root@ansible1 ~]#ansible appsrvs -a "tail -10 /etc/group" 192.168.32.27 | CHANGED | rc=0 >> systemd-network:x:192: dbus:x:81: polkitd:x:998: ssh_keys:x:997: sshd:x:74: postdrop:x:90: postfix:x:89: kaivi:x:1000:kaivi chrony:x:996: apache:x:48: [root@ansible1 ~]#
- 其他模块
ansible 中模块众多, 使用模块前想想好自己的业务需要场景以及原生命令的使用细节,然后查询 ansible 是否有对应的功能模块,根据 ansible-doc 自己的需求找到对应的实现选项进进测试验证。不要刻意记忆具体选项,有使用经验和文档参考即可。
- 点赞
- 收藏
- 分享
- 文章举报
- 集群运维自动化工具ansible使用playbook安装mysql
- 自动化运维工具Ansible的安装与使用
- 自动化运维管理工具ansible的配置与使用
- 自动化运维工具Ansible实战(五)playbook使用
- ansible自动化运维工具使用详解
- 自动化运维工具-Ansible基础 Ansible-ad- hoc
- 自动化运维工具Ansible之Playbooks变量的使用
- ansible自动化运维工具使用详解
- Ansible自动化运维工具安装及使用
- Ansible自动化运维工具使用
- 自动化运维工具之 Ansible 介绍及安装使用
- 集群运维自动化工具ansible之使用playbook安装zabbix客户端
- Ansible自动化运维工具的基本使用
- Ansible自动化运维工具安装与使用实例
- 自动化运维工具ansible学习+使用ansible批量推送公钥到远程主机
- 自动化运维工具ansible学习+使用ansible批量推送公钥到远程主机[学习马哥]
- 自动化运维工具ansible学习+使用ansible批量推送公钥到远程主机
- ansible自动化运维工具的安装与使用
- ansible自动化运维工具的安装与使用