iT邦幫忙

2023 iThome 鐵人賽

DAY 15
0
DevOps

AWS ECS + Gitlab + Laravel + Terraform 從入門到摔坑系列 第 15

Day 15 Terraform import network resource

  • 分享至 

  • xImage
  •  

import ECR repository 後,我們要把 application 有關的 resource 全部 import、改由 terraform 管理。執行 Gitlab Runner 以及單純用來實驗的 MySQL server 的 EC2 instance 不在 import 範圍內,因為它們屬於輔助實驗才產生的 infrastructure,對 application 來說非必要,在不同環境與情境中可能會使用其他方式運行 Gitlab runner 跟 Database。

在 import 跟撰寫 terraform configuration 時,terraform 的 aws resource reference 是好夥伴,我們會在 import 需要知道 id(cloud 上真實 resource 的 identifier,不是 terraform resource id)是什麼、寫 configuration 時查閱有哪些參數可用…等等。

今天我們會先 import 跟網路有關的 resource,分別是 VPC、Subnet、Internet Gateway 以及 Route Table 相關 的 resource。(本日程式碼(原本想一口氣把所有 resource import 進來的飛速前進,結果馬上踩到問題,只好一個個慢慢來…)

VPC

import {
    to = aws_vpc.vpc
    id = "vpc-04828d35609756ab9"
}

得到 generated configuration(註:筆者寫此系列文時 configuration generation 的功能還在實驗中,可能後續 syntax 會有所修改):

resource "aws_vpc" "vpc" {
  assign_generated_ipv6_cidr_block     = false
  cidr_block                           = "172.16.0.0/16"
  enable_dns_hostnames                 = false
  enable_dns_support                   = true
  enable_network_address_usage_metrics = false
  instance_tenancy                     = "default"
  ipv4_ipam_pool_id                    = null
  ipv4_netmask_length                  = null
  ipv6_cidr_block                      = null
  ipv6_cidr_block_network_border_group = null
  ipv6_ipam_pool_id                    = null
  ipv6_netmask_length                  = 0
  tags = {
    Name = "my-app"
  }
  tags_all = {
    Name = "my-app"
  }
}

附帶 planning failed :)

https://ithelp.ithome.com.tw/upload/images/20230925/20160671or3mOHrHko.png

一樣先把 generated configuration 搬到 main.tf,接著看看 error 說些什麼?

看起來跟 IPv6 有關,但…我們又沒有要用 IPv6,把相關的參數都刪掉好了:

resource "aws_vpc" "vpc" {
    assign_generated_ipv6_cidr_block     = false
    cidr_block                           = "172.16.0.0/16"
    enable_dns_hostnames                 = false
    enable_dns_support                   = true
    enable_network_address_usage_metrics = false
    instance_tenancy                     = "default"
    ipv4_ipam_pool_id                    = null
    ipv4_netmask_length                  = null
    tags = {
        Name = "my-app"
    }
    tags_all = {
        Name = "my-app"
    }
}

再 plan 看看,耶!過了~那我們就直接 apply 把 vpc import 進來。

Subnets

import block:

import {
    to = aws_subnet.public_1a
    id = "subnet-02fbb0ca0bf2d6438"
}

import {
    to = aws_subnet.public_1c
    id = "subnet-0d219822dd60f4f83"
}

產生出的 configuration:

resource "aws_subnet" "public_1a" {
  assign_ipv6_address_on_creation                = false
  availability_zone                              = "ap-northeast-1a"
  availability_zone_id                           = "apne1-az4"
  cidr_block                                     = "172.16.0.0/24"
  customer_owned_ipv4_pool                       = null
  enable_dns64                                   = false
  enable_lni_at_device_index                     = 0
  enable_resource_name_dns_a_record_on_launch    = false
  enable_resource_name_dns_aaaa_record_on_launch = false
  ipv6_cidr_block                                = null
  ipv6_native                                    = false
  map_customer_owned_ip_on_launch                = false
  map_public_ip_on_launch                        = true
  outpost_arn                                    = null
  private_dns_hostname_type_on_launch            = "ip-name"
  tags = {
    Name = "my-app-public-1a"
  }
  tags_all = {
    Name = "my-app-public-1a"
  }
  vpc_id = "vpc-04828d35609756ab9"
}

resource "aws_subnet" "public_1c" {
  assign_ipv6_address_on_creation                = false
  availability_zone                              = "ap-northeast-1c"
  availability_zone_id                           = "apne1-az1"
  cidr_block                                     = "172.16.1.0/24"
  customer_owned_ipv4_pool                       = null
  enable_dns64                                   = false
  enable_lni_at_device_index                     = 0
  enable_resource_name_dns_a_record_on_launch    = false
  enable_resource_name_dns_aaaa_record_on_launch = false
  ipv6_cidr_block                                = null
  ipv6_native                                    = false
  map_customer_owned_ip_on_launch                = false
  map_public_ip_on_launch                        = false
  outpost_arn                                    = null
  private_dns_hostname_type_on_launch            = "ip-name"
  tags = {
    Name = "my-app-public-1c"
  }
  tags_all = {
    Name = "my-app-public-1c"
  }
  vpc_id = "vpc-04828d35609756ab9"
}

還是出現 error…QQ

https://ithelp.ithome.com.tw/upload/images/20230925/20160671gdriOxdrSC.png

