Running NodeJS Microservices in Kubernetes using AWS EKS & Travis CI – Part 3

Intro

This is the third out of a series of articles where I’m presenting a sample NodeJS “microservices” project and deploying it to a Kubernetes cluster using Amazon Elastic Kubernetes Service (EKS).

I completed this project as part of the Cloud Developer Nanodegree at Udacity. You can find the source code on GitHub.

In Part 1 and Part 2, we went through the following topics:

  • Familiarize with the overall functionality and business rules
  • The System Architecture
  • PostgreSQL set up with Amazon RDS
  • S3 storage for images
  • Users registration and login process – hashing and generating JWT tokens
  • Dockerizing all the components
  • Run everything locally with Docker & docker-compose
  • Set up Continuous Integration using Travis CI

In this post, we’ll deploy everything to Kubernetes via Amazon EKS.

About the Nanodegree

The Nanodegree will train you in critical AWS skills to become an effective cloud developer.

Some of the covered topics are:

  • Cloud Computing in AWS
  • Storage & Content Delivery
  • Cloud Security
  • Networking & Elasticity
  • Deployments via AWS Elastic Beanstalk
  • Microservices Design Principles
  • Messaging & Containers, Docker
  • Containers orchestration with Kubernetes in AWS
  • Serverless apps, Lambda functions, Auth

Each of the main sections ends with a small project where you can interactively put your knowledge into action.

Also, you’ll get to complete a final Capstone project putting together most of the concepts you go through during the learning journey.

Don’t let the pricing discourage you – at the time I took the Nanodegree, every customer could use a discount coupon that reduces the cost by up to 90%!

Create IAM Roles for the EKS Cluster and Node Group

We first need to prepare some IAM roles for our EKS Cluster and Node Group.

Let’s start with the EKS cluster role.

From the IAM dashboard, create a new role. Enter a Role name and select the EKS “use case” as per the screenshots below:

Similarly, create a new role for the EC2 Node Group:

Make sure you add the following permissions policies for this role:

  • AmazonEKSWorkerNodePolicy
  • AmazonEC2ContainerRegistryReadOnly
  • AmazonEKS_CNI_Policy

Create an SSH Key Pair

This step is not mandatory but will allow you to securely SSH into your new EC2 instances.

From the EC2 dashboard, find the “Key Pairs” section and create a new key pair that we’ll apply for the EC2 Node Group we’ll build in a later section.

Now, it’s time to spin up our Kubernetes cluster.

Create the EKS Cluster

For this tutorial, I’ll be creating the k8s cluster via the AWS Management Console. Of course, you can do that via EKSCTL or AWS CLI if you prefer.

Go to the EKS dashboard and start creating a new cluster.

  • Enter cluster name
  • Use the Cluster role we created previously
  • Make sure to select Public for Cluster endpoint access

It might take 10-15 mins to create the cluster.

Once it’s ready, you should see something similar to this:

Create the EKS Node Group

Now you need to create an EC2 Node Group that will be handling the Kubernetes workload.

Go to your newly created cluster, navigate to the Compute tab, and hit the Add Node Group button:

Add the name of the Node Group and select the IAM role we created before.

Next, you’ll be prompted to select an instance type. Feel free to experiment until you find the cheapest option. Still, it’s doubtful anything below “t3.medium” will be able to handle the required workload properly – with “small” or “micro” instances, I ended up getting resources shortage errors.

Select two nodes as the minimum, maximum, and desired size of the node group.

Then, you can configure the ssh access to your EC2 instances by applying the key pair we’ve created in a previous step.

Review the configuration and hit Create.

Install and Set Up kubectl for the EKS Cluster

It’s time to install kubectl for your OS following this guide.

I assume that you’ve already set up the AWS CLI in Part 1, which we’ll use to set up kubectl.

kubectl needs to run in the context of some user. For this demo, I’ll use the root user with which I created the cluster. This is not the best option in terms of security practices, as ideally, you should have a dedicated user for EKS management.

Anyways, if you’re following along, you need to have AWSAccessKeyId and AWSSecretKey for your root user. If you haven’t saved these before, you can create a new access key through the IAM dashboard:

Now, you can set the following environment variables with your access key credentials (these will be used by AWS CLI when setting up kubectl):

export AWS_ACCESS_KEY_ID=<access_key_id>
export AWS_SECRET_ACCESS_KEY=<secret_access_key>

You can save these env variables permanently for future convenience.

Now you can execute the following command to have kubectl configured:

aws eks update-kubeconfig --region eu-central-1 --name EKSCluster

As a smoke test, you can run:

kubectl get nodes

You should see something similar to the output below:

Don’t bother that some of the screenshots display a region “us-east-2” while in most other cases, I use “eu-central-1”. That’s just because I had to so switch regions at some point and re-do most of the steps, but the reasoning is irrelevant to the demo. You just make to constantly select whatever region you’re working with.

Deployment

Now that we have all the necessary AWS resources and tooling setup, it’s time to create the required k8s artifacts (.yaml files) and proceed with the deployment.

Create Config Maps and Secrets

We’ll need a few ConfigMap and Secret files to store the configuration values. As you should’ve set the environment variables in the first article, you can get the concrete values from there. Some of these configs will contain sensitive data, so make sure you don’t commit them to a public GitHub repo.

The first config file you need is env-configmap:

Next is the env-secret.yaml file that stores the base64-encoded Postgres username and password:

To generate the base64 values, you can use the base64 Linux utility. Here’s an example:

If you’re on Windows, there are some online tools like this one.

Now let’s review the aws-secret.yaml file:

Here, we need to store the credentials for the udagram-api user we created in Part 1:

The credentials field contains the base64-encoded content of the ~/.aws/credentials file.

For example, my credentials file looks like so:

And you can execute this command to base64-encode its content.

cat ~/.aws/credentials | base64

Then just concatenate the separate lines of the output and put them in the credentials field of the aws-secret.yaml file.

Creating Deployments and Services

Next, we need a Deployment and Service resource file for each of our components.

You can check them out in the k8s directory of the repo.

Here’s a full list:

  • backend-feed-deployment.yaml
  • backend-feed-service.yaml
  • backend-user-deployment.yaml
  • backend-user-service.yaml
  • frontend-deployment.yaml
  • frontend-service.yaml
  • reverseproxy-deployment.yaml
  • reverseproxy-service.yaml

Make sure you use the docker images that “live” in your DockerHub repo. In the previous article, we ensured these images were published to DockerHub by implementing Continuous Integration via Travis CI.

For example, the feed service image in my Deployment file has the following reference to the docker image:

Deploy the Application

For convenience, there’s a deployment.sh file that will deploy all of the components listed in the previous section:

It’s time to run the deployment.sh script:

In my case, I already have the system deployed, that’s why you see most of the resources as “unchanged.”

Exposing the App Publicly

Now, our sample system is deployed to the k8s cluster.

We need to make it available through the public internet, which means exposing the following two components:

  • The front-end app so that we can load the UI resources in our browser.
  • The reverse proxy as it’s being directly called by the front-end to access the back-end services.

One option is to use port forwarding when kubectl would simply tunnel the traffic from a specified port at your localhost machine to the specified port on a concrete pod.

You can do that for testing purposes, but I’ll use a more proper approach.

Exposing External IPs

In order to expose External IPs for the required services, you can use the steps below.

First, check your deployments:

Remember, we need to expose the frontend and reverseproxy ones. To do so, run the following commands:

kubectl expose deployment frontend –-type==LoadBalancer –name=publicfrontend
kubectl expose deployment reverseproxy –-type==LoadBalancer –name=publicreverseproxy

Next, get the existing services to find the assigned public DNS values:

kubectl get services

Copy these values as you’ll need them in a moment.

Update the Host URL and Re-Deploy the Application

There are two places where the reverse proxy URL is hardcoded in the front-end app. These are the environment.ts file and the environment.prod.ts file.

Maybe a better approach would be to configure the reverse proxy URL via an environment variable so that you won’t need to re-build the project in case of a change. Feel free to do so as your own exercise.

You need to make sure the URL points to the exposed reverse proxy DNS for the publicreverseproxy service:

Now you have to re-build and deploy the front-end docker image. If you’re using Travis CI, this will automatically happen when you push the change to the repo. Otherwise, you can use the terminal to build and push the image to Docker Hub.

After that, you should also re-deploy the front end to k8s by just re-running the deployement.sh script.

If everything is successful, you should be able to access your app on its public URL:

Congratulations! We have our system up and running in an EKS Kubernetes cluster!

Summary

This is the last article from a series where we explored how to build, deploy and run a sample NodeJS system in Kubernetes using AWS EKS and Travis CI.

I hope you found this helpful!

See you next time!

Resources

  1. Part 1
  2. Part 2
  3. Udacity Nanodegree
  4. Source Code

Site Footer

Subscribe To My Newsletter

Email address