pulumi aws api: https://www.pulumi.com/registry/packages/aws/
github: https://github.com/dewble/pulumi-aws-network/tree/v1.0.0
2024.04.07 - [IaC/Pulumi] - [Pulumi]Create AWS Network:VPC, Subnet, Security Group
위 내용에 이어 AWS NAT, RouteTable, IGW, VPCE를 생성하는 Pulumi 코드를 작성합니다.
Architecture
💡기본 라우팅 테이블 설정은 배포 후 수동으로 변경(jeff-route-default)했습니다.
Create NAT Gateway
NAT 게이트웨이는 프라이빗 서브넷 내의 인스턴스가 인터넷이나 다른 AWS 서비스와 통신할 수 있게 해주는 서비스입니다. 이는 프라이빗 서브넷 내의 인스턴스에 대해 인터넷으로부터의 직접적인 접근을 차단하면서도 필요한 외부 통신은 가능하게 합니다.
nat.py:
from pulumi_aws import ec2
def create_elastic_ip(resource_name, tags=None):
tags_with_name = tags.copy()
tags_with_name["Name"] = resource_name
eip = ec2.Eip(resource_name, tags=tags_with_name)
return eip
def create_nat_gateway(resource_name, subnet_id, eip_allocation_id, tags=None):
tags_with_name = tags.copy()
tags_with_name["Name"] = resource_name
nat_gateway = ec2.NatGateway(
resource_name,
subnet_id=subnet_id,
allocation_id=eip_allocation_id,
tags=tags_with_name,
)
return nat_gateway
Create Route Table
라우트 테이블은 네트워크 트래픽이 어디로 (또는 어떤 게이트웨이를 통해) 전송될지를 결정하는 데 사용됩니다. VPC 내의 각 서브넷은 하나 이상의 라우트 테이블을 가질 수 있습니다.
route_table.py 파일에서는 VPC 내에 하나 이상의 라우트 테이블을 생성하고, 특정 라우트(예: 인터넷 게이트웨이로의 라우트, NAT 게이트웨이로의 라우트 등)를 추가하는 방법을 구현합니다.
route_table.py:
from pulumi_aws import ec2
def create_default_route(
resource_name,
default_route_table_id=None,
gateway_id=None,
tags=None,
opts=None,
cidr_block: str = "0.0.0.0/0", # 기본값 설정
):
tags_with_name = (tags or {}).copy()
tags_with_name["Name"] = resource_name
# CIDR block과 gateway_id를 사용하여 routes 리스트 구성
routes = [
ec2.DefaultRouteTableRouteArgs(cidr_block=cidr_block, gateway_id=gateway_id)
]
# 기본 라우트 테이블 생성
default_route_table = ec2.DefaultRouteTable(
resource_name,
default_route_table_id=default_route_table_id,
routes=routes,
tags=tags_with_name,
opts=opts,
)
return default_route_table
def create_route_table(resource_name, vpc_id, tags):
tags_with_name = (tags or {}).copy()
tags_with_name["Name"] = resource_name
route_table = ec2.RouteTable(resource_name, vpc_id=vpc_id, tags=tags_with_name)
return route_table
def associate_subnet_route_table(
association_name, route_table_id, subnet_id, opts=None
):
association = ec2.RouteTableAssociation(
association_name,
route_table_id=route_table_id,
subnet_id=subnet_id,
opts=opts, # ResourceOptions 인스턴스를 생성자에 전달
)
return association
def add_route_to_route_table(
resource_name,
route_table_id,
destination_cidr_block="0.0.0.0/0",
nat_gateway_id=None,
):
"""
특정 라우트 테이블에 라우트를 추가하는 함수
"""
route = ec2.Route(
resource_name,
route_table_id=route_table_id,
destination_cidr_block=destination_cidr_block,
nat_gateway_id=nat_gateway_id,
)
return route
Create Internet Gateway
인터넷 게이트웨이는 AWS VPC와 인터넷 간의 통신을 가능하게 해주는 VPC 구성 요소입니다. 이를 통해 VPC 내의 리소스가 인터넷과 통신할 수 있게 됩니다.
from pulumi_aws import ec2
def create_internet_gateway(resource_name, tags=None):
tags_with_name = tags.copy()
tags_with_name["Name"] = resource_name
igw = ec2.InternetGateway(resource_name, tags=tags_with_name)
return igw
def attach_igw_to_vpc(resource_name, vpc_id, igw_id):
attachment = ec2.InternetGatewayAttachment(
resource_name,
vpc_id=vpc_id,
internet_gateway_id=igw_id,
)
return attachment
Create VPC Endpoint
VPC 엔드포인트를 사용하면 VPC 내의 인스턴스가 인터넷 게이트웨이나 NAT 게이트웨이를 사용하지 않고도 AWS 서비스(예: S3, DynamoDB)와 직접 통신할 수 있습니다. 이는 네트워크 트래픽을 AWS 네트워크 내부에서만 유지하게 해서 보안성과 속도를 향상시킵니다.
from pulumi_aws import ec2
import json
def create_interface_vpce(
resource_name, service_name, vpc_id, subnet_ids, security_group_id, tags=None
):
"""
인터페이스형 VPC 엔드포인트 생성 함수
"""
tags_with_name = tags.copy()
tags_with_name["Name"] = resource_name
vpce = ec2.VpcEndpoint(
resource_name,
vpc_id=vpc_id,
service_name=service_name,
vpc_endpoint_type="Interface",
subnet_ids=subnet_ids,
security_group_ids=[security_group_id],
private_dns_enabled=True,
tags=tags_with_name,
)
return vpce
def create_gateway_vpce(
resource_name, service_name, vpc_id, route_table_ids, tags=None
):
"""
게이트웨이형 VPC 엔드포인트 생성 함수
"""
tags_with_name = tags.copy()
tags_with_name["Name"] = resource_name
vpce = ec2.VpcEndpoint(
resource_name,
vpc_id=vpc_id,
service_name=service_name,
vpc_endpoint_type="Gateway",
route_table_ids=route_table_ids,
tags=tags_with_name,
)
return vpce
def attach_vpc_endpoint_policy(resource_name, vpc_endpoint_id, policy, tags=None):
"""
VPC 엔드포인트 정책 적용 함수
"""
tags_with_name = tags.copy()
tags_with_name["Name"] = resource_name
endpoint_policy = ec2.VpcEndpointPolicy(
resource_name=resource_name,
vpc_endpoint_id=vpc_endpoint_id,
policy=json.dumps(policy),
)
tags = tags_with_name
return endpoint_policy
Deloy pulumi project
main.py 파일은 프로젝트의 진입점으로, 위에서 언급한 모든 리소스를 생성하는 로직을 포함합니다. 각 리소스 생성 함수를 호출하고, 필요한 매개변수를 전달하여 AWS에 이 리소스들을 배포합니다.
main.py:
# 중략
from nat import create_elastic_ip, create_nat_gateway
from route_table import (
create_default_route,
create_route_table,
associate_subnet_route_table,
add_route_to_route_table,
)
from igw import create_internet_gateway, attach_igw_to_vpc
from vpce import (
create_interface_vpce,
create_gateway_vpce,
attach_vpc_endpoint_policy,
)
#
######## Create Nat Gateway ########
# Create Elastic IP
nat_eip = create_elastic_ip(f"{project}-nat-eip", tags)
# Create Nat Gateway
nat_gateway_a = create_nat_gateway(
f"{project}-nat-gateway-a",
subnet_id=subnet_public_ingress_a.id,
eip_allocation_id=nat_eip.id,
tags=tags,
)
######## Create Routetable ########
# 라우트 테이블 생성 및 서브넷 연결: app
route_app = create_route_table(
f"{project}-route-app", vpc.id, {**tags, "Name": f"{project}-route-app"}
)
route_app_association_a = associate_subnet_route_table(
f"{project}-route-app-association-a", route_app.id, subnet_private_app_a.id
)
route_app_association_c = associate_subnet_route_table(
f"{project}-route-app-association-c", route_app.id, subnet_private_app_c.id
)
route_app_route_nat = add_route_to_route_table(
f"{project}-route-app-add-route-nat",
route_app.id,
destination_cidr_block="0.0.0.0/0",
nat_gateway_id=nat_gateway_a.id,
)
######## Create Internet Gateway ########
# 인터넷 게이트웨이 생성 및 VPC에 연결
igw = create_internet_gateway(f"{project}-igw", tags)
vpcgw_attachment = attach_igw_to_vpc(f"{project}-vpcgw-attachment", vpc.id, igw.id)
# 라우트 테이블 생성 및 서브넷 연결: ingress
route_ingress = create_route_table(
f"{project}-route-ingress",
vpc_id=vpc.id,
tags={**tags, "Name": f"{project}-route-ingress"},
)
route_ingress_association_a = associate_subnet_route_table(
f"{project}-route-ingress-association-a",
route_ingress.id,
subnet_id=subnet_public_ingress_a.id,
)
route_ingress_association_c = associate_subnet_route_table(
f"{project}-route-ingress-association-c",
route_ingress.id,
subnet_public_ingress_c.id,
)
# 기본 라우트 설정
route_default = create_default_route(
f"{project}-route-default",
default_route_table_id=route_ingress.id,
cidr_block="0.0.0.0/0",
gateway_id=igw.id,
tags=tags,
)
######## Create VPC Endpoints ########
# Interface VPCE 생성
vpce_interface_ecr_api = create_interface_vpce(
f"{project}-ecr-api-vpce",
service_name="com.amazonaws.ap-northeast-2.ecr.api",
vpc_id=vpc.id,
subnet_ids=[subnet_private_egress_a.id, subnet_private_egress_c.id],
security_group_id=security_group_vpce.id,
tags=tags,
)
vpce_interface_ecr_api_policy = attach_vpc_endpoint_policy(
f"{project}-ecr-api-vpce-policy",
vpce_interface_ecr_api.id,
policy={
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "ecr:*",
"Resource": "*",
}
],
},
tags=tags,
)
vpce_interface_ecr_dkr = create_interface_vpce(
f"{project}-ecr-dkr-vpce",
service_name="com.amazonaws.ap-northeast-2.ecr.dkr",
vpc_id=vpc.id,
subnet_ids=[subnet_private_egress_a.id, subnet_private_egress_c.id],
security_group_id=security_group_vpce.id,
tags=tags,
)
vpce_interface_ecr_dkr_policy = attach_vpc_endpoint_policy(
f"{project}-ecr-dkr-vpce-policy",
vpce_interface_ecr_dkr.id,
policy={
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "ecr:*",
"Resource": "*",
}
],
},
tags=tags,
)
# Gateway VPCE 생성
vpce_s3_gateway = create_gateway_vpce(
f"{project}-s3-vpce",
service_name="com.amazonaws.ap-northeast-2.s3",
vpc_id=vpc.id,
route_table_ids=[route_app.id],
tags=tags,
)
vpce_s3_gateway_policy = attach_vpc_endpoint_policy(
f"{project}-s3-vpce-policy",
vpce_s3_gateway.id,
policy={
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:*",
"Resource": "*",
}
],
},
tags=tags,
)
######## Export the name of the bucket ########
# 중략
# nat gateway
pulumi.export("nat_gateway_a_id", nat_gateway_a.id)
# route table
pulumi.export("route_app_id", route_app.id)
pulumi.export("route_ingress_id", route_ingress.id)
pulumi.export("route_default_id", route_default.id)
# vpc endpoint
pulumi.export("vpce_interface_ecr_api_id", vpce_interface_ecr_api.id)
pulumi.export("vpce_interface_ecr_dkr_id", vpce_interface_ecr_dkr.id)
pulumi.export("vpce_s3_gateway_id", vpce_s3_gateway.id)
# vpc endpoint policy
pulumi.export("vpce_interface_ecr_api_policy_id", vpce_interface_ecr_api_policy.id)
pulumi.export("vpce_interface_ecr_dkr_policy_id", vpce_interface_ecr_dkr_policy.id)
pulumi.export("vpce_s3_gateway_policy_id", vpce_s3_gateway_policy.id)
pulumi up:
➜ pulumi up
Previewing update (dev)
View in Browser (Ctrl+O): <https://app.pulumi.com/dewble/aws-network/dev/previews/501ef324-14df-4a1d-aafa-fc7caaf4c6e2>
Type Name Plan Info
pulumi:pulumi:Stack aws-network-dev
+ ├─ aws:ec2:Eip jeff-nat-eip create
+ ├─ aws:ec2:InternetGateway jeff-igw create
├─ aws:ec2:SecurityGroup jeff-security-group-ingress 1 warning
├─ aws:ec2:SecurityGroup jeff-security-group-frontend 1 warning
├─ aws:ec2:SecurityGroup jeff-security-group-db 1 warning
+ ├─ aws:ec2:RouteTable jeff-route-app create
├─ aws:ec2:SecurityGroup jeff-security-group-backend 1 warning
├─ aws:ec2:SecurityGroup jeff-security-group-internal-lb 1 warning
├─ aws:ec2:SecurityGroup jeff-security-group-vpce 1 warning
├─ aws:ec2:SecurityGroup jeff-security-group-management 1 warning
+ ├─ aws:ec2:RouteTableAssociation jeff-route-app-association-c create
+ ├─ aws:ec2:RouteTableAssociation jeff-route-app-association-a create
+ ├─ aws:ec2:InternetGatewayAttachment jeff-vpcgw-attachment create
+ ├─ aws:ec2:NatGateway jeff-nat-gateway-a create
+ ├─ aws:ec2:VpcEndpoint jeff-s3-vpce create
+ ├─ aws:ec2:RouteTable jeff-route-ingress create
+ ├─ aws:ec2:RouteTableAssociation jeff-route-ingress-association-c create
+ ├─ aws:ec2:VpcEndpoint jeff-ecr-api-vpce create
+ ├─ aws:ec2:VpcEndpoint jeff-ecr-dkr-vpce create
+ ├─ aws:ec2:RouteTableAssociation jeff-route-ingress-association-a create
+ ├─ aws:ec2:DefaultRouteTable jeff-route-default create
+ ├─ aws:ec2:Route jeff-route-app-add-route-nat create
+ ├─ aws:ec2:VpcEndpointPolicy jeff-ecr-api-vpce-policy create
+ ├─ aws:ec2:VpcEndpointPolicy jeff-ecr-dkr-vpce-policy create
+ └─ aws:ec2:VpcEndpointPolicy jeff-s3-vpce-policy create
Diagnostics:
aws:ec2:SecurityGroup (jeff-security-group-db):
warning: Use of inline rules is discouraged as they cannot be used in conjunction with any Security Group Rule resources. Doing so will cause a conflict and may overwrite rules.
aws:ec2:SecurityGroup (jeff-security-group-internal-lb):
warning: Use of inline rules is discouraged as they cannot be used in conjunction with any Security Group Rule resources. Doing so will cause a conflict and may overwrite rules.
aws:ec2:SecurityGroup (jeff-security-group-frontend):
warning: Use of inline rules is discouraged as they cannot be used in conjunction with any Security Group Rule resources. Doing so will cause a conflict and may overwrite rules.
aws:ec2:SecurityGroup (jeff-security-group-management):
warning: Use of inline rules is discouraged as they cannot be used in conjunction with any Security Group Rule resources. Doing so will cause a conflict and may overwrite rules.
aws:ec2:SecurityGroup (jeff-security-group-backend):
warning: Use of inline rules is discouraged as they cannot be used in conjunction with any Security Group Rule resources. Doing so will cause a conflict and may overwrite rules.
aws:ec2:SecurityGroup (jeff-security-group-ingress):
warning: Use of inline rules is discouraged as they cannot be used in conjunction with any Security Group Rule resources. Doing so will cause a conflict and may overwrite rules.
aws:ec2:SecurityGroup (jeff-security-group-vpce):
warning: Use of inline rules is discouraged as they cannot be used in conjunction with any Security Group Rule resources. Doing so will cause a conflict and may overwrite rules.
Outputs:
+ nat_gateway_a_id : output
+ route_app_id : output
+ route_default_id : output
+ route_ingress_id : output
+ vpce_interface_ecr_api_id : output
+ vpce_interface_ecr_api_policy_id : output
+ vpce_interface_ecr_dkr_id : output
+ vpce_interface_ecr_dkr_policy_id : output
+ vpce_s3_gateway_id : output
+ vpce_s3_gateway_policy_id : output
Resources:
+ 18 to create
29 unchanged
Do you want to perform this update? yes
Updating (dev)
View in Browser (Ctrl+O): <https://app.pulumi.com/dewble/aws-network/dev/updates/4>
Type Name Status Info
pulumi:pulumi:Stack aws-network-dev
├─ aws:ec2:SecurityGroup jeff-security-group-ingress 1 warning
├─ aws:ec2:SecurityGroup jeff-security-group-management 1 warning
+ ├─ aws:ec2:Eip jeff-nat-eip created (0.83s)
+ ├─ aws:ec2:InternetGateway jeff-igw created (0.79s)
├─ aws:ec2:SecurityGroup jeff-security-group-db 1 warning
├─ aws:ec2:SecurityGroup jeff-security-group-backend 1 warning
├─ aws:ec2:SecurityGroup jeff-security-group-internal-lb 1 warning
├─ aws:ec2:SecurityGroup jeff-security-group-vpce 1 warning
+ ├─ aws:ec2:RouteTable jeff-route-ingress created (1s)
├─ aws:ec2:SecurityGroup jeff-security-group-frontend 1 warning
+ ├─ aws:ec2:RouteTable jeff-route-app created (1s)
+ ├─ aws:ec2:VpcEndpoint jeff-ecr-dkr-vpce created (84s)
+ ├─ aws:ec2:VpcEndpoint jeff-ecr-api-vpce created (93s)
+ ├─ aws:ec2:InternetGatewayAttachment jeff-vpcgw-attachment created (1s)
+ ├─ aws:ec2:NatGateway jeff-nat-gateway-a created (105s)
+ ├─ aws:ec2:RouteTableAssociation jeff-route-ingress-association-c created (1s)
+ ├─ aws:ec2:DefaultRouteTable jeff-route-default created (2s)
+ ├─ aws:ec2:RouteTableAssociation jeff-route-ingress-association-a created (1s)
+ ├─ aws:ec2:VpcEndpoint jeff-s3-vpce created (8s)
+ ├─ aws:ec2:RouteTableAssociation jeff-route-app-association-c created (1s)
+ ├─ aws:ec2:RouteTableAssociation jeff-route-app-association-a created (1s)
+ ├─ aws:ec2:VpcEndpointPolicy jeff-s3-vpce-policy created (5s)
+ ├─ aws:ec2:VpcEndpointPolicy jeff-ecr-dkr-vpce-policy created (5s)
+ ├─ aws:ec2:VpcEndpointPolicy jeff-ecr-api-vpce-policy created (5s)
+ └─ aws:ec2:Route jeff-route-app-add-route-nat created (0.93s)
Diagnostics:
aws:ec2:SecurityGroup (jeff-security-group-ingress):
warning: Use of inline rules is discouraged as they cannot be used in conjunction with any Security Group Rule resources. Doing so will cause a conflict and may overwrite rules.
aws:ec2:SecurityGroup (jeff-security-group-internal-lb):
warning: Use of inline rules is discouraged as they cannot be used in conjunction with any Security Group Rule resources. Doing so will cause a conflict and may overwrite rules.
aws:ec2:SecurityGroup (jeff-security-group-vpce):
warning: Use of inline rules is discouraged as they cannot be used in conjunction with any Security Group Rule resources. Doing so will cause a conflict and may overwrite rules.
aws:ec2:SecurityGroup (jeff-security-group-db):
warning: Use of inline rules is discouraged as they cannot be used in conjunction with any Security Group Rule resources. Doing so will cause a conflict and may overwrite rules.
aws:ec2:SecurityGroup (jeff-security-group-frontend):
warning: Use of inline rules is discouraged as they cannot be used in conjunction with any Security Group Rule resources. Doing so will cause a conflict and may overwrite rules.
aws:ec2:SecurityGroup (jeff-security-group-management):
warning: Use of inline rules is discouraged as they cannot be used in conjunction with any Security Group Rule resources. Doing so will cause a conflict and may overwrite rules.
aws:ec2:SecurityGroup (jeff-security-group-backend):
warning: Use of inline rules is discouraged as they cannot be used in conjunction with any Security Group Rule resources. Doing so will cause a conflict and may overwrite rules.
Outputs:
+ nat_gateway_a_id : "nat-09cbdc525fe1808a3"
+ route_app_id : "rtb-02b82d35892256729"
+ route_default_id : "rtb-099ea49fe428eb82b"
+ route_ingress_id : "rtb-099ea49fe428eb82b"
security_group_backend_id : "sg-0e3b22fb545044914"
security_group_db_id : "sg-0edb2ccafcb86fb04"
security_group_frontend_id : "sg-001c2820a31f81e13"
security_group_ingress_id : "sg-0a50918e2ebb3f4af"
security_group_internal_lb_id : "sg-0eed1ac2fd04e9843"
security_group_management_id : "sg-066adfe4e7a1e02b5"
security_group_vpce_id : "sg-0080f09c3715a8279"
sg_backend_from_sg_internal_lb_rule_id : "sgrule-2629722229"
sg_db_from_sg_backend_rule_id : "sgrule-196001820"
sg_db_from_sg_frontend_rule_id : "sgrule-1102388768"
sg_db_from_sg_management_rule_id : "sgrule-2502730656"
sg_frontend_from_sg_ingress_rule_id : "sgrule-4234715315"
sg_internal_lb_from_sg_front_rule_id : "sgrule-270241600"
sg_internal_lb_from_sg_management_rule_id: "sgrule-3296867008"
sg_vpce_from_sg_backend_rule_id : "sgrule-2422481157"
sg_vpce_from_sg_frontend_rule_id : "sgrule-3665821497"
sg_vpce_from_sg_management_rule_id : "sgrule-249971385"
subnet_private_app_a_id : "subnet-0408be5378856a5a1"
subnet_private_app_c_id : "subnet-028befbbf23656471"
subnet_private_db_a_id : "subnet-0d776212b9ce9dd8c"
subnet_private_db_c_id : "subnet-019fc6b0a78e0f050"
subnet_private_egress_a_id : "subnet-0b8bc53490b62e51e"
subnet_private_egress_c_id : "subnet-000bbc63eeb970e24"
subnet_public_ingress_a_id : "subnet-04d4637f4b6127961"
subnet_public_ingress_c_id : "subnet-0f21617a4fd1c7e69"
subnet_public_management_a_id : "subnet-00fef85651d7ac059"
subnet_public_management_c_id : "subnet-0591fb3ad29233ef0"
vpc_id : "vpc-06440e0fb854f5e7c"
+ vpce_interface_ecr_api_id : "vpce-0a4dd333e3d489f03"
+ vpce_interface_ecr_api_policy_id : "vpce-0a4dd333e3d489f03"
+ vpce_interface_ecr_dkr_id : "vpce-0c76bc9588e602729"
+ vpce_interface_ecr_dkr_policy_id : "vpce-0c76bc9588e602729"
+ vpce_s3_gateway_id : "vpce-0fb248e5d47049c71"
+ vpce_s3_gateway_policy_id : "vpce-0fb248e5d47049c71"
Resources:
+ 18 created
29 unchanged
Duration: 1m53s
'IaC > Pulumi' 카테고리의 다른 글
[Pulumi]Create AWS Network:VPC, Subnet, Security Group (0) | 2024.04.07 |
---|---|
[Pulumi]Quick Start with AWS (0) | 2024.04.06 |