运维自动化之Ansible

ansible是什么?

借助官网上的一句话,ansible is a simple IT automation, 即ansible 是用于IT自动化管理的一个工具。

ansible能做什么?

ansible可以完成一些批量任务,或者完成一些需要经常重复的工作。

如何使用ansible?

执行如下命令前,需要进行一些配置,如下命令才能正常执行,后文中会对这些操作进行描述。

[root@ansible-centos7-shanghai-area0 ~]# ansible 10.0.2.10 -m ping # 使用ansible去ping  10.0.2.10 这台主机,“ping”是ansible中的一个模块,这个模块的作用就是ping对应的主机,ansible调用ping模块,就相当于我们手动执行ping命令一样,上述命令中的”-m ping”表示调用ping模块
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
[WARNING]: Could not match supplied host pattern, ignoring: 10.0.2.10 

想要让上述命令正常执行,则必须同时满足两个最基本的条件:

  • 条件一、ansible所在的主机可以通过ssh连接到受管主机。

  • 条件二、受管主机的IP地址等信息已经添加到ansible的”管理清单”中。

ansible不用在受管主机上安装agent,但需要依赖ssh,但在满足条件一的情况下,还要同时满足条件二,也就是说,即使ansible所在的主机能够通过ssh连接到受管主机,仍然需要将受管主机的IP地址、ssh端口号等信息添加到一个被称作为”清单(Inventory)”的配置文件中,如果对应的主机信息在ansible的”清单”中不存在,那么ansible则无法操作对应主机。


部署配置ansible管理主机

[root@ansible-centos7-shanghai-area0 ~]# yum install ansible -y # ansible会提供一个默认的”清单”,这个清单就是/etc/ansible/hosts
[root@ansible-centos7-shanghai-area0 ~]# vim /etc/ansible/hosts # 过ansible主机管理10主机,最直接的方式就是将它的IP地址写入到/etc/ansible/hosts文件中
# 10.0.2.10 ansible_port=22 ansible_user=hj ansible_ssh_pass=v2L8x;pV #ansible主机并不知道10.0.2.10这台主机的用户名和密码,ansible无法通过ssh连接到
test10 ansible_host=10.0.2.10 ansible_port=22 ansible_user=hj ansible_ssh_pass=v2L8x;pV # 为了更加方便的使用,ansible还支持对主机添加别名,当主机存在别名时,可以通过主机的”别名”管理对应主机

ansible_port 用于配置对应主机上的sshd服务端口号;
ansible_user 用于配置连接到对应主机时所使用的用户名称;
ansible_ssh_pass 用于配置对应用户的连接密码;

[root@ansible-centos7-shanghai-area0 ~]# ansible 10.0.2.10 -m ping # 正常执行,ansible主机成功的ping通了
10.0.2.10 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
} 

[root@ansible-centos7-shanghai-area0 ~]# ansible test10 -m ping
test10 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}

注意:无法通过主机的IP进行管理,除非同时使用了别名的方式与IP的方式配置两个主机条目。

[root@ansible-centos7-shanghai-area0 ~]# ssh-keygen # 在ansible主机中生成密钥
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:zbpf3x7e9VP10eSfqlLqVT3tP02rc2qOPBvRSFpAGYc root@ansible-centos7-shanghai-area0
The key's randomart image is:
+---[RSA 2048]----+
|        .++.     |
|         Eo     .|
|           o   o.|
|         o+ o ..=|
|        S.oo o oB|
|         . .o  o*|
|        . oo. .o*|
|         +ooo=.*B|
|        ooo=*+*oO|
+----[SHA256]-----+
[root@ansible-centos7-shanghai-area0 ~]# ssh-copy-id -i /root/.ssh/id_rsa.pub root@10.0.2.10 # 将生成的公钥加入到10.1.1.60的认证列表
/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
root@10.0.2.10's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'root@10.0.2.10'"
and check to make sure that only the key(s) you wanted were added.

