Ansible 部署接口

Ansible 是一种成熟且流行的自动化工具,用 Python 编写,无需在被配置的节点上运行代理。与节点的默认通信方式是通过安全的 SSH 传输。

ansible 部署接口使用 Ansible playbook 定义部署逻辑。它不基于 Ironic Python Agent (IPA),通常也不需要在部署 ramdisk 中运行 IPA。

概述

此部署接口的主要优势在于,对于根据特定用例更改和调整节点部署逻辑的灵活性有所扩展,通过操作员已经熟悉的 Ansible 工具实现。

它可以用来缩短通常的特性开发周期,即

  • 在 ironic 中实现逻辑,

  • 在 IPA 中实现逻辑,

  • 重建部署 ramdisk,

  • 将部署 ramdisk 上传到 Glance/HTTP 存储,

  • 将部署 ramdisk 重新分配给节点,

  • 重新启动 ironic-conductor 服务,以及

  • 运行测试部署

通过使用“稳定”的部署 ramdisk,而无需重新启动 ironic-conductor (参见 扩展 playbook)。

此部署接口的主要缺点是以同步方式执行部署/清理任务。为正在配置或清理的每个节点都会生成一个单独的 ansible-playbook 进程,这会消耗 ironic-conductor 进程可用的线程池中的一个线程,并阻塞该线程,直到节点配置或清理步骤完成或失败。在规划启用此部署接口的 ironic 部署时,必须考虑到这一点。

每个操作(部署、清理)都由一个带有 roles 的 playbook 描述,在部署期间运行整个 playbook,或在清理期间按标签运行。 清理步骤的控制通过标签和辅助清理步骤文件进行。 操作的 playbook 可以设置为每个节点,清理步骤文件也可以。

特性

与依赖于 Ironic Python Agent (IPA) 的部署接口类似,此部署接口也依赖于部署 ramdisk 回调到 ironic API 的 heartbeat 端点。

但是,驱动程序当前是同步的,因此仅处理第一个 heartbeat,并将其用作启动 ansible-playbook 进程的信号。

用户镜像

支持全盘镜像和分区镜像

  • 压缩镜像下载到 RAM 并转换为磁盘设备;

  • 原始镜像直接流式传输到磁盘。

对于分区镜像,驱动程序将创建根分区,如果请求,还会创建 Compute 服务或操作员在节点的 instance_info 中设置的临时分区和交换分区。默认分区表类型为 msdos,如果节点 instance_info 中设置了节点的 disk_label 功能,则会遵从该功能 (请参阅 选择磁盘标签)。

Configdrive 分区

支持全盘镜像和分区镜像的 configdrive 分区创建,适用于 msdosGPT 标记的磁盘。

根设备提示

根设备提示目前仅以其基本形式支持,具有精确匹配 (请参阅 指定部署磁盘(根设备提示) 以获取更多详细信息)。 如果未为节点提供根设备提示,则作为 ansible_devices fact 的一部分返回的第一个设备将用作创建分区或写入整个磁盘镜像的根设备。

节点清理

支持清理,包括自动和手动清理。 驱动程序具有两个默认清理步骤

  • 擦除设备元数据

  • 磁盘粉碎

它们可以通过 ironic 配置文件中的 [deploy]\erase_devices_metadata_priority[deploy]\erase_devices_priority 选项覆盖优先级。

像使用依赖于 Ironic Python Agent (IPA) 的驱动程序一样,如果没有任何清理步骤需要执行,则完全跳过启动部署 ramdisk。

注意

不支持中止清理步骤。

日志

日志记录实现为自定义 Ansible 回调模块,该模块使用 oslo.logoslo.config 库,并可以重用 ironic 配置文件中定义的日志记录配置来设置 Ansible 事件的日志记录,或为此目的使用单独的文件。

当为日志记录启用 journald 支持时,它效果最佳。

需求

Ansible

使用 Ansible 2.5.x 进行测试,并以此为目标。

