用于 Linux 系统自动化的 10 个 Ansible 模块

这些方便的模块通过自动化您的许多日常任务来节省时间和麻烦,并且只需几个命令即可轻松实现。
268 位读者喜欢这篇文章。
gears and lightbulb to represent innovation

Opensource.com

Ansible 是适用于您 IT 环境的完整自动化解决方案。您可以使用 Ansible 自动化 Linux 和 Windows 服务器配置、编排服务配置、部署云环境,甚至配置您的网络设备。

Ansible 模块抽象了系统上的操作,因此您无需担心实现细节。您只需描述所需的状态,Ansible 即可确保目标系统与之匹配。

模块的可用性是 Ansible 的主要优势之一,它通常被称为 Ansible “内置电池”。 实际上,您可以找到大量任务的模块,虽然这很棒,但我经常听到初学者说他们不知道从哪里开始。

虽然您对模块的选择将完全取决于您的需求以及您尝试使用 Ansible 自动化的内容,但以下是您开始使用 Ansible 进行 Linux 系统自动化所需的十大模块。

1. copy

copy 模块允许您将文件从 Ansible 控制节点复制到目标主机。 除了复制文件外,它还允许您为目标文件设置所有权、权限和 SELinux 标签。 这是一个使用 copy 模块将“每日消息”配置文件复制到目标主机的示例

- name: Ensure MOTD file is in place
  copy:
    src: files/motd
    dest: /etc/motd
    owner: root
    group: root
    mode: 0644

对于不太复杂的内容,您可以将内容直接复制到目标文件,而无需本地文件,就像这样

- name: Ensure MOTD file is in place
  copy:
    content: "Welcome to this system."
    dest: /etc/motd
    owner: root
    group: root
    mode: 0644

此模块以 幂等方式工作,这意味着它仅在具有相同内容和权限的相同文件尚未就位时才复制文件。

copy 模块是复制少量具有静态内容文件的绝佳选择。 如果您需要复制大量文件,请查看 synchronize 模块。 要复制具有动态内容的文件,请接下来查看 template 模块。

2. template

template 模块的工作方式与 copy 模块类似,但它在使用 Jinja2 模板语言动态处理内容后,再将其复制到目标主机。

例如,定义一个“每日消息”模板,用于显示目标系统名称,就像这样

$ vi templates/motd.j2
Welcome to {{ inventory_hostname }}.

然后,使用 template 模块实例化此模板,就像这样

- name: Ensure MOTD file is in place
  template:
    src: templates/motd.j2
    dest: /etc/motd
    owner: root
    group: root
    mode: 0644

在复制文件之前,Ansible 会处理模板并插值变量,将其替换为目标主机系统名称。 例如,如果目标系统名称是 rh8-vm03,则结果文件为

Welcome to rh8-vm03.

虽然 copy 模块在使用 content 参数时也可以插值变量,但 template 模块通过创建模板文件提供了额外的灵活性,使您能够定义更复杂的内容,包括 for 循环、if 条件等等。 有关完整参考,请查看 Jinja2 文档

此模块也是幂等的,如果目标系统上的内容已与模板的内容匹配,则它不会复制文件。

3. user

user 模块允许您在目标系统中创建和管理 Linux 用户。 此模块有许多不同的参数,但在其最基本的形式中,您可以使用它来创建新用户。

例如,要创建 UID 为 2001、属于 groups 和 wheel 组且密码为 mypassword 的用户 ricardo,请使用以下参数应用 user 模块

- name: Ensure user ricardo exists
  user:
    name: ricardo
    group: users
    groups: wheel
    uid: 2001
    password: "{{ 'mypassword' | password_hash('sha512') }}" 
    state: present

请注意,此模块尝试是幂等的,但它不能保证其所有选项都如此。 例如,如果您再次执行之前的模块示例,它会将密码重置为定义的值,从而在每次执行时都更改系统中的用户。 为了使此示例是幂等的,请使用参数 update_password: on_create,确保 Ansible 仅在创建用户时设置密码,而不是在后续运行时设置密码。

您还可以使用此模块通过设置参数 state: absent 来删除用户。

user 模块有许多选项供您管理多个用户方面。 请务必查看模块文档以获取更多信息。

4. package

package 模块允许您使用操作系统标准包管理器从目标系统中安装、更新或删除软件包。

