一、Ansible介绍

Ansible 简单的说是一个配置管理系统(configuration management system)。你只需要可以使用 ssh 访问你的服务器或设备就行。它也不同于其他工具,因为它使用推送的方式,而不是像 puppet 等 那样使用拉取安装agent的方式。你可以将代码部署到任意数量的服务器上!

1、Ansible能做什么

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

  • 比如:同时在100台服务器上安装nginx服务,并在安装后启动它们。
  • 比如:将某个文件一次性拷贝到100台服务器上。
  • 比如:每当有新服务器加入工作环境时,你都要为新服务器部署某个服务,也就是说你需要经常重复的完成相同的工作。

这些场景中我们都可以使用到ansible。

2、Ansible特性

  • 模块化:调用特定的模块,完成特定任务
  • 有Paramiko,PyYAML,Jinja2(模板语言)三个关键模块
  • 支持自定义模块
  • 基于Python语言实现
  • 部署简单,基于python和SSH(默认已安装),agentless
  • 安全,基于OpenSSH
  • 支持playbook编排任务
  • 幂等性:一个任务执行1遍和执行n遍效果一样,不因重复执行带来意外情况
  • 无需代理不依赖PKI(无需ssl)
  • 可使用任何编程语言写模块
  • YAML格式,编排任务,支持丰富的数据结构
  • 较强大的多层解决方案

3、Ansible架构

  • Ansible核心组件说明:

**Ansible:**Ansible的核心程序 **Host Lnventory:**记录了每一个由Ansible管理的主机信息,信息包括ssh端口,root帐号密码,ip地址等等。可以通过file来加载,可以通过CMDB加载 **Playbooks:**YAML格式文件,多个任务定义在一个文件中,使用时可以统一调用,“剧本”用来定义那些主机需要调用那些模块来完成的功能. **Core Modules:**Ansible执行任何管理任务都不是由Ansible自己完成,而是由核心模块完成;Ansible管理主机之前,先调用core Modules中的模块,然后指明管理Host Lnventory中的主机,就可以完成管理主机。 **Custom Modules:**自定义模块,完成Ansible核心模块无法完成的功能,此模块支持任何语言编写。 **Connection Plugins:**连接插件,Ansible和Host通信使用

二、Ansible 的安装

安装方法有很多,这里仅仅以CentOS 7 yum安装为例,Ansible默认不在标准仓库中,需要用到EPEL源。

yum install ansible -y
[root@monitor ~]# ansible --version
ansible 2.6.2
  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.6/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.6.6 (r266:84292, Jul 23 2015, 15:22:56) [GCC 4.4.7 20120313 (Red Hat 4.4.7-11)]

三、Ansible 配置

1、实验环境

我这里主要是拿这几台设备进行测试,分组是随意的。

IP 系统 功能
10.0.0.14 CentOS 6.7 ansible主控服务器
10.0.0.4 CentOS 7.3 cluster1
10.0.0.9 CentOS 6.6 cluster1
10.0.0.19 CentOS 6.9 cluster2
10.0.0.20 CentOS 6.5 cluster2
10.0.0.21 CentOS 6.5 cluster2

2、Inventory 主机清单

在主控服务器上面配置清单。

# cat /etc/ansible/hosts
[cluster1]
10.0.0.4
10.0.0.9
[cluster2]
10.0.0.19
10.0.0.20
10.0.0.21

3、配置无密码通信

这里配置比较简单,自行操作一下。

4、测试 ping

[root@monitor ~]# ansible all -m ping
10.0.0.4 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
10.0.0.19 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
10.0.0.21 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
10.0.0.20 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}
10.0.0.9 | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}

四、Ansible 模块

ansible 使用方法

ansible <host-pattern> [-m module_name] [options]
指令 匹配规则的主机清单 -m 模块名 选项

查看模块使用方法

ansible-doc -s MODULE_NAME

1、ping

