使用Docker容器在Ansible控制器/目标上进行构建

初次见面。我是食べログ的 DevOps / 数据科学团队的爲岡(ためおか)。
我在Twitter和GitHub上通常使用账号@zettaittenani进行活动。
无关紧要,我目前还没有遇到过重名的情况。

本次我们专注于DevOps,讲述使用Docker构建Ansible执行环境的故事。

背景

我们在搭建食べログ的开发环境时使用了Ansible,但由于各种原因,出现了整理用于搭建开发环境的Ansible playbook的任务。
Ansible基本上是保证幂等性的,但像command模块等则不是这样,编写新的为新开发环境设计的Ansible playbook时,要意识到是否保证了幂等性,这是一项费力的工作。
因此,我们讨论了构建符合下述要求的测试环境的问题。

    1. 如果正在开发中的playbook存在错误,并因此导致无法保证幂等性,那么可以轻松地启动一个新的环境作为playbook的执行对象。

 

    可以轻松地验证第一次对全新环境执行playbook的结果。

在此,我們可以使用 Docker 容器建立一個用於驗證的 Ansible 目標環境,如果環境損毀了,只需要重新建立容器,就能滿足上述兩個要求,這樣是不是很方便呢?由於我不想弄髒我的本地環境,所以我們可以利用 Docker 一次性建立 Ansible 控制器,這就是本次的討論內容。

2019年3月13日追记
此内容已公开在GitHub代码库(ansible_tester)中,
若您不想复制粘贴,请务必使用。

前提 – tí

确认主机上已经安装了Docker,如果没有则进行安装。

$ docker -v
Docker version 18.09.0, ...

控制器建构 zhì qì

Ansible在通过ssh进行执行,但official提供的全新centos未安装openssh-server和openssh-clients,因此需要准备以下类似的Dockerfile。

为控制器,准备了一个基于 CentOS 的映像,其中安装了 openssh-clients。据说,如果主机是 CentOS,则可以从 EPEL 仓库中安装 Ansible,但官方建议使用 pip 进行安装,因此我们选择了后者。

2018/12/14(星期五)附注:
由于Dockerfile的最后缺少了CMD /sbin/init,已进行修正。
@ikemo先生,非常感谢您mm。

FROM centos:7.5.1804
MAINTAINER "zettaittenani"

# infra settings
RUN yum check
RUN yum -y update
RUN yum -y install openssh-clients

# application settings
RUN curl -L https://bootstrap.pypa.io/get-pip.py | python
RUN pip install ansible

CMD /sbin/init

目标:建构

为目标准备了一个基于CentOS的映像,其中安装了openssh-server。这次的目的是验证在开发环境中执行playbook,因此将UsePAM设置为no,并允许root登录。另外,通过使用EXPOSE 22来配置接受来自控制器的ssh访问。

FROM centos:7.5.1804
MAINTAINER "zettaittenani"

# infra settings
RUN yum check
RUN yum -y update
RUN yum -y install openssh-server
RUN sed -ri 's/^#PermitEmptyPasswords no/PermitEmptyPasswords yes/' /etc/ssh/sshd_config
RUN sed -ri 's/^#PermitRootLogin yes/PermitRootLogin yes/' /etc/ssh/sshd_config
RUN sed -ri 's/^UsePAM yes/UsePAM no/' /etc/ssh/sshd_config
RUN passwd -d root

# start sshd when booting
RUN /bin/systemctl enable sshd
EXPOSE 22

CMD /sbin/init

将其汇总到docker-compose中

为了一次性完成从两个镜像的构建到容器启动的过程,
我们将准备一个用于此目的的docker-compose.yml文件。

首先,准备一个简单的用于执行测试的Ansible playbook。
关于hosts,docker-compose在启动容器时会自动为我们设置解析名称,所以我们只需要简单地写下target即可。
真是太方便了…。

[managed_node]
target
---
- name: Test
  hosts: managed_node
  user: root

  tasks:
    - name: Hello
      shell: date >> now.txt

接下来, 准备下面的docker-compose.yml文件, 并将这个Ansible playbook挂载到控制器上进行设置。

version: '3'

services:
  controller:
    build: ./controller
    privileged: true
    volumes:
      - "./ansible_dir:/ansible"
  target:
    build: ./target
    privileged: true

启动容器

在主机上运行下面的命令来启动 Docker 容器。

$ pwd
/some_dir
$ docker-compose up -d --build

只需要一个选项:现在,controller和target容器都应该已经启动。
我们可以从不同的shell中使用docker-compose命令来验证每个容器是否已启动。

# @shell 1 (controller 用)
$ docker-compose exec controller /bin/bash
$ [root@xxxxxxxxxxxx ~]#

# @shell 2 (target 用)
$ docker-compose exec target /bin/bash
$ [root@xxxxxxxxxxxx ~]#

请确认连通性。

由于容器已经准备好了,所以最后需要进行连通性确认。
将控制器容器中的playbook测试运行到目标容器上。

# @shell 1 (controller 用)
[root@xxxxxxxxxxxx ~]# cd ansible
[root@xxxxxxxxxxxx ~]# ansible-playbook -k ./setup.yml -vvv -i ./hosts
...

PLAY RECAP *********************************************************************************************************************************************************************************************************************************************************************
xxx.xxx.xxx.xxx               : ok=2    changed=1    unreachable=0    failed=0

我已经成功执行了。
接下来,我会在目标Docker容器中检查测试结果。

# @shell 2 (target 用)
[root@xxxxxxxxxxxx ~]# cat now.txt
xxxx年 xx月 xx日 x曜日 xx時xx分xx秒 JST

是的,确实可以从控制器执行playbook到目标。

由于playbook本身已经被装载,所以您可以在本地主机的shell上进行编辑或其他操作,执行时只需在控制器容器中使用ansible-playbook命令即可。
执行结果可以在目标容器上进行确认,如果目标容器出现问题,只需执行docker-compose down/up即可。
这真是一个非常幸福的环境,不是吗?

非常感谢您阅读到最后。
愿你的Ansible生活幸福快乐!!

广告
将在 10 秒后关闭
bannerAds