Как развернуть ресурсы AWS с помощью Boto3, Terraform и CloudFormation

Давайте поговорим обо всех трех, прежде чем мы начнем:

Boto3 (AWS SDK для Python)

Вы используете AWS SDK для Python (Boto3) для создания, настройки и управления сервисами AWS, такими как Amazon Elastic Compute Cloud (Amazon EC2) и Amazon Simple Storage Service (Amazon S3). SDK предоставляет объектно-ориентированный API, а также низкоуровневый доступ к сервисам AWS.

Terraform

Terraform - это инфраструктура с открытым исходным кодом в виде инструмента кода, который обеспечивает последовательный рабочий процесс CLI для управления сотнями облачных сервисов, специфичных для поставщиков. Terraform кодирует облачные API в декларативные файлы конфигурации.

Советы:

  • Обеспечивает бесперебойную работу инфраструктуры
  • С легкостью обновляет инфраструктуру
  • Без проблем разрушает инфраструктуру
  • Он проверяет ошибки кода одним нажатием кнопки
  • Он планирует инфраструктуры перед развертыванием.
  • Он отслеживает записи из файла состояния

CloudFormation

AWS CloudFormation дает вам простой способ смоделировать набор связанных ресурсов AWS и сторонних поставщиков, быстро и согласованно предоставить их и управлять ими на протяжении всего их жизненного цикла, рассматривая инфраструктуру как код. Шаблон CloudFormation описывает желаемые ресурсы и их зависимости, поэтому вы можете запускать и настраивать их вместе как стек. Вы можете использовать шаблон для создания, обновления и удаления всего стека как единого целого так часто, как вам нужно, вместо того, чтобы управлять ресурсами по отдельности. Вы можете управлять стеками и выделять их для нескольких учетных записей AWS и регионов AWS.

Примечание. CloudFormation - это проприетарный инструмент IAC AWS, другими словами, собственный шаблон AWS, что означает, что его можно использовать только на платформе AWS. Так что это может не подойти вам, если AWS не является вашим поставщиком облака.

Terraform + CloudFormation

Наконец, с AWS мы можем использовать CloudFormation. Вместе с другими поставщиками облачных услуг мы можем воспользоваться другими ресурсами. В любом случае, terraform можно рассматривать как центр IaC для всех наших облачных проектов, мы можем

  • беспрепятственное предоставление инфраструктуры
  • легко обновлять инфраструктуру
  • без проблем разрушить инфраструктуру
  • проверить коды ошибок одним нажатием кнопки
  • спланировать инфраструктуры перед развертыванием
  • отслеживать записи из файла состояния

Выполнение всего вышеперечисленного с использованием Terraform и создание инфраструктуры вместе с собственным инструментом IaC от любых конкретных почти всех облачных провайдеров!

Напоминание:. Это должно быть частью 1 проекта, поскольку я углублюсь в AWS CDK с Terraform и попытаюсь подготовить VPC с помощью CDK с Terraform.

Вот варианты, которые я хотел бы затронуть в этом проекте.

Предпосылки

  • Учетная запись AWS - с пользователем без полномочий root (с учетом безопасности)
  • Ваш локальный компьютер Windows 10 с установленным Python3 или просто найдите и установите Python из Магазина Windows.
  • Установите Visual Studio Code здесь.
  • AWSCLI установил ссылку здесь.
  • Установите Terraform здесь

Давайте начнем работать над ними по очереди.

Создание пользователя без полномочий root

В соответствии с передовой практикой AWS пользователю root не рекомендуется выполнять повседневные задачи, даже административные. Пользователь root, скорее, используется для создания вашего первого пользователя, групп и ролей IAM. Затем вам нужно надежно заблокировать учетные данные пользователя root и использовать их для выполнения лишь нескольких задач управления учетными записями и службами.

Примечание. Если вы хотите узнать больше о том, почему мы не должны использовать пользователя root для операций, и подробнее об учетной записи AWS, прочтите здесь.

  • Во-вторых, создайте пользователя под IAM.
  • Перед созданием выберите программный доступ для этого пользователя
  • когда появляется сообщение Успешно загрузите CSV-файл для учетных данных для дальнейшего использования. (Идентификатор ключа доступа и Секретный ключ доступа)
  • Проверьте установку, открыв VS Code и удерживая ctrl и ~, чтобы открыть внутри PowerShell.

Затем используйте следующие команды, чтобы проверить установку

$ aws --version
aws-cli/2.2.1 Python/3.8.8 Windows/10 exe/AMD64 prompt/off

Чтобы использовать AWS cli, нам необходимо настроить его с помощью ключа доступа AWS, секретного ключа доступа, региона по умолчанию и выходной формат:

$ aws configure
AWS Access Key ID [****************46P7]:
AWS Secret Access Key [****************SoXF]:
Default region name [us-east-1]:
Default output format [json]:

Пришло время установить Terraform (альтернативные методы ссылка).

Легкий путь

Уф, это было много работы! Было бы ужасно делать это каждый раз, когда вам приходилось устанавливать новое программное обеспечение на ваше устройство. Вместо этого воспользуемся менеджером пакетов. Есть несколько менеджеров пакетов, которые вы можете использовать для установки Terraform в Windows. Для Windows мне больше всего нравится Chocolatey. Он упрощает установку, удаление и обновление программного обеспечения, как однострочную команду, и Terraform не является исключением.

Чтобы установить Terraform с Chocolatey, выполните следующие действия:

  1. Откройте командную строку CMD / PowerShell от имени администратора и установите Chocolatey с помощью команды со их страницы установки.
  2. Как только это будет завершено, запустите choco install terraform. Если хотите, вы также можете поставить -y в конце, чтобы автоматически согласиться на его установку на свое устройство.

После выполнения этой команды вы получите что-то вроде этого:

