Skip to content

Files

Latest commit

f87fb9e · Dec 29, 2021

History

History
825 lines (565 loc) · 35.6 KB

File metadata and controls

825 lines (565 loc) · 35.6 KB

七、使用 Ansible 部署和操作 AWS 网络资源

云是一项正在改变多个行业的技术。它对信息技术的整体基础设施、应用的部署方式以及应用的云架构产生了重大影响。

AWS 是主要的云供应商之一。它提供多种网络资源和服务,以构建可扩展且高度可用的网络设计,从而在 AWS 云上容纳应用。

采用云的主要支柱之一是自动化以及我们部署工作负载的速度。每个云供应商都有自己的自动化能力。在 AWS 的情况下,这是一种称为云信息的服务,它使我们能够使用基础架构作为代码(IaC) 来描述 AWS 基础架构,并在 AWS 云上部署基础架构。然而,与 CloudFormation 相比,Ansible 的优势在于它能够跨所有云供应商(包括 AWS)描述/部署资源。这使我们能够拥有一个一致的工具来在多云环境中部署我们的工作负载。

Ansible 提供了多个模块来与 AWS 云交互,以调配和控制其中的不同资源。

在本章中,我们将重点介绍 AWS 提供的基本网络服务的部署,这使我们能够在 AWS 中构建可扩展的网络设计。我们将在插图中使用以下示例 AWS 网络设计,并概述如何使用 Ansible 构建该网络:

本章涵盖的主要配方如下:

  • 安装 AWS 软件开发工具包
  • 建立 Ansible 库存
  • 向您的 AWS 帐户进行身份验证
  • 使用 Ansible 部署 VPCs
  • 使用 Ansible 部署子网
  • 使用 Ansible 部署 IGWs
  • 使用 Ansible 控制 VPC 内的路由
  • 使用 Ansible 部署网络 ACL
  • 使用 Ansible 进行部署验证
  • 使用 Ansible 停用 AWS 资源

技术要求

本章使用的 GitHub 代码可以在这里找到: https://GitHub . com/PacktPublishing/Network-Automation-Cookbook/tree/master/ch7 _ AWS

以下是本章所基于的软件版本:

  • 运行 CentOS 7 的 Ansible 机器
  • Ansible 2.9
  • Python 3.6.8

查看以下视频,了解《行动守则》: https://bit.ly/3ckoAFe

安装 AWS 软件开发工具包

在本食谱中,我们将概述如何安装 Ansible 开始与 AWS 编排系统交互所需的 Python 库。这一步是强制性的,因为这些 Python 库必须安装在 Ansible 控制机器上,以便所有 Ansible AWS 模块工作。

准备好

为了安装所需的 Python 库,您需要在机器上拥有 sudo 访问权限。此外,您需要安装python-pip包,因为我们将使用 pip 来安装所需的 Python 库。

怎么做...

  1. 我们可以测试任何 Ansible AWS 模块,以检查是否安装了所需的 Python 库:
$ ansible localhost -m aws_az_facts

localhost | FAILED! => {
 "changed": false,
 "msg": "boto3 required for this module"
 }
  1. 安装botoboto3包装,如下所示:
$ sudo pip3 install boto3 boto

它是如何工作的...

与 AWS 编排系统 API 交互的 Python SDK 库有botoboto3。这些 python 包必须存在于 Ansible 控制机器上,因为有了 Ansible,所有 AWS 模块都依赖于其中一个 python 包来运行。我们可以使用前面的第一步来检查该软件包是否已经安装在系统上,以便使用ansible命令运行任何 AWS 模块(例如,aws_az_facts)。如果boto3库不存在,我们将收到一条错误消息,通知我们没有安装boto3

我们可以使用 Python pip 程序使用pip3命令安装botoboto3包,这将安装包以及正确安装和运行包所需的所有依赖项。在这个阶段,我们拥有运行所有 Ansible AWS 模块所需的一切。

建立 Ansible 库存

在本食谱中,我们将概述如何构建 Ansible 清单,以描述我们将跨 AWS 公共云构建的基础架构网络设置。这是一个强制性步骤,以便在我们将部署基础架构的所有地区定义我们的所有虚拟专用网络。

怎么做...

  1. 新建一个ch7_aws文件夹,在里面创建一个hosts文件,如下图:
$ cat hosts

[us]
 us_prod_vpc

[eu]
 eu_prod_vpc

[prod_vpcs]
 us_prod_vpc
 eu_prod_vpc
  1. ch7_aws内创建ansible.cfg文件,内容如下所示:
$ cat ansible.cfg

[defaults]
 inventory=hosts
 vault_password_file=~/.ansible_vault_passwd
 gathering=explicit
 transport=local
 retry_files_enabled=False
 action_warnings=False

