Kubernetes Series Part 3 - Deploy a node application to a Kubernetes cluster

Kubernetes Series Part 3 - Deploy a node application to a Kubernetes cluster

🏗️ What we’ll build

In previous posts from this series, we created an express server that serves weather data from the open weather API. We then created a Dockerfile for that service that we can use to deploy to various cloud services.

This post will deploy that Dockerfile to a Kubernetes (k8s) cluster running on Digital Ocean, a popular cloud hosting provider.

❓ What is Kubernetes?

Straight from the docs:

Kubernetes, also known as K8s, is an open-source system for automating the deployment, scaling, and management of containerized applications.

It groups containers that make up an application into logical units for easy management and discovery. Kubernetes builds upon 15 years of experience of running production workloads at Google, combined with best-of-breed ideas and practices from the community.

✅ Prerequisites

🌊 Set up a Kubernetes cluster on Digital Ocean

  1. Log into your Digital Ocean account and choose Kubernetes from the side navigation.
  2. Click on Create Cluster
  3. Choose a fixed-size cluster with basic nodes. 3 nodes are fine for this exercise.
  4. Click Create Cluster again
  1. Follow the steps to authenticate with your cluster from your terminal. (Choose the automatic method)
doctl kubernetes cluster kubeconfig save <provided-cluster-key>
Notice: Adding cluster credentials to kubeconfig file found in "/Users/<username>/.kube/config"
Notice: Setting current-context to <cluster-name>
  1. Test the connection to your cluster by issuing a few kubectl commands
kubectl get nodes
NAME                     STATUS   ROLES    AGE   VERSION
node-weather-app-q1u1d   Ready    <none>   27m   v1.26.3
node-weather-app-q1u1i   Ready    <none>   27m   v1.26.3
node-weather-app-q1u1v   Ready    <none>   27m   v1.26.3
  1. Click I'm done. You now have a Kubernetes cluster running. Now we’re on our own 😄

🗒️ Create a Kubernetes deployment for your Express application.

In order to deploy our Express server to our Kubernetes cluster, we need to create a Deployment and a Service.

Create a new file called deployment.yml with the following contents:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: express-server
spec:
  replicas: 2
  selector:
    matchLabels:
      app: express-server
  template:
    metadata:
      labels:
        app: express-server
    spec:
      containers:
      - name: express-server
        image: your-dockerhub-username/<express-server-image-name>:latest
        ports:
        - containerPort: 3000
        env:
        - name: API_KEY
          valueFrom:
            secretKeyRef:
              name: api-key-secret
              key: api_key

---

apiVersion: v1
kind: Service
metadata:
  name: express-server
spec:
  selector:
    app: express-server
  ports:
    - protocol: TCP
      port: 80
      targetPort: 3000
  type: LoadBalancer

The deployment.yml file contains two Kubernetes resources:

  1. Deployment: This specifies the desired state for the Express server application, such as the number of replicas and the container image to use.
  2. Service: This resource creates a load balancer that listens on port 80 and forwards traffic to the application on port 3000.

To create the api-key-secret, run the following command:

kubectl create secret generic api-key-secret --from-literal=api_key=your-api-key-value

🚀 Deploy to your Kubernetes cluster

With the deployment.yml file in place, you can deploy your Express server to your Kubernetes cluster. First, ensure you have the correct context set with kubectl by running:

kubectl config use-context <your-kubernetes-context>

Then, deploy your application by running:

kubectl apply -f deployment.yml

🌍 Access your application on the internet

To make your Express server accessible on the internet, the Service resource you created earlier has exposed it via a load balancer. To get the external IP address of the load balancer, run the following command:

kubectl get service express-server

The output should look similar to the following:

NAME            TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)        AGE
express-server  LoadBalancer   10.47.248.217   203.0.113.42      80:32426/TCP   5m

In this example, the external IP address is 203.0.113.42. You can now access your Express server on the internet by navigating to http://203.0.113.42.

💡 Troubleshooting

If you built your images on an M1 Macbook, or a machine with ARM architecture, you may run into the issue of your pods crashing when you deploy them.

To avoid this issue, you will need to build your images on your MacBook with buildx.

Run the following commands to build you images with buildx:

docker buildx install

docker buildx create --name multiarch-builder

docker buildx use multiarch-builder

docker buildx build --platform linux/amd64,linux/arm64 --tag your-dockerhub-username/<express-server-image-name>:latest --push .

This will produce a multi-architecture build of your image that should now work on Linux Digital Ocean droplets.

That’s it!

In this blog post, we have walked through the process of deploying an Express.js server to a Kubernetes cluster and making it available on the internet. This process involved containerizing the application using Docker, creating Kubernetes deployment and service resources, deploying the application to a Kubernetes cluster, and accessing it via an external IP address.

By following these steps, you can leverage the power of Kubernetes to manage and scale your Express.js applications easily and efficiently.

In the next post, we’ll learn how to use a vault to have more control over our secrets.

Did you find this article valuable?

Support I Learned a Thing by becoming a sponsor. Any amount is appreciated!