一、概述
自动化运维是指通过运维工具来解决生产中大量、繁杂的事务,监控生产环境变化、自动响应并处置事件等问题(日常检查、配置变更和软件安装),从而提升运维效率、降低重大问题发生的概率、更全面的保障生产环境
站在运维的角度来说自动化运维弥补了传统运维的人效低、响应慢,极大的提升了生产力,让人专注于生产中的关键问题。站在开发的角度来说自动化运维面向生产环境 (对象),挖掘生产环境更多的属性,总结业务生命周期的规律,找到维护业务的逻辑,从而更全面的感知、保障生产环境
自动化运维主要关注的方面:
1.管理机与被管理机的连接(管理机如何将管理指令发送给被管理机)
2.服务器信息收集(如果被管理的服务器有 centos7.9 外还有其它 linux 发行版,如 suse,ubuntu 等。当你要做的事情在不同 OS 上有所不同,你需要收集信息,并将其分开处理)
3.服务器分组(因为有些时候我要做的事情不是针对所有服务器,可能只针对某一个分组)
4.管理内容的主要分类
- 文件目录管理(包括文件的创建,删除,修改,查看状态,远程拷贝等)
- 用户和组管理
- cron 时间任务管理
- yum 源配置与通过 yum 管理软件包
- 服务管理
- 远程执行脚本
- 远程执行命令
二、ansible概述以及搭建
1.概述
1)概述
ansible 是新出现的自动化运维工具,基于 Python 开发,集合了众多运维工具(puppet、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。
ansible 是基于 paramiko 开发的,并且基于模块化工作,本身没有批量部署的能力。真正具有批量部署的是 ansible 所运行的模块,ansible 只是提供一种框架。ansible 不需要在远程主机上安装 client/agents,因为它们是基于 ssh 来和远程主机通讯的。ansible 目前已经被红帽官方收购,是自动化运维工具中大家认可度最高的,并且上手容易,学习简单。是每位运维工程师必须掌握的技能之一。
paramiko 是 Python 的一个库,实现了 SSHv2 协议 (底层使用 cryptography),后面讲 Python 的时候会着重提到。
2)特点
- 部署简单,只需在主控端部署 Ansible 环境,被控端无需做任何操作;
- 默认使用 SSH 协议对设备进行管理;
- 有大量常规运维操作模块,可实现日常绝大部分操作;
- 配置简单、功能强大、扩展性强;
- 支持 API 及自定义模块,可通过 Python 轻松扩展;
- 通过 Playbooks 来定制强大的配置、状态管理;
- 轻量级,无需在客户端安装 agent,更新时,只需在操作机上进行一次更新即可;
- 提供一个功能强大、操作性强的 Web 管理界面和 REST API 接口 ------AWX 平台;
- 幂等性:一个任务执行 1 遍和执行 n 遍效果一样,不因重复执行带来意外情况。
3)架构图

- Ansible:Ansible 核心程序。
- HostInventory:记录由 Ansible 管理的主机信息,包括端口、密码、ip 等。
- Playbooks:"剧本" YAML 格式文件,多个任务定义在一个文件中,定义主机需要调用哪些模块来完成的功能。
- CoreModules:核心模块,主要操作是通过调用核心模块来完成管理任务。
- CustomModules:自定义模块,完成核心模块无法完成的功能,支持多种语言。
- ConnectionPlugins:连接插件,Ansible 和 Host 通信使用
2.搭建
1)初始化服务器
bash
#!/bin/bash
# 1. 设置主机名
hostnamectl set-hostname $1
# 2. 修改hosts文件
echo 192.168.22.152 host01 >> /etc/hosts
echo 192.168.22.153 host02 >> /etc/hosts
echo 192.168.22.154 host03 >> /etc/hosts
# 3. 关闭防火墙
systemctl stop firewalld && systemctl disable firewalld
setenforce 0
sed -i "s/SELINUX=enforcing/SELINUX=disabled/" /etc/selinux/config
# 4. 配置yum源
cd /etc/yum.repos.d
rm -rf *
curl -o /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
yum clean all
yum makecache
yum install epel-release -y
# 5. 安装必要软件
yum install vim -y
yum install net-tools -y
yum install wget -y
yum install yum-utils -y
yum install ntp -y
# 6. 时间同步
systemctl enable ntpd --now
# 7. 重启
reboot
目标主机
hostnamectl set-hostname host01
hostnamectl set-hostname host02
hostnamectl set-hostname host03
# 修改一下ssh配置文件可以提升连接速度
vi /etc/ssh/sshd_config
所有主机都修改一下