Chocolatey v0.10.13
2 validations performed. 1 success(es), 1 warning(s), and 0 error(s).
Installing the following packages:
terraform
By installing you accept licenses for the packages.
Progress: Downloading terraform 0.12.6... 100%
terraform v0.12.6 [Approved]
Downloading terraform 64 bit
  from 'https://releases.hashicorp.com/terraform/0.12.6/terraform_0.12.6_windows
Download of terraform_0.12.6_windows_amd64.zip (15.32 MB) completed.
--SNIP--

Другой способ

Попробуйте этот метод Подсистема Windows для Linux. Это позволяет запускать команды Linux в Windows и, если вы хотите создать отдельную тестовую среду.

  1. Установите WSL через Microsoft Store, выполните поиск в Ubuntu и установите последнюю версию.

2. В оболочке WSL запустите apt-get install unzip. Это понадобится вам для извлечения двоичных файлов Terraform позже.

3. Загрузите Terraform, запустив wget https://releases.hashicorp.com/terraform/0.12.6/terraform_0.12.6_linux_amd64.zip. Не забудьте заменить версию и архитектуру на те, которые лучше всего подходят вашему устройству. Вы можете найти полный список релизов Terraform здесь.

4. Запустите unzip terraform_0.12.6_linux_amd64.zip terraform, чтобы распаковать содержимое zip-архива в папку с именем terraform.

5. После того, как ZIP-файл будет распакован, вам нужно переместить его в другое место, доступное по системному пути. К счастью, в Linux есть папка, в которую пользователи могут добавлять двоичные файлы по умолчанию. Переместите туда двоичный файл Terraform, запустив mv terraform /usr/local/bin/. Папка / usr / local / bin уже задана в вашем системном пути.

6. Убедитесь, что установка прошла успешно, запустив

$ terraform version
Terraform v0.14.3
+ provider registry.terraform.io/hashicorp/aws v3.21.0.
Note:If you are using WSL also use this command to generate private key
$ ssh-keygen
$ cat .ssh/id_rsa       <-- to make sure your key exist in that path
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gt
.
.
.
-----END OPENSSH PRIVATE KEY-----

Установка Python3 и Boto3

Хотя в вашей системе может быть предустановлен Python2. Однако для этого проекта рекомендуется установить последнюю версию Python3.

Для более подробной установки посетите здесь

Убедитесь, что вы действительно проверяете установку после установки

$pip install boto3
python3 --version
Python 3.9.4
pip3 --version   
pip 20.2.3 from C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.1264.0_x64__qbz5n2kfra8p0\lib\site-packages\pip (python 3.9)
pip3 show boto3
Name: boto3
Version: 1.17.62
Summary: The AWS SDK for Python
Home-page: https://github.com/boto/boto3
Author: Amazon Web Services
Author-email: None
License: Apache License 2.0
Location: c:\users\msun_\appdata\local\packages\pythonsoftwarefoundation.python.3.9_qbz5n2kfra8p0\localcache\local-packages\python39\site-packages
Requires: s3transfer, jmespath, botocore
Required-by:

Boto3 для предоставления нашего VPC

Пришло время создать файл Python с помощью Python и выполнить наш первый скрипт Boto3 для развертывания ресурсов в AWS.

Сначала создайте папку и переключитесь на нее

$ mkdir Boto3forVPC && cd Boto3forVPC/

vim vpc.py

Запустите следующий сценарий, чтобы развернуть нужные ресурсы на AWS.

$ python3 vpc.py
ec2.Vpc(id='vpc-005382a4c773378a7')
[ec2.Tag(resource_id='vpc-005382a4c773378a7', key='Name', value='boto3_vpc')]
ec2.InternetGateway(id='igw-0e1ca1c17c56dea96')
ec2.RouteTable(id='rtb-0b0b2afb80ba70677')
ec2.Route(route_table_id='rtb-0b0b2afb80ba70677', destination_cidr_block='0.0.0.0/0')
ec2.Subnet(id='subnet-0b3fcb0b24adadd8b')
ec2.SecurityGroup(id='sg-03090bf8dcd216d50')
[ec2.Instance(id='i-0db6a00626adcd7d7')]

Через несколько минут перекрестная проверка в консоли AWS

Bastian Host- Ec2, VPC с именем boto3_vpc, подключенный к нему InternetGateway и связанная с ним подсеть, также создаются таблица маршрутов (с общедоступным маршрутом).

Группа безопасности и разрешите входящее правило SSH через VPC через ваш собственный IP-адрес (Примечания: для вашей собственной безопасности вы должны никогда не раскрывать свой IP-адрес )

Создайте файл для локального хранения ключа и вызовите функцию boto3 ec2 ​​для создания пары ключей с именем ec2-keypair, затем запишите ключ и сохраните его в файле ec2-keypair.pem

$ ls 
ec2-keypair.pem  vpc.py
Its time to destroy the resources we have just created using vim vpc_destroy.py & copy the code below.

используйте команду ниже, чтобы уничтожить ресурсы, которые мы создали ранее, в зависимости от вашего vpc_id

$ python3 vpc_destroy.py --vpc_id vpc-005382a4c773378a7 --region us-east-1 --services ec2
type: <class 'str'>
[vpc_destroy.py:243 -             <module>() ] calling destroy_services with ec2
[credentials.py:1217 -                 load() ] Found credentials in shared credentials file: ~/.aws/credentials
[vpc_destroy.py:58 -          destroy_ec2() ] instance deletion list: ['i-0db6a00626adcd7d7']
[vpc_destroy.py:60 -          destroy_ec2() ] Waiting for instances to terminate
[vpc_destroy.py:246 -             <module>() ] calling delete_vpc with vpc-005382a4c773378a7
[vpc_destroy.py:162 -           delete_vpc() ] no ENIs remaining
destroyed vpc-005382a4c773378a7 in us-east-1