功能:尝试连接到主机,验证并返回pong成功。

对于Windows目标,请改用win_ping模块 不使用icmp协议,使用ssh协议。

# ansible all -m ping
10.0.0.4 | SUCCESS => {
    "changed": false, 
    "ping": "pong"             # 返回pong表明成功通讯
}

2、command

功能:在远程节点上执行命令

变量和操作符号 "<", ">", "|", ";" and "&" 不能正常工作。如果需要使用,请使用 shell 模块 Ansible 默认不指定模块时,将使用此模块。

[root@monitor ~]# ansible cluster1 -a 'date'
10.0.0.4 | SUCCESS | rc=0 >>
Thu Sep 13 17:00:23 CST 2018

10.0.0.9 | SUCCESS | rc=0 >>
Thu Sep 13 17:00:33 CST 2018

3、shell

功能:在远程节点上执行命令。

与command模快使用一致,但是,变量 和操作符号 "<", ">", "|", ";" and "&" 能正常工作。

我这里使用通配符,使用command模块是不行的。

# ansible cluster1 -m command -a 'ls -d /usr/local/tomcat0[1-3]'
10.0.0.4 | FAILED | rc=2 >>
ls: cannot access /usr/local/tomcat0[1-3]: No such file or directorynon-zero return code

10.0.0.9 | FAILED | rc=2 >>
ls: cannot access /usr/local/tomcat0[1-3]: No such file or directorynon-zero return code

改成shell模块就可以。

# ansible cluster1 -m shell -a 'ls -d /usr/local/tomcat0[1-3]'       
10.0.0.4 | SUCCESS | rc=0 >>
/usr/local/tomcat01
/usr/local/tomcat02
/usr/local/tomcat03

10.0.0.9 | SUCCESS | rc=0 >>
/usr/local/tomcat01
/usr/local/tomcat02
/usr/local/tomcat03

4、cron

功能:管理计划任务

backup:对远程主机上的原任务计划内容修改之前做备份 cron_file:如果指定该选项,则用该文件替换远程主机上的cron.d目录下的用户的任务计划 day:日(1-31,/2,……) hour:小时(0-23,/2,……)
minute:分钟(0-59,/2,……) month:月(1-12,/2,……) weekday:周(0-7,*,……) job:要执行的任务,依赖于state=present name:该任务的描述 special_time:指定什么时候执行,参数:reboot,yearly,annually,monthly,weekly,daily,hourly state:确认该任务计划是创建还是删除 user:以哪个用户的身份执行

  • 创建一个定时任务。
# ansible cluster1 -m cron -a 'name="test cron job" minute=*/2 job="/usr/bin/wall hello world"'  
10.0.0.4 | SUCCESS => {
    "changed": true, 
    "envs": [], 
    "jobs": [
        "test cron job"
    ]
}
10.0.0.9 | SUCCESS => {
    "changed": true, 
    "envs": [], 
    "jobs": [
        "test cron job"
    ]
}
  • 查看创建的任务
# ansible cluster1 -a 'crontab -l'
10.0.0.4 | SUCCESS | rc=0 >>
42 5 * * * /usr/sbin/ntpdate time1.aliyun.com
#Ansible: test cron job
*/2 * * * * /usr/bin/wall hello world

10.0.0.9 | SUCCESS | rc=0 >>
23 15 * * * /usr/sbin/ntpdate time1.aliyun.com
#Ansible: test cron job
*/2 * * * * /usr/bin/wall hello world
  • 删除定时任务
# ansible cluster1 -m cron -a 'name="test cron job" minute=*/2 job="/usr/bin/wall hello world" state=absent'
10.0.0.4 | SUCCESS => {
    "changed": true, 
    "envs": [], 
    "jobs": []
}
10.0.0.9 | SUCCESS => {
    "changed": true, 
    "envs": [], 
    "jobs": []
}

5、fetch

