Ansible是什么
Ansible是一个流行的自动化运维工具,基于Python开发,分布式,无需客户端,轻量级,配置语法使用YMAL及Jinja2模板语言。
利用它可以做的事情:批量部署,服务安装,日常备份等。
Ansible的特性:
- 无需客户端,通过ssh协议进行通信
- 安装后无需启动服务
- 依赖大量的python模块扩展功能
- Ansible的配置文件:
/etc/ansible/ansible.cfg
Ansible的组件架构如下图:
由上图可以看到Ansible由5个部分组成:
- Ansible:Ansible核心
- Modules:包括Ansible自带的核心模块及自定义模块
- Plugins:完成模块功能的补充,包括连接插件、邮件插件等
- Playbooks:定义Ansible多任务配置文件,由Ansible自动执行
- Inventory:定义Ansible管理主机的清单
Asible无需客户端,只需要在管理节点安装Ansible即可,其工作模式如下图所示:
Ansible实践
实践环境拓扑图:
首先需要在管理节点上安装Ansible。
安装Ansible
如下安装基于CentOS 7.8。
$ cat /etc/redhat-release
CentOS Linux release 7.8.2003 (Core)
第一步:添加yum源
# epel源(扩展包)
wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
# linux镜像源
wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
第二步:安装Ansible。
yum -y install ansible
成功安装好Ansible之后,查看版本信息:
$ ansible --version
ansible 2.9.27
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 = /usr/bin/ansible
python version = 2.7.5 (default, Apr 2 2020, 13:16:51) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]
在管理节点安装完Ansible后,还需要做一些基础配置(如下示例均以主机192.168.3.141
作为被管理端)。
(1)编辑ansible主机清单
$ vim cat /etc/ansible/hosts
[web] # 指定主机分组标签
192.168.3.141
[benet:children] # 包含多个主机标签
web
(2)将管理节点的ssh公钥复制到被管理节点
$ ssh-keygen -t rsa # 执行后按三次回车键
$ ssh-copy-id root@192.168.3.141 # 该操作需要输入被管理节点的root用户密码
调用Ansible模块
当需要在被管理节点执行某些操作时,可以通过调用Ansible的模块来实现。
调用Ansible模块的执行结果会显示不同的颜色,它们的含义如下:
- 黄色:更改成功
- 绿色:没有更改(例如:被管理节点已经安装好了nginx组件,再次安装时返回结果显示绿色)
- 红色:错误
- 紫色:警告
Ansible的自带的核心模块已经非常多了,可以通过命令:ansible-doc --list
或者ansible-doc -l
查看。
在ansible 2.9.27
中自带的核心模块数量已经有3387个了:
$ ansible-doc --list|wc -l
3387
如果需要查看模块的帮助文档,执行命令:ansible-doc <模块>
。
# 查看yum模块帮助信息
$ ansible-doc yum
可以使用-s
选项查看模块的片段信息,看起来比较简洁一些。
$ ansible-doc -s yum
在管理节点成功安装好Ansible之后,通过ansible
命令调用Ansible模块,语法如下:
$ ansible [-i 主机文件] [-f 批次] [组名] [-m 模块名称] [-a 模块参数] pattern
ansible
命令参数含义如下:
-i PATH, -inventory=PATH # 指定host文件的路径,默认是在/etc/ansible/hosts
-f NUM,-forks=NUM # NUM是指定一个整数,默认是5,指定fork开启同步进程的个数
-m NAME,-module-name=NAME # 指定使用的模块名称,默认使用command模块
-a MODULE_ARGS # 指定模块的参数
-k,-ask-pass # 提示输入ssh的密码,而不是使用基于ssh的密钥认证
-sudo # 指定使用sudo获得root权限
-K,-ask-sudo-pass # 提示输入sudo密码,与-sudo一起使用
-u USERNAME,-user=USERNAME # 指定被管理端的执行用户
-C,–check # 测试此命令执行会改变什么内容,不会真正的去执行
pattern # 指定执行命令的主机标签,这个标签是在ansible主机清单文件中指定的;如果指定为"all"表示对主机清单中的所有主机执行命令
如下介绍常用的Asible模块。
command模块
仅支持简单的语法命令,语句中不能包含管道符等复杂元素。
(1)查看web主机的主机名
$ ansible web -m command -a "hostname"
192.168.3.141 | CHANGED | rc=0 >>
192.168.3.141
执行成功,返回结果显示黄色:
(2)在web主机上创建用户“zhangsan”
$ ansible web -m command -a "useradd zhangsan"
192.168.3.141 | CHANGED | rc=0 >>
shell模块
shell模块是command模块的升级版,支持复杂语句,但不支持别名。
通常使用shell模块就可以了,command模块了解即可。
# 修改web主机上新建的zhangsan用户密码为123
$ ansible web -m shell -a "echo 123|passwd --stdin zhangsan"
192.168.3.141 | CHANGED | rc=0 >>
Changing password for user zhangsan.
passwd: all authentication tokens updated successfully.
yum模块
yum模块用于在被管理节点上安装组件。
# 在web主机上安装nginx
$ ansible web -m yum -a "name=nginx state=installed"
yum模块参数含义:
- name: 安装的软件包名
- state:服务状态,可选值:
installed,present:安装软件包
removed,absent:卸载软件包
latest:安装最新软件包
service模块
service模块用于控制被管理节点上的服务。
# 关闭web主机上的nginx服务,并设置开机启动
$ ansible web -m service -a "name=nginx state=stopped enabled=yes"
service模块参数含义:
- name:指定服务名
- state:指定服务运行状态,可选值:
started:开启服务
stopped:关闭服务
reloaded:重载服务
restarted:重启服务 - enabled:是否开机自启
systemd模块
跟service
模块一样,systemd模块也是用于控制被管理节点上的服务。
# 启动web主机上的nginx服务,并取消开机启动
ansible web -m systemd -a "name=nginx state=started enabled=no"
这里有一个疑问:为什么已经有了service
模块,又存在一个与其功能相同的systemd
模块呢?
在StackOverflow上也有人提出了这个问题In Ansible, what is the difference between the service and the systemd modules?,甚至在github上还有一个issue说systemd
模块是service
模块的替代品。
实际上,我的理解是systemd
模块是对service
模块的补充和完善。为什么这么说呢?因为在systemd
模块的帮助信息中明确说明了使用systemd
模块的要求:
# 需要被管理节点是使用systemd来管理服务的,此时才能在ansible中使用systemd模块
REQUIREMENTS: A system managed by systemd.
group模块
group模块用于在被管理节点上进行用户组管理。
# (1)在所有清单主机上创建组www,gid 666
$ ansible all -m group -a "name=www gid=666"
# (2)在所有清单主机删除组www
$ ansible all -m group -a "name=www gid=666 state=absent"
grouo模块参数含义:
- name:用户组名
- gid:用户组标志
- state:添加或删除用户组,默认值为present,可选值:
absent:删除用户组
present:添加用户组
user模块
user模块用于在被管理节点上实现用户管理。
# 所有主机创建用户zhangsan
$ ansible all -m user -a "name=zhangsan"
user模块参数含义:
- name: 用户名
file模块
file模块用于在被管理节点进行文件管理操作,如:创建文件/目录,设置文件权限等
#(1)在web主机上创建backup目录,并赋权,更改属主属组
$ ansible web -m file -a "path=/backup owner=root group=root recurse=yes mode=777"
# (2)在web主机上创建test.txt文件,file模块可以创建目录又能创建文件
$ ansible web -m file -a "path=/test.txt owner=root group=root state=touch mode=777"
file模块参数含义;
- path:文件或目录路径
- owner:文件或目录所属用户
- group:文件或目录所属用户组
- recurse:为yes时表示可以递归地修改目录中文件的属性
- mode:文件目录的操作权限
- state:操作文件或目录状态,可选值:
absent:递归删除目录
hard:创建硬链接
link:创建符号链接
touch:创建一个空文件
copy模块
copy模块用于从Ansible管理节点本地复制文件到被管理节点。
# 复制本地hosts文件到web主机,并且备份web主机之前的hosts文件
$ ansible web -m copy -a "src=/etc/hosts dest=/etc/hosts backup=yes"
执行完上述操作后,在被管理节点web主机上可以看到之前的hosts文件被保存成了一个新的文件。
$ ll /etc/hosts*
-rw-r--r-- 1 root root 214 Sep 3 15:36 /etc/hosts
-rw-r--r-- 1 root root 158 Jun 7 2013 /etc/hosts.22105.2023-09-03@15:36:44~ # 这个文件是复制之前web主机本身的hosts文件
copy模块参数含义:
- src:源文件路径
- dest:目标文件路径
- backup:覆盖到目标文件前,是否提前备份
- content:添加文件内容
- group:指定属组
- owner:指定属主
- mode:指定权限
fetch模块
从被管理主机获取文件到Ansible管理节点。
# 将web主机上的nginx配置文件获取到Ansible管理节点上
$ ansible web -m fetch -a "src=/etc/nginx/nginx.conf dest=/root/ansible"
执行上述命令之后:会将web主机上的/etc/nginx/nginx.conf
下载到Ansible管理节点上的/root/ansible/
目录下,同时注意:获取到的文件会自动创建原来的目录结构。
$ pwd
/root/ansible
$ tree .
.
├── 192.168.3.141 # 注意:这个目录结构是自动创建的
│ └── etc
│ └── nginx
│ └── nginx.conf
└── script.sh
2 directories, 2 files
mount模块
mount模块用于在被管理节点上进行设备的挂载或卸载操作。
# 将web主机上的/nfs目录使用nfs协议挂载到/usr/share/nginx/html,这样/nfs路径下的内容与/usr/share/nginx/html路径下的内容就是相同的了
$ ansible web -m mount -a "src=nfs:/nfs path=/usr/share/nginx/html fstype=nfs state=mounted"
mount模块参数含义:
- src:需要挂载的设备
- path:设备挂载挂载路径
- state:对设备的操作,可选值:
mounted:挂载
unmounted:卸载
script模块
scritp模块可用于将Ansible管理节点上的脚本应用到被管理节点上去执行。
假设Ansible管理节点上存在一个脚本:
$ vim /root/ansible/script.sh
ping -c 4 baidu.com
使用script模块在被管理节点上指定该脚本:
$ ansible web -m script -a "/root/ansible/script.sh"
使用Playbook实现多任务操作
在上述实践操作中可以知道,使用Ansible模块可以很方便地实现对被管理节点的操作。但是存在一个问题:每一个模块都是单独使用的,而如果在一个业务部署中需要执行多个操作怎么办呢?当然,需要多次执行相应的模块命令,但是这不利于对操作进行复用和管理。
可以使用Ansible的Playbook来解决这个问题,具体来说就是:将多个模块命令操作编写在一个yaml文件中,这个yaml文件就是一个Playbook。
如下使用Playbook在web主机上实现nginx的安装,配置和启动。
$ cat nginx.yaml
---
- name: install nginx and start
hosts: web
tasks:
- name: install nginx
yum:
name: nginx
state: latest
- name: config nginx
copy:
src: /usr/share/nginx/html/index.html
dest: /usr/share/nginx/html/
notify: restart nginx
- name: start nginx
service:
name: nginx
state: started
enabled: yes
handlers:
- name: restart nginx
service:
name: nginx
state: restarted
编写好Playbook文件之后,可以执行测试:
# 测试Playbook文件的编排是否存在问题
$ ansible-playbook -C nginx.yaml
# 如果Playbook文件编写没有问题,就可以真正执行
$ ansible-playbook nginx.yaml
关于Palybook的具体用法详见:Ansible playbooks
虽然Playbook很好地解决了Ansible模块的编排问题,但是当需要配置更加复杂的被控端环境,那么单单的将所有的配置命令写成一个Playbook文件就可多达成百上千行,这极不利于Playbook的管理和维护。
Ansible自1.2版本之后,可以使用Roles来解决这个问题。
使用Roles实现更加复杂的编排
详见:Roles
在Terraform中调用Ansible
【参考】
Ansible自动化运维工具
CloudIaC Ansible 介绍
快速上手Ansible以及常见模块应用
3分钟了解Ansible是什么?
Ansible 的自动化运维(四)条件判断
Ansible 的自动化运维(五)角色
Ansible 批量100台服务器添加 Crontab
Ansible Playbook快速部署一主多从MySQL集群
一个现代化的 Ansible 用户界面
Ansbile官方文档
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达,在下面评论区告诉我^_^^_^