它是如何工作的...

我们创建了主机的 Ansible 清单文件,现在我们需要将我们的 VPC 声明为清单中的节点,类似于我们定义网络节点的方式。唯一的例外是 VPC 没有管理 IP 地址,所以我们没有为那些 VPC 指定ansible_host参数。

我们需要在库存文件中创建以下组:

  • 一个美国组织,将美国所有的虚拟专业人员组织起来
  • 一个欧盟组织,将欧洲所有的虚拟专业人员组织起来
  • prod_vpcs,将我们所有的生产 VPC 分组

我们还需要定义ansible.cfg文件,其中包含我们在前面所有食谱中使用的所有配置选项。我们需要指定保管库密码文件,其中包括我们将用来加密所有敏感信息的加密密码。

向您的 AWS 帐户进行身份验证

在本食谱中,我们将概述如何创建以编程方式向我们的 AWS 帐户进行身份验证所需的凭据,以及如何使用 Ansible Vault 保护这些凭据。这是一个强制性的步骤,以便能够在以下所有配方中运行任何 Ansible 模块。

准备好

Ansible 控制器必须能够访问互联网,并且 Ansible 库存必须按照前面的配方进行设置。此外,执行这些步骤的用户必须在 AWS 帐户上拥有所需的访问权限,才能创建新用户。

怎么做...

  1. 使用具有编程访问权限的 IAM 创建新用户,如下所示:

  1. 为该新用户分配正确的 IAM 策略,这允许他们创建它应该管理的所有网络资源(为简单起见,也可以是完全访问策略):

  1. 创建完用户后,在最后一页,添加用户向导会在.csv文件中显示访问密钥 ID 和机密访问密钥以供下载。这些参数将用于向该帐户的 AWS 应用编程接口进行身份验证:

  1. 使用 Ansible Vault 加密访问密钥标识和机密访问密钥,如下所示:
$ ansible-vault encrypt_string <ACCESS_KEY_ID> --name aws_access_key

$ ansible-vault encrypt_string <SECRET_ACCESS_KEY> --name aws_secret_key_id

  1. ch7_aws内创建group_vars,在group_vars内创建all.yml文件。使用上一步中使用ansible-vault加密的密码填充all.yml文件:
ansible_connection: local

aws_access_key: !vault |
 $ANSIBLE_VAULT;1.1;AES256
 37623631653336633662666138353639653365323637323665353731386661343164393664333434
 3430306562623532366137663835636138613633633835660a656235363130303035383965663464
 39326130613433643861653933623032393735376466333861326537646563643736356632303435
 6631326531666461310a353461396431303765393830636432363430323438373635383132336462
 37356163643662623633643965386465656563613533613938666232343063396261

aws_secret_key_id: !vault |
 $ANSIBLE_VAULT;1.1;AES256
 38353165666437393262303035646531666139623963643066623066346633393964633438626539
 6266623937343036376266373463623266316462613139660a336664353564623531393332613433
 34336363393962666633363630393631376135656666623862373966643935386665363733376133
 6236326462326566320a653364336464363963623136363362666632396133613863376166343135
 37373839316430643337353564373062333232656136393564613132333065316638383739326238
 3530386534303033636463626664346234653136353534633265

它是如何工作的...

第一步是确保用户帐户可以通过应用编程接口编程访问 AWS 控制台。为了让用户向 AWS 应用编程接口进行身份验证,必须为用户分配两个密码,这两个密码由 AWS 在用户创建期间或用户请求更改其密码时生成。这两个密码是访问密钥 ID 和机密访问密钥。这两个密码只有在创建时才可见和可用,AWS 以您可以下载的 CSV 文件形式提供它们。此外,我们需要确保该用户拥有创建必要资源(VPC、子网、路由表等)的正确 IAM 权限。因此,在我们的示例中,这个新用户被分配了管理员策略,这使他们可以完全访问 AWS 帐户来创建任何资源(如 EC2 实例、VPC、子网等)。如果用户已经拥有编程访问权限和所需的 IAM 权限,我们概述的创建新用户的步骤是可选的;为了完整起见,我们刚刚演示了这一点。

由于我们在 CSV 文件中有 AWS 为该帐户生成的明文机密,因此我们可以获取这些密码,并使用 Ansible Vault 对其进行加密,然后将其存储在group_vars/all.yml文件中,以便我们在为 VPCs 创建所有资源时可以使用这些凭据。通过ansible-vault encrypt_string命令加密后,我们将这些机密存储到aws_access_keyaws_secret_key_id参数中。Ansible Vault 使用我们在ansible.cfg文件中声明的 Vault 密码文件,并且该文件具有我们将用于加密所有这些密码的加密密码。

在下一个食谱中,我们将概述如何在创建 VPC 时使用我们创建的这些加密变量向 AWS 控制台进行身份验证。

使用 Ansible 部署 VPCs

在本食谱中,我们将概述如何使用 Ansible 部署 AWS VPCs。AWS 虚拟专用网络是 AWS 中的基础网络结构,可以将其视为管理员在其 AWS 帐户中创建的云中的虚拟数据中心。为了开始在 AWS 内建立任何其他基础设施相关服务,必须首先创建一个 VPC。我们将概述如何描述所有必需的 VPC,以及如何使用 Ansible 自动创建它们。

准备好

要连接到 AWS API,AWS 控制机器必须连接到互联网。AWS 帐户也必须准备好,如前一个配方中所述,并带有所需的 AWS 凭据。

怎么做...

  1. group_vars目录下创建us.ymleu.yml文件,并用 AWS 区域名称定义填充这些文件,如下所示:
$ cat group_vars/eu.yml
 aws_region: eu-west-1

$ cat group_vars/eu.yml
 aws_region: us-east-1
  1. host_vars目录下创建eu_prod_vpc.ymlus_prod_vpc.yml文件,并用 VPC 参数填充它们,如下所示:
$ cat host_vars/eu_prod_vpc.yml

vpc_name: EU_Prod_Public_VPC
vpc_cidr: 10.3.0.0/16
vpc_tags:
 role: prod
 region: eu EU $ cat host_vars/us_prod_vpc.yml
vpc_name: US_Prod_Public_VPC
vpc_cidr: 10.1.0.0/16
vpc_tags:
 role: prod
 region: US
  1. 创建一个新的行动手册pb_aws_net_build.yml,并填充它,如下所示:
$ cat pb_aws_net_build.yml

- name: Create all AWS Networks
 hosts: prod_vpcs
 environment:
 AWS_ACCESS_KEY: "{{ aws_access_key }}"
 AWS_SECRET_KEY: "{{ aws_secret_key_id }}"
 tasks:
 - name: Create New VPC
 ec2_vpc_net:
 cidr_block: "{{ vpc_cidr }}"
 region: "{{ aws_region }}"
 name: "{{ vpc_name }}"
 state: "{{ vpc_state | default('present') }}"
 tags: "{{ vpc_tags }}"
 register: create_vpc

它是如何工作的...

AWS 的业务遍及全球,它将其在世界各地的基础设施的各个部分划分为区域。AWS 区域是世界某一地区 AWS 设施的集合,AWS 中的每个区域都被认为是一个独立的故障域,有自己的编排和管理系统。因此,当我们创建一个 VPC 时,我们需要指定我们将把这个 VPC 部署到哪个地区,所以我们需要在我们的 Ansible 变量中描述这个信息。在我们的案例中,我们将我们在美国的所有 VPC 的 AWS 区域指定为us-east-1,将我们在欧盟的所有 VPC 指定为eu-west-1。这是通过在eu.ymlus.yml文件下以及group_vars目录下定义aws_region变量来实现的。

AWS 区域的这种逻辑对于 AWS 中的大多数特定于区域的服务至关重要,我们将构建的所有网络结构都是特定于区域的。对于几乎所有的 AWS Ansible 模块,我们需要指定 AWS 区域,以便对指定区域中的正确 API 端点发起正确的 API 调用。这是因为每个地区的 API 端点都有不同的 FQDN。有关所有地区 AWS 中所有服务的 AWS 端点的更多信息,请使用以下链接:

https://docs.aws.amazon.com/general/latest/gr/rande.html

我们需要在host_vars目录下声明每个 VPC 的变量,并为我们的每个 VPC 创建一个 YAML 文件。我们需要指定 VPC 的名称、前缀以及应该分配给 VPC 的标签。最后,我们需要创建 Ansible 行动手册来构建我们的基础架构,并在行动手册中使用一个新选项,即环境。该选项在剧本执行期间创建临时环境变量(AWS_ACCESS_KEYAWS_SECRET_KEY)。这些环境变量的值设置为与我们在group_vars/all.yml文件中定义的aws_access_keyaws_secret_key_id变量相同的值。这使得包含在这些环境变量中的值在剧本执行期间出现,以便每个任务中的 AWS 模块可以使用这些信息来验证所有的 API 调用。

我们可以使用ec2_vpc_net Ansible 模块在 AWS 云上创建 VPCs,并且我们可以使用region属性指定将在其中部署 VPC 的 AWS 区域。我们需要定义它的 IP 前缀、名称和任何相关的标签。所有这些信息都来源于我们在这个 VPC 的host_vars文件中定义的变量。

