如何创建 Ansible Play 和 Playbook - 第 5 部分
在 Ansible 系列的第 5 部分中,我们将解释如何使用 Ansible 模块创建 Ansible Plays 和 Playbooks。
Ansible 附带称为模块 的独立脚本,这些脚本在playbooks 中用于在远程节点上执行专门任务。
模块对于自动化任务非常有用,例如包管理、归档和复制文件等等。它们允许您调整配置文件并管理路由器、交换机、负载平衡器、防火墙和许多其他设备等设备。
本子主题的目的是让您概述可以通过 Ansible 模块 完成的各种任务:
Linux 中的包管理
包管理是系统管理员最重要、最频繁的任务之一。 Ansible 附带的模块可帮助您在基于 RedHat 和 Debian 的系统中执行包管理任务。
它们相对容易猜测。有用于基于 Debian 的 APT 软件包管理的 apt 模块,用于 YUM 软件包管理的旧 yum 模块,以及与较新的 RHEL 发行版相关的 dnf 模块 。
以下是如何在剧本中使用模块的一些示例:
示例 1:在 RHEL 8 上安装 Apache Web 服务器
---
- name: install Apache webserver
hosts: webservers
tasks:
- name: install httpd
dnf:
name: httpd
State: latest
示例 2:在 Debian 10 上安装 Apache Web 服务器
---
- name: install Apache webserver
hosts: databases
tasks:
- name: install Apache webserver
apt:
name: apache2
State: latest
服务模块
服务模块允许系统管理员启动、停止、更新、升级和重新加载系统上的服务。
示例 1:启动 Apache Web 服务器
---
- name: Start service httpd, if not started
service:
name: httpd
state: started
示例 2:停止 Apache Web 服务器
---
- name: Stop service httpd
service:
name: httpd
state: stopped
示例 3:重新启动网络接口 enp2s0
---
- name: Restart network service for interface eth0
service:
name: network
state: restarted
args: enp2s0
复制模块
顾名思义,复制模块将文件从远程计算机上的一个位置复制到同一计算机上的不同位置。
示例1:将文件从本地复制到远程Linux
---
- name: Copy file with owner and permissions
copy:
src: /etc/files/tecmint.conf
dest: /srv/tecmint.conf
owner: tecmint
group: tecmint
mode: '0644'
该剧本将配置文件 howtoing.conf 从 /etc/files/ 目录复制到 /srv/ 目录作为 howtoing > 具有 0644 权限的用户。
权限也可以使用符号表示法来表示,如最后一行所示。
示例2:将文件从本地复制到远程Linux
---
- name: Copy file with owner and permissions
copy:
src: /etc/files/tecmint.conf
dest: /srv/tecmint.conf
owner: tecmint
group: tecmint
mode: u=rw, g=r, o=r
上例中的权限可以表示为最后一行所示,用户被分配读和写权限,组被分配写权限,其余的世界被分配了读取权限。
文件模块
文件模块用于执行许多文件操作,包括创建文件和目录、分配文件权限以及设置符号链接。
示例1:执行Linux文件权限
---
- name: Change file ownership, group, and permissions
file:
path: /etc/tecmint.conf
owner: tecmint
group: tecmint
mode: '0644'
上面的代码在/etc目录中创建了一个名为howtoing.conf的文件,将权限设置为0644。
示例2:删除Linux文件
---
- name: Remove file (delete file)
file:
path: /etc/tecmint.conf
state: absent
这将删除文件 howtoing.conf。
示例 3:创建目录
---
- name: create a directory if it doesn’t exist
file:
path: /etc/mydirectory
State: directory
mode: '0777'
这将在/etc目录中创建一个目录,并将权限设置为0777。
示例 4:递归删除目录
---
- name: Recursively deleting a directory
file:
path: /etc/tecmint.conf
state: absent
上面的播放递归地删除了一个目录。
行文件模块
当您想要更改文件中的单行时,lineinfile 模块非常有用。它可以取代现有的生产线。
示例 1:在 Linux 中操作文件
---
- name: Ensure SELinux is set to enforcing mode
lineinfile:
path: /etc/selinux/config
regexp: '^SELINUX='
line: SELINUX=disabled
上面的例子将SELINUX值设置为disabled。
SELINUX=disabled
示例 2:在 Linux 中更改文件
---
- name: Add a line to a file if the file does not exist, without passing regexp
lineinfile:
path: /etc/hosts
line: 10.200.50.51 linux-console.net
create: yes
这会将条目 10.200.50.51 howtoing.com 添加到 /etc/hosts 文件中。
存档模块
Archive 模块用于创建单个或多个文件的压缩存档。它假设压缩源存在于目标目的地上。归档后,可以使用语句 remove=True
删除或删除源文件。
示例 1:创建存档文件
- name: Compress directory /path/to/tecmint_dir/ into /path/to/tecmint.tgz
archive:
path: /path/to/tecmint_dir
dest: /path/to/tecmint.tgz
This compresses the /path/to/tecmint_dir directory to /path/to/tecmint.tgz
示例 2:创建存档文件并删除
- name: Compress regular file /path/to/tecmint into /path/to/foo.gz and remove it
archive:
path: /path/to/tecmint
dest: /path/to/tecmint.tgz
remove: yes
在上面的播放中,源文件/path/to/howtoing在归档完成后被删除。
示例 3:创建存档文件
- name: Create a bz2 archive of /path/to/tecmint
archive:
path: /path/to/tecmint
format: bz2
这将从 /path/to/howtoing 文件创建一个 bz2 格式的压缩文件。
Git 模块
该模块管理软件存储库的 git 签出。
示例 1:检查 Git 存储库
- git:
repo: 'https://foosball.example.org/path/to/repo.git'
dest: /srv/checkout
version: release-0.22
命令模块
command 模块是最常用的模块之一,它采用命令名称,后面跟着参数列表。该命令的传递方式与您在 Linux shell 中键入的方式相同。
示例 1:运行命令
- name: Executing a command using the command module
command: cat helloworld.txt
示例 2:检查远程 Linux 的正常运行时间
---
- name: Check the remote host uptime
hosts: servers
tasks:
- name: Execute the Uptime command over Command module
register: uptimeoutput
command: "uptime"
- debug:
var: uptimeoutput.stdout_lines
命令模块检索远程服务器的正常运行时间。
用于检索运行命令结果的变量
通常,Ansible playbook 用于在托管主机上执行任务,而不在命令行上显示输出。然而,在某些情况下,您可能需要捕获输出或结果。在本节中,我们将引导您了解如何在变量中捕获 playbook 的输出并稍后显示它。
ansible 寄存器用于捕获任务的输出并将其保存为变量。此后该变量将包含任务的标准输出。
例如,假设您要使用 df -Th/命令检查各个根目录中受管节点的磁盘使用情况。您将使用 'command'
模块定义命令,并使用 'register'
将 std 输出保存在变量中。
要显示该命令,您将使用 ‘debug’
模块以及 stdout 返回值。
---
- hosts: all
become: yes
tasks:
- name: Execute /boot usage on Hosts
command: 'df -Th /'
register: df
- debug: var=df.stdout
现在,让我们运行剧本。在本例中,我们将 playbook 命名为 check_disk_space.yml。
ansible-playbook check_disk_space.yml
正如您所看到的,输出都是混乱的,很难理解。
要对齐输出并使其更易于阅读,请将 stdout 返回值替换为 stdout_lines。
---
- hosts: all
become: yes
tasks:
- name: Execute /boot usage on Hosts
command: 'df -Th /'
register: df
- debug: var=df.stdout_lines
使用条件控制播放执行
就像在编程语言中一样,当可能有多个结果时使用条件语句。让我们看一下 Ansible playbook 中一些常用的条件语句。
当语句
有时,您可能希望在特定节点而不是其他节点上执行任务。 'when'
条件语句在剧本中非常容易使用和实现。使用 'when'
子句时,只需声明该子句旁边的条件,如下所示:
when: condition
当条件满足时,任务将在远程系统上执行。
让我们看几个例子:
示例 1:使用 When 运算符
---
- hosts: all
tasks:
- name: Install Nginx on Debian
apt: name=nginx state=present
when: ansible_os_family == “Debian”
上面的例子在运行 Debian 系列发行版的主机上安装了 Nginx 网络服务器。
您还可以在when 条件语句旁边使用OR
和AND
运算符。
示例 2:将 AND 运算符与 When 一起使用
---
- hosts: all
tasks:
- name: Install Nginx on Debian
apt: name=nginx state=present
when: ansible_os_family == “Debian” and
ansible_distribution_version == “18.04”
使用 AND
运算符时,必须满足两个语句才能执行任务。
上面的例子在运行 Debian 系列操作系统(版本 18.04)的节点上安装了 Nginx。显然,这将是 Ubuntu 18.04。
示例 3:将 OR 运算符与 When 一起使用
使用OR
运算符,如果满足任一条件,则执行任务。
---
- hosts: all
tasks:
- name: Install Nginx on Debian
apt: name=nginx state=present
when: ansible_os_family == “Debian” or
Ansible_os_family == “SUSE”
上面的例子在 Debian 或 SUSE 系列操作系统或两者上安装 Nginx Web 服务器。
注意:测试条件时始终确保使用双等号==
。
循环中的条件语句
条件语句也可以在循环中使用。举例来说,您有一个需要在远程节点上安装的多个软件包的列表。
在下面的剧本中,我们有一个名为 packages 的数组,其中包含需要安装的软件包列表。如果required子句设置为True,这些任务将依次执行。
---
- name: Install Software packages
hosts: all
vars:
packages:
• name: nginx
required: True
• name: mysql
required: True
• name: apache
required: False
tasks:
• name: Install “{{ item.name }}”on Debian
apt:
name: “{{ item.name }}”
state: present
When: item.required == True
loop: “{{ packages }}”
配置错误处理
有时,运行 playbook 时任务会失败。假设您在 3 台服务器上运行 5 个任务,如下面的剧本所示。如果服务器 2 上的任务 3(启动 MySQL)发生错误,Ansible 将停止执行服务器 2 上的剩余任务,并尝试在其余服务器上完成剩余任务。
---
- name: Install Software packages
hosts: server1, server2, server3
tasks:
- name: Install dependencies
<< some code >>
- name: Install MySQL database
<< some code >>
- name: Start MySQL
<< some code >>
- name: Install Nginx
<< some code >>
- name: Start Nginx
<< some code >>
例如,如果您希望 playbook 的执行保持一致,则在其中一台服务器出现故障时停止 playbook 的执行,请添加该选项。
---
- name: Install Software packages
hosts: server1, server2, server3
any_errors_fatal: true
tasks:
这样,如果一台服务器上的一项任务失败,Ansible 将停止所有服务器上整个 playbook 的执行并退出。
如果您希望 playbook 忽略错误并继续执行剩余的任务集,请使用 ignore_errors: True 选项。
---
- name: Install Software packages
hosts: server1, server2, server3
tasks:
- name: Install dependencies
<< some code >>
ignore_errors: True
创建 Playbook 以将系统配置为指定状态
在本节中,我们将了解运行 playbook 时可用的一些其他选项。
让我们从检查模式或试运行选项开始。运行 playbook 时使用试运行或检查模式选项来检查是否会遇到任何错误以及是否会对托管主机进行任何更改。但是,它不会对远程节点进行任何更改。
例如,要试运行一个名为 httpd.yml
的 playbook,它会安装并启动 Apache Web 服务器,请运行:
ansible-playbook httpd.yml --check
我们需要查看的另一个选项是 --start-at-task
选项。在指定 playbook 应开始或开始的任务名称时使用。
让我们举个例子:下面的 playbook 列出了 2 个任务:第一个 play 安装 Apache Web 服务器,第二个 play 安装 htop 实用程序。
---
- name: Install httpd
hosts: all
tasks:
yum:
name: httpd
state: Installed
- name: Install htop
yum:
name: htop
state: started
如果您想跳过安装 Apache Web 服务器并安装 htop 实用程序,请运行:
ansible-playbook playbook.yml --start-at-task “Install htop”
最后,您可以通过将标签选项添加到您的剧本中来标记您的任务或剧本,如图所示。当您有相当大的剧本并且您想要运行整个剧本中的特定任务时,这会派上用场。
---
- name: Install httpd
tags: Install and start
hosts: all
tasks:
yum:
name: httpd
state: Installed
tags: Install
• service:
name: httpd
state: started
ansible-playbook playbook.yml -tags "Install"
要省略标签,请使用 --skip-tags
选项,如图所示。
ansible-playbook playbook.yml --skip-tags "Install"
结论
在本主题中,我们带您了解了 Ansible 中的常用模块、如何从 playbook 的执行中检索 stdout 进行分析、使用 playbook 中的条件以及如何管理运行时可能发生的错误任务。最后,我们回顾了 playbook 的配置,以及如果您不打算运行整个 playbook,如何使用其他选项来决定运行哪些任务。