Running a Node.JS API on Kubernetes local with K3D
Tags: node, kubernetes, docker, k3d
Published: 2023-02-26 12:49:51

How to "play" with [Kubernetes](https://kubernetes.io) on your own machine? One way to achieve this could be [K3D](https://k3d.io/v5.4.7)!

This tutorial will show how to run an application on a local Kubernetes inside a Ubuntu machine running on [WSL2](https://learn.microsoft.com/en-us/windows/wsl/install)!

## Prerequisites

First, we need to install:
- [Node.js](https://nodejs.org/en/)
- [Docker](https://www.docker.com/)
- [K3D](https://k3d.io/v5.4.7)
- [kubectl](https://kubernetes.io/docs/tasks/tools/#kubectl)
- [Visual Studio Code](https://code.visualstudio.com/) (or another code editor)

Also, you need to have an account in [Docker Hub](https://hub.docker.com/).

## Creating Node.js API

The first step is to create our API. Let's create a folder and initialize a Node.js project:

![Node initialization](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gy0x1fhrrmn469zz1osn.png)

The next step is to install [express](https://www.npmjs.com/package/express) with the command below:

```
npm i express
```

Now open the Visual Studio Code, or another code editor, and create a folder called `src` and inside a file called `index.js` as in the picture below:

![Application structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e2cf8azcf681353dkxm2.png)

Let's write some code to create an API that responds with `Hello World` in the path `http://localhost:8087/api/v1/test`:

```
const express = require('express')
const app = express()

app.get('/api/v1/test', (req, res) => {
    res.send('Hello World')
})

app.listen(8087, () => console.log('Server started on port 8087'))
```

Now, let's change the `package.json` file to remove the `test` instruction created by default and add our instruction to execute the application:

![package.json file](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/19h3jamisgis0td6so96.png)

In the command line just type `npm start` and you can open your browser and access the application with the URL `http://localhost:8087/api/v1/test`.

![Application running](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1gz4jrji0x0sq7z1oiqr.png)

## Docker image

In order to execute our application in Kubernetes, we should create an image of our application. In this tutorial, we will create a Docker image.

The first step is to create in the root of the project a file called `Dockerfile` and add this content below:

```
FROM node:18-alpine

WORKDIR /app

COPY package*json ./

RUN npm i

COPY ./src ./src

CMD ["npm", "start"]
```

Now we should use the `build` command to generate the image:

```
docker build -t rodrigoluisfaria/new-api:1.0.0 .
```

In the command above you should replace `rodrigoluisfaria` with your username in Docker Hub.

If the command executes successfully, you can check the image generated using the command `docker images`:

![docker images command](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d43jz0cdvzilodm5gbjp.png)

In order to test the image generated, we can run the command below to execute the container:

```
docker run -it --rm -p 8087:8087 rodrigoluisfaria/new-api:1.0.0
```

After the container start, you can open the browser and test if you can access the application:

![running application on Docker](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/37h67o0dl2ufqqgeoj4x.png)

The last step is to put this image in our Docker Hub repository.
For this you need to log in to the docker hub using the following command:

```
docker login
```

On the page Docker Hub create a new repository called `new-api` and execute the command below:

```
docker push rodrigoluisfaria/new-api:1.0.0
```

Remember to replace `rodrigoluisfaria` with your username in Docker Hub.

## Cluster Kubernetes - K3D

Now let's create our cluster using K3D!
For this you just need to execute the command:

```
k3d cluster create -p "8087:80@loadbalancer" my-cluster
```

In this command, you start a cluster and expose port `8087` of it.

![Creating cluster Kubernetes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xb2kf7wvs30h5d907txa.png)

In order to test your cluster you could run some commands:

```
kubectl cluster-info
kubectl get nodes
kubectl get pods --all-namespaces
```

![Cluster info](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mms8qefu15gzefce2cdk.png)

## Kubernetes

Now let's create a folder called `k8s` and three files inside:
- deployment.yaml - [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/)
- service.yaml - [Service](https://kubernetes.io/docs/concepts/services-networking/service/)
- ingress.yaml - [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/)

In the `deployment.yaml` file put the content:

```
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app-deployment
  labels:
    app: my-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-app
          image: rodrigoluisfaria/new-api:1.0.0
          ports:
            - containerPort: 8087
```

In the `service.yaml` file put the content:

```
apiVersion: v1
kind: Service
metadata:
  name: my-app-service
spec:
  selector:
    app: my-app
  ports:
  - port: 8087
    targetPort: 8087
```

In the `ingress.yaml` file put the content:

```
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app-ingress
spec:
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-app-service
            port:
              number: 8087
```

Now let's run a kubectl commands to create those resources:

```
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
kubectl apply -f ingress.yaml
```

To verify the resources you could execute the commands below:

```
kubectl get deployments
kubectl get services
kubectl get ingress
```

The result is something like this:

![kubectl commands](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4ubj42ligixxzdq1qv52.png)

The last step is to test! Open the browser and check if your application is running:

![Application](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sy83sbf0w8lqkee270n9.png)

I hope this tutorial was helpful, and if you have any comments or questions you could comment here or in my e-mail rodrigolfsi@gmail.com.