Skip to content

Commit 6af9643

Browse files
committed
added config for microservices
1 parent b6f2162 commit 6af9643

3 files changed

Lines changed: 98 additions & 18 deletions

File tree

Daily Journal.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -328,24 +328,28 @@ One of my integration test was causing some issues, the test passed for the gett
328328

329329
I'll use Localstack - an AWS simulator to avoid any and all charges. AWS simplies the process of starting and creating docker containers and allowing them to communicate with each other in a virtual private cloud, located in a private subnet that can only be accessed via an ALB - application load balancer. So the frontend client will make a request to that.
330330

331-
### 3rd May 2025 -
331+
### 3rd May 2026 -
332332

333333
Created account on localstack, they have a nice student plan that I can use. Localstack simulates AWS services via the use of Docker containers. Encountered issue with localstack container not being found but that was fixed by simply pulling the localstack image from docker. Now to instantiate the AWS instance. Now I'll write the infrastructure as code in Java.
334334

335335
Some dependencies are required to write IaC in Java.
336336

337-
### 7th May 2025 -
337+
### 7th May 2026 -
338338

339339
Added some packages to the infrastructure module. Stack is all the components that make up the infra. Running the JAVA file to generate the cloud formation template - sort of like generating a docker image from a dockerfile.
340340

341341
As we build the components of our infrastructure, the localstack.template.json will be not empty and built out. Implemented the createVpc function and called it in the constructor and ran it again and now the localstack.template.json is now not empty. cdk is useful for not having to create the template from scratch
342342

343-
### 8th May 2025 -
343+
### 8th May 2026 -
344344

345345
Create a health check method for the databases. The health check runs every 30 seconds and does a maximum of 3 tries. After running the LocalStack file again I see the updated health checks on the cloud formation template file.
346346

347347
Next step is to use the MSK service for Kafka broker, handling the low level maintenance. Now going to create the method to create this service
348348

349-
### 9th May 2025 -
349+
### 9th May 2026 -
350350

351-
The last step for the cloud formation template is to add the ECS cluster
351+
The last step for the cloud formation template is to add the ECS cluster
352+
353+
### 10th May 2026
354+
355+
Added the container options for the AWS ECS containers - exposing the necessary ports and setting up the logs.

infrastructure/src/main/java/com/pm/stack/LocalStack.java

Lines changed: 89 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.pm.stack;
22

3+
import java.util.HashMap;
34
import java.util.List;
45
import java.util.Map;
56
import java.util.stream.Collectors;
@@ -20,15 +21,24 @@
2021
import software.amazon.awscdk.services.ec2.InstanceSize;
2122
import software.amazon.awscdk.services.ec2.InstanceType;
2223
import software.amazon.awscdk.services.ec2.Vpc;
24+
import software.amazon.awscdk.services.ecs.AwsLogDriverProps;
2325
import software.amazon.awscdk.services.ecs.CloudMapNamespaceOptions;
2426
import software.amazon.awscdk.services.ecs.Cluster;
27+
import software.amazon.awscdk.services.ecs.ContainerDefinitionOptions;
28+
import software.amazon.awscdk.services.ecs.ContainerImage;
2529
import software.amazon.awscdk.services.ecs.FargateService;
30+
import software.amazon.awscdk.services.ecs.FargateTaskDefinition;
31+
import software.amazon.awscdk.services.ecs.LogDriver;
32+
import software.amazon.awscdk.services.ecs.PortMapping;
33+
import software.amazon.awscdk.services.ecs.Protocol;
2634
import software.amazon.awscdk.services.rds.Credentials;
2735
import software.amazon.awscdk.services.rds.DatabaseInstance;
2836
import software.amazon.awscdk.services.rds.DatabaseInstanceEngine;
2937
import software.amazon.awscdk.services.rds.PostgresEngineVersion;
3038
import software.amazon.awscdk.services.rds.PostgresInstanceEngineProps;
3139
import software.amazon.awscdk.services.route53.CfnHealthCheck;
40+
import software.amazon.awscdk.services.logs.LogGroup;
41+
import software.amazon.awscdk.services.logs.RetentionDays;
3242

