<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kestrion</title>
    <description>The latest articles on DEV Community by Kestrion (@kestrion).</description>
    <link>https://dev.to/kestrion</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4076790%2Fa73d6b49-26ae-4550-b348-aea995027922.png</url>
      <title>DEV Community: Kestrion</title>
      <link>https://dev.to/kestrion</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kestrion"/>
    <language>en</language>
    <item>
      <title>The Kubernetes Audit Worksheet</title>
      <dc:creator>Kestrion</dc:creator>
      <pubDate>Tue, 15 Sep 2026 09:15:18 +0000</pubDate>
      <link>https://dev.to/kestrion/the-kubernetes-audit-worksheet-1m30</link>
      <guid>https://dev.to/kestrion/the-kubernetes-audit-worksheet-1m30</guid>
      <description>&lt;p&gt;&lt;em&gt;&lt;strong&gt;Do it right from the beginning&lt;/strong&gt; ----&amp;gt; Print this, block four hours, and work through it with whoever knows the cluster best. Every command is read-only.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Section 0 — Context (15 min, no terminal)
&lt;/h2&gt;

&lt;p&gt;Write down before looking at anything:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Business: what runs on this cluster, and what does one hour of downtime cost?&lt;/li&gt;
&lt;li&gt;People: who can operate it? Who is the single point of failure?&lt;/li&gt;
&lt;li&gt;History: last incident, last upgrade, last restore test (dates, not vibes).&lt;/li&gt;
&lt;li&gt;Bill: monthly cloud + observability spend, best guess.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You'll compare these answers with reality at the end. The gap is your executive summary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Section 1 — Inventory (30 min)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl version                          &lt;span class="c"&gt;# in support?&lt;/span&gt;
kubectl get nodes &lt;span class="nt"&gt;-o&lt;/span&gt; wide                &lt;span class="c"&gt;# count, versions, ages, pressure&lt;/span&gt;
kubectl get ns                           &lt;span class="c"&gt;# what exists&lt;/span&gt;
kubectl get deploy,sts,ds,cronjob &lt;span class="nt"&gt;-A&lt;/span&gt;     &lt;span class="c"&gt;# workload inventory&lt;/span&gt;
helm &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-A&lt;/span&gt;                               &lt;span class="c"&gt;# what Helm thinks is installed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Record: K8s version and support status, node count/type, workload count, and — critically — &lt;strong&gt;which workloads are NOT represented in any Git repo&lt;/strong&gt;. That list is your unreproducible surface.&lt;/p&gt;

&lt;h2&gt;
  
  
  Section 2 — Deployment path (30 min)
&lt;/h2&gt;

&lt;p&gt;Trace one real service from commit to production and write each step down. Then answer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Can anyone deploy by hand to prod? (If yes: who has, recently? Check &lt;code&gt;kubectl rollout history&lt;/code&gt;.)&lt;/li&gt;
&lt;li&gt;Rollback: exact commands/steps, and when it was last exercised.&lt;/li&gt;
&lt;li&gt;Probes and shutdown: for the top 3 services, check readiness probes, &lt;code&gt;preStop&lt;/code&gt;, &lt;code&gt;terminationGracePeriodSeconds&lt;/code&gt;, rollout strategy, PDBs.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get deploy &amp;lt;top-service&amp;gt; &lt;span class="nt"&gt;-o&lt;/span&gt; yaml | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-A5&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s2"&gt;"readinessProbe|preStop|strategy"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Section 3 — Access &amp;amp; secrets (45 min)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get clusterrolebindings &lt;span class="nt"&gt;-o&lt;/span&gt; wide | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-iE&lt;/span&gt; &lt;span class="s2"&gt;"admin|edit"&lt;/span&gt;
kubectl auth can-i get secrets &lt;span class="nt"&gt;-n&lt;/span&gt; &amp;lt;shared-ns&amp;gt; &lt;span class="nt"&gt;--as&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&amp;lt;a-normal-user&amp;gt;
kubectl get secrets &lt;span class="nt"&gt;-A&lt;/span&gt; | &lt;span class="nb"&gt;wc&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Record: humans with cluster-admin (target: ~0 for daily use), service accounts with broad rights, secret source of truth (ESO/Vault/SOPS vs. hand-created), whether the API server is internet-reachable, and whether any Git repo contains a base64 secret (&lt;code&gt;git grep -i "kind: Secret"&lt;/code&gt; across infra repos). Also check &lt;code&gt;kubectl get validatingwebhookconfigurations,clusterpolicies -A&lt;/code&gt; — if nothing comes back, there's no admission-time guardrail catching a bad manifest before RBAC and secrets hygiene even get tested.&lt;/p&gt;

&lt;h2&gt;
  
  
  Section 4 — Cost (45 min)
&lt;/h2&gt;

