推广 Ansible 部署接口到 ironic

https://blueprints.launchpad.net/ironic/+spec/ansible-deploy-driver

本规范提出了一种新的部署驱动程序接口,用于通过 Ansible playbook 配置节点。

问题描述

有时,可能需要将(某些)裸机节点更像宠物而非牲畜对待,为部署过程提供每个节点的自定义逻辑。

目前,在 Ironic 中进行此类自定义并非易事,开发人员/云管理员可能需要执行以下一项或多项操作

  • 修改 Ironic 部署驱动程序的代码。

  • 修改 Ironic Python Agent 的代码。

  • 修改 ironic-lib 的代码。

  • 重建 IPA ramdisk。

  • 将新的 ramdisk 上传到 Glance 或 HTTP 服务器。

  • 使用新的 ramdisk 更新节点信息。

  • 更新 Ironic conductors 上的部署驱动程序。

  • 重启 conductors。

这个问题可以通过基于外部模板的部署驱动程序来部分解决,用于配置管理工具。

可能的用例和优势

  • 在部署过程的任何阶段,使用厂商的工具进行自定义操作,无论是机内还是机外。

  • 轻松替换部署中使用的 Linux 工具。

  • 深度调整部署过程。

  • 在不重启 conductors 的情况下更改部署过程的行为。

  • 部署 ramdisk 的长生命周期 - 厂商的工具可以在部署过程中从外部源下载。

  • 职责分离 - ironic 管理“是什么”部分,Ansible 管理“如何”部分

  • 允许将 BM 更像宠物一样对待

提议的变更

本规范提出了一种基于 Ansible [1] 作为配置管理解决方案的部署接口。实际上,它使用 ironic 实现其电源、管理和启动功能,并将部署逻辑本身转移到 Ansible playbook。

该部署接口已经实现,并且作为 ironic-staging-drivers 项目的一部分提供 [2]。它可以作为 ipmi 硬件(以及可能其他硬件)的可能的部署接口使用。因此,本规范建议将 ansible 部署接口提升到核心 ironic 中,作为可用的部署接口之一。

以下是此部署接口架构和当前功能的简要说明。更多信息可在 ironic-staging-drivers 项目文档中找到,网址为 [3]

用例

此部署接口最适合“undercloud”类型的或独立 ironic 用例,其中 ironic 服务的操作员通常是将被部署的镜像和/或已部署实例的所有者。但是,它已经包含一组 Ansible playbook,这些 playbook 尽可能地模拟标准 direct 部署接口的功能。

当在配置过程中需要执行一些难以在已配置实例中完成的底层系统配置(例如,将根分区放在 LVM/软件 RAID 上),或需要额外重启(例如,更改内核参数)时,此部署接口非常有用。

总体概述

我们选择 Ansible 的原因是

  • 开源(GPLv3 + 部分 MIT),成熟且流行,包括 OpenStack 生态系统本身

  • 用 Python 编写和扩展,与 OpenStack 生态系统完美契合

  • 配置文件是人类可读的 YAML

  • 按设计是无代理的,对受管节点的最低要求是 Python 和 SSH 服务器。

有两种方法可以从 Python 程序中使用 Ansible:使用 Ansible Python API 或运行带有参数的 CLI 实用程序。Ansible Python API 当前强制调用进程分叉,此行为不适合 Ironic conductor(oslo.messaging 至少不允许分叉)。此外,Ansible 许可选择(GPLv3)禁止从 ironic 使用 Ansible Python API(Apache 2.0)。因此,使用 ansible-playbook CLI 实用程序。

每个操作(部署、清理)都由一个 Ansible playbook 描述,其中包含角色,并在部署期间作为整体运行,或在清理期间按标签运行。 清理步骤的控制通过 Ansible 标签和辅助清理步骤文件进行。 操作的 playbook 可以设置为每个节点,就像清理步骤文件一样。

该 dreploy 接口尝试尽可能多地重用 ironic 中的代码,并且在接口方面与 direct 部署接口非常相似。

当前此接口支持两种模式以继续部署或清理

  • 部署 ramdisk 调用 ironic API 的 heartbeat 端点(默认)

  • 在 playbook 的一部分中轮询节点,直到打开 ssh 端口

当将其移动到 ironic 时,我们建议删除后者,因为对其支持在 gate 中未经过测试,它会降低性能,并且通常会使代码更复杂。

使用自定义 Ansible 回调插件进行日志记录。它可以从 ironic 配置文件中读取日志配置,从而将 Ansible 事件的日志条目直接发送到 ironic 也使用的日志后端(与 journald 后端配合使用效果最佳)。

部署

该接口准备部署所需的一组参数,包括要部署的节点的访问信息。然后,它执行 ansible-playbook 脚本,传递所有收集到的信息,节点访问信息用于在运行时将节点注册到 Ansible inventory。

支持的镜像类型是整个磁盘镜像和带有“local”启动选项的分区镜像,“netboot”当前不受支持。压缩的镜像下载到部署 ramdisk 并转换为实际的磁盘设备/分区,RAW 镜像直接流式传输到目标。

支持为整个磁盘和分区镜像创建 configdrive 分区,同时支持 msdos 和 GPT 标记的磁盘。

根设备提示当前仅以其基本形式受支持(具有确切匹配,没有 oslo.utils 运算符),正在审查中存在添加完全支持的补丁。 如果未为节点提供根设备提示,则作为 ansible_devices Ansible fact 的一部分返回的第一个设备将用作根设备,以在其上创建分区或写入整个磁盘镜像。

清理

Ansible 部署接口的清理过程

  • 每个清理步骤都是用于清理的 Ansible playbook 文件中的一个标签。 可用的步骤、它们的优先级和相应的标签在辅助清理步骤配置文件中定义。

  • get_clean_steps() 方法返回在所述配置文件中定义的清理步骤列表。

  • prepare_cleaning() 方法加载与部署相同的 ramdisk。

  • execute_clean_step() 方法通过 Ansible 同步执行清理步骤,仅执行分配给清理步骤的 Ansible 标签的任务。

与接口提供的默认清理 playbook 支持 direct 部署接口的 erase_devices_metadataerase_devices 清理步骤,通过执行浅层磁盘元数据清理和粉碎磁盘设备来实现,并遵守 ironic 配置文件中设置的这些步骤的优先级。

备选方案

使用不同的部署自定义机制或不支持宠物般的处理。

当前 ansible 部署接口与已有的标准 direct 部署接口相比的主要优缺点概述

  • 更容易扩展自定义配置逻辑

  • 不是异步的

  • 不支持 netboot

数据模型影响

状态机影响

REST API 影响

客户端 (CLI) 影响

RPC API 影响

驱动程序 API 影响

Nova 驱动程序影响

Ramdisk 影响

为了支持这个新的部署接口,部署 ramdisk 应该包括

  • 具有无密码 sudo 权限的用户 - 必需

  • 配置为通过 SSH 密钥访问此用户的 SSH 服务器 - 必需

  • Python 解释器(Python2 >= 2.6 或 Python3 >= 3.5)

    • 目前仅使用 Python2 2.7 进行测试

    • 实际的 Python 版本取决于用于 Ansible 的版本以及在 ironic-conductor 主机上执行 Ansible 的 Python 解释器的版本

    • 当前 Ansible 对受管节点上的 Python3 的支持仍然被认为是实验性的(并且在 Ansible 2.1.x 中完全不受支持)

  • 一个软件组件,在 ramdisk 启动时将发出对 ironic API 的 lookup API 请求,然后发出 heartbeat 请求

    • 默认选择此类组件是 IPA

  • 部署或清理 playbook 中使用的其他系统工具

所有或部分这些(除了 SSH 服务器)原则上可以在运行时通过 playbook 中的其他 Ansible 任务安装(减少部署 ramdisk 的内存占用和下载/启动时间),但也可以与部署 ramdisk 一起提供以缩短配置时间。

将 IPA 作为 lookupheartbeat ironic API 客户端重用,可以使 directiscsiansible 部署接口的统一部署 ramdisk 成为可能。

ironic-staging-drivers 项目包含一组脚本,用于执行基于 TinyCore Linux 的部署 ramdisk(TinyIPA)的简单重建,以及 diskimage-builder 元素,用于使用此实用程序构建合适的 ramdisk,基于 ironic-agent 元素,从而也包含 IPA。这些将被提升到新的 openstack/ironic-python-agent-builder 项目 [4]

目前不支持基于 CoreOS 的部署 ramdisk 的重建,但将来可以添加对此的支持。

安全影响

Ansible 通过 SSH 与远程机器通信。如果正确保护了私有 SSH 密钥(只能由运行 ironic-conductor 服务的用户访问),则部署过程是安全的。

其他最终用户影响

可扩展性影响

该驱动程序不是异步的并且是阻塞的。每个 ironic-conductor 工作线程需要一个正在配置或清理的节点。大多数时候,线程在阻塞状态下等待 ansible-playbook 进程完成。在计划允许使用此部署接口并配置 ironic 配置文件中的线程池大小([conductor]workers_pool_size 选项)时,必须考虑可能的线程池耗尽。

有一些关于如何使驱动程序异步/非阻塞的想法,这些想法将在后续的规范/RFE 中提出。

性能影响

我们进行了一些测试来衡量在 ironic-conductor 主机上运行多个 ansible-playbook 进程的性能影响 [5]

结果表明,虽然使用 ansible 部署接口确实会引入性能开销,但它在相当标准的硬件范围内 - 我们能够通过单个 ironic-conductor 服务使用此部署接口同时配置 50 个和 100 个节点,总配置时间与 direct 部署接口相似。有关测试设置和结果的更多详细信息,请参阅上述博客文章。

其他部署者影响

配置选项

这些在 ironic 配置文件的 [ansible] 部分中定义

详细程度

无,0-4。对应于传递给 ansible-playbook 的“v”的数量。默认值(无)将在 ironic 中启用全局调试时传递“vvvv”,否则不传递任何内容。

ansible_playbook_script

ansible-playbook 脚本的完整路径。主要用于测试环境,例如,当您从源代码运行 Ansible 而不是安装它时。默认值(无)将在运行 ironic-conductor 服务的用户的 $PATH 中搜索。

playbooks_path

包含所有 Ansible 相关文件的文件夹的路径(Ansible inventory、部署/清理 playbook、角色等)。默认情况下,使用从安装包中安装的 playbook。

config_file_path

Ansible 配置文件路径。设置为 None 时,将使用全局系统默认值(通常为 /etc/ansible/ansible.cfg)。默认值为 playbooks_path/ansible.cfg

ansible_extra_args

每次调用时传递给 ansible-playbook 的额外参数。默认值为 None。

default_username

通过 SSH 连接到 ramdisk 时要使用的用户名。默认值为“ansible”。可以被节点 driver_info 字段中的每个节点的 ansible_username 选项覆盖。

default_key_file

用于通过 SSH 连接到 ramdisk 时,Ansible 默认使用的私钥 SSH 密钥文件的绝对路径。如果未提供(默认),Ansible 将使用运行 ironic-conductor 服务的用户配置的默认 SSH 密钥。请注意,带有密码的私钥必须预先加载到 ssh-agent 中。它可以通过节点 driver_info 字段中的每个节点的 ansible_key_file 选项覆盖。

default_deploy_playbook

用于部署的默认 playbook 的路径(相对于 $playbooks_path 或绝对路径)。默认值为 ‘deploy.yaml’。它可以通过节点 driver_info 字段中的每个节点的 ansible_deploy_playbook 选项覆盖。

default_shutdown_playbook

用于优雅地在带内关闭节点的默认 playbook 的路径(相对于 $playbooks_path 或绝对路径)。默认值为 ‘shutdown.yaml’。它可以通过节点 driver_info 字段中的每个节点的 ansible_shutdown_playbook 选项覆盖。

default_clean_playbook

用于节点清理的默认 playbook 的路径(相对于 $playbooks_path 或绝对路径)。默认值为 ‘clean.yaml’。它可以通过节点 driver_info 字段中的每个节点的 ansible_clean_playbook 选项覆盖。

default_clean_steps_config

用于节点清理期间使用的默认辅助清理步骤文件的路径(相对于 $playbooks_path 或绝对路径)。默认值为 ‘clean_steps.yaml’。它可以通过节点 driver_info 字段中的每个节点的 ansible_clean_steps_config 选项覆盖。

extra_memory

