7. 容器和实例组

AWX 允许您通过 Ansible 剧本运行直接在集群成员上或 Openshift 集群的命名空间中执行作业,其中提供必要的服务帐户,称为容器组。您只能根据需要在每个剧本中在容器组中执行作业。有关更多信息,请参见本节末尾的 容器组

有关执行环境,请参见 *AWX 用户指南* 中的 执行环境

7.1. 实例组

实例可以分组到一个或多个实例组中。实例组可以分配给下面列出的一个或多个资源。

  • 组织

  • 清单

  • 作业模板

当与其中一个资源关联的作业执行时,它将被分配给与该资源关联的实例组。在执行过程中,与作业模板关联的实例组在与清单关联的实例组之前进行检查。类似地,与清单关联的实例组在与组织关联的实例组之前进行检查。因此,三个资源的实例组分配形成了一个层次结构:作业模板 > 清单 > 组织。

以下是在使用实例组时需要考虑的一些事项

  • 您可以选择定义其他组并将实例分组到这些组中。这些组应该以 instance_group_ 为前缀。实例需要与其他 instance_group_ 组一起位于 awxexecution_nodes 组中。在集群设置中,至少一个实例 **必须** 存在于 awx 组中,它将在 API 实例组中显示为 controlplane。请参见 awx 组策略 以获取示例场景。

  • 一个 default API 实例组会自动创建,其中包含所有能够运行作业的节点。从技术上讲,它与任何其他实例组一样,但是如果特定实例组未与特定资源关联,则作业执行将始终回退到 default 实例组。default 实例组始终存在(它不能被删除或重命名)。

  • 不要创建名为 instance_group_default 的组。

  • 不要将任何实例命名为与组名相同。

7.1.1. awx 组策略

在定义节点时使用以下标准

  • 位于 awx 组中的节点可以定义 node_type 主机变量为 hybrid(默认)或 control

  • 位于 execution_nodes 组中的节点可以定义 node_type 主机变量为 execution(默认)或 hop

您可以通过将组命名为 instance_group_* 在清单文件中定义自定义组,其中 * 成为 API 中的组名。或者,您可以在安装完成后在 API 中创建自定义实例组。

当前行为期望 instance_group_* 的成员是 awxexecution_nodes 组的一部分。考虑以下示例场景

[awx]
126-addr.tatu.home ansible_host=192.168.111.126  node_type=control

[awx:vars]
peers=execution_nodes

[execution_nodes]

[instance_group_test]
110-addr.tatu.home ansible_host=192.168.111.110 receptor_listener_port=8928

运行安装程序后,您将收到以下错误

TASK [ansible.automation_platform_installer.check_config_static : Validate mesh topology] ***
fatal: [126-addr.tatu.home -> localhost]: FAILED! => {"msg": "The host '110-addr.tatu.home' is not present in either [awx] or [execution_nodes]"}

要解决此问题,您可以将框 110-addr.tatu.home 移动到 execution_node 组中。

[awx]
126-addr.tatu.home ansible_host=192.168.111.126  node_type=control

[awx:vars]
peers=execution_nodes

[execution_nodes]
110-addr.tatu.home ansible_host=192.168.111.110 receptor_listener_port=8928

[instance_group_test]
110-addr.tatu.home

这会导致

TASK [ansible.automation_platform_installer.check_config_static : Validate mesh topology] ***
ok: [126-addr.tatu.home -> localhost] => {"changed": false, "mesh": {"110-addr.tatu.home": {"node_type": "execution", "peers": [], "receptor_control_filename": "receptor.sock", "receptor_control_service_name": "control", "receptor_listener": true, "receptor_listener_port": 8928, "receptor_listener_protocol": "tcp", "receptor_log_level": "info"}, "126-addr.tatu.home": {"node_type": "control", "peers": ["110-addr.tatu.home"], "receptor_control_filename": "receptor.sock", "receptor_control_service_name": "control", "receptor_listener": false, "receptor_listener_port": 27199, "receptor_listener_protocol": "tcp", "receptor_log_level": "info"}}}

从旧版本的 awx 升级后,旧的 instance_group_ 成员很可能安装了 awx 代码,这会导致该节点被放置在 awx 组中。

7.1.2. 通过 API 配置实例组

实例组可以通过 POST 到 /api/v2/instance_groups 作为系统管理员来创建。

