Deploying JHipster Microservices on AWS EKS (Elastic Container Service for Kubernetes )

Barry Vredevoort
8 min readMay 15, 2019

--

This is my first blog on medium, as a software entrepreneur and enthusiastic developer, I love JHIPSTER. So obviously I’m writing the blog about JHIPSTER. This blog is largely based on the blog of Deepu k Sasidharan the JHIPSTER co-lead.

Creating the microservice application

In a post of one of my fellow JHIPSTER enthusiasts, they showcased how to create a full stack microservice architecture using JHipster and JDL, read the post here if you want to learn more details about it. For this exercise, we will use the same application.

Let us recap the steps required.

Create a JDL file, let’s say app.jdl, and copy the below content into it.

Now create a directory called ecommerce and navigate into it. Run the JHipster import-jdl command. It could take a few minutes, especially the NPM install step.

$ mkdir ecommerce && cd ecommerce
$ jhipster import-jdl app.jdl

Once the JHipster process is complete, you will see that we have our store gateway, invoice service and notification service created and ready for us. The process until this is explained in more detail in my previous post here and you can deploy the application locally using Docker as explained in that post. If you haven’t done that before I strongly suggest that step so that you get an idea of the application and you also can make sure it works locally on your machine.

Generating the Kubernetes configuration

Now that our application is ready, let us create the required configurations for Kubernetes using JHipster.

In the ecommerce folder, we created earlier, create a new directory, let’s call in k8s so that we get the below structure.

├── app.jdl
├── invoice
├── k8s
├── notification
└── store

Create the k8s directory and navigate to it. Now run the JHipster Kubernetes command there.

$ mkdir k8s && cd k8s
$ jhipster kubernetes

The generator will ask you a few questions and choose the answers as highlighted below, as you can see the questions are very similar to the ones asked by jhipster docker-compose command. For the “base Docker repository name” provide your own docker hub account id(For example, my Docker Hub id is vrecon). For real-world use cases, you could also use a private image repository like the Amazon Elastic Container Registry or Azure Container Registry or and in that case, you would have to provide the AECR or ACR login server name here. For now, let us keep it simple.

⎈ Welcome to the JHipster Kubernetes Generator ⎈
Files will be generated in folder: /home/vrecon/workspace/temp/ecommerce/k8s
✔ Docker is installed
? Which *type* of application would you like to deploy? Microservice application? Enter the root directory where your gateway(s) and microservices are located ../3 applications found at /home/deepu/workspace/temp/ecommerce/
? Which applications do you want to include in your configuration? invoice, notification, store
? Do you want to setup monitoring for your applications ? No? Which applications do you want to use with clustered databases (only available with MongoDB and Couchbase)?JHipster registry detected as the service discovery and configuration provider used by your apps? Enter the admin password used to secure the JHipster Registry admin? What should we use for the Kubernetes namespace? default? What should we use for the base Docker repository name? <your Docker hub account id>? What command should we use for push Docker image to repository? docker push? Do you want to configure Istio? Not required? Choose the kubernetes service type for your edge services LoadBalancer - Let a kubernetes cloud provider automatically assign an IP

The generator will go to work with this and will create the following files and output.

create invoice/invoice-deployment.yml
create invoice/invoice-service.yml
create invoice/invoice-mysql.yml
create notification/notification-deployment.yml
create notification/notification-service.yml
create notification/notification-mongodb.yml
create store/store-deployment.yml
create store/store-service.yml
create store/store-mysql.yml
create README.md
create registry/jhipster-registry.yml
create registry/application-configmap.yml
create kubectl-apply.sh
WARNING! Kubernetes configuration generated with missing images!To generate the missing Docker image(s), please run:./gradlew -Pprod bootWar buildDocker in /home/vrecon/workspace/temp/ecommerce/invoice./gradlew -Pprod bootWar buildDocker in /home/vrecon/workspace/temp/ecommerce/notification./gradlew -Pprod bootWar buildDocker in /home/vrecon/workspace/temp/ecommerce/storeWARNING! You will need to push your image to a registry. If you have not done so, use the following commands to tag and push the images:docker image tag invoice vrecon/invoice
docker push vrecon/invoice
docker image tag notification vrecon/notification
docker push vrecon/notification
docker image tag store vrecon/store
docker push vrecon/store
You can deploy all your apps by running the following script:
./kubectl-apply.sh
Use these commands to find your application's IP addresses:
kubectl get svc store
Congratulations, JHipster execution is complete!

As you can see the generator creates all the required Kubernetes configuration files and prints out useful information to proceed further (Note that the docker hub id you provided will be in the instructions in place of vrecon here). Go through the generated k8s files and familiarize yourself.

Let us build and push the docker images for our application. Follow the instructions above and build docker images in each of the application folders and then tag and push the images to your Docker hub account.

Preparing the AWS Cluster

Now that our applications are built and pushed its time for us to deploy them to AWS EKS. But before that let’s make sure we have all the prerequisites ready. You will need the below tools.

  1. kubectl: The command line tool to interact with Kubernetes. Install and configure it.
  2. AWS cli: Install the Latest AWS Command Line Interface
  3. eksctl: a CLI for Amazon EKS. Install and read this tutorial on how to get started.

Configure Your AWS CLI Credentials

Both eksctl and the AWS CLI require that you have AWS credentials configured in your environment. The aws configure command is the fastest way to set up your AWS CLI installation for general use.

$ aws configure
AWS Access Key ID [None]: AKIAIOSFODNN7EXAMPLE
AWS Secret Access Key [None]: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Default region name [None]: us-west-2
Default output format [None]: json

