Exemplo n.º 1
0
        internal InternalLoadBalancerStack(Construct scope, string id, IInternalLoadBalancerStackProps props) : base(scope, id, props)
        {
            var loadBalancer = new ApplicationLoadBalancer(this, "LoadBalancer", new ApplicationLoadBalancerProps
            {
                Vpc            = props.Vpc,
                InternetFacing = true
            });

            var defaultTarget = new ApplicationTargetGroup(this, "TargetGroup", new ApplicationTargetGroupProps
            {
                Vpc  = props.Vpc,
                Port = 80
            });

            Listener = loadBalancer.AddListener("Listener", new BaseApplicationListenerProps
            {
                Port = 80,
                DefaultTargetGroups = new ApplicationTargetGroup[] { defaultTarget }
            });

            new CfnOutput(this, "LoadBalancerDNS", new CfnOutputProps
            {
                Value = loadBalancer.LoadBalancerDnsName
            });
        }
Exemplo n.º 2
0
        internal CreditoWebApiStack(Construct scope, string id, CustomStackProps props = null)
            : base(scope, id, props)
        {
            var vpc = props.Vpc;

            var creditoWebApiTargetGroup = new ApplicationTargetGroup(this, "CreditoWebApiTargetGroup",
                                                                      new ApplicationTargetGroupProps
            {
                Protocol            = ApplicationProtocol.HTTP,
                Port                = 80,
                Vpc                 = vpc,
                TargetType          = TargetType.IP,
                DeregistrationDelay = Duration.Seconds(60),
                HealthCheck         =
                    new Amazon.CDK.AWS.ElasticLoadBalancingV2.HealthCheck
                {
                    Enabled  = true,
                    Path     = "/api/credito/_monitor/shallow",
                    Protocol = Amazon.CDK.AWS.ElasticLoadBalancingV2.Protocol.HTTP,
                    Port     = "traffic-port",
                    UnhealthyThresholdCount = 2,
                    Interval = Duration.Seconds(60),
                    HealthyThresholdCount = 5,
                    Timeout          = Duration.Seconds(5),
                    HealthyHttpCodes = "200"
                }
            });

            var webApiServiceSecurityGroup = SecurityGroup.FromSecurityGroupId(this,
                                                                               "WebApiServiceSecurityGroup",
                                                                               Fn.ImportValue(Globals.GetDeployEnvironment(this).PutEnvNamePrefixWithDash("WebApiServiceSecurityGroupId")));

            var appListener = ApplicationListener.FromApplicationListenerAttributes(this, "AppListener",
                                                                                    new ApplicationListenerAttributes
            {
                ListenerArn   = Fn.ImportValue(Globals.GetDeployEnvironment(this).PutEnvNamePrefixWithDash("AppListenerArn")),
                SecurityGroup = webApiServiceSecurityGroup
            });

            appListener.AddTargetGroups("CreditoWebApiTargetGroup",
                                        new AddApplicationTargetGroupsProps
            {
                Conditions =
                    new ListenerCondition[]
                {
                    ListenerCondition.PathPatterns(new string[] { "/api/credito*" })
                },
                Priority     = 100,
                TargetGroups = new ApplicationTargetGroup[] { creditoWebApiTargetGroup }
            });

            var creditoWebApiLogGroup = new LogGroup(this, "CreditoWebApiContainerLogGroup",
                                                     new LogGroupProps
            {
                LogGroupName  = $"/ecs/{Globals.GetDeployEnvironment(this).EnvName}/credito/web-api",
                Retention     = RetentionDays.FIVE_DAYS,
                RemovalPolicy = RemovalPolicy.SNAPSHOT
            });

            var creditoWebApiTaskDefinition = new FargateTaskDefinition(this, "CreditoWebApiTaskDefinition",
                                                                        new FargateTaskDefinitionProps
            {
                MemoryLimitMiB = 512,
                Cpu            = 256
            });

            var creditoWebApiLogging = new AwsLogDriver(
                new AwsLogDriverProps
            {
                StreamPrefix = "ecs",
                LogGroup     = creditoWebApiLogGroup
            });

            var creditoWebApiContainer = creditoWebApiTaskDefinition.AddContainer("CreditoWebApiContainer",
                                                                                  new ContainerDefinitionOptions
            {
                Image = ContainerImage.FromAsset(
                    Directory.GetCurrentDirectory(),
                    new AssetImageProps
                {
                    File = "src/Credito.WebApi/Dockerfile"
                }),
                Logging     = creditoWebApiLogging,
                Environment =
                    new Dictionary <string, string>()
                {
                    ["CreditoDatabase__ConnectionString"] =
                        StringParameter.ValueFromLookup(
                            this,
                            $"/{Globals.GetDeployEnvironment(this).EnvName}/credito/web-api/db/connection-string"),
                    ["CreditoDatabase__DatabaseName"] =
                        StringParameter.ValueFromLookup(
                            this,
                            $"/{Globals.GetDeployEnvironment(this).EnvName}/credito/web-api/db/database-name")
                }
            });

            creditoWebApiContainer.AddPortMappings(
                new PortMapping
            {
                ContainerPort = 80,
                HostPort      = 80,
                Protocol      = Amazon.CDK.AWS.ECS.Protocol.TCP
            });

            var cluster = Cluster.FromClusterAttributes(this, "Cluster",
                                                        new ClusterAttributes
            {
                ClusterName    = Fn.ImportValue(Globals.GetDeployEnvironment(this).PutEnvNamePrefixWithDash("ClusterName")),
                Vpc            = vpc,
                SecurityGroups = new SecurityGroup[] { }
            });

            var creditoWebApiService = new FargateService(this, "CreditoWebApiService",
                                                          new FargateServiceProps
            {
                Cluster        = cluster,
                TaskDefinition = creditoWebApiTaskDefinition,
                DesiredCount   = 1,
                CircuitBreaker = new DeploymentCircuitBreaker {
                    Rollback = true
                },
                AssignPublicIp         = false,
                HealthCheckGracePeriod = Duration.Seconds(60),
                SecurityGroups         = new ISecurityGroup[] { webApiServiceSecurityGroup },
                VpcSubnets             = new SubnetSelection {
                    SubnetType = SubnetType.PRIVATE
                }
            });

            creditoWebApiService.AttachToApplicationTargetGroup(creditoWebApiTargetGroup);
        }
