Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

gitops-k8s-platform

A commit becomes a running, monitored deployment. On your laptop, in about five minutes.

License Kubernetes Argo CD CI

The scenario

Kestrel is a small European logistics company. Its parcel-tracking API, kestrel-api, needs to ship several times a day without anyone running kubectl apply against production, and it needs to be observable enough that the on-call engineer finds out about a problem before customers do.

This repository is the delivery path that makes that true. GitHub Actions builds and publishes the image, then writes the new tag back into the Helm chart as a commit. Argo CD notices the commit and reconciles the cluster to match. Prometheus scrapes the result, and Grafana and Alertmanager work off SLO-based rules rather than arbitrary thresholds. The cluster is never pushed to; it pulls. git revert is the rollback button.

How it fits together

flowchart LR
    dev["Engineer"] -->|git push| repo[("GitHub<br/>gitops-k8s-platform")]

    subgraph ci["GitHub Actions"]
        direction TB
        test["go test<br/>helm lint<br/>kubeconform"] --> img["buildx →<br/>GHCR"]
    end

    repo --> ci
    img -.->|"writes image tag<br/>back as a commit"| repo

    subgraph cluster["Kubernetes cluster (kind locally, EKS in production)"]
        direction TB
        argo["Argo CD<br/>reconcile loop"]
        argo --> app["kestrel-api<br/>Deployment · HPA · PDB · NetworkPolicy"]
        argo --> mon["kube-prometheus-stack"]
        app -->|"/metrics"| prom["Prometheus"]
        prom --> graf["Grafana<br/>RED dashboard"]
        prom --> alert["Alertmanager<br/>error-budget alerts"]
    end

    repo -->|"Argo CD pulls,<br/>nothing pushes in"| argo
Loading

Try it in five minutes

Needs docker, kind, kubectl and helm. No cloud account, no registry login, nothing to pay for.

git clone https://github.com/thisiskazem/gitops-k8s-platform
cd gitops-k8s-platform
make demo        # three-node kind cluster, Argo CD, Prometheus, the app
make traffic     # 60s of mixed traffic so the dashboards have something to show

make demo ends with:

==> verifying the platform
    pod placement across nodes:
      kestrel-api-6cfd7c94b6-mkbx4             kestrel-worker
      kestrel-api-6cfd7c94b6-vqp9z             kestrel-worker2
    calling the API from inside the cluster:
      {"id":"KSL-4417","origin":"Turin, IT","destination":"Amsterdam, NL",
       "status":"in_transit","updated_at":"2026-07-26T13:41:02Z"}
    checking that Prometheus actually scrapes it:
 ok kestrel-api is an active Prometheus target

Then open Grafana (make status prints the port-forward commands and the password) and look at Kestrel / Kestrel API / RED. make down deletes everything.

What is in here

app/                     Go service: RED metrics, split liveness/readiness, graceful drain
  Dockerfile             multi-stage → distroless, non-root, 18 MB, multi-arch
charts/kestrel-api/      Helm chart: Deployment, HPA, PDB, NetworkPolicy, ServiceMonitor
  values-prod.yaml       only the lines that genuinely differ in production
gitops/argocd/           AppProject + three Applications (app, monitoring, observability)
observability/           SLO alert rules and the Grafana dashboard, delivered by Argo CD
.github/workflows/       ci.yaml (test, lint, validate, publish) · release.yaml (promote)
hack/                    kind cluster config and the demo script

What this demonstrates

Skill Where to look
Go app/main.go, app/metrics.go: RED instrumentation, bounded label cardinality
Docker app/Dockerfile: distroless, non-root, cross-compiled, cache mounts
Kubernetes charts/kestrel-api/templates/: PDB, NetworkPolicy, topology spread, probe strategy
Helm _helpers.tpl immutable selectors, .Capabilities CRD guard, minimal prod overlay
Argo CD gitops/argocd/: AppProject as a blast-radius boundary, HPA drift handling, sync waves
GitHub Actions ci.yaml least-privilege permissions, OIDC push to GHCR, no stored secrets
Prometheus observability/alerts.yaml: multi-window multi-burn-rate SLO alerts
Grafana observability/dashboard-kestrel-api.json: RED dashboard, version-controlled
Bash hack/demo.sh: strict mode, idempotent, waits on conditions rather than sleeping

Deliberate trade-offs

Things that are simplified here, and why. A reviewer should be able to tell what is a decision and what is a shortcut.

  • make demo installs the app with Helm, not Argo CD. Argo CD pulls from a git remote, and a freshly cloned working tree has no published commit to pull from. The monitoring stack is genuinely reconciled by Argo CD, so the pull loop is real and visible. After pushing this repo, make gitops hands the app over to gitops/argocd/app-kestrel-api.yaml too. Same chart either way.
  • State lives in memory. A database would add a StatefulSet, migrations and backups without teaching anything more about delivery, which is what this repo is about.
  • Control-plane scrape jobs are disabled. On kind these components bind to localhost; on EKS the control plane is managed by AWS. Leaving them enabled produces permanently-DOWN targets, and a dashboard that is always partly red is a dashboard nobody reads.
  • Base images are pinned by tag, not digest. Digest pinning is correct for production but needs Renovate or Dependabot to stay current, and a repo full of stale digests is worse than one with readable tags.
  • No CPU limit, only a memory limit. CPU is compressible, so a limit only buys throttling latency during a spike. Memory is not, so it gets a hard cap.
  • The NetworkPolicy allows ingress from any namespace. Narrowing it needs a real client inventory; inventing one would be theatre.

Related

The EKS cluster this deploys to in production is built by aws-landing-zone.

Author

Kazem Bigdeli · Cloud, DevOps & Platform Engineer · Turin, Italy linkedin.com/in/kazembigdeli

About

A commit becomes a running, monitored deployment. Go, Docker, Helm, Argo CD, Prometheus, verified on kind.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages