Загружаем каталог…
Загружаем каталог…
개요 2편 에서 OU, 계정, SCP까지 구성했으니 이번에는 Network입니다. LZA에서 Network는 network-config.yaml 파일 하나로 관리합니다. IPAM, Transit Gateway, VPC, Routing이 전부 이 파일에 들어가서 설정 파일 6개 중에 제일 깁니다. 제 환경에서도 지금 20KB 정도 됩니다. 이번 글에서 다루는 내용은 아래와 같습니다. 기본 VPC 삭제 IPAM으로 CIDR 나누기 서울 Region Transit Gateway 만들고 다른 계정에 공유하기 중앙 egress용 inspection VPC, Workload VPC 만들기 배포하다 실패한 것, 안 쓰는 Network 비용 정리한 것 처음에는 서울 / 버지니아 / 오레곤 세 Region에 TGW를 하나씩 두고 peering으로 다 엮었습니다. 그런데 막상 써 보니 실제로 쓰는 건 서울뿐이라 나머지는 정리했고, 그 얘기도 뒤에 같이 적었습니다. 계정 ID는 111122223333 으로 가렸습니다. 설정 파일은 실제로 쓰는 파일에서 필요한 부분만 잘라 왔습니다. 이번 편의 최종 구성 network 계정에 Transit Gateway와 inspection VPC를 두고, 다른 계정의 VPC들은 TGW에 붙여서 Internet으로 나갈 때 inspection VPC의 NAT Gateway를 같이 쓰는 구조입니다. 흔히 말하는 중앙 집중식 egress입니다. 그림에 점선으로 그린 Workload 쪽 attachment는 지금은 꺼 둔 상태입니다. 이유는 뒤에 비용 얘기할 때 설명하겠습니다. 1. 기본 network-config.yaml LZA를 처음 설치하면 network-config.yaml 은 이렇게 생겼습니다. S3 config Bucket의 default/ 폴더에 설치 직후 파일이 남아 있어서 그대로 가져왔습니다. defaultVpc: delete: false excludeAccounts: [] transitGateways: [] endpointPolicies: [] vpcs: [] 이게 전부입니다. 여기서부터 하나씩 채워 나가면 됩니다. 제일 먼저 바꾼 건 defaultVpc.delete 입니다. 계정을 새로 만들면 Region마다 기본 VPC가 하나씩 생기는데, 이 값을 true 로 두면 LZA가 배포하는 계정/Region에서 기본 VPC를 지워 줍니다. defaultVpc: delete: true excludeAccounts: [] 기본 VPC가 남아 있으면 누군가 실수로 거기에 EC2를 띄울 수도 있어서 저는 그냥 지웠습니다. 특정 계정만 남기고 싶으면 excludeAccounts 에 넣으면 됩니다. 2. IPAM으로 CIDR 나누기 계정마다 VPC를 만들다 보면 CIDR 겹치는 게 제일 귀찮습니다. 나중에 TGW로 연결하려고 보면 이미 대역이 겹쳐 있어서 VPC를 다시 만들어야 하는 경우도 생기고요. 그래서 VPC CIDR을 직접 적지 않고 IPAM 풀에서 받아 오도록 했습니다. 먼저 전체 대역을 정했습니다. 172.16.0.0/12 를 /15 8개로 나눠서 Region마다 하나씩 줬습니다. CIDR Region 비고 172.16.0.0/15 ap-northeast-2 서울 (실제 사용) 172.18.0.0/15 us-east-1 버지니아 172.20.0.0/15 us-west-2 오레곤 172.22.0.0/15 ~ 172.30.0.0/15 - 예약 10.0.0.0/8 은 일부러 안 썼습니다. 나중에 외부 Network와 연결할 일이 생기면 10 대역이 제일 잘 겹쳐서 피했습니다. IPAM 설정은 centralNetworkServices 아래에 들어갑니다. 아래는 서울 풀 부분입니다. centralNetworkServices: delegatedAdminAccount: network ipams: - name: ipam-network region: us-east-1 description: Organization IPAM operatingRegions: - us-east-1 - us-west-2 - ap-northeast-2 pools: - name: pool-network-ane2 description: Regional pool - ap-northeast-2 (172.16.0.0/15) locale: ap-northeast-2 provisionedCidrs: - 172.16.0.0/15 allocationDefaultNetmaskLength: 20 allocationMinNetmaskLength: 17 allocationMaxNetmaskLength: 24 shareTargets: organizationalUnits: - Infrastructure - Security delegatedAdminAccount: network 로 Network 관리를 network 계정에 위임하고, 풀은 shareTargets 로 OU 단위로 공유합니다. VPC 쪽에서는 풀 이름이랑 크기만 적으면 됩니다. ipamAllocations: - ipamPoolName: pool-network-ane2 netmaskLength: 24 Subnet도 ipamAllocation 에 netmaskLength 만 적어 두면 VPC가 받은 대역 안에서 잘라서 줍니다. 덕분에 설정 파일에 CIDR 숫자를 거의 안 적어도 됩니다. 3. Transit Gateway TGW는 network 계정 서울 Region에 하나 만들었습니다. transitGateways: - name: tgw-network-ane2 account: network region: ap-northeast-2 shareTargets: organizationalUnits: - Infrastructure - Security - Sandbox - Workload asn: 65020 dnsSupport: enable vpnEcmpSupport: enable defaultRouteTableAssociation: disable defaultRouteTablePropagation: disable autoAcceptSharingAttachments: enable 몇 가지만 짚고 넘어가겠습니다. shareTargets : RAM으로 TGW를 OU에 공유합니다. 이걸 해야 다른 계정 VPC가 이 TGW에 붙을 수 있습니다. defaultRouteTableAssociation / Propagation: disable : 기본 Route Table을 쓰면 붙은 VPC끼리 전부 통신이 됩니다. 그래서 끄고 Route Table을 직접 만들었습니다. autoAcceptSharingAttachments: enable : 다른 계정에서 attachment 요청이 오면 자동으로 수락합니다. 이걸 안 켜면 network 계정에서 하나씩 수락해 줘야 합니다. asn : Region별로 다르게 줬습니다. (버지니아 65010, 서울 65020, 오레곤 65030) Route Table은 두 개입니다. TGW Route Table 연결(association) 하는 일 rt-tgw-network-ane2 inspection VPC attachment 각 VPC 대역이 propagation돼서 돌아오는 경로 rt-tgw-network-ane2-dev dev VPC attachment들 0.0.0.0/0 -> inspection VPC dev VPC에서 Internet으로 나가는 Traffic은 rt-tgw-network-ane2-dev 의 0/0 경로를 타고 inspection VPC로 가고, 거기 NAT Gateway를 통해 나갑니다. 돌아오는 Traffic은 rt-tgw-network-ane2 에 propagation된 VPC 대역을 보고 원래 VPC로 돌아옵니다. 처음에는 stg / prd 테이블도 따로 만들 생각이었는데, 지금은 dev만 있어서 두 개만 두고 있습니다. 4. VPC 구성 inspection VPC (network 계정) 다른 VPC들이 Internet으로 나갈 때 거쳐 가는 VPC입니다. Subnet은 용도별로 3개입니다. vpcs: - name: vpc-network-ane2-inspection account: network region: ap-northeast-2 ipamAllocations: - ipamPoolName: pool-network-ane2 netmaskLength: 24 internetGateway: true routeTables: - name: rt-network-ane2-tgw routes: - name: route-default-natgw destination: 0.0.0.0/0 type: natGateway target: natgw-network-ane2a - name: rt-network-ane2-natgw routes: - name: route-default-igw destination: 0.0.0.0/0 type: internetGateway target: IGW - name: route-internal-tgw destination: 172.16.0.0/12 type: transitGateway target: tgw-network-ane2 # (rt-network-ane2-nfw, subnets 생략) natGateways: - name: natgw-network-ane2a subnet: subnet-network-ane2a-natgw transitGatewayAttachments: - name: tgwatt-network-ane2-inspection transitGateway: name: tgw-network-ane2 account: network routeTableAssociations: - rt-tgw-network-ane2 routeTablePropagations: - rt-tgw-network-ane2-dev subnets: - subnet-network-ane2a-tgw 흐름은 이렇습니다. TGW에서 들어온 Traffic은 tgw Subnet에 도착하고, 0/0이 NAT Gateway로 가 있어서 NAT를 거쳐 IGW로 나갑니다. 돌아올 때는 natgw Subnet Route Table에 172.16.0.0/12 → TGW 가 있어서 다시 TGW로 들어갑니다. nfw Subnet은 원래 Network Firewall Endpoint 자리였습니다. 방화벽은 8월에 비용 때문에 지웠고, 지금은 Subnet만 남아 있습니다. 그리고 NAT Gateway는 비용 때문에 a존에 하나만 뒀습니다. 운영 환경이면 AZ마다 하나씩 두는 게 맞습니다. 배포하고 Console에서 Resource Map을 보면 이렇게 나옵니다. Workload VPC (seanson-workload-dev 계정) Workload VPC는 다른 계정에 있지만 설정은 같은 network-config.yaml 에 적습니다. account 만 바꿔 주면 LZA가 그 계정에 VPC를 만들어 줍니다. - name: vpc-workload-ane2-dev account: seanson-workload-dev region: ap-northeast-2 ipamAllocations: - ipamPoolName: pool-network-ane2 netmaskLength: 24 internetGateway: true routeTables: - name: rt-workload-ane2-private routes: - name: route-default-tgw destination: 0.0.0.0/0 type: transitGateway target: tgw-network-ane2 - name: route-internal-tgw destination: 172.16.0.0/12 type: transitGateway target: tgw-network-ane2 private Subnet의 0/0이 NAT Gateway가 아니라 TGW로 가 있습니다. 이렇게 하면 Workload 계정마다 NAT Gateway를 만들 필요가 없습니다. Subnet은 public(/28), private(/26), database(/27), tgw(/28)를 a·c 두 AZ에 하나씩 해서 8개입니다. TGW attachment용 Subnet은 작게 따로 빼 두었습니다. 5. 배포하고 확인하기 배포는 2편과 똑같습니다. 설정 파일을 zip으로 묶어서 config Bucket zipped/ 에 올리면 AWSAccelerator-Pipeline 이 돌기 시작합니다. Network 쪽은 Deploy 단계의 Network_Prepare -> Network_VPCs -> Network_Associations 순서로 진행됩니다. 대략 TGW·IPAM 같은 공용 Resource를 먼저 만들고, VPC·Subnet·Routing을 만든 다음, 마지막에 TGW 연결과 공유 쪽을 정리하는 순서입니다. 배포가 끝나고 network 계정에서 확인해 봤습니다. $ aws ec2 describe-transit-gateways --region ap-northeast-2 \ --query 'TransitGateways[].[Tags[?Key==`Name`]|[0].Value,State,Options.AmazonSideAsn]' --output table -------------------------------------------- | DescribeTransitGateways | +-------------------+-------------+--------+ | tgw-network-ane2 | available | 65020 | +-------------------+-------------+--------+ $ aws ec2 describe-transit-gateway-attachments --region ap-northeast-2 \ --query 'TransitGatewayAttachments[].[Tags[?Key==`Name`]|[0].Value,ResourceType,State]' --output table -------------------------------------------------------- | DescribeTransitGatewayAttachments | +---------------------------------+------+-------------+ | tgwatt-network-ane2-inspection | vpc | available | | None | vpc | available | +---------------------------------+------+-------------+ 이름이 None 으로 나오는 attachment는 LZA 밖에서 따로 붙인 것이라 이름 Tag가 없습니다. 6. 겪은 문제들 6-1. Route 이름 바꿨다가 Network_VPCs 실패 (2026-07-15) shared service VPC는 처음에 NAT Gateway를 따로 두고 있었습니다. 이걸 inspection VPC로 나가게 바꾸려고 private Route Table의 0/0을 NAT -> TGW로 바꿨는데, 이왕 바꾸는 김에 Route 이름도 내용에 맞게 route-default-tgw 로 바꿨습니다. - name: rt-sharedservice-ane2-private routes: - - name: route-default-natgw + - name: route-default-tgw destination: 0.0.0.0/0 - type: natGateway - target: natgw-sharedservice-ane2a + type: transitGateway + target: tgw-network-ane2 그리고 Pipeline을 돌렸더니 Network_VPCs 에서 실패했습니다. CodeBuild Log를 보면 이렇게 나와 있습니다. AWSAccelerator-RouteEntriesStack-vpc-sharedservice-ane2-111122223333-ap-northeast-2 | 6 | 1:21:46 AM | CREATE_FAILED | AWS::EC2::Route | VpcSharedserviceAne2VpcRtSharedserviceAne2PrivateRouteTableRouteDefaultTgwRouteEntry Resource handler returned message: "The route identified by 0.0.0.0/0 already exists. (Service: Ec2, Status Code: 400, ...)" Resource 이름을 보면 ...PrivateRouteTable RouteDefaultTgw RouteEntry 처럼 Route 이름이 CloudFormation Logical ID에 그대로 들어갑니다. 그래서 이름을 바꾸면 CloudFormation은 "기존 Route 수정"이 아니라 "새 Route 추가 + 기존 Route 삭제"로 처리합니다. 문제는 새 걸 먼저 만들려고 하는데, 같은 Route Table에 0.0.0.0/0이 이미 있으니 만들 수가 없는 거죠. 해결은 간단했습니다. 이름은 원래대로 두고 type / target만 바꿨습니다. - name: rt-sharedservice-ane2-private routes: # NOTE: route name kept as route-default-natgw for CFN logical-ID stability. # Only the TARGET changed (NAT gateway -> TGW) so private egress flows through the # inspection VPC/NFW. Renaming the route makes CFN CREATE a duplicate 0/0 route while # the old one still exists -> "route already exists" (2026-07-15 Network_VPCs failure). - name: route-default-natgw destination: 0.0.0.0/0 type: transitGateway target: tgw-network-ane2 이렇게 다시 올리니 같은 날 바로 성공했습니다. 이름이 natgw 인데 실제로는 TGW로 가니까 좀 어색하긴 합니다. 그래서 주석을 꼭 남겨 뒀습니다. 이 일 이후로 Route 이름에는 Target 종류를 안 넣으려고 합니다. 한번 배포한 Route 이름은 바꾸지 않는 게 속 편합니다. 6-2. 안 쓰는 TGW에도 비용이 나간다 처음에는 서울 / 버지니아 / 오레곤에 TGW를 하나씩 만들고 peering 3개로 다 엮어 뒀습니다. 그런데 VPC가 실제로 붙어 있는 건 서울뿐이었습니다. TGW는 attachment 단위로 시간당 요금이 붙는데, peering attachment도 여기에 들어갑니다. VPC가 하나도 안 붙은 버지니아 / 오레곤 TGW에서도 peering 때문에 계속 돈이 나가고 있었습니다. Cost Explorer로 TGW 시간 요금만 뽑아 보면 이렇습니다. (조직 전체, USD) $ aws ce get-cost-and-usage --profile sean-lza \ --time-period Start=2026-06-01,End=2026-10-01 --granularity MONTHLY --metrics UnblendedCost \ --filter '{"Dimensions":{"Key":"USAGE_TYPE","Values":["APN2-TransitGateway-Hours","USE1-TransitGateway-Hours","USW2-TransitGateway-Hours"]}}' \ --group-by Type=DIMENSION,Key=USAGE_TYPE \ --query 'ResultsByTime[].{month:TimePeriod.Start,cost:Groups[].[Keys[0],Metrics.UnblendedCost.Amount]}' --output json | python3 -c " import json,sys for r in json.load(sys.stdin): print(r['month'], ', '.join(f'{k.split(\"-\")[0]} {float(v):.2f}' for k,v in r['cost']))" 2026-06-01 APN2 53.34, USE1 18.80, USW2 18.80 2026-07
То, что RADAR обнаружил и классифицировал для этой возможности. Это опубликованный источником текст, а не подтверждение, что предложение ещё действует.
쉽게 따라하는 LZA를 활용한 AWS Control Tower 구축 (3) - Transit Gateway / VPC Network 구성. 개요 2편 에서 OU, 계정, SCP까지 구성했으니 이번에는 Network입니다. LZA에서 Network는 network-config.yaml 파일 하나로 관리합니다. IPAM, Transit Gateway, VPC, Routing이 전부 이 파일에 들어가서 설정 파일 6개 중에 제일 깁니다. 제 환경에서도 지금 20KB 정도 됩니다. 이번 글에서 다루는 내용은 아래와 같습니다. 기본 VPC 삭제 IPAM으로 CIDR 나누기 서울 Region Transit Gateway 만들고 다른 계정에 공유하기 중앙 egress용 inspection VPC, Workload…
Открыть источник