Примечания. Как показано выше, вы должны предоставить vpc_id, регион и услуги. Если вы хотите узнать больше о том, как эта очистка VPC с помощью Boto3, пожалуйста, обратитесь к этому сообщению

Примечания. Убедитесь, что каждый раз, когда вы применяете vpc.py для создания нового VPC, вам необходимо указывать новое имя пары ключей . В противном случае создание не может быть выполнено должным образом. Для этого вы можете использовать AWS или AWS CLI.

Для AWS CLI примените код ниже

$ aws ec2 delete-key-pair --key-name <name of your key pair>

Здесь я также хотел бы предоставить Terraforming VPC и Terraforming VPC с использованием AWS CloudFormation.

Причина в том, чтобы предоставить различные способы предоставления VPC для удовлетворения различных потребностей и требований. Также давайте разберемся, какой вариант более действенный и действенный.

Начнем с Terraforming VPC

Во-первых, нам нужно создать с помощью vi vpc.tf файл в той же папке или создать отдельный, используя следующий код:

Во-вторых, вам также потребуется создать vi variables.tf файл, чтобы предоставить дополнительные настройки.

В-третьих, вам также нужно будет создать vi terraform.tfvars файл, чтобы указать необходимые переменные.

Наконец, вам также необходимо создать файл vi outputs.tf для вывода на консоль после создания.

Теперь пришло время терра из нашего vpc

$ terraform init

Это инициализирует и установит необходимые плагины для запуска terraform.

Обязательно проверяет синтаксис всех файлов terraform в вашем каталоге.

$ terraform validate
Success! The configuration is valid.

Затем мы спланируем нашу инфраструктуру terraform, чтобы убедиться, какие ресурсы будут развернуты с использованием этого кода.

$ terraform plan
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
 + create
Terraform will perform the following actions:
# aws_instance.bastion_host will be created
 + resource “aws_instance” “bastion_host” {
 + ami = “ami-0742b4e673072066f”
 + arn = (known after apply)
 + associate_public_ip_address = true
 + availability_zone = (known after apply)
 + cpu_core_count = (known after apply)
 + cpu_threads_per_core = (known after apply)
 + get_password_data = false
 + host_id = (known after apply)
 + id = (known after apply)
 + instance_initiated_shutdown_behavior = (known after apply)
 + instance_state = (known after apply)
 + instance_type = “t2.micro”
 + ipv6_address_count = (known after apply)
 + ipv6_addresses = (known after apply)
 + key_name = “ec2-keypair”
 + outpost_arn = (known after apply)
 + password_data = (known after apply)
 + placement_group = (known after apply)
 + primary_network_interface_id = (known after apply)
 + private_dns = (known after apply)
 + private_ip = (known after apply)
 + public_dns = (known after apply)
 + public_ip = (known after apply)
 + secondary_private_ips = (known after apply)
 + security_groups = (known after apply)
 + source_dest_check = true
 + subnet_id = (known after apply)
 + tags_all = (known after apply)
 + tenancy = (known after apply)
 + vpc_security_group_ids = (known after apply)
+ ebs_block_device {
 + delete_on_termination = (known after apply)
 + device_name = (known after apply)
 + encrypted = (known after apply)
 + iops = (known after apply)
 + kms_key_id = (known after apply)
 + snapshot_id = (known after apply)
 + tags = (known after apply)
 + throughput = (known after apply)
 + volume_id = (known after apply)
 + volume_size = (known after apply)
 + volume_type = (known after apply)
 }
+ enclave_options {
 + enabled = (known after apply)
 }
+ ephemeral_block_device {
 + device_name = (known after apply)
 + no_device = (known after apply)
 + virtual_name = (known after apply)
 }
+ metadata_options {
 + http_endpoint = (known after apply)
 + http_put_response_hop_limit = (known after apply)
 + http_tokens = (known after apply)
 }
+ network_interface {
 + delete_on_termination = (known after apply)
 + device_index = (known after apply)
 + network_interface_id = (known after apply)
 }
+ root_block_device {
 + delete_on_termination = (known after apply)
 + device_name = (known after apply)
 + encrypted = (known after apply)
 + iops = (known after apply)
 + kms_key_id = (known after apply)
 + tags = (known after apply)
 + throughput = (known after apply)
 + volume_id = (known after apply)
 + volume_size = (known after apply)
 + volume_type = (known after apply)
 }
 }
# aws_internet_gateway.igw will be created
 + resource “aws_internet_gateway” “igw” {
 + arn = (known after apply)
 + id = (known after apply)
 + owner_id = (known after apply)
 + tags = {
 + “Environment” = “Development”
 + “Name” = “boto3_vpc”
 }
 + tags_all = {
 + “Environment” = “Development”
 + “Name” = “boto3_vpc”
 }
 + vpc_id = (known after apply)
 }
# aws_key_pair.bastion_host_key will be created
 + resource “aws_key_pair” “bastion_host_key” {
 + arn = (known after apply)
 + fingerprint = (known after apply)
 + id = (known after apply)
 + key_name = “ec2-keypair”
 + key_pair_id = (known after apply)
 + public_key = (known after apply)
 + tags_all = (known after apply)
 }
# aws_route_table.public_route_table will be created
 + resource “aws_route_table” “public_route_table” {
 + arn = (known after apply)
 + id = (known after apply)
 + owner_id = (known after apply)
 + propagating_vgws = (known after apply)
 + route = [
 + {
 + carrier_gateway_id = “”
 + cidr_block = “0.0.0.0/0”
 + destination_prefix_list_id = “”
 + egress_only_gateway_id = “”
 + gateway_id = (known after apply)
 + instance_id = “”
 + ipv6_cidr_block = “”
 + local_gateway_id = “”
 + nat_gateway_id = “”
 + network_interface_id = “”
 + transit_gateway_id = “”
 + vpc_endpoint_id = “”
 + vpc_peering_connection_id = “”
 },
 ]
 + tags = {
 + “Environment” = “var.environment_tag”
 }
 + tags_all = {
 + “Environment” = “var.environment_tag”
 }
 + vpc_id = (known after apply)
 }
