A fully containerized microservices playground running on Kind (Kubernetes-in-Docker), featuring Golang, NestJS, RabbitMQ, NGINX Ingress, and a local Docker registry.
This project demonstrates a clean, minimal example of an event-driven microservices architecture deployed inside a local Kubernetes cluster.
-
API Gateway (Go, REST) Exposes
POST /usersand forwards requests to the User Service. -
User Service (Go, REST) Creates a user and publishes a
user.createdevent to RabbitMQ. -
Notification Service (NestJS + RabbitMQ) Subscribes to
user.createdand logs: “Welcome email sent to ”.
- Kind Cluster – Includes custom node config, Metrics Server, namespaces, LoadBalancer support via
cloud-provider-kind, and liveness/readiness probes. - Local Docker Registry – Used by Kind to pull microservice images.
- RabbitMQ (StatefulSet) – Provides persistent message queues.
- NGINX Ingress Controller – Routes external traffic to the API Gateway.
- Devbox Environment – Reproducible dev environment with
docker,kind,kubectl, andcloud-provider-kind.
flowchart LR
subgraph Client
Browser[User → API Request]
end
subgraph Ingress
Nginx[NGINX Ingress Controller]
end
subgraph API
Gateway[API Gateway - REST]
end
subgraph Microservices
UserService[Go User Service]
NotificationService[NestJS Notification Service]
end
subgraph Messaging
RabbitMQ[(RabbitMQ)]
end
Browser --> Nginx --> Gateway
Gateway --> UserService
UserService -->|Publish user.created| RabbitMQ
RabbitMQ --> NotificationService
Install locally:
Alternatively, install only Devbox and run below command inside the project root:
devbox shellInside the shell, tools like Kind, kubectl, and cloud-provider-kind are installed and isolated to the project directory. (you still need to install Docker separately)
This will:
- Create a Kind cluster
- Start a local Docker registry
- Install Metrics Server
- Create namespaces
- Switch kubectl context
make kind-create-clusterbelow command will install NGINX Ingress and start cloud-provider-kind in background:
make kind-deploy-nginx-ingressThe command will wait for External IP to be available but if it times out, you can manually check via:
kubectl get service -n ingress-nginxEdit /etc/hosts:
[External-IP] microservices.local
Hostname is defined inside: k8s/api-gateway/ingress.yaml.
Build:
make kind-build-imagesPush to the local registry:
make kind-push-imagesDeploy RabbitMQ + all microservices:
make kind-deploy-servicesCheck readiness:
kubectl get pods -n microservices
kubectl get pods -n datastoresCreate a user:
curl -X POST http://microservices.local/users \
-H "Content-Type: application/json" \
-d '{"name": "daniel", "email": "daniel@example.com", "password": "123"}'Check Notification Service logs:
kubectl logs -f deployment/notification-service -n microservicesYou should see something like:
{
"level": "log",
"pid": 25,
"timestamp": 1764442767463,
"message": "Sending welcome email to daniel",
"context": "NotificationController"
}Delete the Kind cluster:
make kind-delete-clusterDeployment logs:
kubectl logs -n microservices deployment/notification-serviceSpecific pod logs:
kubectl get pods -n microservices
kubectl logs -n microservices <pod-name>Stream logs:
kubectl logs -n microservices -f deployment/notification-servicePods:
kubectl get pods -n microservicesDescribe:
kubectl describe pod -n microservices <pod-name>Deployments:
kubectl get deployment -n microservices
kubectl describe deployment -n microservices <deployment-name>Services:
kubectl get service -n microservicesLive watching:
kubectl get pods -n microservices -wkubectl port-forward -n datastores service/rabbitmq 15672:15672Then open:
http://localhost:15672
Default credentials:
- Username:
default - Password:
default
Pods may restart during initial startup due to:
- RabbitMQ image pulling
- RabbitMQ not ready yet
- Microservices waiting for RabbitMQ connection
- Readiness/liveness probes failing until dependencies are up
Wait a moment and check:
kubectl get pods -n microservices
kubectl get pods -n datastoresWatch all namespaces:
kubectl get pods -A -wIf you find this project useful, consider giving it a ⭐, it helps others discover it.
Contributions, feedback, and suggestions are always welcome. Feel free to open an issue or submit a PR anytime.