将UseDNS改为no
2)ansible安装
只在ansible主机安装即可
yum install ansible -y
ansible --version

3.ansible命令
语法格式:
bash
ansible <host-pattern> [-f forks] [-m module_name] [-a args]
ansible 匹配主机模式 -m 模块 -a '需要执行的内容'
<host-pattern> 匹配主机的列表
- ALL 表示列表中的所有主机
ansible all -m ping #匹配所有主机
ansible "*" -m ping #匹配所有主机
ansible 192.168.1.* -m ping #匹配IP地址以192.168.1开头的主机
ansible "*srvs" -m ping #匹配分组名 以 srvs结尾的主机
ansible websrvs -m ping #匹配分组名为websrvs
4.主机清单
通过ansible的ping模块测试ansible的主机清单文件,主要验证以下几项内容:分组,子分组,组变量
需求1:ping三台主机
bash
ansible host01 -m ping
ansible host02 -m ping
ansible host03 -m ping
在刚开始的时候是ansible是不通的

主要原因
- 主机清单为空 :Ansible 加载的主机列表是空的,除了默认的
localhost外,没有任何被管理的主机配置。 - 目标主机无法匹配 :你指定的
host01不在清单中,Ansible 无法识别,因此忽略了这个目标,命令没有实际执行。
需求2:需要添加主机清单在ansible里面
bash
vim /etc/ansible/hosts
host01
host02
host03
ansible host01 -m ping

