Alexander Hosking
cf369c6a3a
Permissions are not correct in code to allow the images to be pulled by the ECS tasks. As such, they will not start and run without some manual intervention. Pulumi will happily let the process sit at this stage forever.
217 lines
6.6 KiB
Python
217 lines
6.6 KiB
Python
import pulumi
|
|
from pulumi import Config, Output, export
|
|
import pulumi_aws as aws
|
|
from pulumi_aws import acm, alb, ecs, ec2, lb, iam, ecr
|
|
import pulumi_awsx as awsx
|
|
import json
|
|
|
|
|
|
config = Config()
|
|
# container_port = config.get_int("containerPort", 80)
|
|
cpu = config.get_int("cpu", 512)
|
|
memory = config.get_int("memory", 128)
|
|
# Create a VPC
|
|
vpc = ec2.Vpc("production", cidr_block="10.0.0.0/16")
|
|
|
|
# Create a Gateway
|
|
ig = ec2.InternetGateway("internet-gateway", vpc_id=vpc.id)
|
|
|
|
cert = acm.Certificate(
|
|
"air-tech",
|
|
domain_name="air-tech.ahosking.com",
|
|
validation_method="DNS",
|
|
)
|
|
# Public Subnet
|
|
public_subnet = ec2.Subnet(
|
|
"public-subnet",
|
|
vpc_id=vpc.id,
|
|
cidr_block="10.0.1.0/26",
|
|
availability_zone="us-east-2a",
|
|
|
|
# Allow the Internet Gateway to handle public traffic
|
|
map_public_ip_on_launch=True
|
|
)
|
|
public_subnet2 = ec2.Subnet(
|
|
"public-subnet2",
|
|
vpc_id=vpc.id,
|
|
cidr_block="10.0.2.0/26",
|
|
availability_zone="us-east-2b",
|
|
|
|
# Allow the Internet Gateway to handle public traffic
|
|
map_public_ip_on_launch=True
|
|
)
|
|
|
|
# Associate the Gateway to a route
|
|
route_table = ec2.RouteTable('route-table', vpc_id=vpc.id)
|
|
route = ec2.Route('route', route_table_id=route_table.id,
|
|
destination_cidr_block='0.0.0.0/0', gateway_id=ig.id)
|
|
|
|
# Private Subnet
|
|
private_subnet = ec2.Subnet(
|
|
"private-subnet",
|
|
vpc_id=vpc.id,
|
|
cidr_block="10.0.3.0/26",
|
|
availability_zone="us-east-2a",
|
|
map_public_ip_on_launch=False
|
|
)
|
|
private_subnet2 = ec2.Subnet(
|
|
"private-subnet2",
|
|
vpc_id=vpc.id,
|
|
cidr_block="10.0.4.0/26",
|
|
availability_zone="us-east-2b",
|
|
map_public_ip_on_launch=False
|
|
)
|
|
repo = ecr.Repository("repo")
|
|
|
|
# Create an IAM role
|
|
ecs_task_execution_role = iam.Role("ecsExecutionRole",
|
|
path="/",
|
|
assume_role_policy=iam.get_policy_document(statements=[{
|
|
"actions": ["sts:AssumeRole"],
|
|
"principals": {
|
|
"type": "Service",
|
|
"identifiers": ["ecs-tasks.amazonaws.com"]
|
|
}
|
|
}
|
|
]).json,
|
|
)
|
|
|
|
# Attach a policy to the execution role that will allow it to pull images from ECR
|
|
iam.RolePolicy("accessECRImages",
|
|
role=ecs_task_execution_role.id,
|
|
policy={
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Action": [
|
|
"ecr:GetDownloadUrlForLayer",
|
|
"ecr:BatchGetImage",
|
|
"ecr:BatchCheckLayerAvailability",
|
|
],
|
|
"Resource": repo.repository_arn
|
|
}
|
|
]
|
|
}
|
|
)
|
|
|
|
|
|
image_web = awsx.ecr.Image(
|
|
"image_web",
|
|
repository_url=repo.url,
|
|
path=".",
|
|
dockerfile=".\infra-web\Dockerfile")
|
|
|
|
image_api = awsx.ecr.Image(
|
|
"image_api",
|
|
repository_url=repo.url,
|
|
path=".",
|
|
dockerfile=".\infra-api\Dockerfile")
|
|
|
|
security_group = aws.ec2.SecurityGroup(
|
|
"securityGroup",
|
|
vpc_id=vpc.id,
|
|
egress=[aws.ec2.SecurityGroupEgressArgs(
|
|
from_port=0,
|
|
to_port=0,
|
|
protocol="-1",
|
|
cidr_blocks=["0.0.0.0/0"],
|
|
ipv6_cidr_blocks=["::/0"],
|
|
)])
|
|
# Create an ECS Cluster
|
|
cluster = ecs.Cluster("cluster")
|
|
|
|
pulumi.export("certificateArn", cert.arn)
|
|
loadbalancer = lb.LoadBalancer(
|
|
"loadbalancer",
|
|
load_balancer_type="application",
|
|
security_groups=[security_group.id],
|
|
subnets=[public_subnet.id, public_subnet2.id])
|
|
|
|
|
|
target_group = lb.TargetGroup('target-group',
|
|
port=5000,
|
|
protocol="HTTP",
|
|
target_type="ip",
|
|
vpc_id=vpc.id)
|
|
|
|
# Create a listener for the ALB at port 80
|
|
listener = lb.Listener('listener',
|
|
load_balancer_arn=loadbalancer.arn,
|
|
port=80,
|
|
default_actions=[{
|
|
'type': "forward",
|
|
'target_group_arn': target_group.arn # Forward to our target group
|
|
}])
|
|
|
|
|
|
web_sg = ec2.SecurityGroup('web-sg',
|
|
vpc_id=vpc.id,
|
|
ingress=[
|
|
{
|
|
'protocol': 'tcp',
|
|
'from_port': 80,
|
|
'to_port': 80,
|
|
'cidr_blocks': ['0.0.0.0/0'],
|
|
}
|
|
],
|
|
egress=[
|
|
{
|
|
'protocol': '-1',
|
|
'from_port': 0,
|
|
'to_port': 0,
|
|
'cidr_blocks': ['0.0.0.0/0'],
|
|
}
|
|
]
|
|
)
|
|
|
|
|
|
api = awsx.ecs.FargateService(
|
|
"api",
|
|
cluster=cluster.arn,
|
|
network_configuration={
|
|
'assignPublicIp': "false",
|
|
'subnets': [private_subnet.id],
|
|
'securityGroups': [web_sg.id]
|
|
},
|
|
task_definition_args=awsx.ecs.FargateServiceTaskDefinitionArgs(
|
|
container=awsx.ecs.TaskDefinitionContainerDefinitionArgs(
|
|
name="theApi",
|
|
image=image_api.image_uri,
|
|
cpu=cpu,
|
|
memory=memory,
|
|
essential=True,
|
|
port_mappings=[awsx.ecs.TaskDefinitionPortMappingArgs(
|
|
container_port=5000,
|
|
host_port=5000,
|
|
)],
|
|
),
|
|
))
|
|
|
|
|
|
service = awsx.ecs.FargateService(
|
|
"web",
|
|
cluster=cluster.arn,
|
|
network_configuration={
|
|
'assignPublicIp': "true",
|
|
'subnets': [public_subnet.id],
|
|
'securityGroups': [web_sg.id]
|
|
},
|
|
# assign_public_ip=True,
|
|
task_definition_args=awsx.ecs.FargateServiceTaskDefinitionArgs(
|
|
container=awsx.ecs.TaskDefinitionContainerDefinitionArgs(
|
|
name="theOne",
|
|
image=image_web.image_uri,
|
|
cpu=cpu,
|
|
memory=memory,
|
|
essential=True,
|
|
port_mappings=[awsx.ecs.TaskDefinitionPortMappingArgs(
|
|
container_port=5000,
|
|
host_port=5000,
|
|
target_group=target_group,
|
|
)],
|
|
),
|
|
),
|
|
opts=pulumi.ResourceOptions(depends_on=[api, target_group])
|
|
)
|