功能:从远程节点获取文件(只能是文件)到本地目录,默认会以主机清单中的主机名为目录存放获取到的文件。

注意,src=/var/log/mess* 这种通配符语法是不支持的

# ansible cluster1 -m fetch -a 'src=/var/log/messages dest=/root'
10.0.0.4 | SUCCESS => {
    "changed": true, 
    "checksum": "dc5e292dc6800090cff7be7dba7bdfd2aa2437c9", 
    "dest": "/root/10.0.0.4/var/log/messages", 
    "md5sum": "b6464134c74148dc34a6c0274eb73c7b", 
    "remote_checksum": "dc5e292dc6800090cff7be7dba7bdfd2aa2437c9", 
    "remote_md5sum": null
}
10.0.0.19 | SUCCESS => {
    "changed": true, 
    "checksum": "40582aad25f55ed6a0a70eefbfecc1555f90bfb1", 
    "dest": "/root/10.0.0.19/var/log/messages", 
    "md5sum": "688372b69571788bd144b956c73181b7", 
    "remote_checksum": "40582aad25f55ed6a0a70eefbfecc1555f90bfb1", 
    "remote_md5sum": null
}

6、script

功能:把脚本复制到远程节点后,在远程节点本地运行脚本。

给定的脚本将通过远程节点上的shell环境进行处理。 这个模块在远程系统上不需要python,就像原始脚本一样。

# ansible cluster1 -m script -a '/root/date.sh'
10.0.0.4 | SUCCESS => {
    "changed": true, 
    "rc": 0, 
    "stderr": "Shared connection to 10.0.0.4 closed.\r\n", 
    "stderr_lines": [
        "Shared connection to 10.0.0.4 closed."
    ], 
    "stdout": "Fri Sep 14 11:42:26 CST 2018\r\n", 
    "stdout_lines": [
        "Fri Sep 14 11:42:26 CST 2018"
    ]
}
10.0.0.9 | SUCCESS => {
    "changed": true, 
    "rc": 0, 
    "stderr": "Shared connection to 10.0.0.9 closed.\r\n", 
    "stderr_lines": [
        "Shared connection to 10.0.0.9 closed."
    ], 
    "stdout": "Fri Sep 14 11:42:39 CST 2018\r\n", 
    "stdout_lines": [
        "Fri Sep 14 11:42:39 CST 2018"
    ]
}

7、copy

功能:复制文件或目录到远程节点。默认会覆盖目标文件。

**backup:**在覆盖之前将原文件备份,备份文件包含时间信息。有两个选项:yes|no **content:**用于替代"src",可以直接设定指定文件的内容,相当于echo 重定向内容到文件 **dest:**必选项。要将源文件复制到的远程主机的绝对路径,如果源文件是一个目录,那么该路径也必须是个目录 **directory_mode:**递归的设定目录的权限,默认为系统默认权限 **force:**如果目标主机包含该文件,但内容不同,如果设置为yes,则强制覆盖,如果为no,则只有当目标主机的目标位置不存在该文件时,才复制。默认为yes **others:**所有的file模块里的选项都可以在这里使用 **src:**要复制到远程主机的文件在本地的地址,可以是绝对路径,也可以是相对路径。如果路径是一个目录,它将递归复制。在这种情况下,如果路径使用"/"来结尾,则只复制目录里的内容,如果没有使用"/"来结尾,则包含目录在内的整个内容全部复制,类似于rsync。

