+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
张贺,多年互联网行业工作经验,担任过网络工程师、系统集成工程师、LINUX系统运维工程师
个人网站:www.zhanghehe.cn
笔者微信:zhanghe15069028807,现居济南历下区
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-


一、基础概念

ansible是什么?

ansible是通过调用ssh协议进行批量配置和管理的软件。

为什么用ansible?

如果我们只有两台主机,根本没必要用ansible,但是假如我们有50多台主机,要统一进行修改配置,一台台的改工作量太大了,我们这时就可以用ansible工具,统一对50台主机同时进行连接并修改配置,仅需要一次的操作,减少重复性的操作,大大提高了运维人员的效率。

ansible可以做些什么?

  • 批量命令执行
  • 批量同步配置文件
  • 批量代码部署

ansible的特点和优势

  • 只需要在控制端安装ansible软件,受控端保证ssh正常运行即可,并不用启动服务。

  • 修改配置之后不用重读,立马生效。

  • 模块相当于ansible的命令,而playbook相当于脚本。

ansible的架构组成

  • host inventory:主机清单

  • playbook:任务剧本

  • core modules:核心模块

  • commection plugin:连接插件

ansible的执行流程

  1. ansible读取playbook中的剧本,剧本中会记录将要对哪些主机执行哪些任务。
  2. ansible通过主机清单找到要执行的主机,然后调用具体的模块(相当于不同功能的命令)
  3. 然后,通过连接插件连接对应的主机下发任务列表。
  4. 最后受控端主机将下发来的任务解析成本地shell命令执行。

怎么用ansible?

至于怎么用ansible,那正是这一节的主要内容所在。

与ansible同类型的工具,比较出名的就属salstack

二、基本操作

安装

安装之前准备epel源:

yum -y install ansible
ansible --version
ansible 2.9.1

推送公钥

ansible默认是使用公钥进行连接受控端的,在使用ansible之前要先将ansible的公钥推送到三台受控端。

如果受控端数量较少,可以手动推送公钥,如果受控端数量较多,就使用脚本推送公钥。当前受控端有三台主机

  • 192.168.80.62
  • 192.168.80.63
  • 192.168.80.64

手动推送公钥的步骤:

  1. 主控端ansible通过ssh-keygen生成一对密钥,会自动存放在家目录的.ssh/authorized_keys文件下

  2. 然后通过ssh-copy-id把公钥上传到被控端,会自动保存在目的用户家目录下的.ssh/

//生成公钥,一路回车
[root@ansible ~]# ssh-keygen   
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): 
Created directory '/root/.ssh'.
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:GS0Cof8VpoMGy9QfS9ICN1ZFrpwWHo5ED9zrPYBSZlo root@ansible
The key's randomart image is:
+---[RSA 2048]----+
|  ..O+.oo        |
|   BE*.. .       |
|  +*=.O.* .      |
| oo=.@o@ =       |
|  o.=.%oS        |
|   . o.oo        |
|      .  .       |
|                 |
|                 |
+----[SHA256]-----+

//发现有两个密钥
[root@ansible .ssh]# ls
id_rsa  id_rsa.pub

//这样就可以推送了,交互式输入yes和被控端的密码
[root@ansible ~]# ssh-copy-id 192.168.80.62 

脚本推送公钥的步骤:

//找个文件把受控端IP和密码写好,中间用空格隔开
[root@ansible ~]# cat host
192.168.80.62 cba-123
192.168.80.63 cba-123
192.168.80.64 cba-123

[root@ansible ~]# vim push_pub_key.sh 
#!/bin/bash
#先定义一个函数expect
expect () {
/usr/bin/expect <<-EOF
spawn ssh-copy-id root@$ADDR
expect {
"yes/no" { send "yes\r"; exp_continue }
"password:" { send $PASSWD\r }
}
expect eof
EOF
}           #函数在此结束

SERVERHOST=./host

for ADDR in `cut -d" " -f1 $SERVERHOST`;do  #这一cut把所有的ip全都列出来了
PASSWD=$(grep $ADDR $SERVERHOST | cut -d" " -f2)
test -f ~/.ssh/id_rsa
    if [ $? -ne 0 ];then
        ssh-keygen -P "" -f ~/.ssh/id_rsa &>/dev/null
        expect
        echo "key already send!"
    else
        expect
        echo "key already send!!"
    fi
done

由于此章节是讲ansible,所以对shell脚本不做过多的解释,如果想看具体的解释,请点击我的博客链接,传送门

定义主机清单

所谓的定义主机清单就是告诉ansible程序,要连接哪些主机的IP,也可以使用主机名,支持组;

[root@ansible ~]# vim /etc/ansible/hosts
[test]
192.168.80.62
192.168.80.63
192.168.80.64
//列出test组的主机
[root@ansible ~]# ansible test --list-host
  hosts (3):
    192.168.80.62
    192.168.80.63
    192.168.80.64
    
//列出所有主机
[root@ansible ~]# ansible all --list-host
  hosts (3):
    192.168.80.62
    192.168.80.63
    192.168.80.64

推送完公钥、定义完主机清单,测试一下是否可以使用了,用ping模块,这个模块不是网络当中的ping,而仅是测试ansible与受控端的连通性而已。

//ansible后面直接跟组名,-m是指定模块,这里我们使用ping模块,测试成功,全是绿色的。
[root@ansible ~]# ansible test -m ping
192.168.80.62 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
192.168.80.63 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
192.168.80.64 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "ping": "pong"
}
  • 绿色代表被管理主机没有被修改
  • 黄色代表被管理主机发现变更
  • 红色代表出现故障,注意查看提示原因

ad-hoc(远程执行命令)

什么是ad-hoc?

其实就是远程对主机清单里面的主机执行命令,这些命令是临时执行,执行完就结束了,并不会保存。

ad-hoc的使用场景

比如在多台机器上查看某个进程是否启动

ad-hoc的格式

ansible <组名> -m <模块名称> -a <具体命令>

模块可以不写,默认是command,如ansible test -m command -a 'hostname' 可以简写成如下格式:

//ansible后面直接写组名,-a 后面加上单引号,把命令引起来就可以了
[root@ansible ~]# ansible test -a 'hostname'
192.168.80.64 | CHANGED | rc=0 >>
backup

192.168.80.63 | CHANGED | rc=0 >>
nfs

192.168.80.62 | CHANGED | rc=0 >>
nginx

ad-hoc缺点就是不太支持管道和&符号,一用就报错,如果想让其支持管道的话,就用shell模块,如下

//在command模块中使用管道会报错,红色
[root@ansible ~]# ansible test -a 'df -h | head -2'
192.168.80.64 | FAILED | rc=1 >>
df: invalid option -- '2'
Try 'df --help' for more information.non-zero return code

192.168.80.62 | FAILED | rc=1 >>
df: invalid option -- '2'
Try 'df --help' for more information.non-zero return code

192.168.80.63 | FAILED | rc=1 >>
df: invalid option -- '2'
Try 'df --help' for more information.non-zero return code

//使用shell模块就好了
[root@ansible ~]# ansible test -m shell -a 'df -h | head -2'
192.168.80.62 | CHANGED | rc=0 >>
Filesystem               Size  Used Avail Use% Mounted on
/dev/mapper/centos-root   45G  1.7G   44G   4% /

192.168.80.63 | CHANGED | rc=0 >>
Filesystem               Size  Used Avail Use% Mounted on
/dev/mapper/centos-root   45G  1.7G   44G   4% /

192.168.80.64 | CHANGED | rc=0 >>
Filesystem               Size  Used Avail Use% Mounted on
/dev/mapper/centos-root   45G  1.7G   44G   4% /

shell模块是万能的,啥都能执行,那我们干脆只学shell模块不就行了,干吗还要学习其他的模块呢?是因为shell模块不管对方是什么状态,都要将命令在对方执行一次,而其他模块会判断,判断对方当前的状态是什么,如果的对方的状态就是我们希望的,那就不执行,如果不是,就执行,这样多好,我们下面来举一个例子:

[root@ansible ~]# ansible test -m shell -a 'yum -y install vim'

上述命令,无论你执行多少次都会显示黄色,而黄色代表对方被更改,其实只有第一次被更改,后面都是重复的,按理说除了第一次都应该显示绿色,但是通过shell模块不会判断对方的状态,我们如果使用专门的安装模块结果就变成我们想要的,如果受控端已经安装了vim,就不会再执行安装了,不被更改就显示绿色,如下所示:

[root@web1 ~]# ansible-doc yum    #找到帮助示例学习一下yum模块的使用
EXAMPLES:

- name: install the latest version of Apache   #将这个安装apache的写法转换成临时命令的写法
  yum:
    name: httpd    #模块是httpd
    state: latest  #方法是latest(更新),absent(移除),present(安装)
    
[root@ansible ~]# ansible test -m yum -a 'name=vim state=present'