Amazon Web Services 指南

amazon.aws 集合包含许多用于控制 Amazon Web Services (AWS) 的模块和插件。本指南解释如何使用模块和清单脚本通过 Ansible 自动化您的 AWS 资源。

AWS 模块的要求很低。

所有模块都需要并针对最新版本的 botocore 和 boto3 进行测试。从 2.0 AWS 集合版本开始,集合的策略通常是支持在最近的主要集合修订版之前的 12 个月发布的这些库的版本。个别模块可能需要更新的库版本来支持特定功能,或者可能需要 boto 库,请查看模块文档以了解每个模块的最低要求版本。您必须在您的控制机器上安装 boto3 Python 模块。您可以从您的操作系统发行版或使用 python 包安装程序安装这些模块:pip install boto3

从两个集合的 2.0 版本开始,将根据 AWS 的 Python 2.7 支持终止 结束对 Python 2.7 的支持,并且将需要 Python 3.6 或更高版本。

虽然传统上 Ansible 会在其主机循环中针对多个远程计算机执行任务,但大多数云控制步骤都发生在您的本地计算机上,并参考要控制的区域。

在您的 playbook 步骤中,我们通常会为配置步骤使用以下模式

- hosts: localhost
  gather_facts: False
  tasks:
    - ...

身份验证

AWS 相关模块的身份验证是通过将您的访问密钥和秘密密钥指定为 ENV 变量或模块参数来处理的。

对于环境变量

export AWS_ACCESS_KEY_ID='AK123'
export AWS_SECRET_ACCESS_KEY='abc123'

对于将它们存储在 vars_file 中,最好使用 ansible-vault 加密

---
aws_access_key: "--REMOVED--"
aws_secret_key: "--REMOVED--"

请注意,如果您将凭据存储在 vars_file 中,您需要在每个 AWS 模块中引用它们。例如

- amazon.aws.ec2_instance:
    aws_access_key: "{{ aws_access_key }}"
    aws_secret_key: "{{ aws_secret_key }}"
    key_name: "example-ssh-key"
    image_id: "..."

或者可以使用 playbook 顶部的“module_defaults”指定它们。

# demo_setup.yml

- hosts: localhost
  module_defaults:
    group/aws:
      aws_access_key: '{{ aws_access_key }}'
      aws_secret_key: '{{ aws_secret_key }}'
      region: '{{ region }}'
  tasks:
    - amazon.aws.ec2_instance:
        key_name: "example-ssh-key"
        image_id: "..."

还可以从 凭据配置文件访问凭据。

- amazon.aws.ec2_instance:
    aws_profile: default
    key_name: "example-ssh-key"
    image_id: "..."

配置

ec2_instance 模块在 EC2 中配置和取消配置实例。

以下是创建分配了公共 IP 的实例的示例。

“name”参数将在实例上创建一个 “tag:Name”。可以使用 “tags” 参数指定其他标签。

# demo_setup.yml

- hosts: localhost
  gather_facts: False

  tasks:

    - name: Provision an EC2 instance with a public IP address
      amazon.aws.ec2_instance:
        name: Demo
        key_name: "example-ssh-key"
        vpc_subnet_id: subnet-5ca1ab1e
        instance_type: c5.large
        security_group: default
        network:
          assign_public_ip: true
        image_id: ami-123456
        tags:
          Environment: Testing
      register: result

已创建的实例的相关数据由 “register” 关键字保存在名为 “result” 的变量中。

由此,我们将使用 add_host 模块动态创建由这些新实例组成的主机组。这有助于在后续任务中立即对主机执行配置操作。

# demo_setup.yml

- hosts: localhost
  gather_facts: False

  tasks:

    - name: Provision an EC2 instance with a public IP address
      amazon.aws.ec2_instance:
        name: Demo
        key_name: "example-ssh-key"
        vpc_subnet_id: subnet-5ca1ab1e
        instance_type: c5.large
        security_group: default
        network:
          assign_public_ip: true
        image_id: ami-123456
        tags:
          Environment: Testing
      register: result

   - name: Add all instance public IPs to host group
     add_host: hostname={{ item.public_ip }} groups=ec2hosts
     loop: "{{ result.instances }}"

现在创建了主机组,同一配置 playbook 文件底部的第二个 play 现在可能有一些配置步骤

# demo_setup.yml

- name: Provision a set of instances
  hosts: localhost
  # ... AS ABOVE ...

- hosts: ec2hosts
  name: configuration play
  user: ec2-user
  gather_facts: true

  tasks:

     - name: Check NTP service
       service: name=ntpd state=started

安全组

AWS 上的安全组是有状态的。无论入站安全组规则如何,都允许从您的实例发出的请求的响应流入,反之亦然。如果您只想允许与 AWS S3 服务的流量,则需要获取一个区域的 AWS S3 的当前 IP 范围,并将其应用为出口规则。

- name: fetch raw ip ranges for aws s3
  set_fact:
    raw_s3_ranges: "{{ lookup('aws_service_ip_ranges', region='eu-central-1', service='S3', wantlist=True) }}"