Exemplo n.º 3
0
        internal AutoScaledInstances(
            CdkStack stack,
            CfnParameter targetPlatform,
            Vpc vpc,
            bool publicAccess,
            SecurityGroup albSecurityGroup,
            SecurityGroup instanceSecurityGroup,
            Database database = null,
            Policy policy     = null,
            ApplicationLoadBalancer restApiLoadBalancer = null)
        {
            IMachineImage selectedImage;

            bool targetWindows = false;

            if (targetWindows)
            {
                var userData = UserData.ForWindows();
                userData.AddCommands(
                    "New-Item -Path c:\\temp -ItemType Directory -Force",
                    $"Read-S3Object -BucketName aws-codedeploy-{stack.Region}/latest -Key codedeploy-agent.msi -File c:\\temp\\codedeploy-agent.msi",
                    "Start-Process -Wait -FilePath c:\\temp\\codedeploy-agent.msi -WindowStyle Hidden"
                    );
                selectedImage = new WindowsImage(
                    WindowsVersion.WINDOWS_SERVER_2019_ENGLISH_CORE_BASE,
                    new WindowsImageProps
                {
                    UserData = userData
                }
                    );
            }
            else
            {
                var userData = UserData.ForLinux(new LinuxUserDataOptions {
                    Shebang = "#!/bin/bash -xe"
                });
                userData.AddCommands(
                    "exec > >(tee /var/log/user-data.log|logger -t user-data -s 2>/dev/console) 2>&1",
                    "yum install -y aws-cli ruby jq",
                    "yum -y update",
                    "cd /tmp/",
                    $"curl -O https://aws-codedeploy-{stack.Region}.s3.amazonaws.com/latest/install",
                    "chmod +x ./install",
                    "if ./install auto; then",
                    "    echo \"CodeDeploy Agent installation completed successfully!\"",
                    "    exit 0",
                    "else",
                    "    echo \"CodeDeploy Agent installation failed, please investigate.\"",
                    "    rm -f /tmp/install",
                    "    exit 1",
                    "fi",
                    "rm -rf /tmp/*"
                    );
                selectedImage = new AmazonLinuxImage(new AmazonLinuxImageProps
                {
                    Edition        = AmazonLinuxEdition.STANDARD,
                    Virtualization = AmazonLinuxVirt.HVM,
                    Generation     = AmazonLinuxGeneration.AMAZON_LINUX_2,
                    Storage        = AmazonLinuxStorage.EBS,
                    UserData       = userData
                });
            };

            var alb = new ApplicationLoadBalancer(stack, $"ApplicationLoadBalancer-{(publicAccess ? "public" : "private")}", new ApplicationLoadBalancerProps
            {
                InternetFacing = publicAccess,
                Vpc            = vpc,
                VpcSubnets     = new SubnetSelection {
                    SubnetType = publicAccess ? SubnetType.PUBLIC : SubnetType.PRIVATE
                },
                SecurityGroup = albSecurityGroup,
                IpAddressType = IpAddressType.IPV4,
                Http2Enabled  = true
            });

            var albTargetGroup = new ApplicationTargetGroup(stack, $"ApplicationTargetGroup-{(publicAccess ? "public" : "private")}", new ApplicationTargetGroupProps
            {
                Vpc         = vpc,
                Port        = 80,
                Protocol    = ApplicationProtocol.HTTP,
                TargetType  = TargetType.INSTANCE,
                HealthCheck = new Amazon.CDK.AWS.ElasticLoadBalancingV2.HealthCheck
                {
                    Timeout  = Duration.Seconds(5),
                    Interval = Duration.Seconds(10),
                    HealthyThresholdCount = 2
                }
            });
            var albListener = new ApplicationListener(stack, $"ApplicationListener-{(publicAccess ? "public" : "private")}", new ApplicationListenerProps
            {
                Port          = 80,
                Protocol      = ApplicationProtocol.HTTP,
                DefaultAction = ListenerAction.Forward(new[] { albTargetGroup }),
                LoadBalancer  = alb
            });

            var asg = new AutoScalingGroup(stack, $"ASG-{(publicAccess ? "public" : "private")}", new AutoScalingGroupProps
            {
                Vpc          = vpc,
                MinCapacity  = 2,
                InstanceType = InstanceType.Of(InstanceClass.BURSTABLE3, InstanceSize.MEDIUM),
                MachineImage = selectedImage,
                BlockDevices = new[] {
                    new Amazon.CDK.AWS.AutoScaling.BlockDevice()
                    {
                        DeviceName = "/dev/xvda",
                        Volume     = Amazon.CDK.AWS.AutoScaling.BlockDeviceVolume.Ebs(
                            targetWindows ? 30: 8,
                            new Amazon.CDK.AWS.AutoScaling.EbsDeviceOptions {
                            VolumeType          = Amazon.CDK.AWS.AutoScaling.EbsDeviceVolumeType.GP2,
                            DeleteOnTermination = true
                        }
                            )
                    }
                },
                AssociatePublicIpAddress = false,
                VpcSubnets = new SubnetSelection {
                    SubnetType = SubnetType.PRIVATE
                }
            });

            if (policy != null)
            {
                asg.Role.AttachInlinePolicy(policy);
            }
            asg.Role.AddToPrincipalPolicy(
                new PolicyStatement(new PolicyStatementProps
            {
                Effect    = Effect.ALLOW,
                Actions   = new[] { "ec2:DescribeTags" },
                Resources = new[] { "*" }
            })
                );
            asg.Role.AddManagedPolicy(ManagedPolicy.FromAwsManagedPolicyName("AmazonSSMManagedInstanceCore"));
            asg.Role.AddManagedPolicy(ManagedPolicy.FromAwsManagedPolicyName("AWSXRayDaemonWriteAccess"));
            asg.Role.AddManagedPolicy(ManagedPolicy.FromAwsManagedPolicyName("CloudWatchAgentServerPolicy"));

            Tag.Add(asg, "Application", stack.StackName);
            if (publicAccess)
            {
                Tag.Add(asg, "ApplicationRole", "Front End");
                Tag.Add(asg, "RESTAPIAddress", restApiLoadBalancer.LoadBalancerDnsName);
            }
            else
            {
                Tag.Add(asg, "ApplicationRole", "REST API");
            }
            if (database != null)
            {
                asg.Node.AddDependency(database.DatabaseResource);
                Tag.Add(asg, "DBSecretArn", database.Password.SecretArn);
            }

            // Enable access from the ALB
            asg.AddSecurityGroup(instanceSecurityGroup);
            Result = new LoadBalancedInstancesResult
            {
                AutoScalingGroup = asg,
                TargetGroup      = albTargetGroup,
                LoadBalancer     = alb
            };
        }