3343
public class LocalStack extends Stack {
3444
private final Vpc vpc;
@@ -94,27 +104,93 @@ private CfnHealthCheck CfnHealthCheckForDb(DatabaseInstance databaseInstance, St
94104

95105
private CfnCluster CfnClusterKafka() {
96106
return CfnCluster.Builder.create(this, "MskCluster")
97-
.clusterName("kafka-cluster-for-patients")
98-
.kafkaVersion("2.8.0")
99-
.numberOfBrokerNodes(1) // connects vpn to broker node
100-
.brokerNodeGroupInfo(CfnCluster.BrokerNodeGroupInfoProperty.builder().instanceType("kafka.m5.xlarge") // specifying size of machine to run on - more compute power
101-
.clientSubnets(vpc.getPrivateSubnets().stream().map(ISubnet::getSubnetId).collect(Collectors.toList()))
102-
.brokerAzDistribution("DEFAULT").build()).build();
107+
.clusterName("kafka-cluster-for-patients")
108+
.kafkaVersion("2.8.0")
109+
.numberOfBrokerNodes(1) // connects vpn to broker node
110+
.brokerNodeGroupInfo(CfnCluster.BrokerNodeGroupInfoProperty.builder().instanceType("kafka.m5.xlarge") // specifying
111+
// size
112+
// of
113+
// machine
114+
// to
115+
// run
116+
// on
117+
// -
118+
// more
119+
// compute
120+
// power
121+
.clientSubnets(
122+
vpc.getPrivateSubnets().stream().map(ISubnet::getSubnetId).collect(Collectors.toList()))
123+
.brokerAzDistribution("DEFAULT").build())
124+
.build();
103125
}
104126

105-
// so to find a specific service add the name of the service (container name) and the name of the namespace
127+
// so to find a specific service add the name of the service (container name)
128+
// and the name of the namespace
106129
// eg. auth-service.patient-management.local
107130
private Cluster createEcsCluster() {
108-
// added the service discovery namespace to this cluster, makes it easy to find this service and read about it
109-
// does not run well on localstack since it runs on localhost but this works for an actual amazon aws system
110-
return Cluster.Builder.create(this, "patientManagementCluster").vpc(vpc).defaultCloudMapNamespace(CloudMapNamespaceOptions.builder().name("patient-management.local").build()).build();
131+
// added the service discovery namespace to this cluster, makes it easy to find
132+
// this service and read about it
133+
// does not run well on localstack since it runs on localhost but this works for
134+
// an actual amazon aws system
135+
return Cluster.Builder.create(this, "patientManagementCluster").vpc(vpc)
136+
.defaultCloudMapNamespace(CloudMapNamespaceOptions.builder().name("patient-management.local").build())
137+
.build();
111138
}
112139

113-
// create service using the FargateService launch type, makes it easy to start, stop, scale ecs tasks that run the containers
140+
// create service using the FargateService launch type, makes it easy to start,
141+
// stop, scale ecs tasks that run the containers
114142
// the last argument is a map of key value pairs
115-
// private FargateService creatFargateService(String id, String imageName, List<Integer> ports, DatabaseInstance dbName, Map<String, String> addEnvVars) {
143+
private FargateService creatFargateService(String id, String imageName, List<Integer> ports,
144+
DatabaseInstance dbName, Map<String, String> addEnvVars) {
145+
// specify the resources being used for a container
146+
FargateTaskDefinition taskDefinition = FargateTaskDefinition.Builder.create(this, id + "Task")
147+
.cpu(256) // 256 cpu units
148+
.memoryLimitMiB(512)
149+
.build();
116150

117-
// }
151+
// adding the image name to run the container
152+
ContainerDefinitionOptions containerOptions = ContainerDefinitionOptions.builder()
153+
.image(ContainerImage.fromRegistry(imageName))
154+
.portMappings(ports.stream().map( // port mapping to expose the ports of the container
155+
port -> PortMapping.builder().containerPort(port).hostPort(port).protocol(Protocol.TCP).build())
156+
.toList())
157+
.logging(LogDriver.awsLogs(AwsLogDriverProps.builder()
158+
.logGroup(LogGroup.Builder.create(this, id + "LogGroup")
159+
.logGroupName("/ecs/" + imageName)
160+
.removalPolicy(RemovalPolicy.DESTROY)
161+
.retention(RetentionDays.ONE_DAY) // keeping logs can be expensive, reduce it
162+
.build())
163+
.build()))
164+
.build();
165+
166+
Map<String, String> envVars = new HashMap<>();
167+
// local addresses where aws can set the kafka servers on - patient service and
168+
// analytics service can use these
169+
envVars.put("SPRING_KAFKA_BOOTSTRAP_SERVERS",
170+
"localhost.localstack.cloud:4511, localhost.localstack.cloud:4512");
171+
172+
if (addEnvVars != null) {
173+
envVars.putAll(addEnvVars);
174+
}
175+
176+
if (dbName != null) {
177+
// the way this works jdbc:postgresql://%s:%s/%s-db => each %s is replaced with
178+
// endpoint address, port, and image name
179+
envVars.put("SPRING_DATASOURCE_URL", "jdbc:postgresql://%s:%s/%s-db"
180+
.formatted(dbName.getDbInstanceEndpointAddress(), dbName.getDbInstanceEndpointPort(), imageName));
181+
182+
envVars.put("SPRING_DATASOURCE_USERNAME", "admin");
183+
// secret manager creates a password for you behind the scenes, all you have to
184+
// do is to grab it
185+
envVars.put("SPRING_DATASOURCE_PASSWORD", dbName.getSecret().secretValueFromJson("password").toString());
186+
// same list of patients to use for testing, for production this should be
187+
// changed
188+
envVars.put("SPRING_JPA_HIBERNATE_DDL_AUTO", "update");
189+
envVars.put("SPRING_SQL_INIT_MODE", "always");
190+
envVars.put("SPRING_DATASOURCE_HIKARI_INITIALIZATION_FAIL_TIMEOUT", "60000");
191+
}
192+
193+
}
118194

119195
public static void main(final String[] args) {
120196
// creating a new cdk app and defining where the output should be
667 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)