Localstackは、クラウドアプリケーションを開発するためのクラウドサービスエミュレーターをコンテナで提供してくれるものだけど、無料で使えるCommunity版でもAWSアカウント無しでAWS APIを叩けるようになるから、TerraformでAWS環境を作る時の入門、学習用に打って付け!
Community版ではRDSのAPI叩けないとかEC2は実際にVMとして動かないとか、Pro版との違いはあるけど、Terraform学習の入り口としては充分。
用意するもの
AlmaLinux 9
最小セットアップしたAlmaLinux 9.0 x86_64
メモリは2GBでもなんとか足りる
Docker
公式手順に従う
インストール
$ sudo yum install -y yum-utils
$ sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
$ sudo yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin
自動起動有効化と起動
$ sudo systemctl enable --now docker
自分のユーザーに権限付与
$ sudo usermod -aG docker `whoami`
SSHを一度抜けて入り直す
確認
$ docker version
Client: Docker Engine - Community
Version: 20.10.21
API version: 1.41
Go version: go1.18.7
Git commit: baeda1f
Built: Tue Oct 25 18:02:16 2022
OS/Arch: linux/amd64
Context: default
Experimental: true
Server: Docker Engine - Community
Engine:
Version: 20.10.21
API version: 1.41 (minimum version 1.12)
Go version: go1.18.7
Git commit: 3056208
Built: Tue Oct 25 18:00:01 2022
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.6.9
GitCommit: 1c90a442489720eec95342e1789ee8a5e1b9536f
runc:
Version: 1.1.4
GitCommit: v1.1.4-0-g5fd4c4d
docker-init:
Version: 0.19.0
GitCommit: de40ad0
Localstack
公式手順に従う
インストール
$ sudo yum install -y python3-pip
$ python3 -m pip install localstack
確認
$ localstack --version
1.2.0
Dockerイメージをpull
$ docker pull localstack/localstack
起動
$ localstack start -d
AWS CLI
公式手順に従う
インストール
$ sudo yum install -y unzip
$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
$ unzip awscliv2.zip
$ sudo ./aws/install
確認
$ aws --version
aws-cli/2.8.7 Python/3.9.11 Linux/5.14.0-70.26.1.el9_0.x86_64 exe/x86_64.almalinux.9 prompt/off
awslocal
エンドポイントをLocalstackに向けてAWS CLI実行してもいいけど、その辺をいい感じにしてくれるawscli-localを使う
公式手順に従う
インストール
$ python3 -m pip install awscli-local
確認
$ awslocal --version
aws-cli/2.8.7 Python/3.9.11 Linux/5.14.0-70.26.1.el9_0.x86_64 exe/x86_64.almalinux.9 prompt/off
tfenv
公式手順に従う
インストール
$ sudo yum install git
$ git clone --depth=1 https://github.com/tfutils/tfenv.git ~/.tfenv
$ mkdir ~/bin
$ ln -s ~/.tfenv/bin/* ~/bin/
確認
$ tfenv --version
tfenv 3.0.0
Terraform
tfenvを使う
インストール
$ tfenv install latest
$ tfenv use latest
確認
$ terraform version
Terraform v1.3.3
on linux_amd64
tflocal
AWS CLIと同じようにTerraformもエンドポイントをLocalstackに変えられるけど、awslocalと同じようにいい感じにしてくれるtflocalを使う方が楽
インストール
$ python3 -m pip install terraform-local
確認
$ tflocal version
Terraform v1.3.3
on linux_amd64
自習の入口
AWS CLIでVPC一覧を確認
$ awslocal ec2 describe-vpcs
{
"Vpcs": [
{
"CidrBlock": "172.31.0.0/16",
"DhcpOptionsId": "dopt-7a8b9c2d",
"State": "available",
"VpcId": "vpc-adead4e7",
"OwnerId": "000000000000",
"InstanceTenancy": "default",
"Ipv6CidrBlockAssociationSet": [],
"CidrBlockAssociationSet": [
{
"AssociationId": "vpc-cidr-assoc-b6712cac",
"CidrBlock": "172.31.0.0/16",
"CidrBlockState": {
"State": "associated"
}
}
],
"IsDefault": true,
"Tags": []
}
]
}
既に1つある
AWS CLIでVPCを作ってみる
$ awslocal ec2 create-vpc --cidr-block 10.0.0.0/16
{
"Vpc": {
"CidrBlock": "10.0.0.0/16",
"DhcpOptionsId": "dopt-1a2b3c4d2",
"State": "pending",
"VpcId": "vpc-4b1cc5d5",
"OwnerId": "000000000000",
"InstanceTenancy": "default",
"Ipv6CidrBlockAssociationSet": [],
"CidrBlockAssociationSet": [
{
"AssociationId": "vpc-cidr-assoc-66e6af95",
"CidrBlock": "10.0.0.0/16",
"CidrBlockState": {
"State": "associated"
}
}
],
"Tags": []
}
}
再度確認
$ awslocal ec2 describe-vpcs
{
"Vpcs": [
{
"CidrBlock": "172.31.0.0/16",
"DhcpOptionsId": "dopt-7a8b9c2d",
"State": "available",
"VpcId": "vpc-adead4e7",
"OwnerId": "000000000000",
"InstanceTenancy": "default",
"Ipv6CidrBlockAssociationSet": [],
"CidrBlockAssociationSet": [
{
"AssociationId": "vpc-cidr-assoc-b6712cac",
"CidrBlock": "172.31.0.0/16",
"CidrBlockState": {
"State": "associated"
}
}
],
"IsDefault": true,
"Tags": []
},
{
"CidrBlock": "10.0.0.0/16",
"DhcpOptionsId": "dopt-7a8b9c2d",
"State": "available",
"VpcId": "vpc-4b1cc5d5",
"OwnerId": "000000000000",
"InstanceTenancy": "default",
"Ipv6CidrBlockAssociationSet": [],
"CidrBlockAssociationSet": [
{
"AssociationId": "vpc-cidr-assoc-66e6af95",
"CidrBlock": "10.0.0.0/16",
"CidrBlockState": {
"State": "associated"
}
}
],
"IsDefault": false,
"Tags": []
}
]
}
追加された
今度はTerraformでVPCを追加してみる
以下の内容でtfファイルを用意、名前は test.tf でも main.tf でもお好みで
書き方は公式ドキュメント参照
provider "aws" {
region = "ap-northeast-1"
}
resource "aws_vpc" "main" {
cidr_block = "10.1.0.0/16"
}
terraform init
$ tflocal init
Initializing the backend...
Initializing provider plugins...
- Finding latest version of hashicorp/aws...
- Installing hashicorp/aws v4.37.0...
- Installed hashicorp/aws v4.37.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 plan
$ tflocal 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_vpc.main will be created
+ resource "aws_vpc" "main" {
+ arn = (known after apply)
+ cidr_block = "10.1.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 = (known after apply)
+ enable_dns_support = true
+ enable_network_address_usage_metrics = (known after apply)
+ id = (known after apply)
+ instance_tenancy = "default"
+ ipv6_association_id = (known after apply)
+ ipv6_cidr_block = (known after apply)
+ ipv6_cidr_block_network_border_group = (known after apply)
+ main_route_table_id = (known after apply)
+ owner_id = (known after apply)
+ tags_all = (known after apply)
}
Plan: 1 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.
意図したVPCが1つ作られそうだ。
適用してみる
$ tflocal apply
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_vpc.main will be created
+ resource "aws_vpc" "main" {
+ arn = (known after apply)
+ cidr_block = "10.1.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 = (known after apply)
+ enable_dns_support = true
+ enable_network_address_usage_metrics = (known after apply)
+ id = (known after apply)
+ instance_tenancy = "default"
+ ipv6_association_id = (known after apply)
+ ipv6_cidr_block = (known after apply)
+ ipv6_cidr_block_network_border_group = (known after apply)
+ main_route_table_id = (known after apply)
+ owner_id = (known after apply)
+ tags_all = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
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
aws_vpc.main: Creating...
╷
│ Error: error reading EC2 VPC (vpc-b9f4c5aa) Attribute (enableNetworkAddressUsageMetrics): InvalidParameterValue: Value enable_network_address_usage_metrics is invalid for parameter.
│ status code: 400, request id: CWMCFQLTVBC1HQEIYX2S3UKCEJU9M09T7JVS4T1W2HU2AATC5LMW
│
│ with aws_vpc.main,
│ on main.tf line 5, in resource "aws_vpc" "main":
│ 5: resource "aws_vpc" "main" {
あら?Errorだ
AWS Providerの4.35.0から入ったenable_network_address_usage_metricsが悪さをしているらしいので、enable_network_address_usage_metricsがまだ入っていなかった4.34.0に戻す。
(Errorが出ないなら戻さなくていい)
$ cat main.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "4.34.0"
}
}
}
provider "aws" {
region = "ap-northeast-1"
}
resource "aws_vpc" "main" {
cidr_block = "10.1.0.0/16"
}
再度terraform init
$ tflocal init -upgrade
Initializing the backend...
Initializing provider plugins...
- Finding hashicorp/aws versions matching "4.34.0"...
- Installing hashicorp/aws v4.34.0...
- Installed hashicorp/aws v4.34.0 (signed by HashiCorp)
Terraform has made some changes to the provider dependency selections recorded
in the .terraform.lock.hcl file. Review those changes and commit them to your
version control system if they represent changes you intended to make.
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.
一旦潰す
$ tflocal destroy
aws_vpc.main: Refreshing state... [id=vpc-b9f4c5aa]
Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
- destroy
Terraform will perform the following actions:
# aws_vpc.main will be destroyed
- resource "aws_vpc" "main" {
- arn = "arn:aws:ec2:us-east-1:000000000000:vpc/vpc-b9f4c5aa" -> null
- assign_generated_ipv6_cidr_block = false -> null
- cidr_block = "10.1.0.0/16" -> null
- default_network_acl_id = "acl-8af5b4fb" -> null
- default_route_table_id = "rtb-4e2c6219" -> null
- default_security_group_id = "sg-1e077d9bc992d098c" -> null
- dhcp_options_id = "dopt-7a8b9c2d" -> null
- enable_classiclink = false -> null
- enable_classiclink_dns_support = false -> null
- enable_dns_hostnames = false -> null
- enable_dns_support = true -> null
- id = "vpc-b9f4c5aa" -> null
- instance_tenancy = "default" -> null
- ipv6_netmask_length = 0 -> null
- main_route_table_id = "rtb-4e2c6219" -> null
- owner_id = "000000000000" -> null
- tags = {} -> null
- tags_all = {} -> null
}
Plan: 0 to add, 0 to change, 1 to destroy.
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
aws_vpc.main: Destroying... [id=vpc-b9f4c5aa]
aws_vpc.main: Destruction complete after 0s
Destroy complete! Resources: 1 destroyed.
再度作る
$ tflocal apply
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_vpc.main will be created
+ resource "aws_vpc" "main" {
+ arn = (known after apply)
+ cidr_block = "10.1.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 = (known after apply)
+ enable_dns_support = true
+ id = (known after apply)
+ instance_tenancy = "default"
+ ipv6_association_id = (known after apply)
+ ipv6_cidr_block = (known after apply)
+ ipv6_cidr_block_network_border_group = (known after apply)
+ main_route_table_id = (known after apply)
+ owner_id = (known after apply)
+ tags_all = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.
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
aws_vpc.main: Creating...
aws_vpc.main: Creation complete after 0s [id=vpc-128325bd]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
今度は問題ない
AWS CLIで確認
$ awslocal ec2 describe-vpcs
{
"Vpcs": [
{
"CidrBlock": "172.31.0.0/16",
"DhcpOptionsId": "dopt-7a8b9c2d",
"State": "available",
"VpcId": "vpc-adead4e7",
"OwnerId": "000000000000",
"InstanceTenancy": "default",
"Ipv6CidrBlockAssociationSet": [],
"CidrBlockAssociationSet": [
{
"AssociationId": "vpc-cidr-assoc-b6712cac",
"CidrBlock": "172.31.0.0/16",
"CidrBlockState": {
"State": "associated"
}
}
],
"IsDefault": true,
"Tags": []
},
{
"CidrBlock": "10.0.0.0/16",
"DhcpOptionsId": "dopt-7a8b9c2d",
"State": "available",
"VpcId": "vpc-4b1cc5d5",
"OwnerId": "000000000000",
"InstanceTenancy": "default",
"Ipv6CidrBlockAssociationSet": [],
"CidrBlockAssociationSet": [
{
"AssociationId": "vpc-cidr-assoc-66e6af95",
"CidrBlock": "10.0.0.0/16",
"CidrBlockState": {
"State": "associated"
}
}
],
"IsDefault": false,
"Tags": []
},
{
"CidrBlock": "10.1.0.0/16",
"DhcpOptionsId": "dopt-7a8b9c2d",
"State": "available",
"VpcId": "vpc-128325bd",
"OwnerId": "000000000000",
"InstanceTenancy": "default",
"Ipv6CidrBlockAssociationSet": [],
"CidrBlockAssociationSet": [
{
"AssociationId": "vpc-cidr-assoc-a923e4e3",
"CidrBlock": "10.1.0.0/16",
"CidrBlockState": {
"State": "associated"
}
}
],
"IsDefault": false,
"Tags": []
}
]
}
問題ない
これでTerraformのドキュメントを見ながら色々と試せる環境ができた