使用 Docker 和 Travis CI 对 Ansible 角色进行持续测试

分享此内容
分享此内容

Ansible 和 Docker

Ansible 是 IT 自动化的行业标准之一,而这种自动化是现代化和数字化转型的核心组成部分。今天,我们将了解如何使用 Travis CI 和 Docker 自动执行此测试。

借助 Ansible,我们可以以非常简单的方式自动执行基础设施的供应、设置和配置的几乎所有方面。

但测试 Ansible 并不那么容易。在 Ansible 中,我们可以使用角色来开发通用功能并鼓励可重用性。

有一个中央仓库,即 Ansible Galaxy,用于与其他开发者共享角色。这个中央仓库与 GitHub 完全集成,因此您可以找到许多现成的角色,可以随时使用和分叉。

这些角色可能同时针对许多 Linux 发行版,为多个平台提供通用功能。

通常,当开发者创建新角色时,他们倾向于花大量时间在全新基础设施上对其进行测试。

例如,要测试在任何 Linux 发行版中安装新数据库的角色,我们可能需要为每个发行版启动一个新的虚拟机,每次我们想要测试它时,然后运行 Ansible,检查它,删除它并从头开始。我们可以使用 VM 快照,但它仍然是一个非常缓慢且资源密集型的开发过程。

另一种方法是使用 Docker。与 VM 相比,我们可以每次想要测试角色时启动一个新的容器。每个容器都将基于我们想要支持的每个 Linux 发行版。尽管效率很高,但这将要求我们运行许多步骤才能完成一次测试。

如果我们将这个过程自动化到我们的持续集成管道中会怎么样?这正是下面要解释的方法。

使用 Travis 进行 Ansible CI

在 Travis CI 中,您可以创建一个 CI 管道,您可以在其中同时为单个构建并行运行多个阶段。

当为支持多个平台的 Ansible 角色建模持续测试管道时,此功能非常有用。鉴于我们希望通过 Galaxy 和 GitHub 共享我们的角色,它也很方便。

我已经准备了一个非常基本的演示角色,它在不同的 Linux 发行版上安装 Nginx。它非常简单,我们将重点关注 Travis 部分。您可以在 GitHub 上找到演示角色:https://github.com/drhelius/travis-ansible-demo

要在 Travis 构建中运行 Docker,我们将按照 在构建中使用 Docker 的文档,并在 .travis.yml 文件中相应地设置它。

sudo: required

services:
  - docker

现在,我们将为每个 Linux 发行版创建并行作业,创建一个 构建矩阵,如下所示

env:
  - distribution: centos
    version: 7
  - distribution: fedora
    version: 26
  - distribution: fedora
    version: 25
  - distribution: fedora
    version: 24
  - distribution: ubuntu
    version: xenial
  - distribution: ubuntu
    version: trusty
  - distribution: debian
    version: stretch
  - distribution: debian
    version: jessie

构建将分成 8 个作业,我们将使用这里为每个作业定义的环境变量来配置每个发行版的测试。

To have full control of the specs, we’ll extend the base Docker images in their corresponding Dockerfiles. This way, we can run Ansible, systemd and any other tools you may need when testing your role. You can find my customizations for Ubuntu, Debian, Fedora, … in the travis folder, inside the repository. We’ll use these images based on the official ones.

Back in our .travis.yml file, the first thing is pulling the base image and building our customized version of it:
before_install:
  - 'sudo docker pull ${distribution}:${version}'
  - 'sudo docker build --no-cache --rm --file=travis/Dockerfile.${distribution}-${version} --tag=${distribution}-${version}:ansible travis'

其中 ${distribution}${version} 是我们在构建矩阵中定义的不同环境变量。在此之后,我们可以从此映像创建一个新容器并让它运行。为此,我们将容器的 ID 存储在一个 ${container_id} 环境变量中,以便在随后的命令中使用它。

script:
  - container_id=$(mktemp)
  - 'sudo docker run --detach --privileged -v /sys/fs/cgroup:/sys/fs/cgroup:ro --volume="${PWD}":/etc/ansible/roles/nginx_role:ro ${distribution}-${version}:ansible > "${container_id}"'

此时,我们的容器已在 Travis CI 构建中启动并运行,我们将在此容器中运行 Ansible,通过使用为测试目的创建的通用剧本 test.yml 来测试我们的角色。

我们首先检查语法

 - 'sudo docker exec "$(cat ${container_id})" env ANSIBLE_FORCE_COLOR=1 ansible-playbook -v /etc/ansible/roles/nginx_role/travis/test.yml --syntax-check'

然后继续运行实际的角色

  - 'sudo docker exec "$(cat ${container_id})" env ANSIBLE_FORCE_COLOR=1 ansible-playbook -v /etc/ansible/roles/nginx_role/travis/test.yml'

两次运行它非常方便,这样您可以检测到角色的幂等性方面的错误。

 - >
    sudo docker exec "$(cat ${container_id})" env ANSIBLE_FORCE_COLOR=1 ansible-playbook -v /etc/ansible/roles/nginx_role/travis/test.yml
    | grep -q 'changed=0.*failed=0'
    && (echo 'Idempotence test: pass' && exit 0)
    || (echo 'Idempotence test: fail' && exit 1)

然后,我们可以停止容器并完成我们的构建,此时一切应该正常。

  - 'sudo docker rm -f "$(cat ${container_id})"'

现在,每次我们进行推送或创建新的 PR 时,此过程将触发并将在我们矩阵中指定的 8 个平台上测试我们的角色,只需几分钟。

您可以查看 我在这里使用的完整 .travis.yml 文件

关于作者

Ignacio Sánchez,@drhelius 在西班牙的 atSistemas 担任 DevOps 技术主管,帮助客户实现整个开发生命周期的自动化,实施 CI/CD 管道和开发基础设施即代码。这篇文章也会在西班牙的 enmilocalfunciona.io 上发布,即 atSistemas 的技术博客。

© 版权所有 2024 年,保留所有权利
© 版权所有 2024 年,保留所有权利
© 版权所有 2024 年,保留所有权利