当模块创建 VPC 时,它会返回创建的 VPC 的所有信息,我们可以将这些信息保存在一个名为create_vpc的新变量中。

以下是 VPC 创建任务返回的数据片段:

"create_vpc": {
 "vpc": {
 "cidr_block": "10.1.0.0/16",

< -- Output Omitted for brevity -->

 "dhcp_options_id": "dopt-b983c8c2",
 "id": "vpc-0d179be0eb66847f3",
 "instance_tenancy": "default",
 "is_default": false,
 "owner_id": "955645556619",
 "state": "available",
 "tags": {
 "Name": "US_Prod_Public_VPC",
 "region": "US",
 "role": "prod"
 }
 }
}

以下截图概述了从控制台在 AWS 上创建的 VPC:

请参见

有关ec2_vpc_net模块和该模块中其他可用参数的更多信息,请使用以下网址:

https://docs . ansi ble . com/ansi ble/latest/modules/ec2 _ VPC _ net _ module . html

使用 Ansible 部署子网

在本食谱中,我们将概述如何使用 Ansible 在我们的 AWS VPCs 中部署子网。子网是 AWS 中的一个基本网络结构,目的是为部署在 AWS 云上的应用提供更大的弹性。这种额外的弹性是通过子网可以映射到不同的可用性区域来实现的。使用这种逻辑,我们可以通过将资源分散到不同的可用性区域来为部署提供高可用性。

准备好

Ansible 控制机器必须具有互联网可达性,并且必须已经按照之前的配方配置了虚拟专用网络。

怎么做...

  1. 用子网的数据更新host_vars/eu_prod_vpc.yml文件,如下图所示。对host_vars/us_prod_vpc.yml也进行同样的操作,以包括子网的所有数据:
$ cat host_vars/eu_prod_vpc.yml

< -- Output Omitted for brevity -->

vpc_subnets:
 eu-prod-public-a:
 cidr: 10.3.1.0/24
 az: "{{ aws_region }}a"
 tags: "{{ vpc_tags }}"
 public: true

 eu-prod-public-b:
 cidr: 10.3.2.0/24
 az: "{{ aws_region}}b"
 tags: "{{ vpc_tags }}"
 public: true
  1. 更新pb_aws_net_build.yml行动手册,并用新任务填充它以构建子网:

- name: "set fact: VPC ID"
 set_fact:
 vpc_id: "{{ create_vpc.vpc.id }}"

- name: create VPC subnets
 ec2_vpc_subnet:
 region: "{{ aws_region }}"
 vpc_id: "{{ vpc_id }}"
 cidr: "{{ item.value.cidr }}"
 az: "{{ item.value.az }}"
 tags: "{{item.value.tags | combine({ 'Name': item.key })}}"
 with_dict: "{{ vpc_subnets }}"
 register: create_vpc_subnets

它是如何工作的...

可用性区域是为 AWS 区域内的物理基础架构提供弹性的构造。为了高效地使用可用性区域,我们需要将 VPC 内的基础架构映射到一个区域内的不同可用性区域。这是使用 AWS 子网完成的。

在我们的示例部署中,我们使用分布在两个可用性区域的两个子网,以便为我们的网络设置提供高可用性。我们使用vpc_subnets变量声明将在每个 VPC 部署的子网。这些变量包括我们将在每个子网中使用的 CIDR(必须是 VPC CIDR 的子集)、我们希望该子网附加到的可用性区域,以及我们希望分配给该子网的标签。我们使用 AWS 区域加上后缀(abc等)来构建可用性区域的名称。这是 AWS 用来命名区域内可用性区域的命名约定。

为了在 AWS 中创建子网,我们需要将一个子网与其父 VPC 相关联。为此,我们需要在 API 调用期间指定vpc-id参数来创建子网。该vpc-id是 AWS 在其创建期间分配给 VPC 的唯一标识符。我们从创建 VPC 的 VPC 创建任务中获得这个值,并将这个任务的输出保存到vpc_create变量中。我们可以使用这个变量来检索 VPC 的标识,并使用set_fact模块将其分配给vpc-id变量。

最后,我们可以使用ec2_vpc_subnet模块构建子网,在每个 VPC 内创建必要的子网,并在vpc_subnets数据结构上循环,以构建所有需要的子网。

以下屏幕截图显示了在我们的US_Prod VPC 的 AWS 云上正确配置的子网:

以下是分配给该子网的标签:

请参见

有关ec2_vpc_subnet模块和该模块中其他可用参数的更多信息,请使用以下网址:

