一、如何使用模块
由前面的学习可知,当我们使用 ansible 完成实际任务时,需要依靠 ansible 的各个模块,比如,我们想要去 ping 某主机,则需要使用 ping 模块,命令如下:
ansible all -m ping
除了 ping 模块,ansible 还有很多模块可供我们使用。我们可以使用如下命令,查看 ansible 都有哪些模块:
[root@ansible-manager ~]# ansible-doc -l
a10_server Manage A10 Networks AX/SoftAX/Thunder/vThunder devices' server object.
a10_server_axapi3 Manage A10 Networks AX/SoftAX/Thunder/vThunder devices
a10_service_group Manage A10 Networks AX/SoftAX/Thunder/vThunder devices' service groups.
a10_virtual_server Manage A10 Networks AX/SoftAX/Thunder/vThunder devices' virtual servers.
accelerate Enable accelerated mode on remote node
aci_aaa_user Manage AAA users (aaa:User)
aci_aaa_user_certificate Manage AAA user certificates (aaa:UserCert)
aci_access_port_to_interface_policy_leaf_profile Manage Fabric interface policy leaf profile interface selectors (infra:HPortS, infra:RsAccBaseGrp, infra:PortBlk)
aci_aep Manage attachable Access Entity Profile (AEP) objects (infra:AttEntityP, infra:ProvAcc)
aci_aep_to_domain Bind AEPs to Physical or Virtual Domains (infra:RsDomP)
aci_ap Manage top level Application Profile (AP) objects (fv:Ap)
aci_bd Manage Bridge Domains (BD) objects (fv:BD)
aci_bd_subnet Manage Subnets (fv:Subnet)
aci_bd_to_l3out Bind Bridge Domain to L3 Out (fv:RsBDToOut)
......
通过上面命令可以看到 ansible 中各个模块的名称,以及模块的大概功能。当然,通过ansible-doc -l命令获取到的模块信息比较概括,并不是特别详细,如果想要获取到各个模块更加详细的用法,可以使用ansible-doc -s命令。比如,我们想要获取 ping 模块的详细使用方法,则可以使用如下命令:
[root@ansible-manager ~]# 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 -s ping命令查看 ping 模块的描述,得到的信息也是比较少的。这是因为 ping 模块本来就比较简单,而且 ping 模块并没有太多参数可用。但是并非所有模块都像 ping 模块一样简单,有的模块在使用时必须使用参数,比如 fetch 模块,fetch 为”拿来”之意,当我们需要将被管理主机中的文件拉取到 ansible 主机时,则可以使用此模块。首先,我们可以使用ansible-doc -s fetch命令,查看一下 fetch 模块的用法:
[root@ansible-manager ~]# ansible-doc -s fetch
- name: Fetches a file from remote nodes
fetch:
dest: # (required) A directory to save the file into. For example, if the `dest' directory is `/backup' a `src' file named `/etc/profile' on host
`host.example.com', would be saved into `/backup/host.example.com/etc/profile'
fail_on_missing: # When set to 'yes', the task will fail if the remote file cannot be read for any reason. Prior to Ansible-2.5, setting this would only fail
if the source file was missing. The default was changed to "yes" in Ansible-2.5.
flat: # Allows you to override the default behavior of appending hostname/path/to/file to the destination. If dest ends with '/', it will use the
basename of the source file, similar to the copy module. Obviously this is only handy if the filenames are
unique.
src: # (required) The file on the remote system to fetch. This `must' be a file, not a directory. Recursive fetching may be supported in a later
release.
validate_checksum: # Verify that the source and destination checksums match after the files are fetched.
从帮助信息中可以看出,fetch 模块的作用就是”Fetches a file from remote nodes”,即”从被管理主机中拉取文件”之意,而且 fetch 模块提供了一些参数供我们使用,可用的参数有 dest、fail_on_missing、flat、src、validate_checksum ,而且帮助信息中注释了每个参数的作用。
比如 src 参数的作用就是指定从被管理主机中拉取哪个文件。
比如 dest 参数的作用就是指定拉取文件到本地以后文件存放的位置。
dest 参数和 src 参数的注释中都包含”(required)”字样,这表示在使用 fetch 模块时,dest 参数与 src参数是必须提供的,如果在使用 fetch 模块时,没有提供这两个参数,将会报错。想想也对,如果我们想要从远程主机中拉取文件,那么我们必须告诉 ansible,从哪里拉取文件,然后将文件存放到哪里。所以,在学习怎样使用一个模块时,要注意这些必选参数。
现在,我们就以 fetch 模块为例,看看怎样使用带有参数的模块。
首先来看一下主机清单配置:
[demoA]
ansible-demo1
[demoB]
ansible-demo2
ansible-demo3
[demo:children]
demoA
demoB
假如我们想要将 demoB 组中所有主机的 /testdir/testfile1 文件拉取到本地,则可以使用如下命令:
ansible demoB -m fetch -a "src=/testdir/testfile1 dest=/testdir/ansible/"
如上述命令所示,-m 选项用于调用指定的模块,”-m fetch“表示调用 fetch 模块,-a 选项用于传递模块所需要使用的参数, -a "src=/testdir/testfile1 dest=/testdir/ansible/" 表示我们在使用 fetch 模块时,为 fetch 模块传入了两个参数,src 与 dest。
我们看一下上述命令的执行效果:
从命令的执行结果可以看出,上述命令执行成功了,因为两个主机对应的返回信息都返回了”SUCCESS”字样。
为什么命令执行成功了,返回的信息却是”黄色”的,在我们的印象中,执行成功,返回的信息不应该是”绿色”的吗?这个后面我们再解释。
从返回信息可以看出,执行上述 ansible 命令后,主机 ansible-demo2 和主机 ansible-demo3 中的文件已经拉取成功,ansible-demo2 的 testfile1 文件被拷贝到了本机的 /testdir/ansible目录中,而且,ansible在 /testdir/ansible 目录中自动创建了目录结构 ansible-demo2/testdir/,由于我们是同时从多台被管理主机中拉取相同名称的文件,所以 ansible 会自动为我们创建各个主机对应的目录,以区分存放不同主机中的同名文件。是不是很方便,很人性化呢?
二、关于幂等性
在00节介绍 ansible 特点时说过,ansible 具有幂等性,幂等性能够保证我们重复的执行一项操作时,得到的结果是相同的,下面详细介绍一下幂等性的概念。
举个例子,你想把一个文件拷贝到目标主机的某个目录上,但是你不确定此目录中是否已经存在此文件,当你使用 ansible 完成这项任务时,就非常简单了,因为如果目标主机的对应目录中已经存在此文件,那么 ansible 则不会进行任何操作,如果目标主机的对应目录中并不存在此文件,ansible 就会将文件拷贝到对应目录中。说白了,ansible 是”以结果为导向的”,我们指定了一个”目标状态”,ansible 会自动判断,”当前状态”是否与”目标状态”一致,如果一致,则不进行任何操作,如果不一致,那么就将”当前状态”变成”目标状态”,这就是”幂等性”,”幂等性”可以保证我们重复的执行同一项操作时,得到的结果是一样的。
现在我们就来实验一下,看看重复执行相同的 ansible 命令时,会得到什么效果,如下图所示:
从上图可以看出,返回信息仍然包含”SUCCESS”字样,证明 ansible 命令执行成功,不过很明显,这次的返回信息为”绿色”,而且细心的你一定发现了,这次绿色的返回信息中,”changed” 字段的值为false,而之前黄色的返回信息中,”changed” 字段的值为 true。
当返回信息为绿色时,”changed” 为 false,表示 ansible 没有进行任何操作,没有”改变什么”。
当返回信息为黄色时,”changed” 为 true,表示 ansible 执行了操作,”当前状态”已经被 ansible 改变成了”目标状态”。
这就是幂等性的体现,当第一次执行上述命令时,ansible 发现当前主机中并没有我们需要的 testfile1文件,ansible 就会按照我们指定的操作,拉取 testfile1 文件,也就是说,ansible “改变”了”当前状态”,将当前”没有 testfile1 文件的状态”变为了”有 testfile1 文件的状态”。当我们再次执行同样的命令时,ansible 发现对应文件已经存在于对应目录中,于是 ansible 并没有做出任何操作,也没有进行任何改变,因为”当前状态”与我们预期的”目标状态”一致,没有必要再做出重复的无用功。
看到这里,你应该已经明白,为什么执行 ansible 命令时,会返回黄色的成功信息或者绿色的成功信息了吧?我们可以通过返回信息的颜色,更加精准的判断执行命令之前的状态是否与我们预期的一致。
从返回信息中可以看到,当 ansible 进行 fetch 操作时,会对对应文件进行哈希计算,算出文件哈希值,也就是说,如果我们改变了文件中的内容,哈希值也将随之发生改变,这个时候,即使对应目录中存在同名的文件,ansible 也会判断出两个文件属于不同的文件,因为它们的哈希值并不相同,我们来实验一下,操作如下:
如上图所示,我们在 /testdir/ansible/ansible-demo2/testdir/testfile1文件的尾部加入一个”空格”,以改变文件内容,然后又执行了 fetch 命令,结果发现,ansible-demo2 的返回信息为黄色,ansible-demo3 主机的返回信息为绿色,证明 ansible 已经做出了正确的判断,将修改过的文件替换为重新拉取的文件。
三、总结
我们对上面的一些命令进行总结,方便以后回顾:
1.列出ansible所支持的模块。
ansible-doc -l
2.查看模块的详细帮助信息,比如查看 fetch 模块的帮助。
ansible-doc -s fetch
3.调用模块,比如调用 ping模块。
ansible 192.168.128.83 -m ping
4.调用模块的同时传入模块所需要的参数,以 fetch 模块为例。
ansible 192.168.128.83 -m fetch -a "src=/testdir/testfile1 dest=/testdir/ansible/"