Skip to content

Commit ea5de82

Browse files
authored
feat(typescript): add AWS Batch with ECR and Lambda example for OpenMP (#1188)
* feat(typescript): add AWS Batch with ECR and Lambda example for OpenMP benchmarks * feat(typescript): add AWS Batch with ECR and Lambda example for OpenMP benchmarks * Update package.json * Update package.json * Update aws-batch-openmp-benchmark.test.ts * chore(typescript/batch-ecr-openmp):Update Dockerfile, README.md Update Dockerfile to use Ubuntu 24 instead of 22 Update README * chore(typescript/batch-ecr-openmp):Update Dockerfile
1 parent dcf0e8a commit ea5de82

File tree

15 files changed

+2703
-0
lines changed

15 files changed

+2703
-0
lines changed
Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
# AWS Batch with ECR and Lambda
2+
<!--BEGIN STABILITY BANNER-->
3+
---
4+
5+
![Stability: Stable](https://img.shields.io/badge/stability-Stable-success.svg?style=for-the-badge)
6+
7+
> **This is a stable example. It should successfully build out of the box**
8+
>
9+
> This examples is built on Construct Libraries marked "Stable" and does not have any infrastructure prerequisites to build.
10+
11+
---
12+
<!--END STABILITY BANNER-->
13+
14+
This example demonstrates how to use AWS Batch with a containerized C++ OpenMP application stored in Amazon ECR, with optional Lambda function for job submission. The OpenMP application performs parallel computing benchmarks (arithmetic operations, mathematical functions, matrix multiplication) to demonstrate CPU-intensive workloads and compare sequential vs parallel execution performance.
15+
16+
## Prerequisites
17+
18+
Before deploying, ensure you have:
19+
- AWS CLI configured with sufficient permissions for infrastructure deployment
20+
- AdministratorAccess recommended, or custom policy with EC2, VPC, Batch, ECR, Lambda, IAM, CloudFormation, and CloudWatch Logs permissions
21+
- Docker installed and running
22+
- Node.js and npm installed
23+
- `jq` command-line JSON processor (for job submission script)
24+
25+
## Quick Start
26+
27+
For a complete end-to-end deployment and testing:
28+
29+
```bash
30+
# 1. Test locally first (optional but recommended)
31+
./scripts/test-local.sh
32+
33+
# 2. Deploy everything to AWS
34+
AWS_PROFILE=your-profile ./scripts/build-and-deploy.sh
35+
36+
# 3. Submit a benchmark job
37+
./scripts/submit-job.sh --benchmark-type simple
38+
```
39+
40+
## Build
41+
42+
To build this app manually, you need to be in this example's root folder. Then run the following:
43+
44+
```bash
45+
npm install -g aws-cdk
46+
npm install
47+
npm run build
48+
```
49+
50+
This will install the necessary CDK, then this example's dependencies, and then build your TypeScript files and your CloudFormation template.
51+
52+
## Deploy
53+
54+
### Option 1: Automated Deployment (Recommended)
55+
56+
Use the provided script for a complete deployment:
57+
58+
```bash
59+
AWS_PROFILE=your-profile ./scripts/build-and-deploy.sh
60+
```
61+
62+
This script will:
63+
1. Build the CDK stack
64+
2. Deploy the infrastructure to AWS
65+
3. Build and push the Docker image to ECR
66+
4. Save deployment information for job submission
67+
68+
### Option 2: Manual Deployment
69+
70+
For manual control over each step:
71+
72+
```bash
73+
# Deploy CDK stack
74+
npx cdk deploy --profile your-profile
75+
76+
# Get ECR login and build/push Docker image
77+
aws ecr get-login-password --region your-region | docker login --username AWS --password-stdin your-account.dkr.ecr.your-region.amazonaws.com
78+
docker build -f docker/Dockerfile -t openmp-benchmark:latest .
79+
docker tag openmp-benchmark:latest your-account.dkr.ecr.your-region.amazonaws.com/openmp-benchmark:latest
80+
docker push your-account.dkr.ecr.your-region.amazonaws.com/openmp-benchmark:latest
81+
```
82+
83+
After deployment, you will see the Stack outputs, which include the ECR repository URI and Batch job queue name.
84+
85+
## Running Benchmarks
86+
87+
After successful deployment, you can submit OpenMP benchmark jobs using the provided script:
88+
89+
### Basic Usage
90+
91+
```bash
92+
# Submit a simple benchmark (default)
93+
./scripts/submit-job.sh
94+
95+
# Submit specific benchmark types
96+
./scripts/submit-job.sh --benchmark-type math
97+
./scripts/submit-job.sh --benchmark-type matrix
98+
./scripts/submit-job.sh --benchmark-type heavy
99+
./scripts/submit-job.sh --benchmark-type all
100+
```
101+
102+
### Advanced Options
103+
104+
```bash
105+
# Custom parameters
106+
./scripts/submit-job.sh --benchmark-type matrix --instance c6i.2xlarge --threads 8
107+
108+
# Submit via Lambda function
109+
./scripts/submit-job.sh --method lambda --benchmark-type simple
110+
111+
# Preview commands without executing
112+
./scripts/submit-job.sh --dry-run --benchmark-type all
113+
```
114+
115+
### Available Benchmark Types
116+
117+
- **simple** - Basic arithmetic operations (~2 seconds)
118+
- **math** - Mathematical functions: sin, cos, sqrt, pow (~5 seconds)
119+
- **matrix** - Matrix multiplication (memory intensive, ~3 seconds)
120+
- **heavy** - Complex arithmetic expressions (~3 seconds)
121+
- **all** - Run all benchmarks sequentially (~15 seconds total)
122+
123+
### Monitoring Jobs
124+
125+
After submitting a job, you can monitor it through:
126+
127+
1. **AWS Console**:
128+
- Batch: https://console.aws.amazon.com/batch/
129+
- CloudWatch Logs: https://console.aws.amazon.com/cloudwatch/
130+
131+
2. **AWS CLI**:
132+
```bash
133+
# Check job status
134+
aws batch describe-jobs --profile your-profile --jobs <JOB_ID>
135+
136+
# View logs
137+
aws logs describe-log-streams --profile your-profile --log-group-name /aws/batch/openmp-benchmark
138+
```
139+
140+
## Testing
141+
142+
### Local Testing
143+
144+
Before deploying to AWS, you can test the OpenMP application locally:
145+
146+
```bash
147+
./scripts/test-local.sh
148+
```
149+
150+
This script will:
151+
1. Build the OpenMP application locally
152+
2. Run C++ unit tests (8 test cases)
153+
3. Execute integration tests with various parameters
154+
4. Build and test the Docker container
155+
5. Run CDK unit tests
156+
157+
### What Gets Tested
158+
159+
- ✓ OpenMP application builds successfully
160+
- ✓ C++ unit tests pass (sequential vs parallel validation)
161+
- ✓ Integration tests with different parameters
162+
- ✓ Docker container builds and runs correctly
163+
- ✓ CDK stack synthesizes without errors
164+
165+
## The Component Structure
166+
167+
The whole component contains:
168+
169+
- An ECR repository for storing the Docker image
170+
- AWS Batch compute environment with managed EC2 instances
171+
- AWS Batch job definition and job queue
172+
- Lambda function for job submission (optional)
173+
- VPC with public and private subnets
174+
- CloudWatch log group for job logs
175+
176+
## CDK Toolkit
177+
178+
The [`cdk.json`](./cdk.json) file in the root of this repository includes
179+
instructions for the CDK toolkit on how to execute this program.
180+
181+
After building your TypeScript code, you will be able to run the CDK toolkit commands as usual:
182+
183+
```bash
184+
$ cdk ls
185+
<list all stacks in this program>
186+
187+
$ cdk synth
188+
<generates and outputs cloudformation template>
189+
190+
$ cdk deploy
191+
<deploys stack to your account>
192+
193+
$ cdk diff
194+
<shows diff against deployed stack>
195+
```
196+
197+
## Cleanup
198+
199+
To completely remove all AWS resources and avoid ongoing charges:
200+
201+
### Step 1: Cancel Running Jobs
202+
203+
Before destroying the stack, ensure no jobs are running:
204+
205+
#### Option A: Using AWS Console (Visual Method)
206+
1. Navigate to [AWS Batch Console](https://console.aws.amazon.com/batch/)
207+
2. Click on "Jobs" in the left sidebar
208+
3. Select your job queue (e.g., "AwsBatchOpenmpBenchmarkStack-OpenMPJobQueue...")
209+
4. Filter by status: RUNNING, RUNNABLE, or PENDING
210+
5. Select any active jobs and click "Terminate job"
211+
6. Provide a reason (e.g., "Stack cleanup")
212+
7. Verify all jobs show as SUCCEEDED, FAILED, or CANCELLED
213+
214+
#### Option B: Using AWS CLI (Programmatic Method)
215+
```bash
216+
# List running jobs
217+
aws batch list-jobs --profile your-profile \
218+
--job-queue <queue-name> \
219+
--job-status RUNNING
220+
221+
# Terminate each job
222+
aws batch terminate-job --profile your-profile \
223+
--job-id <job-id> \
224+
--reason "Stack cleanup"
225+
```
226+
227+
### Step 2: Destroy the Stack
228+
229+
```bash
230+
npx cdk destroy --profile your-profile
231+
```
232+
233+
Type 'y' when prompted to confirm deletion. This will remove:
234+
- ✓ All infrastructure resources (VPC, subnets, NAT gateway)
235+
- ✓ ECR repository and all Docker images inside it
236+
- ✓ Batch compute environment, job queue, and job definitions
237+
- ✓ Lambda function and IAM roles
238+
- ✓ CloudWatch log groups and all logs
239+
- ✓ Security groups and all networking components
240+
241+
### Step 3: Clean Up Local Artifacts (Optional)
242+
243+
```bash
244+
# Remove deployment info file
245+
rm -f deployment-info.json
246+
247+
# Remove all local Docker images (including tagged ECR images)
248+
docker rmi $(docker images | grep openmp-benchmark | awk '{print $3}')
249+
250+
# Clean up Docker build cache (frees significant disk space)
251+
docker builder prune
252+
253+
# Clean up any dangling Docker images
254+
docker image prune
255+
```
256+
257+
### Verification
258+
259+
After cleanup, verify in the AWS Console that:
260+
- The CloudFormation stack is deleted
261+
- No ECR repositories remain for this project
262+
- No VPC resources are left behind
263+
- No unexpected charges appear in your AWS billing
264+
265+
> **Note**: The stack is specifically configured for complete resource deletion. All resources have appropriate removal policies to ensure clean deletion without leaving orphaned resources.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#!/usr/bin/env node
2+
import * as cdk from 'aws-cdk-lib';
3+
import { AwsBatchOpenmpBenchmarkStack } from '../lib/aws-batch-openmp-benchmark-stack';
4+
5+
const app = new cdk.App();
6+
new AwsBatchOpenmpBenchmarkStack(app, 'AwsBatchOpenmpBenchmarkStack', {
7+
/* If you don't specify 'env', this stack will be environment-agnostic.
8+
* Account/Region-dependent features and context lookups will not work,
9+
* but a single synthesized template can be deployed anywhere. */
10+
11+
/* Uncomment the next line to specialize this stack for the AWS Account
12+
* and Region that are implied by the current CLI configuration. */
13+
// env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION },
14+
15+
/* Uncomment the next line if you know exactly what Account and Region you
16+
* want to deploy the stack to. */
17+
// env: { account: '123456789012', region: 'us-east-1' },
18+
19+
/* For more information, see https://docs.aws.amazon.com/cdk/latest/guide/environments.html */
20+
});
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
{
2+
"app": "npx ts-node --prefer-ts-exts bin/aws-batch-openmp-benchmark.ts",
3+
"watch": {
4+
"include": [
5+
"**"
6+
],
7+
"exclude": [
8+
"README.md",
9+
"cdk*.json",
10+
"**/*.d.ts",
11+
"**/*.js",
12+
"tsconfig.json",
13+
"package*.json",
14+
"yarn.lock",
15+
"node_modules",
16+
"test"
17+
]
18+
},
19+
"context": {
20+
"@aws-cdk/aws-lambda:recognizeLayerVersion": true,
21+
"@aws-cdk/core:checkSecretUsage": true,
22+
"@aws-cdk/core:target-partitions": [
23+
"aws",
24+
"aws-cn"
25+
],
26+
"@aws-cdk-containers/ecs-service-extensions:enableDefaultLogDriver": true,
27+
"@aws-cdk/aws-ec2:uniqueImdsv2TemplateName": true,
28+
"@aws-cdk/aws-ecs:arnFormatIncludesClusterName": true,
29+
"@aws-cdk/aws-iam:minimizePolicies": true,
30+
"@aws-cdk/core:validateSnapshotRemovalPolicy": true,
31+
"@aws-cdk/aws-codepipeline:crossAccountKeyAliasStackSafeResourceName": true,
32+
"@aws-cdk/aws-s3:createDefaultLoggingPolicy": true,
33+
"@aws-cdk/aws-sns-subscriptions:restrictSqsDescryption": true,
34+
"@aws-cdk/aws-apigateway:disableCloudWatchRole": true,
35+
"@aws-cdk/core:enablePartitionLiterals": true,
36+
"@aws-cdk/aws-events:eventsTargetQueueSameAccount": true,
37+
"@aws-cdk/aws-ecs:disableExplicitDeploymentControllerForCircuitBreaker": true,
38+
"@aws-cdk/aws-iam:importedRoleStackSafeDefaultPolicyName": true,
39+
"@aws-cdk/aws-s3:serverAccessLogsUseBucketPolicy": true,
40+
"@aws-cdk/aws-route53-patters:useCertificate": true,
41+
"@aws-cdk/customresources:installLatestAwsSdkDefault": false,
42+
"@aws-cdk/aws-rds:databaseProxyUniqueResourceName": true,
43+
"@aws-cdk/aws-codedeploy:removeAlarmsFromDeploymentGroup": true,
44+
"@aws-cdk/aws-apigateway:authorizerChangeDeploymentLogicalId": true,
45+
"@aws-cdk/aws-ec2:launchTemplateDefaultUserData": true,
46+
"@aws-cdk/aws-secretsmanager:useAttachedSecretResourcePolicyForSecretTargetAttachments": true,
47+
"@aws-cdk/aws-redshift:columnId": true,
48+
"@aws-cdk/aws-stepfunctions-tasks:enableEmrServicePolicyV2": true,
49+
"@aws-cdk/aws-ec2:restrictDefaultSecurityGroup": true,
50+
"@aws-cdk/aws-apigateway:requestValidatorUniqueId": true,
51+
"@aws-cdk/aws-kms:aliasNameRef": true,
52+
"@aws-cdk/aws-autoscaling:generateLaunchTemplateInsteadOfLaunchConfig": true,
53+
"@aws-cdk/core:includePrefixInUniqueNameGeneration": true,
54+
"@aws-cdk/aws-efs:denyAnonymousAccess": true,
55+
"@aws-cdk/aws-opensearchservice:enableOpensearchMultiAzWithStandby": true,
56+
"@aws-cdk/aws-lambda-nodejs:useLatestRuntimeVersion": true,
57+
"@aws-cdk/aws-efs:mountTargetOrderInsensitiveLogicalId": true,
58+
"@aws-cdk/aws-rds:auroraClusterChangeScopeOfInstanceParameterGroupWithEachParameters": true,
59+
"@aws-cdk/aws-appsync:useArnForSourceApiAssociationIdentifier": true,
60+
"@aws-cdk/aws-rds:preventRenderingDeprecatedCredentials": true,
61+
"@aws-cdk/aws-codepipeline-actions:useNewDefaultBranchForCodeCommitSource": true,
62+
"@aws-cdk/aws-cloudwatch-actions:changeLambdaPermissionLogicalIdForLambdaAction": true,
63+
"@aws-cdk/aws-codepipeline:crossAccountKeysDefaultValueToFalse": true,
64+
"@aws-cdk/aws-codepipeline:defaultPipelineTypeToV2": true,
65+
"@aws-cdk/aws-kms:reduceCrossAccountRegionPolicyScope": true,
66+
"@aws-cdk/aws-eks:nodegroupNameAttribute": true,
67+
"@aws-cdk/aws-ec2:ebsDefaultGp3Volume": true,
68+
"@aws-cdk/aws-ecs:removeDefaultDeploymentAlarm": true,
69+
"@aws-cdk/custom-resources:logApiResponseDataPropertyTrueDefault": false,
70+
"@aws-cdk/aws-s3:keepNotificationInImportedBucket": false,
71+
"@aws-cdk/aws-ecs:enableImdsBlockingDeprecatedFeature": false,
72+
"@aws-cdk/aws-ecs:disableEcsImdsBlocking": true,
73+
"@aws-cdk/aws-ecs:reduceEc2FargateCloudWatchPermissions": true,
74+
"@aws-cdk/aws-dynamodb:resourcePolicyPerReplica": true,
75+
"@aws-cdk/aws-ec2:ec2SumTImeoutEnabled": true,
76+
"@aws-cdk/aws-appsync:appSyncGraphQLAPIScopeLambdaPermission": true,
77+
"@aws-cdk/aws-rds:setCorrectValueForDatabaseInstanceReadReplicaInstanceResourceId": true,
78+
"@aws-cdk/core:cfnIncludeRejectComplexResourceUpdateCreatePolicyIntrinsics": true,
79+
"@aws-cdk/aws-lambda-nodejs:sdkV3ExcludeSmithyPackages": true,
80+
"@aws-cdk/aws-stepfunctions-tasks:fixRunEcsTaskPolicy": true,
81+
"@aws-cdk/aws-ec2:bastionHostUseAmazonLinux2023ByDefault": true,
82+
"@aws-cdk/aws-route53-targets:userPoolDomainNameMethodWithoutCustomResource": true,
83+
"@aws-cdk/aws-elasticloadbalancingV2:albDualstackWithoutPublicIpv4SecurityGroupRulesDefault": true,
84+
"@aws-cdk/aws-iam:oidcRejectUnauthorizedConnections": true,
85+
"@aws-cdk/core:enableAdditionalMetadataCollection": true,
86+
"@aws-cdk/aws-lambda:createNewPoliciesWithAddToRolePolicy": false,
87+
"@aws-cdk/aws-s3:setUniqueReplicationRoleName": true,
88+
"@aws-cdk/aws-events:requireEventBusPolicySid": true,
89+
"@aws-cdk/core:aspectPrioritiesMutating": true,
90+
"@aws-cdk/aws-dynamodb:retainTableReplica": true,
91+
"@aws-cdk/aws-stepfunctions:useDistributedMapResultWriterV2": true,
92+
"@aws-cdk/s3-notifications:addS3TrustKeyPolicyForSnsSubscriptions": true,
93+
"@aws-cdk/aws-ec2:requirePrivateSubnetsForEgressOnlyInternetGateway": true,
94+
"@aws-cdk/aws-s3:publicAccessBlockedByDefault": true,
95+
"@aws-cdk/aws-lambda:useCdkManagedLogGroup": true
96+
}
97+
}

0 commit comments

Comments
 (0)