https://docs . ansi ble . com/ansi ble/latest/modules/ec2 _ VPC _ subnet _ module . html # ec2-VPC-subnet-module

使用 Ansible 部署 IGWs

在本食谱中,我们将概述如何使用 Ansible 将互联网网关 ( IGWs )部署到我们的 AWS VPCs。IGWs 是我们从 VPC 到互联网的出口点,以便到达公共外部目的地。由于我们正在建设面向公众的服务,我们需要从我们的 VPC 有互联网可达性。这是由 AWS 云中的 IGW 构造完成的。

准备好

Ansible 控制机器必须具有互联网可达性,并且根据之前的配方,必须已经配置了虚拟专用网络。

怎么做...

  1. 用 IGW 数据更新eu_prod_vpc.yml文件,如下图所示,对us_prod_vpc.yml进行同样的操作:
$ cat host_vars/eu_prod_vpc.yml

< -- Output Omitted for brevity -->

igw_name: eu_prod_igw

$ cat host_vars/eu_prod_vpc.yml

< -- Output Omitted for brevity -->

igw_name: us_prod_igw
  1. 更新pb_aws_net_build.yml行动手册,并用构建 IGW 节点的新任务填充它:

- name: Create IGW
 ec2_vpc_igw:
 region: "{{ aws_region }}"
 vpc_id: "{{ vpc_id }}"
 state: present
 tags: "{{ vpc_tags | combine({'Name': igw_name}) }}"
 register: vpc_igw_create

- name: Extract VPC IGW ID
 set_fact:
 igw_id: "{{ vpc_igw_create.gateway_id }}"

它是如何工作的...

IGW 网络建设是我们从 VPC 出发,通过互联网到达公共目的地的出口点。IGW 附属于 VPC,它为位于 VPC 的任何资源(如 EC2 或 RDS 实例)提供互联网连接。为了创建一个 IGW,我们需要指定这个 IGW 将附属的 VPC。所以,我们需要 VPC 的身份证。

正如我们在前面的食谱中所讨论的,当我们创建 VPC 时,我们得到了 VPC 标识,我们可以使用一个单独的任务保存这个变量。我们可以在 IGW 的创作中使用这个变量的值。我们可以使用ec2_vpc_igw模块创建 IGW,并指定我们希望 IGW 部署到的区域。我们还可以指定 IGW 将附加到的 VPC ID。最后,我们可以指定将分配给 IGW 节点的标签。IGW 标签是可选的,但是在使用自动化部署时,它们非常重要,因为它们允许我们引用已经创建的对象。当我们在下面的食谱中讨论部署验证和事实收集时,我们将概述标签的使用。

当我们部署一个新的 IGW 时,ec2_vpc_igw模块返回在 AWS 内部提供的 IGW 参数。一个特别重要的参数是igw-id。此参数唯一标识已调配的 IGW 节点,当我们在与此 IGW 节点相关的任何操作中引用 IGW 时,我们必须使用它。

以下是由ec2_vpc_igw返回的 IGW 参数的片段,我们在us_prod_vpc中的 IGW 节点的vpc_igw_create变量中捕捉到了这些参数:

ok: [us_prod_vpc] => {
 "vpc_igw_create": {
 "changed": true,
 "failed": false,
 "gateway_id": "igw-05d3e4c664486790b",
 "tags": {
 "Name": "us_prod_igw",
 "region": "US",
 "role": "prod"
 },
 "vpc_id": "vpc-0abc32281330c9bc6"
 }
}

在前一个任务中,我们捕获了ec2_vpc_igw返回的gateway-id变量,并将其存储在一个名为igw_id的新变量中,我们将在后续任务中引用 IGW 节点时使用该变量。

以下屏幕截图概述了已调配并连接到 VPC 的 IGW 节点:

请参见

有关ec2_igw_vpc模块和该模块中其他可用参数的更多信息,请使用以下网址:

https://docs . ansi ble . com/ansi ble/latest/modules/ec2 _ VPC _ igw _ module . html # ec2-VPC-igw-module

使用 Ansible 控制 VPC 内的路由

在本菜谱中,我们将概述如何调整 AWS VPC 内部的路由,以便控制 VPC 内部子网内的流量转发。通过控制 VPC 的路由,我们可以定制 VPC 的设计,以及如何在 VPC 转发流量,以及如何从 VPC 到达外部目的地。

准备好

Ansible 控制机器必须具有互联网可达性,并且必须已经按照之前的配方配置了虚拟专用网络。

怎么做...

  1. 用路由表数据更新eu_prod_vpc.yml文件,如下所示,对us_prod_vpc.yml也是如此:
$ cat host_vars/eu_prod_vpc.yml

< -- Output Omitted for brevity -->