Ansible 相关进程在部署 ramdisk 中消耗的内存(以 MiB 为单位)。影响下载的用户镜像是否能适应节点的 RAM。默认值为 10。

post_deploy_get_power_state_retries

在软关机后,重试获取电源状态的次数,以检查裸机节点是否已关机。默认值为 6。

post_deploy_get_power_state_retry_interval

触发软关机后,轮询电源状态之间等待的时间量(以秒为单位)。默认值为 5。

最后 3 个选项实际上是配置文件的 [agent] 部分中类似选项的副本。我们可以为所有使用它们的部署接口使用单个选项,特别是如果我们从 [agent] 部分将它们重命名/移动到具有更通用名称的部分(如 [deploy])。

driver_info 中的节点字段

这些参数可以与 driver_info 一起提供,所有参数都是可选的,并且可以在 ironic 配置文件中设置它们的默认值

ansible_username

Ansible 用于访问节点的用户名(默认值为 ansible)。

ansible_deploy_username

已被 ansible_username 取代。

ansible_key_file

用于访问节点的私钥 SSH 密钥。如果未提供(默认),Ansible 将使用运行 ironic-conductor 服务的用户配置的默认 SSH 密钥。请注意,带有密码的私钥必须预先加载到 ssh-agent 中。

ansible_deploy_keyfile

已被 ansible_key_file 取代。

ansible_deploy_playbook

playbooks_path 文件夹中用于部署此节点的 playbook 文件的名称。

ansible_shutdown_playbook

playbooks_path 文件夹中用于优雅地在带内关闭节点的 playbook 文件的名称。

ansible_clean_playbook

playbooks_path 文件夹中用于清理节点的 playbook 文件的名称。

ansible_clean_steps_config

playbooks_path 文件夹中包含此节点使用的清理步骤描述的 YAML 文件的名称,并定义 ansible_clean_playbook 文件中与每个清理步骤对应的 playbook 标签。

开发人员影响

开发人员可以使用此部署接口进行驱动程序开发。

实现

负责人

主要负责人

Pavlo Shchelokovskyy - pas-ha (IRC), pshchelo (Launchpad)

其他贡献者

Yurii Zveryanskyy - yuriyz (IRC), yzveryanskyy (Launchpad)

工作项

  • ironic-staging-drivers 项目复制 ansible 部署接口

    • 大部分更改将发生在单元测试模块的导入中

  • 注册 ansible 部署接口入口点,将其添加到 ipmi 硬件类型的支持部署接口列表中,不要在配置文件中默认启用它。

  • 复制文档。

  • imagebuild 脚本从 ironic-staging-drivers 项目复制到新的 ironic-python-agent-builder 项目

    • 在 DevStack 插件和 gate 作业中安装并使用此新项目中的脚本

  • 修改 ironic 的 DevStack 插件,使其能够使用此部署接口设置节点。

    • 目前需要在 DevStack 安装期间对 TinyIPA 镜像进行小幅重建。

  • 复制并修改 gate-tempest-dsvm-ironic-staging-drivers-ansible-wholedisk-ubuntu-xenial-nv gate 作业,以非投票模式在 ironic 项目中启用它。

依赖项

必须在运行 ironic-conductor 服务的宿主机上安装 Ansible。

此部署接口使用 Ansible 2.1 开发和测试,并针对 Ansible >= 2.1(排除一些不兼容的中间版本)。目前测试此部署接口的 gate 作业通过了最新的 Ansible 版本(截至撰写本文时为 2.3.2.0)。

另请参阅 Ramdisk 影响 部分,了解对部署 ramdisk 的必要更改。

测试

  • 单元测试已经到位。

  • CI 测试已经到位

    • 由于这是一个供应商无关的部署接口,因此可以在 DevStack 的上游 gate 上使用虚拟硬件进行测试

    • 作业 gate-tempest-dsvm-ironic-staging-drivers-ansible-wholedisk-ubuntu-xenial-nv 已经在 ironic-staging-drivers 项目的所有更改上以非投票模式运行

    • 在对 ironic 的 DevStack 插件进行适当更改后,必须对其进行复制和修改。

升级和向后兼容性

无。

文档影响

文档已经可用,也必须移动到 ironic 代码树中。

参考资料