# aws_route_table_association.public_rt_association[0] will be created
 + resource “aws_route_table_association” “public_rt_association” {
 + id = (known after apply)
 + route_table_id = (known after apply)
 + subnet_id = (known after apply)
 }
# aws_security_group.bastion_host will be created
 + resource “aws_security_group” “bastion_host” {
 + arn = (known after apply)
 + description = “Managed by Terraform”
 + egress = [
 + {
 + cidr_blocks = []
 + description = “”
 + from_port = 22
 + ipv6_cidr_blocks = []
 + prefix_list_ids = []
 + protocol = “var.protocol”
 + security_groups = []
 + self = false
 + to_port = 22
 },
 ]
 + id = (known after apply)
 + ingress = [
 + {
 + cidr_blocks = [
 + “72.137.76.221/32”,
 ]
 + description = “”
 + from_port = 22
 + ipv6_cidr_blocks = []
 + prefix_list_ids = []
 + protocol = “tcp”
 + security_groups = []
 + self = false
 + to_port = 22
 },
 ]
 + name = (known after apply)
 + name_prefix = (known after apply)
 + owner_id = (known after apply)
 + revoke_rules_on_delete = false
 + tags_all = (known after apply)
 + vpc_id = (known after apply)
 }
# aws_subnet.public_subnet[0] will be created
 + resource “aws_subnet” “public_subnet” {
 + arn = (known after apply)
 + assign_ipv6_address_on_creation = false
 + availability_zone = “us-east-1a”
 + availability_zone_id = (known after apply)
 + cidr_block = “172.16.1.0/24”
 + id = (known after apply)
 + ipv6_cidr_block_association_id = (known after apply)
 + map_public_ip_on_launch = false
 + owner_id = (known after apply)
 + tags = {
 + “Environment” = “var.environment_tag”
 }
 + tags_all = {
 + “Environment” = “var.environment_tag”
 }
 + vpc_id = (known after apply)
 }
# aws_vpc.main will be created
 + resource “aws_vpc” “main” {
 + arn = (known after apply)
 + assign_generated_ipv6_cidr_block = false
 + cidr_block = “172.16.0.0/16”
 + default_network_acl_id = (known after apply)
 + default_route_table_id = (known after apply)
 + default_security_group_id = (known after apply)
 + dhcp_options_id = (known after apply)
 + enable_classiclink = (known after apply)
 + enable_classiclink_dns_support = (known after apply)
 + enable_dns_hostnames = true
 + enable_dns_support = true
 + id = (known after apply)
 + instance_tenancy = “default”
 + ipv6_association_id = (known after apply)
 + ipv6_cidr_block = (known after apply)
 + main_route_table_id = (known after apply)
 + owner_id = (known after apply)
 + tags = {
 + “Environment” = “Development”
 + “Name” = “boto3_vpc”
 }
 + tags_all = {
 + “Environment” = “Development”
 + “Name” = “boto3_vpc”
 }
 }
# tls_private_key.public_key will be created
 + resource “tls_private_key” “public_key” {
 + algorithm = “RSA”
 + ecdsa_curve = “P224”
 + id = (known after apply)
 + private_key_pem = (sensitive value)
 + public_key_fingerprint_md5 = (known after apply)
 + public_key_openssh = (known after apply)
 + public_key_pem = (known after apply)
 + rsa_bits = 4096
 }
Plan: 9 to add, 0 to change, 0 to destroy.
Changes to Outputs:
 + cidr_block = “172.16.0.0/16”
 + gateway_id = (known after apply)
 + key_name = “ec2-keypair”
 + route_table_id = (known after apply)
 + subnet_id = (known after apply)
 + tags = {
 + Environment = “Development”
 }
 + vpc_security_group_ids = [
 + (known after apply),
 ]

Когда вы будете готовы, давайте подготовим инфраструктуру с помощью приведенной ниже команды.

$ terraform apply --auto-approve

Затем давайте дважды проверим наши ресурсы, которые были созданы в консоли AWS.

Создан VPC с именем boto3_vpc

Пора прояснить инфраструктуру, созданную с помощью Terraform

$ terraform destroy
.
.
   Enter a value: yes

Теперь мы подготовим VPC с помощью CloudFormation.

Вот официальный шаблон AWS для VPC в качестве справки.

Примечание. Сначала создайте пару ключей, поскольку CloudFormation не может ее создать. Он понадобится вам для доступа к экземплярам EC2.