Exemplo n.º 4
0
        private void ConfigureLoadBalancer(Configuration settings)
        {
            if (AppVpc == null)
            {
                throw new InvalidOperationException($"{nameof(AppVpc)} has not been set. The {nameof(ConfigureVpc)} method should be called before {nameof(ConfigureLoadBalancer)}");
            }
            if (EcsCluster == null)
            {
                throw new InvalidOperationException($"{nameof(EcsCluster)} has not been set. The {nameof(ConfigureECSClusterAndService)} method should be called before {nameof(ConfigureLoadBalancer)}");
            }
            if (AppFargateService == null)
            {
                throw new InvalidOperationException($"{nameof(AppFargateService)} has not been set. The {nameof(ConfigureECSClusterAndService)} method should be called before {nameof(ConfigureLoadBalancer)}");
            }

            if (settings.LoadBalancer.CreateNew)
            {
                ServiceLoadBalancer = new ApplicationLoadBalancer(this, nameof(ServiceLoadBalancer), InvokeCustomizeCDKPropsEvent(nameof(ServiceLoadBalancer), this, new ApplicationLoadBalancerProps
                {
                    Vpc            = AppVpc,
                    InternetFacing = true
                }));

                LoadBalancerListener = ServiceLoadBalancer.AddListener(nameof(LoadBalancerListener), InvokeCustomizeCDKPropsEvent(nameof(LoadBalancerListener), this, new ApplicationListenerProps
                {
                    Protocol = ApplicationProtocol.HTTP,
                    Port     = 80,
                    Open     = true
                }));

                ServiceTargetGroup = LoadBalancerListener.AddTargets(nameof(ServiceTargetGroup), InvokeCustomizeCDKPropsEvent(nameof(ServiceTargetGroup), this, new AddApplicationTargetsProps
                {
                    Protocol            = ApplicationProtocol.HTTP,
                    DeregistrationDelay = Duration.Seconds(settings.LoadBalancer.DeregistrationDelayInSeconds)
                }));
            }
            else
            {
                ServiceLoadBalancer = ApplicationLoadBalancer.FromLookup(this, nameof(ServiceLoadBalancer), InvokeCustomizeCDKPropsEvent(nameof(ServiceLoadBalancer), this, new ApplicationLoadBalancerLookupOptions
                {
                    LoadBalancerArn = settings.LoadBalancer.ExistingLoadBalancerArn
                }));

                LoadBalancerListener = ApplicationListener.FromLookup(this, nameof(LoadBalancerListener), InvokeCustomizeCDKPropsEvent(nameof(LoadBalancerListener), this, new ApplicationListenerLookupOptions
                {
                    LoadBalancerArn = settings.LoadBalancer.ExistingLoadBalancerArn,
                    ListenerPort    = 80
                }));

                ServiceTargetGroup = new ApplicationTargetGroup(this, nameof(ServiceTargetGroup), InvokeCustomizeCDKPropsEvent(nameof(ServiceTargetGroup), this, new ApplicationTargetGroupProps
                {
                    Port = 80,
                    Vpc  = EcsCluster.Vpc,
                }));


                var addApplicationTargetGroupsProps = new AddApplicationTargetGroupsProps
                {
                    TargetGroups = new[] { ServiceTargetGroup }
                };

                if (settings.LoadBalancer.ListenerConditionType != LoadBalancerConfiguration.ListenerConditionTypeEnum.None)
                {
                    addApplicationTargetGroupsProps.Priority = settings.LoadBalancer.ListenerConditionPriority;
                }

                if (settings.LoadBalancer.ListenerConditionType == LoadBalancerConfiguration.ListenerConditionTypeEnum.Path)
                {
                    if (settings.LoadBalancer.ListenerConditionPathPattern == null)
                    {
                        throw new ArgumentNullException("Listener condition type was set to \"Path\" but no value was set for the \"TargetPathPattern\"");
                    }
                    addApplicationTargetGroupsProps.Conditions = new ListenerCondition[]
                    {
                        ListenerCondition.PathPatterns(new [] { settings.LoadBalancer.ListenerConditionPathPattern })
                    };
                }

                LoadBalancerListener.AddTargetGroups("AddTargetGroup", InvokeCustomizeCDKPropsEvent("AddTargetGroup", this, addApplicationTargetGroupsProps));
            }

            // Configure health check for ALB Target Group
            var healthCheck = new Amazon.CDK.AWS.ElasticLoadBalancingV2.HealthCheck();

            if (settings.LoadBalancer.HealthCheckPath != null)
            {
                var path = settings.LoadBalancer.HealthCheckPath;
                if (!path.StartsWith("/"))
                {
                    path = "/" + path;
                }
                healthCheck.Path = path;
            }
            if (settings.LoadBalancer.HealthCheckInternval.HasValue)
            {
                healthCheck.Interval = Duration.Seconds(settings.LoadBalancer.HealthCheckInternval.Value);
            }
            if (settings.LoadBalancer.HealthyThresholdCount.HasValue)
            {
                healthCheck.HealthyThresholdCount = settings.LoadBalancer.HealthyThresholdCount.Value;
            }
            if (settings.LoadBalancer.UnhealthyThresholdCount.HasValue)
            {
                healthCheck.UnhealthyThresholdCount = settings.LoadBalancer.UnhealthyThresholdCount.Value;
            }

            ServiceTargetGroup.ConfigureHealthCheck(healthCheck);

            ServiceTargetGroup.AddTarget(AppFargateService);
        }