这里会报错,提示不知道ssh的密码因此需要重新添加
bash
# 一次一次执行输入,密码之后即可成功
ansible host01 -m ping -u root -k
ansible host02 -m ping -u root -k
ansible host03 -m ping -u root -k
需求3:免密登录
给每台host主机设置ssh免密登录,之后使用ping模块测试一下
bash
ssh-keygen -P '' -f /root/.ssh/id_rsa
ssh-copy-id root@host02
ssh root@host02
ansible host02 -m ping -o
需求4:添加组nginxServer,将host01,host02添加到nginxServer组中,ping组nginxServer
bash
host03
[nginxServer]
host01
host02
ansible nginxServer -m ping -o
需求5:更改host文件,给nginxServere组内的host01主机设置用户名与密码
bash
host03
[nginxServer]
host01 ansible_ssh_user=root ansible_ssh_pass="root"
host02
ansible nginxServer -m ping -o
需求6:添加分组tomcatServer,将host03添加到tomcatServer中,添加分组webServer,将nginxServer及tomcatServer添加到webServer中,ping组webServer,同时通过组变量设置组内所有机器的账号与密码
bash
[tomcatServer]
host03
[nginxServer]
host01
host02
[webServer:children]
nginxServer
tomcatServer
[webServer:vars]
ansible_ssh_user="root"
ansible_ssh_pass="root"
ansible webServer -m ping -o
这就是最终的配置文件,其中每一项配置的主要作用
- 主机分组:按功能分类服务器,批量操作指定机器[nginxServer]、[tomcatServer]
- 父子分组:层级管理,一键操作所有关联服务器[webServer:children]
- 组变量:统一配置 SSH 账号密码,简化连接,无需逐台设置[webServer:vars]
三、ansible模块
1.概述
ansible的模块就是提供了特定的功能的命令,比如之前使用的ping模块,就是用于检测目标主机是否可以联通
| 模块名 | 说明 |
|---|---|
| ping | 检查指定节点机器是否还能连通,用法很简单,不涉及参数,主机如果在线,则回复 pong |
| command 和 shell | 用于在各被管理节点运行指定的命令。shell 和 command 的区别:shell 模块可以特殊字符,而 command 是不支持 |
| copy | 在远程主机执行复制操作文件。 |
| file | 主要用于远程主机上的文件操作。 |
| fetch | 它用于从远程机器获取文件,并将其本地存储在由主机名组织的文件树中。 |
| cron | 该模块适用于管理 cron 计划任务的。 |
| yum | RedHat 和 CentOS 的软件包安装和管理工具。 |
| apt | Ubuntu/Debian 的软件包安装和管理工具。 |
| service 或 systemd | 用于管理远程主机的服务。 |
| user 模块与 group | user 模块是请求的是 useradd, userdel, usermod 三个指令,goup 模块请求的是 groupadd, groupdel, groupmod 三个指令。 |
| script | 在远程主机上执行主控端的脚本,相当于 scp+shell 组合。 |
| setup | 该模块主要用于收集信息 |
| lineinfile | 远程主机上的文件编辑模块 |
| unarchive | 用于解压文件。 |
| hostname | 修改远程主机名的模块。批量修改主机名时最好加变量,防止所有主机名一致,ansible all -m hostname -a "name=webserver1" |
| mount | 挂载文件系统。 |
| wait_for | 等待一个事情发生,然后继续。它可以等待某个端口被占用,然后再做下面的事情,也可以在一定时间超时后做另外的事。 |
2.file模块
bash
常用选项:
path: #必选项,定义文件/目录的路径
force: #需要在两种情况下强制创建软链接,一种是源文件不存在,但之后会建立的情况下;另一种是目标软链接已存在,需要先取消之前的软链,然后创建新的软链,有两个选项:yes|no
group: #定义文件/目录的属组。后面可以加上mode:定义文件/目录的权限
owner: #定义文件/目录的属主。后面必须跟上path:定义文件/目录的路径
recurse: #递归设置文件的属性,只对目录有效,后面跟上src:被链接的源文件路径,只应用于state=link的情况
dest: #被链接到的路径,只应用于state=link的情况
state: #状态,有以下选项:
directory: 如果目录不存在,就创建目录
file: 即使文件不存在,也不会被创建
link: 创建软链接
hard: 创建硬链接
touch: 如果文件不存在,则会创建一个新的文件,如果文件或目录已存在,则更新其最后修改时间
absent: 删除目录、文件或者取消链接文件
ansible语法
bash
ansible 匹配主机模式 -m 模块 -a '需要执行的内容'
# 执行以下操作
# 创建新文件
# 删除文件
# 创建软连接
# 创建文件指定所有者,权限
创建新文件,先创建文件夹,在创建目录

删除文件,直接删除了整个目录,也能直接删除文件指定文件即可
创建软链接

创建文件,指定所有者,以及权限,现在host03上面创建一个user普通用户
bash
usradd xiaohong


3.copy模块
bash
常用选项:
src: # 源文件绝对路径或相对路径
dest: # 必选项,将源文件复制到的远程主机的绝对路径
content: # 用于替换"src",可以直接指定文件的值
backup: # 当文件内容发生改变后,在覆盖之前把源文件备份,备份文件包含时间信息
directory_mode: # 递归设定目录的权限,默认为系统默认权限
force: # 当目标主机包含该文件,但内容不同时,设为"yes",表示强制覆盖;为"no",表示目标主机的目标位置不存在该文件才复制。默认为"yes"
others: # 所有的 file 模块中的选项可以在这里使用
mode: # 设置文件权限
owner: # 属主
group: # 属组
指定内容生成文件,并制定权限

在家目录中创建abc.txt文件,将文件脚背到目标主机汇总的/usr/local下面
我以test.txt命名,且将覆盖的文件进行备份