$ aws ec2 create-key-pair --key-name ec2-keypair
{
    "KeyFingerprint": "ab:b2:0c:81:9e:1e:07:d5:15:bb:a9:b1:41:b0:5d:e2:af:b5:38:23",
    "KeyMaterial": "-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAmB0Ani+OiUMiqrlgrMc50oGo9KjsVj3MNnxbmFSyMNxuLrSp\nXLiRsSHcJK7cH6IxOXuSOE0fczJmhFQZnFLTpkOqx7ELpRBDSTFdnYfqXf5oxrjs\nf5OZRXuZqjncgxxd7f/KLEBrn5xBR03aiUkc/w5lYTR0JMjWIlIsPxIxRwF9NZ/o\n2AA6K/gX2lqteFV9mUizq0Z301Ryd/RNyeABEHhJ4fuJTb1MlBc1wEGZj2pM0aVr\n67nRV0RZhTP8uj9MKg1OAvb5yaZuvBiccoiUOshoYjgrPJsnuywH6kNLHNahbrjj\n9XirKQdQ4TogqJnaW/Vd3d9J8IwNA8LcYs88owIDAQABAoIBACxeaUu6u2y2NGpv\n4A8FnYwVXd7fVvBg3iwWYfEw4zj1Uv40nCH7hCOSqM/aYUKo4IrPzHq3pDDJxrVa\ngo3iavHYUvwkXC0tbTLwP0ov1uDL0GwGjJU5zD9EKjJI5lUn9Q3yylnWAI5x2Wif\nANuCg/6xiEiuMCJ6olsodNeAyvbWuIhR+uyFfVE4vEdoqK4l8UYWQNACOnppKgaJ\nrbcKnfi+dj0AejQInpk8Ov6UUdTEINQZ4JG/d/2DFYWktGBmHVhEm9h4WIr9HRV6\nQT6LklIZYF6e9W379Z5ZXX1aGUdSeHPAefFkNwPrNCMjLCRur+C16dUAzO6jBRpG\nYZPcauECgYEA3F/9ioQ0x4//wAQkzZb81tFqRRjKTSggx2+lTKkb/UhXtCN67XJD\nMzJoGOIVPVbHdcmpP0v0cG7g71e0gyRZ7zN0m28n6L415UXOx2/PL3qZoRb3TcAq\njm4uaTxp0pCXLRmfryqiCcZzu6cmxG6YujmtKNdBrGjuvIqNdZCutu8CgYEAsLQR\nNcvxBxAGFwSWZv5ztf5agmpgK8j9gVxcO3Qc0QIU67o78hgvVkNhYgopWt4UmKzi\nPRMMVRwX82iNpLFXwqgKQnIcueYiYXdC8F9+FSByq1TnkTFtLQJwJlRln0/TreNO\n6XN+gZBmldacExyqPAz93+vZo4lvu1LcbXybNY0CgYAkPf0afKeZcksjLwtGbGBk\ni8goWO1cRw8s/WV3+A/MVctmqrcaucHnd5C7FuNbVRw0eNfGux0WKIYBlrDvKFlK\nB3JT5bHwiueeLx7UmcS/EDCX14kQVlwpVGF5mR/mKzVRi3dBfYdsiCCcad7sSyv+\n5GFf6Ba63f71LuwYu5SgLQKBgQCTxzQxcorz5iHBtFN4dUseJEdblE0zsRbZzf1Q\nt421+nC2p/ykPjewhA94Z5koZlyBRuy6OSjyMNmS9pim6K3FnLVf1oFRszaDnrL7\nxlDyqD1eLlavpc9xef2DAMgwURlt7pE7Shy9jJ9OprnGfg2cxRy43U0ZqMIpvmWc\npz5CrQKBgCttNZrapWuh8Y6QXlMDp5sCovUAj9Fw5J11j0yZyf+i704hnEuv+/5H\nvzFuvTwaRlSIoz1Frnvhb9NF+9NYqrno2T3GOATRgThgHKN9soqJism5tG/jLGDS\n2x9P99HC94Ybd13IKDXrLK/gCVh97Zlel21CY2+Pu6K/6L3kjogH\n-----END RSA PRIVATE KEY-----",
    "KeyName": "ec2-keypair",
    "KeyPairId": "key-023bd02d2f97b4a31"
}

После создания пары ключей самое время создать стек с помощью AWS-CLI с CloudFormation и кодом ниже:

Используя следующий код, вы можете развернуть аналогичные ресурсы в CloudFormation.

$ aws cloudformation create-stack — stack-name cfvpc — template-body file://vpc.yaml
StackId: arn:aws:cloudformation:us-east-1:050411548990:stack/cfvpc/56c90c50-ab72–11eb-b620–0adbfd4180bb

Затем мы перепроверим наши ресурсы в консоли AWS. ›› CloudFormation на вкладке «Ресурсы»:

Вы можете проверить все ресурсы здесь и щелкнуть ресурсы, чтобы перейти в их прямое местоположение, где они были созданы, преимущество CloudFormation, где вы можете проверять, редактировать и уничтожать ресурсы в AWS.

Примечания. Используя CloudFormation, мы также сможем распечатывать выходные данные для справки в будущем.

Параметры

Примечания. Параметры позволяют нам записывать параметры, которые мы вводим изначально.

Шаблон

Примечание. В этом разделе мы можем сохранить исходный файл шаблона CloudFormation в качестве резервной копии.

Пришло время очистить и удалить инфраструктуру.

aws cloudformation delete-stack --stack-name cfvpc

Теперь все убрано.

Воспользуйтесь преимуществами Terraform и CloudFormation, чтобы выполнить Terraforming CloudFormation для предоставления VPC

Для реализации этого проекта нам нужно будет создать новый каталог и перейти в него.

$ mkdir tf_cf_vpc && cd tf_cf_vpc/

Для CloudFormation мы по-прежнему будем использовать наш vpc.yaml файл, созданный ранее.

Нам также нужно создать наш tf_cf_vpc.tf file, используя код ниже

Наконец, мы готовы терраформировать нашу инфраструктуру, используя оба инструмента IaC.

$ terraform init

Затем проверьте наш код:

$ terraform validate
Success! The configuration is valid.

После этого давайте спланируем нашу инфраструктуру и убедимся в желаемых ресурсах:

$ terraform plan
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
 + create