创建后,可以使用以下方法将实例与实例组关联

HTTP POST /api/v2/instance_groups/x/instances/ {'id': y}`

添加到实例组的实例将自动重新配置自身以监听该组的工作队列。请参见下一节,实例组策略,以了解更多详细信息。

7.1.3. 实例组策略

您可以配置 AWX 实例,以便它们在上线时自动加入实例组,方法是定义一个 策略。这些策略会针对每个上线的新实例进行评估。

实例组策略由 Instance Group 上的三个可选字段控制

  • policy_instance_percentage:这是一个介于 0 - 100 之间的数字。它保证此百分比的活动 AWX 实例将被添加到此实例组。随着新实例上线,如果此组中实例的数量相对于总实例数小于给定百分比,则会添加新的实例,直到满足百分比条件为止。

  • policy_instance_minimum:此策略尝试在实例组中保留至少这么多个实例。如果可用实例的数量低于此最小值,则所有实例将被放置在此实例组中。

  • policy_instance_list:这是一个固定列表,包含始终包含在此实例组中的实例名称。

AWX 用户界面中的实例组列表视图提供了每个实例组的容量级别的摘要,这些级别是根据实例组策略确定的

Instance Group list view with example instance group and container groups.

有关更多详细信息,请参见 创建实例组

7.1.4. 值得注意的策略注意事项

  • policy_instance_percentagepolicy_instance_minimum 都设置了最小分配。导致分配到该组的实例数更多的规则将生效。例如,如果您有 50% 的 policy_instance_percentage 和 2 的 policy_instance_minimum,并且您启动 6 个实例,那么其中 3 个将被分配到实例组。如果您将集群中的总实例数减少到 2 个,那么这两个实例都将被分配到实例组以满足 policy_instance_minimum。这样,您可以设置可用资源量的下限。

  • 策略不会积极地阻止实例与多个实例组关联,但是可以通过将百分比加起来达到 100% 来有效地实现这一点。如果您有 4 个实例组,为每个组分配 25% 的百分比值,那么实例将被分配到这些组中,而不会重叠。

7.1.5. 手动将实例固定到特定组

如果您有一个特殊的实例,需要将其专门分配到一个特定的实例组,但又不想让它通过“百分比”或“最小值”策略自动加入其他组

  1. 将该实例添加到一个或多个实例组的 policy_instance_list

  2. 将该实例的 managed_by_policy 属性更新为 False

这将阻止该实例根据百分比和最小值策略自动添加到其他组中;它只属于您手动分配给它的组

HTTP PATCH /api/v2/instance_groups/N/
{
"policy_instance_list": ["special-instance"]
}

HTTP PATCH /api/v2/instances/X/
{
"managed_by_policy": False
}

7.1.6. 作业运行时行为

当您运行与实例组关联的作业时,值得注意的一些行为是

  • 如果一个集群被分成独立的实例组,那么行为与整个集群类似。如果两个实例被分配到一个组中,那么这两个实例中的任何一个都同样有可能收到作业,就像组中任何其他实例一样。

  • 当 AWX 实例上线时,它实际上扩展了系统的处理能力。如果这些实例也被放置到实例组中,那么它们也会扩展该组的处理能力。如果一个实例正在执行工作,并且它是多个组的成员,那么它所属的所有组的处理能力都会降低。取消配置一个实例将从该实例被分配到的所有集群中移除处理能力。

注意

并不需要所有实例都配备相同的处理能力。

7.1.7. 控制作业运行的位置

如果作业模板、清单或组织中任何一个与实例组相关联,那么从该作业模板运行的作业将不符合默认行为。这意味着如果与这 3 个资源相关联的所有实例组中的所有实例都已满负荷,那么该作业将保持在待处理状态,直到有处理能力可用。

确定将作业提交到哪个实例组的优先级顺序如下:

  1. 作业模板

  2. 清单

  3. 组织(通过项目)

如果实例组与作业模板相关联,并且所有这些实例组都已满负荷,那么该作业将被提交到清单中指定的实例组,然后是组织。当资源可用时,作业应该按优先级顺序在这些组中执行。

全局 default 组仍然可以与资源相关联,就像在剧本中定义的任何自定义实例组一样。这可以用来在作业模板或清单上指定一个首选实例组,但仍然允许在这些实例组的处理能力不足时将作业提交到任何实例。

例如,通过将 group_a 与作业模板相关联,并将 default 组与它的清单相关联,您可以允许在 group_a 的处理能力不足的情况下使用 default 组作为备用。

此外,还可以不将实例组与一个资源相关联,而是将另一个资源指定为备用。例如,不将实例组与作业模板相关联,而是让它回退到清单和/或组织的实例组。

这提供了另外两个很好的用例:

  1. 将实例组与清单相关联(省略将作业模板分配给实例组)将允许用户确保针对特定清单运行的任何剧本都只在与其相关联的组上运行。这在只有这些实例与受管理节点直接连接的情况下非常有用。

  2. 管理员可以将实例组分配给组织。这实际上允许管理员将整个基础设施分割出来,并保证每个组织都有运行作业的处理能力,而不会干扰任何其他组织运行作业的能力。

同样,管理员可以根据需要将多个组分配给每个组织,如以下场景所示:

  • 有三个实例组:A、B 和 C。有两个组织:Org1 和 Org2。

  • 管理员将组 A 分配给 Org1,将组 B 分配给 Org2,然后将组 C 分配给 Org1 和 Org2,作为任何可能需要的额外处理能力的溢出。

  • 然后,组织管理员可以随意将清单或作业模板分配到他们想要的任何组(或者只让他们从组织继承默认顺序)。

Illustration showing grouping scenarios.

以这种方式排列资源提供了很大的灵活性。此外,您可以创建只有一个实例的实例组,从而允许您将工作直接定向到 AWX 集群中的非常特定的主机。

7.1.8. 实例组处理能力限制

有时存在外部业务逻辑,可能会驱动限制发送到实例组的作业的并发性或要消耗的最大分叉数的愿望。

对于传统实例和实例组,可能希望允许两个组织在相同的底层实例上运行作业,但限制每个组织的并发作业总数。这可以通过为每个组织创建一个实例组并为 max_concurrent_jobs 分配值来实现。

对于容器组,AWX 通常不了解 OpenShift 集群的资源限制。在命名空间中设置的 Pod 数量可能存在限制,或者如果没有自动缩放,可能只允许资源在任何时候调度一定数量的 Pod。同样,在这种情况下,我们可以调整 max_concurrent_jobs 的值。

另一个可用的参数是 max_forks。这为限制实例组或容器组的消耗的处理能力提供了额外的灵活性。如果正在运行具有各种清单大小和“分叉”值的作业,则可以使用此参数。这样,您可以将一个组织的并发作业运行限制为 10 个,但同时消耗的“分叉”数不超过 50 个。

max_concurrent_jobs: 10
max_forks: 50

如果运行 10 个每个使用 5 个“分叉”的作业,那么第 11 个作业将等待这些作业中的一个完成才能在该组上运行(或者被调度到具有处理能力的不同组)。

如果 2 个作业正在运行,每个使用 20 个“分叉”,那么第 3 个作业的 task_impact 为 11 或更大,将等待这些作业中的一个完成才能在该组上运行(或者被调度到具有处理能力的不同组)。

对于容器组,使用 max_forks 值非常有用,因为所有作业都是使用相同的 pod_spec 提交的,具有相同的资源请求,与作业的“分叉”值无关。默认的 pod_spec 设置请求而不是限制,因此 Pod 可以“突发”超出其请求的值,而不会被节流或收割。通过设置 max_forks 值,您可以帮助防止出现以下情况:太多具有大“分叉”值的作业同时被调度,导致 OpenShift 节点被多个使用比其请求值更多资源的 Pod 过度订阅。

要设置实例组中并发作业和“分叉”的最大值,请参阅AWX 用户指南中的创建实例组

7.1.9. 取消配置实例组

重新运行设置剧本不会自动取消配置实例,因为集群目前无法区分有意下线的实例和由于故障而下线的实例。相反,请关闭 AWX 实例上的所有服务,然后从任何其他实例运行取消配置工具。

  1. 使用命令 automation-awx-service stop 关闭实例或停止服务。

  2. 从另一个实例运行取消配置命令 $ awx-manage deprovision_instance --hostname=<inventory 文件中使用的名称> 以将其从 AWX 集群注册表中移除。

    例如:awx-manage deprovision_instance --hostname=hostB

类似地,取消配置 AWX 中的实例组不会自动取消配置或移除实例组,即使重新配置通常会导致这些实例组变得未使用。它们可能仍然显示在 API 端点和统计监控中。可以使用以下命令移除这些组。

例如:awx-manage unregister_queue --queuename=<名称>

从清单文件中移除实例对实例组的成员资格,然后重新运行设置剧本并不能确保实例不会被添加回组。为了确保实例不会被添加回组,请通过 API 移除它,并在清单文件中移除它,或者您可以完全停止在清单文件中定义实例组。您也可以通过 AWX 用户界面管理实例组拓扑。有关在 UI 中管理实例组的更多信息,请参阅AWX 用户指南中的实例组

7.2. 容器组

AWX 支持容器组,它允许您在 Kubernetes (k8s) 或 OpenShift 集群上的 Pod 中执行作业。容器组充当虚拟环境中的资源池。这些 Pod 是按需创建的,并且只在剧本运行期间存在。这被称为短暂执行模型,确保每个作业运行都有一个干净的环境。

在某些情况下,希望容器组保持“始终处于运行状态”,这可以通过创建实例来配置。

容器组不同于执行环境,因为执行环境是容器镜像,不使用虚拟环境。有关详细信息,请参阅AWX 用户指南中的执行环境

7.2.1. 创建容器组

一个 ContainerGroup 是一种类型的 InstanceGroup,它与一个允许连接到 OpenShift 集群的凭据相关联。要设置容器组,您必须首先拥有以下内容:

  • 您可以启动的命名空间(每个集群都有一个“默认”命名空间,但您可能希望使用特定的命名空间)。

  • 一个服务帐户,该帐户具有允许它在该命名空间中启动和管理 Pod 的角色。

  • 如果您将在私有注册表中使用执行环境,并在 AWX 中将容器注册表凭据与它们相关联,那么服务帐户还需要具有在命名空间中获取、创建和删除秘密的角色。如果您不想将这些角色授予服务帐户,则可以预先创建 ImagePullSecrets 并在容器组的 Pod 规范中指定它们。在这种情况下,执行环境不应该与容器注册表凭据相关联,否则 AWX 将尝试在命名空间中为您创建秘密。

  • 与该服务帐户相关联的令牌(OpenShift 或 Kubernetes Bearer 令牌)。

  • 与该集群相关联的 CA 证书。

本节介绍如何在 OpenShift 集群(或 K8s)中创建服务帐户,以便通过 AWX 在容器组中运行作业。创建服务帐户后,其凭据将以 OpenShift 或 Kubernetes API 凭据的形式提供给 AWX。下面描述如何创建服务帐户并收集配置 AWX 所需的信息。

配置 AWX

  1. 要创建服务帐户,您可以下载并使用此示例服务帐户,containergroup sa,并根据需要修改它以获取上述凭据。

  2. 应用来自 containergroup-sa.yml 的配置。

    oc apply -f containergroup-sa.yml
    
  3. 获取与服务帐户关联的密钥名称。

    export SA_SECRET=$(oc get sa containergroup-service-account -o json | jq '.secrets[0].name' | tr -d '"')
    
  4. 从密钥中获取令牌。

    oc get secret $(echo ${SA_SECRET}) -o json | jq '.data.token' | xargs | base64 --decode > containergroup-sa.token
    
  5. 获取 CA 证书。

    oc get secret $SA_SECRET -o json | jq '.data["ca.crt"]' | xargs | base64 --decode > containergroup-ca.crt
    
  6. 使用 containergroup-sa.tokencontainergroup-ca.crt 的内容来提供容器组所需的 OpenShift 或 Kubernetes API 凭据 信息。

创建容器组

  1. 使用 AWX 用户界面创建一个 OpenShift 或 Kubernetes API 凭据,该凭据将与您的容器组一起使用,请参阅 添加新的凭据(在AWX 用户指南中)以了解详情。

  2. 通过点击左侧导航栏中的实例组,导航到实例组配置窗口,创建一个新的容器组。

  3. 点击添加按钮,并选择创建容器组

Create new container group form.

  1. 为您的新容器组输入一个名称,并选择先前创建的凭据将其与容器组关联。

7.2.2. 自定义 pod 规范

AWX 提供了一个简单的默认 pod 规范,但是,您可以提供一个自定义的 YAML(或 JSON)文档,它会覆盖默认的 pod 规范。此字段使用任何可以“序列化”为有效 pod JSON 或 YAML 的自定义字段(例如,ImagePullSecrets)。可以在 OpenShift 文档中找到所有选项的完整列表。

要自定义 pod 规范,请选中自定义 pod 规范选项以启用并展开自定义 pod 规范字段,您可以在其中指定命名空间并根据需要提供其他自定义项。

Create new container group form with the option to custom the pod spec.

点击展开以查看整个自定义窗口。

The expanded view for customizing the pod spec.

注意

在作业启动时使用的镜像由与作业关联的执行环境决定。如果容器注册表凭据与执行环境相关联,则 AWX 将尝试创建 ImagePullSecrets 来拉取镜像。如果您不想授予服务帐户管理密钥的权限,则必须预先创建 ImagePullSecrets 并将其指定在 pod 规范中,并且不要在使用的执行环境中添加任何凭据。

提示

为了覆盖 DNS/主机条目,请在 pod 规范中使用 hostAliases 属性。创建 pod 时,这些条目将添加到运行作业的容器中的 /etc/hosts 中。

spec:
  hostAliases:
  - ip: "127.0.0.1"
    hostnames:
    - "foo.local"

有关更多信息,请参阅 Kubernetes 关于 使用 hostAliases 添加额外的条目 的文档。

容器组创建成功后,新创建的容器组的详细信息选项卡将保留,您可以查看和编辑容器组信息。如果点击实例组链接中的编辑(编辑按钮。)按钮,也会打开相同的菜单。您还可以编辑实例并查看与该实例组相关的作业

Example of the successfully created instance group as shown in the Jobs tab of the Instance groups window.

容器组和实例组将分别标记。

注意

如果默认 pod_spec 发生更改,使用自定义 pod 规范可能会导致升级问题。由于任何清单都可以应用于任何命名空间,并且命名空间是单独指定的,因此您很可能只需要覆盖命名空间。类似地,将平台不同版本的默认镜像固定到默认作业运行器容器的不同版本是比较棘手的。如果默认镜像在 pod 规范中指定,则升级不会获取对默认 pod 规范所做的新的默认更改。

7.2.3. 验证容器组功能

要验证容器的部署和终止,

  1. 创建一个模拟清单,并在实例组字段中填充容器组的名称,将容器组与之关联。请参阅 添加新的清单(在AWX 用户指南中)以了解详情。

Example of creating a new container group test inventory.

  1. 在清单中创建“localhost”主机,并添加变量。

{'ansible_host': '127.0.0.1', 'ansible_connection': 'local'}

The new container group test inventory showing the populated variables.

  1. 使用pingsetup模块,对 localhost 发起一次临时作业。即使机器凭据字段是必需的,但对于这个简单的测试,选择哪一个都没有关系。

Launch inventory with localhost

Launching a Ping adhoc command on the newly created inventory with localhost.

您可以在作业详细信息视图中看到,使用临时作业之一成功访问了容器。

Jobs output view showing a successfully ran adhoc job.

如果您有 OpenShift UI,则可以查看 pod 在部署和终止时出现和消失。或者,您可以使用 CLI 对您的命名空间执行 get pod 操作来实时观察这些事件的发生。

7.2.4. 查看容器组作业

当您运行与容器组关联的作业时,您可以在详细信息视图中查看该作业的详细信息,以及它关联的容器组和启动的执行环境。

Example Job details window showing the associated execution environment and container group.

7.2.5. Kubernetes API 故障条件

运行容器组时,如果 Kubernetes API 响应资源配额已超出,AWX 会将作业保留在挂起状态。其他故障会导致错误详细信息字段的回溯显示故障原因,类似于以下示例

Error creating pod: pods is forbidden: User "system: serviceaccount: aap:example" cannot create resource "pods" in API group "" in the namespace "aap"

7.2.6. 容器容量限制

容器的容量限制和配额通过 Kubernetes API 中的对象定义。

  • 要设置给定命名空间中所有 pod 的限制,请使用 LimitRange 对象。请参阅 OpenShift 文档了解 配额和限制范围

  • 要直接设置 AWX 启动的 pod 定义的限制,请参阅 自定义 pod 规范,并参阅 OpenShift 文档了解如何设置 计算资源 选项。

注意

容器组不使用普通节点使用的容量算法。您需要在作业模板级别明确设置分叉数量,例如。如果在 AWX 中配置了分叉,则该设置将传递给容器。