Skip to main content

Notes from the Field

Field notes on Kubernetes, GitOps and cloud cost from live consulting work, plus the hands-on guides I teach from. Browse the guides →

From 49 to 87: an enforced CSP, caching and image fixes on a React SPA, without breaking production

· 15 min read
Ashik Mostofa Tonmoy
Senior DevOps Engineer & Platform Engineering Consultant

A security scanner gave our main site 49/100, "Critical CSP gaps". There was no Content-Security-Policy at all, the favicon alone weighed 601 KB, and nobody had looked at how the frontends were cached or compressed.

The stack: three React + Vite single-page apps, each served by nginx in a container, behind a host nginx and Cloudflare, talking to FastAPI backends. Two environments, dev and prod, on two VPSs.

Production observability on two small VPSs: metrics, logs, traces and SLOs with Grafana LGTM

· 22 min read
Ashik Mostofa Tonmoy
Senior DevOps Engineer & Platform Engineering Consultant

When I started, the platform had no monitoring at all. No host metrics, no central logs, no alerting, no traces. If a page was slow, the only tool was docker logs and a guess.

The stack: a handful of FastAPI services on MongoDB Atlas, a Django service on PostgreSQL, React frontends and MinIO for uploads, all in Docker Compose on two VPSs: production and dev. No Kubernetes, no budget for a SaaS observability bill, and a small team.

Building an internal developer platform: six decisions that determine whether it works

· 6 min read
Ashik Mostofa Tonmoy
Senior DevOps Engineer & Platform Engineering Consultant

An internal developer platform succeeds or fails on six decisions. Not on the technology — Kubernetes, ArgoCD and Terraform are the baseline, and every platform uses them. The decisions are architectural, and they are invisible until the platform is in production and developers are either adopting it or working around it.

GPU scheduling on Kubernetes: a practical guide

· 5 min read
Ashik Mostofa Tonmoy
Senior DevOps Engineer & Platform Engineering Consultant

A GPU node costs 5-10x what a CPU node costs per hour. Getting GPU scheduling wrong on Kubernetes means paying for idle GPUs, or worse — having GPUs available and no workload scheduled on them while a data scientist waits. This guide covers the setup, the scheduling rules and the cost controls.

Migrating from Jenkins to GitHub Actions: what survives and what breaks

· 6 min read
Ashik Mostofa Tonmoy
Senior DevOps Engineer & Platform Engineering Consultant

A pipeline migration is not a YAML translation exercise. It is a re-examination of every step in the pipeline and a decision about whether that step still belongs there. Most Jenkins pipelines carry years of accumulated logic that nobody remembers adding, and the migration is the first opportunity in years to delete it.

Kubernetes disaster recovery: backup, restore and the etcd snapshot you forgot

· 5 min read
Ashik Mostofa Tonmoy
Senior DevOps Engineer & Platform Engineering Consultant

Kubernetes disaster recovery is not complicated. It is a checklist, and most teams get three-quarters of the way down it and stop. The missing quarter is the one that matters in an actual disaster.

This is the full checklist, from etcd snapshots to the restore runbook you need to test before you need to run it.

Setting up Prometheus and Grafana on Kubernetes: a practical guide

· 5 min read
Ashik Mostofa Tonmoy
Senior DevOps Engineer & Platform Engineering Consultant

Observability is the difference between knowing something is broken and finding out from a user. On Kubernetes, the toolchain that answers this for most teams is Prometheus, Grafana and Alertmanager — three projects from the CNCF ecosystem that together give you metrics collection, dashboards and alerting.

This guide walks through setting them up, deciding what to monitor and configuring the alerts that actually matter.

Azure workload identity on self-managed RKE2

· 9 min read
Ashik Mostofa Tonmoy
Senior DevOps Engineer & Platform Engineering Consultant

Managed Kubernetes hands you workload identity. AKS runs an OIDC issuer for the cluster, publishes its discovery documents, and Entra already trusts them — a pod gets an Azure token and nobody thinks about it.

On plain VMs, none of that exists. The nodes have no Azure identity to assume, and the workloads still need Key Vault and Blob Storage. The default answer at that point is a service principal secret in a Kubernetes Secret: a static cloud credential, sitting on a node, rotated by nobody. It is the same credential CI pipelines are still carrying, in a different place.

There is a better answer, and the cluster already does most of it. Every Kubernetes cluster signs service-account tokens with a private key. Those tokens are already OIDC-shaped JWTs. Publish the public half over HTTPS, point Entra at it, and the cluster becomes an identity provider it always was.

This is what that took on a production RKE2 cluster running on bare VMs.

The step that breaks CI/CD when you move to OIDC

· 4 min read
Ashik Mostofa Tonmoy
Senior DevOps Engineer & Platform Engineering Consultant

Long-lived cloud credentials in CI are the most reliably exploited secret in any organisation. They are copied into a settings page once, they never expire, and nothing tells you when one leaks. Federated identity — OIDC — removes them: the pipeline presents a short-lived token that the cloud verifies against your CI provider, and no static key exists to steal.

The migration is genuinely worth doing. It also fails, almost always, at exactly one step.