Skip to content

Commit 781c18e

Browse files
author
Yuriy Bezsonov
committed
refactor(infra): replace API Gateway with Lambda Function URL for thread analysis
1 parent 8b0f896 commit 781c18e

File tree

13 files changed

+328
-486
lines changed

13 files changed

+328
-486
lines changed

apps/jvm-ai-analyzer/.gitignore

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,3 @@ release.properties
2727
# Test output
2828
*.exec
2929
test-output/
30-
31-
# Kubernetes manifests (generated during workshop)
32-
k8s/

apps/unicorn-store-spring-java25/.gitignore

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,3 @@ release.properties
2727
# Test output
2828
*.exec
2929
test-output/
30-
31-
# Kubernetes manifests (generated during workshop)
32-
k8s/

apps/unicorn-store-spring-java25/src/main/java/com/unicorn/store/service/ThreadGeneratorService.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,13 @@ public synchronized void startThreads(int threadCount) {
2424
logger.info("Starting {} threads", threadCount);
2525

2626
for (int i = 0; i < threadCount; i++) {
27-
var thread = Thread.ofVirtual()
27+
var thread = Thread.ofPlatform()
2828
.name("DummyThread-" + i)
2929
.start(new DummyWorkload(running));
3030
activeThreads.add(thread);
3131
}
3232

33-
logger.info("Started {} virtual threads", threadCount);
33+
logger.info("Started {} platform threads", threadCount);
3434
}
3535

3636
public synchronized void stopThreads() {

infra/cdk/src/main/java/sample/com/constructs/ThreadAnalysis.java

Lines changed: 20 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import software.amazon.awscdk.Duration;
44
import software.amazon.awscdk.RemovalPolicy;
5-
import software.amazon.awscdk.services.apigateway.*;
65
import software.amazon.awscdk.services.ec2.*;
76
import software.amazon.awscdk.services.eks.v2.alpha.AccessEntry;
87
import software.amazon.awscdk.services.eks.v2.alpha.AccessEntryType;
@@ -14,6 +13,9 @@
1413
import software.amazon.awscdk.services.iam.*;
1514
import software.amazon.awscdk.services.lambda.Code;
1615
import software.amazon.awscdk.services.lambda.Function;
16+
import software.amazon.awscdk.services.lambda.FunctionUrl;
17+
import software.amazon.awscdk.services.lambda.FunctionUrlAuthType;
18+
import software.amazon.awscdk.services.lambda.FunctionUrlOptions;
1719
import software.amazon.awscdk.services.lambda.Runtime;
1820
import software.amazon.awscdk.services.logs.LogGroup;
1921
import software.amazon.awscdk.services.logs.RetentionDays;
@@ -28,13 +30,14 @@
2830

2931
/**
3032
* ThreadAnalysis construct for thread dump analysis.
31-
* Creates Lambda function and API Gateway for thread dump collection and AI analysis.
33+
* Creates Lambda function with Function URL for thread dump collection and AI analysis.
34+
* Uses async self-invocation pattern for fast webhook response.
3235
*/
3336
public class ThreadAnalysis extends Construct {
3437

3538
private final SecurityGroup lambdaSecurityGroup;
3639
private final Function threadDumpLambda;
37-
private final RestApi threadDumpApi;
40+
private final FunctionUrl functionUrl;
3841
private final Role lambdaRole;
3942

4043
public static class ThreadAnalysisProps {
@@ -130,21 +133,14 @@ public ThreadAnalysis(final Construct scope, final String id, final ThreadAnalys
130133
props.getWorkshopBucket().grantReadWrite(lambdaRole);
131134
}
132135

133-
// Create Lambda security group
136+
// Create Lambda security group for EKS and ECS access
134137
this.lambdaSecurityGroup = SecurityGroup.Builder.create(this, "SecurityGroup")
135138
.vpc(props.getVpc())
136139
.securityGroupName(prefix + "-thread-dump-lambda-sg")
137140
.description("Security group for Thread Dump Lambda function")
138141
.allowAllOutbound(true)
139142
.build();
140143

141-
// Allow inbound from VPC for HTTPS
142-
lambdaSecurityGroup.addIngressRule(
143-
Peer.ipv4(props.getVpc().getVpcCidrBlock()),
144-
Port.tcp(443),
145-
"Allow VPC traffic to Lambda"
146-
);
147-
148144
// Create CloudWatch Log Group
149145
LogGroup.Builder.create(this, "LogGroup")
150146
.logGroupName("/aws/lambda/" + prefix + "-thread-dump-lambda")
@@ -173,56 +169,22 @@ public ThreadAnalysis(final Construct scope, final String id, final ThreadAnalys
173169
"S3_BUCKET_NAME", bucketName,
174170
"EKS_CLUSTER_NAME", eksClusterName,
175171
"S3_THREAD_DUMPS_PREFIX", "thread-dumps/",
176-
"APP_LABEL", "unicorn-store-spring",
177-
"KUBERNETES_AUTH_TYPE", "aws",
178-
"K8S_NAMESPACE", "unicorn-store-spring",
179172
"SECRET_NAME", prefix + "-ide-password"
180173
))
181174
.build();
182175

183-
// Create VPC Endpoint for API Gateway
184-
InterfaceVpcEndpoint apiGatewayEndpoint = InterfaceVpcEndpoint.Builder.create(this, "ApiGatewayVpcEndpoint")
185-
.vpc(props.getVpc())
186-
.service(InterfaceVpcEndpointAwsService.APIGATEWAY)
187-
.subnets(SubnetSelection.builder()
188-
.subnetType(SubnetType.PRIVATE_WITH_EGRESS)
189-
.build())
190-
.securityGroups(List.of(lambdaSecurityGroup))
191-
.privateDnsEnabled(true)
192-
.build();
193-
194-
// Create Private REST API Gateway
195-
this.threadDumpApi = RestApi.Builder.create(this, "Api")
196-
.restApiName(prefix + "-thread-dump-api")
197-
.endpointConfiguration(EndpointConfiguration.builder()
198-
.types(List.of(EndpointType.PRIVATE))
199-
.vpcEndpoints(List.of(apiGatewayEndpoint))
200-
.build())
201-
.policy(PolicyDocument.Builder.create()
202-
.statements(List.of(
203-
PolicyStatement.Builder.create()
204-
.effect(Effect.ALLOW)
205-
.principals(List.of(new AnyPrincipal()))
206-
.actions(List.of("execute-api:Invoke"))
207-
.resources(List.of("*"))
208-
.conditions(Map.of(
209-
"StringEquals", Map.of(
210-
"aws:SourceVpce", apiGatewayEndpoint.getVpcEndpointId()
211-
)
212-
))
213-
.build()
214-
))
215-
.build())
216-
.build();
217-
218-
// Remove auto-generated endpoint output
219-
threadDumpApi.getNode().tryRemoveChild("Endpoint");
220-
221-
// Add POST method to root
222-
LambdaIntegration lambdaIntegration = LambdaIntegration.Builder.create(threadDumpLambda)
223-
.build();
176+
// Add permission for Lambda to invoke itself (async pattern)
177+
threadDumpLambda.addToRolePolicy(PolicyStatement.Builder.create()
178+
.effect(Effect.ALLOW)
179+
.actions(List.of("lambda:InvokeFunction"))
180+
.resources(List.of(threadDumpLambda.getFunctionArn()))
181+
.build());
224182

225-
threadDumpApi.getRoot().addMethod("POST", lambdaIntegration);
183+
// Create Function URL (replaces API Gateway + VPC Endpoint)
184+
// Auth is handled by Lambda code via basic auth against Secrets Manager
185+
this.functionUrl = threadDumpLambda.addFunctionUrl(FunctionUrlOptions.builder()
186+
.authType(FunctionUrlAuthType.NONE)
187+
.build());
226188

227189
// Create EKS Access Entry for Lambda role (if EKS cluster provided)
228190
if (props.getEksCluster() != null) {
@@ -292,8 +254,8 @@ public Function getThreadDumpLambda() {
292254
return threadDumpLambda;
293255
}
294256

295-
public RestApi getThreadDumpApi() {
296-
return threadDumpApi;
257+
public FunctionUrl getFunctionUrl() {
258+
return functionUrl;
297259
}
298260

299261
public Role getLambdaRole() {

infra/cfn/base-stack.yaml

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,29 @@ Resources:
676676
Fn::GetAtt:
677677
- IdeInstanceLauncherFunction803C5A2A
678678
- Arn
679+
InstanceTypes: m6a.xlarge,m7a.xlarge
680+
InstanceName: ide
681+
IamInstanceProfileArn:
682+
Fn::GetAtt:
683+
- IdeInstanceProfile61B92038
684+
- Arn
685+
VolumeSize: "50"
686+
SubnetIds:
687+
Fn::Join:
688+
- ""
689+
- - Ref: VpcPublicSubnet1Subnet8E8DEDC0
690+
- ","
691+
- Ref: VpcPublicSubnet2SubnetA811849C
692+
SecurityGroupIds:
693+
Fn::Join:
694+
- ""
695+
- - Fn::GetAtt:
696+
- IdeSecurityGroup73B02454
697+
- GroupId
698+
- ","
699+
- Fn::GetAtt:
700+
- IdeInternalSecurityGroupB0A5D76B
701+
- GroupId
679702
ImageId:
680703
Ref: SsmParameterValueawsserviceamiamazonlinuxlatestal2023amikernel61x8664C96584B6F00A464EAD1953AFF4B05118Parameter
681704
UserData:
@@ -814,29 +837,6 @@ Resources:
814837
"
815838
exit 1
816839
fi
817-
InstanceTypes: m6a.xlarge,m7a.xlarge
818-
InstanceName: ide
819-
IamInstanceProfileArn:
820-
Fn::GetAtt:
821-
- IdeInstanceProfile61B92038
822-
- Arn
823-
VolumeSize: "50"
824-
SubnetIds:
825-
Fn::Join:
826-
- ""
827-
- - Ref: VpcPublicSubnet1Subnet8E8DEDC0
828-
- ","
829-
- Ref: VpcPublicSubnet2SubnetA811849C
830-
SecurityGroupIds:
831-
Fn::Join:
832-
- ""
833-
- - Fn::GetAtt:
834-
- IdeSecurityGroup73B02454
835-
- GroupId
836-
- ","
837-
- Fn::GetAtt:
838-
- IdeInternalSecurityGroupB0A5D76B
839-
- GroupId
840840
UpdateReplacePolicy: Delete
841841
DeletionPolicy: Delete
842842
IdeEipAssociationDFF81215:

infra/cfn/java-ai-agents-stack.yaml

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -760,25 +760,6 @@ Resources:
760760
Fn::GetAtt:
761761
- IdeInstanceLauncherFunction803C5A2A
762762
- Arn
763-
VolumeSize: "50"
764-
SubnetIds:
765-
Fn::Join:
766-
- ""
767-
- - Ref: VpcPublicSubnet1Subnet8E8DEDC0
768-
- ","
769-
- Ref: VpcPublicSubnet2SubnetA811849C
770-
SecurityGroupIds:
771-
Fn::Join:
772-
- ""
773-
- - Fn::GetAtt:
774-
- IdeSecurityGroup73B02454
775-
- GroupId
776-
- ","
777-
- Fn::GetAtt:
778-
- IdeInternalSecurityGroupB0A5D76B
779-
- GroupId
780-
ImageId:
781-
Ref: SsmParameterValueawsserviceamiamazonlinuxlatestal2023amikernel61x8664C96584B6F00A464EAD1953AFF4B05118Parameter
782763
UserData:
783764
Fn::Base64:
784765
Fn::Join:
@@ -921,6 +902,25 @@ Resources:
921902
Fn::GetAtt:
922903
- IdeInstanceProfile61B92038
923904
- Arn
905+
VolumeSize: "50"
906+
SubnetIds:
907+
Fn::Join:
908+
- ""
909+
- - Ref: VpcPublicSubnet1Subnet8E8DEDC0
910+
- ","
911+
- Ref: VpcPublicSubnet2SubnetA811849C
912+
SecurityGroupIds:
913+
Fn::Join:
914+
- ""
915+
- - Fn::GetAtt:
916+
- IdeSecurityGroup73B02454
917+
- GroupId
918+
- ","
919+
- Fn::GetAtt:
920+
- IdeInternalSecurityGroupB0A5D76B
921+
- GroupId
922+
ImageId:
923+
Ref: SsmParameterValueawsserviceamiamazonlinuxlatestal2023amikernel61x8664C96584B6F00A464EAD1953AFF4B05118Parameter
924924
UpdateReplacePolicy: Delete
925925
DeletionPolicy: Delete
926926
IdeEipAssociationDFF81215:

0 commit comments

Comments
 (0)