Ansible自动化运维

发布时间 2023-08-14 10:41:44作者: 燚林博客

一、什么是ansible

1、介绍

Ansible 是一款开源自动化平台。是一种简单的自动化语言,能够在 Ansible Playbook 中完美地描述 IT 应用基础架构。也是一个自动化引擎,可运行Ansible Playbook。

2、逻辑图

3、ansible特点

  • 简单明了

  Ansible playbook提供人类可读的自动化。

  • 功能强大

  利用 Ansible 部署应用,也可将它用于配置管理、工作流自动化和网络自动化。

  • 无需代理

  Ansible 围绕无代理架构构建。通常而言,Ansible通过OpenSSH或WinRM 连接它所管理的主机并 且运行任务,方法通常是(但不总是)将称为 Ansible 模块的小程序推送至这些主机。

  • 跨平台支持

  Ansible 提供 Linux、Windows、UNIX 和网络设备的无代理支持,适用于物理、虚 拟、云和容器环境。

  • 轻松管理版本控制

  Ansible Playbook 和项目是纯文本。它们可以视作源代码,放在您的现有版 本控制系统中。

  • 支持动态清单

  可以从外部来源动态更新 Ansible 管理的计算机的列表,随时获取所有受管服务 器的当前正确列表,不受基础架构或位置的影响。

  • 编排可与其他系统轻松集成

  能够利用环境中现有的 HP SA、Puppet、Jenkins、红帽卫星和其他 系统,并且集成到您的 Ansible 工作流中。

4、ansible架构

  • Ansible 架构中有两种计算机类型,即控制节点和受管主机。

  • 受管主机列在清单中,清单还可以将这些系统组织到组中,以便于集中管理。

  • Ansible 用戶无需编写复杂的脚本,而只要创建高级别 play 即可确保主机或主机组处于特定状态。

  • 每个任务运行一个模块,即(使用 Python、PowerShell 或某种其他语言编写的)一小段代码。

  • 在任务中使用时,模块通常确保某一特定方面处于特定状态。

  • 任务、play 和 playbook 设计为具有幂等性。

  • Ansible 也使用插件。插件是您可以添加到 Ansible 中的代码,以对它进行扩展并使它适合新的用途 和平台。

  • Ansible 架构是无代理的。通常,当管理员运行 Ansible Playbook 或临时命令时,控制节点使用 SSH(默认)或 WinRM 连接受管主机。

  • 红帽 AnsibleTower 是一种企业框架,可帮助您规模化控制、保护和管理 Ansible 自动化。

5、ansible控制节点

  • Ansible 易于安装。Ansible 软件只需要安装到要运行它的一个(或多个)控制节点上。由 Ansible 管理的主机不需要安装 Ansible。

  • 控制节点应当是Linux或UNIX系统。不支持将 Microsoft Windows 用作控制节点,Windows 系统可以是被管理主机。

  • 控制节点上需要安装 Python

    • Python3 版本5 或以上

    • Python2 版本7 或以上

    • # yum list   installed   platform-python

6、被管理节点

  • Ansible优点是被管理节点不需要安装特殊的代理。Ansible控制节点使用标准的网络协议连接被管理节点。

  • Linux和UNIX被管理节点需要安装有 Python 2(版本6 或以上)或 Python 3(版本 3.5 或以上)。

  • 对于RHEL8,可以依靠 platform-python 软件包。可以启用并安装 python36或python27。

  • 如果被管理主机上启用了SELinux,需要安装 python3-libselinux软件包,才能使用与任何复制、文件或模板功能相关的模块。

7、ansible软件安装

Ansible仓库默认不在yum仓库中,因此需要下载并启用epel仓库。

8、清单(inventory)

inventory定义Ansible 将要管理的一批主机。这些主机也可以分配到组中,以进行集中管理。

  • 组可以包含子组,主机也可以是多个组的成员。
  • 清单还可以设置应用到它所定义的主机和组的变量。

可以通过两种方式定义主机清单;

  • 静态主机清单可以通可以通过文本文件来定义。
  • 动态主机清单可以根据需要使用外部信息提供程序通过脚本或其他程序来生成。

9、ansible配置文件

通过修改Ansible 配置文件中的设置来自定义Ansible行为。Ansible从控制节点上多个可能的位置之一选择其配置文件。

# /etc/ansible/ansible.cfg  当找不到其它配置文件时则使用此文件。

# /root/.ansible.cfg  当创建此文件并且ansible工作目录没有配置文件时,则使用此文件。

# ./ansible.cfg  当ansible工作目录(执行ansible命令的目录)存在此文件时,则使用此文件。而不使用全局文件和用户目录下的文件。

10、ansible管理机和被管理机初始配置

环境:管理机安装ansible软件,被管理机不需要

系统版本:centos8.2

Python版本:python3.6.8

  • 为了方便执行play,首先实现管理机和被管理机免密登录。

  • 将被管理机主机名和IP写入到管理机的/etc/hosts文件中并ping测试(也可以不写)

  • 创建一个ansible的工作目录,并将全局配置文件复制到工作目录一份。

  • 在工作目录创建一个清单文件。

  • 修改当前目录下cfg配置文件,参数inventory的目录改为当前清单目录。

11、清单验证

12、ansible配置文件部分参数

Ansible 配置文件由几个部分组成,每一部分含有以键值对形式定义的设置。每一个章节名称以方括号括起。

  • [defaults] 章节设置 Ansible 操作的默认值。
  • [privilege_escalation] 配置 Ansible 如何在被管理主机上执行特权升级。

13、ansible远程主机连接配置

  • 清单位置

  Inventory=./inventory位于default章节下

  • 连接设置

默认使用ssh,需要设置ssh信任关系,使用公钥的方式验证连接。

  • 升级权限

  become = true

  become_method = sudo

  become_user = root

14、临时命令

简单的在线操作,无需编写playbook即可运行 ,一次编写一次使用。临时命令是快速执行简单任务时所需要的工具。

15、常用模块介绍

二、ansible playbook

1、play和playbook介绍

  • play是针对清单中选定的主机运行的一组有序任务。playbook是一个文本文件,其中包含由一个或多个按特定顺序运行的play组成的列表。

  • play可以让您将一系列冗长而复杂的手动管理任务转变为可轻松重复的例程,并且具有可预测的成功成果。在 playbook 中,您可以将 play 内的任务序列保存为人类可读并可立即运行的形式。

2、ansible playbook格式

  • Playbook是以YAML格式编写的文本文件,通常使用扩展名yml保存。

  • Playbook使用空格字符缩进来表示其数据结构。YAML对用于缩进的空格数量没有严格的要求。

  • 但是处于层次结构中同一级别的数据元素(例如同一列表中的项目)必须具有相同的缩进量。

  • 如果项目属于其他项目的子项,其缩进数量必须大于父项

  • Playbook开头的一行由三个破折号 (---) 组成,这是文档开始标记;其末尾可能使用三个圆点 (...) 作为文档结束标记,在实际实践中通常会省略。

3playbook基本书写

  • --- 后的行以破折号开头,开始列出 play 列表中第一个。

  • Play本身是一个键值对集合。同一个play中的键应当使用相同的缩进量。以上示例显示了具有三个键 的YAML代码片段。前两个键具有简单的值。第三个将含有三个项目的列表作为值。

  • 第一个键是name键是可选的,但建议使用它,因为它有助于记录您的playbook。

  • 第二个键是hosts属性,它指定对其运行play中的任务的主机。

  • 第三个键是tasks属性,其值指定要为该play运行的任务的列表。

  • tasks属性按顺序实际列出要在被管理主机上运行的任务。列表中各项任务本身是一个键值对集合。name是记录任务用途的可选标签。最好命名为任务的描述,从而帮助记录自动流程中每一步的用途 ,service是要为这个任务运行的模块。其参数作为一组键值对传递(name 和 enabled)。

4、运行playbook

  • ansible-playbook命令可用于运行playbook。该命令在控制节点上执行,要运行的playbook的名称则作为参数传递。

    ansible-playbook site.yml

  • 配置ansible的输出

  ansible-playbook命令提供的默认输出不提供详细的任务执行信息。ansible-playbook -v命令提供了额外的信息,总共有四个级别 (-vvvv)

  • Playbook语法验证

     ansible-playbook --syntax-check  webserver.yml

  • 执行模拟运行,使用-C选项对playbook执行模拟运行。使Ansible报告在执行该playbook时将会发生什么更改,不会对受管主机进行任何实际的更改。

     ansible-playbook  -C  webserver.yml 

5、实现多个playbook

  • Playbook(剧本)是由YAML文件组成,含有一个或多个play项目组(场次)组成的列表。一个play按顺序列出了要对清单中的选定主机执行的多个task任务(条次)。

  • 如果一个playbook中含有多个play,每个play可以将其task应用到单独的一组主机。