[root@ansible-centos7-shanghai-area0 ~]# cat /etc/ansible/hosts 
# This is the default ansible 'hosts' file.
#
# It should live in /etc/ansible/hosts
#
#   - Comments begin with the '#' character
#   - Blank lines are ignored
#   - Groups of hosts are delimited by [header] elements
#   - You can enter hostnames or ip addresses
#   - A hostname/ip can be a member of multiple groups

# Ex 1: Ungrouped hosts, specify before any group headers.

## green.example.com
## blue.example.com
## 192.168.100.1
## 192.168.100.10

# Ex 2: A collection of hosts belonging to the 'webservers' group

## [webservers]
## alpha.example.org
## beta.example.org
## 192.168.1.100
## 192.168.1.110

# If you have multiple hosts following a pattern you can specify
# them like this:

## www[001:006].example.com

# Ex 3: A collection of database servers in the 'dbservers' group

## [dbservers]
## 
## db01.intranet.mydomain.net
## db02.intranet.mydomain.net
## 10.25.1.56
## 10.25.1.57

# Here's another example of host ranges, this time there are no
# leading 0s:

## db-[99:101]-node.example.com
#10.0.2.10 ansible_port=22 ansible_user=hj ansible_ssh_pass=v2L8x;pV
#test10 ansible_host=10.0.2.10 ansible_port=22 ansible_user=hj ansible_ssh_pass=v2L8x;pV
test10 ansible_host=10.0.2.10 ansible_port=22 ansible_user=root # ansible_ssh_pass 可以省略

ansible模块的基本使用

[root@ansible-centos7-shanghai-area0 ~]# ansible-doc  -l # 查看ansible都有哪些模块,
[root@ansible-centos7-shanghai-area0 ~]# ansible-doc -s ping # 使用“ansible-doc -s”命令,获取ping模块的详细使用方法,得到的信息也是比较少的,这是因为ping模块本来就比较简单,而且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.

[root@ansible-centos7-shanghai-area0 ~]# ansible test10 -m fetch -a "src=/home/hj/data/mysql-bin.log dest=/testdir/ansible" # -m选项用于调用指定的模块,-m fetch”表示调用fetch模块,-a选项用于传递模块所需要使用的参数, -a “src=/home/hj/data/mysql-bin.log dest=/testdir/ansible/”在使用fetch模块时,为fetch模块传入了两个参数,src与dest
test10 | CHANGED => {
    "changed": true,  # 幂等性的体现:当返回信息为黄色时,“changed”为true,表示ansible执行了操作,“当前状态”已经被ansible改变成了“目标状态”;当返回信息为绿色时,“changed”为false,表示ansible没有进行任何操作,没有“改变什么”。
    "checksum": "e7fad69d31d03c1f7957f2deef499f85fc97f5fa", 
    "dest": "/testdir/ansible/test10/home/hj/data/mysql-bin.log", 
    "md5sum": "5838fd7c201bc9aefd2edcb9fc523806", 
    "remote_checksum": "e7fad69d31d03c1f7957f2deef499f85fc97f5fa", 
    "remote_md5sum": null
} # 主机test10文件已经拉取成功,test10的mysql-bin.log文件被拷贝到了本机的/testdir/ansible目录中

ansible具有幂等性,幂等性能够保证重复的执行一项操作时,得到的结果是相同的。

ansible是“以结果为导向的”,通过命令行指定了一个“目标状态”,ansible会自动判断,“当前状态”是否与“目标状态”一致,如果一致,则不进行任何操作,如果不一致,那么就将“当前状态”变成“目标状态”。

