Ansible自动化运维实战

引言

在现代IT基础设施管理中,自动化运维已经成为提高效率、减少人为错误的关键手段。Ansible作为一款基于Python开发的自动化运维工具,凭借其简单易用、功能强大的特点,迅速成为运维人员的得力助手。本文将从Ansible的基础概念出发,详细介绍其安装部署、配置使用以及高级功能,帮助读者快速掌握Ansible自动化运维技能。

一、Ansible简介

1. 什么是Ansible

Logo:

Ansible是一款自动化运维工具,基于Python开发,集合了众多运维工具(如puppet、cfengine、chef、func、fabric)的优点,实现了批量系统配置、批量程序部署、批量运行命令等功能。与其他工具不同的是,Ansible采用无客户端架构,通过SSH协议与目标主机通信,无需在被控节点上安装额外的软件。

2. Ansible的工作原理

Ansible的工作原理基于以下几个核心组件:

  • 控制节点:安装Ansible的服务器,负责管理和执行自动化任务
  • 被控节点:需要被管理的服务器,通过SSH与控制节点通信
  • Inventory:主机清单,定义了Ansible需要管理的主机和主机组
  • Playbook:任务剧本,定义了一系列要执行的任务
  • 模块:Ansible执行具体操作的功能单元

二、Ansible安装部署

1. 环境准备

在开始安装Ansible之前,需要准备以下环境:

角色 IP地址 配置
Ansible服务器 192.168.100.100 安装Ansible
Ansible客户机 192.168.100.101 、 192.168.100.102、192.168.100.103、192.168.100.104 无需安装客户端

2. 安装步骤(Ansible服务器)

2.1 配置DNS解析

在Ansible服务器上配置主机名解析:

bash 复制代码
# vim /etc/hosts
192.168.100.100 ansible
192.168.100.101 host1
192.168.100.102 host2
192.168.100.103 host3
192.168.100.104 host4

2.2 安装Ansible

  1. 安装EPEL源:
bash 复制代码
# 安装epel源
 yum install -y epel-release