&lt;p&gt;If OpenCost/Kubecost isn't installed, note it as finding #1 and use what you have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl top nodes
kubectl top pods &lt;span class="nt"&gt;-A&lt;/span&gt; &lt;span class="nt"&gt;--sort-by&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;memory | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-30&lt;/span&gt;
kubectl describe nodes | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-A8&lt;/span&gt; &lt;span class="s2"&gt;"Allocated resources"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Record: requested vs. actually-used CPU/memory ratio (the over-provisioning factor), workloads with &lt;strong&gt;no&lt;/strong&gt; requests, count of &lt;code&gt;type: LoadBalancer&lt;/code&gt; services, log ingestion GB/day and retention, non-prod running out-of-hours, unattached volumes in the cloud console.&lt;/p&gt;

&lt;h2&gt;
  
  
  Section 5 — Observability (30 min)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Where do engineers look first during an incident? (Ask two people separately; different answers = finding.)&lt;/li&gt;
&lt;li&gt;Open the alert history for the last 2 weeks: which alerts fired, which led to action? Non-actionable ones are noise debt.&lt;/li&gt;
&lt;li&gt;Do golden-signal dashboards exist for the top 3 services?&lt;/li&gt;
&lt;li&gt;Certificates: &lt;code&gt;kubectl get certificates -A -o json | jq -r '.items[] | select(.status.conditions[]?.status!="True") | .metadata.name'&lt;/code&gt; lists cert-manager certs not currently Ready. Is renewal automated AND alerted on failure?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Section 6 — Backup &amp;amp; DR (30 min)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get backups &lt;span class="nt"&gt;-A&lt;/span&gt;          &lt;span class="c"&gt;# velero, if present&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Record: what is backed up (cluster state? volumes? databases?), where backups live (outside the blast radius?), last successful backup, &lt;strong&gt;last tested restore&lt;/strong&gt;, and estimated time to rebuild everything from Git + backups. If the restore has never been tested, the audit's #1 recommendation writes itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  Section 7 — Upgrade readiness (20 min)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubent   &lt;span class="c"&gt;# or: pluto detect-all-in-cluster    # deprecated APIs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Record: versions behind latest, deprecated API usage, add-on versions (ingress, cert-manager, CNI, CSI) and whether anyone owns their lifecycle, existence of a staging cluster or IaC to create one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Section 8 — Synthesis (45 min)
&lt;/h2&gt;

&lt;p&gt;Turn notes into three artifacts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Risk map&lt;/strong&gt; — every finding rated Impact (1–3) × Likelihood (1–3). Anything 6+ goes on page one. Example: an untested restore is Impact 3 (the business can't recover) × Likelihood 2 (backups exist but nobody's proven they work) = 6.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost opportunity&lt;/strong&gt; — over-provisioning factor + logging retention + orphans, expressed in currency/month.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Remediation backlog&lt;/strong&gt; — max 10 items, ordered by risk score, each with an effort guess (hours/days/weeks). Default priority when tied: tested restore → rollback → secrets/RBAC → requests cleanup → cert automation → upgrade plan.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Finish by re-reading Section 0. The distance between what the team &lt;em&gt;believed&lt;/em&gt; and what you &lt;em&gt;found&lt;/em&gt; is the story the leadership summary should tell.&lt;/p&gt;

&lt;h2&gt;
  
  
  A note on scope
&lt;/h2&gt;

&lt;p&gt;This worksheet deliberately excludes application code quality, CI pipeline internals, and cloud account security outside the cluster. Those matter, but mixing them in is how audits become three-week projects nobody finishes. Half a day, cluster-focused, three artifacts out. Done beats comprehensive.&lt;/p&gt;

&lt;p&gt;A version of this with 0–100 scoring runs in the browser: the &lt;a href="https://kestrion.dev/scorecard/" rel="noopener noreferrer"&gt;free production readiness scorecard&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>sre</category>
      <category>devops</category>
      <category>cloudnative</category>
    </item>
    <item>
      <title>Why Kubernetes Rolling Updates Still Give You 503s</title>
      <dc:creator>Kestrion</dc:creator>
      <pubDate>Wed, 09 Sep 2026 20:46:30 +0000</pubDate>
      <link>https://dev.to/kestrion/why-kubernetes-rolling-updates-still-give-you-503s-3j4p</link>
      <guid>https://dev.to/kestrion/why-kubernetes-rolling-updates-still-give-you-503s-3j4p</guid>
      <description>&lt;p&gt;"We use rolling updates, so deploys are zero-downtime." Then you deploy, and for 2–3 seconds users get 503s. This exact complaint shows up constantly on Stack Overflow and Reddit, and it has a precise, fixable cause — actually four of them, stacked.&lt;/p&gt;