[root@ansible-centos7-shanghai-area0 ~]# ansible test10 -m fetch -a "src=/home/hj/data/mysql-bin.log dest=/testdir/ansible"
test10 | SUCCESS => {
    "changed": false, 
    "checksum": "e7fad69d31d03c1f7957f2deef499f85fc97f5fa", 
    "dest": "/testdir/ansible/test10/home/hj/data/mysql-bin.log", 
    "file": "/home/hj/data/mysql-bin.log", 
    "md5sum": "5838fd7c201bc9aefd2edcb9fc523806"
} # 当第一次执行,ansible发现当前主机中并没有需要的mysql-bin.log文件,ansible就会按指定的操作,拉取mysql-bin.log文件,也就是说,ansible“改变”了“当前状态”,将当前“没有mysql-bin.log文件的状态”变为了“有mysql-bin.log文件的状态”,当再次执行同样的命令时,ansible发现对应文件已经存在与对应目录中,于是ansible并没有做出任何操作,也没有进行任何改变,因为“当前状态”与我们预期的“目标状态”一致,没有必要再做出重复的无用功。

从返回信息中可以看到,当ansible进行fetch操作时,会对对应文件进行哈希计算,算出文件哈希值,也就是说,如果我们改变了文件中的内容,哈希值也将随之发生改变,这个时候,即使对应目录中存在同名的文件,ansible也会判断出两个文件属于不同的文件,因为它们的哈希值并不相同。


ansible 常用模块之文件操作

copy模块

copy模块的作用就是拷贝文件,与fetch类似,fetch模块是从远程主机中拉取文件到ansible主机,copy模块是将ansible主机上的文件拷贝到远程主机中。

  • src参数:用于指定需要copy的文件或目录;
    • dest参数:用于指定文件将被拷贝到远程主机的哪个目录中,dest为必须参数;
    • content参数 :当不使用src指定拷贝的文件时,可以使用content直接指定文件内容,src与- – – content两个参数必有其一,否则会报错;
    • force参数 : 当远程主机的目标路径中已经存在同名文件,并且与ansible主机中的文件内容不同时,是否强制覆盖,可选值有yes和no,默认值为yes,表示覆盖,如果设置为no,则不会执行覆盖拷贝操作,远程主机中的文件保持不变;
    • backup参数 : 当远程主机的目标路径中已经存在同名文件,并且与ansible主机中的文件内容不同时,是否对远程主机的文件进行备份,可选值有yes和no,当设置为yes时,会先备份远程主机中的文件,然后再将ansible主机中的文件拷贝到远程主机;
    • owner参数 : 指定文件拷贝到远程主机后的属主,但是远程主机上必须有对应的用户,否则会报错;
    • group参数 : 指定文件拷贝到远程主机后的属组,但是远程主机上必须有对应的组,否则会报错;
    • mode参数 : 指定文件拷贝到远程主机后的权限,如果你想将权限设置为”rw-r–r–“,则可以使用mode=0644表示,如果你想要在user对应的权限位上添加执行权限,则可以使用mode=u+x表示;
[root@ansible-centos7-shanghai-area0 ~]# ansible test10 -m copy -a "src=/testdir/ansible/test10/home/hj/data/ dest=/home/hj/data_copy"
test10 | CHANGED => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": true, 
    "checksum": "e7fad69d31d03c1f7957f2deef499f85fc97f5fa", 
    "dest": "/home/hj/data_copy/mysql-bin.log", 
    "gid": 1000, 
    "group": "hj", 
    "md5sum": "5838fd7c201bc9aefd2edcb9fc523806", 
    "mode": "0664", 
    "owner": "hj", 
    "size": 42, 
    "src": "/home/hj/.ansible/tmp/ansible-tmp-1617090650.7-1662-232269174104878/source", 
    "state": "file", 
    "uid": 1000
} # 将ansible主机中/testdir/ansible/test10/home/hj/data/文件复制到远程主机的/home/hj/data_copy目录下,如果mysql-bin.log文件已经存在于远程主机的/home/hj/data_copy目录中,并且远程主机中的copytest与ansible主机中copytest文件内容不同,那么远程主机中的mysql-bin.log文件将被覆盖
上一篇
下一篇