# 或使用阿里YUM源
rm -rf /etc/yum.repos.d/*
wget -O /etc/yum.repos.d/CentOS-Base.repo https://mirrors.aliyun.com/repo/Centos-7.repo
wget -O /etc/yum.repos.d/epel.repo https://mirrors.aliyun.com/repo/epel-7.repo
  1. 安装Ansible:
bash 复制代码
yum install -y ansible
  1. 验证安装:
bash 复制代码
# 列出所有文件
rpm -ql ansible

# 查看配置文件
rpm -qc ansible

# 查看ansible帮助
ansible --help

# 查看所有模块
ansible-doc -l

# 查看yum模块详情
ansible-doc -s yum

3. SSH密钥配置(可选)

为了实现免密码登录,可以配置SSH密钥:

bash 复制代码
# 生成密钥
ssh-keygen

# 推送公钥到目标主机
ssh-copy-id IP地址

Ansible客户机无需任何操作

三、Ansible基础配置与使用

1. 定义主机清单

编辑/etc/ansible/hosts文件,添加主机信息:

ini 复制代码
host1
host2
host3

注意此处没有添加host4

2. 测试连通性

使用ping模块测试主机连通性:

bash 复制代码
# 测试localhost连通性
ansible localhost -m ping

# 测试host1连通性
ansible host1 -m ping

# 简洁输出
ansible host1 -m ping -o

-m 指定模块。 什么功能,ping只是其中一个模块。还有shell,yum等等

3. 解决SSH连接问题

如果遇到SSH连接问题,可以使用以下方法:

bash 复制代码
# 使用用户名和密码连接
ansible host2 -m ping -u root -k -o

# 去掉yes/no询问
vim /etc/ssh/ssh_config
# 添加:StrictHostKeyChecking no
systemctl restart sshd

# 再次测试
ansible host2 -m ping -u root -k -o

4.错误示范

bash 复制代码
# 测试host4连通性
ansible host4 -m ping -u root -k -o 

# 失败,主机清单未标注host4主机。
[root@ansible ~]# ansible host4 -m ping -u root -k -o 
SSH password: 
[WARNING]: Could not match supplied host pattern, ignoring: host4
[WARNING]: No hosts matched, nothing to do

5.注意ping和ssh的区别

  • 基础概念区分 :系统原生的ping命令基于ICMP(网际消息管理协议) ,用于测试主机间网络层的连通性;而 Ansible 的ping模块,和 ICMP 协议无关。
  • 核心测试结论 :即便关闭目标主机 host1 的 sshd 进程,原生ping命令仍能完成连通性测试(网络层通畅),但此时用 Ansible 对 host1 做连通测试会失败。
  • 这证明Ansible 的 ping 模块,本质是探测目标主机的 SSH 服务 /sshd 进程是否可正常连接、完成认证,是应用层的 SSH 连通性校验,而非网络层的 ICMP ping。

四、Inventory主机清单高级配置

Inventory:清查;存货清单;财产目录;主机清单

1. 增加主机组

ini 复制代码
vim /etc/ansible/hosts
# 编辑内容如下
[webserver]
host1
host2
host3
host4

测试主机组连通性:

bash 复制代码
ansible webserver -m ping -o

# 输出结果如下
host4 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
host2 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
host3 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
host1 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}

2. 配置用户名和密码

如果你没有做SSH秘钥步骤,也可以在主机配置文件中设置主机登录信息

ini 复制代码
vim /etc/ansible/hosts
# 配置内容如下
[webserver]
host[1:4] ansible_ssh_user='root' ansible_ssh_pass='666666'

如果你的主机密码之间互不相同可以如下所示配置

bash 复制代码
[webserver]
host1 ansible_ssh_user='root' ansible_ssh_pass='777777'
host[2:4] ansible_ssh_user='root' ansible_ssh_pass='666666'

测试主机组连通性

bash 复制代码
ansible webserver -m ping -o

3. 配置端口

如果主机SSH端口不是默认的22,可以这样配置:

ini 复制代码
[webserver]
host1 ansible_ssh_user='root' ansible_ssh_pass='777777' ansible_ssh_port='2222'
host[2:4] ansible_ssh_user='root' ansible_ssh_pass='666666'

4. 组变量

ansible内部变量可以帮助我们简化主机清单的设置:

ini 复制代码
[webserver]
host[1:4]
[webserver:vars]
ansible_ssh_user='root'
ansible_ssh_pass='111111'

常用变量

5. 子分组

将不同的分组进行组合:

ini 复制代码
[apache]
host[1:2]
[nginx]
host[3:4]
[webserver:children]
apache
nginx
[webserver:vars]
ansible_ssh_user='root'
ansible_ssh_pass='666666'

6. 自定义主机列表

创建自定义主机列表文件:

ini 复制代码
# vim hostlist
[dockers]
host1
host2
[dockers:vars]
ansible_ssh_user='root'
ansible_ssh_pass='111111'

使用自定义主机列表:

bash 复制代码
[root@ansible ~]# ansible -i hostlist dockers -m ping -o
host1 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}
host2 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"}

五、Ad-Hoc命令

Ad-Hoc命令是指在ansible中需要快速执行的单条命令,并且不需要保存的命令,适用于快速操作。对于复杂的命令则为 playbook。

1. Shell模块

可以执行ansible-doc shell 语句查看使用说明

模块核心特性 :在目标主机的原生 Shell 环境 中执行命令,支持管道、重定向、通配符、变量等所有 Shell 语法(区别于 command 模块,是运维最常用执行模块)

bash 复制代码
# 获取主机名
ansible webserver -m shell -a 'hostname' -o

# 指定线程数
ansible webserver -m shell -a 'hostname' -o -f 2

# host2部署apache
ansible host2 -m shell -a 'yum -y install httpd' -o

# 查询host3系统负载
ansible host3 -m shell -a 'uptime' -o

Ansible -f/--forks 参数

  • 参数作用 :用于指定 Ansible 执行一次命令时并发运行的进程(线程)数,以此控制同时在多少台目标主机上执行任务。
  • 取值要求 :需指定为整数NUM)。
  • 默认值 :若不手动指定,默认并发数为 5

2. 复制模块

帮助:ansible-doc copy

bash 复制代码
# 复制文件
ansible webserver -m copy -a 'src=/etc/hosts dest=/tmp/2.txt owner=root group=bin mode=777'

# 备份复制
ansible webserver -m copy -a 'src=/etc/hosts dest=/tmp/2.txt owner=root group=bin mode=777 backup=yes'

backup参数:

  • 备份位置:/tmp/(和目标文件2.txt同目录)
  • 备份名称:2.txt.时间戳~
  • 仅目标文件已存在且内容不同时才备份

3. 用户模块

帮助:ansible-doc user

bash 复制代码
# 创建用户
ansible webserver -m user -a 'name=zhangsan state=present'

# 生成加密密码
[root@ansible ~]# echo '123456' | openssl passwd -1 -stdin
$1$8IcMZr1b$gHENEoMncluo4mUVhuNZG0

# 修改密码
ansible webserver -m user -a 'name=zhangsan password="$1$8IcMZr1b$gHENEoMncluo4mUVhuNZG0"'

# 修改shell
ansible webserver -m user -a 'name=zhangsan shell=/sbin/nologin append=yes'

# 删除用户
ansible webserver -m user -a 'name=zhangsan state=absent'

4. 软件包管理

帮助:ansible-doc yum

bash 复制代码
# 升级所有包
ansible host1 -m yum -a 'name="*" state=latest'

# 安装apache
ansible host2 -m yum -a 'name="httpd" state=latest'

5. 服务模块

帮助:ansible-doc service

bash 复制代码
# 启动服务
ansible host2 -m service -a 'name=httpd state=started'

# 开机启动
ansible host2 -m service -a 'name=httpd state=started enabled=yes'

# 停止服务
ansible host2 -m service -a 'name=httpd state=stopped'

# 重启服务
ansible host2 -m service -a 'name=httpd state=restarted'

# 开机禁止启动
ansible host2 -m service -a 'name=httpd state=started enabled=no'

6. 文件模块

帮助:ansible-doc file

bash 复制代码
# 创建文件
ansible host1 -m file -a 'path=/tmp/88.txt mode=777 state=touch'

# 创建目录
ansible host1 -m file -a 'path=/tmp/99 mode=777 state=directory'

7. 收集模块

帮助:ansible-doc setup

bash 复制代码
# 查询所有信息
ansible host3 -m setup

# 过滤查询IP地址
ansible host3 -m setup -a 'filter=ansible_all_ipv4_addresses'

六、Playbook与YAML语法

1. YAML基础语法

YAML是一种非标记语言,语法简洁明了:

列表

  • 键值对用 : 分隔,列表用 - 表示;
  • 语法简洁,无需多余标签,适合写配置文件。
  • 缩进表示层级关系(禁止使用 Tab,必须用空格);
yaml 复制代码
fruits:
    - Apple
    - Orange
    - Strawberry
    - Mango

格式详解:

  1. 父级键定义
    • fruits: 是一个键(Key) ,表示后续内容是 fruits 对应的值;
    • 键名后必须加冒号 :,冒号后可换行(也可直接跟值,但列表通常换行写)。
  2. 列表项格式
    • 每个列表项以 连字符 - 开头,- 后必须加一个空格
    • 所有列表项的缩进必须一致(示例中用了 4 个空格,也可用 2 个,只要统一即可);
    • 缩进表示 "属于 fruits 这个键的子元素"。

字典:

yaml 复制代码
martin:
    name: Martin D'vloper
    job: Developer
    skill: Elite

格式详解:

  1. 父级字典定义
    • martin: 是一个,对应的值是一个 "嵌套字典";
    • 同样,键名后加冒号 :,后续子元素通过缩进表示层级。
  2. 键值对格式
    • 子键(如 namejob)与值用 : 分隔,: 后必须加一个空格
    • 同一层级的子键(namejobskill缩进必须一致
    • 值可以是字符串(如 Martin D'vloper,包含单引号也无需额外转义)。

2. 编写Playbook

准备工作

bash 复制代码
# 清理环境
ansible all -m yum -a 'name=httpd state=removed' -o

# 准备配置文件
yum install -y httpd
mkdir apache
cd apache
cp -rf /etc/httpd/conf/httpd.conf .

#修改端口为8080
[root@ansible apache]# grep '^Listen' httpd.conf
Listen 8080

下面是一个部署Apache的Playbook示例:

vim apache.yaml

yaml 复制代码
- hosts: host2
  tasks:
  - name: install apache packages
    yum: name=httpd state=present
  - name: copy apache conf
    copy: src=./httpd.conf dest=/etc/httpd/conf/httpd.conf
  - name: ensure apache is running
    service: name=httpd state=started enabled=yes

3. 执行Playbook

bash 复制代码
# 检验语法
ansible-playbook apache.yaml --syntax-check

# 列出任务
ansible-playbook apache.yaml --list-tasks

# 列出主机
ansible-playbook apache.yaml --list-hosts

# 执行
ansible-playbook apache.yaml

4. 使用Handlers

Handlers 是 Ansible 中一种特殊的任务,具有以下特点:

  • 触发条件 :只有被 notify 指令 "通知" 时才会执行;
  • 触发时机 :在 Playbook 中所有 tasks 执行完毕后才运行;
  • 去重执行 :即使被多个任务多次 notify,同一个 Handler 也只会执行一次;
  • 典型场景:服务重启(如 Apache、Nginx)、配置重载等 "仅当变化时才需要做" 的操作。

当配置文件发生变化时,自动重启服务:

我们模拟一次运行,看 Ansible 是如何工作的(例如修改端口为9999):

  1. 执行任务 1(安装 Apache)
    • 如果 host2 没装过 httpd:安装软件,任务状态标记为 changed
    • 如果已经装过:不操作,任务状态标记为 ok
  2. 执行任务 2(复制配置文件)
    • 对比本地 httpd.conf 和远程/etc/httpd/conf/httpd.conf
      • 内容不一致 :覆盖远程文件,任务状态 changed → 发送 notifyrestart apache Handler;
      • 内容一致 :不操作,任务状态 ok → 不发送 notify
  3. 执行任务 3(确保服务运行)
    • 如果 httpd 没运行:启动服务,状态 changed
    • 如果已经在运行:不操作,状态 ok
  4. 执行 Handlers(仅当被 notify 时)
    • 如果任务 2 发送了 notify:在所有 tasks 执行完后,运行 restart apache Handler → 重启 Apache,让新配置生效;
    • 如果没收到 notify:跳过 Handler,不重启。

七、Role角色扮演

1. Role目录结构

Role是Ansible中Playbook的目录组织结构,将代码或文件进行模块化,成为roles的文件目录组织结构,易读,代码可重用,层次清晰。

目标:通过role远程部署nginx并配置

复制代码
roles/
├── nginx
│   ├── files
│   │   └── index.html
│   ├── handlers
│   │   └── main.yaml
│   ├── tasks
│   │   └── main.yaml
│   ├── templates
│   │   └── nginx.conf.j2
│   └── vars
│       └── main.yaml
└── site.yaml

2. 创建Role

bash 复制代码
# 创建目录结构
mkdir roles/nginx/{files,handlers,tasks,templates,vars} -p

# 创建必要文件
touch roles/site.yaml roles/nginx/{handlers,tasks,vars}/main.yaml
echo 1234 > roles/nginx/files/index.html
yum install -y nginx && cp /etc/nginx/nginx.conf roles/nginx/templates/nginx.conf.j2

3. 编写Role文件

3.1 任务文件(tasks/main.yaml)

yaml 复制代码
---
- name: install epel-release packge
  yum: name=epel-release state=latest

- name: install nginx packge
  yum: name=nginx  state=latest

- name: copy index.html
  copy: src=index.html dest=/usr/share/nginx/html/index.html

- name: copy nginx.conf template
  template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf
  notify: restart nginx

- name: make sure nginx service running
  service: name=nginx state=started enabled=yes

对迭代项的引用,固定变量名为"item",使用with_item属性给定要迭代的元素;

3.2 模板文件(templates/nginx.conf.j2)

nginx 复制代码
worker_processes {{ ansible_processor_cores }};
worker_connections {{ worker_connections }};

调用内部已知变量

3.3 变量文件(vars/main.yaml)

yaml 复制代码
worker_connections: 10240

3.4 处理程序文件(handlers/main.yaml)

yaml 复制代码
---
- name: restart nginx
  service: name=nginx state=restarted

3.5 主剧本文件(site.yaml)

yaml 复制代码
- hosts: host4
  roles:
  - nginx

4. 执行Role

bash 复制代码
# 测试语法
ansible-playbook site.yaml --syntax-check

# 实施剧本
ansible-playbook site.yaml

5.验证

八、常用技巧

1. 不同用户登录不同主机

在主机清单中设置:

ini 复制代码
[webservers]
asdf.example.com ansible_port=5000 ansible_user=alice ansible_pass=123456
jkl.example.com ansible_port=5001 ansible_user=bob ansible_pass=654321

2. 加密主机清单文件

bash 复制代码
# 加密文件
ansible-vault encrypt db_hosts

# 使用加密文件
ansible -i db_hosts --ask-vault-pass localhost -m ping

3. 条件执行

根据主机IP地址执行不同任务:

yaml 复制代码
- hosts: webserver
  tasks:
  - name: "shut down 10.18.46.37 systems"
    command: /usr/sbin/init 0
    when: ansible_all_ipv4_addresses == "10.18.46.37"

4. 循环操作

循环创建多个用户:

yaml 复制代码
- hosts: host2
  tasks:
  - name: add several users
    user: name={{ item }} state=present groups=wheel
    with_items:
       - testuser1
       - testuser2

九、总结

Ansible作为一款强大的自动化运维工具,通过简单的配置和丰富的模块,极大地提高了运维效率。本文从Ansible的基础概念出发,简单介绍了其安装部署、配置使用以及高级功能,包括Inventory配置、Ad-Hoc命令、Playbook编写和Role使用等。根据实际需求编写自动化任务,实现服务器的批量管理和配置,可以进一步探索Ansible的高级特性,如自定义模块、插件开发等,从而构建更加高效、可靠的自动化运维系统。

相关推荐
qqxhb2 小时前
23|工具生态全景:本地文件、网络、数据库、浏览器自动化
网络·数据库·自动化·ai编程·最小权限·人工确认
艾莉丝努力练剑2 小时前
C++ 核心编程练习:从基础语法到递归、重载与宏定义
linux·运维·服务器·c语言·c++·学习
Trouvaille ~3 小时前
【MySQL篇】从零开始:安装与基础概念
linux·数据库·mysql·ubuntu·c·教程·基础入门
Curtain_Gin3 小时前
windows vim 配置
linux·编辑器·vim
Dontla3 小时前
(龙虾)OpenClaw(原 Clawdbot / Moltbot)常见部署方式介绍(Linux部署、Windows桌面部署)
linux·运维·服务器
Ghost Face...3 小时前
Linux USB 全栈解析:OTG + Type-C + PD 内核架构(架构师级)
linux·c语言·架构
菜鸟z级3 小时前
在新电脑装ubuntu包
linux·运维·ubuntu
一个人旅程~3 小时前
旧笔记本电脑安装win10精简版LTSB&win10LTSC&linuxmint作为三系统的操作指导书(以DELL n4020为例)
linux·windows·经验分享·电脑
yumgpkpm3 小时前
华为昇腾910B上用Kubernetes(K8s)部署LLM(Qwen3-32B)的详细步骤,保姆级命令及方法、下载链接等
运维·服务器·华为·stable diffusion·aigc·copilot·llama