# ansible cluster1 -m copy -a 'src=/root/date.sh dest=/tmp' 
10.0.0.4 | SUCCESS => {
    "changed": true, 
    "checksum": "782d676e0b7dd360d486f89a77a03eb4623dfc6b", 
    "dest": "/tmp/date.sh", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "7c73186c5baeeced9773809d51f55903", 
    "mode": "0644", 
    "owner": "root", 
    "secontext": "unconfined_u:object_r:admin_home_t:s0", 
    "size": 17, 
    "src": "/root/.ansible/tmp/ansible-tmp-1536896736.17-200166515132170/source", 
    "state": "file", 
    "uid": 0
}
10.0.0.9 | SUCCESS => {
    "changed": true, 
    "checksum": "782d676e0b7dd360d486f89a77a03eb4623dfc6b", 
    "dest": "/tmp/date.sh", 
    "gid": 0, 
    "group": "root", 
    "md5sum": "7c73186c5baeeced9773809d51f55903", 
    "mode": "0644", 
    "owner": "root", 
    "size": 17, 
    "src": "/root/.ansible/tmp/ansible-tmp-1536896736.17-253235719611601/source", 
    "state": "file", 
    "uid": 0
}

8、file

功能:设置远程节点的文件的文件属性。

**force:**需要在两种情况下强制创建软链接,一种是源文件不存在但之后会建立的情况下;另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,有两个选项:yes|no **group:**定义文件/目录的属组 **mode:**定义文件/目录的权限 **owner:**定义文件/目录的属主 **path:**必选项,定义文件/目录的路径 **recurse:**递归的设置文件的属性,只对目录有效 **src:**要被链接的源文件的路径,只应用于state=link的情况 **dest:**被链接到的路径,只应用于state=link的情况 state: 操作方法 directory:如果目录不存在,创建目录 file:即使文件不存在,也不会被创建 link:创建软链接 hard:创建硬链接 touch:如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间 absent:删除目录、文件或者取消链接文件。相当于rm -rf

  • 创建空文件,类似于touch。
ansible cluster1 -m file -a 'path=/tmp/abc.txt state=touch mode=666'
  • 创建空目录, 类似于mkdir -p。
ansible cluster1 -m file -a 'path=/tmp/abc state=directory mode=666 owner=ftp'

创建软链接。

ansible cluster1 -m file -a 'path=/tmp/abc/abc.txt state=link src=/tmp/abc.txt'

9、yum

功能:使用yum包管理器来管理软件包。

**config_file:**yum的配置文件 **disable_gpg_check:**关闭gpg_check **disablerepo:**不启用某个源 **enablerepo:**启用某个源 **name:**要进行操作的软件包的名字,也可以传递一个url或者一个本地的rpm包的路径 state: (present' orinstalled', latest'), or remove (absent' or `removed')

ansible all -m yum -a 'name=tree state=present'
# ansible all -a 'rpm -q tree' -o                
10.0.0.4 | CHANGED | rc=0 | (stdout) tree-1.6.0-10.el7.x86_64
10.0.0.19 | CHANGED | rc=0 | (stdout) tree-1.5.3-3.el6.x86_64
10.0.0.21 | CHANGED | rc=0 | (stdout) tree-1.5.3-3.el6.x86_64
10.0.0.20 | CHANGED | rc=0 | (stdout) tree-1.5.3-3.el6.x86_64
10.0.0.9 | CHANGED | rc=0 | (stdout) tree-1.5.3-3.el6.x86_64

10、service

功能:配置管理服务。

**arguments:**给命令行提供一些选项 。可以使用别名 args **enabled:**是否开机启动 yes|no **name:**必选项,服务名称 **pattern:**定义一个模式,如果通过status指令来查看服务的状态时,没有响应,就会通过ps指令在进程中根据该模式进行查找,如果匹配到,则认为该服务依然在运行 **runlevel:**运行级别 **sleep:**如果执行了restarted,在则stop和start之间沉睡几秒钟 **state:**对当前服务执行启动,停止、重启、重新加载等操作(started,stopped,restarted,reloaded)

ansible cluster1 -m service -a 'name=haproxy state=started' 

11、setup

功能:收集关于远程主机的信息。

ansible cluster1 -m setup

等等等等,如果查看支持哪些模块,可以使用命令ansible-doc -l,要查看模块的详细使用方法,可以使用命令ansible-doc -s MODULE_NAME来进行查看。