最终效果备份文件是没有被覆盖的,只有最新的文件是被覆盖的且覆盖的文件有时间
需求1: 在ansible上配置好所有的yum源,然后拷贝到webServer的远程机器上(要求目录内的内容完全一致)
ansible tomcatServer -m file -a "path=/etc/yum.repos.d/ state=absent"
ansible tomcatServer -m copy -a "src=/etc/yum.repos.d dest=/etc/"
ansible tomcatServer -m yum -a "update_cache=yes"
需求2: 使用hostname模块修改过主机名后,在ansible上修改/etc/hosts文件,并拷贝到webServer的远程机器上
4.user模块
bash
comment # 用户的描述信息
createhome # 是否创建家目录
force # 在使用state=absent时,行为与userdel -force一致.
group # 指定基本组
groups # 指定附加组,如果指定为(groups=)表示删除所有组
home # 指定用户家目录
move_home # 如果设置为home=时,试图将用户主目录移动到指定的目录
name # 指定用户名
non_unique # 该选项允许改变非唯一的用户ID值
password # 指定用户密码
remove # 在使用state=absent时,行为是与userdel -remove一致
shell # 指定默认shell
state # 设置帐号状态,不指定为创建,指定值为absent表示删除
system # 当创建一个用户,设置这个用户是系统用户。这个设置不能更改现有用户
uid # 指定用户的uid
#创建aaa用户,设置系统用户,创建家目录,执行shell类型为/sbin/nologin
#创建bbb系统用户,设置为普通用户,并且登录shell环境为/bin/bash,使用password参数传密码
#删除bbb用户不删除家目录
#删除aaa用户,同时删除家目录
练习
bash
#创建aaa用户,设置系统用户,创建家目录,执行shell类型为/sbin/nologin
ansible tomcatServer -m user -a 'name=aaa system=yes shell="/sbin/nologin"'
#创建bbb系统用户,设置为普通用户,并且登录shell环境为/bin/bash,使用password参数传密码
echo 123456 | openssl passwd -1 -stdin
ansible tomcatServer -m user -a 'name=bbb password="$1$iQYFYdvf$sKwtPk1JM/5Jchwp4PQRJ."'
#删除bbb用户不删除家目录
ansible tomcatServer -m user -a "name=bbb state=absent"
#删除aaa用户, 同时删除家目录
ansible tomcatServer -m user -a "name=aaa state=absent remove=yes"
5.yum模块
bash
常用选项:
name # 所安装的包的名称
state # present--->安装, latest--->安装最新的, absent---> 卸载软件。
update_cache # 强制更新yum的缓存
conf_file # 指定远程yum安装时所依赖的配置文件(安装本地已有的包)。
disable_pgp_check # 是否禁止GPG checking,只用于presentor latest。
disablerepo # 临时禁止使用yum库。 只用于安装或更新时。
enablerepo # 临时使用的yum库。只用于安装或更新时。
在使用yum模块之前,前提是所有目标主机的yum源已经配置好
bash
#安装vsftpd包
ansible tomcatServer -m yum -a 'name=vsftpd'
#安装vsftpd包与httpd包
ansible tomcatServer -m yum -a 'name=vsftpd,httpd'
#卸载vsftpd包
ansible tomcatServer -m yum -a 'name=vsftpd state=removed'
#安装本地的包,且排除某些包不安装
ansible tomcatServer -m yum -a "name=/tmp/*.rpm exclude=*unix* state=present"
6.server模块
bash
常用选项:
enabled=[yes|no] # 是否开机启动 默认no
name: # 必选项,服务名称
pattern: # 定义一个模式,如果通过status指令来查看服务的状态时,没有响应,就会通过ps指令在进程中根据该模式进行查找,如果匹配到,则认为该服务依然在运行
sleep: # 如果执行了restarted,在则stop和start之间沉睡几秒钟
state: # 对当前服务执行启动,停止、重启、重新加载等操作
# (started,stopped,restarted,reloaded)
# 启动vsftpd服务,并设为开机自动启动
# 关闭vsftpd服务,并设为开机不自动启动
# 启动vsftpd服务,并设为开机自动启动
ansible tomcatServer -m service -a 'name=vsftpd state=started enabled=on'
# 关闭vsftpd服务,并设为开机不自动启动
ansible tomcatServer -m service -a 'name=vsftpd state=stopped enabled=false'
7.cron模块
bash
8、cron模块
常用选项:
name # 定时任务描述
job # 指明运行的命令是什么,可以写shell命令
cron_file # 自定义cron_file的文件名,使用相对路径则在/etc/cron.d中。
user # 以哪个用户的身份执行
minute # 分(0-59, *, */N),不写时,默认为*
hour # 时(0-23, *, */N),不写时,默认为*
day # 日(1-31, *, */N),不写时,默认为*
month # 月(1-12, *, */N),不写时,默认为*
weekday # 周(0-6 for Sunday-Saturday, *),不写时,默认为*
special_time # 特殊的时间范围,参数: reboot(重启时),annually(每年),monthly(每月),weekly(每周),daily(每天),hourly(每小时)
state # 指定状态
present # 表示添加定时任务,也是默认设置
absent # 表示删除定时任务
# 创建计划任务:每周1,3,5,每分钟打印warning,任务名称:test
# 删除计划任务
# 创建计划任务:每周1,3,5,每分钟打印warning,任务名称:test
ansible tomcatServer -m cron -a 'minute=* weekday=1,3,5 job="/usr/bin/wall warning" name=test'
# 删除计划任务
ansible tomcatServer -m cron -a 'job="/usr/bin/wall warning" name=test state=absent'
8.shell模块
shell模块可以在远程主机上调用shell解释器运行命令,支持shell的各种功能
bash
ansible tomcatServer -m shell -a 'wc -l /etc/passwd'
四、playbook
1.概述
Playbooks是Ansible的配置,部署和编排语言。他们可以描述您希望在远程机器做哪些事。使用易读的YAML格式组织Playbook。
playbook是由一个或多个play组成的列表,play的主要功能在于将事先归并为一组的主机装扮成事先通过ansible中的task定义好的角色。从根本上来讲,所谓的task无非是调用ansible的一个module。将多个play组织在一个playbook中,即可以让它们联合起来按编排的机制完成某一任务。
2.核心元素
Hosts 执行的远程主机列表
Tasks 任务集
Variables 内置变量或自定义变量在playbook中调用
Templates 模板,即使用模板语法的文件,比如配置文件,模板的后缀必须为xxx.j2等
Handlers 和notify结合使用,由特定条件触发的操作,满足条件方才执行,否则不执行
tags 标签,指定某条任务执行,用于选择运行playbook中的部分代码。
remote_user: 在远程主机以哪个用户身份执行;
bash
# 图1 核心元素说明
hosts: 用于指定要执行任务的主机,其可以是一个或多个由冒号分隔主机组
remote_user: 用于指定远程主机上的执行任务的用户
tasks: 任务列表,按顺序执行任务,如果一个host执行task失败,整个tasks都会回滚,修正playbook 中的错误,然后重新执行即可
tasks:
- name: ensure apache is at the latest version
yum: name=httpd,httpd-devel state=latest
- name: write the apache config file
copy: src=/etc/httpd/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
handlers: 类似task,但需要使用notify通知调用
不管有多少个通知者进行了notify,等到play中的所有task执行完成之后,handlers也只会被执行一次
handlers最佳的应用场景是用来重启服务,或者触发系统重启操作,除此以外很少用到了
tasks:
- name: ensure apache is at the latest version
yum: name=httpd,httpd-devel state=latest
notify:
- restart apache
- name: ensure apache is running (and enable it at boot)
service: name=httpd state=started enabled=yes
handlers:
- name: restart apache
service: name=httpd state=restarted
variables: 变量,定义变量可以被多次方便调用
---
- hosts: group1
remote_user: root
vars:
- user: test1
tasks:
- name: create user
user: name={{user}} state=present
3.语法格式
bash
---
# 表示文档开始
- hosts: host01 # "- "表示一个块序列的节点,注意:横杠后面有空格,可以写主机名,主机组名,多个使用逗号隔开
remote_user: root # 指定在进行远程操作时使用root用户进行操作
tasks: # 使用tasks关键字指明要进行操作的任务列表,之后的行都属于tasks键值对中的值
- name: Ping # 每个任务都以"- "开头,每个任务都有自己的名字,任务名使用name关键字进行指定
ping: # ansible模块
- name: make directory test # 第二个任务使用file模块,使用file模块时,指定了path参数与state参数的值
file:
path: /data/test # 模块的参数
state: directory
---
# 标记文件的开始
- hosts: webserver # 指定该playbook在哪个服务器上执行
vars: # 表示下面是定义的变量
http_port: 80 # 变量的形式,key: value,这里http_port是变量名,80是值
max_clients: 200
remote_user: root # 指定远程的用户名,这里缩进和vars保持了一致,说明变量的代码块已经结束
tasks: # 下面构成playbook的tasks,每个task都有 - name: 开始,name指定该任务的名称
- name: ensure apache is at the latest version # 指定该任务的名称
yum: pkg=httpd state=latest # yum说明要使用的模块名称,后面指定对应的参数,这两行结合起来就相当于一个shell命令
- name: write the apache config file # 每个task之间可以使用空行来做区分
template: src=/srv/httpd.j2 dest=/etc/httpd.conf
# 需要说明的是缩进的意义和python中缩进的意义是一样,是来区分代码块的
4.相关命令
bash
# 检测语法
ansible-playbook --syntax-check /path/to/playbook.yaml
# 测试运行
ansible-playbook -C /path/to/playbook.yaml
# 运行
ansible-playbook /path/to/playbook.yaml
5.测试案例
需求1:使用playbook给tomcatServer主机创建用户及用户组(创建组httpd,创建用户httpd并指定主组为httpd)
bash
mkdir /etc/ansible/playboot
cd /etc/ansible/playboot
vim sysuser.yaml
---
- hosts: tomcatServer
remote_user: root
tasks:
- name: create httpd group
group: name=httpd system=yes
- name: create httpd user
user: name=httpd system=yes group=httpd
bash
# 检查执行
ansible-playbook --syntax-check sysuser.yaml # 检查语法
ansible-playbook -C sysuser.yaml # 测试运行,并不会真正的执行,也就是不会创建用户
ansible-playbook sysuser.yaml # 执行
需求2:使用playbook给tomcatserver主机安装httpd,修改httpd监听的端口号为10086,并启动(ansible机器要准备一个httpd的配置文件)
再次之前先把之前的服务器初始化一下
bash
---
- hosts: all
remote_user: root
tasks:
- name: scp init.sh
copy: src=/root/init.sh dest=/root/init.sh
- name: bash shell
shell: bash /root/init.sh
在安装httpd服务
bash
---
- hosts: tomcatServer
remote_user: root
tasks:
- name: install httpd
yum: name=httpd
- name: configure
shell: sed -i '/^Listen/c\Listen 8080' /etc/httpd/conf/httpd.conf
- name: start httpd
service: name=httpd state=started enabled=on
需求3:在需求2的基础上使用模版(端口号跟Servername使用变量的方式,使用handlers重启httpd)
要使用模板的话,需要创建一个templates的目录,目录的层级关系为:
httpd-template.yaml
templates
httpd.conf.j2
httpd.conf.j2
bash
Listen: {{http_port}}
ServerName {{Servername}}:{{http_port}}
bash
---
- hosts: tomcatServer
remote_user: root
vars:
- http_port: 8080
- Servername: localhost
tasks:
- name: install httpd
yum: name=httpd
tags: install
- name: configure
template: src=/etc/ansible/templates/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
tags: configure
notify:
- restart httpd
handlers:
- name: restart httpd
service: name=httpd state=started enabled=on
模板文件创建上述的变量会替代j2文件结尾里面的{{}}里面的内容,一般都是用模板文件