前言
在如今的IT环境中,服务器数量越来越多,业务流程也越来越复杂。如果还靠手工登录每台服务器操作,不仅效率低,还容易出错。这时候,自动化运维工具就成了运维工程师的"救星"。
Ansible作为其中的佼佼者,凭借简单易用、无需客户端、安全可靠的特点,成为了很多人的首选。它不用在被管理的服务器上安装额外软件,通过SSH就能实现集中管理,哪怕是新手也能快速上手。今天,我们就从基础到实战,一步步带你认识和使用Ansible。
一、Ansible 概述和运行机制
1.1 Ansible 概述
Ansible是一款面向类Unix系统的开源自动化工具,用Python语言编写。和SaltStack、Puppet这些同类工具比,它最大的优势就是"轻量级"------被管理的服务器(被控端)不需要安装任何客户端软件,只要能通过SSH访问就行。
它的核心特点特别好记:
- 部署简单:只需要在一台管理机上安装Ansible,被控端不用做任何配置
- 通信安全:基于SSH协议通信,不用额外开放端口,安全又可靠
- 配置简单:用YAML格式编写任务,像写清单一样容易理解
- 功能强大:能实现软件安装、用户管理、服务配置等各种运维操作,还支持云计算和大数据平台
这里有个小知识点:Ansible成立于2013年,2015年被红帽公司以1-1.5亿美元收购,背后有强大的技术支持。
1.2 Ansible 工作机制
Ansible的工作原理特别简单,就像"快递员送货":
- 管理员在管理端编写好要执行的任务(比如安装软件、创建用户)
- Ansible通过SSH协议,把对应的"操作模块"(相当于快递包裹)推送到每台被控端服务器
- 被控端执行完模块中的操作后,会把结果反馈给管理端
- 执行完成后,模块会自动删除,不会在被控端留下残留
整个过程不用人工干预,还能结合Git、SVN这些工具管理任务配置,方便团队协作。
1.3 Ansible 角色 (Role)
刚开始用Ansible时,任务少,配置文件也简单。但随着服务器增多、任务变复杂,配置文件会变得越来越臃肿,不好维护。这时候,"角色(Role)"就派上用场了。
Role相当于把复杂的任务拆分成一个个独立的"功能模块",比如把"安装Nginx""配置MySQL"分别做成独立的Role。这样做的好处是:
- 结构清晰,方便管理和修改
- 可以重复使用,比如在多个项目中都用到Nginx配置,直接调用现成的Role就行
- 支持从外部加载任务和变量,灵活适配不同场景
每个Role都有固定的目录结构,按照规范组织文件,后续维护起来会省心很多。
二、Ansible 环境安装部署
2.1 环境规划
我们以三台虚拟机为例,搭建一个简单的Ansible环境,具体规划如下:
| 节点类型 | IP地址 | 角色描述 |
|---|---|---|
| 管理端 | 192.168.10.23 | 安装Ansible,统一管理其他服务器 |
| 被管理端1 | 192.168.10.14 | 作为Web服务器,归为webservers组 |
| 被管理端2 | 192.168.10.15 | 作为数据库服务器,归为dbservers组 |
注意:所有服务器都需要安装CentOS/RHEL系统,并且能互相ping通。
2.2 安装步骤
Ansible只需要在管理端安装,步骤很简单:
-
首先安装EPEL源(因为Ansible不在CentOS默认的软件源里)
bashyum install -y epel-release -
安装Ansible
bashyum install -y ansible -
验证安装是否成功,输入以下命令查看版本:
bashansible --version如果能显示Ansible的版本信息,就说明安装成功了。
安装完成后,Ansible会自动创建默认目录/etc/ansible/,里面有三个重要的东西:
ansible.cfg:主配置文件,默认不用修改hosts:主机清单,用来记录被控端服务器的信息roles/:存放Role的目录,后续复杂任务会用到
2.3 主机清单配置
主机清单就是Ansible的"服务器通讯录",告诉它要管理哪些服务器,以及这些服务器属于哪个组。
编辑主机清单文件:
bash
vim /etc/ansible/hosts
在文件中添加以下内容,把被控端按功能分组:
ini
# Web服务器组,命名为webservers
[webservers]
192.168.10.14
# 数据库服务器组,命名为dbservers
[dbservers]
192.168.10.15
保存退出后,Ansible就知道要管理哪些服务器了。如果服务器的SSH端口不是默认的22,还可以在IP后面加:端口号,比如192.168.10.14:2222。
2.4 SSH免密登录配置
因为Ansible通过SSH通信,为了避免每次执行任务都输入密码,需要配置管理端到被控端的免密登录:
-
在管理端生成SSH密钥对(一路按回车就行,不用输入额外信息)
bashssh-keygen -t rsa -
把公钥复制到两台被控端服务器(替换成你的被控端IP和密码,示例密码123456)
bash# 复制到webservers组的被控端 sshpass -p '123456' ssh-copy-id root@192.168.10.14 # 复制到dbservers组的被控端 sshpass -p '123456' ssh-copy-id root@192.168.10.15 -
测试免密登录是否成功,比如登录到192.168.10.14:
bashssh root@192.168.10.14如果不用输入密码就能登录,就说明配置成功了。
三、Ansible 基础命令及模块操作
3.1 基本命令格式
Ansible的命令格式很固定,记住这个公式就能灵活使用:
bash
ansible <目标主机/组> -m <模块名> -a "<模块参数>"
<目标主机/组>:可以是单个IP(比如192.168.10.14)、组名(比如webservers),也可以用all表示所有被控端-m <模块名>:指定要使用的模块(比如安装软件用yum模块),如果省略这个参数,默认使用command模块-a "<模块参数>":模块的具体参数(比如要安装的软件名、要执行的命令)
另外,想查看某个模块的用法,可以用ansible-doc -s 模块名,比如ansible-doc -s yum就能查看yum模块的使用说明。
3.2 常用模块详解
Ansible有很多模块,每个模块对应不同的功能,下面介绍最常用的13个模块,每个模块都配了简单的示例,拿来就能用。
3.2.1 command 模块
功能:在被控端执行简单命令,不支持管道(|)、重定向(>) 这些Shell特性
示例:
bash
# 查看webservers组所有服务器的当前时间
ansible webservers -m command -a 'date'
# 查看所有被控端的/目录下的文件(省略-m,默认用command模块)
ansible all -a 'ls /'
# 执行命令前先切换到/home目录
ansible all -m command -a 'chdir=/home ls ./'
3.2.2 shell 模块
功能:和command模块类似,但支持管道、重定向 等Shell特性,适合执行复杂命令
示例:
bash
# 给dbservers组的test用户设置密码(123456)
ansible dbservers -m shell -a 'echo 123456 | passwd --stdin test'
# 获取被控端的IP地址(通过管道命令筛选)
ansible dbservers -m shell -a 'ifconfig ens33 | awk "NR==2 {print \$2}"'
注意:如果命令里有$符号,需要加\转义,否则会出错。
3.2.3 cron 模块
功能:管理被控端的计划任务(比如定时执行脚本、备份数据)
常用参数:
minute/hour/day/month/weekday:分/时/日/月/周(*/1表示每分钟,0 3 * * *表示每天凌晨3点)job:要执行的任务命令name:计划任务的名称(方便后续删除或修改)state:present(添加任务,默认)或absent(删除任务)
示例:
bash
# 给webservers组添加每分钟执行的任务(输出helloworld)
ansible webservers -m cron -a 'minute="*/1" job="/bin/echo helloworld" name="test_cron"'
# 查看webservers组的计划任务
ansible webservers -a 'crontab -l'
# 删除刚才添加的计划任务(通过名称匹配)
ansible webservers -m cron -a 'name="test_cron" state=absent'
3.2.4 user 模块
功能:管理被控端的系统用户(创建、删除、修改用户信息)
常用参数:
name:用户名(必填)state:present(创建用户)或absent(删除用户)uid:用户IDgroup:用户所属的基本组
示例:
bash
# 给dbservers组创建test01用户
ansible dbservers -m user -a 'name="test01"'
# 查看是否创建成功(查看/etc/passwd文件末尾)
ansible dbservers -a 'tail /etc/passwd'
# 删除test01用户(不删除家目录)
ansible dbservers -m user -a 'name="test01" state=absent'
3.2.5 group 模块
功能:管理被控端的系统用户组(创建、删除用户组)
示例:
bash
# 给dbservers组创建mysql用户组(GID=306)
ansible dbservers -m group -a 'name=mysql gid=306 system=yes'
# 把test01用户添加到mysql组
ansible dbservers -m user -a 'name=test01 group=mysql'
# 验证用户组配置
ansible dbservers -a 'id test01'
3.2.6 copy 模块
功能:把管理端的文件复制到被控端,或者直接在被控端创建文件并写入内容
常用参数:
src:管理端的文件路径(要复制的文件)dest:被控端的目标路径(绝对路径)content:直接写入被控端文件的内容(和src不能同时使用)owner:目标文件的属主mode:目标文件的权限(比如640、755)
示例:
bash
# 把管理端的/etc/fstab文件复制到dbservers组的/opt目录下,并重命名为fstab.bak
ansible dbservers -m copy -a 'src=/etc/fstab dest=/opt/fstab.bak owner=root mode=640'
# 直接在webservers组的/opt目录下创建hello.txt文件,写入内容helloworld
ansible webservers -m copy -a 'content="helloworld" dest=/opt/hello.txt'
3.2.7 file 模块
功能:管理被控端的文件属性(修改属主、权限)、创建/删除文件、创建软链接等
示例:
bash
# 修改/opt/fstab.bak的属主为test01,属组为mysql,权限为644
ansible dbservers -m file -a 'owner=test01 group=mysql mode=644 path=/opt/fstab.bak'
# 给/opt/fstab.bak创建软链接/opt/fstab.link
ansible dbservers -m file -a 'path=/opt/fstab.link src=/opt/fstab.bak state=link'
# 在被控端创建abc.txt文件
ansible all -m file -a 'path=/opt/abc.txt state=touch'
# 删除abc.txt文件
ansible all -m file -a 'path=/opt/abc.txt state=absent'
3.2.8 hostname 模块
功能:修改被控端的主机名
示例:
bash
# 把dbservers组的被控端主机名改为mysql01
ansible dbservers -m hostname -a 'name=mysql01'
# 验证主机名是否修改成功
ansible dbservers -a 'hostname'
3.2.9 ping 模块
功能:检测管理端和被控端的连通性(最常用的测试模块)
示例:
bash
# 测试所有被控端的连通性
ansible all -m ping
如果输出ping: "pong",说明连通正常;如果报错,需要检查SSH配置或网络连接。
3.2.10 yum 模块
功能:管理被控端的RPM软件包(安装、卸载软件)
示例:
bash
# 给webservers组安装Apache服务(httpd)
ansible webservers -m yum -a 'name=httpd'
# 卸载webservers组的httpd服务
ansible webservers -m yum -a 'name=httpd state=absent'
3.2.11 service/systemd 模块
功能:管理被控端的系统服务(启动、停止、重启、设置开机自启)
常用参数:
name:服务名称(比如httpd、mysql)state:started(启动)、stopped(停止)、restarted(重启)enabled:yes(开机自启)、no(不开机自启)
示例:
bash
# 启动webservers组的httpd服务,并设置开机自启
ansible webservers -m service -a 'name=httpd state=started enabled=yes'
# 查看httpd服务状态
ansible webservers -a 'systemctl status httpd'
# 重启httpd服务
ansible webservers -m service -a 'name=httpd state=restarted'
3.2.12 script 模块
功能:在所有被控端批量执行管理端的Shell脚本(不用把脚本传到被控端,Ansible会自动处理)
示例:
-
bash
vim test.sh写入以下内容:
bash#!/bin/bash echo "hello ansible from script" > /opt/script.txt -
给脚本添加执行权限
bashchmod +x test.sh -
在webservers组的被控端执行这个脚本
bashansible webservers -m script -a 'test.sh' -
验证执行结果(查看被控端的/opt/script.txt文件)
bashansible webservers -a 'cat /opt/script.txt'
3.2.13 setup 模块
功能:收集被控端的系统信息(比如IP地址、内存大小、磁盘信息等)
示例:
bash
# 收集所有被控端的详细信息
ansible all -m setup
# 只收集被控端的IP地址信息(通过filter筛选)
ansible all -m setup -a 'filter=*ipv4'
# 只收集被控端的内存信息
ansible all -m setup -a 'filter=ansible_memory_mb'
四、Inventory 主机清单与变量配置
4.1 主机分组管理
Inventory支持灵活的主机分组,除了前面提到的固定IP分组,还可以用"范围匹配"的方式批量添加主机,适合服务器数量多的场景。
示例:
ini
# Web服务器组,包含192.168.10.12、192.168.10.13、192.168.10.14、192.168.10.15
[webservers]
192.168.10.1[2:5]
# 数据库服务器组,包含db-a.example.org到db-f.example.org
[dbservers]
db-[a:f].example.org
这样就不用一个个写IP或主机名,大大减少了配置量。
4.2 Inventory变量配置
有时候,不同的被控端可能有不同的SSH配置(比如端口、用户名、密码),这时候可以通过变量来设置,不用每次执行命令都指定参数。
4.2.1 主机变量配置
直接在主机后面添加变量,只对该主机生效:
ini
[webservers]
# 该主机的SSH端口是2222,用户名root,密码123456
192.168.10.14 ansible_port=2222 ansible_user=root ansible_password=123456
4.2.2 组变量配置
给整个组设置变量,组内所有主机都生效:
ini
[webservers]
192.168.10.14
192.168.10.15
# webservers组的所有主机共用这些变量
[webservers:vars]
ansible_user=root
ansible_password=123456
# 所有组的主机共用的变量(全局变量)
[all:vars]
ansible_port=22
4.2.3 组嵌套配置
如果有多个小组,想把它们归为一个大组统一管理,可以用组嵌套(通过children关键字实现):
ini
# 定义两个小组:nginx组和apache组
[nginx]
192.168.10.20
192.168.10.21
[apache]
192.168.10.30
192.168.10.31
# 把nginx和apache组嵌套成webs大组
[webs:children]
nginx
apache
之后执行命令时,用webs作为目标组,就能管理所有nginx和apache组的主机了:
bash
# 查看webs大组所有主机的时间
ansible webs -a 'date'
总结
Ansible作为一款简单强大的自动化运维工具,能帮我们解决重复的运维工作,提高效率、减少错误。通过本文的介绍,你应该已经掌握了Ansible的核心概念、环境搭建、常用模块和主机清单配置。
它的优势很明显:不用装客户端、配置简单、基于SSH安全可靠,哪怕是新手也能快速上手。而且它的模块非常丰富,几乎能覆盖所有日常运维场景,从软件安装、用户管理到服务配置、任务调度,都能轻松实现。