<?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: Sagar</title>
    <description>The latest articles on DEV Community by Sagar (@sagar_27c8f0d73ec633f7d5b).</description>
    <link>https://dev.to/sagar_27c8f0d73ec633f7d5b</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%2F4196857%2F02a3f847-6a65-482f-b6a6-037c762af22e.jpg</url>
      <title>DEV Community: Sagar</title>
      <link>https://dev.to/sagar_27c8f0d73ec633f7d5b</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sagar_27c8f0d73ec633f7d5b"/>
    <language>en</language>
    <item>
      <title>CrashLoopBackOff: how to find the real cause (and why deleting the pod won't help)</title>
      <dc:creator>Sagar</dc:creator>
      <pubDate>Wed, 21 Oct 2026 11:48:23 +0000</pubDate>
      <link>https://dev.to/sagar_27c8f0d73ec633f7d5b/crashloopbackoff-how-to-find-the-real-cause-and-why-deleting-the-pod-wont-help-130g</link>
      <guid>https://dev.to/sagar_27c8f0d73ec633f7d5b/crashloopbackoff-how-to-find-the-real-cause-and-why-deleting-the-pod-wont-help-130g</guid>
      <description>&lt;p&gt;A config change goes out. A couple of minutes later every request to the app fails, and &lt;code&gt;kubectl get pods&lt;/code&gt; shows the status nobody wants to see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;NAME                      READY   STATUS             RESTARTS      AGE
go-api-7b45497dfd-qxqx2   0/1     CrashLoopBackOff   4 &lt;span class="o"&gt;(&lt;/span&gt;15s ago&lt;span class="o"&gt;)&lt;/span&gt;   115s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I broke a small Go service on purpose to walk through this one properly, from the first symptom to a fix you can prove. The commands work on any cluster. The specific bug is just one example, and I'll come back at the end to the other things that cause the same status.&lt;/p&gt;

&lt;h2&gt;
  
  
  What CrashLoopBackOff actually tells you
&lt;/h2&gt;

&lt;p&gt;It is easy to read CrashLoopBackOff as an error. It isn't one. It is Kubernetes describing what it is doing about an error.&lt;/p&gt;

&lt;p&gt;The container starts and then exits. The kubelet on the node restarts it, because the pod's &lt;code&gt;restartPolicy&lt;/code&gt; says so. If it exits again, the kubelet waits before the next try, and the wait grows each time: 10 seconds, 20, 40, and so on, capped at five minutes (Kubernetes docs: container restarts). While it is waiting, the pod shows &lt;code&gt;CrashLoopBackOff&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So the status answers "what is happening?" (the container keeps dying) and says nothing about why. That second question is the whole job, and the pod has already written the answer down somewhere. You just have to know where to read it.&lt;/p&gt;

&lt;h2&gt;
  
  
  First, check whether anyone is still being served
&lt;/h2&gt;

&lt;p&gt;Before digging into the crash, it's worth thirty seconds to find out how bad things are. A crash loop during a rollout is often harmless: with a rolling update and a readiness probe, the old pods keep serving until a new one becomes Ready. If the new pod never gets there, the rollout just stalls.&lt;/p&gt;

&lt;p&gt;A Deployment keeps one ReplicaSet per version of its pod template, so listing them tells you whether an older version is still up:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl get rs &lt;span class="nt"&gt;-n&lt;/span&gt; go-api
NAME                DESIRED   CURRENT   READY   AGE
go-api-5d8497557b   0         0         0       5m46s
go-api-7b45497dfd   1         1         0       2m9s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not good. The old ReplicaSet is at zero, and the new one wants a pod and has none ready. Nothing is serving. In my drill I set it up that way on purpose, but you get the same picture in real life with a &lt;code&gt;Recreate&lt;/code&gt; strategy, or when the crash only starts after the pod has already passed its readiness check. Either way, this isn't a stuck rollout any more. It's an outage.&lt;/p&gt;

&lt;p&gt;The browser agreed:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff0c9ipaaj5ewl6o4wqef.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ff0c9ipaaj5ewl6o4wqef.png" alt="Snowopslabs - Kubernetes logs previous" width="800" height="132"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That message comes from the ingress. It had a route for the app and no ready pod to send the request to.&lt;/p&gt;

&lt;h3&gt;
  
  
  A detour worth taking: the dashboard that says everything is fine
&lt;/h3&gt;

&lt;p&gt;This was the part of the drill that surprised me most. Here is the Grafana dashboard during the outage. On the left is the app's own error rate (HTTP 5xx). On the right is the failure rate seen by k6, the load generator sending traffic from outside.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3bhy8leq2avmyxcqvobl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3bhy8leq2avmyxcqvobl.png" alt="Grafana dashboard" width="800" height="325"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The app reports zero errors. The client sees 100% of requests fail. Both are telling the truth: a process that never finishes starting can't count the requests it never received, so its own metrics go quiet rather than red. If your alerting only looks at what the service says about itself, a total outage can look like a calm afternoon. Watch at least one signal from the client side too, whether that's an ingress or load balancer metric, a synthetic check, or a probe from outside the cluster.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read the crash's last words: &lt;code&gt;kubectl logs --previous&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Plain &lt;code&gt;kubectl logs&lt;/code&gt; shows the current container. In a crash loop the current container has often just started, or hasn't started yet, so you get nothing useful. The container that just died is still on the node, and &lt;code&gt;--previous&lt;/code&gt; (or &lt;code&gt;-p&lt;/code&gt;) asks for its logs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl logs &lt;span class="nt"&gt;-n&lt;/span&gt; go-api go-api-7b45497dfd-qxqx2 &lt;span class="nt"&gt;--previous&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"level"&lt;/span&gt;:&lt;span class="s2"&gt;"INFO"&lt;/span&gt;,&lt;span class="s2"&gt;"msg"&lt;/span&gt;:&lt;span class="s2"&gt;"server starting"&lt;/span&gt;,&lt;span class="s2"&gt;"port"&lt;/span&gt;:&lt;span class="s2"&gt;"80800"&lt;/span&gt;,&lt;span class="s2"&gt;"service"&lt;/span&gt;:&lt;span class="s2"&gt;"go-api"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;"level"&lt;/span&gt;:&lt;span class="s2"&gt;"ERROR"&lt;/span&gt;,&lt;span class="s2"&gt;"msg"&lt;/span&gt;:&lt;span class="s2"&gt;"server error"&lt;/span&gt;,&lt;span class="s2"&gt;"error"&lt;/span&gt;:&lt;span class="s2"&gt;"listen tcp: address 80800: invalid port"&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(I trimmed the timestamps.) Two lines, and the second one is the answer. The server tried to listen on port 80800. Port numbers stop at 65535, so the bind fails and the process exits.&lt;/p&gt;

&lt;p&gt;Most of the time the logs get you this far. When they don't, the next command usually does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Confirm it from Kubernetes' side: &lt;code&gt;kubectl describe pod&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;describe&lt;/code&gt; is long, so I pipe it into &lt;code&gt;less&lt;/code&gt; and search for &lt;code&gt;Last State&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl describe pod &lt;span class="nt"&gt;-n&lt;/span&gt; go-api go-api-7b45497dfd-qxqx2 | less
...
    Last State:     Terminated
      Reason:       Error
      Exit Code:    1
    Ready:          False
    Restart Count:  4
    ...
    Environment:
      PORT:                 80800
      READINESS_FAILURE:    &lt;span class="nb"&gt;false
      &lt;/span&gt;SHUTDOWN_TIMEOUT:     10s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three things to take from this block.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The exit code.&lt;/strong&gt; &lt;code&gt;1&lt;/code&gt; means the app chose to exit with an error. Nothing killed it. If you see &lt;code&gt;137&lt;/code&gt; instead, the process got a SIGKILL (128 + 9), and a &lt;code&gt;Reason&lt;/code&gt; of &lt;code&gt;OOMKilled&lt;/code&gt; tells you it ran out of memory. Those two numbers send you down completely different paths, so it's worth reading this line before anything else.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The environment.&lt;/strong&gt; The same 80800 again, now in the spec. So the bad value isn't something the app made up at runtime. Kubernetes handed it over.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The events at the bottom.&lt;/strong&gt; In this case they only confirm the loop: &lt;code&gt;Back-off restarting failed container&lt;/code&gt;. For other causes they carry the real clue, such as &lt;code&gt;Liveness probe failed&lt;/code&gt;, a missing ConfigMap or Secret, or an image that can't be pulled.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix everyone tries first
&lt;/h2&gt;

&lt;p&gt;With the pod clearly broken, deleting it is tempting. I tried:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl delete pod &lt;span class="nt"&gt;-n&lt;/span&gt; go-api go-api-7b45497dfd-qxqx2
pod &lt;span class="s2"&gt;"go-api-7b45497dfd-qxqx2"&lt;/span&gt; deleted

&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl get pods &lt;span class="nt"&gt;-n&lt;/span&gt; go-api
NAME                      READY   STATUS             RESTARTS      AGE
go-api-7b45497dfd-4c995   0/1     CrashLoopBackOff   1 &lt;span class="o"&gt;(&lt;/span&gt;21s ago&lt;span class="o"&gt;)&lt;/span&gt;   22s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A new name, the same crash, within seconds. The pod was never the problem. A pod owned by a Deployment is a copy of the Deployment's pod template, and the ReplicaSet will keep making fresh copies of the same mistake for as long as you delete them. The only thing deleting achieved was resetting the restart counter, which made the situation look less serious than it was.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fix it where it lives: the pod template
&lt;/h2&gt;

&lt;p&gt;So the question becomes where the template gets &lt;code&gt;PORT=80800&lt;/code&gt; from. &lt;code&gt;describe deploy&lt;/code&gt; shows the template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl describe deploy go-api &lt;span class="nt"&gt;-n&lt;/span&gt; go-api | less
...
  Containers:
   go-api:
    Image:      go-api:v1.2.0
    Port:       8080/TCP &lt;span class="o"&gt;(&lt;/span&gt;http&lt;span class="o"&gt;)&lt;/span&gt;
    Liveness:   http-get http://:http/health &lt;span class="nv"&gt;delay&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;15s &lt;span class="nb"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5s &lt;span class="nv"&gt;period&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10s
    Readiness:  http-get http://:http/ready &lt;span class="nv"&gt;delay&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;10s &lt;span class="nb"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3s &lt;span class="nv"&gt;period&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;5s
    Environment:
      PORT:                 80800
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The container declares port 8080, both probes use that named port, and the environment variable says 80800. One zero too many. The fix goes on the Deployment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; go-api &lt;span class="nb"&gt;set env &lt;/span&gt;deploy/go-api &lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8080
deployment.apps/go-api &lt;span class="nb"&gt;env &lt;/span&gt;updated
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Changing the template starts a new rollout. In a real team you'd make the same change in whatever produced the manifest (the Helm values, the Kustomize overlay, the GitOps repo) or the next sync will put the typo straight back. &lt;code&gt;kubectl set env&lt;/code&gt; is fine for stopping the bleeding, as long as the real fix follows it.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;kubectl rollout undo deploy/go-api -n go-api&lt;/code&gt; would have worked too. It returns the template to the previous revision, environment included. When you're paged and you know the last change caused it, rolling back first and investigating second is often the right call.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prove the fix instead of assuming it
&lt;/h2&gt;

&lt;p&gt;Don't eyeball &lt;code&gt;get pods&lt;/code&gt; a few seconds after the change. &lt;code&gt;rollout status&lt;/code&gt; waits until the new pods are actually Ready:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; go-api rollout status deploy/go-api
Waiting &lt;span class="k"&gt;for &lt;/span&gt;deployment &lt;span class="s2"&gt;"go-api"&lt;/span&gt; rollout to finish: 1 old replicas are pending termination...
deployment &lt;span class="s2"&gt;"go-api"&lt;/span&gt; successfully rolled out

&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl get pods &lt;span class="nt"&gt;-n&lt;/span&gt; go-api
NAME                      READY   STATUS    RESTARTS   AGE
go-api-5d8497557b-r47rn   1/1     Running   0          26s

&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl get rs &lt;span class="nt"&gt;-n&lt;/span&gt; go-api
NAME                DESIRED   CURRENT   READY   AGE
go-api-5d8497557b   1         1         1       9m8s
go-api-7b45497dfd   0         0         0       5m31s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look at the ReplicaSet names. Kubernetes didn't create a third one. The fixed template is identical to the one from before the bad change, so the Deployment scaled the old ReplicaSet back up. It's a small detail, but it's a nice confirmation that the template now matches the last version that worked.&lt;/p&gt;

&lt;p&gt;Then check from outside, the way users see it. The health URL answered again, and the request rate on the dashboard came back.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try it on your own cluster
&lt;/h2&gt;

&lt;p&gt;You don't need anything special to reproduce this. On a test cluster, take any Deployment whose app reads its port from an environment variable and give it an impossible one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl &lt;span class="nb"&gt;set env &lt;/span&gt;deploy/&amp;lt;your-test-app&amp;gt; &lt;span class="nv"&gt;PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;80800
kubectl get pods &lt;span class="nt"&gt;-w&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the default rolling update you'll likely see the stalled-rollout version: the old pod stays Running while the new one crash-loops. That's a useful thing to see for yourself, because it's exactly why the ReplicaSet check at the start matters. Put it back with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl rollout undo deploy/&amp;lt;your-test-app&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you'd rather practise the full outage version, with traffic, dashboards, alerts and a check that tells you when you've actually fixed it, this drill is one of the incidents in SnowOps Labs, a free, open-source Kubernetes lab that runs on a laptop. Disclosure: I build it. Every screenshot above is from it, and the code is on &lt;a href="https://www.github.com/sagar2395/snowopslabs" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd5afyzizxlz8i9552x71.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fd5afyzizxlz8i9552x71.png" alt="Snowopslabs UI" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Other causes of the same status
&lt;/h2&gt;

&lt;p&gt;The port typo is one cause among many. The Kubernetes docs group the usual suspects into application errors, configuration errors, resource limits, and failing health checks. In practice that looks like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A bug or a missing dependency in the app.&lt;/strong&gt; Logs with &lt;code&gt;--previous&lt;/code&gt; usually say so, often as a stack trace or a "connection refused" to a database that isn't there.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Missing or wrong configuration.&lt;/strong&gt; A typo like this one, a variable renamed in one place and not the other, a config file mounted at the wrong path, or a value that's fine in staging and wrong in production.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Not enough memory.&lt;/strong&gt; Exit code 137 with &lt;code&gt;Reason: OOMKilled&lt;/code&gt; in &lt;code&gt;describe&lt;/code&gt;. Raise the limit or fix the leak, but find out which one first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A liveness probe that kills a healthy app.&lt;/strong&gt; The app starts, the probe fails (too strict, wrong path, too short a delay for a slow start), and the kubelet restarts the container. The events say &lt;code&gt;Liveness probe failed&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The container never really starts.&lt;/strong&gt; A wrong &lt;code&gt;command&lt;/code&gt; or &lt;code&gt;args&lt;/code&gt;, an image built for another CPU architecture, a missing binary. Here the logs are often empty, because nothing ran long enough to write any. &lt;code&gt;describe&lt;/code&gt; and its events carry the message instead.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One extra tip from the docs on finding why a pod failed: set &lt;code&gt;terminationMessagePolicy: FallbackToLogsOnError&lt;/code&gt; on your containers. When a container fails without writing a termination message, Kubernetes then copies the last lines of its log into the pod status, so &lt;code&gt;describe&lt;/code&gt; shows the error even after the logs are gone.&lt;/p&gt;

&lt;h2&gt;
  
  
  The short version
&lt;/h2&gt;

&lt;p&gt;When a pod is in CrashLoopBackOff, this order gets you to the cause quickly, whatever the cause turns out to be:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;kubectl get pods&lt;/code&gt; shows the symptom and the restart count.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kubectl get rs&lt;/code&gt; tells you whether anything is still serving, which decides how urgent this is.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kubectl logs &amp;lt;pod&amp;gt; --previous&lt;/code&gt; gives you the dead container's last words.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;kubectl describe pod &amp;lt;pod&amp;gt;&lt;/code&gt; gives the exit code, the reason and the events.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Then fix the thing the pod was copied from, not the pod, and let &lt;code&gt;rollout status&lt;/code&gt; tell you when it's really done.&lt;/p&gt;

</description>
      <category>debugging</category>
      <category>devops</category>
      <category>go</category>
      <category>kubernetes</category>
    </item>
  </channel>
</rss>
