使用 Ansible 管理您的工作站:自动化配置

了解如何使 Ansible 自动将配置更改应用到一批笔记本电脑和台式机。
360 位读者喜欢这篇文章。
Manage your workstation with Ansible: Automating configuration

Opensource.com

Ansible 是一款出色的自动化和配置管理工具。它主要用于服务器和云部署,但在工作站(包括台式机和笔记本电脑)中的应用却鲜为人知,而这正是本系列文章的重点。

在本系列文章的第一部分中,我向您展示了 ansible-pull 命令的基本用法,并且我们创建了一个 playbook 来安装少量软件包。这本身并不是非常有用,但它为进一步自动化奠定了基础。

在本文中,一切都将水到渠成,到最后我们将拥有一个完全可用的解决方案,用于自动化工作站配置。这一次,我们将设置 Ansible 配置,以便我们将来所做的更改将自动应用到我们的工作站。此时,我假设您已经完成了第一部分。如果您还没有完成,请随时先完成第一部分,然后在完成后返回本文。您应该已经有一个 GitHub 仓库,其中包含第一篇文章中的代码。我们将直接在我们之前所做的基础上构建。

首先,我们需要进行一些重组,因为我们将做的不只是安装软件包。目前,我们有一个名为 local.yml 的 playbook,内容如下

- hosts: localhost
  become: true
  tasks:
  - name: Install packages
    apt: name={{item}}
    with_items:
      - htop
      - mc
      - tmux

如果我们只想执行一项任务,这当然很好。但是,随着我们向配置中添加新内容,这个文件将变得非常大且非常混乱。最好将我们的 play 组织成单独的文件,每个文件负责不同类型的配置。为了实现这一点,请创建一个所谓的 taskbook,它非常像 playbook,但内容更精简。让我们在 Git 仓库中创建一个目录来存放 taskbook

mkdir tasks

当前 local.yml playbook 中的代码非常适合成为安装软件包的 taskbook。让我们将此文件移动到我们刚刚创建的 tasks 目录中,并使用新名称

mv local.yml tasks/packages.yml

现在,我们可以编辑我们的 packages.yml taskbook 并对其进行大幅精简。实际上,我们可以删除除单个任务本身之外的所有内容。让我们使 packages.yml 看起来像这样

- name: Install packages
  apt: name={{item}}
  with_items:
    - htop
    - mc
    - tmux

如您所见,它使用相同的语法,但我们删除了与它执行的任务无关的所有内容。现在我们有了一个专门用于安装软件包的 taskbook。但是,我们仍然需要一个名为 local.yml 的文件,因为 ansible-pull 仍然希望找到一个具有该名称的文件。因此,我们将在仓库的根目录(而不是在 tasks 目录中)创建一个新的文件,内容如下

- hosts: localhost
  become: true
  pre_tasks:
    - name: update repositories
      apt: update_cache=yes
      changed_when: False

  tasks:
    - include: tasks/packages.yml

这个新的 local.yml 充当索引,它将导入我们所有的 taskbook。我在此文件中添加了一些您在本系列中尚未见过的新内容。首先,在文件开头,我添加了 pre_tasks,这允许我们在所有其他任务运行之前让 Ansible 执行一个任务。在本例中,我们告诉 Ansible 更新我们发行版的仓库索引。这行代码为我们执行此操作

apt: update_cache=yes

通常,apt 模块允许我们安装软件包,但我们也可以告诉它更新我们的仓库索引。我们的想法是,我们希望我们所有的单个 play 每次在 Ansible 运行时都使用新的索引。这将有助于确保我们在尝试安装软件包时不会遇到陈旧索引的问题。请注意,apt 模块仅适用于 Debian、Ubuntu 及其衍生版本。如果您运行的是其他发行版,则需要使用特定于您的发行版的模块,而不是 apt。如果您需要使用其他模块,请参阅 Ansible 的文档。

以下行也值得进一步解释

changed_when: False

单个任务上的这一行阻止 Ansible 将 play 的结果报告为已更改,即使它导致系统发生更改。在本例中,我们不关心仓库索引是否包含新数据;它几乎总是会包含新数据,因为仓库总是不断变化。我们不关心 apt 仓库的更改,因为索引更改是理所当然的。如果我们省略此行,我们将在流程结束时的摘要中看到报告说某些内容已更改,即使它仅仅是关于仓库已更新。最好忽略这些类型的更改。

接下来是我们的常规任务部分,我们导入我们创建的 taskbook。每次我们添加另一个 taskbook 时,我们都会在此处添加另一行

tasks:
  - include: tasks/packages.yml

如果您在此处运行 ansible-pull 命令,它应该基本上执行与上一篇文章中相同的操作。不同之处在于我们改进了组织,并且可以更有效地扩展它。ansible-pull 命令语法,为了避免您查找上一篇文章,是这样的

