Ansible自动化运维实战

引言

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

Ansible简介

什么是Ansible

Logo:image-20260324115237186

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

Ansible的工作原理

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

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

Ansible安装部署

环境准备

在开始安装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无需安装客户端

安装步骤(Ansible服务器)

配置DNS解析

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

# 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

安装Ansible

  1. 安装EPEL源:
# 安装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:
yum install -y ansible
  1. 验证安装:
# 列出所有文件
rpm -ql ansible

# 查看配置文件
rpm -qc ansible

# 查看ansible帮助
ansible --help

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

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

SSH密钥配置(可选)

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

# 生成密钥
ssh-keygen

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

Ansible客户机无需任何操作

Ansible基础配置与使用

定义主机清单

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

host1
host2
host3

注意此处没有添加host4

测试连通性

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

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

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

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

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

解决SSH连接问题

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

# 使用用户名和密码连接
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

错误示范

# 测试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

注意ping和ssh的区别

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

Inventory主机清单高级配置

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

增加主机组

vim /etc/ansible/hosts
# 编辑内容如下
[webserver]
host1
host2
host3
host4

测试主机组连通性:

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"}

配置用户名和密码

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

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

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

[webserver]
host1 ansible_ssh_user='root' ansible_ssh_pass='777777'
host[2:4] ansible_ssh_user='root' ansible_ssh_pass='666666'

测试主机组连通性

ansible webserver -m ping -o

配置端口

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

[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'

组变量

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

[webserver]
host[1:4]
[webserver:vars]
ansible_ssh_user='root' ansible_ssh_pass='111111'

常用变量

image-20260324153937348

子分组

将不同的分组进行组合:

[apache]
host[1:2]
[nginx]
host[3:4]
[webserver:children]
apache
nginx
[webserver:vars]
ansible_ssh_user='root' ansible_ssh_pass='666666'

自定义主机列表

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

# vim hostlist
[dockers]
host1
host2
[dockers:vars]
ansible_ssh_user='root' ansible_ssh_pass='111111'

使用自定义主机列表:

[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。

Shell模块

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

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

# 获取主机名
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

复制模块

帮助:ansible-doc copy

# 复制文件
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.时间戳~
  • 仅目标文件已存在且内容不同时才备份

用户模块

帮助:ansible-doc user

# 创建用户
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'

软件包管理

帮助:ansible-doc yum

# 升级所有包
ansible host1 -m yum -a 'name="*" state=latest'

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

服务模块

帮助:ansible-doc service

# 启动服务
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'

文件模块

帮助:ansible-doc file

# 创建文件
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'

收集模块

帮助:ansible-doc setup

# 查询所有信息
ansible host3 -m setup

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

Playbook与YAML语法

YAML基础语法

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

列表

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

格式详解:

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

字典:

martin:
    name: Martin D'vloper
    job: Developer
    skill: Elite

格式详解:

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

编写Playbook

准备工作

# 清理环境
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

- 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

执行Playbook

# 检验语法
ansible-playbook apache.yaml --syntax-check

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

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

# 执行
ansible-playbook apache.yaml

使用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角色扮演

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

创建Role

# 创建目录结构
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

编写Role文件

任务文件(tasks/main.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属性给定要迭代的元素;

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

worker_processes {{ ansible_processor_cores }};
worker_connections {{ worker_connections }};

调用内部已知变量

变量文件(vars/main.yaml)

worker_connections: 10240

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

---
- name: restart nginx
  service: name=nginx state=restarted

主剧本文件(site.yaml)

- hosts: host4
  roles:
  - nginx

执行Role

# 测试语法
ansible-playbook site.yaml --syntax-check

# 实施剧本
ansible-playbook site.yaml

验证

常用技巧

不同用户登录不同主机

在主机清单中设置:

[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

加密主机清单文件

# 加密文件
ansible-vault encrypt db_hosts

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

条件执行

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

- 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"

循环操作

循环创建多个用户:

- 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的高级特性,如自定义模块、插件开发等,从而构建更加高效、可靠的自动化运维系统。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