我们希望听到你的声音!帮助我们深入了解 Ansible 生态系统的现状。
参与 2024 年 Ansible 项目调查

两种简单的方法,使用自动化节省 AWS 账单

两种简单的方法,使用自动化节省 AWS 账单

Red Hat Ansible 自动化平台是一个用于公共云的优秀的自动化和编排工具。在本篇文章中,我将介绍 Ansible 自动化平台可以帮助解决的两种常见场景。我想跳出常见的公共云用例(例如资源的供应和解除供应),转而关注自动化常见的运维任务。

cloud engineer diagram

什么是运维任务?简单来说,就是管理员除了创建和删除云资源(例如实例、网络、密钥等)之外,还需要执行的其他任何操作,以帮助维护其公司的公共云账户。我遇到的一个问题是,实例被遗忘开启,在后台不断产生公共云账单,而我们却将注意力集中在其他地方。用户越多,出现问题可能性就越大;自动化可以帮助解决这些问题,并保持对账户的控制。这里我想介绍两个常见的场景。

  1. 为一次性活动手动创建的定制 AWS 实例,通常用于测试某些内容,然后这些实例被遗忘并保持运行状态。
  2. 每次将 Pull Request (PR) 推送到我们的项目时,都会启动持续集成 (CI) 实例以编程方式测试更改,并且有时会遇到某些特殊情况,导致并非所有内容都正确地解除供应(关闭)。

在这两种情况下,孤立的实例都可能长时间保持运行状态。假设您启动了几十个实例来测试公共云上的某些内容,然后您开始忙碌,忘记了时间,并且在结束一天的工作前忘记终止这些实例。这可能意味着您在 16 小时(至少)内被收取费用,而您并没有从公司资助的公共云中获得任何价值。现在,将此乘以数十个用户,账单很快就会达到数万美元。

用例一:处理定制孤立实例

因此,让我们解决这些问题,并使用 Ansible 自动化平台为上述第一个场景自动化解决方案,在该场景中,实例在任何自动化防护栏之外启动(即,它们没有使用任何自动化工具,包括 Ansible,来启动云资源)。我们要求团队中所有有权访问公共云账户的人员为其实例添加标签。他们必须创建一个键值对标签,内容为:owner: person

inventory tags screenshot

这创建了一种非常简单的方法来审计和查看谁(哪个个人、组织或团队)负责计费,这解决了难题的一半。我将编写一个非常简单的 Ansible Playbook 来执行此操作。我将使用完全受支持的 amazon.aws 集合来演示这一点。

这里,社区集合和受支持集合之间的主要区别在于,受支持集合需要您的 Red Hat 订阅。此外,完全受支持的 amazon.aws 集合(作为 Red Hat 订阅的一部分提供)还进行了大量的集成测试、代码审计以及 Python 3/boto3 支持。

处理未标记的实例

在我的第一个 Ansible Playbook 中,我想获取所有没有标签的实例列表。首先,让我们检索特定区域中所有正在运行的实例

- name: grab info for un-tagged instances
  amazon.aws.ec2_instance_info:
    region: "{{ ec2_region }}"
    filters:
      instance-state-name: running
  register: ec2_node_info

我使用的是 AWS 集合(Amazon 命名空间的一部分)中的 ec2_instance_info 模块。此任务检索所有实例(无论是否有标签)。我发现最简单的方法是获取所有内容,然后筛选出空标签

- name: set the untagged to a var
  set_fact:
    untagged_instances: "{{ ec2_node_info.instances | selectattr('tags', 'equalto', {}) | map(attribute='instance_id') | list }}"

selectattr 过滤器只是匹配任何没有标签的实例,使用 ['tags', 'equalto', {} ]

然后我可以简单地终止它们,因为我的同事没有遵循我制定的良好准则

