AWS: 使用terraform创建EC2实例
简介
我将使用Terraform来创建EC2实例。
创建、终止、再创建,以便立即使用。
使用 Terraform
请参考下方链接以了解相关内容。
https://qiita.com/yamanashi7474/items/d12961780ad296335ed2
依照之前的核实
在本地环境中安装Terraform。
如果按照上述步骤进行操作,您可以下载版本0.12.3,但目前版本已升级到0.14.X。
请参考以下内容。
$ wget https://releases.hashicorp.com/terraform/0.14.10/terraform_0.14.10_linux_amd64.zip
$ sudo apt-get install unzip
$ unzip terraform_0.14.10_linux_amd64.zip
$ sudo mv terraform /usr/local/bin/
yamanashi@DESKTOP-9KCV2CQ:~/studymyself$ terraform -version
Terraform v0.14.10
Your version of Terraform is out of date! The latest version
is 1.0.7. You can update by downloading from https://www.terraform.io/downloads.html
如果可以确认版本,就可以进行引入。
创建工作目录
terraform的操作中,目录结构非常重要。
如果进行不适当的操作,可能会将意外更改应用于不希望更改的环境,因此需要进行分开管理。
在本次工作中,我们将以名为make_ec2_01的目录作为工作目录。
在本页面,除非另有说明,否则假定始终在工作目录中进行操作。
yamanashi@DESKTOP-9KCV2CQ:~/studymyself$ tree ./
./
├── study_ec2.pem
└── terraform
└── aws
└── make_ec2_01
3 directories, 1 file
创建.tf文件
.tf文件没有命名规则或其他限制。
可以将大量资源记录在一个文件中,也可以将其细分和分割。
从资源管理的角度来看,我认为将每个资源分开为不同的.tf文件会更容易使用。
.tf文件的写法非常简单。它是一种数据表,用于告诉terraform要创建什么,因此在括号的关闭方式和数据传递方式上有一些规则,但基本上是按照AWS的各种资源(如EC2实例、VPC、安全组等)来编写的。
以resource开头的块是一个整体。
resource "AWSリソース名" "任意の名前" {
設定1 = "設定値"
設定2 = 設定値
設定3 = [
"aaa","bbb"
]
ブロック {
設定4 = 設定値
}
tags = {
Name = "test-tag"
}
}
AWSリソース名是指在AWS上可以创建的各种对象的特定术语。如前所述,如果是VPC,则命名为aws_vpc;如果是EC2实例,则命名为aws_instance,并附带特定的代码。
您可以在官方网站上查找要创建的资源名称以进行确认。甚至只需进行谷歌搜索,通常也可以找到答案。
X指的是设置项,设置值也是如此。
需要注意的是,关于设置值的传递方式有几种不同的类型。这些也可以在官方网站上查找,每个设置项都会列出可传递的设置值以及传递时的规则。
在设置值中,包括了创建资源的id等。在terraform中,可以通过以下方式将terraform创建的资源信息传递。
AWS资源名称.任意名称.配置名称
例如:aws_vpc.test-vpc.id
块是一种像箱子一样将多个设置包围起来的东西。虽然无法直接对块进行设置,但是在块内需要写入必要的设置。
标签是可以应用于AWS许多资源的标签。在上面的例子中,创建了一个名为Name的标签并在其中输入了test-tag字符串。这是一个常见的用法,因此进行了说明。
这个资源的必要部分将被写入.tf文件。您无需担心资源的顺序或内部设置的顺序,只需将其写入.tf文件中,terraform命令将能够解析。
基础的terraform命令(格式化/计划/应用/销毁)
在创建具体的.tf文件之前,我们将介绍常用的Terraform命令(terraform fmt / terraform plan / terraform apply / terraform destroy)。
terraform fmt 美化
terraform fmt可以帮助整理.tf文件的缩进。
之前
resource "aws_vpc" "test-vpc" {
cidr_block = "10.40.0.0/16"
instance_tenancy = "default"
enable_dns_support = true
enable_dns_hostnames = true
tags = {
Name = "test-main"
}
}
之后
resource "aws_vpc" "test-vpc" {
cidr_block = "10.40.0.0/16"
instance_tenancy = "default"
enable_dns_support = true
enable_dns_hostnames = true
tags = {
Name = "test-main"
}
}
整形过的文件仅在提示符上输出文件名。
yamanashi@DESKTOP-9KCV2CQ:~/studymyself/terraform/aws/make_ec2_01$ terraform fmt
vpc.tf
计划terraform
terraform plan会读取terraform工作目录中的.tf文件,并在屏幕上显示要创建的资源列表。
由于长度较长,请在此处不提供示例,但是基于.tf文件创建的资源仅仅输出,并不会进行任何更改。此操作仅用于执行以进行创建前的确认。
执行Terraform应用
如果terraform plan没有任何问题,我们将使用terraform apply来创建资源。
执行之后,将显示与plan中相同的资源配置列表,并最后询问是否要创建这些资源。
如果输入“yes”,则开始创建,否则不会创建,程序会结束。
~snip~
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value:
如果在这里输入yes,经过一段时间后,将输出以下结果:分别创建、更改和删除了多少个对象。
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
如果.tf文件中的资源描述有误,将会输出错误的位置和部分原因,请您在确认后进行修正.tf文件。
使用target选项,只能在.tf文件中创建部分资源。
销毁基础设施
terraform destroy的功能正如其名,它会删除资源。
需要注意的是,直接执行terraform destroy时,将删除terraform apply创建的所有资源。
不打算删除全部内容,只有在删除特定资源时,请使用-target选项来限定目标。
此外,即使使用“-target”参数指定了目标,也可能会一并删除与该目标相关联且已创建的资源。请确认清楚要删除的内容后再输入“yes”进行执行。
创建.tf文件
由于我们已经准备好开始使用Terraform,所以让我们立即创建AWS资源。
创建 provider.tf
提供程序.tf需要terraform命令行工具用于操作的云环境信息。本次将写入AWS的信息和使用的账户信息。
[yamanashi@ip-172-31-46-224 test01]$ cat provider.tf
provider "aws" {
version = "~> 2.0"
region = "ap-northeast-1"
access_key = "AKIXXXXXXXXXXXXXXXX"
secret_key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
需要分别获取access_key和secret_key。
请将添加awscli设置时查询到的访问密钥和秘密访问密钥替换掉。
terraform init是用于terraform的初始设置。
执行terraform init即可完成Terraform的初始设置。
terraform init是第一次执行的命令,执行此命令会读取provider.tf文件并自动获取所需的组件。由于我们声明要操作AWS,它会自动获取所需的组件以操作AWS。
只要执行一次,就无需再更新该文件夹中的.tf文件并重新执行。然而,如果更新了provider.tf并添加了组件,需要重新执行。可以多次执行而不会出现问题。
请在包含provider.tf文件的目录中执行terraform init命令。
yamanashi@DESKTOP-9KCV2CQ:~/studymyself/terraform/aws/make_ec2_01$ terraform init
Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/aws versions matching "~> 2.0"...
- Installing hashicorp/aws v2.70.0...
- Installed hashicorp/aws v2.70.0 (self-signed, key ID 34365D9472D7468F)
~snip~
Terraform has been successfully initialized!
You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.
If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.
若显示出” Terraform已成功初始化!”即为正常。
你現在可以開始創建provider.tf以外的其他.tf文件。
vpc.tf 的翻译为:
虚拟专用云.tf
VPC代表着AWS虚拟网络。创建以便部署EC2实例。在AWS中,不能将EC2实例直接放置在VPC网络下,因此还需要子网,所以需要在vpc.tf文件中都进行配置。
请创建vpc.tf文件,并输入以下代码。
resource "aws_vpc" "test-vpc" {
cidr_block = "10.40.0.0/16"
instance_tenancy = "default"
enable_dns_support = true
enable_dns_hostnames = true
tags = {
Name = "test-main"
}
}
resource "aws_subnet" "test-subnet-a" {
vpc_id = aws_vpc.test-vpc.id
cidr_block = "10.40.0.0/24"
availability_zone = "ap-northeast-1a"
map_public_ip_on_launch = true
tags = {
Name = "test-subnet-a"
}
}
igw.tf 可以在中文母语环境中进行概括为 “igw.tf”。
为了将VPC连接到互联网,需要使用互联网网关。
请创建igw.tf,并输入以下代码。
resource "aws_internet_gateway" "test-igw" {
vpc_id = aws_vpc.test-vpc.id
tags = {
Name = "main-igw"
}
}
需要将vpc_id替换为之前创建的vpc的id。
正如前面所提到的,通过上述方式可以传递已创建的test-vpc的id。
实时转发.tk
当出现对外通信时,需要一个路由表将其定向到互联网网关。
请创建一个名为rt.tf的文件,并输入以下代码。
resource "aws_route_table" "test-routetable" {
vpc_id = aws_vpc.test-vpc.id
tags = {
Name = "test-routetable"
}
}
resource "aws_route" "route-to-igw" {
route_table_id = aws_route_table.test-routetable.id
gateway_id = aws_internet_gateway.test-igw.id
destination_cidr_block = "0.0.0.0/0"
}
resource "aws_route_table_association" "rt_association" {
subnet_id = aws_subnet.test-subnet-a.id
route_table_id = aws_route_table.test-routetable.id
}
这里,关于 Terraform 的麻烦点是,在创建 AWS 路由表(aws_route_table)之后,我们需要使用 aws_route 创建路由。而 aws_route_table_association 则是用来将路由表和子网关联起来的资源。
换句话说,aws_route 和 aws_route_table_association 并没有具体的实体,很难形象化。



还有其他需要这样写资源的情况。而且在大多数情况下,这是很难调查的。
cc.sg
安全组本身是通信规则。它包括进入通信(入站)和离开通信(出站)两种通信方式,对于每种方式,安全组规定了允许通过的通信规则。
我們將在本次操作中創建用於EC2實例的安全群組。
请创建一个sg.tf文件,并输入以下代码。
resource "aws_security_group" "test-sg" {
name = "test-sg"
vpc_id = aws_vpc.test-vpc.id
description = "test sg"
}
resource "aws_security_group_rule" "inbound_ssh" {
type = "ingress"
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = [
"0.0.0.0/0"
]
security_group_id = aws_security_group.test-sg.id
}
resource "aws_security_group_rule" "outbound_all" {
type = "egress"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = [
"0.0.0.0/0"
]
security_group_id = aws_security_group.test-sg.id
}
创建名为test-sg的安全组,并为其创建一个入站规则和一个出站规则。
用于外部通过ssh连接的规则:aws_security_group_rule.inbound_ssh
用于内部向外部连接的规则:aws_security_group_rule.outbound_all
尽管安全组相当松散,但我们会先使用这个进行推进。
ec2.tf 的中文释义是什么呢?
创建EC2实例,它是主要角色。获取并将弹性IP地址与创建的实例关联,以便进行外部连接。
请创建ec2.tf文件并输入以下代码。
resource "aws_instance" "terraform-ec2-01" {
ami = "ami-02892a4ea9bfa2192"
availability_zone = "ap-northeast-1a"
instance_type = "t2.micro"
key_name = "study_ec2"
subnet_id = aws_subnet.test-subnet-a.id
vpc_security_group_ids = [aws_security_group.test-sg.id]
associate_public_ip_address = false
private_ip = "10.40.0.10"
root_block_device {
volume_type = "gp2"
volume_size = 8
delete_on_termination = true
}
tags = {
"Name" = "terraform-ec2-01"
}
lifecycle {
ignore_changes = all
}
}
resource "aws_eip" "ec2-eip" {
instance = aws_instance.terraform-ec2-01.id
vpc = true
}
aws_eip是在AWS上获取的弹性IP。如果没有使用,只获取而不使用会产生费用。
key_name指定了用于连接的密钥对。在下面的页面中,我们指定了我们创建的密钥对,但您可以更改为任何其他密钥对。您需要预先创建它,所以如果您还没有创建,请在继续之前创建密钥对。
创建资源
由于.tf文件已经创建完成,现在将使用terraform进行建设。
目前应该有6个.tf文件存在。
yamanashi@DESKTOP-9KCV2CQ:~/studymyself/terraform/aws/make_ec2_01$ tree
.
├── ec2.tf
├── igw.tf
├── provider.tf
├── rt.tf
├── sg.tf
└── vpc.tf
0 directories, 6 files
请先执行terraform plan。
如果资源名称或配置名称有任何错误,将在此处被拒绝。请适当进行修正。
如果没有问题,请执行terraform apply。
yamanashi@DESKTOP-9KCV2CQ:~/studymyself/terraform/aws/make_ec2_01$ terraform apply
~snip~
Plan: 11 to add, 0 to change, 0 to destroy.
Warning: Version constraints inside provider configuration blocks are deprecated
on provider.tf line 2, in provider "aws":
2: version = "~> 2.0"
Terraform 0.13 and earlier allowed provider version constraints inside the
provider configuration block, but that is now deprecated and will be removed
in a future version of Terraform. To silence this warning, move the provider
version constraint into the required_providers block.
Do you want to perform these actions?
Terraform will perform the actions described above.
Only 'yes' will be accepted to approve.
Enter a value: yes
~snip~
Apply complete! Resources: 11 added, 0 changed, 0 destroyed.
创建了11个资源,并已完成。
连接到创建的实例
包含一些在浏览器上的工作。


如果在保存密钥对的目录中执行复制的命令,则可以登录到创建的EC2。
yamanashi@DESKTOP-9KCV2CQ:~/studymyself$ ls
study_ec2.pem terraform
yamanashi@DESKTOP-9KCV2CQ:~/studymyself$ ssh -i "study_ec2.pem" ec2-user@ec2-54-150-79-122.ap-northeast-1.compute.amazonaws.com
The authenticity of host 'ec2-54-150-79-122.ap-northeast-1.compute.amazonaws.com (54.150.79.122)' can't be established.
ECDSA key fingerprint is SHA256:9u4mfukp5J4XzjmVhrE8JcLY9GiELAVbG+OByyHJ4vA.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'ec2-54-150-79-122.ap-northeast-1.compute.amazonaws.com,54.150.79.122' (ECDSA) to the list of known hosts.
__| __|_ )
_| ( / Amazon Linux 2 AMI
___|\___|___|
https://aws.amazon.com/amazon-linux-2/
12 package(s) needed for security, out of 42 available
Run "sudo yum update" to apply all updates.
[ec2-user@ip-10-40-0-10 ~]$
[ec2-user@ip-10-40-0-10 ~]$
我成功登录了。
重新创建并再次登录
如果成功登录了,下一步我们尝试使用 terraform 删除并重新创建此实例。
具体操作是在工作目录中运行 terraform destroy,等待删除完成后再次运行 terraform apply。由于会重新分配 DNS,请重新获取或相应地修正 ssh 命令。
通过使用Terraform,在基础架构上实现一键删除和创建,可以迅速进行故障恢复。
我认为使用Terraform是为了在一个提供相同功能的系统基础上实现规模较小的操作目标。