&lt;p&gt;The core misunderstanding: &lt;strong&gt;rolling updates guarantee pod replacement order, not traffic correctness.&lt;/strong&gt; Kubernetes replaces pods gracefully; whether &lt;em&gt;requests&lt;/em&gt; survive depends on details it leaves to you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cause 1: traffic arrives before the app is ready
&lt;/h2&gt;

&lt;p&gt;A pod becomes a load-balancing target when its readiness probe passes. If you have no readiness probe, that's the moment the container starts — before your app has loaded config, connected to the database, or warmed anything. First requests: connection refused.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; a readiness probe that checks what "ready to serve" actually means for your app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;readinessProbe&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;httpGet&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;/ready&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;8080&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
  &lt;span class="na"&gt;periodSeconds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
  &lt;span class="na"&gt;failureThreshold&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And &lt;code&gt;/ready&lt;/code&gt; should verify dependencies (DB connection up), not just return 200 unconditionally.&lt;/p&gt;

&lt;p&gt;If startup is slow and variable (JVM warmup, a large cache preload), pair this with a &lt;code&gt;startupProbe&lt;/code&gt;. Without one, a slow-but-healthy app can hit the readiness probe's &lt;code&gt;failureThreshold&lt;/code&gt; and get killed mid-boot — the opposite symptom, same root cause: nothing told Kubernetes "still starting" is different from "broken."&lt;/p&gt;

&lt;h2&gt;
  
  
  Cause 2: traffic keeps arriving after the pod is told to die
&lt;/h2&gt;

&lt;p&gt;This is the one that causes the classic "2–3 seconds of 503s," and it's the least intuitive. When a pod terminates, two things happen &lt;strong&gt;in parallel&lt;/strong&gt;, not in sequence:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The pod gets SIGTERM.&lt;/li&gt;
&lt;li&gt;Endpoint controllers start removing the pod from load balancers.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Step 2 takes time to propagate — kube-proxy rules on every node, cloud LB target deregistration. For seconds after SIGTERM, traffic is still routed to a pod that may already be shutting down. If your app exits immediately on SIGTERM, every one of those requests fails.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix — the famous sleep:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;lifecycle&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;preStop&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;exec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;sleep"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;preStop&lt;/code&gt; hook runs before SIGTERM is sent. Sleeping a few seconds keeps the app fully serving while endpoints propagate. It looks like a hack; it's the standard, load-bearing pattern (Kubernetes docs and every ingress vendor recommend some form of it).&lt;/p&gt;