sudo ansible-pull -U https://github.com/<github_user>/ansible.git

如果您还记得,ansible-pull 命令会拉取 Git 仓库并应用其中包含的配置。

现在我们的基础已经就位,我们可以扩展我们的 Ansible 配置并添加功能。具体来说,我们将添加配置以自动化将来的更改部署到我们的工作站。为了支持这个目标,我们应该做的第一件事是创建一个专门用于应用我们的 Ansible 配置的用户。这不是必需的——我们可以继续在自己的用户下运行我们的 Ansible 配置。但是,使用单独的用户会将其隔离到一个系统进程,该进程将在后台运行,而无需我们的参与。

我们可以使用正常方法创建此用户,但由于我们正在使用 Ansible,因此我们应该避免手动更改。相反,我们将创建一个 taskbook 来处理用户创建。这个 taskbook 现在只创建一个用户,但您可以随时向此 taskbook 添加其他 play 以添加其他用户。我将此用户命名为 ansible,但如果您愿意,可以将其命名为其他名称(如果这样做,请确保更新所有出现的地方)。让我们创建一个名为 users.yml 的 taskbook,并将以下代码放在其中

- name: create ansible user
  user: name=ansible uid=900

接下来,我们需要编辑我们的 local.yml 文件,并将这个新的 taskbook 附加到文件中,使其看起来像这样

- hosts: localhost
  become: true
  pre_tasks:
    - name: update repositories
      apt: update_cache=yes
      changed_when: False

  tasks:
    - include: tasks/users.yml
    - include: tasks/packages.yml

现在,当我们运行 ansible-pull 命令时,将在系统上创建一个名为 ansible 的用户。请注意,我通过使用 UID 选项专门为此用户声明了 User ID 900。这不是必需的,但建议这样做。原因是 UID 小于 1,000 的用户通常不会显示在登录屏幕上,这很好,因为我们没有理由以我们的 ansible 用户身份登录桌面会话。UID 900 是任意的;它应该是任何小于 1,000 且尚未使用的数字。您可以使用以下命令查明 UID 900 是否在您的系统中使用

cat /etc/passwd |grep 900

但是,您不应该遇到此 UID 的问题,因为在我迄今为止使用的任何发行版中,我从未见过默认使用它。

现在,我们有了一个 ansible 用户,稍后将用于自动应用我们的 Ansible 配置。接下来,我们可以创建实际的 cron 作业,该作业将用于自动化此过程。与其将其放在我们刚刚创建的 users.yml taskbook 中,不如将其分离到自己的文件中。在 tasks 目录中创建一个名为 cron.yml 的 taskbook,并将以下代码放在其中

- name: install cron job (ansible-pull)
  cron: user="ansible" name="ansible provision" minute="*/10" job="/usr/bin/ansible-pull -o -U https://github.com/<github_user>/ansible.git > /dev/null"

cron 模块的语法应该是不言自明的。通过此 play,我们正在创建一个 cron 作业,该作业将以 ansible 用户身份运行。该作业将每 10 分钟执行一次,它将执行的命令是

/usr/bin/ansible-pull -o -U https://github.com/<github_user>/ansible.git > /dev/null

此外,我们可以将我们希望所有工作站都拥有的其他 cron 作业放在这个文件中。我们只需要添加额外的 play 来添加新的 cron 作业。但是,仅仅为 cron 添加一个新的 taskbook 是不够的——我们还需要将其添加到我们的 local.yml 文件中,以便调用它。将以下行与其他的 include 放在一起

- include: tasks/cron.yml

现在,当 ansible-pull 运行时,它将设置一个新的 cron 作业,该作业将以 ansible 用户身份每 10 分钟运行一次。但是,每 10 分钟运行 Ansible 作业并不理想,因为它会占用相当多的 CPU 功率。除非我们在 Git 仓库中更改了某些内容,否则 Ansible 每 10 分钟运行一次真的没有意义。

但是,我们已经解决了这个问题。请注意我在 cron 作业中的 ansible-pull 命令中添加的 -o 选项,我们以前从未使用过它。此选项告诉 Ansible 仅在仓库自上次调用 ansible-pull 以来发生更改时才运行。如果仓库没有更改,它将不会执行任何操作。这样,您就不会无缘无故地浪费宝贵的 CPU。当然,在拉取仓库时会使用一些 CPU,但远不及重新应用整个配置所使用的 CPU 多。当 ansible-pull 运行时,它将遍历 Playbook 和 taskbook 中的所有任务,但至少它不会无缘无故地运行。