6、play中的远程用户和特权升级

Play可以将不同的远程用戶或特权升级设置用于play,取代配置文件中指定的默认设置。play本身中与hosts或tasks关键字相同的级别上设置。(简单来说在play中配置特权升级可以取代配置文件中的设置)

  • 用戶属性

  Playbook中的任务通常通过与被管理主机的网络连接来执行。与临时命令相同,用于任务执行的用戶帐戶取决于Ansible配置文件/etc/ansible/ansible.cfg中的不同关键字。运行任务的用戶可以通过remote_use关键字来定义。启用特权升级,become_user 等其他关键字也会发生作用。

  • 特权升级属性

  playbook内定义特权升级参数。become布尔值关键字可用于启用或禁用特权升级,取yes或true值来启用特权升级,或者取no或false值来禁用它。使用become_metho关键字来定义特定play期间要使用的特权升级方法。

以上示例表示remote_user即使在配置文件中是root也无效,使用play中规定的automation登录,并根据配置文件中become的配置进行提权。

7、模块文档和模块查找

  • Ansible文档网站http://docs.ansible.com。通过该网站上的模块索引,可以轻松浏览Ansible随附的模块列表。
  • 使用ansible-doc命令来查找关于本地系统上安装的模块的信息

  ansible-doc  –l

  ansible-doc   -s

  ansible-doc   module_name

