0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

既存AWS構成をTerraformでIaC化(VPC,API Gateway)

Posted at

はじめに

現在の以下の構成をTerraformでIaC化していきたいと思います。
image.png

内容としては
・VPC関連(VPC,Subnet,InternetGateway,RouteTable,SecurityGroup)
・API Gateway
の部分をまずはやっていきたいと思います。その他コンポーネントについては順次記事を追加投稿していきたいと思います。(長くなってしまうので)

※Subnetの種類としてPublic SubnetとPrivate Subnetを用意していますが、前提構成ではPublic Subnetしか利用していないので基本はPublic Subnetの設定を実施していきます。(Private Subnetは一部の検証を実施する際に利用した。詳細は以下記事)

IaC化

基本の流れ

まずは全てのコンポーネントに対して適用される基本の流れを確認。

  1. Terraformの公式Docでリソースタイプや個別パラメータなどを確認する。(各リソースページの一番下にはImportセクションが記載されているので、terafform importする際のコマンドも確認できる。)
  2. リソースを管理する.tfファイル(例:aws_vpc.tf)に必要なリソースセクションを用意する。
  3. terraform importを実行。
  4. terraform state showで既存構成を確認。
  5. 既存構成のうち、必要なパラメータや設定値を.tfファイルに記載する。
  6. terraform fmtterraform validateで内容を整備・確認。
  7. terraform planで既存構成と差分がないかを確認(追加変更する場合は差分があってOK)。
  8. もし意図しない差分があったら、再度4~7を実施して内容確認。意図した差分があるならterraform applyで変更を環境に反映する。

VPC関連サービス

VPC

最初のリソースなので基本の流れの内容を順を追って残しておく。
まずは公式Docからリソースタイプなどを確認。VPCは以下のようなブロックとなる。

aws_pubsub_vpc.tf
resource "aws_vpc" "main" {
  cidr_block = "10.0.0.0/16"
}

今回は既存環境をIaC化するので、リソースタイプはそのままにしてVPC名は既存のVPC名に書き換え、cidr_blockなども記載なしにした.tfファイルを以下のように用意する。

aws_pubsub_vpc.tf
resource "aws_vpc" "pubsub-vpc" {
 
}

公式Docにはterraform importする際の例も以下のように記載されているので確認。

Using terraform import, import VPCs using the VPC id. For example:
% terraform import aws_vpc.test_vpc vpc-a01106c2

上記のコマンド例に沿って自分のIaC化実施環境でもコマンドを打つ

terraform import aws_vpc.pubsub-vpc [既存のVPCIDをコンソールから確認して入力]

Importされた。
image.png

次にterraform state showで既存構成を確認する。

terraform state show aws_vpc.pubsub-vpc

出力された構成情報のうち、デフォルト値を除いた必須項目などをtfファイルに記載していく。

aws_pubsub_vpc.tf
#----------------------------------------
# Create VPC
#----------------------------------------
resource "aws_vpc" "pubsub-vpc" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_hostnames = true
  tags = {
    Name = "pubsub-vpc"
  }
}

フォーマットの整備や、(念のため)構文エラーなどもないかを確認。

terraform fmt 
terraform validate

上記OKであれば、terraform planで記載内容と既存構成内容の差分を確認。

terraform plan

差分がなければ以下のように表示される。
image.png

ここまでで既存構成のIaC化は完了。既存構成に対して構成差分がある場合はterraform applyで内容を反映する。

Subnet

以降のリソースはIaC化された後の状態のtfファイルのみ残しておく。VPC関連のサービスは同じファイルに記載して管理する。

aws_pubsub_vpc.tf
#----------------------------------------
# Create Public Subnet
#----------------------------------------
resource "aws_subnet" "pubsub-subnet-public1-ap-northeast-1a" {
  vpc_id            = aws_vpc.pubsub-vpc.id
  availability_zone = "ap-northeast-1a"
  cidr_block        = "10.0.0.0/20"
  tags = {
    Name = "pubsub-subnet-public1-ap-northeast-1a"
  }
}

resource "aws_subnet" "pubsub-subnet-public2-ap-northeast-1c" {
  vpc_id            = aws_vpc.pubsub-vpc.id
  availability_zone = "ap-northeast-1c"
  cidr_block        = "10.0.16.0/20"
  tags = {
    Name = "pubsub-subnet-public2-ap-northeast-1c"
  }
}

#----------------------------------------
# Create Private Subnet
#----------------------------------------
resource "aws_subnet" "pubsub-subnet-private1-ap-northeast-1a" {
  vpc_id            = aws_vpc.pubsub-vpc.id
  availability_zone = "ap-northeast-1a"
  cidr_block        = "10.0.128.0/20"
  tags = {
    Name = "pubsub-subnet-private1-ap-northeast-1a"
  }
}

resource "aws_subnet" "pubsub-subnet-private2-ap-northeast-1c" {
  vpc_id            = aws_vpc.pubsub-vpc.id
  availability_zone = "ap-northeast-1c"
  cidr_block        = "10.0.144.0/20"
  tags = {
    Name = "pubsub-subnet-private2-ap-northeast-1c"
  }
}

Internet Gateway

aws_pubsub_vpc.tf
#----------------------------------------
# Create Internet Gateway
#----------------------------------------
resource "aws_internet_gateway" "pubsub-igw" {
  vpc_id = aws_vpc.pubsub-vpc.id
  tags = {
    Name = "pubsub-igw"
  }
}

Route Table

