public MyStack() { var vpc = Output.Create(Aws.Ec2.GetVpc.InvokeAsync(new Aws.Ec2.GetVpcArgs { Default = true, })); var subnets = vpc.Apply(vpc => Output.Create(Aws.Ec2.GetSubnetIds.InvokeAsync(new Aws.Ec2.GetSubnetIdsArgs { VpcId = vpc.Id, }))); // Create a security group that permits HTTP ingress and unrestricted egress. var webSecurityGroup = new Aws.Ec2.SecurityGroup("webSecurityGroup", new Aws.Ec2.SecurityGroupArgs { VpcId = vpc.Apply(vpc => vpc.Id), Egress = { new Aws.Ec2.Inputs.SecurityGroupEgressArgs { Protocol = "-1", FromPort = 0, ToPort = 0, CidrBlocks = { "0.0.0.0/0", }, }, }, Ingress = { new Aws.Ec2.Inputs.SecurityGroupIngressArgs { Protocol = "tcp", FromPort = 80, ToPort = 80, CidrBlocks = { "0.0.0.0/0", }, }, }, }); // Create an ECS cluster to run a container-based service. var cluster = new Aws.Ecs.Cluster("cluster", new Aws.Ecs.ClusterArgs { }); // Create an IAM role that can be used by our service's task. var taskExecRole = new Aws.Iam.Role("taskExecRole", new Aws.Iam.RoleArgs { AssumeRolePolicy = JsonSerializer.Serialize(new Dictionary <string, object?> { { "Version", "2008-10-17" }, { "Statement", new[] { new Dictionary <string, object?> { { "Sid", "" }, { "Effect", "Allow" }, { "Principal", new Dictionary <string, object?> { { "Service", "ecs-tasks.amazonaws.com" }, } }, { "Action", "sts:AssumeRole" }, }, } }, }), }); var taskExecRolePolicyAttachment = new Aws.Iam.RolePolicyAttachment("taskExecRolePolicyAttachment", new Aws.Iam.RolePolicyAttachmentArgs { Role = taskExecRole.Name, PolicyArn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy", }); // Create a load balancer to listen for HTTP traffic on port 80. var webLoadBalancer = new Aws.ElasticLoadBalancingV2.LoadBalancer("webLoadBalancer", new Aws.ElasticLoadBalancingV2.LoadBalancerArgs { Subnets = subnets.Apply(subnets => subnets.Ids), SecurityGroups = { webSecurityGroup.Id, }, }); var webTargetGroup = new Aws.ElasticLoadBalancingV2.TargetGroup("webTargetGroup", new Aws.ElasticLoadBalancingV2.TargetGroupArgs { Port = 80, Protocol = "HTTP", TargetType = "ip", VpcId = vpc.Apply(vpc => vpc.Id), }); var webListener = new Aws.ElasticLoadBalancingV2.Listener("webListener", new Aws.ElasticLoadBalancingV2.ListenerArgs { LoadBalancerArn = webLoadBalancer.Arn, Port = 80, DefaultActions = { new Aws.ElasticLoadBalancingV2.Inputs.ListenerDefaultActionArgs { Type = "forward", TargetGroupArn = webTargetGroup.Arn, }, }, }); // Spin up a load balanced service running NGINX var appTask = new Aws.Ecs.TaskDefinition("appTask", new Aws.Ecs.TaskDefinitionArgs { Family = "fargate-task-definition", Cpu = "256", Memory = "512", NetworkMode = "awsvpc", RequiresCompatibilities = { "FARGATE", }, ExecutionRoleArn = taskExecRole.Arn, ContainerDefinitions = JsonSerializer.Serialize(new[] { new Dictionary <string, object?> { { "name", "my-app" }, { "image", "nginx" }, { "portMappings", new[] { new Dictionary <string, object?> { { "containerPort", 80 }, { "hostPort", 80 }, { "protocol", "tcp" }, }, } }, }, } ), }); var appService = new Aws.Ecs.Service("appService", new Aws.Ecs.ServiceArgs { Cluster = cluster.Arn, DesiredCount = 5, LaunchType = "FARGATE", TaskDefinition = appTask.Arn, NetworkConfiguration = new Aws.Ecs.Inputs.ServiceNetworkConfigurationArgs { AssignPublicIp = true, Subnets = subnets.Apply(subnets => subnets.Ids), SecurityGroups = { webSecurityGroup.Id, }, }, LoadBalancers = { new Aws.Ecs.Inputs.ServiceLoadBalancerArgs { TargetGroupArn = webTargetGroup.Arn, ContainerName = "my-app", ContainerPort = 80, }, }, }, new CustomResourceOptions { DependsOn = { webListener, }, }); this.Url = webLoadBalancer.DnsName; }
public FargateStack() { // Read back the default VPC and public subnets, which we will use. var vpc = Output.Create(Ec2.GetVpc.InvokeAsync(new Ec2.GetVpcArgs { Default = true })); var vpcId = vpc.Apply(vpc => vpc.Id); var subnet = vpcId.Apply(id => Ec2.GetSubnetIds.InvokeAsync(new Ec2.GetSubnetIdsArgs { VpcId = id })); var subnetIds = subnet.Apply(s => s.Ids); // Create a SecurityGroup that permits HTTP ingress and unrestricted egress. var webSg = new Ec2.SecurityGroup("web-sg", new Ec2.SecurityGroupArgs { VpcId = vpcId, Egress = { new Ec2.Inputs.SecurityGroupEgressArgs { Protocol = "-1", FromPort = 0, ToPort = 0, CidrBlocks ={ "0.0.0.0/0" } } }, Ingress = { new Ec2.Inputs.SecurityGroupIngressArgs { Protocol = "tcp", FromPort = 80, ToPort = 80, CidrBlocks ={ "0.0.0.0/0" } } } }); // Create an ECS cluster to run a container-based service. var cluster = new Ecs.Cluster("app-cluster"); // Create an IAM role that can be used by our service's task. var taskExecRole = new Iam.Role("task-exec-role", new Iam.RoleArgs { AssumeRolePolicy = @"{ ""Version"": ""2008-10-17"", ""Statement"": [{ ""Sid"": """", ""Effect"": ""Allow"", ""Principal"": { ""Service"": ""ecs-tasks.amazonaws.com"" }, ""Action"": ""sts:AssumeRole"" }] }" }); var taskExecAttach = new Iam.RolePolicyAttachment("task-exec-policy", new Iam.RolePolicyAttachmentArgs { Role = taskExecRole.Name, PolicyArn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy" }); // Create a load balancer to listen for HTTP traffic on port 80. var webLb = new Elb.LoadBalancer("web-lb", new Elb.LoadBalancerArgs { Subnets = subnetIds, SecurityGroups = { webSg.Id } }); var webTg = new Elb.TargetGroup("web-tg", new Elb.TargetGroupArgs { Port = 80, Protocol = "HTTP", TargetType = "ip", VpcId = vpcId }); var webListener = new Elb.Listener("web-listener", new Elb.ListenerArgs { LoadBalancerArn = webLb.Arn, Port = 80, DefaultActions = { new Elb.Inputs.ListenerDefaultActionArgs { Type = "forward", TargetGroupArn = webTg.Arn, } } }); // Create a private ECR registry and build and publish our app's container image to it. var appRepo = new Ecr.Repository("app-repo"); var appRepoCredentials = appRepo.RegistryId.Apply(async rid => { var credentials = await Ecr.GetCredentials.InvokeAsync(new Ecr.GetCredentialsArgs { RegistryId = rid }); var data = Convert.FromBase64String(credentials.AuthorizationToken); return(Encoding.UTF8.GetString(data).Split(":").ToImmutableArray()); }); var image = new Docker.Image("app-img", new Docker.ImageArgs { Build = "../App", ImageName = appRepo.RepositoryUrl, Registry = new Docker.ImageRegistry { Server = appRepo.RepositoryUrl, Username = appRepoCredentials.GetAt(0), Password = appRepoCredentials.GetAt(1) } }); // Spin up a load balanced service running our container image. var appTask = new Ecs.TaskDefinition("app-task", new Ecs.TaskDefinitionArgs { Family = "fargate-task-definition", Cpu = "256", Memory = "512", NetworkMode = "awsvpc", RequiresCompatibilities = { "FARGATE" }, ExecutionRoleArn = taskExecRole.Arn, ContainerDefinitions = image.ImageName.Apply(imageName => @"[{ ""name"": ""my-app"", ""image"": """ + imageName + @""", ""portMappings"": [{ ""containerPort"": 80, ""hostPort"": 80, ""protocol"": ""tcp"" }] }]") }); var appSvc = new Ecs.Service("app-svc", new Ecs.ServiceArgs { Cluster = cluster.Arn, DesiredCount = 3, LaunchType = "FARGATE", TaskDefinition = appTask.Arn, NetworkConfiguration = new Ecs.Inputs.ServiceNetworkConfigurationArgs { AssignPublicIp = true, Subnets = subnetIds, SecurityGroups = { webSg.Id } }, LoadBalancers = { new Ecs.Inputs.ServiceLoadBalancerArgs { TargetGroupArn = webTg.Arn, ContainerName = "my-app", ContainerPort = 80 } } }, new CustomResourceOptions { DependsOn = { webListener } }); // Export the resulting web address. this.Url = Output.Format($"http://{webLb.DnsName}"); }
private static void ConfigureEcsCluster() { cluster = new Ecs.Cluster($"{baseName}-cluster", null, new CustomResourceOptions()); // Create a SecurityGroup that permits HTTP ingress and unrestricted egress. var webSg = new Ec2.SecurityGroup($"{baseName}-web-sg", new Ec2.SecurityGroupArgs { VpcId = vpcId, Egress = { new Ec2.Inputs.SecurityGroupEgressArgs { Protocol = "-1", FromPort = 0, ToPort = 0, CidrBlocks ={ "0.0.0.0/0" }, }, }, Ingress = { new Ec2.Inputs.SecurityGroupIngressArgs { Protocol = "tcp", FromPort = 80, ToPort = 80, CidrBlocks ={ "0.0.0.0/0" }, }, }, }); // Create an IAM role that can be used by our service's task. var taskExecRole = new Iam.Role($"{baseName}-task-exec-role", new Iam.RoleArgs { AssumeRolePolicy = File.ReadAllText("perm.json"), }); var taskExecAttach = new Iam.RolePolicyAttachment($"{baseName}-task-exec-policy", new Iam.RolePolicyAttachmentArgs { Role = taskExecRole.Name, PolicyArn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy", }); // Create a load balancer to listen for HTTP traffic on port 80. var webLb = new Elb.LoadBalancer($"{baseName}-web-lb", new Elb.LoadBalancerArgs { Subnets = new InputList <string>() { subnetId, subnetTwoId }, SecurityGroups = { webSg.Id }, }); var webTg = new Elb.TargetGroup($"{baseName}-web-tg", new Elb.TargetGroupArgs { Port = 80, Protocol = "HTTP", TargetType = "ip", VpcId = vpcId, }); var webListener = new Elb.Listener($"{baseName}-web-listener", new Elb.ListenerArgs { LoadBalancerArn = webLb.Arn, Port = 80, DefaultActions = { new Elb.Inputs.ListenerDefaultActionsArgs { Type = "forward", TargetGroupArn = webTg.Arn, }, }, }); var launchConfig = new Ec2.LaunchConfiguration($"{baseName}-launchconfig", new Ec2.LaunchConfigurationArgs() { ImageId = "ami-a1491ad2", InstanceType = "t2.nano", AssociatePublicIpAddress = true, SecurityGroups = webSg.Id, }); var scalingGroup = new Group($"{baseName}-autoscaling", new GroupArgs() { AvailabilityZones = new InputList <string>() { "eu-west-1a", "eu-west-1b" }, VpcZoneIdentifiers = new InputList <string>() { subnetId, subnetTwoId }, DesiredCapacity = 1, LaunchConfiguration = launchConfig.Id, MaxSize = 1, MinSize = 0, }); // Spin up a load balanced service running our container image. var appTask = new Ecs.TaskDefinition($"{baseName}-app-task", new Ecs.TaskDefinitionArgs { Family = "fargate-task-definition", Cpu = "256", Memory = "512", NetworkMode = "awsvpc", RequiresCompatibilities = { "FARGATE", "EC2" }, ExecutionRoleArn = taskExecRole.Arn, ContainerDefinitions = @"[{ ""name"": ""my-app"", ""image"": ""nginx"", ""portMappings"": [{ ""containerPort"": 80, ""hostPort"": 80, ""protocol"": ""tcp"" }] }]", }); var ec2Svc = new Ecs.Service($"{baseName}-ec2-svc", new Ecs.ServiceArgs() { Cluster = cluster.Arn, DesiredCount = 1, LaunchType = "EC2", TaskDefinition = appTask.Arn, NetworkConfiguration = new Ecs.Inputs.ServiceNetworkConfigurationArgs { Subnets = new InputList <string>() { subnetId, subnetTwoId }, SecurityGroups = { webSg.Id }, }, LoadBalancers = { new Ecs.Inputs.ServiceLoadBalancersArgs { TargetGroupArn = webTg.Arn, ContainerName = "my-app", ContainerPort = 80, }, }, }, new CustomResourceOptions { DependsOn = { webListener } }); }