Once the tools are ready let us prepare our Kubernetes cluster.

First, let us create the cluster. Run the below command. This will create a cluster named eCommerceCluster in US west location(You can use other AWS Regions as well).

eksctl create cluster --name eCommerceCluster

This would take several minutes to complete, and with several I mean a lot of minutes.

The output will look something like this:

[ℹ]  using region us-west-2
[ℹ] setting availability zones to [us-west-2b us-west-2c us-west-2d]
[ℹ] subnets for us-west-2b - public:192.168.0.0/19 private:192.168.96.0/19
[ℹ] subnets for us-west-2c - public:192.168.32.0/19 private:192.168.128.0/19
[ℹ] subnets for us-west-2d - public:192.168.64.0/19 private:192.168.160.0/19
[ℹ] nodegroup "standard-workers" will use "ami-0923e4b35a30a5f53" [AmazonLinux2/1.12]
[ℹ] creating EKS cluster "ecommercecluster" in "us-west-2" region
[ℹ] will create 2 separate CloudFormation stacks for cluster itself and the initial nodegroup
[ℹ] if you encounter any issues, check CloudFormation console or try 'eksctl utils describe-stacks --region=us-west-2 --name=ecommercecluster'
[ℹ] building cluster stack "eksctl-ecommercecluster-cluster"
[ℹ] creating nodegroup stack "eksctl-ecommercecluster-nodegroup-standard-workers"
[✔] all EKS cluster resource for "ecommercecluster" had been created
[✔] saved kubeconfig as "/Users/ericn/.kube/config"
[ℹ] adding role "arn:aws:iam::111122223333:role/eksctl-prod-nodegroup-standard-wo-NodeInstanceRole-IJP4S12W3020" to auth ConfigMap
[ℹ] nodegroup "standard-workers" has 0 node(s)
[ℹ] waiting for at least 1 node(s) to become ready in "standard-workers"
[ℹ] nodegroup "standard-workers" has 2 node(s)
[ℹ] node "ip-192-168-22-17.us-west-2.compute.internal" is not ready
[ℹ] node "ip-192-168-32-184.us-west-2.compute.internal" is ready
[ℹ] kubectl command should work with "/Users/ericn/.kube/config", try 'kubectl get nodes'
[✔] EKS cluster "ecommercecluster" in "us-west-2" region is ready

Verify that we are able to connect to the cluster by running kubectl get nodes

NAME                                        STATUS ROLES AGE VERSION
ip-192–168–28–143.us-west-2.compute.internal Ready <none> 18h v1.12.7
ip-192–168–72–37.us-west-2.compute.internal Ready <none> 18h v1.12.7

Deploying the application to AWS EKS

Now that our cluster is ready, let us deploy our microservice stack to this cluster.

We can deploy our application using the kubectl apply command for this we have to navigate to the k8s folder we created earlier and run the below commands in the same order

$ kubectl apply -f registry$ kubectl apply -f invoice$ kubectl apply -f notification$ kubectl apply -f store

Or you could also just run the handy kubectl-apply.sh script generated which runs the above.

So we are deploying the JHipster Registry first as it is required for other services, followed by the microservices and finally our gateway(store).

If you get a timeout during any of these, as I did, just try the command again.

Though the services get created fast, the actual applications might not be up and running yet, give the entire thing a minute or two to start.

Now run kubectl get pods to see the status of our containers.

$ kubectl get pods -wNAME                                    READY  STATUS 
invoice-5ffb46d944-h8x42 1/1 Running
invoice-mysql-66bc4b7874-p7ghk 1/1 Running
jhipster-registry-0 1/1 Running
jhipster-registry-1 1/1 Running
notification-76847b7667-d7xjb 1/1 Running
notification-mongodb-6db986b556-8bw8z 1/1 Running
store-8dc5cd6f7-s2dpx 1/1 Running
store-mysql-779d66685d-tmkqd 1/1 Running

Wait until all the containers are in Running status. Once the containers are running we can run the kubectl get service command to get the external IP for the application.

$ kubectl get service storeNAME   TYPE         CLUSTER-IP    EXTERNAL-IP    PORT(S)         AGE
store LoadBalancer 10.100.20.215 a317424b3765211e9831306d9c07d674-1390706390.us-west-2.elb.amazonaws.com 8080:32307/TCP 18h

In this case, the external IP for our gateway application is a317424b3765211e9831306d9c07d674–1390706390.us-west-2.elb.amazonaws.com running on port 8080. Opening this in the browser will give you the following result.

The JHipster registry is deployed as a headless service by default. If we need to access the registry we need to create a secondary service with a Load Balancer. Run the below command to expose the second service.

$ kubectl expose service jhipster-registry --type=LoadBalancer --name=exposed-registry

Now run the kubectl get service command to get the IP.

$ kubectl get service exposed-registryNAME             TYPE         CLUSTER-IP   EXTERNAL-IP    PORT(S)
exposed-registry LoadBalancer 10.100.194.130 af86bcd7c765211e9831306d9c07d674-372126431.us-west-2.elb.amazonaws.com 8761:31185/TCP 18h

Visit the URL in a browser to see the registry in action

Conclusion

Kubernetes is definitely the best way to deploy microservice applications to production but creating and managing Kubernetes clusters itself is not an easy task, but Kubernetes services like EKSCTL make it a bit easier.

JHipster provides a great Kubernetes setup to start with which you can further tweak as per your needs and platform. Using AWS EKS is working great and scaling up and down instances' can be done quite easily.

--

--