您的位置:首页 > 运维架构

ansible 自动化运维工具——ansible Ad-Hoc 使用

2020-01-14 23:25 218 查看

Ansible模块官网

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 ~]#
  1. 其他模块
    ansible 中模块众多, 使用模块前想想好自己的业务需要场景以及原生命令的使用细节,然后查询 ansible 是否有对应的功能模块,根据 ansible-doc 自己的需求找到对应的实现选项进进测试验证。不要刻意记忆具体选项,有使用经验和文档参考即可。
  • 点赞
  • 收藏
  • 分享
  • 文章举报
Magedu-M39-李凯 发布了52 篇原创文章 · 获赞 0 · 访问量 658 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: