Q: How do I add resources to a VPC? E.g., I can cr...
# getting-started
r
Q: How do I add resources to a VPC? E.g., I can create a VPC, but how do I add s3, dynamodb tables, clusters, fargate, etc to the vpc? Of course, I want to create the standard dev/prod/stage vpcs and have them isolated from each other, etc.
b
it largely varies depending on the resource. DynamoDB: isn’t VPC based S3: isn’t VPC based Fargate: you set the subnets associated with the VPC
r
@billowy-army-68599 - your video (especially the couch one) was amazing. Thx for the feedback. I am (clearly) an aws newb.
b
always happy to help! keep the questions coming
p
Thanks @billowy-army-68599. Do you know of any workarounds for https://github.com/pulumi/pulumi-awsx/issues/430? I have a Fargate service using the subnets associated with my VPC, but I used
awsx
to create the Fargate service, and it fails when there is no default VPC even if the default VPC would not be used.
At least I'm pretty sure that nothing is using the default VPC.
Nevermind - seems to be working now after following the instructions from https://github.com/pulumi/pulumi-awsx/issues/430#issuecomment-1146532556. Not sure what I was doing wrong before.
r
@billowy-army-68599 is there a working example of using pulumi with awsx (crosswalk) + fargate + vpc + custom security group? I have a simple example mostly working, but I'm having trouble (i think) with getting the lb to forward traffic to the fargate service... Links: • https://www.pulumi.com/docs/guides/crosswalk/aws/ecs/https://www.pulumi.com/docs/guides/crosswalk/aws/vpc/https://www.pulumi.com/docs/guides/crosswalk/aws/api-gateway/https://www.pulumi.com/registry/packages/aws/how-to-guides/ecs-fargate/https://www.pulumi.com/docs/reference/pkg/nodejs/pulumi/awsx/ecs/#Image-fromDockerBuildhttps://www.pulumi.com/registry/packages/aws/api-docs/ecs/cluster/https://www.pulumi.com/registry/packages/awsx/api-docs/lb/applicationloadbalancer/https://docs.aws.amazon.com/elasticloadbalancing/latest/userguide/what-is-load-balancing.htmlhttps://docs.aws.amazon.com/elasticloadbalancing/latest/application/introduction.htmlhttps://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-target-groups.htmlhttps://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-listeners.htmlhttps://docs.aws.amazon.com/elasticloadbalancing/latest/application/create-https-listener.htmlhttps://docs.aws.amazon.com/elasticloadbalancing/latest/application/application-load-balancers.htmlhttps://medium.com/@_ipeacocks/pulumi-vpc-and-fargate-configuration-fd60f1b053eahttps://www.pulumi.com/registry/packages/awsx/api-docs/lb/applicationloadbalancer/https://www.pulumi.com/registry/packages/aws/api-docs/alb/listener/https://github.com/pulumi/examples/blob/master/aws-py-fargate/__main__.py I'll paste my code snippet next...
r
@billowy-army-68599 Thx! I'll read through those and get back to you.
BTW, not to ask for the world, but these examples are in
ts
and I'm using
python
... the pulumi API seems to be subtly different. Is there a full stack example in python out there?
(less involved)
r
Ok, cool. thx! yeah, it's the addition of the vpc and then linking up all the networking pieces that I'm fumbling with. I'll read these two examples.
b
do you have some code or errors?
r
sure, I'll share a couple gists to show you what I'm doing. btw - your last example is great, but it's still using the default vpc...
b
it looks pretty fine so far, what issue are you running into?
r
Trying to hit the dns endpoint hangs with a 503
Copy code
503 Service Temporarily Unavailable
Copy code
watch curl <http://dev-v4-dashboard-alb-1f52b4a-628890030.us-east-1.elb.amazonaws.com|dev-v4-dashboard-alb-1f52b4a-628890030.us-east-1.elb.amazonaws.com>
b
if you go into the AWS dashboard, is the ALB attached to the nodes correctly? Where do you define your VPC?
r
I'm pretty sure I don't have the lb configured quite right. Must not be exposing or mapping the port all the way to the svc.
btw - I owe you a coffee for all the help. I'm in Seattle (MapleLeaf) so we are both local.
b
i’m British so prefer tea, but I’ll never turn down a beer 😄 🍻
r
right on, you have a deal
b
@refined-engine-12125 if you want to grab some time we can run through what you have https://calendly.com/leebriggs58
although will likely have to be next week
r
sure, scheduled for tmo morning, but next week is cool too.
b
that works, see you then!
r
Copy code
"""JAXXStorm's Python Pulumi example program."""

from pulumi import export, ResourceOptions
import pulumi
import pulumi_awsx as awsx
import pulumi_aws as aws
import json

# Create an ECS cluster to run a container-based service.
cluster = aws.ecs.Cluster("cluster")

# Read back the **custom** VPC and public subnets, which we will use.
custom_vpc = awsx.ec2.Vpc("custom-vpc", number_of_availability_zones=1, )

# Create a SecurityGroup that permits HTTP ingress and unrestricted egress.
group = aws.ec2.SecurityGroup(
    "web-secgrp",
    vpc_id=custom_vpc.vpc.id,
    description="Enable HTTP access",
    ingress=[
        aws.ec2.SecurityGroupIngressArgs(
            protocol="tcp",
            from_port=80,
            to_port=80,
            cidr_blocks=["0.0.0.0/0"],
        )
    ],
    egress=[
        aws.ec2.SecurityGroupEgressArgs(
            protocol="-1",
            from_port=0,
            to_port=0,
            cidr_blocks=["0.0.0.0/0"],
        )
    ],
)

# Create a load balancer to listen for HTTP traffic on port 80.
alb = aws.lb.LoadBalancer(
    "app-lb",
    security_groups=[group.id],
    subnets=custom_vpc.public_subnet_ids,
)

atg = aws.lb.TargetGroup(
    "app-tg",
    port=80,
    protocol="HTTP",
    target_type="ip",
    vpc_id=custom_vpc.vpc.id,
    opts=pulumi.ResourceOptions(parent=alb),
)

wl = aws.lb.Listener(
    "web",
    load_balancer_arn=alb.arn,
    port=80,
    default_actions=[
        aws.lb.ListenerDefaultActionArgs(
            type="forward",
            target_group_arn=atg.arn,
        )
    ],
    opts=pulumi.ResourceOptions(parent=alb)
)

# Create an IAM role that can be used by our service's task.
role = aws.iam.Role(
    "task-exec-role",
    assume_role_policy=json.dumps(
        {
            "Version": "2008-10-17",
            "Statement": [
                {
                    "Sid": "",
                    "Effect": "Allow",
                    "Principal": {"Service": "<http://ecs-tasks.amazonaws.com|ecs-tasks.amazonaws.com>"},
                    "Action": "sts:AssumeRole",
                }
            ],
        }
    ),
)

rpa = aws.iam.RolePolicyAttachment(
    "task-exec-policy",
    role=role.name,
    policy_arn="arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy",
    opts=pulumi.ResourceOptions(parent=role)
)

# Spin up a load balanced service running our container image.
task_definition = aws.ecs.TaskDefinition(
    "app-task",
    family="app-task",
    cpu="256",
    memory="512",
    network_mode="awsvpc",
    requires_compatibilities=["FARGATE"],
    execution_role_arn=role.arn,
    container_definitions=pulumi.Output.all(lb_one=alb.dns_name).apply(
        lambda args: json.dumps(
            [
                {
                    "name": "my-app",
                    "image": "nginx",
                    "portMappings": [
                        {"containerPort": 80, "hostPort": 80, "protocol": "tcp"}
                    ],
                    "environment": [
                        {"name": "LOADBALANCER", "value": args["lb_one"]},
                    ],
                }
            ]
        ),
    ),
    opts=pulumi.ResourceOptions(parent=cluster)
)

service = aws.ecs.Service(
    "app-svc",
    cluster=cluster.arn,
    desired_count=3,
    launch_type="FARGATE",
    task_definition=task_definition.arn,
    network_configuration=aws.ecs.ServiceNetworkConfigurationArgs(
        assign_public_ip=True,
        subnets=custom_vpc.private_subnet_ids,
        security_groups=[group.id],
    ),
    load_balancers=[
        aws.ecs.ServiceLoadBalancerArgs(
            target_group_arn=atg.arn,
            container_name="my-app",
            container_port=80,
        )
    ],
    opts=ResourceOptions(depends_on=[wl], parent=cluster),
)

export("cluster", cluster.name)
export("url", alb.dns_name)