- name: prepare list structure for ec2_group module
  set_fact:
    s3_ranges: "{{ s3_ranges | default([]) + [{'proto': 'all', 'cidr_ip': item, 'rule_desc': 'S3 Service IP range'}] }}"
  loop: "{{ raw_s3_ranges }}"

- name: set S3 IP ranges to egress rules
  ec2_group:
    name: aws_s3_ip_ranges
    description: allow outgoing traffic to aws S3 service
    region: eu-central-1
    state: present
    vpc_id: vpc-123456
    purge_rules: true
    purge_rules_egress: true
    rules: []
    rules_egress: "{{ s3_ranges }}"
    tags:
      Name: aws_s3_ip_ranges

主机清单

一旦您的节点启动,您可能需要再次与它们通信。对于云设置,最好不要在文本文件中维护云主机名的静态列表。相反,处理此问题的最佳方法是使用 aws_ec2 清单插件。请参阅 使用动态清单

该插件还将返回在 Ansible 外部创建的实例,并允许 Ansible 管理它们。

标签、组和变量

使用清单插件时,您可以根据 AWS 返回的元数据配置额外的清单结构。

例如,您可以使用 keyed_groups 从实例标签创建组

plugin: amazon.aws.aws_ec2
keyed_groups:
  - prefix: tag
    key: tags

然后,您可以在 play 中将所有具有值为 “webserver” 的 “class” 标签的实例作为目标

- hosts: tag_class_webserver
  tasks:
    - ping

您还可以将这些组与 “group_vars” 一起使用,以设置自动应用于匹配实例的变量。

使用 Ansible Pull 进行自动缩放

Amazon 自动缩放功能会根据负载自动增加或减少容量。云文档中还显示了一些 Ansible 模块,可以配置自动缩放策略。

当节点上线时,等待下一个 ansible 命令周期出现来配置该节点可能不够。

为了实现这一点,可以预先构建包含必要 ansible-pull 调用的机器镜像。Ansible-pull 是一个命令行工具,它从 Git 服务器获取 playbook 并在本地运行。

这种方法的一个挑战是,需要有一种集中的方式来存储自动扩展环境中 pull 命令的结果数据。因此,下一节中提供的自动扩展解决方案可能是一种更好的方法。

阅读 ansible-pull 以获取有关 pull 模式 playbook 的更多信息。

使用 Ansible Automation Platform 进行自动扩展

Ansible Automation Platform (AAP) 还包含一个非常好的用于自动扩展用例的功能。在这种模式下,一个简单的 curl 脚本可以调用一个定义的 URL,服务器将“拨出”到请求者并配置正在启动的实例。这可以成为重新配置临时节点的好方法。有关更多详细信息,请参阅安装和产品文档。

与 pull 模式相比,在 AAP 中使用回调的好处是,作业结果仍然集中记录,并且必须与远程主机共享的信息更少。

Ansible 与 CloudFormation(以及对比)

CloudFormation 是亚马逊的一项技术,用于将云堆栈定义为 JSON 或 YAML 文档。

在许多示例中,Ansible 模块提供了比 CloudFormation 更易于使用的界面,无需定义复杂的 JSON/YAML 文档。 这对于大多数用户来说是推荐的。

但是,对于已经决定使用 CloudFormation 的用户,有一个 Ansible 模块可以用来将 CloudFormation 模板应用于 Amazon。

当将 Ansible 与 CloudFormation 结合使用时,通常会将 Ansible 与 Packer 等工具一起使用来构建镜像,然后 CloudFormation 将启动这些镜像,或者一旦镜像上线,将通过用户数据调用 Ansible,或者将两者结合使用。

有关更多详细信息,请参阅 Ansible CloudFormation 模块中的示例。

使用 Ansible 构建 AWS 镜像

许多用户可能希望镜像启动时具有更完整的配置,而不是在实例化后完全配置它们。为此,可以使用许多程序中的一个与 Ansible playbook 一起定义和上传基本镜像,然后该镜像将获得自己的 AMI ID,以便与 ec2 模块或其他 Ansible AWS 模块(例如 ec2_asg 或 cloudformation 模块)一起使用。可能的工具包括 Packer、aminator 和 Ansible 的 ec2_ami 模块。

一般来说,我们发现大多数用户使用 Packer。

请参阅 Packer 文档中的 Ansible local Packer provisionerAnsible remote Packer provisioner

如果您现在不想采用 Packer,则在配置后使用 Ansible 配置基本镜像(如上所示)是可以接受的。

后续步骤:探索模块

Ansible 附带了许多用于配置各种 EC2 服务的模块。浏览模块文档的“Cloud”类别,以获取带有示例的完整列表。

另请参阅

集合索引

浏览现有集合、模块和插件

使用 playbook

playbook 简介

控制任务的运行位置:委托和本地操作

委托,对于使用负载均衡器、云和本地执行的步骤很有用。