A complete local development environment featuring:
- Kind - Local Kubernetes cluster
- Sample Go API - REST API with structured logging
- Loki - Log aggregation system
- Promtail - Log collector
- Grafana - Log visualization and dashboarding
The following tools need to be installed on your system:
-
Docker Desktop - Container runtime (required for Kind)
- Download from: https://www.docker.com/products/docker-desktop
- Make sure Docker is running before proceeding
-
Homebrew - Package manager for macOS (if on macOS)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
The following tools have been installed:
- ✅ kind (v0.31.0) - Kubernetes in Docker
- ✅ kubectl (v1.35.0) - Kubernetes CLI
- ✅ helm (v4.1.0) - Kubernetes package manager
- ✅ go - Go programming language
local_stack_merln/
├── app/ # Go application
│ ├── main.go # REST API with logging
│ ├── go.mod # Go module definition
│ ├── go.sum # Go dependencies
│ └── Dockerfile # Multi-stage Docker build
├── k8s/ # Kubernetes manifests
│ ├── app/ # Application manifests
│ │ ├── deployment.yaml # App deployment
│ │ └── service.yaml # App service (NodePort)
│ └── loki-stack/ # Loki stack configuration
│ └── values.yaml # Helm values for Loki/Promtail/Grafana
├── kind/ # Kind cluster configuration
│ └── kind-config.yaml # Cluster config with port mappings
├── scripts/ # Automation scripts
│ ├── setup.sh # Create Kind cluster
│ ├── deploy-loki.sh # Deploy Loki stack
│ └── deploy-app.sh # Build and deploy sample app
└── README.md # This file
Ensure Docker Desktop is running:
docker ps./scripts/setup.shThis will:
- Create a Kind cluster named
local-stack - Configure port mappings for Grafana (30000) and the API (30080)
- Wait for the cluster to be ready
./scripts/deploy-loki.shThis will:
- Add the Grafana Helm repository
- Install Loki, Promtail, and Grafana
- Configure Loki as a datasource in Grafana
- Wait for all pods to be ready
Access Grafana:
- URL: http://localhost:30000
- Username:
admin - Password:
admin
./scripts/deploy-app.shThis will:
- Build the Docker image for the Go application
- Load the image into the Kind cluster
- Deploy the application to Kubernetes
- Create a NodePort service for external access
Access the API:
- Base URL: http://localhost:30080
The sample Go application exposes the following endpoints:
| Endpoint | Method | Description |
|---|---|---|
/ |
GET | Home page with welcome message |
/health |
GET | Health check endpoint |
/api/users |
GET | Returns a list of sample users |
/api/data |
GET | Returns random system metrics |
/api/random |
GET | Random response with different log levels |
# Home page
curl http://localhost:30080/
# Health check
curl http://localhost:30080/health
# Get users
curl http://localhost:30080/api/users
# Get sample data
curl http://localhost:30080/api/data
# Random endpoint (generates different log levels)
curl http://localhost:30080/api/random# View logs from all sample-api pods
kubectl logs -l app=sample-api -n default
# Follow logs in real-time
kubectl logs -f deployment/sample-api -n default
# View logs from a specific pod
kubectl logs <pod-name> -n default- Open Grafana at http://localhost:30000
- Login with
admin/admin - Go to Explore (compass icon in the left sidebar)
- Select Loki datasource
- Use LogQL queries to filter logs:
# All logs from sample-api
{app="sample-api"}
# Error logs only
{app="sample-api"} |~ "ERROR"
# Warning logs only
{app="sample-api"} |~ "WARN"
# Logs from a specific endpoint
{app="sample-api"} |~ "/api/random"
The sample application generates logs at different levels:
- INFO - Normal operations, requests, responses
- WARN - Warning conditions
- ERROR - Error conditions (simulated in
/api/random)
The /api/random endpoint is particularly useful for testing as it randomly generates different log levels.
# Get cluster info
kubectl cluster-info
# Get all nodes
kubectl get nodes
# Get all pods
kubectl get pods -A
# Get services
kubectl get svc -A# Deploy the dashboard
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml
# Create a proxy
kubectl proxy
# Access at:
# http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/If you see errors about Docker:
# Check Docker status
docker ps
# If not running, start Docker Desktop
open -a Docker# Delete existing cluster
kind delete cluster --name local-stack
# Recreate
./scripts/setup.sh# Check pod status
kubectl get pods -A
# Describe a failing pod
kubectl describe pod <pod-name> -n default
# Check events
kubectl get events -n default --sort-by='.lastTimestamp'# Verify port mappings
docker ps
# Check if services are running
kubectl get svc -A
# Verify NodePort services
kubectl get svc sample-api -n default
kubectl get svc loki-stack-grafana -n default# Check Promtail pods
kubectl get pods -l app.kubernetes.io/name=promtail -n default
# Check Promtail logs
kubectl logs -l app.kubernetes.io/name=promtail -n default
# Check Loki logs
kubectl logs -l app.kubernetes.io/name=loki -n default
# Verify Loki is receiving logs
kubectl port-forward svc/loki-stack 3100:3100 -n default
curl http://localhost:3100/readykubectl delete -f k8s/app/helm uninstall loki-stack -n defaultkind delete cluster --name local-stackdocker rmi sample-api:latest- Edit
app/main.go - Rebuild and redeploy:
./scripts/deploy-app.sh
- Edit
k8s/loki-stack/values.yaml - Update the Helm release:
helm upgrade loki-stack grafana/loki-stack \ -n default \ -f k8s/loki-stack/values.yaml
Edit k8s/app/deployment.yaml and modify the replicas field, then:
kubectl apply -f k8s/app/deployment.yaml- Kind Documentation
- Kubernetes Documentation
- Loki Documentation
- Grafana Documentation
- Go Documentation
┌─────────────────────────────────────────────────────────┐
│ Local Machine │
│ │
│ ┌────────────────────────────────────────────────────┐ │
│ │ Kind Cluster (local-stack) │ │
│ │ │ │
│ │ ┌──────────────┐ ┌─────────────┐ │ │
│ │ │ Sample API │ │ Promtail │ │ │
│ │ │ (2 replicas)│───▶│ (Log Agent) │ │ │
│ │ │ Port: 30080 │ └──────┬──────┘ │ │
│ │ └──────────────┘ │ │ │
│ │ │ Push Logs │ │
│ │ ▼ │ │
│ │ ┌──────────────┐ │ │
│ │ │ Loki │ │ │
│ │ │ (Log Storage)│ │ │
│ │ └──────┬───────┘ │ │
│ │ │ │ │
│ │ │ Query Logs │ │
│ │ ▼ │ │
│ │ ┌──────────────┐ │ │
│ │ │ Grafana │ │ │
│ │ │ Port: 30000 │ │ │
│ │ └──────────────┘ │ │
│ └──────────────────────────────────────────────────────┘ │
│ ▲ │
│ │ │
│ Access via localhost:30000/30080 │
└─────────────────────────────────────────────────────────┘
This is a sample project for local development and testing purposes.