例如,要在 Red Hat Linux 机器上安装 Apache Web 服务器,请像这样应用模块

- name: Ensure Apache package is installed
  package:
    name: httpd
    state: present

 

此模块与发行版无关,它通过使用底层包管理器工作,例如 Red Hat 发行版的 yum/dnf 和 Debian 的 apt。 因此,它只执行安装和删除软件包等基本任务。 如果您需要更多地控制包管理器选项,请使用目标发行版的特定模块。

 

另外,请记住,即使模块本身可以在不同的发行版上工作,但每个发行版的软件包名称可能不同。 例如,在基于 Red Hat 的发行版中,Apache Web 服务器软件包名称是 httpd,而在 Debian 中,它是 apache2。 确保您的 playbook 处理好这一点。

此模块是幂等的,如果当前系统状态与所需状态匹配,则它不会执行任何操作。

[ 提升您的自动化专业知识。 获取 Ansible 清单: 迁移到 Red Hat Ansible Automation Platform 2 的 5 个理由 ]

5. service

使用 service 模块通过所需的 init 系统来管理目标系统服务;例如,systemd

在其最基本的形式中,您只需提供服务名称和所需的状态。 例如,要启动 sshd 服务,请像这样使用模块

- name: Ensure SSHD is started
  service:
    name: sshd
    state: started

您还可以通过提供参数 enabled: yes 来确保服务在目标系统启动时自动启动。

package 模块一样,service 模块也很灵活,并且可以在不同的发行版上工作。 如果您需要对特定目标 init 系统进行微调,请使用相应的模块;例如,systemd 模块。

与您目前看到的其他模块类似,service 模块也是幂等的。

6. firewalld

在支持 firewalld 守护程序的系统(例如基于 Red Hat 的发行版)上,使用 firewalld 模块来控制系统防火墙。

例如,要在端口 80 上打开 HTTP 服务,请像这样使用它

- name: Ensure port 80 (http) is open
  firewalld:
    service: http
    state: enabled
    permanent: yes
    immediate: yes

您还可以使用 port 参数指定自定义端口而不是服务名称。 在这种情况下,请确保也指定协议。 例如,要打开 TCP 端口 3000,请使用此方法

- name: Ensure port 3000/TCP is open
  firewalld:
    port: 3000/tcp
    state: enabled
    permanent: yes
    immediate: yes

您还可以使用此模块来控制 firewalld 的其他方面,例如区域或复杂规则。 请务必查看模块的文档以获取选项的完整列表。

7. file

file 模块允许您控制文件和目录的状态——设置权限、所有权和 SELinux 标签。

例如,使用 file 模块创建一个由用户 ricardo 拥有的目录 /app,所有者和组 users 具有读取、写入和执行权限

- name: Ensure directory /app exists
  file:
    path: /app
    state: directory
    owner: ricardo
    group: users
    mode: 0770

您还可以使用此模块通过使用参数 recurse: yes 递归地设置目录上的文件属性,或使用参数 state: absent 删除文件和目录。

此模块对于其大多数参数都以幂等方式工作,但其中一些参数可能会使其每次都更改目标路径。 请查看文档以获取更多详细信息。

8. lineinfile

lineinfile 模块允许您管理现有文件中的单行。 它对于更新现有文件上的目标配置非常有用,而无需更改文件的其余部分或复制整个配置文件。

例如,像这样在您的 hosts 文件中添加一个新条目

- name: Ensure host rh8-vm03 in hosts file
  lineinfile:
    path: /etc/hosts
    line: 192.168.122.236 rh8-vm03
    state: present

您还可以使用此模块通过应用参数 regexp 来查找要替换的现有行来更改现有行。 例如,更新 sshd_config 文件以防止 root 登录,方法是将 PermitRootLogin yes 行修改为 PermitRootLogin no

- name: Ensure root cannot login via ssh
  lineinfile:
    path: /etc/ssh/sshd_config
    regexp: '^PermitRootLogin'
    line: PermitRootLogin no
    state: present

注意:使用 service 模块重新启动 SSHD 服务以启用此更改。

此模块也是幂等的,但是,在行修改的情况下,请确保正则表达式与原始状态和更新状态都匹配,以避免不必要的更改。

9. unarchive