- name: Terminate every un-tagged running instance in a region.
  amazon.aws.ec2:
    region: "{{ ec2_region }}"
    state: absent
    instance_ids: "{{ untagged_instances }}"
  when: untagged_instances | length  > 0

但是,由于您可能比我更宽容,因此您可以使用 state: stopped 而不是 absent,这将关闭它们而不是终止它们。

检索任何缺少标签的实例

为了扩展以上内容,我们不仅关心完全未标记的实例(意味着根本没有标签),而且我们特别关注 owner 标签。我现在想检索任何缺少 owner 标签的实例。我可以使用与上面完全相同的逻辑,但改为使用 selectattr 过滤器查找未定义的值。

- name: set the missing tag to a var
  set_fact:
    missing_tag: "{{ ec2_node_info.instances | selectattr('tags.owner', 'undefined') | map(attribute='instance_id') | list }}"

我想展示以上两个示例,以提供一条操作路径。通过使用 Ansible 自动化平台实现以上操作,您的组织现在可以理解,他们需要使用标签,否则他们的实例将被关闭(或更糟!)。更进一步,组织可以使用自动化来强制执行特定的标签以分配所有权,或者将对实例采取的操作。您可以使用上述一个或两个示例。

用例二:处理自动化实例

对于我的特定用例,我有一个代码存储库,会自动进行测试。我们的代码每晚都会进行测试,并且每次将 Pull Request (PR) 推送到代码存储库时都会进行测试。CI 测试将在 AWS 上供应实例,配置实例,运行自动化测试,然后解除供应。有时解除供应步骤无法成功完成,从而留下孤立的主机。我注意到的一件常见的事情是,这些实例通常处于部分关闭状态,其中它们的标签完全丢失(删除),但实例实际上并没有关闭,因此我们仍在被收费。前面示例中的 Ansible Playbook 可以捕获这种情况。

但是,另一个很棒的测试是使用新的正常运行时间参数。

- name: grab info
  amazon.aws.ec2_instance_info:
    region: "{{ ec2_region }}"
    uptime: 121
    filters:
      instance-state-name: [ "running" ]
      "tag:ansible-workshops": true
  register: ec2_node_info

在此任务中,我想强调两个参数。第一个是正常运行时间参数(在 amazon.aws 的 1.4.0 版本中添加),它只会返回运行时间超过该整数(以分钟为单位)的实例。对于此示例,它必须运行超过 121 分钟,或超过两个小时。我知道我的 CI 测试永远不应该超过两个小时。要么实例卡住了,要么我的自动化测试坏了,要么解除供应没有成功。

此处的另一个标签只是一个过滤器,以便我只返回属于我的自动化测试(相对于其他计划)的实例。在此示例中,它必须是 研讨会。现在您应该明白为什么我在开头需要“未标记”示例!如果根本没有标签,则整个运维任务将失败。因此,由于标签在公共云基础设施中的重要性,因此“无标签”用例与每个其他用例都重叠。

自动化自动化

因此,这种自动化很棒,但是手动运行 Playbook 只能节省您那么多时间。我继续使用 Ansible 工作流 功能一次性访问多个区域,然后对其进行计划,以便我的自动化作业每小时运行一次。

ansible workflow diagrams

右侧的每个矩形代表一个自动化 作业。同一列中的每个作业都将在我的 Ansible 自动化平台集群上并行运行。每个作业模板都设置为不同的区域。我还使用了 调查功能 使得从 Web UI 配置变得容易。

screenshot

在我的特定场景中,我在四个 AWS 区域(us-east-1、ap-northeast-1、ap-southeast-1 和 eu-central-1)中运行自动化测试。现在我的工作流已完成,安排我的工作流每小时运行一次非常简单。

screenshot

瞧!现在我已经在幕后实现了自动化测试,以确保没有孤立的实例正在运行。对于我的特定用例,这将节省大量资金,并强制在公共云使用方面形成一种责任文化,以便团队成员之间能够清晰透明地了解成本。