48.Ansible自动化

文章目录

  • Ansible自动化
    • [01-Ansible 自动化介绍](#01-Ansible 自动化介绍)
      • [Ansible 自动化介绍](#Ansible 自动化介绍)
    • [Ansible 部署](#Ansible 部署)
    • [02-Ansible 基本使用](#02-Ansible 基本使用)
      • [Ansible 清单](#Ansible 清单)
        • [Ansible 软件包文件结构](#Ansible 软件包文件结构)
        • 主机清单定义与分类
        • 静态主机清单配置示例
          • [1. 最简单的静态清单(仅列主机 / IP)](#1. 最简单的静态清单(仅列主机 / IP))
          • [2. 主机组配置](#2. 主机组配置)
          • [3. 主机组嵌套](#3. 主机组嵌套)
          • [4. 范围简写(简化大量主机配置)](#4. 范围简写(简化大量主机配置))
        • [ansible-inventory 命令(清单查看工具)](#ansible-inventory 命令(清单查看工具))
          • [1. 命令帮助](#1. 命令帮助)
          • [2. 常用操作](#2. 常用操作)
      • [管理 ANSIBLE 配置文件](#管理 ANSIBLE 配置文件)
      • [运行 AD HOC 命令](#运行 AD HOC 命令)
        • 实验环境准备
        • [AD HOC 命令基础](#AD HOC 命令基础)
          • [1. 命令作用](#1. 命令作用)
          • [2. 命令语法](#2. 命令语法)
          • [3. 执行结果颜色说明](#3. 执行结果颜色说明)
        • 常用模块与命令示例
          • [1. 基础执行模块(command/shell/raw)](#1. 基础执行模块(command/shell/raw))
          • [(1)command 模块(默认模块,不支持 shell 特性)](#(1)command 模块(默认模块,不支持 shell 特性))
          • [(2)shell 模块(支持管道、重定向等 shell 特性)](#(2)shell 模块(支持管道、重定向等 shell 特性))
          • 文件模块(copy)
          • 其他常用模块示例
        • [AD HOC 命令选项与配置文件映射](#AD HOC 命令选项与配置文件映射)
    • [03-编写和运行 Ansible Playbook](#03-编写和运行 Ansible Playbook)
      • 实验环境准备
      • [Playbook 介绍](#Playbook 介绍)
        • 核心定义
        • [与 Ad Hoc 命令的对比](#与 Ad Hoc 命令的对比)
      • [YAML 格式基础规则](#YAML 格式基础规则)
        • [Vim 编辑器优化配置](#Vim 编辑器优化配置)
        • [YAML 核心语法元素](#YAML 核心语法元素)
          • [1. 注释](#1. 注释)
          • [2. 字符串](#2. 字符串)
        • [字典(映射 / 哈希)](#字典(映射 / 哈希))
        • [列表(序列 / 数组)](#列表(序列 / 数组))
      • [Playbook 编写示例](#Playbook 编写示例)
      • [Playbook 运行与调试](#Playbook 运行与调试)
      • [Playbook 提权配置](#Playbook 提权配置)
    • 04-管理变量和事实
      • 实验环境准备
      • [管理 VARIABLES](#管理 VARIABLES)
      • [管理 SECRETS(敏感数据)](#管理 SECRETS(敏感数据))
        • [Ansible Vault 简介](#Ansible Vault 简介)
        • [ansible-vault 命令使用](#ansible-vault 命令使用)
          • [1. 基础配置(指定编辑器)](#1. 基础配置(指定编辑器))
          • [2. 核心操作命令](#2. 核心操作命令)
          • [3. 配置文件中指定密码文件(简化操作)](#3. 配置文件中指定密码文件(简化操作))
        • 综合案例(加密数据库密码)
      • 敏感变量管理推荐做法
        • [ACTS 简介](#ACTS 简介)
        • [查看 FACTS 内容](#查看 FACTS 内容)
          • [1. 查看所有 FACTS](#1. 查看所有 FACTS)
          • [2. 查看单个 FACTS](#2. 查看单个 FACTS)
          • [3. 用 Ad Hoc 命令过滤 FACTS](#3. 用 Ad Hoc 命令过滤 FACTS)
        • [常用 FACTS 变量](#常用 FACTS 变量)
        • [FACTS 收集控制](#FACTS 收集控制)
          • [1. 关闭 FACTS 收集](#1. 关闭 FACTS 收集)
          • [2. 手动收集 FACTS](#2. 手动收集 FACTS)
        • [自定义 FACTS(可选)](#自定义 FACTS(可选))
    • 05-部署文件到受管主机
      • 实验环境准备
      • [Files 模块库核心模块说明](#Files 模块库核心模块说明)
      • [核心模块使用示例(含 Playbook 代码)](#核心模块使用示例(含 Playbook 代码))
        • [file 模块(文件 / 目录基础操作)](#file 模块(文件 / 目录基础操作))
          • [1. 创建文件并设置权限、属主属组](#1. 创建文件并设置权限、属主属组)
          • [2. 创建目录并设置权限](#2. 创建目录并设置权限)
          • [3. 删除文件](#3. 删除文件)
        • [sefcontext 模块(SELinux 上下文配置)](#sefcontext 模块(SELinux 上下文配置))
          • [前提条件(受管节点 node1 操作)](#前提条件(受管节点 node1 操作))
          • [Playbook 配置(控制节点操作)](#Playbook 配置(控制节点操作))
        • [lineinfile 模块(单行文本操作)](#lineinfile 模块(单行文本操作))
          • [1. 向文件末尾添加指定行](#1. 向文件末尾添加指定行)
          • [2. 在指定行前后插入内容](#2. 在指定行前后插入内容)
          • [3. 替换文件中的指定行](#3. 替换文件中的指定行)
          • [4. 替换为多行文本](#4. 替换为多行文本)
        • [replace 模块(批量文本替换)](#replace 模块(批量文本替换))
        • [blockinfile 模块(多行文本块操作)](#blockinfile 模块(多行文本块操作))
          • [stat 模块(文件状态检索)](#stat 模块(文件状态检索))
        • [copy 模块(文件拷贝 / 内容写入)](#copy 模块(文件拷贝 / 内容写入))
          • [1. 从控制节点拷贝文件到受管节点](#1. 从控制节点拷贝文件到受管节点)
          • [2. 直接向文件写入字符串内容](#2. 直接向文件写入字符串内容)
        • [synchronize 模块(基于 rsync 同步)](#synchronize 模块(基于 rsync 同步))
          • [1. 同步单个文件](#1. 同步单个文件)
          • [2. 同步目录(含子文件 / 子目录)](#2. 同步目录(含子文件 / 子目录))
        • [fetch 模块(从受管节点拉取文件)](#fetch 模块(从受管节点拉取文件))
          • [2. 直接向文件写入字符串内容](#2. 直接向文件写入字符串内容)
        • [synchronize 模块(基于 rsync 同步)](#synchronize 模块(基于 rsync 同步))
          • [1. 同步单个文件](#1. 同步单个文件)
          • [2. 同步目录(含子文件 / 子目录)](#2. 同步目录(含子文件 / 子目录))
        • [fetch 模块(从受管节点拉取文件)](#fetch 模块(从受管节点拉取文件))

Ansible自动化

01-Ansible 自动化介绍

Ansible 自动化介绍

手动执行任务和自动化执行任务

手动执行任务缺点:

  • 很容易遗漏某个步骤或错误地执行某个步骤。步骤是否正确执行或产生预期的结果的验证通常有 限。
  • 管理大量服务器很容易会出现差异,加大维护的难度,并给IT环境带来错误或不稳定性。

自动化执行任务优点:

  • 通过标准化,确保快速、正确地部署和配置所有系统。
  • 自动执行日常计划重复性任务,从而空出时间并专注于更重要的事情。
  • 更快速的交付应用。
基础架构即代码
  • 良好的自动化系统允许实施基础架构即代码方法。基础架构即代码意味着可以使用机器可读的自动 化语言来定义和描述IT基础架构所处的状态。理想情况下,这种自动化语言也应该非常便于人类阅 读,因为这样就可以轻松了解所处的状态并对其进行更改。
  • 如果自动化语言使用简单文本文件表示,还可以使用版本控制系统管理。这样做的好处是每个更改 都可以嵌入到版本控制系统中,可以获得随时间所做更改的历史记录,可以将系统恢复到更早的配 置。这样就奠定了一个遵循DevOps的基础。开发人员可以在自动化语言中定义所需的配置。操作 员可以更轻松地查看这些更改以提供反馈,并使用该自动化可重复地确保系统处于开发人员期望的 状态。
Ansible 与 DevOps

**百度百科:**DevOps(Development 和 Operations 的组合词)是一组过程、方法与系统的统称,用于 促进开发(应用程序/软件工程)、技术运营和质量保障(QA)部门之间的沟通、协作与整合。它是一种 重视"软件开发人员(Dev)"和"IT运维技术人员(Ops)"之间沟通合作的文化、运动或惯例。透过自动化 "软件交付"和"架构变更"的流程,来使得构建、测试、发布软件能够更加地快捷、频繁和可靠。

DevOps的关键在于 communication(沟通和交流)。

Ansible是第一款可以在整个IT范围读取和编写的自动化语言,也是唯一能够从头至尾自动化应用生命周 期和持续交付管道的自动化引擎。

什么是 ANSIBLE?

Ansible is a simple automation language,通过Playbooks描述和配置IT基础架构。

Ansible可以管理强大的自动化任务,适用于不同的生产环境。同时,Ansible对于新用户来说,也可以很 快的上手运用到生产环境。

  • OpenStack 搭建和维护
  • OpenShift 搭建和维护
  • ceph 搭建和维护
Ansible 特点
  • 简单:Ansible Playbooks 是一个人们非常容易查阅,理解和更改的文本文件,用户不需要具备特 定的代码编写技能。
  • 功能强大:可以使用Ansible部署应用,例如配置管理,工作流自动化,网络自动化。还可用于编排 整个应用生命周期。
  • 无代理:Ansible 是一个无代理的架构,通过OpenSSH或者WinRM连接到hosts,并执行任务,推 送小的程序(Ansible modules)到这些主机上。这些程序用于设置系统到预期状态。在Ansible执 行完成后,任何之前推送的模块,都会被删除。Ansible可以随时使用,因为被管理主机上不需要配 置特定代理。正是因为这点,Ansible 才更加高效和安全。
  • 跨平台支持:可以管理Linux、UNIX、windows 和网络设备。
  • 非常准确地描述应用:Ansible Playbook使用YAML格式描述生产环境。
  • 可以通过版本控制管理:Ansible Playbooks和projects是纯文本格式,可以当作源码存放在版本控 制系统中。
  • 非常容易与其他系统集成: HP SA,Puppet,Jenkins,红帽卫星服务器等。
Ansible 概念和架构
  • NODES:Ansible架构中有两种计算机类型:

    • 控制节点,安装有ansible软件的节点。
    • 受管节点,被ansible管理的Linux系统、Windows系统、网络设备等。
  • INVENTORY:受管主机清单。

  • PLAYBOOK:Ansible用户只需要编写playbook,确保主机是预期状态。

    • 每个playbook可以包含多个play。
    • 每个play会在一组hosts上按顺序执行一系列tasks。
    • 每个task都执行一个模块,模块是一个小的代码段(Python,PowerShell,或者其他语 言)。Ansible自带几百个模块,执行不同类型自动化任务,例如操作系统文件,安装软件, API调用。Tasks,plays和Playbooks是 idempotent(幂等的),在相同的主机上多次安全地 执行Playbooks,让主机是正确的状态。如果主机已经是预期状态,则Playbook不会做任何改 变。
  • PLUGINS,添加到Ansible中的代码段,用于扩展Ansible平台。

Ansible Way
  • Complexity Kills Productivity(复杂性会破坏效率),越简单越好。Ansible的设计宗旨是工具 易用,自动化易写易读,所以在创建自动化时尽可能地追求简单化。
  • Optimize For Readability(专为易读性优化),Ansible自动化语言围绕简单易读的声明性文本 文件来构建。正确编写的Ansible Playbook可以清楚地记录您的工作流自动化。
  • Think Declaratively(声明式思维),Ansible是一种要求状态引擎。它通过表达您希望系统处于 何种状态来解决如何自动化IT部署的问题。Ansible的目标是通过仅执行必要的更改,使您的系统处 于所需的状态。
Ansible 用例
  • **配置管理:**集中化配置文件管理和部署是Ansible的常见用例,很多高级用户也是通过这种方式了解 Ansible自动化平台。
  • 应用部署:通过Ansible定义应用,以及使用红帽Ansible Tower管理部署时,各团队可以更加有效 地管理从开发到生产的整个应用生命周期。
  • 工作流管理:Ansible 和红帽Ansible Tower有助于简化调配系统的流程,不论您是要PXE引导和 kickstart安装裸机恢复服务器或虚拟机,还是从模板创建虚拟机或云实例。
  • **持续交付:**创建CI/CD管道需要多个团队的协调和参与。如果没有组织内人人可用的简单自动化平 台,就无法实现这个目标。Ansible Playbook让您的应用可以在整个生命周期内得到正确部署(和管 理)
  • **安全性和合规性:**当您在Ansible Playbook中定义安全策略时,也可以将扫描和修复整站安全策略 集成到其他自动化流程中。确保安全应该是您所有部署中不可或缺的组成部分,而不是事后才去考 虑的部分。 编排:仅配置本身不足以定义您的环境,您还需定义多个配置间就应如何交互,并确保以整体的方 式管理各类分散资源。

Ansible 部署

准备实验环境

基于 CentOS-7-template 克隆出 5 台虚拟机,分别按下面的实验环境命名、配置 IP:

主机名 IP 地址 作用
controller.dcr.cloud 192.168.108.10 控制节点
node1.dcr.cloud 192.168.108.11 受控节点
node2.dcr.cloud 192.168.108.12 受控节点
node3.dcr.cloud 192.168.108.13 受控节点
node4.dcr.cloud 192.168.108.14 受控节点

5 节点 /etc/hosts 配置如下:

bash 复制代码
192.168.108.10 controller.dcr.cloud controller
192.168.108.11 node1.dcr.cloud node1
192.168.108.12 node2.dcr.cloud node2
192.168.108.13 node3.dcr.cloud node3
192.168.108.14 node4.dcr.cloud node4

配置控制节点 dcr 用户使用dcr用户免密登录所有节点,并免提sudo提权执行任何命令。

bash 复制代码
[root@all-所有节点 ~]# cat >> /etc/hosts <<EOF
################# ansible #################
192.168.108.10 controller.dcr.cloud controller
192.168.108.11 node1.dcr.cloud node1
192.168.108.12 node2.dcr.cloud node2
192.168.108.13 node3.dcr.cloud node3
192.168.108.14 node4.dcr.cloud node4
EOF

#所有节点添加用户
[root@all-所有节点 ~]# useradd dcr
[root@all-所有节点 ~]# echo huawei | passwd --stdin dcr

#所有节点配置免密提权
[root@all-所有节点 ~]# echo 'dcr ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/dcr

#controller 节点操作
# 安装sshpass
[root@controller ~]# yum install -y sshpass

# 密钥登陆
[root@controller ~]# su - dcr
[dcr@controller ~]$ ssh node1 #输入yes,密码,exit退出
[dcr@controller ~]$ ssh node2
[dcr@controller ~]$ ssh node3
[dcr@controller ~]$ ssh node4
[dcr@controller ~]$ ssh controller

# 创建密钥对
[dcr@controller ~]$ [ -d ~/.ssh ] || mkdir -m 700 .ssh
[dcr@controller ~]$ ssh-keygen -t rsa -f .ssh/id_rsa -N ''

# 推送公钥到目标主机
[dcr@controller ~]$ sudo yum install -y sshpass
[dcr@controller ~]$ for host in controller node{1..4}
do
sshpass -p huawei ssh-copy-id dcr@$host
done

# 验证免密登录
[dcr@controller ~]$ for host in controller node{1..4}
do
ssh dcr@$host hostname
done

#安装 ansible
[root@controller ~]# yum install -y ansible

# 验证安装
[dcr@centos7 ~]$ ansible --version

控制节点说明

控制节点即用来安装 Ansible 软件的主机节点。控制节点可以是一个或多个,由 ansible 管理的主机不用安装 Ansible。

提示:控制节点是 Linux 或 UNIX 系统,不支持 Windows 作为控制节点。

受管节点要求

Linux

受管节点满足的要求取决于控制节点连接它们的方式以及它们要运行的模块:

  • Python 版本:Linux 和 UNIX 受管节点需要安装 Python 才能运行大部分的模块。
  • 一些模块不需要 Python,例如 raw 模块的参数直接通过配置的远程 shell 运行,在没有 Python 环境的设备上使用。不过,raw 模块难以通过安全的幂等方式使用。
Windows

Ansible 随附了多个专门为 Microsoft Windows 系统设计的模块。这些模块列在 Ansible 模块索引的 Windows Modules 部分。

大部分专门为 Microsoft Windows 受管节点设计的模块需要在受管节点上:

  • 安装 Power Shell 3.0 或更高版本。
  • 配置 Power Shell 远程连接。
  • 安装.NET Framework 4.0 或更高版本。

本课程的示例中使用基于 Linux 的受管节点,不会深入阐述管理基于 Microsoft Windows 的受管节点时的具体差别和必要调整。可以在 Ansible 网站上查看更多信息。

网络设备

还可以使用 Ansible 自动化来配置受管网络设备,例如路由器和交换机。Ansible 包含大量专门为此目的而设计的模块。其中包括对 Cisco IOS、IOSXR 和 NX-OS 的支持;Juniper Junos;AristaEOS;以及基于 VyOS 的网络设备等。

由于大多数网络设备无法运行 Python,因此 Ansible 在控制节点上运行网络模块,而不是在受管节点上运行。特殊连接方法也用于与网络设备通信,通常使用 SSH 上的 CLI、SSH 上的 XML 或 HTTP (S) 上的 API。

02-Ansible 基本使用

Ansible 清单

Ansible 软件包文件结构
bash 复制代码
[dcr@controller ~]$ rpm -ql ansible

核心目录说明:

  • 配置文件目录:/etc/ansible
  • 执行文件目录:/usr/bin
  • lib 依赖库目录:/usr/lib/python2.7/site-packages/ansible
  • 插件目录:/usr/share/ansible/plugins
  • Help 文档目录:/usr/share/doc/ansible
  • Man 文档目录:/usr/share/man/man1/
主机清单定义与分类

Inventory 用于定义 Ansible 管理的主机集合,支持主机分组、子组嵌套和变量配置,分为两种类型:

  1. 静态主机清单:以文本文件形式定义,支持 ini、yaml 等格式(本次课程使用 ini 格式)。
  2. 动态主机清单:通过脚本或外部程序自动生成,适用于 OpenStack、Kubernetes、
静态主机清单配置示例
1. 最简单的静态清单(仅列主机 / IP)
bash 复制代码
# inventory 文件内容
web1.example.com
web2.example.com
db1.example.com
db2.example.com
192.0.2.42

验证命令:

bash 复制代码
# 验证指定主机是否在清单中
ansible --list-hosts -i inventory web1.example.com
ansible --list-hosts -i inventory 192.0.2.42
2. 主机组配置
bash 复制代码
# 未分组主机
app1.example.com

# 定义 web 服务器组
[webservers]
web1.example.com
web2.example.com
192.168.3.7

# 定义数据库服务器组
[dbservers]
db1.example.com
db2.example.com
192.0.2.42
192.0.2.43

# 按地域分组
[eastdc]
web1.example.com
db1.example.com

[westdc]
web2.example.com
db2.example.com

验证命令:

bash 复制代码
# 查看 webservers 组主机
ansible --list-hosts -i inventory webservers
# 查看所有主机(all 组默认存在)
ansible --list-hosts -i inventory all
# 查看未分组主机(ungrouped 组默认存在)
ansible --list-hosts -i inventory ungrouped
3. 主机组嵌套
bash 复制代码
# 子组定义
[eastdc]
web1.example.com
db1.example.com

[westdc]
web2.example.com
db2.example.com

# 父组(包含子组)
[dc:children]
eastdc
westdc

验证命令:

bash 复制代码
# 查看父组 dc 包含的所有主机
ansible --list-hosts -i inventory dc

注意:子组必须先定义,否则会报语法错误。

4. 范围简写(简化大量主机配置)

语法:[start:end](支持数字和字母范围)

bash 复制代码
# IP 范围:192.168.4.0-192.168.7.255
[priv]
192.168.[4:7].[0:255]

# 主机名数字范围:host01.example.com 到 host20.example.com
[hosts]
host[01:20].example.com

# 主机名字母范围:servera.example.com 到 serverc.example.com
[servers]
server[a:c].example.com

验证命令:

bash 复制代码
ansible --list-hosts -i inventory hosts
ansible --list-hosts -i inventory priv
ansible --list-hosts -i inventory servers

错误示例(混合数字和字母范围):

bash 复制代码
[servers]
server[0a:2c].example.com  # 报错:无法解析非纯数字/字母范围
ansible-inventory 命令(清单查看工具)
1. 命令帮助
bash 复制代码
ansible-inventory --help
2. 常用操作
bash 复制代码
# 树形结构显示清单(清晰展示组关系)
ansible-inventory -i inventory --graph

# YAML 格式显示清单详情
ansible-inventory -i inventory --list -y

# 导出清单到文件
ansible-inventory -i inventory --list -y --output=inventory.yaml

管理 ANSIBLE 配置文件

配置文件位置与优先级

优先级从高到低:

  1. 环境变量 ANSIBLE_CONFIG
  2. 当前目录的 ./ansible.cfg(项目目录,推荐使用)
  3. 用户家目录的 ~/.ansible.cfg
  4. 系统默认配置 /etc/ansible/ansible.cfg
验证优先级示例
bash 复制代码
# 环境准备:创建测试目录
mkdir web && cd web

# 查看当前使用的配置文件
ansible --version | grep 'config file'

# 创建 ~/.ansible.cfg,验证优先级
touch ~/.ansible.cfg
ansible --version | grep 'config file'

# 创建当前目录 ansible.cfg,验证优先级
touch ansible.cfg
ansible --version | grep 'config file'

# 通过环境变量指定配置文件,验证优先级
export ANSIBLE_CONFIG=/opt/ansible.cfg
sudo touch /opt/ansible.cfg
ansible --version | grep 'config file'
配置文件核心 sections 与参数

默认配置文件:/etc/ansible/ansible.cfg核心 sections 包括 [defaults][inventory][privilege_escalation] 等,常用参数如下:

1. [defaults] 核心参数
bash 复制代码
[defaults]
# 清单文件路径
inventory = /etc/ansible/hosts
# 并发执行任务的主机数量
forks = 5
# 连接受管主机时是否提示输入密码
ask_pass = True
# Facts 收集策略(smart/implicit/explicit)
gathering = implicit
# 收集 Facts 的范围
gather_subset = all
# SSH 主机密钥校验(生产环境建议开启,测试环境可关闭)
host_key_checking = False
# 远程登录用户名
remote_user = root
# 日志文件路径
log_path = /var/log/ansible.log
# 默认模块(未指定 -m 时使用)
module_name = command
# 未定义变量时是否报错
error_on_undefined_vars = False
2. [privilege_escalation] 提权配置
bash 复制代码
[privilege_escalation]
# 是否启用提权
become = True
# 提权方式(sudo/su 等)
become_method = sudo
# 提权后的目标用户
become_user = root
# 提权时是否提示输入密码
become_ask_pass = False
配置文件示例
bash 复制代码
[defaults]
# 远程登录用户
remote_user = dcr
# 清单文件路径(当前目录的 inventory)
inventory = ./inventory

[privilege_escalation]
# 启用提权
become = True
# 提权到 root 用户
become_user = root
# 提权方式为 sudo
become_method = sudo
# 免密提权
become_ask_pass = False
配套 inventory 示例
bash 复制代码
# inventory 文件内容
node1
node2
node3
node4
验证配置效果
bash 复制代码
# 执行命令测试(查看所有节点 hostname)
ansible all -a hostname

预期输出:

bash 复制代码
node3 | CHANGED | rc=0 >>
node3.dcr.cloud
node1 | CHANGED | rc=0 >>
node1.dcr.cloud
node2 | CHANGED | rc=0 >>
node2.dcr.cloud
node4 | CHANGED | rc=0 >>
node4.dcr.cloud
ansible-config 命令
1. 命令帮助
bash 复制代码
ansible-config -h
2. 常用操作
bash 复制代码
# 查看当前生效的配置文件内容
ansible-config view

# 导出所有生效配置(含默认值)
ansible-config dump

# 查看所有配置参数的用途和位置
ansible-config list
localhost连接说明
  • 默认连接协议:smart(优先使用 SSH)
  • 隐式 localhost:清单未指定 localhost 时,Ansible 自动添加,使用 local 连接类型
  • local 连接特性:忽略 remote_user,直接使用本地账户执行命令;提权时使用当前执行账户

运行 AD HOC 命令

实验环境准备
bash 复制代码
# 创建项目目录
mkdir web && cd web

# 创建 ansible.cfg 配置文件
cat > ansible.cfg <<'EOF'
[defaults]
remote_user = dcr
inventory = ./inventory
[privilege_escalation]
become = True
become_user = root
become_method = sudo
become_ask_pass = False
EOF

# 创建 inventory 清单文件
cat > inventory <<'EOF'
node1
node2
node3
node4
EOF
AD HOC 命令基础
1. 命令作用

快速执行单个临时任务,无需编写 Playbook,适用于测试、应急操作等场景。

2. 命令语法
bash 复制代码
ansible host-pattern -m module [-a 'module arguments'] [-i inventory]
  • host-pattern:清单中的主机 / 组名(必选)
  • -m module:指定模块(默认使用 command 模块)
  • -a 'module arguments':模块参数
  • -i inventory:指定清单文件
3. 执行结果颜色说明
  • 红色:执行异常,中止后续任务
  • 绿色:目标已达预期状态,无需更改
  • 黄色:执行成功,目标状态已更新
常用模块与命令示例
1. 基础执行模块(command/shell/raw)
(1)command 模块(默认模块,不支持 shell 特性)
bash 复制代码
# 示例 1:查看所有节点 hostname(简化写法,省略 -m command)
ansible all -a "hostname"

# 示例 2:查看操作系统版本
ansible all -a "cat /etc/os-release"

# 示例 3:查看内核版本
ansible all -a "uname -r"

# 示例 4:查看内存使用情况
ansible all -a "free -h"

# 示例 5:创建空文件
ansible all -a "touch /tmp/ansible_test.txt"

# 示例 6:查看指定文件最后 10 行
ansible all -a "tail -10 /var/log/messages"
(2)shell 模块(支持管道、重定向等 shell 特性)
bash 复制代码
# 示例 1:统计 /etc 目录文件数量(使用管道)
ansible all -m shell -a "ls -l /etc | wc -l"

# 示例 2:查找 sshd 进程(使用管道过滤)
ansible all -m shell -a "ps aux | grep sshd"

# 示例 3:查看磁盘挂载中包含 /sys 的记录(使用管道)
ansible all -m shell -a "mount | grep /sys"
文件模块(copy)

核心作用:从控制端拷贝文件 / 目录到受管节点

bash 复制代码
# 示例 1:基础文件拷贝(覆盖目标文件)
touch /tmp/local_file.txt
ansible all -m copy -a "src=/tmp/local_file.txt dest=/opt/remote_file.txt"

# 示例 2:拷贝并设置权限、属主属组,自动备份原文件
ansible all -m copy -a "src=/etc/httpd/conf/httpd.conf dest=/tmp/httpd.conf owner=dcr group=root mode=0644 backup=yes"

# 示例 3:递归拷贝目录(含子文件)
ansible dbservers -m copy -a "src=/tmp/mysql_config/ dest=/etc/mysql/ recursive=yes directory_mode=0750"
其他常用模块示例
bash 复制代码
# 查看模块文档(以 user 模块为例)
ansible-doc user

# 示例:创建用户(user 模块)
ansible all -m user -a "name=johnd uid=1040 group=admin state=present"

# 示例:安装软件包(yum 模块)
ansible all -m yum -a "name=httpd state=latest"

# 示例:启动并设置开机自启(service 模块)
ansible all -m service -a "name=httpd enabled=yes state=started"
AD HOC 命令选项与配置文件映射
配置文件指令 命令行选项
inventory -i
remote_user -u
ask_pass -k, --ask-pass
become --become, -b
become_method --become_method
become_user --become-user
become_ask_pass --ask-become-pass, -K

03-编写和运行 Ansible Playbook

实验环境准备

配置文件与清单设置
bash 复制代码
# 创建项目目录并进入
mkdir web && cd web

# 编写 ansible.cfg 配置文件
vim ansible.cfg

ansible.cfg 内容:

bash 复制代码
[defaults]
remote_user = dcr
inventory = ./inventory

[privilege_escalation]
become = True
become_user = root
become_method = sudo
become_ask_pass = False
bash 复制代码
# 编写 inventory 清单文件
vim inventory

inventory 内容:

bash 复制代码
controller
node1
node2
node3
node4

Playbook 介绍

核心定义

Playbook 是包含一个或多个按序执行的 play 的文本文件,play 是针对清单中指定主机运行的一组有序任务。它能将复杂手动管理任务转化为可重复、可预测的自动化例程,是发挥 Ansible 核心能力的关键。

与 Ad Hoc 命令的对比
  • Ad Hoc 命令:适用于一次性简单任务,无需保存。

    示例:在 node1 上创建用户 newbie(UID=4000)

bash 复制代码
ansible node1 -m user -a "name=newbie uid=4000 state=present"
  • Playbook:适用于复杂、需重复执行的任务,以文件形式保存(YAML 格式,扩展名通常为 .yaml.yml)。

上述 Ad Hoc 命令对应的 Playbook 版本:

bash 复制代码
---
name: Configure important user consistently
hosts: node1
tasks:
  - name: newbie exists with UID 4000
    user:
      name: newbie
      uid: 4000
      state: present
...

ansible-playbook newuser.yaml

YAML 格式基础规则

Playbook 基于 YAML 编写,核心规则如下:

  1. 缩进:仅使用空格(不支持 Tab),同一级别元素缩进一致,子元素比父元素缩进更多。
  2. 键值对:键与值用 : 分隔,: 后必须加空格(如 name: Enable intranet services)。
  3. 起始与结束:第一行必须是 ---(表示 YAML 文档开始),最后一行 ... 可省略。
  4. 可读性:适当增加空白行,提升文件可读性。
Vim 编辑器优化配置

为方便编写 Playbook,可配置 Vim 自动缩进和

Tab 替换:

bash 复制代码
# 编辑 Vim 配置文件
vim ~/.vimrc

# 全局生效:自动缩进,Tab 键替换为 2 个空格
set ai ts=2

# 仅 YAML 文件生效:自动缩进,Tab 键替换为 2 个空格
autocmd FileType yaml set ai ts=2
  • ai(autoindent):自动缩进。
  • ts(tabstop):Tab 键对应空格数。
YAML 核心语法元素
1. 注释

# 开头,# 右侧内容为注释;若注释在内容右侧,# 前需加空格。

bash 复制代码
# 单行注释
name: Enable intranet services  # 行尾注释
2. 字符串
  • 单行字符串:无需引号,含空格时也可省略(如需转义字符则用双引号)。
bash 复制代码
content: Welcome dcr WebSite!
content: "Welcome dcr\nWebSite!"  # 含转义字符需用双引号

多行字符串:

  • 竖线 |:保留换行符。

  • 大于号 >:换行符替换为空格,删除行首空白。

bash 复制代码
# 保留换行
debug:
  msg: |
    Example Company
    123 Main Street
    Atlanta, GA 30303

# 合并为单行
debug:
  msg: >
    This is an example
    of a long string,
    that will become
    a single sentence once folded.
字典(映射 / 哈希)

一组键值对集合,支持两种格式:

  • 缩进块格式(推荐,可读性强):
bash 复制代码
user:
  name: dcr
  uid: 1088
  state: absent
  • 内联格式(不推荐,可读性差,仅适合简单场景):
bash 复制代码
user: {name: dcr, uid: 1088, state: absent}
列表(序列 / 数组)

按顺序排列的值集合,支持两种格式:

  • 缩进块格式(推荐):
bash 复制代码
yum:
  name:
    - httpd
    - firewalld
  state: latest
  • 内联格式(不推荐):
bash 复制代码
yum:
  name: [httpd, firewalld]
  state: latest

Playbook 编写示例

以下示例实现 "部署内网 Web 服务":安装 httpd 和 firewalld、配置主页、放行防火墙端口、启动服务,并测试服务可用性。

bash 复制代码
---
# 第一个 Play:部署 Web 服务
name: Enable intranet services
hosts: node1  # 目标主机(清单中定义)
tasks:
  # 任务 1:安装最新版 httpd 和 firewalld
  - name: latest version of httpd and firewalld installed
    yum:
      name:
        - httpd
        - firewalld
      state: latest  # 状态为"最新版"

  # 任务 2:配置 Web 主页内容
  - name: test html page is installed
    copy:
      content: "Welcome dcr WebSite!\n"  # 主页内容
      dest: /var/www/html/index.html  # 目标文件路径

  # 任务 3:启用并启动 firewalld 服务
  - name: firewalld enabled and running
    service:
      name: firewalld
      enabled: yes  # 开机自启
      state: started  # 当前状态为"启动"

  # 任务 4:防火墙放行 http 服务(永久生效)
  - name: firewalld permits access to httpd service
    firewalld:
      service: http  # 放行的服务名
      permanent: yes  # 永久生效(重启防火墙不失效)
      state: enabled  # 启用该规则
      immediate: yes  # 立即生效(无需重启防火墙)

  # 任务 5:启用并启动 httpd 服务
  - name: httpd enabled and running
    service:
      name: httpd
      enabled: true  # 等同于 yes,开机自启
      state: started  # 当前状态为"启动"

# 第二个 Play:测试 Web 服务可用性
- name: Test intranet web server
  hosts: localhost  # 本地执行(控制节点)
  become: no  # 无需提权
  tasks:
    - name: connect to intranet web server
      uri:
        url: http://node1  # 目标 URL(node1 的 Web 服务)
        return_content: yes  # 返回页面内容
        status_code: 200  # 期望响应状态码(200 表示成功)
...

Playbook 运行与调试

核心运行命令
bash 复制代码
# 基本运行(执行 Playbook)
ansible-playbook playbook.yaml

# 语法检查(仅验证格式,不执行任务)
ansible-playbook --syntax-check playbook.yaml

# 空运行(模拟执行,不实际修改目标主机)
ansible-playbook playbook.yaml -C

# 提高输出详细程度(根据需求选择 -v 级别)
ansible-playbook playbook.yaml -v    # 显示任务结果
ansible-playbook playbook.yaml -vv   # 显示任务结果 + 配置
ansible-playbook playbook.yaml -vvv  # 增加连接信息
ansible-playbook playbook.yaml -vvvv # 最详细(含执行脚本、用户信息)
运行结果说明
  • 绿色:目标主机已达预期状态,无需修改。
  • 黄色:任务执行成功,目标主机状态已更新。
  • 红色:执行异常,中止后续任务。

示例:第二次运行上述 Playbook 时,所有任务状态均为绿色(已达预期状态)。

Playbook 提权配置

可在 Playbook 中直接指定提权参数,覆盖 ansible.cfg 中的配置。

场景示例

若注释 ansible.cfg 中的提权配置:

bash 复制代码
[defaults]
inventory=./inventory
# remote_user = dcr  # 注释远程用户配置

[privilege_escalation]
# become=True  # 注释提权启用
# become_method=sudo  # 注释提权方式
# become_user=root  # 注释目标用户
# become_ask_pass=False  # 注释免密提权
在 Playbook 中添加提权配置
bash 复制代码
---
name: Enable intranet services
hosts: node1
remote_user: dcr  # 指定远程登录用户
become: true  # 启用提权
become_method: sudo  # 提权方式(sudo)
become_user: root  # 提权目标用户(root)
tasks:
  - name: latest version of httpd and firewalld installed
    yum:
      name:
        - httpd
        - firewalld
      state: latest
...
运行验证
bash 复制代码
ansible-playbook playbook.yaml

预期输出:任务执行成功(changed=1),无权限报错。

04-管理变量和事实

实验环境准备

bash 复制代码
# 创建项目目录并进入
mkdir web && cd web

# 编写 ansible.cfg 配置文件
cat > ansible.cfg <<'EOF'
[defaults]
remote_user = dcr
inventory = ./inventory

[privilege_escalation]
become = True
become_user = root
become_method = sudo
become_ask_pass = False
EOF

# 编写 inventory 清单文件
cat > inventory <<'EOF'
controller
node1
node2
node3
node4
EOF

管理 VARIABLES

变量简介

变量用于在 Ansible 项目中存储可重复引用的数据,简化配置维护并降低出错率。可针对用户、软件包、服务、文件等对象定义变量,适用于 Playbook、清单等场景。

变量命名规则
  • 仅包含字母、数字和下划线,禁止含空格、点、$ 等特殊字符。
  • 必须以字母开头(不能以数字或下划线开头)。
变量范围和优先级
1. 变量范围
  • Global scope(全局范围):通过命令行或 Ansible 配置定义的变量。
  • Play scope(Play 范围):在 Play 或相关结构中定义的变量。
  • Host scope(主机范围):通过清单、事实(Facts)或任务注册的变量,作用于主机组或单个主机。
2. 优先级

优先级从高到低:Global → Play → Host。同名变量时,高优先级变量覆盖低优先级变量。

不同范围变量的定义与使用
1. Global scope(全局变量)

通过 -e 选项在命令行传递,适用于临时覆盖场景。

bash 复制代码
# 调试全局变量
ansible node1 -e "package=httpd" -m debug -a "msg={{ package }}"

# 使用全局变量安装软件
ansible node1 -e "package=httpd" -m yum -a "name={{ package }} state=present"
2. Play scope(Play 变量)
(1)vars 声明(直接在 Play 中定义)
bash 复制代码
# playbook.yaml
name: test vars statement in play
hosts: node1
vars:
  user: joe
  home: /home/joe
tasks:
  - name: add user {{ user }}
    user:
      name: "{{ user }}"
      home: "{{ home }}"
      state: present
  - name: debug user
    debug:
      msg: |
        username is {{ user }}
        home is {{ home }}

运行命令:

bash 复制代码
ansible-playbook playbook.yaml
(2)vars_files 声明(引用外部变量文件)

适用于变量较多的场景,便于分类管理。

bash 复制代码
# 创建变量文件目录及文件
mkdir vars
vim vars/user1.yaml

变量文件内容(YAML 格式):

bash 复制代码
user: user1
home: /home/user1

Playbook 引用变量文件:

bash 复制代码
# playbook.yaml
name: test vars statement in play
hosts: node1
vars_files:
  - vars/user1.yaml  # 引用外部变量文件
tasks:
  - name: add user {{ user }}
    user:
      name: "{{ user }}"
      home: "{{ home }}"
      state: present
  - name: debug user
    debug:
      msg: >
        username is {{ user }}
        home is {{ home }}

运行命令:

bash 复制代码
ansible-playbook playbook.yaml
3.Host scope(主机变量)
(1)清单文件中直接定义(不推荐)

混合主机和变量信息,清单文件可读性差。

bash 复制代码
# inventory
[servers]
node1 user=dcr  # 单个主机变量
node2
[servers:vars]
user=laowang  # 主机组变量

验证命令:

bash 复制代码
ansible servers -m debug -a 'var=user'
(2)目录分层结构定义(推荐)

通过 group_vars(主机组变量)和 host_vars(单个主机变量)目录管理,结构清晰。

bash 复制代码
# 1. 编辑清单
vim inventory
[servers]
node1
node2

# 2. 创建主机组变量文件
mkdir group_vars
vim group_vars/servers.yaml
user: laowang  # servers 组的变量

# 3. 创建单个主机变量文件
mkdir host_vars
vim host_vars/node1.yaml
user: dcr  # node1 主机的变量

验证命令:

bash 复制代码
ansible servers -m debug -a 'var=user'

进阶示例(嵌套组变量):

bash 复制代码
# inventory
[dc1]
node1
node2
[dc2]
node3
node4
[dc:children]  # 父组包含子组
dc1
dc2

验证命令:

bash 复制代码
ansible all -m debug -a 'var=package'
变量引用规则
  • 变量通过 {``{ 变量名 }} 引用,任务执行时自动替换为对应值。
  • 当变量作为值的第一个元素时,必须用引号(单引号或双引号)包裹,否则会报 YAML 语法错误。

错误示例:

bash 复制代码
tasks:
  - name: create user
    user:
      name: {{ user }}  # 错误:变量作为第一个元素未加引号
      state: present

正确示例:

bash 复制代码
tasks:
  - name: create user
    user:
      name: "{{ user }}"  # 正确:加双引号包裹
      state: present
特殊变量类型
1. 主机连接特殊变量

用于配置主机连接方式,常见变量如下:

  • ansible_connection:连接类型(smart/ssh/paramiko,默认 smart)。
  • ansible_host:目标主机名(默认清单中定义的名称)。
  • ansible_port:SSH 端口(默认 22)。
  • ansible_user:SSH 登录用户名。
  • ansible_ssh_private_key_file:SSH 私钥文件路径。
  • ansible_become:是否启用提权(等效于 sudo/su)。
  • ansible_become_pass:提权密码(需用 Vault 加密,禁止明文存储)。
2. 数组变量

将多个相关值存储在同一变量中,便于批量管理。

bash 复制代码
# 数组变量定义
vars:
  users:
    dcr:
      user_name: dcr
      home_path: /home/dcr
    laowang:
      user_name: laowang
      home_path: /home/laowang

引用方式:

bash 复制代码
tasks:
  # 方式1:. 分隔符引用(推荐,可读性强)
  - name: add user {{ users.dcr.user_name }}
    user:
      name: '{{ users.dcr.user_name }}'
      home: "{{ users.dcr.home_path }}"

  # 方式2:[] 索引引用(避免关键字冲突)
  - name: debug laowang
    debug:
      msg: >
        username is {{ users['laowang']['user_name'] }}
        home_path is {{ users['laowang']['home_path'] }}
3. register 语句(注册变量)

捕获任务执行输出,存储在临时变量中,用于后续调试或条件判断。

bash 复制代码
name: Installs a package and prints the result
hosts: node1
tasks:
  - name: Install the package
    yum:
      name: httpd
      state: installed
    register: install_result  # 注册任务输出到变量

  - name: Print installation result
    debug:
      var: install_result  # 打印注册变量的值
4. Magic 变量(魔术变量)

由 Ansible 自动生成,用于获取主机或清单相关信息,常用魔术变量如下:

  • inventory_hostname:清单中定义的主机名。
bash 复制代码
ansible node1 -m debug -a 'var=inventory_hostname'
  • group_names:当前主机所属的所有主机组。
bash 复制代码
ansible node1 -m debug -a 'var=group_names'
  • hostvars:所有主机的变量,可跨主机引用。
bash 复制代码
ansible node1 -m debug -a 'var=hostvars.node3.group_names'

管理 SECRETS(敏感数据)

Ansible Vault 简介

用于加密敏感数据(如密码、API 密钥),避免明文存储带来的安全风险。支持加密清单变量、Playbook 变量文件、角色变量等结构化数据文件。

ansible-vault 命令使用
1. 基础配置(指定编辑器)
bash 复制代码
# 设置默认编辑器为 vim(临时生效)
export EDITOR=vim

# 永久生效(添加到 bash 配置文件)
echo 'export EDITOR=vim' >> ~/.bashrc
source ~/.bashrc
2. 核心操作命令
bash 复制代码
# 1. 创建加密文件(需设置密码)
ansible-vault create secret.yaml
# 输入密码后,编写变量(YAML 格式)
password: huawei

# 2. 查看加密文件
ansible-vault view secret.yaml  # 需输入密码
# 或通过密码文件自动输入密码
echo huawei > pass
ansible-vault view secret.yaml --vault-password-file=pass

# 3. 编辑加密文件
ansible-vault edit secret.yaml --vault-password-file=pass

# 4. 加密已有文件
ansible-vault encrypt secret.yaml --vault-password-file=pass

# 5. 解密文件
ansible-vault decrypt secret.yaml --vault-password-file=pass

# 6. 更改加密文件密码
ansible-vault rekey secret.yaml --vault-password-file=pass
# 输入新密码即可
3. 配置文件中指定密码文件(简化操作)
bash 复制代码
# ansible.cfg
[defaults]
vault_password_file = ./pass  # 自动读取密码文件,无需手动输入
综合案例(加密数据库密码)
bash 复制代码
# 1. 创建加密变量文件目录
mkdir vault
ansible-vault create vault/mysql.yml
# 输入密码后,编写变量
user: dcr
password: huawei
host: 'localhost'
priv: '*.*:ALL'

# 2. 编写 Playbook
vim playbook.yaml
name: config mariadb server
hosts: node1
vars_files:
  - vault/mysql.yml  # 引用加密变量文件
tasks:
  - name: install mariadb-server
    yum:
      name:
        - mariadb-server
        - python2-PyMySQL
      state: present

  - name: enable and start mariadb
    service:
      name: mariadb
      enabled: yes
      state: started

  - name: create mysql user
    mysql_user:
      name: "{{ user }}"
      password: "{{ password }}"
      host: "{{ host }}"
      priv: "{{ priv }}"
      state: present

# 3. 运行 Playbook(需提供 Vault 密码)
ansible-playbook playbook.yaml --ask-vault-pass
# 输入 Vault 密码即可执行

敏感变量管理推荐做法

  • 敏感变量与普通变量分开存储,敏感变量文件单独用 Vault 加密。
  • 采用目录分层结构管理,如 host_vars/node1/vaults.yaml(加密敏感变量)和 host_vars/node1/vars.yaml(普通变量)。
  • 密码文件避免提交到版本控制系统(如 Git),仅在控制节点本地存储。

管理 FACTS(事实)

ACTS 简介

FACTS 是 Ansible 自动在受管主机上检测到的系统信息变量,仅在当前 Playbook 执行期间有效。包含主机名、内核版本、IP 地址、CPU 数量、内存大小等信息,可像普通变量一样在 Playbook 中引用。

查看 FACTS 内容
1. 查看所有 FACTS
bash 复制代码
# playbook.yaml
name: Dump facts
hosts: node1
tasks:
  - name: Print all facts
    debug:
      var: ansible_facts
2. 查看单个 FACTS
bash 复制代码
# playbook.yaml
hosts: node1
tasks:
  - name: Print default IPv4
    debug:
      msg: >
        The default IPv4 address of {{ ansible_fqdn }}
        is {{ ansible_default_ipv4.address }}
3. 用 Ad Hoc 命令过滤 FACTS

通过 setup 模块的 filter 选项,仅查看指定 FACTS。

bash 复制代码
ansible node1 -m setup -a 'filter=ansible_default_ipv4'
常用 FACTS 变量
FACT 描述 变量格式(新) 变量格式(旧,Ansible 2.5 前)
短主机名 ansible_facts['hostname'] ansible_hostname
完全限定域名 ansible_facts['fqdn'] ansible_fqdn
默认 IPv4 地址 ansible_facts['default_ipv4']['address'] ansible_default_ipv4['address']
网络接口列表 ansible_facts['interfaces'] ansible_interfaces
磁盘分区大小(/dev/vda1) ansible_facts['devices']['vda']['partitions']['vda1']['size'] ansible_devices['vda']['partitions']['vda1']['size']
DNS 服务器列表 ansible_facts['dns']['nameservers'] ansible_dns['nameservers']
内核版本 ansible_facts['kernel'] ansible_kernel
FACTS 收集控制
1. 关闭 FACTS 收集

当不需要使用 FACTS 时,可关闭收集以提升 Playbook 执行速度。

bash 复制代码
# 方式1:在 Play 中设置
name: Fact dump
hosts: node1
gather_facts: no  # 关闭 FACTS 收集

# 方式2:在配置文件中设置(全局生效)
[defaults]
gathering = explicit
2. 手动收集 FACTS

即使关闭自动收集,也可通过 setup 模块手动收集。

bash 复制代码
tasks:
  - name: Gather specific facts
    setup:
      filter: ansible_default_ipv4  # 仅收集指定 FACTS
自定义 FACTS(可选)

可在受管主机上创建自定义 FACTS 文件,Ansible 会自动识别并整合到系统 FACTS 中。

bash 复制代码
# 1. 在受管主机创建目录
mkdir -p /etc/ansible/facts.d/

# 2. 创建自定义 FACTS 文件(INI 格式)
vim /etc/ansible/facts.d/custom.fact
[packages]
web_package = httpd
db_package = mariadb_server
[users]
user1 = joe
user2 = jane

# 3. 在控制节点查看自定义 FACTS
ansible node1 -m setup -a 'filter=ansible_local'

vim

查看ansible的剧本文件是否对齐,:set cursorcolumn

对于yaml,yml格式

对于单行字符串,有空格与与否,都可以不用引号引起来,也可以使用

对于多行字符串,使用| 可以保留原来的换行格式

yaml 复制代码
---
- name: test string
  hosts: node1
  tasks:- name: test string
  # 用户显示变量值或者字符串
  debug:
  msg: |
    Example Company
    123 Main Street
    Atlanta, GA 30303
    
输出结果为:
Example Company\n123 Main Street\nAtlanta, GA 30303\n

不使用| 也可以但是会将换行符识别成空格

yaml 复制代码
---
- name: test string
  hosts: node1
  tasks:- name: test string
  # 用户显示变量值或者字符串
  debug:
  msg:
    Example Company
    123 Main Street
    Atlanta, GA 30303
    
输出结果为:
Example Company 123 Main Street Atlanta, GA 30303

使用>

yaml 复制代码
---
- name: test string
  hosts: node1
  tasks:- name: test string
  # 用户显示变量值或者字符串
  debug:
  msg:
    Example Company
    123 Main Street
    Atlanta, GA 30303
    
输出结果为:
Example Company 123 Main Street Atlanta, GA 30303\n

Ansible 遵循 主机变量 > 子组变量 > 父组变量

host_vars/ group_vars/

FACTS 是 Ansible 在受管主机上自动检测到的变量,默认保存在内容中,只存在于本次playbook执行期 间。

bash 复制代码
[dcr@controller web]$ ansible node1 -m debug -a "var=ansible_facts"
node1 | SUCCESS => {
    "ansible_facts": {}
}


- name: Dump facts
  hosts: node1
  tasks:
    - name: Print all facts
      debug:
        var: ansible_facts

输出结果:
ok: [node1] => {
    "ansible_facts": {
        "all_ipv4_addresses": [
            "192.168.108.11",
            "192.168.122.1"
        ],
.......

05-部署文件到受管主机

实验环境准备

bash 复制代码
# 创建项目目录并进入
mkdir web && cd web

# 编写 ansible.cfg 配置文件
cat > ansible.cfg <<'EOF'
[defaults]
remote_user = dcr
inventory = ./inventory

[privilege_escalation]
become = True
become_user = root
become_method = sudo
become_ask_pass = False
EOF

# 编写 inventory 清单文件
cat > inventory <<'EOF'
controller
node1
node2
node3
node4
EOF

Files 模块库核心模块说明

Files 模块库专注于 Linux 文件管理相关任务,涵盖文件创建、复制、编辑、权限修改等功能,常用核心模块如下:

模块 核心功能
file 设置文件 / 目录权限、属主属组、SELinux 上下文,支持创建 / 删除文件、目录、链接
sefcontext 配置持久化 SELinux 上下文规则
lineinfile 操作文件单行内容(添加、替换、注释指定行)
replace 基于正则表达式批量替换文件中匹配的内容
blockinfile 向文件中插入、更新或删除多行文本块
stat 检索文件状态信息(如校验和、权限、修改时间等)
copy 从控制端 / 远程主机拷贝文件到受管节点
synchronize 基于 rsync 同步文件 / 目录,适用于大文件或频繁更新场景
fetch 从受管节点拉取文件到控制节点

核心模块使用示例(含 Playbook 代码)

file 模块(文件 / 目录基础操作)
1. 创建文件并设置权限、属主属组
bash 复制代码
# playbook.yaml
hosts: node1
gather_facts: no
tasks:
  - name: Touch a file and set permissions
    file:
      path: /tmp/testfile  # 文件路径
      owner: dcr        # 属主
      group: wheel         # 属组
      mode: 0640           # 权限(必须加前导0或引号,避免十进制解析错误)
      state: touch         # 状态:创建空文件

运行命令:

bash 复制代码
ansible-playbook playbook.yaml

注意:mode 选项若直接写 640,会被解析为十进制并转换为异常权限,需写 0640'640'

2. 创建目录并设置权限
bash 复制代码
# playbook.yaml
hosts: node1
gather_facts: no
tasks:
  - name: Install httpd (依赖包)
    yum:
      name: httpd
      state: present

  - name: Create webdev directory
    file:
      path: /webdev        # 目录路径
      owner: apache        # 属主(httpd 服务默认用户)
      group: apache        # 属组
      mode: 0755           # 目录权限(读/写/执行)
      state: directory     # 状态:创建目录
3. 删除文件
bash 复制代码
# playbook.yaml
hosts: node1
gather_facts: no
tasks:
  - name: Delete testfile
    file:
      path: /tmp/testfile  # 要删除的文件路径
      state: absent        # 状态:删除(文件/目录不存在时不报错)
sefcontext 模块(SELinux 上下文配置)

用于设置持久化 SELinux 规则,需结合 restorecon 命令生效(仅修改规则库,不直接应用到文件)。

前提条件(受管节点 node1 操作)
bash 复制代码
# 开启 SELinux
vim /etc/selinux/config
SELINUX=enforcing  # 设置为强制模式
reboot  # 重启生效

# 创建测试目录和文件
mkdir /samba
touch /samba/localfile

# 查看当前 SELinux 上下文(初始为 default_t)
ll -Z /samba/
semanage fcontext -l | grep samba_share_t  # 无匹配规则
Playbook 配置(控制节点操作)
bash 复制代码
# playbook.yaml
- hosts: node1
  gather_facts: no
  tasks:
    - name: Set SELinux context for /samba
      sefcontext:
        target: '/samba(/.*)?'  # 匹配 /samba 及子目录所有文件
        setype: samba_share_t   # 目标 SELinux 类型
        state: present          # 状态:添加规则
lineinfile 模块(单行文本操作)
1. 向文件末尾添加指定行
bash 复制代码
# playbook.yaml
hosts: node1
gather_facts: no
tasks:
  - name: Add line to /tmp/testfile
    lineinfile:
      path: /tmp/testfile    # 目标文件
      line: 'Add this line to file'  # 要添加的行
      state: present         # 状态:确保行存在(不存在则添加)

验证命令(受管节点):

bash 复制代码
cat /tmp/testfile
2. 在指定行前后插入内容
bash 复制代码
# 在 Listen 80 行前插入 Listen 79
- hosts: node1
  gather_facts: no
  tasks:
    - name: Insert line before Listen 80
      lineinfile:
        path: /etc/httpd/conf/httpd.conf
        line: 'Listen 79'          # 插入的内容
        insertbefore: 'Listen 80'  # 插入位置(匹配行前)
        state: present

# 在 Listen 80 行后插入 Listen 81
- hosts: node1
  gather_facts: no
  tasks:
    - name: Insert line after Listen 80
      lineinfile:
        path: /etc/httpd/conf/httpd.conf
        line: 'Listen 81'         # 插入的内容
        insertafter: 'Listen 80'  # 插入位置(匹配行后)
        state: present
3. 替换文件中的指定行
bash 复制代码
# 替换含 "Add" 关键字的行
- hosts: node1
  gather_facts: no
  tasks:
    - name: Replace line containing 'Add'
      lineinfile:
        path: /tmp/testfile
        regexp: 'Add'          # 正则匹配要替换的行
        line: 'replace'        # 替换后的内容
        state: present

# 注释 Listen 80 行(替换为 #Listen 80)
- hosts: node1
  gather_facts: no
  tasks:
    - name: Comment Listen 80 line
      lineinfile:
        path: /etc/httpd/conf/httpd.conf
        regexp: '^Listen 80'   # 精确匹配以 Listen 80 开头的行
        line: '#Listen 80'     # 注释后的内容
        state: present
4. 替换为多行文本
bash 复制代码
- hosts: node1
  gather_facts: no
  tasks:
    - name: Replace line with multi-line content
      lineinfile:
        path: /tmp/testfile
        regexp: 'replace'      # 匹配要替换的行
        line: |                # 多行文本(保留换行)
          line 1
          line 2
        state: present
replace 模块(批量文本替换)

基于正则表达式批量替换文件中所有匹配的内容(区别于 lineinfile 仅操作单行)。

bash 复制代码
# playbook.yaml
hosts: node1
gather_facts: no
tasks:
  - name: Replace all lines starting with 'Hello World'
    replace:
      path: /tmp/testfile
      regexp: '^Hello World.*'  # 正则匹配(以 Hello World 开头的所有行)
      replace: 'Hello dcr'  # 替换后的内容
blockinfile 模块(多行文本块操作)

向文件中插入多行文本块,自动添加 Ansible 管理标记(便于后续更新 / 删除)。

bash 复制代码
# playbook.yaml
hosts: node1
gather_facts: no
tasks:
  - name: Add multi-line block to file
    blockinfile:
      path: /tmp/testfile
      block: |                # 多行文本块
        line 1 in file
        line 2 in fileaa
        line 3 in file sss
      state: present          # 状态:添加文本块

验证结果(受管节点):

bash 复制代码
cat /tmp/testfile

输出内容(自动添加标记):

bash 复制代码
# BEGIN ANSIBLE MANAGED BLOCK
line 1 in file
line 2 in fileaa
line 3 in file sss
# END ANSIBLE MANAGED BLOCK
stat 模块(文件状态检索)

用于获取文件详细信息(如校验和、权限、修改时间),并通过 register 注册变量供后续使用。

bash 复制代码
# playbook.yaml
hosts: node1
gather_facts: no
tasks:
  - name: Get file stat info
    stat:
      path: /tmp/testfile
      checksum_algorithm: md5  # 指定校验和算法(md5/sha256 等)
    register: result  # 注册结果到变量 result

  - name: Print MD5 checksum
    debug:
      msg: "/tmp/testfile md5 is {{ result.stat.checksum }}"  # 引用校验和

  - name: Print full stat info
    debug:
      var: result  # 打印所有状态信息
copy 模块(文件拷贝 / 内容写入)
1. 从控制节点拷贝文件到受管节点
bash 复制代码
# playbook.yaml
- hosts: node1
  gather_facts: no
  tasks:
    - name: Copy /etc/hostname to remote /tmp
      copy:
        src: /etc/hostname  # 控制节点源文件路径
        dest: /tmp          # 受管节点目标路径(文件会保留原名)
        force: yes          # 强制覆盖(默认 yes,设置 no 则不覆盖)
2. 直接向文件写入字符串内容
bash 复制代码
# playbook.yaml
hosts: node1
gather_facts: no
tasks:
  - name: Write string to /tmp/testfile
    copy:
      content: "hello world\n"  # 要写入的内容(\n 表示换行)
      dest: /tmp/testfile       # 目标文件路径(不存在则创建)
synchronize 模块(基于 rsync 同步)

依赖 rsync 工具(控制端和受管端需提前安装),适用于大文件或目录同步,效率高于 copy 模块。

1. 同步单个文件
bash 复制代码
# playbook.yaml
hosts: node1
gather_facts: no
tasks:
  - name: Synchronize file to remote
    synchronize:
      src: /tmp/testfile  # 控制端源文件
      dest: /tmp/         # 受管端目标路径
2. 同步目录(含子文件 / 子目录)
bash 复制代码
# playbook.yaml
- hosts: node1
  gather_facts: no
  remote_user: root  # 同步目录需 root 权限
  tasks:
    - name: Synchronize /etc/sysconfig to remote
      synchronize:
        src: /etc/sysconfig  # 控制端源目录
        dest: /tmp/          # 受管端目标路径(会创建 sysconfig 目录)

运行命令(控制端):

bash 复制代码
sudo ansible-playbook playbook.yaml  # 需 root 权限执行
fetch 模块(从受管节点拉取文件)

用于将受管节点的文件拉取到控制节点,自动按 "主机名 / 原路径" 存储。

bash 复制代码
# playbook.yaml
- hosts: node1
  gather_facts: no
  tasks:
    - name: Fetch /tmp/testfile from remote
      fetch:
        src: /tmp/testfile  # 受管节点源文件(必须是文件,不能是目录)
        dest: /tmp          # 控制节点存储路径

验证结果(控制端):

bash 复制代码
# 查看拉取的文件(自动创建主机名目录)
tree /tmp/node1
# 输出:/tmp/node1/tmp/testfile

/tmp/testfile

checksum_algorithm: md5 # 指定校验和算法(md5/sha256 等)

register: result # 注册结果到变量 result

  • name: Print MD5 checksum

    debug:

    msg: "/tmp/testfile md5 is {{ result.stat.checksum }}" # 引用校验和

  • name: Print full stat info

    debug:

    var: result # 打印所有状态信息

    copy 模块(文件拷贝 / 内容写入)

    1. 从控制节点拷贝文件到受管节点
    bash 复制代码
    # playbook.yaml
    - hosts: node1
      gather_facts: no
      tasks:
        - name: Copy /etc/hostname to remote /tmp
          copy:
            src: /etc/hostname  # 控制节点源文件路径
            dest: /tmp          # 受管节点目标路径(文件会保留原名)
            force: yes          # 强制覆盖(默认 yes,设置 no 则不覆盖)
2. 直接向文件写入字符串内容
bash 复制代码
# playbook.yaml
hosts: node1
gather_facts: no
tasks:
  - name: Write string to /tmp/testfile
    copy:
      content: "hello world\n"  # 要写入的内容(\n 表示换行)
      dest: /tmp/testfile       # 目标文件路径(不存在则创建)
synchronize 模块(基于 rsync 同步)

依赖 rsync 工具(控制端和受管端需提前安装),适用于大文件或目录同步,效率高于 copy 模块。

1. 同步单个文件
bash 复制代码
# playbook.yaml
hosts: node1
gather_facts: no
tasks:
  - name: Synchronize file to remote
    synchronize:
      src: /tmp/testfile  # 控制端源文件
      dest: /tmp/         # 受管端目标路径
2. 同步目录(含子文件 / 子目录)
bash 复制代码
# playbook.yaml
- hosts: node1
  gather_facts: no
  remote_user: root  # 同步目录需 root 权限
  tasks:
    - name: Synchronize /etc/sysconfig to remote
      synchronize:
        src: /etc/sysconfig  # 控制端源目录
        dest: /tmp/          # 受管端目标路径(会创建 sysconfig 目录)

运行命令(控制端):

bash 复制代码
sudo ansible-playbook playbook.yaml  # 需 root 权限执行
fetch 模块(从受管节点拉取文件)

用于将受管节点的文件拉取到控制节点,自动按 "主机名 / 原路径" 存储。

bash 复制代码
# playbook.yaml
- hosts: node1
  gather_facts: no
  tasks:
    - name: Fetch /tmp/testfile from remote
      fetch:
        src: /tmp/testfile  # 受管节点源文件(必须是文件,不能是目录)
        dest: /tmp          # 控制节点存储路径

验证结果(控制端):

bash 复制代码
# 查看拉取的文件(自动创建主机名目录)
tree /tmp/node1
# 输出:/tmp/node1/tmp/testfile
相关推荐
爱艺江河2 小时前
Coze平台开发的“行业洞察智能体”:智能体从0到1开发落地方法论——集成豆包大模型与天眼查、自动化邮件等组件能力、借助通义千问API智能搜索一体化智能体
自动化·智能体·可视化编排
风途知识百科3 小时前
GNSS位移监测站——地质灾害自动化监测项目的“压舱石”
运维·自动化
乾元3 小时前
AI 驱动的网络攻防演练与安全态势推演——从“规则检测”到“行为级对抗”的工程体系
网络·人工智能·安全·web安全·架构·自动化·运维开发
梦想的旅途24 小时前
基于 UI 驱动(RPA)实现企业微信外部群自动化推送的技术逻辑
ui·自动化·企业微信·rpa
源创力环形导轨4 小时前
环形导轨常见的应用领域有哪些?
人工智能·自动化·制造·环形导轨
神秘面具男034 小时前
Ansible Playbook 编写与运行
服务器·网络·ansible
优选资源分享5 小时前
zTasker v2.3.4:Windows 自动化任务工具
运维·自动化
梦想的旅途25 小时前
企业微信二次开发:如何优雅地实现外部群自动化管理?
自动化·企业微信·rpa
2501_941982055 小时前
企业微信 API 二次开发之外部群自动化管理
运维·自动化·企业微信