看有什麼 error 就修正什麼,這邊我是刪掉兩個 subnet 的 availability_zone_idenable_lni_at_device_indexmap_customer_owned_ip_on_launch

Internet Gateway

import block:

import {
    to = aws_internet_gateway.igw
    id = "igw-01bd114b2559c0d00"
}

太好了,internet gateway 沒有 error,繼續 import。(沒有出現 error 的 import,筆者可能就不放 generated code 了)

Route Table

main route table 的 import block:

import {
    to = aws_default_route_table.main
    id = "vpc-04828d35609756ab9"
}

也沒有 error,持續 import,但看著 route 是空 array 有點小擔心……不過 terraform plan 也沒有說有 changes 就先繼續吧。

public route table 及其 route 們的 import block:

import {
    to = aws_route_table.public
    id = "rtb-083e58a57744577c7"
}

import {
    to = aws_route.internal
    id = "rtb-083e58a57744577c7_172.16.0.0/16"
}

import {
    to = aws_route.internet
    id = "rtb-083e58a57744577c7_0.0.0.0/0"
}

generated configuration:

resource "aws_route_table" "public" {
  propagating_vgws = []
  route = [{
    carrier_gateway_id         = ""
    cidr_block                 = "0.0.0.0/0"
    core_network_arn           = ""
    destination_prefix_list_id = ""
    egress_only_gateway_id     = ""
    gateway_id                 = "igw-01bd114b2559c0d00"
    ipv6_cidr_block            = ""
    local_gateway_id           = ""
    nat_gateway_id             = ""
    network_interface_id       = ""
    transit_gateway_id         = ""
    vpc_endpoint_id            = ""
    vpc_peering_connection_id  = ""
  }]
  tags = {
    Name = "my-app-rt-public"
  }
  tags_all = {
    Name = "my-app-rt-public"
  }
  vpc_id = "vpc-04828d35609756ab9"
}

resource "aws_route" "internet" {
  carrier_gateway_id          = null
  core_network_arn            = null
  destination_cidr_block      = "0.0.0.0/0"
  destination_ipv6_cidr_block = null
  destination_prefix_list_id  = null
  egress_only_gateway_id      = null
  gateway_id                  = "igw-01bd114b2559c0d00"
  local_gateway_id            = null
  nat_gateway_id              = null
  network_interface_id        = null
  route_table_id              = "rtb-083e58a57744577c7"
  transit_gateway_id          = null
  vpc_endpoint_id             = null
  vpc_peering_connection_id   = null
}

resource "aws_route" "internal" {
  carrier_gateway_id          = null
  core_network_arn            = null
  destination_cidr_block      = "172.16.0.0/16"
  destination_ipv6_cidr_block = null
  destination_prefix_list_id  = null
  egress_only_gateway_id      = null
  gateway_id                  = "local"
  local_gateway_id            = null
  nat_gateway_id              = null
  network_interface_id        = null
  route_table_id              = "rtb-083e58a57744577c7"
  transit_gateway_id          = null
  vpc_endpoint_id             = null
  vpc_peering_connection_id   = null
}

出現了 error:

https://ithelp.ithome.com.tw/upload/images/20230925/201606710QxYb1d413.png

terraform 幫我們在 aws_route_table.public resource 的 route 產生了 route 相關的 configuration,但是我們已經有另外 import route resource aws_route.internetaws_route.internal 了,這兩種 route 的定義方式不能混用 (ref),所以刪掉 aws_route_table.publicroute

Route table 與 subnet 的 association

沒錯!route table 跟 subnet 之間的 association 關係也是個 resource,寫 IaC 的其中一個困難是 resource 可能拆得很細,遺漏一些細部的 resource 的話它就……不會動。至於要怎麼知道有這麼多細部的 resource?筆者對於不熟悉的服務通常會先看 terraform resource reference 的 example,example 常常有常用的 scenario 可以參考。再來是 terraform 寫完後嘗試用同一份 code 再建立一次新的 infrastructure,看看整個運作是否如預期,不如預期通常是因為缺 resource。

route table 與 subnet 的 association 的 import block:

import {
  to = aws_route_table_association.public_1a
  id = "subnet-02fbb0ca0bf2d6438/rtb-083e58a57744577c7"
}

import {
  to = aws_route_table_association.public_1c
  id = "subnet-0d219822dd60f4f83/rtb-083e58a57744577c7"
}

generated configuration:

resource "aws_route_table_association" "public_1a" {
  gateway_id     = null
  route_table_id = "rtb-083e58a57744577c7"
  subnet_id      = "subnet-02fbb0ca0bf2d6438"
}

resource "aws_route_table_association" "public_1c" {
  gateway_id     = null
  route_table_id = "rtb-083e58a57744577c7"
  subnet_id      = "subnet-0d219822dd60f4f83"
}

把 main.tf 拆成多個 .tf

隨著 import 的 resource 越來越多,main.tf 也越來越龐大。terraform 不只可以在 main.tf 放 resource,在工作目錄下的 .tf 檔案都可以寫 resource。之後還會 import 更多 resource,我們先把網路相關的 resource 都移到 network.tf


上一篇
Day 14 Terraform import resource
下一篇
Day 16 Terraform import compute resource
系列文
AWS ECS + Gitlab + Laravel + Terraform 從入門到摔坑30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言