使用Terraform轻松构建AWS环境
总结
我为了更深入理解Terraform,搭建了一个简单的AWS环境,如下所示。这篇文章记录了这个过程。
环境
Terraform版本:1.5.6
请做好准备。
-
- IAMユーザのアクセスキーとシークレットキーを用意します。
- 以下6つのファイルを準備します。
.
├── main.tf
├── variables.tf
├── vpc.tf
├── ec2.tf
├── rds.tf
└── output.tf
每个文件的细节
主.tf
对于要使用的供应商进行定义。
provider "aws" {
region = "ap-northeast-1"
}
# 自分のパブリックIP取得用
provider "http" {}
变量.tf
我会定义一个变量,用于参考他的文件。
variable "az_a" {
default = "ap-northeast-1a"
}
variable "az_d" {
default = "ap-northeast-1d"
}
variable "access_key" {
default = <アクセスキーを記載して下さい>
}
variable "secret_key" {
default = <シークレットキーを記載して下さい>
}
请为我创建一个名为vpc.tf的文件。
定义VPC及其相关资源。
# ---------------------------
# VPC
# ---------------------------
resource "aws_vpc" "practice_vpc"{
cidr_block = "10.0.0.0/16"
enable_dns_hostnames = true
tags = {
Name = "terraform-practice-vpc"
}
}
# ---------------------------
# Public Subnet
# ---------------------------
resource "aws_subnet" "practice_public_1a_sn" {
vpc_id = aws_vpc.practice_vpc.id
cidr_block = "10.0.1.0/24"
availability_zone = "${var.az_a}"
tags = {
Name = "terraform-practice-public-1a-sn"
}
}
# ---------------------------
# Private Subnet(1a)
# ---------------------------
resource "aws_subnet" "practice_private_1a_sn" {
vpc_id = aws_vpc.practice_vpc.id
cidr_block = "10.0.2.0/24"
availability_zone = "${var.az_a}"
tags = {
Name = "terraform-practice-private-1a-sn"
}
}
# ---------------------------
# Private Subnet(1d)
# ---------------------------
resource "aws_subnet" "practice_private_1d_sn" {
vpc_id = aws_vpc.practice_vpc.id
cidr_block = "10.0.3.0/24"
availability_zone = "${var.az_d}"
tags = {
Name = "terraform-practice-private-1d-sn"
}
}
# ---------------------------
# Internet Gateway
# ---------------------------
resource "aws_internet_gateway" "practice_igw" {
vpc_id = aws_vpc.practice_vpc.id
tags = {
Name = "terraform-practice-igw"
}
}
# ---------------------------
# Elastic IP
# ---------------------------
resource "aws_eip" "practice_eip" {
vpc = true
tags = {
Name = "terraform-practice-eip"
}
}
# ---------------------------
# NAT Gateway
# ---------------------------
resource "aws_nat_gateway" "practice_natgw" {
subnet_id = "${aws_subnet.practice_public_1a_sn.id}"
allocation_id = "${aws_eip.practice_eip.id}"
tags = {
Name = "terraform-practice-natgw"
}
}
# ---------------------------
# Route table(Public Subnet)
# ---------------------------
# Route table
resource "aws_route_table" "practice_public_rt" {
vpc_id = aws_vpc.practice_vpc.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.practice_igw.id
}
tags = {
Name = "terraform-practice-public-rt"
}
}
# SubnetとRoute tableの関連付け
resource "aws_route_table_association" "practice_public_rt_associate" {
subnet_id = aws_subnet.practice_public_1a_sn.id
route_table_id = aws_route_table.practice_public_rt.id
}
# ---------------------------
# Route table(Private Subnet)
# ---------------------------
# Route table
resource "aws_route_table" "practice_private_rt" {
vpc_id = aws_vpc.practice_vpc.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_nat_gateway.practice_natgw.id
}
tags = {
Name = "terraform-practice-private-rt"
}
}
# SubnetとRoute tableの関連付け
#Private Subnet(1a)
resource "aws_route_table_association" "practice_private_1a_rt_associate" {
subnet_id = aws_subnet.practice_private_1a_sn.id
route_table_id = aws_route_table.practice_private_rt.id
}
#Private Subnet(1d)
resource "aws_route_table_association" "practice_private_1d_rt_associate" {
subnet_id = aws_subnet.practice_private_1d_sn.id
route_table_id = aws_route_table.practice_private_rt.id
}
# ---------------------------
# Security Group
# ---------------------------
# 自分のパブリックIPを取得
data "http" "ifconfig" {
url = "http://ipv4.icanhazip.com/"
}
variable "allowed_cidr" {
default = null
}
locals {
myip = chomp(data.http.ifconfig.body)
allowed_cidr = (var.allowed_cidr == null) ? "${local.myip}/32" : var.allowed_cidr
}
# Security Group for EC2
resource "aws_security_group" "practice_ec2_sg" {
name = "terraform-practice-ec2-sg"
description = "For EC2 Linux"
vpc_id = aws_vpc.practice_vpc.id
tags = {
Name = "terraform-practice-ec2-sg"
}
# インバウンドルール
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = [local.allowed_cidr]
}
# アウトバウンドルール
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
# Security Group for RDS
resource "aws_security_group" "practice_rds_sg" {
name = "terraform-practice-rds-sg"
description = "For RDS"
vpc_id = aws_vpc.practice_vpc.id
tags = {
Name = "terraform-practice-rds-sg"
}
# インバウンドルール
ingress {
from_port = 5432
to_port = 5432
protocol = "tcp"
cidr_blocks = ["10.0.1.0/24"]
}
# アウトバウンドルール
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
ec2.tf的中文本地化版本:亚马逊EC2资源配置文件
我們將定義EC2及其相關資源。
# ---------------------------
# EC2 Key pair
# ---------------------------
variable "key_name" {
default = "terraform-practice-keypair"
}
# 秘密鍵のアルゴリズム設定
resource "tls_private_key" "practice_private_key" {
algorithm = "RSA"
rsa_bits = 2048
}
locals {
private_key_file = "<任意のディレクトリを記載して下さい>/${var.key_name}.id_rsa"
}
# 秘密鍵を作成
resource "local_file" "practice_private_key_pem" {
filename = "${local.private_key_file}"
content = "${tls_private_key.practice_private_key.private_key_pem}"
}
# 公開鍵をAWSのKey pairにインポート
resource "aws_key_pair" "practice_keypair" {
key_name = "${var.key_name}"
public_key = "${tls_private_key.practice_private_key.public_key_openssh}"
}
# ---------------------------
# EC2
# ---------------------------
# Amazon Linux 2 の最新版AMIを取得
data "aws_ssm_parameter" "amzn2_lapractice_ami" {
name = "/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2"
}
# EC2作成
resource "aws_instance" "practice_ec2"{
ami = data.aws_ssm_parameter.amzn2_lapractice_ami.value
instance_type = "t2.micro"
availability_zone = "${var.az_a}"
vpc_security_group_ids = [aws_security_group.practice_ec2_sg.id]
subnet_id = aws_subnet.practice_public_1a_sn.id
associate_public_ip_address = "true"
key_name = "${var.key_name}"
tags = {
Name = "terraform-practice-ec2"
}
}
rds.tf可以用中文进行原生的改写。
对于RDS及其相关资源进行定义。
# ---------------------------
# DB Subnet Group
# ---------------------------
resource "aws_db_subnet_group" "practice-dbsg" {
name = "praivate-dbsg"
subnet_ids = ["${aws_subnet.practice_private_1a_sn.id}", "${aws_subnet.practice_private_1d_sn.id}"]
tags = {
Name = "terraform-practice-dbsg"
}
}
# ---------------------------
# RDS
# ---------------------------
resource "aws_db_instance" "practice_rds" {
identifier = "practice-db"
allocated_storage = 20
availability_zone = "${var.az_a}"
storage_type = "gp2"
engine = "postgres"
engine_version = "14.7"
instance_class = "db.t3.micro"
db_name = <DB名を記載して下さい>
username = <ユーザ名を記載して下さい>
password = <PWを記載して下さい>
vpc_security_group_ids = ["${aws_security_group.practice_rds_sg.id}"]
db_subnet_group_name = "${aws_db_subnet_group.practice-dbsg.name}"
skip_final_snapshot = true
}
输出.tf
设定输出所创建的EC2实例的公共IP地址。
output "ec2_global_ips" {
value = "${aws_instance.practice_ec2.*.public_ip}"
}
建立环境
一旦准备好了,我们将使用Terraform命令进行实际构建。
初始化操作目录
执行terraform init,并安装所需的插件。
$ terraform init
Initializing the backend...
Initializing provider plugins...
- Finding latest version of hashicorp/aws...
- Finding latest version of hashicorp/local...
- Finding latest version of hashicorp/tls...
- Finding latest version of hashicorp/http...
- Installing hashicorp/aws v5.17.0...
- Installed hashicorp/aws v5.17.0 (signed by HashiCorp)
- Installing hashicorp/local v2.4.0...
- Installed hashicorp/local v2.4.0 (signed by HashiCorp)
- Installing hashicorp/tls v4.0.4...
- Installed hashicorp/tls v4.0.4 (signed by HashiCorp)
- Installing hashicorp/http v3.4.0...
- Installed hashicorp/http v3.4.0 (signed by HashiCorp)
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.
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已成功初始化!”的提示,就表示一切正常。
文法检查
执行”terraform validate”命令,检查tf文件的语法。
$ terraform validate
Success! The configuration is valid, but there were some validation warnings as shown above.
成功了!如果显示“配置有效”,那就没问题了。
确认创建的资源
执行 terraform plan 命令,以确认会创建哪些资源。
$ terraform plan
data.http.ifconfig: Reading...
data.http.ifconfig: Read complete after 0s [id=http://ipv4.icanhazip.com/]
data.aws_ssm_parameter.amzn2_lapractice_ami: Reading...
data.aws_ssm_parameter.amzn2_lapractice_ami: Read complete after 0s [id=/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2]
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_db_instance.practice_rds will be created
+ resource "aws_db_instance" "practice_rds" {
+ address = (known after apply)
+ allocated_storage = 20
+ apply_immediately = false
+ arn = (known after apply)
+ auto_minor_version_upgrade = true
+ availability_zone = "ap-northeast-1a"
+ backup_retention_period = (known after apply)
+ backup_target = (known after apply)
-------長いため途中省略-------
Plan: 20 to add, 0 to change, 0 to destroy.
Changes to Outputs:
+ ec2_global_ips = [
+ (known after apply),
]
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.
这个计划的结果可以大致分为以下三个部分。
-
- 作成:リソース名の後に「will be created」と表記されます。
-
- 変更:リソース名の後に、「will be updated inplace」と表記されます。
- 削除:リソース名の後に、「will be destoryed」と表記されます。
如果一切顺利,我们将创建20个新资源,没有任何更改或删除。
创建资源
当你运行terraform apply时,实际上会创建资源。
$ terraform apply
data.http.ifconfig: Reading...
data.http.ifconfig: Read complete after 0s [id=http://ipv4.icanhazip.com/]
data.aws_ssm_parameter.amzn2_lapractice_ami: Reading...
data.aws_ssm_parameter.amzn2_lapractice_ami: Read complete after 0s [id=/aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2]
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_db_instance.practice_rds will be created
+ resource "aws_db_instance" "practice_rds" {
+ address = (known after apply)
+ allocated_storage = 20
+ apply_immediately = false
+ arn = (known after apply)
+ auto_minor_version_upgrade = true
+ availability_zone = "ap-northeast-1a"
+ backup_retention_period = (known after apply)
+ backup_target = (known after apply)
-------長いため途中省略-------
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 #yesを入力します。
local_file.practice_private_key_pem: Creating...
aws_key_pair.practice_keypair: Creating...
aws_eip.practice_eip: Creating...
aws_vpc.practice_vpc: Creating...
-------長いため途中省略-------
Apply complete! Resources: 20 added, 0 changed, 0 destroyed.
Outputs:
ec2_global_ips = [
"xx.xx.xx.xx",
]
只要出现“申请完成!”就可以了。
我会从管理控制台上确认资源是否已经创建。
※也可以使用terraform show命令进行确认。
以下是EC2的示例,确认已成功创建。
清理环境
如果继续放置不管,将会发生收费,所以我会进行删除操作。
如果要进行删除,请执行terraform destroy命令。
※请务必十分注意,因为之前创建的所有资源将被删除。
$ terraform destroy
data.http.ifconfig: Reading...
tls_private_key.practice_private_key: Refreshing state... [id=xxx]
local_file.practice_private_key_pem: Refreshing state... [id=xxx]
data.http.ifconfig: Read complete after 0s [id=http://ipv4.icanhazip.com/]
data.aws_ssm_parameter.amzn2_lapractice_ami: Reading...
-------長いため途中省略-------
Do you really want to destroy all resources?
Terraform will destroy all your managed infrastructure, as shown above.
There is no undo. Only 'yes' will be accepted to confirm.
Enter a value: yes #yesを入力
local_file.practice_private_key_pem: Destroying... [id=xxx]
local_file.practice_private_key_pem: Destruction complete after 0s
aws_route_table_association.practice_private_1d_rt_associate: Destroying... [id=xxx]
aws_route_table_association.practice_private_1a_rt_associate: Destroying... [id=xxx]
-------長いため途中省略-------
Destroy complete! Resources: 20 destroyed.
只要显示”Destroy complete!”,就表示OK了。
最后使用terraform show来确认是否已经被删除。
$ terraform show
The state file is empty. No resources are represented.
我并没有被删除。
请提供更多上下文,以便正确理解您想要的翻译内容。
我参考了这个。
-
- https://kacfg.com/terraform-vpc-ec2/
-
- https://y-ohgi.com/introduction-terraform/handson/vpc/
- https://qiita.com/Brutus/items/cd5aab062ea6cebe436c