引导镜像要求

  • 用于 Ansible 的无密码 sudo 权限

  • python 2.7.x

  • openssh-server

  • GNU coreutils

  • utils-linux

  • parted

  • gdisk

  • qemu-utils

  • python-requests (用于 ironic 回调和流式镜像下载)

  • python-netifaces (用于 ironic 回调)

一组脚本,用于基于 TinyCore Linux 和 tinyipa ramdisk 构建合适的部署 ramdisk,以及 diskimage-builder 的一个元素可以在 ironic-staging-drivers 项目中找到,但最终将被迁移到新的 ironic-python-agent-builder 项目。

设置您的环境

  1. 安装 ironic(作为 OpenStack 的一部分或独立安装)

    • 如果将 ironic 作为 OpenStack 的一部分使用,请确保 Image 服务配置为使用 Object Storage 服务作为后端,并且 Bare Metal 服务相应配置,请参阅 配置 Image 服务以获取临时 URL

  2. 安装 Ansible 版本,如 ironic/driver-requirements.txt 文件中指定

  3. 编辑 ironic 配置文件

    1. ansible 添加到 ironic 配置文件中 [DEFAULT]\enabled_deploy_interfaces 选项中定义的部署接口列表中。

    2. 确保在 [DEFAULT]\enabled_hardware_types 选项中启用了支持 ansible 部署接口的硬件类型。

    3. 如果需要,修改 ironic 配置文件 [ansible] 部分中的选项 (请参阅 配置文件)。

  4. (重新)启动 ironic-conductor 服务

  5. 构建合适的部署内核和 ramdisk 镜像

  6. 将它们上传到 Glance 或放入您的 HTTP 存储

  7. 创建新的或更新现有的节点,以使用您选择的启用的驱动程序,并在与默认值不同的情况下填充 驱动程序的节点属性

  8. 像往常一样部署节点。

Ansible 部署选项

配置文件

驱动程序选项在 ironic 配置文件的 [ansible] 部分中配置,有关其描述和默认值,请参阅 配置文件示例

节点的驱动程序属性

通过 baremetal node set 命令为每个节点设置它们,例如

baremetal node set <node> \
    --deploy-interface ansible \
    --driver-info ansible_username=stack \
    --driver-info ansible_key_file=/etc/ironic/id_rsa
ansible_username

用于 Ansible 访问节点的用户名。默认值取自 ironic 配置文件的 [ansible]/default_username 选项 (默认为 ansible)。

ansible_key_file

用于访问节点的私有 SSH 密钥。默认值取自 ironic 配置文件的 [ansible]/default_key_file 选项。如果未设置任何一个,则将使用运行 ironic-conductor 进程的用户的默认私有 SSH 密钥。

ansible_deploy_playbook

部署此节点时使用的 playbook。默认值取自 ironic 配置文件的 [ansible]/default_deploy_playbook 选项 (默认为 deploy.yaml)。

ansible_shutdown_playbook

用于在带内优雅地关闭节点所使用的 playbook。默认值取自 ironic 配置文件的 [ansible]/default_shutdown_playbook 选项 (默认为 shutdown.yaml)。

ansible_clean_playbook

清理节点时使用的 playbook。默认值取自 ironic 配置文件的 [ansible]/default_clean_playbook 选项 (默认为 clean.yaml)。

ansible_clean_steps_config

辅助 YAML 文件,其中包含此节点使用的清理步骤的描述,并定义 ansible_clean_playbook 文件中与每个清理步骤对应的 playbook 标签。默认值取自 ironic 配置文件的 [ansible]/default_clean_steps_config 选项 (默认为 clean_steps.yaml)。

ansible_python_interpreter

管理机器上的 python 解释器的绝对路径。默认值取自 ironic 配置文件的 [ansible]/default_python_interpreter 选项。Ansible 默认使用 /usr/bin/python

自定义部署逻辑

预期的 playbook 目录布局

ironic 配置文件的 [ansible]\playbooks_path 选项预计具有标准 Ansible 项目布局,并进行了一些补充