route_table:
 tags:
 Name: eu_public_rt
 igw:
 - dest: 0.0.0.0/0
 gateway_id: "{{ igw_id }}"
 public:
 - eu-prod-public-a
 - eu-prod-public-b
  1. 更新pb_aws_net_build.yml行动手册,并使用以下任务填充它,以便将路由表附加到我们创建的 VPC:
- name: Get Default VPC Route Table
 ec2_vpc_route_table_facts:
 region: "{{ aws_region }}"
 filters:
 vpc-id: "{{ vpc_id }}"
 register: vpc_route_table_facts
 tags: rt

- name: Extract Route Table IDs
 set_fact:
 rt_id: "{{vpc_route_table_facts.route_tables[0].id }}"
 tags: rt
  1. 更新行动手册,并使用以下任务填充它,以便用所需的路由更新路由表:
- name: Update Default VPC Route Table
 ec2_vpc_route_table :
 region: "{{ aws_region }}"
 vpc_id: "{{ vpc_id }}"
 route_table_id: "{{ rt_id }}"
 routes: "{{ route_table.igw }}"
 subnets: "{{ route_table.public }}"
 lookup: id
 state: present
 tags: "{{ vpc_tags | combine(route_table.tags) }}"

它是如何工作的...

到目前为止,我们已经成功建立了 VPC、子网和 IGW。但是,尽管 IGW 节点已连接到互联网并连接到 VPC,但 VPC 内的所有流量都不会使用 IGW 节点,因为与 VPC 相关联的路由表仍未更新,也没有指向 IGW 的路由。

以下是更改路由表前us_prod_vpc默认路由表的片段:

AWS VPCs have a default route table that is assigned to the VPC and to all the subnets that don't have a specific route table associated with them. So, by default, all the subnets within the VPC are associated with the VPC's default route table.

以下截图显示了在us_prod_vpc内创建的子网与默认路由表相关联:

在我们为每个虚拟专用网络声明的 VPC 定义中,我们包含了一个名为route_table的新数据结构,它包含了我们为 VPC 调整路由表以及将所有子网与之关联所需的所有信息。

我们将在本食谱中执行的第一个任务是获取与我们创建的 VPC 相关联的默认路由表的 ID。我们将使用ec2_vpc_route_table_facts模块获取路由表的事实,并提供 VPC 标识来唯一识别 VPC。我们可以在新变量rt_id中存储默认路由表的标识。

以下片段概述了我们从ec2_vpnc_facts模块中检索到的路由表事实:

ok: [us_prod_vpc] => {
 "vpc_route_table_facts": {
 "route_tables": [
 {
 < -- Output Omitted for brevity --> ],
 "id": "rtb-0b6669ba5fd9eb9c8",
 "routes": [
 {
 "destination_cidr_block": "10.1.0.0/16",
 "gateway_id": "local",

< -- Output Omitted for brevity -->

 }
 ],
 "tags": {},
 "vpc_id": "vpc-005b1dcb981791d86"
 }
 ]
 }
} 

一旦我们有了与 VPC 相关的路由表的标识,我们就可以使用ec2_vpc_route_table模块来调整与 VPC 相关的默认路由表的路由表。我们必须提供 VPC 和路由表标识,以唯一标识我们要修改的确切路由表。我们可以指定要插入路由表的路由,以及要与该路由表关联的子网。我们可以注入默认路线,并使用igw-id将其指向我们在之前的食谱中创建的 IGW。

以下屏幕截图概述了调整路由后的 VPC 路由表:

以下屏幕截图概述了我们在 VPC 的两个子网现在如何与此默认路由表相关联:

请参见

有关与 AWS VPC 和相关模块的路由表交互的多个模块的更多信息,请使用以下链接:

使用 Ansible 部署网络 ACL

在本食谱中,我们将概述如何在 AWS 上部署网络 ACL(NACLs)。NACLs 是 AWS 中可用的安全解决方案之一,用于保护部署在 AWS 云中的计算机资源。在这个食谱中,我们将概述如何在 AWS 中描述和自动化氯化钠的部署。

准备好

Ansible 控制机器必须具有互联网可达性才能到达 AWS 应用编程接口端点,并且必须已经按照之前的方法配置了 VPC 和子网。

怎么做...

  1. 用 NACL 定义数据更新eu_prod_vpc.yml文件,如下所示,并对us_prod_vpc.yml进行同样的操作:
$ cat host_vars/eu_prod_vpc.yml

< -- Output Omitted for brevity -->