Terraform will perform the following actions:
# aws_cloudformation_stack.tf_cf_vpc will be created
 + resource “aws_cloudformation_stack” “tf_cf_vpc” {
 + id = (known after apply)
 + name = “TfCfVpc”
 + outputs = (known after apply)
 + parameters = {
 + “InstanceType” = “t3.nano”
 + “KeyName” = “tf_cf_keypair”
 }
 + policy_body = (known after apply)
 + tags_all = (known after apply)
 + template_body = <<-EOT
 Description: This CloudFormation YAML file will provision a VPC
Parameters:
 KeyName:
 Description: Name of an existing EC2 KeyPair to enable SSH access to the instance
 Type: AWS::EC2::KeyPair::KeyName
 Default: ec2-keypair
InstanceType:
 Description: EC2 instance type
 Type: String
 Default: t2.micro
EnvironmentName:
 Description: An environment name that is prefixed to resource names
 Type: String
 Default: Development
VpcCIDR:
 Description: Please enter the IP range (CIDR notation) for this VPC
 Type: String
 Default: “172.16.0.0/16”
PublicSubnet1CIDR:
 Description: Please enter the IP range (CIDR notation) for the public subnet in the first Availability Zone
 Type: String
 Default: “172.16.1.0/24”
Mappings:
 AWSRegionToAMI:
 us-east-1:
 AMIID: ami-0742b4e673072066f
Resources:
 VPC:
 Type: AWS::EC2::VPC
 Properties:
 CidrBlock:
 Ref: VpcCIDR
 EnableDnsSupport: true
 EnableDnsHostnames: true
 Tags:
 — Key: Name
 Value:
 Ref: EnvironmentName
InternetGateway:
 Type: AWS::EC2::InternetGateway
 Properties:
 Tags:
 — Key: Name
 Value:
 Ref: EnvironmentName
InternetGatewayAttachment:
 Type: AWS::EC2::VPCGatewayAttachment
 Properties:
 InternetGatewayId:
 Ref: InternetGateway
 VpcId:
 Ref: VPC
PublicSubnet1:
 Type: AWS::EC2::Subnet
 Properties:
 VpcId:
 Ref: VPC
 AvailabilityZone: !Select [ 0, !GetAZs ‘’ ]
 CidrBlock:
 Ref: PublicSubnet1CIDR
 MapPublicIpOnLaunch: true
 Tags:
 — Key: Name
 Value: !Sub ${EnvironmentName} Public Subnet (AZ1)
PublicRouteTable:
 Type: AWS::EC2::RouteTable
 Properties:
 VpcId:
 Ref: VPC
 Tags:
 — Key: Name
 Value: !Sub ${EnvironmentName} Public Routes
DefaultPublicRoute:
 Type: AWS::EC2::Route
 DependsOn: InternetGatewayAttachment
 Properties:
 RouteTableId:
 Ref: PublicRouteTable
 DestinationCidrBlock: 0.0.0.0/0
 GatewayId:
 Ref: InternetGateway
PublicSubnet1RouteTableAssociation:
 Type: AWS::EC2::SubnetRouteTableAssociation
 Properties:
 RouteTableId:
 Ref: PublicRouteTable
 SubnetId:
 Ref: PublicSubnet1
VPCEC2SecurityGroup:
 Type: AWS::EC2::SecurityGroup
 Properties:
 GroupDescription: only allow SSH traffic
 GroupName: SSH-ONLY
 SecurityGroupIngress:
 — CidrIp: 72.137.76.221/32
 FromPort: 22
 IpProtocol: tcp
 ToPort: 22
 Tags:
 -
 Key: Name
 Value: CloudFormationSecurityGroup
 VpcId:
 Ref: VPC
VPCEC2:
 Type: AWS::EC2::Instance
 Properties:
 ImageId:
 !FindInMap
 — AWSRegionToAMI
 — !Ref AWS::Region
 — AMIID
 InstanceType: !Ref InstanceType
 SecurityGroupIds:
 — !GetAtt “VPCEC2SecurityGroup.GroupId”
 SubnetId: !Ref PublicSubnet1
 KeyName:
 Ref: KeyName
Outputs:
 VPC:
 Description: A reference to the created VPC
 Value:
 Ref: VPC
PublicSubnet1:
 Description: A reference to the public subnet in the 1st Availability Zone
 Value:
 Ref: PublicSubnet1
VPCEC2SecurityGroup:
 Description: Security group with no ingress rule
 Value:
 Ref: VPCEC2SecurityGroup
InternetGateway:
 Description: InternetGateway Information
 Value:
 Ref: InternetGateway
PublicRouteTable:
 Description: Public Route Table Information
 Value:
 Ref: PublicRouteTable
VPCEC2:
 Description: EC2 Information
 Value:
 Ref: VPCEC2
 EOT
 }
# aws_key_pair.bastion_host_key will be created
 + resource “aws_key_pair” “bastion_host_key” {
 + arn = (known after apply)
 + fingerprint = (known after apply)
 + id = (known after apply)
 + key_name = “tf_cf_keypair”
 + key_pair_id = (known after apply)
 + public_key = (known after apply)
 + tags_all = (known after apply)
 }
# tls_private_key.public_key will be created
 + resource “tls_private_key” “public_key” {
 + algorithm = “RSA”
 + ecdsa_curve = “P224”
 + id = (known after apply)
 + private_key_pem = (sensitive value)
 + public_key_fingerprint_md5 = (known after apply)
 + public_key_openssh = (known after apply)
 + public_key_pem = (known after apply)
 + rsa_bits = 4096
 }
Plan: 3 to add, 0 to change, 0 to destroy.
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Note: You didn’t use the -out option to save this plan, so Terraform can’t guarantee to take exactly these actions if you run “terraform apply” now.
Then run the following to deploy resources in AWS
$ terraform apply  --auto-approve

Затем мы проверим и дважды проверим ресурсы, созданные в консоли AWS.

Создан IGW, который прикреплен к Development

InternetGateway

Подсеть и свяжите ее с таблицей маршрутов

Подсеть с таблицей маршрутизации

Таблица маршрутов с общедоступным маршрутом

Таблица маршрутов с общедоступным маршрутом

Группа безопасности и разрешите входящее правило SSH через VPC через ваш собственный IP-адрес (Примечания: для вашей собственной безопасности вы должны никогда не раскрывать свой IP-адрес )