<playbooks_path>
|
\_ inventory
\_ add-ironic-nodes.yaml
\_ roles
 \_ role1
 \_ role2
 \_ ...
|
\_callback_plugins
 \_ ...
|
\_ library
 \_ ...

此驱动程序依赖的额外文件是

inventory

Ansible 包含单个条目的清单文件,即 conductor ansible_connection=local。这基本上定义了 localhost 的别名。其目的是使 Ansible 执行的本地任务的日志记录以及在 playbook 中引用 localhost 更加直观。 这还会抑制 Ansible 产生的关于 hosts 文件为空的警告。

add-ironic-nodes.yaml

此文件包含一个 Ansible play,它填充内存 Ansible 清单,其中包含从 ansible-deploy 接口接收到的访问信息以及一些每个节点的变量。在所有自定义 playbook 中将其包含为第一个 play。

默认的 deploy.yaml playbook 使用几个较小的 roles,这些 roles 对应于部署过程的特定阶段

  • discover - 例如,设置根设备和镜像目标

  • prepare - 如有需要,准备系统,例如创建分区

  • deploy - 下载/转换/写入用户镜像和 configdrive

  • configure - 部署后步骤,例如安装引导加载程序

更多包含的 roles 是

  • shutdown - 用于在带内优雅地关闭节点

  • clean - 定义清理过程,每个清理步骤定义为单独的 playbook 标签。

扩展 playbook

您可能首先会这样进行实验

  1. 同一文件夹中复制 deploy.yaml playbook,并为其命名一个独特的名称。

  2. roles 文件夹中创建带有自定义逻辑的 Ansible roles。

    1. 在您的自定义部署 playbook 中,将 prepare 角色替换为您自己的角色,该角色定义在镜像下载/写入之前要运行的步骤。这是一个设置事实的地方,以覆盖驱动程序提供/省略的事实,例如 ironic_partitionsironic_root_device,并创建自定义分区或(软件)RAID。

    2. 在您的自定义部署 playbook 中,将 configure 角色替换为您自己的角色,该角色定义在镜像写入磁盘之后要运行的步骤。例如,这是一个配置引导加载程序并添加内核选项以避免额外重启的好地方。

    3. 在您的新 playbook 中使用这些新角色。

  3. 将您创建的自定义部署 playbook 分配给节点的 driver_info/ansible_deploy_playbook 字段。

  4. 运行部署。

    1. 无需重启 ironic-conductor。

    2. 只有当您想要使用当前部署 ramdisk 中不存在的命令/脚本/软件包,并且您无法或不想在运行时安装这些软件包时,才需要构建并分配新的部署 ramdisk 给节点。

您可以访问的变量

该驱动程序会将单个 JSON 化的额外变量参数传递给 Ansible(如 ansible-playbook -e ..)。这些值也可以在您的 playbook 中访问(其中一些是可选的,可能未定义)

ironic:
  nodes:
  - ip: "<IPADDRESS>"
    name: "<NODE_UUID>"
    user: "<USER ANSIBLE WILL USE>"
    extra: "<COPY OF NODE's EXTRA FIELD>"
  image:
    url: "<URL TO FETCH THE USER IMAGE FROM>"
    disk_format: "<qcow2|raw|...>"
    container_format: "<bare|...>"
    checksum: "<hash-algo:hashstring>"
    mem_req: "<REQUIRED FREE MEMORY TO DOWNLOAD IMAGE TO RAM>"
    tags: "<LIST OF IMAGE TAGS AS DEFINED IN GLANCE>"
    properties: "<DICT OF IMAGE PROPERTIES AS DEFINED IN GLANCE>"
  configdrive:
    type: "<url|file>"
    location: "<URL OR PATH ON CONDUCTOR>"
  partition_info:
    label: "<msdos|gpt>"
    preserve_ephemeral: "<bool>"
    ephemeral_format: "<FILESYSTEM TO CREATE ON EPHEMERAL PARTITION>"
    partitions: "<LIST OF PARTITIONS IN FORMAT EXPECTED BY PARTED MODULE>"
  raid_config: "<COPY OF NODE's TARGET_RAID_CONFIG FIELD>"