8、playbook语法

  • YAML注释

  注释也可以用于提高可读性。在YAML中,井字符号 (#) 右侧的所有内容都是注释。如果注释的左侧有内容,请在该编号符号的前面加一个空格。

  • YAML字符串

  YAML中字符串通常不需要放在引号里,即使字符串中包含空格。字符串可以用双引号或单引号包裹。

  this is  a  string

  'this is  another  string'

  "this is  yet  another  a  string"

编写多行字符串方式。可以使用竖线(|)字符表示要保留字符串中的换行字符;使用大于号(>)字符来表示换行字符转换成空格。

  • YAML字典

  缩进块的形式编写的键值对集合:

  字典也可以使用以花括号括起的内联块格式编写:

  • YAML列表

  使用普通单破折号语法编写的列表:

  列表也有以方括号括起的内联格式:

三、ansible变量和facts

1、ansible变量介绍

  • Ansible支持变量,并在Ansible项目的所有文件中重复使用已经定义的变量。可以简化项目的创建和维护,并减少书写错误的数量。

  • 通过变量,可以在Ansible项目中管理给定环境的动态信息。

  • 要创建的用戶
  • 要安装的软件包
  • 要重新启动的服务
  • 要删除的文件
  • 要从互联网检索的存档

2、变量名命名

  • 变量的名称必须以字母开头,变量名只能含有字母、数字和下划线。

  • 不得以数字开头
  • 不得以特殊符号开头
  • 变量名称区分大小写
  • 变量名中间不能包含有空格

3、定义变量

  • Ansible项目中的多个位置可以声明定义变量。

  • 全局范围: 从命令行或Ansible配置设定的变量
  • Play范围: 在play和相关结构中设定的变量
  • 主机范围: 由清单、facts收集或注册的任务,在主机组和个别主机上设置的变量。
  • 如果在多个级别上定义了相同名称的变量,则采用优先级别最高的变量。窄范围优先于更广泛的范围。

  • 由inventory定义的变量将被playbook定义的变量覆盖。

4、在playbook中使用vars定义变量

  • 编写playbook时,可以定义自己的变量, 在任务中调用变量。

  • Playbook变量可以通过多种方式定义。一种常见方式是将变量放在playbook开头的vars块中。

  • 声明了变量后,管理员可以在任务中使用这些变量。若要引用变量,可将变量名称放在双花括号”{{ }}”内。在任务执行时,Ansible会将变量替换为变量对应的值。

5、使用vars_files指令在playbook中定义变量

在外部文件中定义playbook变量。此时不使用playbook中的vars块,可以改为使用vars_files 指令,后面跟上相对于playbook位置的,同一目录下的外部变量文件名称列表。

6、主机变量和组变量

  • 直接应用于主机的清单变量分为两大类:

  • 主机变量,应用于特定主机。
  • 组变量,应用于一个主机组或一组主机组中的所有主机。
  • 主机变量优先于组变量,但playbook中定义的变量的优先级比这两者更高。(playbook定义变量 > 主机变量 > 组变量)
6.1 Inventory文件中定义(不推荐)

主机变量使用:

组变量使用:

例1:定义test1组变量

例2:把一个组作为另一个组的子成员

6.2 分文件定义Host和Group变量

在inventory主文件中保存所有的变量并不是最佳的方式.还可以保存在独立的文件中,这些独立文件与inventory文件保持关联。不同于inventory文件(INI格式),这些独立文件的格式为YAML。

  • 定义主机和主机组的变量的首选做法是在与inventory文件或目录相同的工作目录中,创建 group_vars 和host_vars两个目录。这两个目录分别包含用于定义组变量和主机变量的文件。
  • 定义用于servers组的组变量需要创建名为group_vars/servers的YAML文件,该文件的内容将使用与playbook相同的语法将变量设置为值
  • 定义用于特定主机的主机变量,需要在host_vars目录中创建名称与主机匹配的文件来存放主机变量。

例1:定义主机变量

例2:定义组变量

例3:为一个主机,或一个组,创建一个目录,目录名就是主机名或组名。目录中的可以创建多个文件, 文件中的变量都会被读取为主机或组的变量(当变量变得太多时,分文件定义变量更方便我们进行管理和组织)。

7、命令行覆盖变量

inventory中的变量可被playbook中设置的变量覆盖,这两种变量又可通过在命令行中传递参数到ansible或ansible-playbook命令来覆盖。在命令行上设置的变量称为额外变量。(优先级最高)

8、使用数组作为变量

数组好处在于,数组是可以浏览的,可读性比较强。可以用 “." 点来一级一级引用,也可以用 [ ]来一级一级引用。

9、使用已注册变量捕获命令输出

例:在playbook中可以使用register将捕获命令的输出保存在临时变量中,然后使用debug模块进行显示输出。

10、ansible-vault管理密钥

  • ansible vault在代码中表示为一个class,可以理解为ansible下的一个工具,使用AES256对称加密方式加密敏感信息。
  • ansible vault作用是对密码,API key等数据进行加密,通常,此信息可能以纯文本形式存储在清单变量或其他Ansible文件中。
  • 任何有权访问Ansible文件的用戶或存储这些Ansible文件的版本控制系统都能够访问此敏感数据。存在安全风险。
  • 使用Ansible随附的Ansible Vault可以加密和解密任何由Ansible使用的结构化数据文件。
  • ansible-vault的命令行工具创建、编辑、加密、解密 和查看文件。
  • Ansible Vault可以加密任何由Ansible使用的结构化数据文件。包括清单变量、playbook中含有的变量文件、在执行playbook时作为参数传递的变量文件。
10.1 create创建加密的文件

要创建新的加密文件,可使用ansible-vault create filename命令。

指定密码文件创建加密yml文件:

10.2 view查看加密的文件

使用ansible-vault view filename命令查看Ansible Vault加密文件,而不必打开它进行编辑。

10.3 edit编辑加密的文件

编辑现有的加密文件,Ansible Vault提供了ansible-vault edit filename命令。

  • 将文件解密为一个临时文件,并允许您编辑该文件;保存时,它将复制其内容并删除临时文件。
  • edit子命令始终会重写文件,在文件需要编辑时使用edit子命令。在文件托管在版本控制库下时有影响。
  • 要查看文件的内容而不进行更改,始终应使用view子命令。

10.4 encrypt加密已存在的文件

要加密已存在的文件,使用ansible-vault encrypt filename命令

  • 此命令可取多个需要加密文件的名称作为参数。
  • 使用--output=OUTPUT_FILE选项,可将加密文件保存为新的名称;只能通过--output选项使用一个输入文件。

加密文件时另存为新的文件:

源文件不影响:

另存为的文件为加密文件:

10.5 decrypt解密已存在的文件

已存在的加密文件可以通过ansible-vault decrypt filename命令永久解密;在解密单个文件时,可使用--output选项以其他名称保存解密的文件。

解密时另存为其它文件:

源文件仍然加密:

另存为的文件为解密文件:

10.6 rekey更改加密文件的密码

可使用ansible-vault rekey filename命令更改加密文件的密码。

此命令可一次性更新多个数据文件的密钥。它将提示提供原始密码和新密码。在使用vault密码文件时,请使用 --new-vault-password-file选项。

使用密码文件更改密码:

10.7 playbook使用ansible-vault

运行时访问通过Ansible Vault加密的文件,需要向ansible-playbook命令提供加密密码。如果不提供密码,playbook 将返回错误;要为playbook提供vault密码,可使用-vault-id选项。

使用交互方式提供密码:

有密码文件时可以指定密码文件,不使用交互方式提供密码:

从Ansible 2.4开始,可以通过ansible-playbook使用多个Ansible Vault密码。

创建多个密码文件:

用密码文件分别加密两个文件:

运行playbook时可以指定多个加密文件,会逐个匹配:

11、变量文件管理方法推荐

  • 若要简化管理,务必要设置Ansible项目, 使敏感变量和所有其他变量保存在相互独立的文件中。包含敏感变量、信息的文件可通过ansible-vault命令进行保护。
  • 管理组变量和主机变量的首选方式是在playbook级别上创建目录。
  • group_vars目录通常包含名称与它们所应用的主机组匹配的变量文件。
  • host_vars目录通常包含名称与它们所应用的被管理主机名称匹配的变量文件。

12、   管理ansible facts

12.1 Ansible facts介绍

Ansible事实是Ansible在被管理主机上自动检测到的变量。事实中含有与主机相关的信息,可以像 play中的常规变量、条件、循环或依赖于从受管主机收集的值的任何其他语句那样使用。

  • 主机名称
  • 内核版本
  • 网络接口
  • IP 地址
  • 操作系统版本
  • 各种环境变量
  • CPU 数量
  • 提供的或可用的内存
  • 可用磁盘空间

借助facts,可以方便地检索受管主机的状态,并根据该状态确定要执行的操作。

  • 可以根据facts含有被管理主机当前内核版本的事实运行条件任务,以此来重新启动服务器。
  • 可以根据通过facts报告的可用内存来自定义MySQL配置文件。
  • 可以根据facts的值设置配置文件中使用的IPv4地址。

每个play在执行第一个任务之前会先自动运行setup模块来收集facts。在 Ansible 2.3中报告为Gathering Facts任务,或者在更早版本的 Ansible中报告为setup。默认情况下,无需具有在play中运行setup的任务。通常会自动运行。

12.2 Facts示例

12.3 关闭facts收集

play禁用facts收集,可将gather_facts关键字设置为no, gather_facts关键字设置为no, 可以随时运行setup模块的任务来手动收集。

不想为play收集facts的情况:

  • 可能是不准备使用任何事实,并且希望加快play速度或减小play在受管主机上造成的负载
  • 可能是被管理主机因为某种原因而无法运行setup模块
  • 需要安装一些必备软件后再收集事实。

12.4 创建自定义facts
  • 管理员可以创建自定义事实,将其本地存储在每个被管理主机上。
  • 自定义facts整合到setup模块在受管主机上运行时收集的标准facts列表中。让被管理主机能够向Ansible提供任意变量,以用于调整play的行为。
  • 自定义facts可以在静态文件中定义,格式可为INI文件或采用JSON。也可以是生成JSON输出的可执行脚本,如同动态inventory脚本一样。
  • 借助自定义facts,管理员可以为受管主机定义特定的值,供play用于填充配置文件或有条件地运行任务。
  • 默认情况下,setup模块从各被管理主机的/etc/ansible/facts.d目录下的文件和脚本中加载自定义事实。各个文件或脚本的名称必须以.fact结尾才能被使用。动态自定义事实脚本必须输出

JSON格式的事实,而且必须是可执行文件。

示例:

创建一个.fact文件,手动设置fact:

需要确保被受管主机上有facts.d目录,因为setup模块从各被管理主机的/etc/ansible/facts.d目录下的文件和脚本中加载自定义事实。

编写一个playbook文件,准备完成facts的推送:

在被受管主机上查看是否已推送:

手动获取一次setup:

可以从输出内容中找到刚刚添加的facts:

可以编写一个playbook来使用这些facts:

13、魔法变量

变量属于非facts或通过setup模块配置,也由Ansible自动设置。魔法变量也可用于获取与特定被管理主机相关的信息。

  • hostvars

包含被管理主机的变量,可以用于获取另一台受管主机的变量的值。如果还没有为被管理主机收集facts,则它不会包含该主机的facts。

  • group_names

列出当前被管理主机所属的所有组

  • groups

列出清单中的所有组和主机

  • Inventory_hostname

包含清单中配置的当前被管理主机的主机名称。可能因为各种原因而与事实报告的主机名称不同。

四、任务控制管理

1、ansible loop循环控制

  • 通过利用循环,管理员无需编写多个使用同一模块的任务;不必编写五个任务来创建五个用戶,而是只需编写一个任务来对含有五个用戶的列表迭代。
  • Ansible支持使用loop关键字对一组项目迭代任务;可以配置循环以利用列表中的各个项目、列表中各个文件的内容、生成的数字序列或更为复杂的结构来重复任务。
1.1  Loop数组循环

loop关键字添加到任务中,将应对其迭代任务的项目列表取为值。循环变量item保存每个迭代过程中使用的值。

1.2 vars传递数组给Loop循环

1.3 Loop字典循环

loop列表不需要是简单值列表。在以下示例中, 列表中的每个项实际上是散列或字典。示例中的每个散列或字典具有两个键name和groups,当前item循环变量中每个键的值分别通过item.name和item.groups变量来检索。

1.4 vars传递字典给Loop循环

1.5 Register变量与Loop一起使用

可以使用register关键字捕获循环任务的输出

2、when条件判断

  • Ansible使用conditionals在符合特定条件时执行任务或play。
  • 管理员可利用条件来区分不同的被管理主机,并根据它们所符合的条件来分配功能。
  • Playbook变量、注册的变量和Ansible事实都可通过条件来进行测试。
  • 可以使用比较字符串、数字数据和布尔值的运算符。
  • Ansible 中使用条件的情况:
  • 可以在变量中定义硬限制(如min_memory)并将它与受管主机上的可用内存进行比较。
  • Ansible可以捕获并评估命令的输出,以确定某一任务在执行进一步操作前是否已经完成。
  • 可以利用Ansible事实来确定受管主机网络配置,并且决定要发送的模板文件。
  • 可以评估CPU的数量,来确定如何正确调节某一Web服务器。
  • 将注册的变量与预定义的变量进行比较,以确定服务是否已更改。
2.1 示例1:条件判断语法

when语句用于有条件地运行任务。When语句取测试的条件作为值。如果条件满足,则运行任务。如何条件不满足,则跳过任务。

2.2  示例条件

2.3  示例2:测试多个条件

一个when语句可用于评估多个条件。可以使用and或or关键字组合条件,并使用括号分组条件;如果任一条件为真时满足条件语句,则应当使用 or 语句;使用and运算时,两个条件都必须为真,才能满足整个条件语句。

2.4 示例3:when关键字提供列表

when关键字还支持使用列表来描述条件列表。向when关键字提供列表时,将使用and运算组合所有条件。

3、ansible处理程序

3.1 处理程序介绍
  • Ansible模块设计为具有幂等性,在正确编写的playbook中,playbook及其任务可以运行多次而不会改变受管主机,除非需要进行更改使受管主机进入所需状态。
  • 任务确实更改系统时,可能需要运行进一步的任务。例如,更改服务配置文件时可能要求重新加载该服务以便使更改的配置生效。
  • 处理程序是响应由其他任务触发的通知的任务。仅当任务在被管理主机上更改了某些内容时,任务才通知其处理程序。
  • 每个处理程序具有全局唯一的名称,在 playbook中任务块的末尾触发。
  • 如果没有任务通过名称通知处理程序,处理程序就不会运行。
3.2 处理程序示例:

处理程序可视为非活动任务,只有在使用notify语句显示调用时才会被触发。此示例中tasks只有一个任务,如果有多个任务则多个任务都执行成功才会执行处理程序;因为notify的缩进比tasks靠后。

Notify的名字restart apache和handlers的name:restart apache要一致,否则报错。

3.3 使用处理程序的好处
  • 处理程序始终按照play的handlers部分指定的顺序运行。不按在任务中由notify语句列出的顺序运行,或按任务通知它们的顺序运行。
  • 处理程序通常在相关play的所有其他任务完成后运行。playbook的tasks部分中某一任务调用的处理程序,将等到tasks下的所有任务都已处理后才会运行。
  • 处理程序名称存在于各play命名空间中。如果两个处理程序被错误地给予相同的名称,则仅会运行一个。
  • 即使有多个任务通知处理程序,该处理程序依然仅运行一次。如果没有任务通知处理程序,它就不会运行。
  • 包含notify语句的任务没有报告changed结果,则处理程序不会获得通知。处理程序将被跳过,直到有其他任务通知它。只有相关任务报告了 changed状态,Ansible才会通知处理程序。

4、忽略任务失败

  • Ansible评估各任务的返回代码,从而确定任务是成功还是失败。通常而言,当任务失败时,Ansible 将立即在该主机上中止play的其余部分并且跳过所有后续任务。

  • 希望即使在任务失败时也继续执行play,可以通过忽略失败的任务来覆盖此行为。可以在任务中使用ignore_errors关键字来实现此目的。

5、任务失败后强制执行处理程序

  • 如果任务失败并且play在该主机上终止,则收到play中早前任务通知的处理程序将不会运行。

  • 如果在play中设置force_handlers: yes关键字,则即使play因为后续任务失败而中止也会调用被通知的处理程序。

6、指定任务失败条件

可以在任务中使用failed_when关键字来指定表示任务已失败的条件,常与命令模块搭配使用,模块可能成功执行了某一命令,但命令的输出可能指示了失败。

failed_when的作用就是,当对应的条件成立时,将对应任务的执行状态设置为失败。

下例中,一共有三个任务。

第一个任务通过debug模块输出规定内容;第二个任务通过shell模块输出内容将返回值注册到return_value变量中;failed_when的条件表示error字符存在在shell的输出中则shell模块的执行状态为失败;playbook将终止运行;第三个任务将不执行。

注释failed_when的执行结果:

7、指定何时任务报告changed结果

当任务被管理主机进行了更改时,会报告changed状态并通知处理程序;hanged_when关键字可用于控制任务在何时报告已进行了更改,shell模块将用于获取供后续任务使用的Kerberos凭据。它通常会在运行时始终报告changed。 为抑制这种更改,应设置changed_when: false,以便它仅报告ok或failed。

changed_when关键字的作用是在条件成立时,将对应任务的执行状态设置为changed。

7.1 示例1

debug模块在正常执行的情况下只能是"ok"状态,上例中,我们使用’changed_when’关键字将debug模块的执行后的状态定义为了"changed"。

注释changed_when后的执行结果:

7.2 示例2:

changed_when除了能够在条件成立时将任务的执行状态设置为"changed",还能让对应的任务永远不能是changed状态。

当将changed_when直接设置为false时,对应任务的状态将不会被设置为changed,如果任务原本的执行状态为changed,最终则会被设置为ok。

注释changed_when后执行结果:

8、ansible块和错误处理

8.1 block模块的使用

在playbook中,块是对任务进行逻辑分组的子句,可用于控制任务的执行方式。例如,任务块可以含有when关键字,以将某一条件应用到多个任务。

使用了block后,我们可以对整个block块应用when条件,以上示例when条件显示需要满足的IP地址才可以执行tasks,但是IP故意填错,执行后:

不使用block模块时,则执行会返回第一条任务:

8.2 block结合rescue和always处理错误

可结合rescue和always语句来处理错误。如果块中的任何任务失败,则执行其rescue块中的任务来进行恢复。在block子句中的任务以及rescue子句中的任务(如果出现故障)运行之后,always子句中的任务运行。

  • block: 定义要运行的主要任务。
  • rescue: 定义要在block子句中定义的任务失败时运行的任务。
  • always: 定义始终都独立运行的任务,不论block和rescue子句中定义的任务是成功还是失败。

执行后将跳过第二个任务

修改第一个任务为错误:

执行yml后,将运行第二个任务:

9、files模块

9.1 files模块库

Files模块库包含的模块允许您完成与Linux文件管理相关的大多数任务,如创建、复制、编辑和 修改文件权限等属性。下表提供了常用文件管理模块的列表。

9.2 files模块自动化示例

在被管理主机上创建、复制、编辑和删除文件可以使用 Files 模块库中的模块实施的常用任务。以下示例显示了可以使用这些模块自动执行常用文件管理任务的方式。

9.3 在被管理主机上复制和编辑文件
  • copy 模块用于将位于控制节点上的 Ansible 工作目录中的文件复制到选定的受管主机
  • 设置为force: yes。强制copy模块覆盖远程文件
  • 设置为force: no,则它仅会将该文件复制到被管理主机
  • lineinfile 在文件中添加内容
  • blockinfile要将文本块添加到现有文件

10、JINJA2模板

10.1 使用JINJA2模板部署自定义文件
  • Ansible将Jinja2模板系统用于模板文件。Ansible还使用Jinja2语法来引用playbook中的变量
  • 管理文件的一种更强大的方法是为其构建模板。通过此方法,可以使用 Ansible 变量和facts编写一个模板配置文件,在部署该文件时自动为受管主机自定义此模板配置文件。
  • 使用分隔符
  • Jinja2 模板将变量和逻辑表达式置于标记或分隔符之间:
  • {% EXPR %} 用于表达式或逻辑 (如循环)
  • {{ EXPR }}则用于向最终用戶输出表达式或变量的结果。后一标记在呈现时将被替换为一个或多个值,对最终用戶可用。
  • {# COMMENT #}语法括起不应出现在最终文件中的注释
10.2 构建jinja2模板
  • Jinja2模板由多个元素组成:数据、变量和表达式。
  • 在呈现Jinja2模板时,这些变量和表达式被替换为对应的值。模板中使用的变量可以在playbook的vars部分中指定。可以将被管理主机的facts用作模板中的变量。
10.3 部署jinja2模板
  • jinja2模板是功能强大的工具,可用于自定义要在受管主机上部署的配置文件。创建了适用于配置文件的Jinja2 模板后,它可以通过 template 模块部署到被管理主机上,该模块支持将控制节点中的本地文件转移到被管理主机。
  • 使用template模块,与 src 键关联的值指定来源Jinja2模板,与dest 键关联的值指定要在目标主机上创建的文件。
10.4 管理模板文件
  • 为避免系统管理员修改Ansible部署的文件,最好在模板顶部包含注释,以指示不应手动编辑该文件。
  • 使用ansible_managed指令中设置的 Ansible managed字符串来执行此操作。这不是正常变量,但可以在模板中用作一个变量。ansible_managed 指令在cfg 文件中设置。
10.5 控制结构
  • 模板文件中使用Jinja2控制结构,以减少重复键入,为play中的每个主机动态输入条目, 或者有条件地将文本插入到文件中
  • 使用循环

Jinja2使用for语句来提供循环功能。user 变量替换为 users 变量中包含的所有值, 一行一个值。

10.6 使用条件句

Jinja2使用if语句来提供条件控制。如果满足某些条件,这允许在已部署的文件中放置一行 。

仅当 finished 变量的值为 True 时,才可将 result 变量的值放入已部署的文件。

10.7 变量过滤器

Jinja2提供了过滤器,更改模板表达式的输出格式,适用于YAML和JSON等语言的过滤器。to_json过滤器使用JSON格式化表达式输出,to_yaml 过滤器则使用 YAML 格式化表达式输出。

10.8 变量测试

在Ansible Playbook中与when子句一同使用的表达式是Jinja2表达式。用于测试返回值的内置 Ansible测试包括failed、changed、succeeded 和 skipped。

五、项目管理

1、管理动态清单

  • 动态生成清单。

  • 使用的静态清单文件很容易编写,对于管理小型基础架构而言也很方便。如果要操作许多台计算机,或者在计算机更替非常快的环境中工作,可能难以让静态清单文件保持最新状态。

  • 大多数大型IT环境中设有系统来跟踪可用的主机以及它们的组织方式。

  • Ansible支持动态清单脚本,这些脚本在每当Ansible执行时从这些类型的来源检索当前的信息,使清单能够实时得到更新。

2、开源社区脚本

开源社区向Ansible项目贡献了大量现有的动态清单脚本。没有包含在ansible软件包中,没有红帽的官方支持。脚本可从Ansible GitHub网站获取

  • https://github.com/ansible/ansible/blob/devel/examples/inventory_script_schema.json

  • 贡献的动态清单脚本以一些数据源或平台作为对象

  • 私有云平台,如红帽 OpenStack 平台。
  • 公共云平台,如 Rackspace Cloud、Amazon Web Services EC2 和 Google Compute Engine。
  • 虚拟化平台,如红帽虚拟化 (oVirt) 和 VMware vSphere。
  • 平台即服务解决方案,如 OpenShift Container Platform。
  • 生命周期管理工具,如 Foreman(搭配红帽卫星 6 或独立使用)和 Spacewalk(红帽卫星 5 的上 游)。
  • 主机托管提供程序,如 Digital Ocean 和 Linode。

3、编写动态清单程序

  • 如果使用的目录系统或基础架构没有动态清单脚本,可以编写自定义动态清单程序。可以使用任何编程语言编写自定义程序,但传递适当的选项时必须以JSON格式返回清单信息

  • ansible-inventory命令是学习如何以JSON格式编写Ansible清单的有用工具

  • 以JSON格式显示清单文件的内容,运行ansible-inventory --list命令