All Posts
15 Sep 202518 min readExpert

Designing a Production-Ready Kubernetes Platform

Part of Platform Engineering

  • Kubernetes
  • Platform Engineering
  • AWS

Standing up a Kubernetes cluster is a weekend project. Operating a platform that fifty engineers trust for production deploys is a multi-quarter commitment. The gap between 'we have K8s' and 'we have a production-ready platform' is where most organizations underestimate cost.

I have helped shape platform capabilities at Edmingle around EKS-adjacent patterns: standardized namespaces, ingress, secrets, observability baselines, and guardrails that let product teams move fast without becoming cluster admins. This post captures what I would require before calling a K8s platform production-ready.

Platform Layers, Not Just a Cluster

┌─────────────────────────────────────────────────┐
│  Developer Experience (IDP, templates, docs)     │
├─────────────────────────────────────────────────┤
│  GitOps + CI (build, deploy, promote)           │
├─────────────────────────────────────────────────┤
│  Shared Services (ingress, certs, DNS, secrets) │
├─────────────────────────────────────────────────┤
│  Observability (metrics, logs, traces, alerts)  │
├─────────────────────────────────────────────────┤
│  Policy + Security (RBAC, network, admission)   │
├─────────────────────────────────────────────────┤
│  Cluster Infrastructure (EKS, nodes, autoscale) │
└─────────────────────────────────────────────────┘

A production platform is the stack above the control plane. Teams should onboard with a service template, not a kubectl cheat sheet.

Multi-Tenancy and RBAC

Day one mistake: give every developer cluster-admin because it is faster. Day ninety problem: you cannot audit who changed what, and one bad kubectl deletes a namespace.

Use namespace-per-team or namespace-per-service with RoleBindings scoped to what they need. Platform team owns cluster-level resources; app teams own Deployments, Services, and ConfigMaps in their namespace.

# App team RoleBinding - no cluster-admin
kind: RoleBinding
metadata:
  namespace: team-payments
subjects:
  - kind: Group
    name: payments-devs
roleRef:
  kind: ClusterRole
  name: edit  # or a custom restricted role

Integrate RBAC with your identity provider (OIDC via AWS IAM or Google). No shared kubeconfig files in Slack.

Ingress, TLS, and DNS

Every service needs a predictable path from Internet or internal VPC to Pod without bespoke nginx configs per team.

Standardize on one ingress controller (nginx or AWS Load Balancer Controller for ALB). Automate TLS with cert-manager and Let's Encrypt or ACM. DNS via ExternalDNS so Ingress hostnames resolve automatically.

Document the contract: 'Add these annotations, get a URL.' Deviations require platform review.

Secrets Management

Sealed Secrets, External Secrets Operator with AWS Secrets Manager, or SOPS-encrypted files in Git-pick one and enforce it. Plain Secrets in Git repos happen when you do not pick.

Rotate credentials on a schedule. Mount secrets as files or env vars consistently. Never bake secrets into container images (scan for this in CI).

Observability Baseline

No service ships to prod without metrics scrape, structured logs, and trace propagation. Install Prometheus or managed AMP, Loki or CloudWatch Logs, and OpenTelemetry collector as cluster add-ons.

SignalMinimum barOwner
MetricsRED/USE dashboards, alert on SLO burnPlatform provides; app defines SLOs
LogsJSON logs, correlation ID, 14-day retentionApp emits; platform aggregates
TracesHTTP and DB spans on critical pathsShared instrumentation libs

Platform provides the plumbing. App teams own runbooks for their alerts.

Resource Governance

Set ResourceQuota and LimitRange per namespace before the first OOM kills a neighbor's Redis. Require requests and limits on every container-admission policy can reject non-compliant manifests.

Use Horizontal Pod Autoscaler with sensible defaults in service templates. Cluster Autoscaler or Karpenter for node scaling on AWS.

Cost visibility: label namespaces with team and cost center; export kube-cost metrics monthly.

GitOps and Deployment Safety

All prod changes flow through Git. Argo CD or Flux with AppProject boundaries. Prod sync manual or approval-gated; staging auto-sync.

PodDisruptionBudgets, readiness probes that reflect real dependencies, and NetworkPolicies for sensitive tiers are non-negotiable before GA.

Engineering Takeaways

  • A production K8s platform is shared services + guardrails + DX, not just a running control plane.
  • RBAC via OIDC with namespace isolation beats shared admin kubeconfig every time.
  • Standardize ingress, TLS, DNS, and secrets before onboarding ten teams-you will not refactor later.
  • Observability is a platform deliverable; apps inherit metrics, logs, and trace export by default.
  • Resource quotas and admission policies prevent noisy-neighbor outages and runaway cloud bills.
  • GitOps with promotion gates is the deploy interface; kubectl to prod is an incident waiting to happen.

Trade-offs I Would Consider

Option: Managed EKS with minimal platform tooling

  • Pros: Lower initial build cost, AWS handles control plane patches, faster first deploy.
  • Cons: Teams reinvent ingress/secrets/monitoring; operational toil scales linearly with service count.

Option: Full internal platform with golden paths and IDP

  • Pros: Consistent security and observability, faster onboarding at scale, centralized upgrades.
  • Cons: Higher upfront investment, platform team becomes bottleneck if understaffed.

What I Would Do in Production

Ship a 'service template' repo: Deployment, Service, Ingress, HPA, PDB, ServiceMonitor, and NetworkPolicy stubs with sensible defaults.

Run cluster add-ons (ingress, cert-manager, external-dns, external-secrets, metrics-server) via Helm or GitOps before any app onboard.

Enforce policy with Kyverno or OPA Gatekeeper: required labels, no latest tag, no privileged containers, mandatory probes.

Establish a platform office hours channel and a RFC process for exceptions-rigidity without feedback creates shadow infra.

Game-day test: node failure, AZ loss simulation, and restore from etcd backup at least quarterly.

FAQ

Q: When is self-managed K8s worth it over EKS?

Rarely for product companies. EKS trades control plane toil for AWS integration. Self-managed makes sense at very large scale with dedicated infra teams.

Q: How many platform engineers for N developers?

Rule of thumb: 1 platform engineer per 10-20 devs early, improving with golden paths. Understaffing creates shadow ops in every squad.

Q: Do we need a service mesh?

Not day one. Add Istio or Linkerd when mTLS, traffic splitting, or cross-service auth complexity justifies operational cost.

Q: What about Windows nodes or GPU workloads?

Specialized node pools with taints and tolerations. Keep default platform path Linux amd64; branch templates for exceptions.

Q: How do we version cluster upgrades?

N-1 Kubernetes minor on prod, upgrade staging first, validate add-on compatibility, maintain a runbook for API deprecations.