# 一、ansible的概述
##1.1、百度百科介绍
ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。
##1.2、为什么要使用 ansible
- 提高工作的效率
- 提高工作准确度
- 减少维护的成本
- 减少重复性工作
##1.3、ansible的优点
- 管理端不需要启动服务程序(no server)
- 管理端不需要编写配置文件(/etc/ansible/ansible.cfg)
- 受控端不需要安装软件程序(libselinux-python)
- 受控端不需要启动服务程序(no agent)
- 服务程序管理操作模块众多(module)
- 利用剧本编写来实现自动化(playbook)
- 支持sudo 普通用户
##1.4、ansible架构图:
```
由上面的图可以看到 Ansible 的组成由 5 个部分组成:
Ansible: ansible 核心
Host Inventory: 定义 Ansible 管理主机清单
Plugins: 完成模块功能的补充,包括连接插件、邮件插件、日志插件等
Modules: 包括 Ansible 自带的核心模块及自定义模块
Playbooks: 剧本,定义 Ansible 多任务配置文件,由Ansible 自动执行
```
#二、ansible的安装与部署
##2.1、实验环境
| 名称 | 系统 | ip地址 | 角色 |
| ------ | ------ | ------ | ------ |
| aliyun-47.112.243.244 | centos7 | 47.112.243.244 | 管理端 |
| aliyun-47.112.242.228 | centos7 | 47.112.242.228 | 受控端 |
| aliyun-47.112.238.28 | centos7 | 47.112.238.28 | 受控端 |
| aliyun-120.79.187.66 | centos7 | 120.79.187.66 | 受控端 |
##2.2、安装步骤
```
# Centso 需要设置EPEL仓库
[root@cn-shenzhen ~]# yum install epel-release
# 使用yum 安装ansible
[root@cn-shenzhen ~]# yum install ansible
# 查看ansible 安装版本
[root@cn-shenzhen ~]# ansible --version
ansible 2.9.25
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 = /bin/ansible
python version = 2.7.5 (default, Nov 16 2020, 22:23:17) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]
```
##2.3、定义主机清单
```
[root@cn-shenzhen /]# cd /etc/ansible/
[root@cn-shenzhen ansible]# ll
total 24
-rw-r--r-- 1 root root 19985 Aug 22 04:07 ansible.cfg
-rw-r--r-- 1 root root 0 Dec 6 18:02 hosts
drwxr-xr-x 2 root root 4096 Aug 22 04:07 roles
# 操作配置文件前,习惯先备份
[root@cn-shenzhen ansible]# cp -f hosts hosts.backup
[root@cn-shenzhen ansible]# ll
total 24
-rw-r--r-- 1 root root 19985 Aug 22 04:07 ansible.cfg
-rw-r--r-- 1 root root 0 Dec 6 18:02 hosts
-rw-r--r-- 1 root root 0 Dec 6 18:54 hosts.backup
drwxr-xr-x 2 root root 4096 Aug 22 04:07 roles
# 清空hosts文件内容
[root@cn-shenzhen ansible]# cat /dev/null > hosts
[root@cn-shenzhen ansible]# cat hosts
[root@cn-shenzhen ansible]#
# 写入主机IP ,这些写了[webserver]、[other] 等都是分组,可以不写,为了方便管理
[root@ansible_server/etc/ansible]# cat hosts
[webserver]
aliyun-47.112.242.228 ansible_host=47.112.242.228 ansible_user=root ansible_ssh_private_key_file=/apphome/dev-20201029.pem
aliyun-47.112.238.28 ansible_host=47.112.238.28 ansible_user=root ansible_ssh_private_key_file=/apphome/dev-20201029.pem
# 管理120.79.187.66 作为other组
[other]
aliyun-120.79.187.66 ansible_host=120.79.187.66 ansible_user=root ansible_ssh_private_key_file=/apphome/dev-20201029.pem
# 本机也可以管理自己
[manager]
aliyun-47.112.243.244 ansible_host=47.112.243.244 ansible_user=root ansible_ssh_private_key_file=/apphome/dev-20201029.pem
```
##2.4、使用ping检查节点的连通性。**
```
# 常用参数
-i # 指定 host 文件的路径,默认是在 /etc/ansible/hosts ,用的时候可以省略
-m # 指定使用的ping模块
# web-servers 这个组名,也可以放在最后面
[root@cn-shenzhen ansible]# ansible -i /etc/ansible/hosts 'webserver' -m ping
aliyun-47.112.238.28 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
aliyun-47.112.242.228 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
[root@cn-shenzhen ansible]# ansible -i /etc/ansible/hosts 'other' -m ping
aliyun-120.79.187.66 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"ping": "pong"
}
```
#三、ansible常用模块用法
**!16Ansible基于多模块管理,常用的Ansible工具管理模块包括: command、shell、script、yum、copy、file、synchronize等。!**
###案例1:使用 command 模块
检查节点的内存情况
```
[root@cn-shenzhen ~]# ansible -m command -a "free -h" webserver
aliyun-47.112.242.228 | CHANGED | rc=0 >>
total used free shared buff/cache available
Mem: 15G 10G 545M 59M 4.3G 4.5G
Swap: 0B 0B 0B
aliyun-47.112.238.28 | CHANGED | rc=0 >>
total used free shared buff/cache available
Mem: 15G 8.2G 392M 50M 6.4G 6.4G
Swap: 0B 0B 0B
```
###案例2:使用shell模块的案例
输出服务器时间
```
[root@cn-shenzhen ansible]# ansible -i /etc/ansible/hosts webserver -m shell -a "date"
aliyun-47.112.242.228 | CHANGED | rc=0 >>
Mon Dec 6 20:00:39 CST 2021
aliyun-47.112.238.28 | CHANGED | rc=0 >>
Mon Dec 6 20:00:39 CST 2021
```
另外,我们可以看下使用shell模块检查节点内存情况的结果
```
[root@cn-shenzhen ~]# ansible -m shell -a "free -h" webserver
aliyun-47.112.242.228 | CHANGED | rc=0 >>
total used free shared buff/cache available
Mem: 15G 10G 163M 59M 4.7G 4.5G
Swap: 0B 0B 0B
aliyun-47.112.238.28 | CHANGED | rc=0 >>
total used free shared buff/cache available
Mem: 15G 8.2G 210M 50M 6.6G 6.4G
Swap: 0B 0B 0B
```
###案例3:使用script 模块
新建一个test.sh文件
```
[root@cn-shenzhen ansible]# cat test.sh
#!/bin/bash
date
hostname
echo "大家好,这是在测试!"
```
执行查看结果:
```
[root@cn-shenzhen ansible]# ansible -i /etc/ansible/hosts webserver -m script -a "/etc/ansible/test.sh"
aliyun-47.112.238.28 | CHANGED => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to 47.112.238.28 closed.\r\n",
"stderr_lines": [
"Shared connection to 47.112.238.28 closed."
],
"stdout": "Tue Dec 7 09:33:56 CST 2021\r\nsmart-home-test\r\n大家好,这是在测试!\r\n",
"stdout_lines": [
"Tue Dec 7 09:33:56 CST 2021",
"smart-home-test",
"大家好,这是在测试!"
]
}
aliyun-47.112.242.228 | CHANGED => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to 47.112.242.228 closed.\r\n",
"stderr_lines": [
"Shared connection to 47.112.242.228 closed."
],
"stdout": "Tue Dec 7 09:33:56 CST 2021\r\ncn-shenzhen.i-wz95q0maxgzx1z4bhyxp\r\n大家好,这是在测试!\r\n",
"stdout_lines": [
"Tue Dec 7 09:33:56 CST 2021",
"cn-shenzhen.i-wz95q0maxgzx1z4bhyxp",
"大家好,这是在测试!"
]
}
```
> !16总结上述3个模块的区别!
- command : ansible的默认模块,不指定-m参数的时候,使用的就是command模块; 常见的命令都可以使用,但命令的执行不是通过shell来执行的,所以< > | and & z这些操作都不可以,不支持管道,没法批量执行命令
- shell模块: 使用shell模块的时候默认是通过/bin/sh来执行的,所以在终端输入的各种命令都可以使用
- scripts模块:使用scripts模块可以在本地写一个脚本,在远程服务器上执行
###案例4:使用 yum 模块
安装/启动/卸载 locate 服务
>yum的全称是 Yellowdog Updater Modified,它是一个 C/S 架构的软件,能够对基于 RPM 格式的软件包进行管理,它提供了包括自动解决依赖关系,软件包的分组,软件包的升级等功能。谨慎执行yum update命令,切记坚决不能在生产环境执行,会炸!!!
yum模块提供的state状态:
- latest ,present,installed,这三个代表安装;
- removed, absent,这两个是卸载
```
# 远程在 other 服务器上安装 locate 服务
[root@cn-shenzhen ~]# ansible -i /etc/ansible/hosts other -m yum -a "name=mlocate state=installed"
# 远程在 other 服务器上使用locate查找nginx.conf文件
[root@cn-shenzhen ~]# ansible -i /etc/ansible/hosts other -m command -a "locate nginx.conf"
# 远程在 other 服务器上卸载 locate 服务
[root@cn-shenzhen ~]# ansible -i /etc/ansible/hosts other -m yum -a "name=mlocate state=removed"
```
###案例5:使用copy 模块
>copy模块:实现主控端向目标主机拷贝文件,类似scp功能
尝试把ansible主机的/etc/hosts 拷贝到other组机器中的/root/下
```
[root@cn-shenzhen ansible]# ansible -i /etc/ansible/hosts other -m copy -a "src=/etc/hosts dest=/root owner=root group=root mode=777"
aliyun-120.79.187.66 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"checksum": "bedc6424e2d471de1f05d2e627e1d5586ce76451",
"dest": "/root/hosts",
"gid": 0,
"group": "root",
"md5sum": "6692bf710762171e6e6301771f3c9079",
"mode": "0777",
"owner": "root",
"size": 377,
"src": "/root/.ansible/tmp/ansible-tmp-1638930180.11-24767-246994663413058/source",
"state": "file",
"uid": 0
}
```
再通过command去对应服务器查看文件是否成功复制
```
[root@cn-shenzhen ansible]# ansible -i /etc/ansible/hosts other -m command -a "ls -l /root/hosts"
aliyun-120.79.187.66 | CHANGED | rc=0 >>
-rwxrwxrwx 1 root root 377 Dec 8 02:23 /root/hosts
```
###案例6:使用 file 模块
>file模块主要用于对文件的创建、删除、修改、权限、属性的维护和管理
```
# 在other服务器上 /usr/local 目录下面创建lw文件夹,属主为root
[root@cn-shenzhen ansible]# ansible other -m file -a "path=/usr/local/lw state=directory mode=777 owner=root"
aliyun-120.79.187.66 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"gid": 0,
"group": "root",
"mode": "0777",
"owner": "root",
"path": "/usr/local/lw",
"size": 4096,
"state": "directory",
"uid": 0
}
```
再通过command去对应服务器查看文件夹是否成功创建
```
[root@cn-shenzhen ansible]# ansible -i /etc/ansible/hosts other -m command -a "ls -l /usr/local/"
aliyun-120.79.187.66 | CHANGED | rc=0 >>
total 92
drwxr-xr-x 11 root root 4096 Dec 1 04:46 aegis
drwxr-xr-x. 3 root root 4096 Mar 16 2021 bin
-rw-r--r-- 1 root root 695 Apr 9 2020 CHANGELOG.rst
drwxr-xr-x 4 root root 4096 Jun 29 2020 cloudmonitor
drwxr-xr-x. 2 root root 4096 Apr 11 2018 etc
drwxr-xr-x. 2 root root 4096 Apr 11 2018 games
drwxr-xr-x 2 root root 4096 Apr 23 2020 images
drwxr-xr-x. 3 root root 4096 Apr 11 2018 include
drwxr-xr-x. 4 root root 4096 Apr 11 2018 lib
drwxr-xr-x. 4 root root 4096 Apr 11 2018 lib64
drwxr-xr-x. 2 root root 4096 Apr 11 2018 libexec
-rw-r--r-- 1 root root 11358 Apr 9 2020 LICENSE
drwxrwxrwx 2 root root 4096 Dec 8 02:45 lw
drwxr-xr-x 3 root root 4096 Oct 21 2019 n
drwxr-xr-x 6 root root 4096 Dec 18 2020 python3
-rw-r--r-- 1 root root 4144 Apr 9 2020 README.rst
drwxr-xr-x. 2 root root 4096 Apr 11 2018 sbin
drwxr-xr-x. 12 root root 4096 Sep 22 08:19 share
drwxr-xr-x. 2 root root 4096 Jul 13 07:46 src
drwxr-xr-x 9 root root 4096 Jul 6 02:52 taos
```
###案例7:使用 synchronize 模块
>synchronize模块主要用于目录、文件同步
将本地/tmp/lw/ 目录远程同步到 other 服务器上(增量同步)
```
[root@cn-shenzhen lw]# ansible other -m synchronize -a 'src=/tmp/lw/ dest=/tmp/lw/'
aliyun-120.79.187.66 | CHANGED => {
"changed": true,
"cmd": "/bin/rsync --delay-updates -F --compress --archive --rsh=/bin/ssh -S none -i /apphome/dev-20201029.pem -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null --out-format=<<CHANGED>>%i %n%L /tmp/lw/ root@120.79.187.66:/tmp/lw/",
"msg": ".d..tp..... ./\n<f+++++++++ test.log\n",
"rc": 0,
"stdout_lines": [
".d..tp..... ./",
"<f+++++++++ test.log"
]
}
```
将本地/tmp/lw/ 目录远程同步到 other 服务器上(完全同步)
```
[root@cn-shenzhen lw]# ansible other -m synchronize -a 'src=/tmp/lw/ dest=/tmp/lw/ delete=yes'
aliyun-120.79.187.66 | CHANGED => {
"changed": true,
"cmd": "/bin/rsync --delay-updates -F --compress --archive --rsh=/bin/ssh -S none -i /apphome/dev-20201029.pem -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null --out-format=<<CHANGED>>%i %n%L /tmp/lw/ root@120.79.187.66:/tmp/lw/",
"msg": ".d..tp..... ./\n<f+++++++++ test.log\n",
"rc": 0,
"stdout_lines": [
".d..tp..... ./",
"<f+++++++++ test.log"
]
}
```
##四、ansible playbook用法
>playbook 是 ansible 用于配置,部署,和管理被控节点的剧本。通过 playbook 的详细描述,执行其中的一系列 tasks ,可以让远端主机达到预期的状态。
playbook语法
```
# Playbook是以YAML格式编写的文本文件,通常使用扩展名yml保存。Playbook使用空格字符缩进来表示其数据结构。YAML对用于缩进的空格数量没有严格的要求,但有两个基本的规则:
1)处于层次结构中同一级别的数据元素(例如同一列表中的项目)必须具有相同的缩进量。
2)如果项目属于其他项目的子项,其缩进量必须大于父项
# 只有空格字符可用于缩进,不允许使用tab键。约定俗成的缩进量一般是一级2个空格。
# Playbook开头的一行由三个破折号(---)组成,这是文档开始标记。其末尾可能使用三个圆点(...)作为文档结束标记,尽管在实践中这通常会省略。
```
下面从一个简单的例子讲解下playbook的语法
```
[root@cn-shenzhen ansible]# cat site.yml
- hosts: other
user: root
tasks:
- name: "restart redis"
shell: docker restart redis
- name: "restart nginx"
shell: docker restart nginx-ssl
```
定义了restart redis和restart nginx两个任务,执行一下看效果
```
[root@cn-shenzhen ansible]# ansible-playbook site.yml
PLAY [other] ************************************************************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************************************************************
ok: [aliyun-120.79.187.66]
TASK [restart redis] ****************************************************************************************************************************************************
changed: [aliyun-120.79.187.66]
TASK [restart nginx] ****************************************************************************************************************************************************
changed: [aliyun-120.79.187.66]
PLAY RECAP **************************************************************************************************************************************************************
aliyun-120.79.187.66 : ok=3 changed=2 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
```
github上提供了大量的实例供大家参考: https://github.com/ansible/ansible-examples