ironic.nodes

一个字典列表(当前只有一个元素),将被 add-ironic-nodes.yaml playbook 用于填充内存库存。它还包含节点 extra 字段的副本,以便您可以在 playbook 中访问它。Ansible 的主机设置为节点的 UUID。

ironic.image

节点 instance_info 的所有字段,这些字段以 image_ 开头,都将传递到此变量中。一些额外的说明和字段

  • mem_req 是根据镜像大小(如果可用)和配置选项 ansible.extra_memory 计算得出的。

  • 如果 checksum 不采用 <hash-algo>:<hash-sum> 的形式,则假定哈希算法为 md5(Glance 中的默认值)。

  • validate_certs - 布尔值(yes/no)标志,用于启用或禁用镜像存储 SSL 证书的验证(默认值为“yes”)。由 ironic 配置文件中的 ansible.image_store_insecure 选项控制。

  • cafile - 用于验证镜像存储 SSL 证书的自定义 CA 捆绑包。如果定义了 ansible.image_store_cafile,则采用该值。目前默认 playbook 没有使用它,因为 Ansible 没有办法为单个 HTTPS 操作指定要使用的自定义 CA 捆绑包,但是您可以在自定义 playbook 中使用此值,例如在部署时将此 CA 上传并注册到 ramdisk 中。

  • client_cert - 客户端 SSL 身份验证的证书文件。如果定义了 ansible.image_store_certfile 选项,则采用该值。目前默认 playbook 没有使用它,但是您可以在自定义 playbook 中使用此值。

  • client_key - 客户端 SSL 身份验证的私钥文件。如果定义了 ansible.image_store_keyfile 选项,则采用该值。目前默认 playbook 没有使用它,但是您可以在自定义 playbook 中使用此值。

ironic.partition_info.partitions

可选。定义要在节点上创建的分区的字典列表,形式如下

partitions:
- name: "<NAME OF PARTITION>"
  unit: "<UNITS FOR SIZE>"
  size: "<SIZE OF THE PARTITION>"
  type: "<primary|extended|logical>"
  align: "<ONE OF PARTED_SUPPORTED OPTIONS>"
  format: "<PARTITION TYPE TO SET>"
  flags:
    flag_name: "<bool>"

驱动程序将从 instance_inforoot_gbswap_mbephemeral_gb 字段填充此列表。驱动程序还将在部署到使用 GPT 标签的磁盘时,在 bios_grub 标签的分区前添加一个分区,并在 instance_info 中设置了 configdrive 时,预先创建一个 64 MiB 的分区用于 configdrive。

请阅读 ironic_parted 模块的源代码中包含的文档,以获取有关该模块及其参数的更多信息。

ironic.partition_info.ephemeral_format

可选。从 instance_info 获取,它定义了要在临时分区上创建的文件系统。默认值为 ironic 配置文件中的 [pxe]\default_ephemeral_format 选项的值。

ironic.partition_info.preserve_ephemeral

可选。从 instance_info 获取,它指定是否应保留或重建临时分区。默认值为 no

ironic.raid_config

如果 target_raid_config 不为空,则从该配置获取,它指定要应用的 RAID 配置。

与 Ansible playbook 一样,您还可以访问由 setup 模块发现的标准 Ansible facts。

包含的自定义 Ansible 模块

提供的 playbooks_path/library 文件夹包含几个自定义 Ansible 模块,这些模块由 deployprepare 角色的默认实现使用。您也可以在 playbook 中使用这些模块。

stream_url

直接从 HTTP(S) 源流式下载到磁盘设备,尝试与 Ansible 的 get_url 模块在模块参数方面兼容。由于这种操作的底层性质,它不是幂等的。

ironic_parted

使用 parted 实用程序创建分区表和分区。由于这种操作的底层性质,它不是幂等的。请阅读模块源代码中包含的文档,以获取有关此模块及其参数的更多信息。该名称的选择是为了避免遮蔽 Ansible 中包含的 parted 模块。