使用Ansible的角色来组织低容量、定制化的镜像

47次阅读
没有评论

问题描述

希望使用Ansible来创建和维护一些虚拟机,并根据特定需求将其打包并部署给成千上万的用户。每个人都在做大致相同的工作,但不同的人需要不同的工具。用户不确定是否可以围绕角色来组织结构(尽管他愿意接受错误的指导)。

目前,用户的结构如下:

vagrant-directory
|-Vagrantfile # 多主机设置,每个“用例”一个机器
|-scripts/ # Vagrant运行的Shell脚本(主要用于安装Ansible的先决条件)
|-ansible/ # 所有与Ansible相关的文件
|----Playbook1.yml # 每个用例一个Playbook
|----tasks/ # 包含我想要执行的所有任务文件
|------install/ # 所有与安装软件相关的任务文件
|------apt-update.yml # 例如,运行apt update的脚本
|------iptables-flush.yml # 禁用iptables

使用这种方法,当用户需要一个新的机器时,他必须创建一个新的Playbook,使用import_tasks导入所需的任务,创建任何特定于机器的任务,然后进行配置和导出。

是否有更“官方的”或行业标准的方法来做到这一点?

解决方案

请注意以下操作注意版本差异及修改前做好备份。

方案1

在这种情况下,您确实需要使用Ansible的角色。我将使用真实世界的示例来说明我的观点。下面的代码只是为了说明我的观点(因此它不是完全可运行的,可能包含错误,并且不是强大的科学:您可能需要适应/克服工具的限制)。但至少您将能够告诉我是否理解错误。

假设您为不同的技术/工具(如java、php、nodejs、scala、python、ruby)的开发人员提供服务,并且还需要一些工具,如apache、nginx、postgres、mysql、redis等。

您为每个技术/工具创建一个角色,并可能使用来自Ansible Galaxy的现有角色,您甚至不必编写这些角色,可以在部署时下载。这些角色可以使用变量来控制,以选择版本(请参阅下面的vagrant provisionner配置)。

现在,您可以使用标签在play中激活/停用角色。

您的唯一Playbook可能如下所示:

- name: Vagrant provisionning playbook
  hosts: all
  pre_tasks:
    # 在角色之前执行的任何操作
  roles:
    - role: php
      tags: [php]
    - role: java
      tags: [java]
    - role: nginx
      tags: [nginx,php] # 如果您始终使用nginx部署php
    - role: redis
      tags: [redis]
    # 更多角色在这里
  tasks:
    # 在角色之后需要执行的任务

有了这样的结构,您现在可以在Vagrant中配置Ansible provisioner,定义标签并指定用于使用单个Playbook进行部署所需的变量。

Vagrant.configure(2) do |config|
  config.vm define "php_application" do |php_application|
    # 一些虚拟机配置
    php_application.vm.provision "ansible" do |ansible|
       ansible.playbook = "playbook.yml"
      ansible.tags = "php,nginx,untagged"
    end
  end
  # 全局声明主机变量。您可能能够在每个主机上进行声明,但文档没有指定
  config.vm.provision "ansible" do |ansible|
    ansible.host_vars = {
      "php_application" => {"php_version" => "7.2"}
    }
  end
end

这符合您的需求吗?

  1. 每个应用程序的角色似乎有点重量级,不是吗?我认为我可以通过包含任务文件来实现您建议的相同效果。所以,与PHP角色、标签和Playbook相比,我只有一个单独的PHP任务文件,在主Playbook中使用import_tasks: tasks/install/php-7.2.yml。这样做是否可以以更少的间接性实现相同的可重用性?
  2. 这是您的选择。角色在项目中更具可重用性,可以在其自己的存储库中进行版本控制,并且可以包含正确打包的文件、模板、处理程序、默认变量、文档等。它们可以通过继承自其他角色的自定义角色轻松扩展。
  3. 太晚了,无法编辑我的上一个评论…您应该阅读“unit”而不是“unity”。
  4. 好的,所以如果我正确理解您的方法,与其为每个应用程序(“php-7.2.yml”)创建一个任务文件,我将为每个应用程序创建一个角色目录。然后,我的主Playbook将指定所有这些角色,并且我将在Vagrant中使用标签来指定特定用例中要包含的角色?优势是我可以创建更可重用的应用程序包,而不仅仅将它们定义为任务文件。我理解得对吗?
  5. 是的,至少是我个人的观点。角色是Ansible中可重用性的基础。您在第一个评论中问的是每个应用程序的角色是否太重了:在日常实践中,我可以为单个应用程序使用多个角色。只是为了说明:我在十几个服务器上部署nexus存储库。我使用一个开源角色(我恰好是维护者)部署它。该角色中的反向代理设置对我的客户来说不够用。我们在那里禁用了它,并为此目的创建了一个自定义子角色。

方案2

使用角色的方法可能会有一些复杂性,并且需要确保正确设置了容器A和容器B之间的依赖关系。

另一种方法是编写脚本或使用工具来控制容器的运行顺序。您可以使用docker run命令手动控制容器的启动顺序,或者使用一些第三方工具来管理容器的依赖关系。

以下是一个简单的bash脚本示例,可以在容器A启动后启动容器B:

#!/bin/bash
# 启动容器A
docker run -d --name container_a your_image_a
# 等待容器A完全启动
while ! docker exec container_a echo "Container A is ready"; do
  sleep 1
done
# 启动容器B
docker run -d --name container_b your_image_b

在这个示例中,我们首先使用docker run命令启动容器A,并将其命名为container_a。然后,使用一个循环来等待容器A完全启动(这里是通过在容器内运行echo命令来测试)。一旦容器A就绪,我们再使用docker run命令启动容器B,并将其命名为container_b

希望这些解决方案能够帮助您解决问题!

正文完