A Go-based REST API service for managing books, built with Gorilla Mux and PostgreSQL.
.
├── README.md
├── go.mod
├── main.go
├── db/
│ └── schema.sql
├── Dockerfile
└── k8s/
├── app-deployment.yaml
└── postgres-deployment.yaml
- Go 1.20 or later
- Podman
- Kubernetes cluster (for deployment)
- PostgreSQL (for local development)
- Initialize the Go module:
go mod tidy- Run the application locally:
go run main.goThe project uses a multi-architecture Dockerfile to support both ARM (M1/M2) and Intel-based systems:
# Build for AMD64 (Intel) architecture
podman build --platform linux/amd64 -t bookapi:latest .
# For local testing on M1/M2 Mac
podman build --platform linux/arm64 -t bookapi:latest .- Create a pod for the application:
podman pod create --name bookapp -p 9292:9292 -p 5432:5432- Start PostgreSQL:
podman run --pod bookapp --name postgres -d \
-e POSTGRES_PASSWORD=postgres \
-v ./db/schema.sql:/docker-entrypoint-initdb.d/init.sql:Z \
postgres:latest- Start the application:
podman run --pod bookapp --name bookapi -d \
-e DATABASE_URL="postgres://postgres:postgres@localhost:5432/bookdb?sslmode=disable" \
bookapi:latestTo prepare for deployment:
- Tag the image:
podman tag bookapi:latest <registry-url>/bookapi:latest- Push to registry:
podman push <registry-url>/bookapi:latest- Update the image reference in
k8s/app-deployment.yaml:
image: <registry-url>/bookapi:latest- Deploy PostgreSQL:
kubectl apply -f k8s/postgres-deployment.yaml- Deploy the application:
kubectl apply -f k8s/app-deployment.yaml- Verify the deployment:
kubectl get pods
kubectl get servicesGET /books- Retrieve all booksGET /books?id=<id>- Retrieve a specific book by ID
POST /books- Create a new book
{
"title": "Book Title",
"author": "Author Name",
"summary": "Book summary"
}PUT /books?id=<id>- Update an existing book
{
"title": "Updated Title",
"author": "Updated Author",
"summary": "Updated summary"
}DELETE /books?id=<id>- Delete a book
GET /healthz- Service health check
PORT- Server port (default: 9292)DATABASE_URL- PostgreSQL connection string (default: postgres://postgres:postgres@localhost:5432/bookdb?sslmode=disable)
The application is configured with the following resource limits:
- CPU Limit: 500m
- Memory Limit: 512Mi
- CPU Request: 200m
- Memory Request: 256Mi
- CPU Limit: 1000m
- Memory Limit: 1Gi
- CPU Request: 500m
- Memory Request: 512Mi
The application is instrumented with Datadog APM and StatsD metrics, using OpenTelemetry Collector for data collection and export.
The following metrics are collected:
bookapi.books.get.duration- Histogram of request durationbookapi.books.get.by_id- Counter for individual book requestsbookapi.books.get.all- Counter for all books requests
The application creates traces for:
- Book retrieval operations
- Database queries
- Create the configuration:
kubectl apply -f k8s/otel-collector-config.yaml- Create secrets (replace with your actual values):
kubectl create secret generic otel-collector-secrets \
--from-literal=DD_API_KEY=6708a085cef1cb9c10c4f53e5b32c064 \
--from-literal=DT_API_TOKEN=your_dynatrace_token \
--from-literal=DT_API_URL=your_dynatrace_url- Deploy the collector:
kubectl apply -f k8s/otel-collector-deployment.yamlFor local testing with Podman:
# Run the OpenTelemetry Collector
podman run -d --name otel-collector \
-v ./k8s/otel-collector-config.yaml:/etc/otel/config.yaml:Z \
-p 8126:8126 -p 8125:8125/udp \
-e DD_API_KEY=your_datadog_api_key \
-e DT_API_TOKEN=your_dynatrace_token \
-e DT_API_URL=your_dynatrace_url \
otel/opentelemetry-collector-contrib:latestThe project includes automated load testing using k6, which generates consistent traffic to help visualize traces and metrics in Datadog.
- Deploy the k6 test configuration:
kubectl apply -f k8s/k6-configmap.yaml -n bookapi
kubectl apply -f k8s/k6-cronjob.yaml -n bookapiThis will:
- Run k6 tests every minute via a CronJob
- Generate ~100 requests per minute with:
- 40% GET /books (list all)
- 30% POST /books (create new)
- 30% PUT /books/{id} (update)
Monitor the tests:
# View scheduled jobs
kubectl get cronjobs -n bookapi
# View running/completed jobs
kubectl get jobs -n bookapi
# Check test results
kubectl logs -n bookapi -l job-name=k6-load-test-<timestamp>