Skip to content

terotuomala/k8s-express-api-example

Repository files navigation

Kubernetes Express API example

Build and Release Vulnerability Scan Lint

ℹ️ This project is a part of GitOps workflow example using Flux2 which includes Kubernetes manifests for Redis and NGINX Ingress Controller as well as handles Continuous Delivery.

A simple example REST API Application using Node.js + Express.js + Redis running in Kubernetes.

Table of Contents

🔍 Overview

In a nutshell the application is used as a proxy for fetching most starred GitHub repositories.

A simplified usage flow of the data fetching and Redis cache usage:

flowchart

Endpoints

The application serves the following endpoints:

Method Path Description
GET / Returns 30 most starred GitHub repositories as JSON
GET /readyz Readiness status used by Kubernetes readiness probe
GET /livez Liveness status used by Kubernetes liveness probe

🚀 Features

  • Optimized Dockerfile using multi-stage builds
  • SHA256 digest pinned Docker images with automated update using Renovate
  • Automated vulnerability scan of the Docker image and npm dependencies using Trivy
  • YAML validation using yamllint
  • JavaScript validation using ESLint
  • Graceful shutdown and health checks (readiness and liveness) using Terminus
  • Structured JSON logging using Pino
  • Kubernetes configuration customization using Kustomize
  • Network traffic flow control using Network Policies

Dockerfile optimization

  • In order to keep the Docker image size optimal a multi-stage builds is used
  • The npm dependencies (without devDependencies) are installed in a build stage
  • Only the nessecary things (node_modules and the application code) are copied from the build state to release stage in order to have minimum amount of layers
  • Only the layers from the release stage are pushed when the Docker image is build

SHA256 digest pinned Docker images

SHA256 digest pinning is used to achieve reliable and reproducable builds. Using digest as the image's primary identifier instead of using a tag makes sure that specific version of the image is used.

Docker image and npm dependency updates

In order to receive Docker image and npm dependency updates Renovate is used to create a pull request when:

  • Newer digest from chainguard/node-lts is available on Docker Hub
  • Minor or Patch update of a npm dependency is available

Vulnerability scanning

In order to regularly scan Docker image and npm dependencies for vulnerabilities a scheduled job is used to build the Docker image and scan it's content using Trivy.

Graceful shutdown

In order to gracefully shutdown the node process it must:

To achieve this:

  • The Docker image CMD instructions uses exec form ["node", "src/index.js"] which does not invoke a command shell /bin/sh -c, node, src/index.js
  • Instead it just replaces the command shell with the command to be executed node src/index.js. This makes sure that the node process is spawned as PID 1.
  • Terminus is used to handle the SIGTERM and SIGINT Signals

Kustomize configuration

Kustomize configuration is based on Directory Structure Based Layout in order to be able to use multiple environments with different configuration.

├── base
│   ├── deployment.yaml
│   ├── hpa.yaml
│   ├── ingress.yaml
│   ├── kustomization.yaml
│   ├── netpol-egress.yaml
│   ├── netpol-ingress.yaml
│   ├── pdb.yaml
│   └── service.yaml
└── staging
    ├── hpa-patch.yaml
    ├── kustomization.yaml
    ├── namespace.yaml
    └── pdb-patch.yaml

⌨️ Local development

Start the redis container:

docker run -d --rm --name redis -p 6379:6379 redis:6-alpine

Start the nodemon tool which automatically restarts the node application when file changes in the directory are detected:

npm run dev

About

A simple REST API example using Node.js + Express.js + Redis for Kubernetes.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published