network_acls:
 - name: EU_Prod_ACLs
 subnets: "{{ vpc_subnets.keys() | list }}"
 ingress_rules:
 - [100,'tcp','allow','0.0.0.0/0',null,null,80,80]
 - [200,'tcp','allow','0.0.0.0/0',null,null,443,443]
  1. 更新pb_aws_net_build.yml行动手册,并使用以下任务填充该手册,以创建 NACLs:
- name: Create Network ACLs
 ec2_vpc_nacl:
 region: "{{ aws_region }}"
 vpc_id: "{{ vpc_id }}"
 name: "{{ item.name }}"
 subnets: "{{ item.subnets }}"
 ingress: "{{ item.ingress_rules }}"
 tags: "{{ vpc_tags | combine({'Name':item.name}) }}"
 loop: "{{ network_acls }}"

它是如何工作的...

AWS NACLs 是无状态 ACL,能够根据 L3 和 L4 IP 地址信息允许或拒绝 IP 流量。它们在子网级别实施,并与子网相关联,以保护子网中提供的所有资源。它们可以阻止入口(进入子网的流量)或出口(离开子网的流量)方向的流量。NACL 中的规则根据规则编号进行处理,因此第一个匹配规则将应用于流量。

所有子网都连接了默认的 NACL,AWS 为默认的 NACL 设置了以下规则:

  • 进入时,允许所有流量。以下屏幕截图概述了应用于默认 NACL 的规则:

  • 在出口处,允许所有交通。以下屏幕截图概述了应用于默认 NACL 的规则:

在我们的示例设置中,我们将在所有子网中应用一个实施以下安全策略的 NACL:

  • 必须允许所有到端口80443的 TCP 流量。
  • 任何其他流量都应该被丢弃。

By default, there is a DENY rule at the end of any NACL that drops all traffic.

我们定义了network_acls数据结构,其中包含 NACL 定义和所有必需字段,以便在欧盟和美国地区的所有子网中设置所需的 NaCl。在这个数据结构中,我们需要定义以下参数:

  • Name:这是 NACL 的名字,它是一个标识符。
  • Subnets:这定义了应该与这个 NACL 相关联的子网。我们使用vpc_subnets定义中的数据来构建这个列表。
  • Ingress_rules:这定义了在进入方向作为 NACL 的一部分应该应用的所有规则。
  • Engress_rules:这定义了在出口方向作为 NACL 的一部分应该应用的所有规则。

我们可以在我们的行动手册中创建一个新任务,使用ec2_net_nacl来配置 NACL,并将其附加到我们的所有子网。

以下截图概述了部署在EU_prod VPC 的新 NACL:

以下截图概述了与我们在 VPC 的 NACL 相关的子网:

请参见

有关ec2_net_naclAnsible 模块和该模块支持的不同参数的更多信息,请参考以下网址:

https://docs . ansi ble . com/ansi ble/latest/modules/ec2 _ VPC _ NaCl _ module . html

使用 Ansible 进行部署验证

在本食谱中,我们将概述如何收集 AWS 中不同网络组件的运行状态,例如 VPCs 和子网,以及如何检查我们的部署是否按照我们的设计实施。

准备好

Ansible 控制机器必须具有互联网可达性,并且我们在前面的配方中概述的所有网络组件都应该到位。

怎么做...

  1. 创建新的pb_vpc_validate.yml行动手册,并在其中填充验证 VPC 构建的任务:
$ cat pb_vpc_validate.yml

- name: Validate VPC Build
 hosts: all
 gather_facts: no
 environment:
 AWS_ACCESS_KEY: "{{ aws_access_key }}"
 AWS_SECRET_KEY: "{{ aws_secret_key_id }}"
 AWS_REGION: "{{ aws_region }}"
 tasks:
 - name: Get VPC facts
 ec2_vpc_net_facts:
 filters:
 "tag:Name": "{{ vpc_name }}"
 register: vpc_facts

    - name: Validate VPC Info
 assert:
 that:
 - vpc_facts.vpcs[0].cidr_block == vpc_cidr
 - vpc_facts.vpcs[0].tags.Name == vpc_name
 when: vpc_facts.vpcs != []
  1. 使用以下任务更新行动手册,以收集 AWS 子网的事实:
 - name: Extract VPC ID
 set_fact:
 vpc_id: "{{ vpc_facts.vpcs[0].id }}"

 - name: Get Subnet facts
 ec2_vpc_subnet_facts:
 filters:
 vpc-id: "{{ vpc_id }}"
 register: vpc_subnet_facts
 tags: subnet
  1. 使用以下任务更新行动手册,以验证 AWS 子网的状态:
 - name: Validate VPC Subnets Info
 assert:
 that:
 - vpc_subnet_facts.subnets |
 selectattr('tags.Name','equalto',item.key) |
 map(attribute='cidr_block') |
 list | first == item.value.cidr

 - vpc_subnet_facts.subnets |
 selectattr('tags.Name','equalto',item.key) |
 map(attribute='availability_zone') |
 list | first == item.value.az

 with_dict: "{{ vpc_subnets }}"