&lt;p&gt;How long to sleep depends on the slowest link in your specific path — in-cluster kube-proxy rules update quickly, but a cloud load balancer sitting in front can be far slower (AWS ALB's &lt;code&gt;deregistration_delay&lt;/code&gt; defaults to 300 seconds). Check what's actually in your traffic path before picking a number.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cause 3: the app doesn't drain on SIGTERM
&lt;/h2&gt;

&lt;p&gt;After &lt;code&gt;preStop&lt;/code&gt;, SIGTERM arrives. The app must: stop accepting new connections, finish in-flight requests, then exit. Many frameworks do this only if you ask — and some servers keep-alive connections open forever unless told to close them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; enable your framework's graceful shutdown (Spring: &lt;code&gt;server.shutdown=graceful&lt;/code&gt;; Go: &lt;code&gt;http.Server.Shutdown()&lt;/code&gt;; Node: close the server and track sockets), and make sure &lt;code&gt;terminationGracePeriodSeconds&lt;/code&gt; (default 30) exceeds &lt;code&gt;preStop&lt;/code&gt; + your longest request. If it doesn't, SIGKILL wins and kills in-flight work.&lt;/p&gt;

&lt;p&gt;Keep-alive HTTP/2 and gRPC clients add one more wrinkle: a client holding a long-lived connection open won't notice the pod is going away until that connection actually breaks. The server needs to signal it explicitly — gRPC servers should send &lt;code&gt;GOAWAY&lt;/code&gt;, not just stop accepting new streams — or the client keeps sending requests into a pod that's already draining.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cause 4: the rollout replaces capacity too aggressively
&lt;/h2&gt;

&lt;p&gt;Defaults (&lt;code&gt;maxUnavailable: 25%&lt;/code&gt;) can briefly leave you under-provisioned under load: old pods dying while new pods are technically Ready but cold (empty caches, JIT not warmed, connection pools empty). Latency spikes read as downtime.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;strategy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;rollingUpdate&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;maxUnavailable&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;0&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;maxSurge&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="nv"&gt;1&lt;/span&gt; &lt;span class="pi"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;New capacity comes up before old capacity goes away. Slower rollout, no dip. Add a PodDisruptionBudget so node drains during upgrades obey the same rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  The complete checklist
&lt;/h2&gt;

&lt;p&gt;For every user-facing service:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Readiness probe that checks real dependencies&lt;/li&gt;
&lt;li&gt;[ ] &lt;code&gt;preStop&lt;/code&gt; sleep (5–10s)&lt;/li&gt;
&lt;li&gt;[ ] Graceful shutdown on SIGTERM, verified (kill a pod, watch error rates)&lt;/li&gt;
&lt;li&gt;[ ] &lt;code&gt;terminationGracePeriodSeconds&lt;/code&gt; &amp;gt; preStop + longest request&lt;/li&gt;
&lt;li&gt;[ ] &lt;code&gt;maxUnavailable: 0, maxSurge: 1&lt;/code&gt; for critical services&lt;/li&gt;
&lt;li&gt;[ ] PodDisruptionBudget&lt;/li&gt;
&lt;li&gt;[ ] Actually test it: &lt;code&gt;kubectl rollout restart&lt;/code&gt; under synthetic load and watch the error rate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That last item is the real gap. Teams configure all of this and never verify it. A deploy under load in staging with a load generator running takes fifteen minutes and tells you the truth.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters beyond deploys
&lt;/h2&gt;

&lt;p&gt;The same mechanics run during node upgrades, autoscaler scale-downs, and spot instance reclaims. If deploys cause 503s, so does every cluster maintenance event — your "deployment problem" is actually an "any pod ever moves" problem. Fix it once and cluster upgrades, autoscaling, and spot instances all become safe as a side effect. It's one of the highest ROI afternoons available in Kubernetes.&lt;/p&gt;

&lt;p&gt;Deployment safety is one of seven categories in the &lt;a href="https://kestrion.dev/scorecard/" rel="noopener noreferrer"&gt;free production readiness scorecard&lt;/a&gt; we built.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>sre</category>
      <category>devops</category>
      <category>cloudnative</category>
    </item>
    <item>
      <title>8 Kubernetes Cost Leaks Small Teams Miss</title>
      <dc:creator>Kestrion</dc:creator>
      <pubDate>Tue, 01 Sep 2026 14:28:01 +0000</pubDate>
      <link>https://dev.to/kestrion/8-kubernetes-cost-leaks-small-teams-miss-2p9l</link>
      <guid>https://dev.to/kestrion/8-kubernetes-cost-leaks-small-teams-miss-2p9l</guid>
      <description>&lt;p&gt;&lt;em&gt;The over-provisioning, logging, and idle-infrastructure defaults that quietly inflate a small team's Kubernetes bill—and the order I'd fix them in.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Half of teams report their costs went &lt;strong&gt;up&lt;/strong&gt; after adopting Kubernetes (CNCF FinOps microsurvey), with over-provisioning cited as the top cause. That matches every complaint thread: "our observability costs are destroying our cloud budget," "$80K/month just for APM/logging/metrics." The pattern is consistent: the cluster itself isn't the leak — the defaults around it are.&lt;/p&gt;

&lt;p&gt;Here are the eight leaks I'd check first, roughly in order of typical savings.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Resource requests copied from tutorials
&lt;/h2&gt;

&lt;p&gt;Requests reserve capacity whether you use it or not, and the cluster autoscaler buys nodes to satisfy requests, not usage. Most small-team clusters request 3–5× what they consume, because every deployment inherited &lt;code&gt;500m / 512Mi&lt;/code&gt; from a blog post in 2022.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; measure a week of real usage per workload, reset requests to P95 + headroom. Tools: OpenCost, &lt;code&gt;kubectl top&lt;/code&gt;, Goldilocks/VPA in recommendation mode. This alone is often 30–50% of compute.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Log ingestion with no retention policy
&lt;/h2&gt;

&lt;p&gt;Observability pricing is per-GB-ingested and per-GB-retained. Default behavior — every pod's stdout, debug level, shipped to a SaaS, kept forever — is how a 10-person company gets a five-figure logging bill.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; drop debug logs at the collector (Fluent Bit/OTel Collector filter), sample high-volume noise, set 7–30 day retention with cold archive to object storage for compliance. Bills routinely drop 60–80%.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Non-prod running nights and weekends
&lt;/h2&gt;

&lt;p&gt;Staging and dev clusters at full size, 168 hours a week, used maybe 50. That's paying for 3× the environment you use.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; scale non-prod to zero (or minimum) outside working hours. A CronJob or your cloud's scheduler is enough; kube-downscaler exists precisely for this.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. One load balancer per service
&lt;/h2&gt;

&lt;p&gt;Every &lt;code&gt;Service type: LoadBalancer&lt;/code&gt; is a billed cloud load balancer. Ten services = ten LBs = real money for zero benefit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; one ingress controller behind one LB, route by host/path. This is a one-day change.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Cross-AZ traffic you never asked for
&lt;/h2&gt;

&lt;p&gt;Kubernetes spreads pods across zones, then services route across zones by default, and clouds bill every cross-AZ gigabyte. Chatty microservices + 3 AZs = a silent network line item that grows with traffic.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; topology-aware routing / &lt;code&gt;internalTrafficPolicy&lt;/code&gt;, colocate chatty services, and check whether every environment truly needs 3-AZ HA (staging doesn't). Note the trade-off: &lt;code&gt;internalTrafficPolicy: Local&lt;/code&gt; keeps traffic in-zone and off the bill, but it also stops balancing across zones — fine for a chatty backend with even load, riskier if one zone can end up overloaded while another sits idle.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Orphaned volumes, IPs, and snapshots
&lt;/h2&gt;

&lt;p&gt;Deleting workloads doesn't always delete their PersistentVolumes (depends on reclaim policy), and never deletes old snapshots or static IPs. These accumulate for years.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; quarterly sweep: unattached volumes, unassociated IPs, snapshots older than policy. &lt;code&gt;kubectl get pv -o json | jq '.items[] | select(.status.phase=="Released") | .metadata.name'&lt;/code&gt; finds volumes still billing after their claim is gone — start there. Usually a few hundred/month found in ten minutes.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Zero spot/preemptible usage
&lt;/h2&gt;

&lt;p&gt;Stateless, replicated workloads — the exact thing Kubernetes is good at rescheduling — are ideal for spot instances at 60–90% discount. Small teams avoid them out of fear; the fear is mostly outdated for fault-tolerant workloads.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; a spot node pool for stateless/batch/CI workloads with on-demand fallback (Karpenter or managed node groups make this nearly trivial). Karpenter's consolidation policy actively bin-packs and reshuffles onto cheaper capacity as prices move, not just at initial scheduling — worth enabling on purpose, it isn't the default. Keep databases on on-demand.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Nobody owns the number
&lt;/h2&gt;

&lt;p&gt;The meta-leak. CNCF's survey found 45% blame "lack of awareness/ownership" for overspend. If cost is nobody's metric, every leak above regenerates within a quarter of being fixed.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; install OpenCost (free, CNCF), put cost-per-namespace on a dashboard the team actually sees, review it monthly in an existing meeting. Visibility changes behavior more than any optimization does.&lt;/p&gt;

&lt;h2&gt;
  
  
  The order I'd run this as an audit
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;OpenCost + one week of data (leak 8 enables seeing 1–7).&lt;/li&gt;
&lt;li&gt;Requests vs. usage report → resize (biggest single win).&lt;/li&gt;
&lt;li&gt;Logging ingestion/retention review (second biggest, fastest to fix).&lt;/li&gt;
&lt;li&gt;LB/ingress consolidation and orphan sweep (quick wins).&lt;/li&gt;
&lt;li&gt;Non-prod schedule + spot pools (structural wins).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A realistic outcome for a small cluster that's never been through this: &lt;strong&gt;30–60% off the total bill&lt;/strong&gt;, most of it in the first two steps, with no architecture changes and no new paid tools.&lt;/p&gt;

&lt;p&gt;The uncomfortable truth: none of this is advanced. It's unglamorous hygiene that nobody owns because everyone is shipping features. Which is exactly why it's worth an afternoon.&lt;/p&gt;

&lt;p&gt;Cost is one of seven categories in the &lt;a href="https://kestrion.dev/scorecard/" rel="noopener noreferrer"&gt;50-question production readiness scorecard&lt;/a&gt; I built. It runs in the browser and turns this checklist into a score you can track.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.opencost.io/docs/" rel="noopener noreferrer"&gt;OpenCost documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/" rel="noopener noreferrer"&gt;Kubernetes documentation: resource management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/services-networking/topology-aware-routing/" rel="noopener noreferrer"&gt;Kubernetes documentation: topology-aware routing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://karpenter.sh/docs/" rel="noopener noreferrer"&gt;Karpenter documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kubernetes</category>
      <category>sre</category>
      <category>devops</category>
      <category>cloudnative</category>
    </item>
    <item>
      <title>The First 10 Things I Would Check in a Messy Kubernetes Cluster</title>
      <dc:creator>Kestrion</dc:creator>
      <pubDate>Tue, 25 Aug 2026 20:49:39 +0000</pubDate>
      <link>https://dev.to/kestrion/the-first-10-things-i-would-check-in-a-messy-kubernetes-cluster-7bi</link>
      <guid>https://dev.to/kestrion/the-first-10-things-i-would-check-in-a-messy-kubernetes-cluster-7bi</guid>
      <description>&lt;p&gt;&lt;em&gt;A practical first-pass assessment for an undocumented Kubernetes cluster—focused on risk, cost, recoverability, and ownership.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A practical first-pass assessment for an undocumented Kubernetes cluster—focused on risk, cost, recoverability, and ownership.&lt;/p&gt;

&lt;p&gt;Imagine being handed a Kubernetes cluster with no documentation, one engineer who half-remembers building it, a growing bill, and a business that depends on it.&lt;/p&gt;

&lt;p&gt;Nothing is obviously broken. Deployments work—most days. Certificates renew—probably. Backups exist—somewhere. This is not a failed platform; it is a platform whose risks nobody can clearly name.&lt;/p&gt;

&lt;p&gt;I would not begin by redesigning it or introducing another tool. I would first build a map of reality. These are the ten areas I would inspect, in this order.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Is the foundation still supported?
&lt;/h2&gt;

&lt;p&gt;First, I want to know whether the Kubernetes version and its critical add-ons are still supported. An old cluster turns every other improvement into part of an upgrade project.&lt;/p&gt;

&lt;p&gt;I would also look for node pressure, recurring instability, and conditions the team has learned to call “normal.” Persistent warnings are findings, not personality traits of the cluster.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Does Git describe what is actually running?
&lt;/h2&gt;

&lt;p&gt;Next, I would compare the live cluster with the repositories that supposedly define it. The difference is the team's tribal-knowledge inventory: manual hotfixes, temporary jobs that became permanent, and releases upgraded outside the normal path.&lt;/p&gt;

&lt;p&gt;Anything that exists only in the cluster is difficult to review, explain, or rebuild.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Who can do what?
&lt;/h2&gt;

&lt;p&gt;I would map human and service-account access, especially broad administrative permissions. The problem is rarely one dramatic mistake. It is accumulated access: former experiments, CI credentials, shared accounts, and permissions nobody felt safe removing.&lt;/p&gt;

&lt;p&gt;The useful question is not only “who has access?” but “who still needs it?”&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Where do secrets actually live?
&lt;/h2&gt;

&lt;p&gt;Secrets often reveal the operating model faster than any architecture diagram. Are they stored in plain YAML, created manually, shared between applications, or managed from a clear source of truth?&lt;/p&gt;

&lt;p&gt;If nobody can explain how a secret is rotated without breaking production, it probably has not been rotated.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Do resource requests reflect reality?
&lt;/h2&gt;

&lt;p&gt;I would compare declared requests with observed usage. Messy clusters often contain both extremes: workloads reserving far more than they need and workloads declaring nothing at all.&lt;/p&gt;

&lt;p&gt;This affects more than cost. Scheduling, autoscaling, capacity planning, and stability all depend on resource assumptions that resemble reality.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. What is actually driving the bill?
&lt;/h2&gt;

&lt;p&gt;Compute gets most of the attention, but the expensive surprise may be log ingestion, retention, cross-zone traffic, idle load balancers, or orphaned storage.&lt;/p&gt;

&lt;p&gt;The goal is not an impressive savings percentage. It is a cost map the team can explain: which workloads and operational choices create the bill, and which of them deliver value.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. What expires next?
&lt;/h2&gt;

&lt;p&gt;Certificates, domains, credentials, and tokens are quiet until they are urgent. I would identify what expires, how renewal works, and whether a failed renewal reaches a human before customers notice.&lt;/p&gt;

&lt;p&gt;Automation is not enough. Unobserved automation is only a more sophisticated assumption.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. What happens when something disappears?
&lt;/h2&gt;

&lt;p&gt;For the most important service, I would ask what happens during a pod restart, deployment, or node drain. Are new instances ready before receiving traffic? Do old instances finish in-flight requests? Is there enough capacity to lose one replica?&lt;/p&gt;

&lt;p&gt;This is where “zero-downtime deployment” stops being a YAML setting and becomes observable behaviour.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Can the team restore, not merely back up?
&lt;/h2&gt;

&lt;p&gt;I would find the latest successful backups, where they are stored, and what they actually contain. Cluster resources and application data may need different recovery mechanisms.&lt;/p&gt;

&lt;p&gt;Then comes the decisive question: when was the last restore tested? A successful backup job proves that something was written. A restore test proves that the business can recover.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. What does only one person know?
&lt;/h2&gt;

&lt;p&gt;Finally, I would sit with the person who knows the cluster best and ask: “What are you the only person who knows how to do?”&lt;/p&gt;

&lt;p&gt;The answer might include upgrades, DNS changes, incident recovery, certificate renewal, or a fragile deployment sequence. That list is not a documentation problem. It is operational risk—and often the most valuable output of the assessment.&lt;/p&gt;

&lt;h2&gt;
  
  
  What should come out of this review?
&lt;/h2&gt;

&lt;p&gt;Not a 40-page report and not a shopping list of new tools. The useful result is three small artifacts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A risk map: what could interrupt production, and why.&lt;/li&gt;
&lt;li&gt;A cost map: where the bill comes from and what deserves investigation.&lt;/li&gt;
&lt;li&gt;A prioritized backlog: what the team should fix first, with a clear owner.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first actions are usually unglamorous: test a restore, confirm the rollback path, reduce unnecessary access, document critical knowledge, and schedule the next upgrade.&lt;/p&gt;

&lt;p&gt;Messy clusters rarely need another layer of complexity. They need a shared picture of reality, explicit ownership, and an order of operations.&lt;/p&gt;

&lt;p&gt;I turned this kind of assessment into a &lt;a href="https://kestrion.dev/scorecard/" rel="noopener noreferrer"&gt;50-question Kubernetes production readiness scorecard&lt;/a&gt;. It runs in the browser and helps a team find the first conversation worth having.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>sre</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>The Kubernetes Checklist for Teams Without a Platform Team</title>
      <dc:creator>Kestrion</dc:creator>
      <pubDate>Thu, 13 Aug 2026 21:24:54 +0000</pubDate>
      <link>https://dev.to/kestrion/the-kubernetes-checklist-for-teams-without-a-platform-team-1ian</link>
      <guid>https://dev.to/kestrion/the-kubernetes-checklist-for-teams-without-a-platform-team-1ian</guid>
      <description>&lt;p&gt;Most Kubernetes advice assumes you have a platform team: specialists who own upgrades, ingress, security policies, and the 2 a.m. pages.&lt;/p&gt;

&lt;p&gt;The teams I am writing for usually have three to ten engineers, one of whom “knows Kubernetes,” and no dedicated platform team. They depend on a cluster that nobody fully owns.&lt;/p&gt;

&lt;p&gt;I work in enterprise environments where platform teams are large and everything is process. This article is the opposite exercise: what is the &lt;em&gt;minimum&lt;/em&gt; discipline a small team needs to run Kubernetes in production—and what enterprise baggage should it refuse to copy?&lt;/p&gt;

&lt;h2&gt;
  
  
  The question that matters more than any tool
&lt;/h2&gt;

&lt;p&gt;Before any checklist: &lt;strong&gt;who owns the platform after the migration is finished?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Not “who set it up.” Who owns upgrades next year, certificate renewals, the CNI version, and deprecated APIs?&lt;/p&gt;

&lt;p&gt;If the answer is one person's name, you do not have a platform. You have key-person risk with YAML on top. If the answer is “nobody, really,” Kubernetes is invisible operational debt accumulating interest.&lt;/p&gt;

&lt;p&gt;The rest of this checklist exists to make that ownership small enough for a small team to carry.&lt;/p&gt;

&lt;p&gt;For each item, score 0 if it does not exist, 1 if it exists but is informal or untested, and 2 if it is documented and tested. The purpose is not to produce a flattering number. It is to expose the next few conversations the team needs to have.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Deployments: Git is the source of truth
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Treat Git as the source of truth for workloads and cluster configuration, including temporary fixes.&lt;/li&gt;
&lt;li&gt;Use one reconciliation path—for example, Argo CD or Flux—so production changes are reviewed and reproducible. Keep emergency access, but reconcile every emergency change back into Git.&lt;/li&gt;
&lt;li&gt;Define and test a rollback path for every service. A Git revert is useful only if your delivery process can deploy it safely.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This converts your cluster from a mystery into a diff. Every other practice gets easier once “what is running?” has an answer.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. The rollout basics that prevent late-night incidents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Readiness probes that answer one question: can this pod serve traffic now? Include a dependency only when the application genuinely cannot serve a useful response without it.&lt;/li&gt;
&lt;li&gt;Graceful termination: handle SIGTERM and allow in-flight requests to drain. Add a short &lt;code&gt;preStop&lt;/code&gt; delay only when your routing path needs time to stop sending new traffic, then test the behavior under load.&lt;/li&gt;
&lt;li&gt;Resource requests based on measured usage so scheduling and capacity planning reflect reality. Add limits deliberately; the right choice differs for CPU, memory, and workload behavior.&lt;/li&gt;
&lt;li&gt;PodDisruptionBudgets for replicated workloads that must remain available during voluntary disruptions such as node drains. Size them from the replica count and failure tolerance.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Security: the boring baseline, not the service mesh
&lt;/h2&gt;

&lt;p&gt;Small teams can over-index on advanced security machinery while skipping basics that matter in a customer security review:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RBAC scoped per human and per workload. Nobody uses &lt;code&gt;cluster-admin&lt;/code&gt; for daily work.&lt;/li&gt;
&lt;li&gt;Secrets via External Secrets Operator, Vault, or SOPS. Never store plaintext secrets in Git, and check who can run &lt;code&gt;kubectl get secret&lt;/code&gt; in shared namespaces.&lt;/li&gt;
&lt;li&gt;Admission policy: block &lt;code&gt;:latest&lt;/code&gt;, block privileged workloads, and require resource requests. Kyverno is one approachable option.&lt;/li&gt;
&lt;li&gt;NetworkPolicies around sensitive namespaces and workloads, starting with the traffic paths you actually understand.&lt;/li&gt;
&lt;li&gt;Restrict control-plane access to the networks and identities that need it; use the private-endpoint options of your managed provider where they fit your operating model.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is a stronger starting point than adding advanced machinery while basic access and secret handling remain unclear.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Observability: answers, not data
&lt;/h2&gt;

&lt;p&gt;You do not need every log, metric, and trace. You need to answer three questions quickly: is it broken, where, and since when?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prometheus—or a managed equivalent—plus golden-signal dashboards for your most important services.&lt;/li&gt;
&lt;li&gt;Alerts on symptoms users feel: error rate, latency, and saturation. Regularly review alerts that never produce action.&lt;/li&gt;
&lt;li&gt;Centralized logs with an explicit retention policy.&lt;/li&gt;
&lt;li&gt;Tracing when you have real multi-service debugging pain and the budget. “Not yet” can be a valid architecture decision.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  5. Backup: a backup you have not restored is a rumor
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Velero—or a cloud-native equivalent—for Kubernetes resources and supported persistent volumes; database-native backups for databases.&lt;/li&gt;
&lt;li&gt;Backups stored outside the cluster and account they protect.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Test a restore.&lt;/strong&gt; Restore tests regularly expose missing permissions, credentials, data, or instructions. Find that out on a Tuesday afternoon, not during an incident.&lt;/li&gt;
&lt;li&gt;Write one page titled “the cluster is gone”: how long rebuilding from Git and backups should take, and who does what.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  6. Upgrades: a schedule, not an emergency
&lt;/h2&gt;

&lt;p&gt;Kubernetes releases regularly and managed providers enforce their own support windows. Teams that wait until an upgrade is forced take on more changes at once and have less recent practice.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set a cadence that stays comfortably inside your provider's support window, and put it on the calendar.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;pluto&lt;/code&gt; or &lt;code&gt;kubent&lt;/code&gt; for deprecated APIs before every upgrade.&lt;/li&gt;
&lt;li&gt;Treat add-ons—ingress controller, cert-manager, CSI, and CNI—as part of the upgrade. Their compatibility can be as consequential as the control-plane version.&lt;/li&gt;
&lt;li&gt;Rehearse on a throwaway or staging cluster first.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What not to copy from enterprises
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Multi-cluster, multi-region setups before you have multi-customer problems.&lt;/li&gt;
&lt;li&gt;A service mesh “because security.” Start with NetworkPolicies.&lt;/li&gt;
&lt;li&gt;An internal developer portal for five engineers.&lt;/li&gt;
&lt;li&gt;Change advisory boards. For many small teams, Git history and pull-request review are the change process.&lt;/li&gt;
&lt;li&gt;Every logo in the CNCF landscape. The landscape is a map, not a shopping list.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Copy the &lt;strong&gt;discipline&lt;/strong&gt;: ownership, rollback, tested restores, and an upgrade cadence.&lt;/p&gt;

&lt;p&gt;Refuse the &lt;strong&gt;complexity&lt;/strong&gt;: architecture shaped by headcount you do not have.&lt;/p&gt;

&lt;h2&gt;
  
  
  The one-hour exercise
&lt;/h2&gt;

&lt;p&gt;You do not need to implement all of this at once. The useful outcome is a short, ordered backlog—not a perfect score.&lt;/p&gt;

&lt;p&gt;Sit the team down and score each item from 0 to 2. Anything scoring 0 in backup, rollback, or secrets is a candidate for the next sprint—before another platform feature.&lt;/p&gt;

&lt;p&gt;I turned this exercise into a &lt;a href="https://kestrion.dev/scorecard/" rel="noopener noreferrer"&gt;50-question production readiness scorecard&lt;/a&gt; that runs in the browser. It covers deployment safety, ownership, cost, security, observability, disaster recovery, and upgrades.&lt;/p&gt;

&lt;p&gt;The goal is not a perfect platform. The goal is Kubernetes boring enough that your team can go back to shipping product.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/workloads/pods/probes/" rel="noopener noreferrer"&gt;Kubernetes documentation: probes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/" rel="noopener noreferrer"&gt;Kubernetes documentation: container lifecycle hooks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/workloads/pods/disruptions/" rel="noopener noreferrer"&gt;Kubernetes documentation: disruptions and PodDisruptionBudgets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/" rel="noopener noreferrer"&gt;Kubernetes documentation: resource management&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
      <category>infrastructure</category>
      <category>kubernetes</category>
      <category>sre</category>
    </item>
  </channel>
</rss>