使用 unarchive 模块提取存档文件的内容,例如 tar 或 zip 文件。 默认情况下,它会在提取存档文件之前将其从控制节点复制到目标计算机。 通过提供参数 remote_src: yes 来更改此行为。

例如,使用以下语法提取已下载到目标主机的 .tar.gz 文件的内容

- name: Extract contents of app.tar.gz
  unarchive:
    src: /tmp/app.tar.gz
    dest: /app
    remote_src: yes

某些存档技术需要目标系统上提供额外的软件包;例如,用于提取 .zip 文件的 unzip 软件包。

根据使用的存档格式,此模块可能以幂等方式工作,也可能不以幂等方式工作。 为了防止不必要的更改,您可以使用参数 creates 来指定此模块在提取存档内容时将创建的文件或目录。 如果此文件或目录已存在,则该模块不会再次提取内容。

10. command

command 模块是一个灵活的模块,它允许您在目标系统上执行任意命令。 使用此模块,只要有命令,您几乎可以在目标系统上执行任何操作。

即使 command 模块灵活而强大,也应谨慎使用。 如果有其他合适的模块可用,请避免使用 command 模块来执行任务。 例如,您可以使用 command 模块来执行 useradd 命令来创建用户,但您应该改用 user 模块,因为它为您抽象了很多细节,处理了边缘情况并确保配置仅在必要时才更改。

对于没有模块可用或运行自定义脚本或程序的情况,command 模块仍然是一个很好的资源。 例如,使用此模块运行已存在于目标计算机中的脚本

- name: Run the app installer
  command: "/app/install.sh"

默认情况下,此模块不是幂等的,因为 Ansible 每次都会执行该命令。 为了使 command 模块是幂等的,您可以像 unarchive 模块示例一样,使用 when 条件仅在存在适当条件时才执行该命令,或者使用 creates 参数。

下一步是什么?

使用这些模块,您可以通过复制、模板化或修改配置文件、创建用户、安装软件包、启动系统服务、更新防火墙等来配置整个 Linux 系统。

如果您是 Ansible 的新手,请务必查看有关如何创建 playbook 以组合这些模块来自动化您的系统的文档。 其中一些任务需要以提升的权限运行才能工作。 有关更多详细信息,请查看 权限提升文档。

从 Ansible 2.10 开始,模块组织在集合中。 此列表中的大多数模块都是 ansible.builtin 集合的一部分,并且默认情况下可与 Ansible 一起使用,但其中一些模块是其他集合的一部分。 有关集合的列表,请查看 Ansible 文档

接下来阅读什么
Avatar
Ricardo Gerardi 是 Enable Sysadmin 和 Enable Architect 的技术社区倡导者。 他之前曾担任 Red Hat Canada 的首席顾问,在那里他专注于使用 Ansible 和 OpenShift 进行 IT 自动化。

3 条评论

您对处理跨多个操作系统的正确软件包名称有什么建议?

嘿 Ben。 很好的问题。 谢谢。
我通常创建一个变量来表示要安装的软件包列表,例如“package_list”,并在特定于操作系统的 var 文件中定义它,例如“RedHat.yaml”或“Debian.yaml”。
然后,您可以使用以下语法根据作为 Ansible 事实检索到的操作系统系列在您的 playbook/角色中包含 vars 文件:“{{ ansible_os_family }}.yaml”。
这样,您就可以为每个发行版拥有不同的“package_list”版本。 如果同一发行版的多个版本之间的软件包名称不同,您甚至可以在文件名中包含操作系统版本。

回复 (来自 bcotton)

嘿 Ben。 很好的问题。 谢谢。
我通常创建一个变量来表示要安装的软件包列表,例如“package_list”,并在特定于操作系统的 var 文件中定义它,例如“RedHat.yaml”或“Debian.yaml”。
然后,您可以使用以下语法根据作为 Ansible 事实检索到的操作系统系列在您的 playbook/角色中包含 vars 文件:“{{ ansible_os_family }}.yaml”。
这样,您就可以为每个发行版拥有不同的“package_list”版本。 如果同一发行版的多个版本之间的软件包名称不同,您甚至可以在文件名中包含操作系统版本。

知识共享许可协议本作品根据知识共享署名-相同方式共享 4.0 国际许可协议获得许可。
© . All rights reserved.