它是如何工作的...

我们可以使用ec2_vpc_net_factsec2_vpc_subnet_facts Ansible 模块创建一个新的剧本来收集 VPC 和子网的事实。我们可以收集从这些模块返回的数据,并使用assert模块验证状态,如下所示:

  1. VPS:t0]

    • 检查分配给 VPC 的名称是否符合我们的设计。
    • 检查分配给 VPC 的 CIDR 区块是否按照我们的设计部署。
  2. 子网:

    • 检查分配给子网的 CIDR 配置是否正确。
    • 检查子网是否设置在正确的可用性区域。

我们可以通过将事实模块返回的操作状态与我们在group_varshost_vars变量中为每个 VPC 定义的元数据进行比较,来执行前面的所有验证。

In the ec2_vpc_net_facts task, we used the filters parameter to select our VPC based only on its Name tag. By default, this module will return the facts for all of the VPCs within this region.

In the ec2_vpc_subnet_facts task, we used the filters parameter to only retrieve the subnets data for our VPC, since by default this module will return all the subnets' facts for all of our VPCs within the region.

请参见

有关 AWS 中不同网络资源的事实收集模块的更多信息,请使用以下链接:

使用 Ansible 停用 AWS 上的资源

在本食谱中,我们将概述如何停用 AWS 内的完整网络以及所有相关的网络资源。这概述了我们如何使用 Ansible 通过简单的剧本执行轻松地在云上构建和拆除资源。

准备好

Ansible 控制机器必须具有互联网可达性,并且我们在前面的配方中概述的所有网络组件都应该到位。

怎么做...

  1. 创建新的pb_delete_vpc.yml行动手册,包括以下任务,为 VPC 收集事实:
$ cat pb_delete_vpc.yml

- name: Delete all VPC resources
 hosts: all
 gather_facts: no
 environment:
 AWS_ACCESS_KEY: "{{ aws_access_key }}"
 AWS_SECRET_KEY: "{{ aws_secret_key_id }}"
 AWS_REGION: "{{ aws_region }}"
 tasks:
 - name: Get VPC facts
 ec2_vpc_net_facts:
 filters:
 "tag:Name": "{{ vpc_name }}"
 register: vpc_facts

 - name: Extract VPC ID
 set_fact:
 vpc_id: "{{ vpc_facts.vpcs[0].id }}"
  1. 使用以下任务更新行动手册,删除 VPC 内的所有子网和 IGW 节点:
 - name: Start Delete VPC Resources
 block:
 - name: Delete Subnets
 ec2_vpc_subnet:
 cidr: "{{ item.value.cidr }}"
 vpc_id: "{{ vpc_id }}"
 state: absent
 with_dict: "{{ vpc_subnets }}" - name: Delete IGW
 ec2_vpc_igw:
 vpc_id: "{{ vpc_id }}"
 state: absent
  1. 使用以下任务更新行动手册,以删除所有 NACLs:
 - name: Delete NACLs
 ec2_vpc_nacl:
 name: "{{ item.name }}"
 vpc_id: "{{ vpc_id }}"
 state: absent
 loop: "{{ network_acls }}"
  1. 更新行动手册,完成移除所有 VPC 的最终任务:
 - name: Delete VPC
 ec2_vpc_net:
 cidr_block: "{{ vpc_cidr }}"
 name: "{{ vpc_name }}"
 state: absent
 when: vpc_id is defined

它是如何工作的...

我们可以从 VPC 的一系列事实开始我们的新剧本,为我们部署的 VPC 获得 VPC 身份。一旦我们有了这些信息,我们就可以开始删除资源了。然而,我们删除资源的顺序很重要。我们需要先移除所有相关资源,因此我们必须先移除子网,然后才能移除 VPC。因此,例如,如果有 EC2 实例连接到子网,我们必须先删除这些 EC2 实例,然后才能删除子网。因此,在我们的例子中,我们需要移除子网,然后移除 IGW 节点,最后移除 VPC。

在所有这些任务中,我们使用的模块与我们在前面的食谱中概述的完全相同。唯一的变化是,我们将该州设置为不存在,并提供所需的 VPC 身份证,以唯一标识我们需要从中删除所需资源的 VPC。

最后,当我们开始移除 VPC 内的资源时,我们首先验证是否存在 VPC 标识。如果资源已经被删除,并且我们再次运行剧本,删除步骤将被跳过,因为facts任务将不会检索到 VPC 标识。