虽然我们已经添加了自动化 ansible-pull 所需的所有组件,但它实际上还不能正常工作。ansible-pull 命令将使用 sudo 运行,这将使其有权执行系统级命令。但是,我们的 ansible 用户未设置为以 sudo 身份执行任务。因此,当 cron 作业触发时,它将失败。通常,我们可以只使用 visudo 并手动设置 ansible 用户以具有此访问权限。但是,从现在开始,我们应该以 Ansible 的方式做事,这是一个展示 copy 模块如何工作的绝佳机会。copy 模块允许您将文件从 Ansible 仓库复制到文件系统中的其他位置。在我们的例子中,我们将复制一个用于 sudo 的配置文件到 /etc/sudoers.d/,以便 ansible 用户可以执行管理任务。

打开 users.yml taskbook,并将以下 play 添加到底部

- name: copy sudoers_ansible
  copy: src=files/sudoers_ansible dest=/etc/sudoers.d/ansible owner=root group=root mode=0440

正如我们所见,copy 模块将文件从我们的仓库复制到其他位置。在本例中,我们正在获取一个名为 sudoers_ansible 的文件(我们稍后将创建它),并将其复制到 /etc/sudoers.d/ansible,所有者为 root

接下来,我们需要创建我们将要复制的文件。在您的 Ansible 仓库的根目录中,创建一个 files 目录

mkdir files

然后,在我们刚刚创建的 files 目录中,创建 sudoers_ansible 文件,内容如下

ansible ALL=(ALL) NOPASSWD: ALL

像我们在这里所做的那样,在 /etc/sudoers.d 中创建一个文件,允许我们为特定用户配置 sudo。在这里,我们允许 ansible 用户通过 sudo 完全访问系统,而无需密码提示。这将允许 ansible-pull 作为后台任务运行,而无需我们手动运行它。

现在,您可以再次运行 ansible-pull 以拉取最新的更改

sudo ansible-pull -U https://github.com/<github_user>/ansible.git

从现在开始,ansible-pull 的 cron 作业将每 10 分钟在后台运行,并检查您的仓库是否有更改。如果它发现更改,它将运行您的 playbook 并应用您的 taskbook。

所以现在我们有了一个完全可用的解决方案。当您第一次设置新的笔记本电脑或台式机时,您将手动运行 ansible-pull 命令,但仅在第一次运行。从那时起,ansible 用户将负责在后台进行后续运行。当您想要更改工作站机器时,您只需拉取您的 Git 仓库,进行更改,然后将这些更改推送回仓库。然后,下次 cron 作业在每台机器上触发时,它将拉取这些更改并应用它们。您现在只需更改一次,所有工作站都将效仿。不过,这种方法可能有点非常规。通常,您会有一个 inventory 文件,其中列出了您的机器以及每台机器可以成为成员的多个角色。但是,如本文所述,ansible-pull 方法是一种非常有效的工作站配置管理方法。

我已经更新了 我的 GitLab 仓库 中本文的代码,因此请随时浏览那里的代码,并将您的语法与我的语法进行比较。此外,我已将上一篇文章中的代码移动到该仓库中的其自己的目录中。

在第 3 部分中,我们将通过使用 Ansible 配置 GNOME 桌面设置来结束本系列。我将向您展示如何设置壁纸和锁屏、应用桌面主题等等。

与此同时,现在是布置一点家庭作业的时候了。我们大多数人都有我们喜欢维护的各种应用程序的配置文件。这可能是 Bash、Vim 或您使用的任何工具的配置文件。我现在向您挑战,通过我们一直在使用的 Ansible 仓库,自动化将这些配置文件复制到您的机器。在本文中,我已经向您展示了如何复制文件,因此请查看一下,看看您是否可以将该知识应用于您的个人文件。

标签
User profile image.
Jay LaCroix 是一位来自密歇根州的技术专家,专注于 Linux 和开源软件。自 2002 年以来一直使用 Linux,Jay 从那时起就一直是 Linux 的忠实粉丝。他目前是一名高级解决方案架构师和自由顾问,并且喜欢培训和授权他人使用 Linux 并充分利用这款出色的软件。

2 条评论

你好,

非常感谢这个系列的文章。我一直在寻找类似的东西。不能说这篇文章教会了我任何东西,因为我已经查看了您仓库中的代码,但我意识到一些我以前没有注意到的部分,例如 -o 选项。

我一直在查看其他人的解决方案,其中一些人使用了角色。您能谈谈角色吗?如果您能在您的书签中分享一个更详细的(最终)仓库,以便我可以从中获取一些想法,那就太好了。自从第一篇文章以来,我一直在等待重新安装我的工作站!

干杯,
David

如果 ansible 用户可以使用 sudo 成为 root 用户并执行 root 用户可以执行的所有操作,为什么还要使用 ansible 用户而不是 root 用户?

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