SSH с вашим собственным IP-адресом:

EC2 создан!

Примечание. Здесь мы обновим одно значение InstanceType в нашем .tf-файле и проверим возможности терраформирования. Наряду с CloudFormation мы можем воспользоваться преимуществами гибкости Terraform и встроенного и простого выделения ресурсов AWS от CloudFormation.

Здесь мы сделаем обновление файла tf_cf_vpc.tf и изменим InstanceType from t2.micro >> to t3.large

Давайте спланируем это еще раз, чтобы увидеть разницу:

$ terraform plan
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
 + create
Terraform will perform the following actions:
# aws_cloudformation_stack.tf_cf_vpc will be created
 + resource “aws_cloudformation_stack” “tf_cf_vpc” {
 + id = (known after apply)
 + name = “TfCfVpc”
 + outputs = (known after apply)
 + parameters = {
 + “InstanceType” = “t3.large”
 + “KeyName” = “tf_cf_keypair”
 }
 + policy_body = (known after apply)
 + tags_all = (known after apply)
 + template_body = <<-EOT
 Description: This CloudFormation YAML file will provision a VPC
Parameters:
 KeyName:
 Description: Name of an existing EC2 KeyPair to enable SSH access to the instance
 Type: AWS::EC2::KeyPair::KeyName
 Default: ec2-keypair
InstanceType:
 Description: EC2 instance type
 Type: String
 Default: t2.micro
EnvironmentName:
 Description: An environment name that is prefixed to resource names
 Type: String
 Default: Development
VpcCIDR:
 Description: Please enter the IP range (CIDR notation) for this VPC
 Type: String
 Default: “172.16.0.0/16”
PublicSubnet1CIDR:
 Description: Please enter the IP range (CIDR notation) for the public subnet in the first Availability Zone
 Type: String
 Default: “172.16.1.0/24”
Mappings:
 AWSRegionToAMI:
 us-east-1:
 AMIID: ami-0742b4e673072066f
Resources:
 VPC:
 Type: AWS::EC2::VPC
 Properties:
 CidrBlock:
 Ref: VpcCIDR
 EnableDnsSupport: true
 EnableDnsHostnames: true
 Tags:
 — Key: Name
 Value:
 Ref: EnvironmentName
InternetGateway:
 Type: AWS::EC2::InternetGateway
 Properties:
 Tags:
 — Key: Name
 Value:
 Ref: EnvironmentName
InternetGatewayAttachment:
 Type: AWS::EC2::VPCGatewayAttachment
 Properties:
 InternetGatewayId:
 Ref: InternetGateway
 VpcId:
 Ref: VPC
PublicSubnet1:
 Type: AWS::EC2::Subnet
 Properties:
 VpcId:
 Ref: VPC
 AvailabilityZone: !Select [ 0, !GetAZs ‘’ ]
 CidrBlock:
 Ref: PublicSubnet1CIDR
 MapPublicIpOnLaunch: true
 Tags:
 — Key: Name
 Value: !Sub ${EnvironmentName} Public Subnet (AZ1)
PublicRouteTable:
 Type: AWS::EC2::RouteTable
 Properties:
 VpcId:
 Ref: VPC
 Tags:
 — Key: Name
 Value: !Sub ${EnvironmentName} Public Routes
DefaultPublicRoute:
 Type: AWS::EC2::Route
 DependsOn: InternetGatewayAttachment
 Properties:
 RouteTableId:
 Ref: PublicRouteTable
 DestinationCidrBlock: 0.0.0.0/0
 GatewayId:
 Ref: InternetGateway
PublicSubnet1RouteTableAssociation:
 Type: AWS::EC2::SubnetRouteTableAssociation
 Properties:
 RouteTableId:
 Ref: PublicRouteTable
 SubnetId:
 Ref: PublicSubnet1
VPCEC2SecurityGroup:
 Type: AWS::EC2::SecurityGroup
 Properties:
 GroupDescription: only allow SSH traffic
 GroupName: SSH-ONLY
 SecurityGroupIngress:
 — CidrIp: 72.137.76.221/32
 FromPort: 22
 IpProtocol: tcp
 ToPort: 22
 Tags:
 -
 Key: Name
 Value: CloudFormationSecurityGroup
 VpcId:
 Ref: VPC
VPCEC2:
 Type: AWS::EC2::Instance
 Properties:
 ImageId:
 !FindInMap
 — AWSRegionToAMI
 — !Ref AWS::Region
 — AMIID
 InstanceType: !Ref InstanceType
 SecurityGroupIds:
 — !GetAtt “VPCEC2SecurityGroup.GroupId”
 SubnetId: !Ref PublicSubnet1
 KeyName:
 Ref: KeyName
Outputs:
 VPC:
 Description: A reference to the created VPC
 Value:
 Ref: VPC
PublicSubnet1:
 Description: A reference to the public subnet in the 1st Availability Zone
 Value:
 Ref: PublicSubnet1
VPCEC2SecurityGroup:
 Description: Security group with no ingress rule
 Value:
 Ref: VPCEC2SecurityGroup
InternetGateway:
 Description: InternetGateway Information
 Value:
 Ref: InternetGateway
PublicRouteTable:
 Description: Public Route Table Information
 Value:
 Ref: PublicRouteTable
VPCEC2:
 Description: EC2 Information
 Value:
 Ref: VPCEC2
 EOT
 }
# aws_key_pair.bastion_host_key will be created
 + resource “aws_key_pair” “bastion_host_key” {
 + arn = (known after apply)
 + fingerprint = (known after apply)
 + id = (known after apply)
 + key_name = “tf_cf_keypair”
 + key_pair_id = (known after apply)
 + public_key = (known after apply)
 + tags_all = (known after apply)
 }
