Skip to content

Repository files navigation

3-Microservices-Deployment

Overview

This repository demonstrates a complete Kubernetes deployment of a 3-microservice application backed by PostgreSQL. The solution includes:

  • nodeservice: Node.js/Express frontend that serves a simple UI and acts as an API gateway.
  • pythonservice: Flask-based writer service that inserts items into PostgreSQL.
  • springservice: Spring Boot reader service that reads items from PostgreSQL.
  • postgres: Kubernetes StatefulSet backing the data store.

It also includes cluster bootstrap automation for worker nodes and Kubernetes resource manifests for service deployment, networking, secrets, and persistence.

Architecture

          +-------------------+
          | nginx ingress     |
          | controller        |
          +---------+---------+
                    |
                    v
             +--------------+
             | nodeservice  |
             | (frontend)   |
             +------+-------+
                    |
                    v
    +---------------+----------------+
    |                                |
    v                                v
+------------+                 +--------------+
| pythonservice|               | springservice|
| (writer)    |               | (reader)     |
+------------+                 +--------------+
    |                                |
    +---------------+----------------+
                    |
                    v
             +------------------+
             | PostgreSQL       |
             | (StatefulSet)    |
             +------------------+

Service responsibilities

  • nodeservice

    • Serves static UI from nodeservice/public/index.html
    • Exposes POST /api/items to save new items via pythonservice
    • Exposes GET /api/items to fetch saved items via springservice
    • Configured by environment variables:
      • WRITER_URL → http://pythonservice:5000
      • READER_URL → http://springservice:8081
  • pythonservice

    • Flask API running at port 5000
    • Receives write requests and persists them into PostgreSQL
    • Uses DB_PASSWORD from Kubernetes Secret
  • springservice

    • Spring Boot API running at port 8081
    • Reads rows from PostgreSQL using JdbcTemplate
    • Exposes GET /health and GET /items
    • Uses DB_PASSWORD from Kubernetes Secret
  • postgres

    • PostgreSQL 15 StatefulSet
    • Uses postgres-secret for database password
    • Uses persistence via either built-in volumeClaimTemplates or explicit PVC/PV

Repository layout

  • nodeservice/

    • Dockerfile
    • server.js
    • package.json
    • public/index.html
  • pythonservice/

    • Dockerfile
    • requirements.txt
    • src/app.py
  • springservice/

    • Dockerfile
    • pom.xml
    • src/main/java/com/example/demo/DemoApplication.java
    • src/main/java/com/example/demo/ItemController.java
    • src/main/java/com/example/demo/ItemRepository.java
    • src/main/resources/application.properties
  • K8s_Yaml_Files/

    • configmap.yaml
    • secrets.yaml
    • nodeservice.yaml
    • pythonservice.yaml
    • springservice.yaml
    • postgres.yaml
    • postgres2.yaml
    • persistentvolume.yaml
    • persistentvolumeclaim.yaml
    • storageclass.yaml
    • ingress.yaml
  • K8s_Cluster_Files/

    • create_cluster_worker.sh
  • db/init.sql

    • Database initialization script for the items table

Prerequisites

  • Ubuntu Linux worker nodes (or Linux hosts) with sudo access
  • docker or containerd installed on cluster nodes
  • kubectl installed on your workstation or master node
  • kubeadm, kubelet, and kubectl for cluster bootstrap
  • maven or the included ./mvnw wrapper for the Spring Boot build
  • Docker Hub account (or another registry) if pushing images externally

Build microservices

1. Build the Java Spring Boot reader service

cd /home/shawn/Projects/3-Microservices-Deployment/springservice
./mvnw clean package -DskipTests

2. Build the Docker images

From project root:

cd /home/shawn/Projects/3-Microservices-Deployment

docker build -t shawnprac/nodeservice:latest ./nodeservice

docker build -t shawnprac/pythonservice:latest ./pythonservice

docker build -t shawnprac/springservice:latest ./springservice

Note: The Kubernetes manifests reference images named shawnprac/nodeservice:latest, shawnprac/pythonservice:latest, and shawnprac/springservice:latest. Replace these tags with your own registry or image names if needed.

3. Push images to your registry

docker push shawnprac/nodeservice:latest
docker push shawnprac/pythonservice:latest
docker push shawnprac/springservice:latest

If you are using a local cluster like kind, you can also load the images directly into the cluster instead of pushing.

Kubernetes cluster creation

Master node setup

This repository includes the master initialization script at K8s_Cluster_Files/k8s_Cluster_master.sh. The script configures the master node, installs containerd and Kubernetes components, initializes the cluster, and deploys the network plugin.

sudo apt update -y
sudo swapoff -a
sudo sed -i '/ swap / s/^/#/' /etc/fstab
sudo modprobe overlay
sudo modprobe br_netfilter
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables =k8s_Cluster_Files 1
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
EOF
sudo sysctl --system

sudo apt-get install -y apt-transport-https ca-certificates curl gpg
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /
EOF
sudo apt update -y
sudo apt install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
sudo kubeadm init --pod-network-cidr=10.244.0.0/16

Then configure kubectl on the master:

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

Worker node bootstrap script

