Skip to content

Commit 02179e1

Browse files
authored
Merge branch 'main' into main
2 parents fbb8383 + 99ab6b6 commit 02179e1

File tree

32 files changed

+1430
-16
lines changed

32 files changed

+1430
-16
lines changed

.github/workflows/build-pull-request.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jobs:
3333
# Get the list of changed files, excluding Markdown files
3434
- name: Get changed files
3535
id: changed-files
36-
uses: tj-actions/changed-files@4edd678ac3f81e2dc578756871e4d00c19191daf
36+
uses: tj-actions/changed-files@bab30c2299617f6615ec02a68b9a40d10bd21366
3737
with:
3838
files: ${{ matrix.language }}/**
3939
files_ignore: '**/*.md'
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
.classpath.txt
2+
target
3+
.classpath
4+
.project
5+
.idea
6+
.settings
7+
.vscode
8+
*.iml
9+
10+
# CDK asset staging directory
11+
.cdk.staging
12+
cdk.out
13+
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Application Load Balancer
2+
3+
4+
<!--BEGIN STABILITY BANNER-->
5+
6+
---
7+
8+
![Stability: Stable](https://img.shields.io/badge/stability-Stable-success.svg?style=for-the-badge)
9+
10+
> **This is a stable example. It should successfully build out of the box**
11+
>
12+
> This example is built on Construct Libraries marked "Stable" and does not have any infrastructure prerequisites to build.
13+
14+
---
15+
<!--END STABILITY BANNER-->
16+
17+
This example creates an AutoScalingGroup (containing 2 AWS Graviton2 Micro-T4G EC2 machines running the Amazon Linux 2023 AMI), and an ApplicationLoadBalancer inside a shared VPC.
18+
It hooks up an open listener from the Load Balancer to the Scaling Group to indicate how many targets to balance between.
19+
20+
For more info on using Auto Scaling with Load Balancing see the AWS guide [here](https://docs.aws.amazon.com/autoscaling/ec2/userguide/autoscaling-load-balancer.html).
21+
22+
## Build
23+
24+
To build this example, you need to be in this example's root directory.
25+
Then, run the following:
26+
27+
```bash
28+
npm install -g aws-cdk
29+
npm install
30+
cdk synth
31+
```
32+
33+
This will install the necessary CDK, then this example's dependencies, and then build the CloudFormation template.
34+
The resulting CloudFormation template will be in the `cdk.out` directory.
35+
36+
## Deploy
37+
38+
Run `cdk deploy`.
39+
This will deploy / redeploy the stack to AWS.
40+
After a successful deployment, the URL of the ALB created will be available in the output of the terminal console.
41+
At this point, the ALB URL can be used for testing.
42+
Copy the ALB URL and paste it in the address bar of a browser.
43+
The ALB will route the received requests between the 2 EC2 instances created initially by the ASG.
44+
You can observe that the requests made reach different EC2 instances.
45+
This can be observed based on the content of the web page displayed in the browser (the hello message on the web page contains the host which is different for each EC2 instance).
46+
47+
## Useful commands
48+
49+
* `mvn package` compile and run tests
50+
* `cdk ls` list all stacks in the app
51+
* `cdk synth` emits the synthesized CloudFormation template
52+
* `cdk deploy` deploy this stack to your default AWS account/region
53+
* `cdk diff` compare deployed stack with current state
54+
* `cdk docs` open CDK documentation
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
{
2+
"app": "mvn -e -q compile exec:java",
3+
"watch": {
4+
"include": [
5+
"**"
6+
],
7+
"exclude": [
8+
"README.md",
9+
"cdk*.json",
10+
"target",
11+
"pom.xml",
12+
"src/test"
13+
]
14+
},
15+
"context": {
16+
"@aws-cdk/aws-lambda:recognizeLayerVersion": true,
17+
"@aws-cdk/core:checkSecretUsage": true,
18+
"@aws-cdk/core:target-partitions": [
19+
"aws",
20+
"aws-cn"
21+
],
22+
"@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
23+
"@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
24+
"@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true,
25+
"@aws-cdk/aws-iam:minimizePolicies": true,
26+
"@aws-cdk/core:validateSnapshotRemovalPolicy": true,
27+
"@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true,
28+
"@aws-cdk/aws-s3:createDefaultLoggingPolicy": true,
29+
"@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true,
30+
"@aws-cdk/aws-apigateway:disableCloudWatchRole": true,
31+
"@aws-cdk/core:enablePartitionLiterals": true,
32+
"@aws-cdk/aws-events:eventsTargetQueueSameAccount": true,
33+
"@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true,
34+
"@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true,
35+
"@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true,
36+
"@aws-cdk/aws-route53-patters:useCertificate": true,
37+
"@aws-cdk/customresources:installLatestAwsSdkDefault": false,
38+
"@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true,
39+
"@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true,
40+
"@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true,
41+
"@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true,
42+
"@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true,
43+
"@aws-cdk/aws-redshift:columnId": true,
44+
"@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true,
45+
"@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true,
46+
"@aws-cdk/aws-apigateway:requestValidatorUniqueId": true,
47+
"@aws-cdk/aws-kms:aliasNameRef": true,
48+
"@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": true,
49+
"@aws-cdk/core:includePrefixInUniqueNameGeneration": true,
50+
"@aws-cdk/aws-efs:denyAnonymousAccess": true,
51+
"@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": true,
52+
"@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": true,
53+
"@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": true,
54+
"@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": true,
55+
"@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": true,
56+
"@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": true,
57+
"@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": true,
58+
"@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": true,
59+
"@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": true,
60+
"@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": true,
61+
"@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": true,
62+
"@aws-cdk/aws-eks:nodegroupNameAttribute": true,
63+
"@aws-cdk/aws-ec2:ebsDefaultGp3Volume": true,
64+
"@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": true,
65+
"@aws-cdk/custom-resources:logApiResponseDataPropertyTrueDefault": false,
66+
"@aws-cdk/aws-s3:keepNotificationInImportedBucket": false,
67+
"@aws-cdk/aws-ecs:reduceEc2FargateCloudWatchPermissions": true,
68+
"@aws-cdk/aws-dynamodb:resourcePolicyPerReplica": true,
69+
"@aws-cdk/aws-ec2:ec2SumTimeoutEnabled": true,
70+
"@aws-cdk/aws-appsync:appSyncGraphQLAPIScopeLambdaPermission": true,
71+
"@aws-cdk/aws-rds:setCorrectValueForDatabaseInstanceReadReplicaInstanceResourceId": true,
72+
"@aws-cdk/core:cfnIncludeRejectComplexResourceUpdateCreatePolicyIntrinsics": true,
73+
"@aws-cdk/aws-lambda-nodejs:sdkV3ExcludeSmithyPackages": true,
74+
"@aws-cdk/aws-stepfunctions-tasks:fixRunEcsTaskPolicy": true
75+
}
76+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
3+
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<groupId>com.myorg</groupId>
7+
<artifactId>application-load-balancer</artifactId>
8+
<version>0.1</version>
9+
10+
<properties>
11+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
12+
<cdk.version>2.171.1</cdk.version>
13+
<constructs.version>[10.0.0,11.0.0)</constructs.version>
14+
<junit.version>5.7.1</junit.version>
15+
<maven.compiler.target>22</maven.compiler.target>
16+
<maven.compiler.source>22</maven.compiler.source>
17+
</properties>
18+
19+
<build>
20+
<plugins>
21+
<plugin>
22+
<groupId>org.apache.maven.plugins</groupId>
23+
<artifactId>maven-compiler-plugin</artifactId>
24+
<version>3.11.0</version>
25+
<configuration>
26+
<release>17</release>
27+
</configuration>
28+
</plugin>
29+
<plugin>
30+
<groupId>org.codehaus.mojo</groupId>
31+
<artifactId>exec-maven-plugin</artifactId>
32+
<version>3.1.0</version>
33+
<configuration>
34+
<mainClass>com.myorg.ApplicationLoadBalancerApp</mainClass>
35+
</configuration>
36+
</plugin>
37+
</plugins>
38+
</build>
39+
40+
<dependencies>
41+
<dependency>
42+
<groupId>software.amazon.awscdk</groupId>
43+
<artifactId>aws-cdk-lib</artifactId>
44+
<version>${cdk.version}</version>
45+
</dependency>
46+
<dependency>
47+
<groupId>software.constructs</groupId>
48+
<artifactId>constructs</artifactId>
49+
<version>${constructs.version}</version>
50+
</dependency>
51+
<dependency>
52+
<groupId>org.junit.jupiter</groupId>
53+
<artifactId>junit-jupiter</artifactId>
54+
<version>${junit.version}</version>
55+
<scope>test</scope>
56+
</dependency>
57+
</dependencies>
58+
</project>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.myorg;
2+
3+
import software.amazon.awscdk.App;
4+
import software.amazon.awscdk.StackProps;
5+
6+
public class ApplicationLoadBalancerApp {
7+
public static void main(final String[] args) {
8+
var app = new App();
9+
var stackProps = StackProps.builder().build();
10+
new ApplicationLoadBalancerStack(app, "ApplicationLoadBalancerStack", stackProps);
11+
app.synth();
12+
}
13+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
package com.myorg;
2+
3+
import software.amazon.awscdk.CfnOutput;
4+
import software.amazon.awscdk.Stack;
5+
import software.amazon.awscdk.StackProps;
6+
import software.amazon.awscdk.services.autoscaling.AutoScalingGroup;
7+
import software.amazon.awscdk.services.autoscaling.RequestCountScalingProps;
8+
import software.amazon.awscdk.services.ec2.*;
9+
import software.amazon.awscdk.services.elasticloadbalancingv2.AddApplicationTargetsProps;
10+
import software.amazon.awscdk.services.elasticloadbalancingv2.ApplicationListenerProps;
11+
import software.amazon.awscdk.services.elasticloadbalancingv2.ApplicationLoadBalancer;
12+
import software.constructs.Construct;
13+
14+
import java.util.List;
15+
16+
public class ApplicationLoadBalancerStack extends Stack {
17+
18+
// This user data string is required to deploy a nginx web server to each EC2 instance created.
19+
// A simple web page that displays the host name of the EC2 instance is also deployed to nginx.
20+
// This is useful to check if the ALB created sends requests to different EC2 instances by observing the hostname displayed.
21+
private static final String USER_DATA_CONTENT_NGINX = """
22+
#!/bin/bash
23+
dnf -y upgrade
24+
dnf -y install nginx
25+
systemctl start nginx
26+
systemctl enable nginx
27+
rm -rfv /usr/share/nginx/html/ && mkdir /usr/share/nginx/html/
28+
echo "<h1>Hello world from $(hostname -f)</h1>" > /usr/share/nginx/html/index.html
29+
""";
30+
31+
public ApplicationLoadBalancerStack(final Construct scope, final String id, final StackProps props) {
32+
super(scope, id, props);
33+
var vpc = Vpc.Builder.create(this, "VPC")
34+
.restrictDefaultSecurityGroup(false)
35+
.build();
36+
var amazonLinuxImage = AmazonLinuxImage.Builder.create()
37+
.generation(AmazonLinuxGeneration.AMAZON_LINUX_2023)
38+
.cpuType(AmazonLinuxCpuType.ARM_64)
39+
.userData(UserData.custom(USER_DATA_CONTENT_NGINX))
40+
.build();
41+
var autoScalingGroup = AutoScalingGroup.Builder.create(this, "ASG")
42+
.vpc(vpc)
43+
.instanceType(InstanceType.of(InstanceClass.BURSTABLE4_GRAVITON, InstanceSize.MICRO))
44+
.machineImage(amazonLinuxImage)
45+
// Change the desired capacity (default value of 1) so that 2 EC2 instances are created initially instead of one.
46+
// This way the ALB will route requests between both instances right away making it easier to test load balancing functionality.
47+
.desiredCapacity(2)
48+
.maxCapacity(3)
49+
.minCapacity(1)
50+
.build();
51+
var applicationLoadBalancer = ApplicationLoadBalancer.Builder.create(this, "LB")
52+
.vpc(vpc)
53+
.loadBalancerName("LB")
54+
.internetFacing(Boolean.TRUE)
55+
.build();
56+
var applicationListenerProps = ApplicationListenerProps.builder()
57+
.port(80)
58+
.loadBalancer(applicationLoadBalancer)
59+
.build();
60+
var applicationListener = applicationLoadBalancer.addListener("Listener", applicationListenerProps);
61+
var addApplicationTargetsProps = AddApplicationTargetsProps.builder()
62+
.port(80)
63+
.targets(List.of(autoScalingGroup))
64+
.build();
65+
applicationListener.addTargets("Target", addApplicationTargetsProps);
66+
applicationListener.getConnections().allowDefaultPortFromAnyIpv4("Open to the world");
67+
var requestCountScalingProps = RequestCountScalingProps.builder()
68+
.targetRequestsPerMinute(60)
69+
.build();
70+
// This is an example on how to create a dynamic target tracking scaling policy.
71+
// This is based on the ALB request count per target, but it is more difficult to test.
72+
// The dynamic scaling policy should show up though in the AWS Management Console for the ASG created.
73+
autoScalingGroup.scaleOnRequestCount("AModestLoad", requestCountScalingProps);
74+
CfnOutput.Builder.create(this, "ApplicationLoadBalancerURL")
75+
.value(applicationListener.getLoadBalancer().getLoadBalancerDnsName())
76+
.description("The DNS of the application load balancer.")
77+
.build();
78+
}
79+
}

0 commit comments

Comments
 (0)