# tls_private_key.public_key will be created
 + resource “tls_private_key” “public_key” {
 + algorithm = “RSA”
 + ecdsa_curve = “P224”
 + id = (known after apply)
 + private_key_pem = (sensitive value)
 + public_key_fingerprint_md5 = (known after apply)
 + public_key_openssh = (known after apply)
 + public_key_pem = (known after apply)
 + rsa_bits = 4096
 }
Plan: 3 to add, 0 to change, 0 to destroy.
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Note: You didn’t use the -out option to save this plan, so Terraform can’t guarantee to take exactly these actions if you run “terraform apply” now.

Пришло время повторно подать заявку на обновление изменений instance_type, что занимает меньше времени:

$ terraform apply
.
.
.
 Enter a value: yesaws_cloudformation_stack.tf_cf_vpc: Modifying... [id=arn:aws:cloudformation:us-east-1:464392538707:stack/TfCfVpc/b8b5f360-a4b5-11eb-b4b0-12d101416601]
aws_cloudformation_stack.tf_cf_vpc: Still modifying... [id=arn:aws:cloudformation:us-east-1:464392...c/b8b5f360-a4b5-11eb-b4b0-12d101416601, 10s elapsed]
aws_cloudformation_stack.tf_cf_vpc: Still modifying... [id=arn:aws:cloudformation:us-east-1:464392...c/b8b5f360-a4b5-11eb-b4b0-12d101416601, 20s elapsed]
aws_cloudformation_stack.tf_cf_vpc: Still modifying... [id=arn:aws:cloudformation:us-east-1:464392...c/b8b5f360-a4b5-11eb-b4b0-12d101416601, 30s elapsed]
aws_cloudformation_stack.tf_cf_vpc: Still modifying... [id=arn:aws:cloudformation:us-east-1:464392...c/b8b5f360-a4b5-11eb-b4b0-12d101416601, 40s elapsed]
aws_cloudformation_stack.tf_cf_vpc: Still modifying... [id=arn:aws:cloudformation:us-east-1:464392...c/b8b5f360-a4b5-11eb-b4b0-12d101416601, 50s elapsed]
aws_cloudformation_stack.tf_cf_vpc: Still modifying... [id=arn:aws:cloudformation:us-east-1:464392...c/b8b5f360-a4b5-11eb-b4b0-12d101416601, 1m0s elapsed]
aws_cloudformation_stack.tf_cf_vpc: Still modifying... [id=arn:aws:cloudformation:us-east-1:464392...c/b8b5f360-a4b5-11eb-b4b0-12d101416601, 1m10s elapsed]
aws_cloudformation_stack.tf_cf_vpc: Still modifying... [id=arn:aws:cloudformation:us-east-1:464392...c/b8b5f360-a4b5-11eb-b4b0-12d101416601, 1m20s elapsed]
aws_cloudformation_stack.tf_cf_vpc: Still modifying... [id=arn:aws:cloudformation:us-east-1:464392...c/b8b5f360-a4b5-11eb-b4b0-12d101416601, 1m30s elapsed]
aws_cloudformation_stack.tf_cf_vpc: Modifications complete after 1m39s [id=arn:aws:cloudformation:us-east-1:464392538707:stack/TfCfVpc/b8b5f360-a4b5-11eb-b4b0-12d101416601]Apply complete! Resources: 0 added, 1 changed, 0 destroyed.

Давайте дважды проверим в консоли AWS в экземплярах EC2:

А теперь давайте разрушим всю инфраструктуру в последний раз:

$ terraform destroy — auto-approve

Резюме

Давайте подведем итоги нашего проекта и того, чего мы достигли.

Архитектура проекта

Как видно из архитектуры проекта, мы рассмотрим 4 различных способа предоставления VPC с помощью инструментов Infra-as-code.

  • Boto3
  • CloudFormation (собственный AWS)
  • Terraform (родной для облака)
  • Terraform + CloudFormation

Прежде всего, используя Boto3, может потребоваться 2 разных файла для создания vpc в первую очередь и его уничтожения в конце дня. С учетом сказанного, это может быть проблемой с точки зрения менеджмента.

Во-вторых, мы создали инфраструктуру VPC с помощью CloudFormation. Поскольку он является родным для AWS, он отлично работал. Однако, что касается обновлений, нам может потребоваться поработать с одним и тем же файлом для параметров, как, скажем,. Но этим все еще можно было хорошо управлять.

В-третьих, Terraform как инструмент IaC действительно сиял своей гибкостью. От создания инфраструктуры до обновления до разрушения в конце дня - каждое движение было безупречным. Однако нам нужно потратить время на создание инфраструктуры, используя Terraform как совершенно новый язык. С учетом сказанного, это может занять много времени.

Наконец, мой предпочтительный способ: Terraform + CloudFormation для AWS. Используя преимущества всех аспектов Terraform, мы улучшаем нашу инфраструктуру AWS с помощью CloudFormation. Шаблоны были легко доступны на официальном веб-сайте AWS, а также во многих блогах и веб-сайтах, посвященных облачным технологиям. Мы можем просто применить файл CloudFormation .yaml с Terraform.

Что еще более важно, гибкость Terraform остается в силе. Например, в проекте мы обновляем наш InstanceType, используя параметры в .tf файле. Эта инфраструктура для AWS - лучшее из обоих миров (или, может быть, трех).

Terraform + Cloud Native IaC Tool для вашего облачного провайдера должен стать лучшим выбором в облаке!

Я буду делать больше проектов по миграции, используя Terraform | GCP | AWS | Ansible | Python | более.

Спасибо за чтение! Пожалуйста, дайте мне знать свои мысли в комментариях, и не стесняйтесь делиться, если вы нашли это полезным.

Не стесняйтесь связаться со мной в Linkedin, если у вас возникнут какие-либо проблемы с этим.

Больше контента на plainenglish.io