aws_pubsub_vpc.tf
#----------------------------------------
# Create RouteTable
#----------------------------------------
# RouteTable for Public Subnet
resource "aws_route_table" "pubsub-rtb-public" {
  vpc_id = aws_vpc.pubsub-vpc.id
  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.pubsub-igw.id
  }
  tags = {
    Name = "pubsub-rtb-public"
  }
}

# RouteTable for Private Subnet
resource "aws_route_table" "pubsub-rtb-private" {
  vpc_id = aws_vpc.pubsub-vpc.id
  tags = {
    Name = "pubsub-rtb-private"
  }
}

#----------------------------------------
# Attach RouteTable to Subnet
#----------------------------------------
resource "aws_route_table_association" "public_rt_assoc" {
  subnet_id      = aws_subnet.pubsub-subnet-public1-ap-northeast-1a.id
  route_table_id = aws_route_table.pubsub-rtb-public.id
}

resource "aws_route_table_association" "public_rt_assoc2" {
  subnet_id      = aws_subnet.pubsub-subnet-public2-ap-northeast-1c.id
  route_table_id = aws_route_table.pubsub-rtb-public.id
}

resource "aws_route_table_association" "private1_rt_assoc" {
  subnet_id      = aws_subnet.pubsub-subnet-private1-ap-northeast-1a.id
  route_table_id = aws_route_table.pubsub-rtb-private.id
}

resource "aws_route_table_association" "private2_rt_assoc" {
  subnet_id      = aws_subnet.pubsub-subnet-private2-ap-northeast-1c.id
  route_table_id = aws_route_table.pubsub-rtb-private.id
}

Security Group

aws_pubsub_vpc.tf
#----------------------------------------
# Create Security Group
#----------------------------------------
resource "aws_security_group" "pubsub-public-sg" {
  name   = "pubsub-public-sg"
  vpc_id = aws_vpc.pubsub-vpc.id
  description = "public security group"

  ingress {
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
    self        = true
  }

  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = {
    Name = "pubsub-public-sg"
  }
}

API Gateway

次にAPI Gatewayの構成部分をTerraformでIaC化していく。

aws_pubsub_apigw.tf
# #----------------------------------------
# # Create API Gateway
# #----------------------------------------
resource "aws_api_gateway_rest_api" "pubsubApi" {
  name        = "pubsubApi"
  description = "Api to call publisher lambda"
  endpoint_configuration {
    types = ["REGIONAL"]
  }
}

resource "aws_api_gateway_resource" "pubsubApi" {
  rest_api_id = aws_api_gateway_rest_api.pubsubApi.id
  parent_id   = aws_api_gateway_rest_api.pubsubApi.root_resource_id
  path_part   = "publishtopic"
}

resource "aws_api_gateway_authorizer" "pubsubApi" {
  name        = "PubSubLambdaAuthorizer"
  rest_api_id = aws_api_gateway_rest_api.pubsubApi.id
  authorizer_uri                   = data.aws_lambda_function.AuthForPubSub.invoke_arn
  authorizer_result_ttl_in_seconds = 0
  type                             = "REQUEST"
}

resource "aws_api_gateway_method" "pubsubApi" {
  http_method   = "POST"
  authorization = "CUSTOM"
  authorizer_id = aws_api_gateway_authorizer.pubsubApi.id
  resource_id   = aws_api_gateway_resource.pubsubApi.id
  rest_api_id   = aws_api_gateway_rest_api.pubsubApi.id
}

resource "aws_api_gateway_deployment" "pubsubApi" {
  rest_api_id = aws_api_gateway_rest_api.pubsubApi.id
}

resource "aws_api_gateway_stage" "pubsubApi" {
  rest_api_id   = aws_api_gateway_rest_api.pubsubApi.id
  stage_name    = "dev"
  deployment_id = aws_api_gateway_deployment.pubsubApi.id
  description   = "dev stage for pubsub api"
}

resource "aws_api_gateway_integration" "pubsubApi" {
  rest_api_id             = aws_api_gateway_rest_api.pubsubApi.id
  resource_id             = aws_api_gateway_resource.pubsubApi.id
  http_method             = "POST"
  type                    = "AWS_PROXY"
  uri                     = data.aws_lambda_function.deliverTopicToSNS_Test01.invoke_arn
  content_handling        = "CONVERT_TO_TEXT"
  integration_http_method = "POST"
}

上記で参照しているdata.aws_lambda_function.AuthForPubSub.invoke_arndata.aws_lambda_function.deliverTopicToSNS_Test01.invoke_arnの部分については別ファイルaws_pubsub_lambda.tfで記述している。実際のLambdaの中身自体も同様にTerraformで管理できるようにしたいが、その内容についてはLambdaのIaC化セクションで行うこととし、現状では既存のコード(コンソール上にある)を参照できるところまでにしておく。

aws_pubsub_lambda.tf
data "aws_lambda_function" "AuthForPubSub" {
  function_name = "AuthForPubSub"
}

data "aws_lambda_function" "deliverTopicToSNS_Test01" {
  function_name = "deliverTopicToSNS_Test01"
}

一旦ここまででVPC回りとAPI Gateway回りのIaCはできている(はず)。次回は既存のLambdaの部分をTerraformでスムーズに管理できるところを実施していきたい。

おわりに

一旦ここまで実施するのにも割と時間がかかりました。既存の構成をimportして差分が無いようにIaC化するのには労力かかる面もあるので、やはり最初からIaCを念頭に構築できればベストだと思います。途中からIaC化する場合は、IaC化することによるメリットや費用対効果なども考慮しながら検討する必要がありそうです。次回以降はLambda部分やその他の既存構成部分をTerraformでIaC化していきたいと思います。

参考サイト

今後のTerraform活動でも何回か参照しそうなので載せておく。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?