The problem and purpose

Deploying an application is only one part of operating a platform. I built this lab to connect the rest of the workflow: repeatable packaging, versioned delivery, reconciliation, metrics, alerts, logs, and scaling.

The application is deliberately small so the platform behavior stays visible. A local cluster gives me an environment to inspect changes and exercise failure scenarios without presenting the results as evidence of enterprise-scale performance or availability.

Platform architecture

A two-node Kind cluster runs a React frontend and Flask API, packaged with Helm. PostgreSQL uses persistent storage; Redis supports the application. The local ingress routes requests to the frontend and API.

Observability is a separate platform concern: Prometheus collects metrics, Grafana presents dashboards, and Alertmanager handles alerts. Grafana Alloy collects workload logs and sends them to Loki for querying through Grafana.

CI/CD and GitOps delivery

  1. Build: GitHub Actions builds frontend and API container images after qualifying changes on the main branch.
  2. Publish: Images are published to GitHub Container Registry (GHCR), including commit-specific tags.
  3. Promote: After both image builds succeed, an automated job updates the Helm image tags and commits the desired version back to Git.
  4. Reconcile: Argo CD applies the desired Helm configuration to Kubernetes, which rolls out the versioned workloads.
  5. Maintain: Argo CD detects drift and uses automated self-healing to restore the declared configuration.

The repository documents an end-to-end image release and a drift exercise in which a deleted frontend Deployment was recreated by Argo CD. These are bounded lab validations, not a production service-level guarantee.

Image publishing and promotion workflow ↗
Release validation ↗ · Self-healing evidence ↗

Reliability and observability

  • Health: Liveness and readiness probes make workload health part of Kubernetes operation.
  • Metrics and alerts: Prometheus, Grafana, and Alertmanager support inspection of request rate, latency, resource use, and alert conditions.
  • Scaling: Horizontal Pod Autoscaling adjusts API replicas against CPU utilization. The repository documents a load exercise and scale-down after traffic stops.
  • Logs: Alloy and Loki centralize workload logs so investigation can move between metrics and individual events.
  • State: PostgreSQL persistence separates data from application-pod lifecycles; a persistent volume alone is not a backup strategy.

Autoscaling exercise ↗ · Logging configuration ↗

Security considerations

The repository defines dedicated service accounts, RBAC, non-root container settings, and network policies. Those controls make workload privileges and permitted traffic explicit. NetworkPolicy enforcement depends on the cluster’s network implementation; a manifest alone does not prove isolation.

Image promotion also creates a trust boundary: the publishing workflow can write packages and update deployment configuration. A production adaptation would require deliberate review of workflow permissions, protected branches, digest pinning, secret management, and credential rotation.

Local configuration is not a production security certification. Public exposure, TLS, durable storage, access control, and recovery requirements need their own validation before this pattern is used in a shared environment.

Engineering decisions and tradeoffs

Kind over a managed cloud cluster
A repeatable local environment keeps iteration accessible. Two local nodes still share a host and do not demonstrate independent failure domains or cloud availability.
Helm as the installation contract
A compact chart groups the workload and configuration. It is easy to inspect, but couples components that a larger platform might version independently.
Git as the desired-state record
Image promotion leaves a reviewable history and Argo CD reconciles from it. Direct cluster edits may be reverted, and an incorrect desired state can also be automatically applied.
Commit-specific image tags
Tags connect a rollout to a source revision. Registry tags are not inherently immutable; digest references would give stronger artifact identity.
A complete local observability stack
Metrics, alerts, and logs can be investigated together. They consume local resources; production logging requires separate capacity, retention, access, and durability decisions.

What I learned

The release and self-healing exercises make the difference between CI and GitOps concrete: publishing an image creates an artifact; changing desired state and reconciling it delivers that artifact.

Autoscaling and self-healing solve different problems. Increasing replicas responds to demand, while reconciliation repairs configuration drift. Neither removes the need to understand stateful dependencies, host capacity, or failure domains.

The architectural lesson is to validate each boundary. A successful rollout, a recreated Deployment, and a scaling exercise each establish something specific. Together they provide useful evidence without claiming production readiness.

Explore the evidence

The repository contains the application, Helm chart, GitOps configuration, operational notes, and validation records. The related Impact Explorer adds a separate application workload with its own delivery stage.