The script K8s_Cluster_Files/create_cluster_worker.sh installs required packages and joins a worker node to an existing Kubernetes cluster.

Use it like this on each worker node:

chmod +x K8s_Cluster_Files/create_cluster_worker.sh
sudo ./K8s_Cluster_Files/create_cluster_worker.sh "<kubeadm join command>"

The join command is generated by the master node after kubeadm init, for example:

kubeadm token create --print-join-command

Kubernetes resources deployment

1. Apply configuration and secret resources

kubectl apply -f K8s_Yaml_Files/configmap.yaml
kubectl apply -f K8s_Yaml_Files/secrets.yaml

2. Apply persistence resources if required

  • Use postgres.yaml for a stateful PostgreSQL deployment with its own PVC template.
  • Use postgres2.yaml + persistentvolume.yaml + persistentvolumeclaim.yaml when you want an explicit PVC/PV pairing.
  • storageclass.yaml is a sample AWS EBS StorageClass for cloud environments.

Example dynamic statefulset deployment:

kubectl apply -f K8s_Yaml_Files/postgres.yaml

Example explicit PV/PVC deployment:

kubectl apply -f K8s_Yaml_Files/persistentvolume.yaml
kubectl apply -f K8s_Yaml_Files/persistentvolumeclaim.yaml
kubectl apply -f K8s_Yaml_Files/postgres2.yaml

3. Apply microservice deployments

kubectl apply -f K8s_Yaml_Files/nodeservice.yaml
kubectl apply -f K8s_Yaml_Files/pythonservice.yaml
kubectl apply -f K8s_Yaml_Files/springservice.yaml

4. Apply ingress

If you are using the NGINX ingress controller, make sure it is installed and ready before applying the ingress resource.

kubectl apply -f K8s_Yaml_Files/ingress.yaml

Note: The ingress manifest forwards / to the nodeservice Kubernetes Service on port 80.

Verify deployment

kubectl get nodes
kubectl get pods --all-namespaces
kubectl get svc
kubectl get ingress

Inspect logs if any pod is not ready:

kubectl logs deployment/nodeservice
kubectl logs deployment/pythonservice
kubectl logs deployment/springservice
kubectl logs statefulset/postgres

Accessing the application

  • If using the ingress resource, access the cluster via the ingress host or IP.
  • If using NodePort, send traffic to any cluster node on port 30007.

The frontend UI is served by nodeservice and provides:

  • A form to submit new items
  • A refresh button to load saved items from springservice

Database initialization

The schema for the items table is defined in db/init.sql:

CREATE TABLE IF NOT EXISTS items (
  id SERIAL PRIMARY KEY,
  LogName VARCHAR(255) NOT NULL,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

If PostgreSQL does not automatically initialize the table, run this SQL against the database.

Notes and tips

  • nodeservice uses environment variables to discover pythonservice and springservice inside Kubernetes.
  • pythonservice and springservice both consume DB_PASSWORD from postgres-secret.
  • configmap.yaml contains the DB connection settings:
    • DB_HOST
    • DB_PORT
    • DB_NAME
    • DB_USER
  • Replace Docker image names if you publish images under a different registry.
  • For local Kubernetes environments like kind, you may need to use kind load docker-image for each built image.

Useful commands

# Watch pod rollout
kubectl rollout status deployment/nodeservice
kubectl rollout status deployment/pythonservice
kubectl rollout status deployment/springservice

# Describe resources
kubectl describe svc nodeservice
kubectl describe ingress app-ingress
kubectl describe statefulset postgres

Summary

This project is a full end-to-end microservices deployment example that includes:

  • Kubernetes cluster worker bootstrap automation
  • Node.js UI/API gateway service
  • Python writer service
  • Java Spring Boot reader service
  • PostgreSQL stateful storage
  • Kubernetes ConfigMap, Secret, StatefulSet, Deployment, Service, Ingress, and storage manifests

Use this README to build, deploy, and validate the entire stack in a real Kubernetes environment.

Notes and tips

  • nodeservice uses environment variables to discover pythonservice and springservice inside Kubernetes.
  • pythonservice and springservice both consume DB_PASSWORD from postgres-secret.
  • configmap.yaml contains the DB connection settings:
    • DB_HOST
    • DB_PORT
    • DB_NAME
    • DB_USER
  • Replace Docker image names if you publish images under a different registry.
  • For local Kubernetes environments like kind, you may need to use kind load docker-image for each built image.

Useful commands

# Watch pod rollout
kubectl rollout status deployment/nodeservice
kubectl rollout status deployment/pythonservice
kubectl rollout status deployment/springservice

# Describe resources
kubectl describe svc nodeservice
kubectl describe ingress app-ingress
kubectl describe statefulset postgres

Summary

This project is a full end-to-end microservices deployment example that includes:

  • Kubernetes cluster worker bootstrap automation
  • Node.js UI/API gateway service
  • Python writer service
  • Java Spring Boot reader service
  • PostgreSQL stateful storage
  • Kubernetes ConfigMap, Secret, StatefulSet, Deployment, Service, Ingress, and storage manifests

Use this README to build, deploy, and validate the entire stack in a real Kubernetes environment.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages