public ApplicationLoadBalancer Create(Construct construct, Amazon.CDK.AWS.EC2.Vpc vpc, Amazon.CDK.AWS.AutoScaling.AutoScalingGroup asg, SecurityGroup sg) { var lb = new ApplicationLoadBalancer(construct, _config.Alb.Name, new ApplicationLoadBalancerProps { Vpc = vpc, InternetFacing = true, LoadBalancerName = _config.Alb.Name, SecurityGroup = sg }); Amazon.CDK.Tags.Of(lb).Add("Name", $"{_config.Alb.Name}"); // add a listener var listener = AddListener(lb, 80, null); var appPort = 80; var group = listener.AddTargets($"AppFleet", new AddApplicationTargetsProps { Port = appPort, Targets = new[] { asg } }); // add specific tags Amazon.CDK.Tags.Of(listener).Add("Name", $"{_config.Alb.Name}-listner"); Amazon.CDK.Tags.Of(group).Add("Name", $"{_config.Alb.Name}-fleet"); // exmple of a fixed ok message returned by the LB listener.AddAction($"FixedOkMessage", new AddApplicationActionProps { Priority = 10, Conditions = new[] { ListenerCondition.PathPatterns(new[] { "/ok" }) }, Action = ListenerAction.FixedResponse(200, new FixedResponseOptions { ContentType = "text/html", MessageBody = "OK" }) }); // example of a fixed health status message returned by LB listener.AddAction($"LBHealthInfo", new AddApplicationActionProps { Priority = 15, Conditions = new[] { ListenerCondition.PathPatterns(new[] { "/lb-status" }) }, Action = ListenerAction.FixedResponse(200, new FixedResponseOptions { ContentType = "application/json", MessageBody = "{ \"lb\": { \"type\": \"application-load-balancer\", \"launchDateUtc\": \"{" + DateTime.UtcNow + "}\", \"status\": \"ok\" } }" }) }); //"arn:aws:acm:us-east-1:xxxxxxxxx:certificate/eb2b584c-421d-4134-b679-1746642b5e3f" if (_config.Alb.CertArn != null) { listener = AddListener(lb, 443, _config.Alb.CertArn); // forward any ssl requests to the target group listener.AddAction("SSLForward", new AddApplicationActionProps { Action = ListenerAction.Forward(new[] { group }), }); } return(lb); }
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); }
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); }