<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Think in Systems]]></title><description><![CDATA[Microservices need to be agile. This blog is your resource for practical solutions that will make your applications resilient, scalable, and highly adaptable to]]></description><link>https://brontoza.com</link><image><url>https://cdn.hashnode.com/uploads/logos/68c55f26487177cb942af2d0/95697b6c-2ee4-4ad0-8619-ad50486a3e6c.png</url><title>Think in Systems</title><link>https://brontoza.com</link></image><generator>RSS for Node</generator><lastBuildDate>Mon, 20 Apr 2026 08:20:42 GMT</lastBuildDate><atom:link href="https://brontoza.com/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[kubectl proxy vs kubectl port-forward: Access Your Kubernetes Cluster Securely]]></title><description><![CDATA[When working with Kubernetes, developers often need a way to access applications or services running inside the cluster — without exposing them to the public internet.
1. Why Do We Need Local Access to Cluster Resources?
In a secure Kubernetes archit...]]></description><link>https://brontoza.com/kubectl-proxy-vs-kubectl-port-forward</link><guid isPermaLink="true">https://brontoza.com/kubectl-proxy-vs-kubectl-port-forward</guid><category><![CDATA[Port-forward]]></category><category><![CDATA[kubectl-port-forwarding]]></category><category><![CDATA[Kubernetes]]></category><category><![CDATA[kube-proxy]]></category><category><![CDATA[cka]]></category><category><![CDATA[CKS]]></category><category><![CDATA[#learndevops]]></category><category><![CDATA[authentication]]></category><category><![CDATA[TechBlogs]]></category><category><![CDATA[kube-apiserver]]></category><category><![CDATA[rbac]]></category><dc:creator><![CDATA[Anjalisingh Rajput]]></dc:creator><pubDate>Thu, 13 Nov 2025 17:08:34 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/q10VITrVYUM/upload/332f07a4d27d1cb217fed288f760ee5b.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>When working with Kubernetes, developers often need a way to <strong>access applications or services running inside the cluster</strong> — without exposing them to the public internet.</p>
<h2 id="heading-1-why-do-we-need-local-access-to-cluster-resources">1. <strong>Why Do We Need Local Access to Cluster Resources?</strong></h2>
<p>In a secure Kubernetes architecture, most microservices run in an isolated internal network, meaning they are <strong>not directly exposed</strong> to the node's network or the public internet. This isolation is a <strong>fundamental layer of security</strong> and must be preserved, especially for high-security applications.</p>
<p>However, this strict isolation can make it difficult to troubleshoot internal connectivity and application behavior. The solution is to leverage Kubernetes-native tools to create secure, temporary tunnels that eliminate the need for external exposure.</p>
<p>The key advantage of using tools like <code>kubectl port-forward</code> and <code>kubectl proxy</code> is that they require no code modifications to the application container, preserving its immutability and reducing the risk of accidental exposure when debugging <code>highly secure applications</code>.</p>
<h2 id="heading-2-prerequisite-establishing-cluster-trust">2. Prerequisite: Establishing Cluster Trust</h2>
<p>First verifies that you have the necessary <strong>authentication (kubeconfig)</strong> and <strong>authorization (RBAC permissions)</strong> required for accessing the cluster. You must be able to successfully run a basic command (e.g., kubectl get nodes) from the machine where you intend to run <code>kubectl port-forward</code> or <code>kubectl proxy</code>.</p>
<h2 id="heading-3-what-is-kubectl-proxy">3. What is <code>kubectl proxy</code>?</h2>
<p><code>kubectl proxy</code> acts as an HTTP reverse proxy between your local machine and the Kubernetes API server.<br />It enables you to access any Kubernetes resource exposed by the API server — including <strong>Pods</strong>, <strong>Services</strong>, and other <strong>API endpoints</strong> — directly from your local host.</p>
<pre><code class="lang-plaintext">kubectl proxy
</code></pre>
<h4 id="heading-how-it-works">How it works</h4>
<p><strong>1. Local HTTP server start</strong> – <code>kubectl proxy</code> starts a <strong>local HTTP server</strong> on your machine (by default at <a target="_blank" href="http://localhost:8001">http://localhost:8001</a>).</p>
<p><strong>2. Authentication with API server</strong> – The proxy authenticates using your <strong>kubeconfig credentials</strong>, ensuring secure communication with the <strong>Kubernetes API server</strong>.</p>
<p><strong>3. Request forwarding</strong> – When you make a local HTTP request (e.g., <a target="_blank" href="http://localhost:8001/api/">http://localhost:8001/api/</a>...), the proxy securely forwards it to the <strong>Kubernetes API server</strong> over <strong>HTTPS</strong>.</p>
<p><strong>4. API server processing</strong> – The <strong>API server</strong> receives the request, interacts with the appropriate Kubernetes resources (such as Pods, Services, Deployments or etc..), and prepares the response.</p>
<p><strong>5. Response delivery</strong> – The <strong>proxy</strong> sends the API server’s response back to your local machine, making it appear as if you’re directly interacting with the cluster’s REST API from <a target="_blank" href="http://localhost">localhost</a>.</p>
<p><strong>6.Traffic flow</strong> – <strong>Local machine → kubectl proxy (HTTP server) → API server → Kubernetes resource → API server → kubectl proxy → Local machine</strong></p>
<pre><code class="lang-plaintext"># You’ll see all the Pods in the default namespace directly fetched via the API server, not by connecting to the Pod network.
http://localhost:8001/api/v1/namespaces/default/pods

# To access a services
http://localhost:8001/api/v1/namespaces/&lt;namespace&gt;/services/&lt;service-name&gt;:&lt;port-name&gt;/proxy/
http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/
</code></pre>
<pre><code class="lang-plaintext">## Security aspects

# Most Explicit (Secure): Identical to the default behavior. Used to ensure the proxy is never accidentally exposed by other system configurations.
kubectl proxy --address=127.0.0.1 --accept-hosts='^127\.0\.0\.1$'

# Expose API to anyone who can reach your system.
kubectl proxy --address=0.0.0.0 --port=8001 

#Dangerous(Insecure): Binds to 0.0.0.0 (all network interfaces) and accepts requests from any host (^*\$).
kubectl proxy --address=0.0.0.0 --port=8001 --accept-hosts='^*$'
</code></pre>
<h2 id="heading-4-what-is-kubectl-port-forward">4. What is <code>kubectl port-forward</code>?</h2>
<p><code>kubectl port-forward</code> establishes a <strong>TCP tunnel</strong> that allows you to connect directly from your local machine to a Pod’s or Service’s port.This method provides <strong>application-specific access</strong> for debugging or testing purposes, without exposing the application externally through a LoadBalancer or Ingress.<br />You can perform port forwarding on <strong>Pods</strong>, <strong>Services</strong>, <strong>Deployments</strong>, <strong>StatefulSets</strong>, and <strong>ReplicaSets</strong>.</p>
<pre><code class="lang-plaintext">kubectl port-forward pod/&lt;POD_NAME&gt; &lt;LOCAL_PORT&gt;:&lt;CONTAINER_PORT&gt;
kubectl port-forward service/&lt;SERVICE_NAME&gt; &lt;LOCAL_PORT&gt;:&lt;CONTAINER_PORT&gt;
kubectl port-forward deployments/&lt;DEPLOYMENT_NAME&gt; &lt;LOCAL_PORT&gt;:&lt;CONTAINER_PORT&gt;
kubectl port-forward statefulsets/&lt;STATEFULSET_NAME&gt; &lt;LOCAL_PORT&gt;:&lt;CONTAINER_PORT&gt;
</code></pre>
<h4 id="heading-how-it-works-1"><strong>How it works</strong></h4>
<p><strong>1. Connection to API server</strong> – kubectl connects securely to the <strong>Kubernetes API server</strong> using your kubeconfig credentials, similar to how <code>kubectl proxy</code> operates.</p>
<p><strong>2. Data stream to kubelet</strong> – The <strong>API server</strong> identifies the node where the target Pod is running and securely streams the data to the <strong>kubelet</strong> on that node.</p>
<p><strong>3. Pod connection and tunneling</strong> – The <strong>kubelet</strong> opens a connection to the Pod’s specified port and tunnels the traffic back through the same API server channel to your local machine.</p>
<p><strong>4. Local access established</strong> – You can now access the Pod or Service locally through the forwarded port, without exposing it externally or modifying cluster networking.</p>
<p><strong>5.Traffic flow</strong> – through this secure path: <strong>Local machine → API server → kubelet → Pod.</strong></p>
<pre><code class="lang-plaintext">kubectl run flask-app --image=python:3.11 --port=5000
kubectl port-forward pod/flask-app 5000:5000
## Visit http://localhost:5000

# It takes random port on local machine
kubectl port-forward pod/my-pod :5000
kubectl port-forward --address 0.0.0.0 pod/my-pod 8888:5000

#To Run kubectl port forward command in background
kubectl port-forward pod/flask-app 5000:5000  &amp;
</code></pre>
<h2 id="heading-5-security-note-binding-to-0000">5. Security Note — Binding to <code>0.0.0.0</code></h2>
<p>By default, both <code>kubectl proxy</code> and <code>kubectl port-forward</code> bind to <strong>127.0.0.1</strong>, making them accessible <strong>only from your local machine</strong>.</p>
<p>If you manually bind them to <strong>0.0.0.0</strong>, they become accessible from <strong>any network interface</strong> — not just <a target="_blank" href="http://localhost">localhost</a>.<br />While this can be helpful for remote debugging, it introduces a <strong>major security risk</strong>: Anyone on your network could potentially access your cluster through the open proxy or tunnel, especially if your <strong>kubeconfig</strong> remains active.</p>
<ul>
<li><p><strong>Best Practice:</strong></p>
<ul>
<li><p>Keep the binding to <strong>127.0.0.1</strong> (default).</p>
</li>
<li><p>Only bind to <strong>0.0.0.0</strong> if you have:</p>
<ul>
<li><p>Strong <strong>network isolation</strong> (e.g., VPN or private subnet).</p>
</li>
<li><p>Proper <strong>authentication and authorization</strong> controls in place.</p>
</li>
<li><p>Strict <strong>firewall rules</strong> limiting who can connect.</p>
</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2 id="heading-6-authentication-amp-authorization">6. Authentication &amp; Authorization</h2>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Aspect</strong></td><td><code>kubectl proxy</code></td><td><code>kubectl port-forward</code></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Authentication Type</strong></td><td>Every request goes through the <strong>API server</strong></td><td>Authenticated <strong>once when the tunnel is established</strong></td></tr>
<tr>
<td><strong>Credentials Used</strong></td><td><strong>Kubeconfig</strong> (token / certificate / OIDC)</td><td><strong>Kubeconfig</strong> (token / certificate / OIDC)</td></tr>
<tr>
<td><strong>RBAC Enforcement</strong></td><td>Enforced on <strong>each API call</strong></td><td>Enforced <strong>once at tunnel creation</strong></td></tr>
<tr>
<td><strong>Scope of Access</strong></td><td><strong>All cluster API resources</strong></td><td><strong>Specific Pod or Service</strong></td></tr>
<tr>
<td><strong>Security Strength</strong></td><td>Strong, per-request authentication</td><td>Strong, encrypted tunnel between local machine and Pod</td></tr>
<tr>
<td><strong>Stability / Reliability</strong></td><td>Very stable, persistent access</td><td>Can <strong>break occasionally</strong> due to network issues or Pod restarts</td></tr>
<tr>
<td><strong>Response Data</strong></td><td>Returns <strong>raw HTTP/API responses</strong> (JSON/YAML), e.g., resource lists, metrics, logs via API</td><td>Returns <strong>TCP stream or application data</strong> directly from the Pod (raw bytes, HTTP, database protocol, etc.)</td></tr>
</tbody>
</table>
</div><h2 id="heading-7-when-to-use-which">7. When to Use Which</h2>
<p><strong>For Local Testing and Debugging</strong> – Use <code>kubectl proxy</code> or <code>port-forward</code> to test applications, APIs, or services running inside the cluster from your local machine without exposing them externally.</p>
<p><strong>For Accessing Cluster APIs (HTTP Traffic)</strong> – Use <code>kubectl proxy</code> when you need <strong>HTTP-based access</strong> to Kubernetes resources, dashboards, or metrics APIs.</p>
<p><strong>For Application-Specific Access (TCP Traffic)</strong> – Use <code>kubectl port-forward</code> to connect directly to a Pod or Service for <strong>TCP-based access</strong>, such as web apps, databases, or message queues like Kafka, in a development or testing environment.</p>
<p><strong>For Short-Lived Connections</strong> – Ideal for temporary operations like inspecting logs, running queries, or testing functionality, where permanent exposure is not required.</p>
<p><strong>For Secure Local Access</strong> – Both commands keep your traffic encrypted and access restricted to your kubeconfig permissions, making them safe for local development.</p>
<h2 id="heading-8-when-not-to-use">8. When not to Use</h2>
<p><strong>In Production</strong> – These are temporary connections that break when the command or terminal is closed. Use Ingress, LoadBalancer, or proper service exposure instead.</p>
<p><strong>For Automation or CI/CD</strong> – Port-forwarding can hang or fail randomly. Use ClusterIP or internal services for reliable automation.</p>
<p><strong>For Heavy Traffic</strong> – All traffic passes through the API server, which can cause latency and performance bottlenecks. Use proper network routing or service exposure instead.</p>
<p><strong>For Long-Running Streams</strong> – Database or message queue connections, such as PostgreSQL or Kafka, can drop easily. Use a VPN, Bastion host, or persistent service exposure instead.</p>
<p><strong>On Shared Machines</strong> – Anyone with access to the machine could reach your forwarded ports. Keep bindings local (127.0.0.1) and secure your environment.</p>
<p><strong>Without Access Control</strong> – Running with admin kubeconfig may expose sensitive APIs. Enforce RBAC, limit privileges, and enable audit logging.</p>
<h2 id="heading-question-of-the-day">💡 Question of the Day:</h2>
<p>If you had to securely expose a Kubernetes service for your team without using Ingress or LoadBalancer, what would be your preferred approach and why?</p>
<blockquote>
<h3 id="heading-secure-local-temporary-debug-smart-expose-smart">Secure, local, temporary – debug smart, expose smart.</h3>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[Distroless Containers: Why They Are a Game-Changer for DevOps Security]]></title><description><![CDATA[Introduction
As DevOps engineers, we constantly battle a security game of whack-a-mole. Every week, a new vulnerability is discovered in an OS package we don't even use, forcing us to rebuild and redeploy our container images. Let's stop making your ...]]></description><link>https://brontoza.com/distroless-containers-why-they-are-a-game-changer-for-devops-security</link><guid isPermaLink="true">https://brontoza.com/distroless-containers-why-they-are-a-game-changer-for-devops-security</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[Docker]]></category><category><![CDATA[containerization]]></category><category><![CDATA[distroless]]></category><category><![CDATA[distroless image]]></category><category><![CDATA[Kubernetes Security]]></category><category><![CDATA[docker build ]]></category><category><![CDATA[Microservices]]></category><dc:creator><![CDATA[Anjalisingh Rajput]]></dc:creator><pubDate>Thu, 18 Sep 2025 03:14:17 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/FnA5pAzqhMM/upload/cea37092fe212f19fe6f90e3cf297db7.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2 id="heading-introduction">Introduction</h2>
<p>As DevOps engineers, we constantly battle a security game of whack-a-mole. Every week, a new vulnerability is discovered in an OS package we don't even use, forcing us to rebuild and redeploy our container images. <strong>Let's stop making your container a virtual machine; make it a specific, purposeful application.</strong> This is where <code>distroless</code> containers enter the picture. By stripping away everything but your application and its dependencies, they offer a direct path to a smaller, more secure, and more efficient production environment. This concept, which focuses on creating minimal and secure images, was pioneered by Google to reduce the attack surface of containerized applications.</p>
<h3 id="heading-1-the-core-principle-less-is-more">1. The Core Principle: Less is More</h3>
<p>Traditional container images (like those based on Ubuntu or Debian) include a full Linux distribution, complete with a shell, package manager (<code>apt</code> or <code>yum</code>), and hundreds of system libraries. While this is convenient for debugging, every one of those included packages is a potential entry point for an attacker. A <code>distroless</code> container, on the other hand, contains only your application code and its immediate runtime dependencies.</p>
<h3 id="heading-2-reduced-attack-surface-amp-fewer-cves">2. Reduced Attack Surface &amp; Fewer CVEs</h3>
<p>This is the single biggest security win. With a traditional image, a vulnerability scanner will flag dozens or even hundreds of <strong>CVEs (Common Vulnerabilities and Exposures)</strong> from packages you don't even use. With a <code>distroless</code> image, the number of CVEs drops dramatically, often to zero. Since there's less code, there are fewer bugs and fewer vulnerabilities for an attacker to exploit.</p>
<p>Ready for the proof? A simple <strong>Trivy</strong> scan reveals the security power of a <strong>distroless</strong> container.</p>
<h4 id="heading-non-distroless-image-scanning">Non-Distroless Image Scanning</h4>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758158127880/2f15328a-3abb-4f2a-884b-9a152f21a083.png" alt class="image--center mx-auto" /></p>
<h4 id="heading-distroless-image-scanning">Distroless Image Scanning</h4>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758158154842/fbfac549-8ef3-4395-bf09-633f20686614.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-3-no-shell-no-problem">3. No Shell, No Problem</h3>
<p>One of the most significant security benefits is the <strong>absence of a shell</strong>. If an attacker gains access to your container, they can't simply <code>kubectl exec</code> into it and start running commands. They have no shell to use. This prevents "<strong>living off the land</strong>" attacks where an attacker uses pre-installed system binaries to move laterally within your cluster.</p>
<h3 id="heading-4-no-package-manager">4. No Package Manager</h3>
<p>An attacker who compromises a traditional container could use the built-in package manager to install more tools. With a <code>distroless</code> image, this is impossible. The image is immutable, and no new software can be added at runtime, which greatly limits what an attacker can do after an initial breach.</p>
<h3 id="heading-5-the-size-amp-performance-benefit">5. The Size &amp; Performance Benefit</h3>
<p>While security is the primary driver, a significant secondary benefit is <strong>image size</strong>. <code>distroless</code> images are often an order of magnitude smaller than their full-distribution counterparts. Smaller images mean faster downloads and faster pod startup times in a scaled Kubernetes cluster.</p>
<h3 id="heading-6-multi-stage-builds">6. <strong>Multi-Stage Builds</strong></h3>
<p>Please follow the practical demonstration of a distroless image on GitHub: <a target="_blank" href="https://github.com/techxflourish/kubernetes-security-lessons/tree/main/distroless-image/Helloworld">Distroless Practical</a></p>
<p>Here is the some code snippet of that demo.</p>
<pre><code class="lang-go"><span class="hljs-keyword">package</span> main
<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>
<span class="hljs-function"><span class="hljs-keyword">func</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span> {
    fmt.Println(<span class="hljs-string">"Hello, World!"</span>)
}
</code></pre>
<pre><code class="lang-dockerfile"><span class="hljs-comment"># Build stage</span>
<span class="hljs-keyword">FROM</span> golang:<span class="hljs-number">1.21</span>-alpine AS builder

<span class="hljs-keyword">WORKDIR</span><span class="bash"> /app</span>

<span class="hljs-comment"># Copy the Go source code</span>
<span class="hljs-keyword">COPY</span><span class="bash"> app.go .</span>

<span class="hljs-comment"># Build the Go binary (statically linked)</span>
<span class="hljs-keyword">RUN</span><span class="bash"> go build -o helloworld app.go</span>

<span class="hljs-comment"># Final stage: distroless image</span>
<span class="hljs-keyword">FROM</span> gcr.io/distroless/static-debian12:nonroot

<span class="hljs-keyword">WORKDIR</span><span class="bash"> /app</span>

<span class="hljs-comment"># Copy the statically built binary from the builder</span>
<span class="hljs-keyword">COPY</span><span class="bash"> --from=builder /app/helloworld .</span>

<span class="hljs-comment"># Run the binary</span>
<span class="hljs-keyword">ENTRYPOINT</span><span class="bash"> [<span class="hljs-string">"/app/helloworld"</span>]</span>
</code></pre>
<p>You might be asking, "Why don't we just start with a distroless image?" The reason is that we require some utilities, like a compiler and package manager, during the application's build time. For that, we'll use a minimal image in the first stage. But as you'll see in the next stage, we are only passing the compiled file to the <code>distroless</code> image, leaving all the messy build tools behind.</p>
<h3 id="heading-7-minimal-vs-distroless-a-critical-distinction">7. Minimal vs. Distroless: A Critical Distinction💡</h3>
<p>While many people use the terms "minimal" and "distroless" interchangeably, there is an important difference that is crucial for container security.</p>
<p>A <strong>minimal image</strong> (like <code>alpine</code> or <code>slim</code>) is a simplified Linux distribution. It's designed to be small but still includes a shell, a package manager (<code>apk</code>, <code>apt</code>), and essential utilities. It's like a tiny Linux machine.</p>
<p>A <strong>distroless image</strong>, on the other hand, is not a Linux distribution. It contains only your application and its direct runtime dependencies, like <code>libc</code> and <code>ca-certificates</code>. It's simply a file system with the bare essentials needed to run your code, without a shell or package manager.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1758163709549/7a2b5e2d-bf1b-46b6-b33d-75124bcd3761.png" alt class="image--center mx-auto" /></p>
<h3 id="heading-8-the-trade-off-debugging">8. The Trade-Off: Debugging</h3>
<p>Since you can't <code>kubectl exec</code> into a <code>distroless</code> container, you need a different mental model and tools. To learn the best way to troubleshoot, <a target="_blank" href="https://techxflourish.com/the-ultimate-guide-to-kubernetes-troubleshooting">the-ultimate-guide-to-kubernetes-troubleshooting</a></p>
<blockquote>
<p>Clean, lean, and mean.</p>
</blockquote>
]]></content:encoded></item><item><title><![CDATA[The Ultimate Guide to Kubernetes Troubleshooting]]></title><description><![CDATA[Introduction
A critical pod fails. Your alerts are firing. What's next? Every DevOps/SRE engineer needs a clear plan to handle cluster issues. This guide provides a systematic strategy and the essential tools to diagnose any problem, from pod health ...]]></description><link>https://brontoza.com/the-ultimate-guide-to-kubernetes-troubleshooting</link><guid isPermaLink="true">https://brontoza.com/the-ultimate-guide-to-kubernetes-troubleshooting</guid><category><![CDATA[SRETrobleshooting]]></category><category><![CDATA[Kubernetes]]></category><category><![CDATA[Kubernetes-troubleshooting]]></category><category><![CDATA[#kubernetes #container ]]></category><category><![CDATA[kubernetes logging]]></category><category><![CDATA[kubernetes cloud services]]></category><category><![CDATA[Devops]]></category><category><![CDATA[debugging]]></category><category><![CDATA[containers]]></category><category><![CDATA[SRE devops]]></category><dc:creator><![CDATA[Anjalisingh Rajput]]></dc:creator><pubDate>Tue, 16 Sep 2025 11:23:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/stock/unsplash/KjoMXyZ4S2g/upload/fcd3535b62b41c7cdaba490e76557beb.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3 id="heading-introduction"><strong>Introduction</strong></h3>
<p>A critical pod fails. Your alerts are firing. What's next? Every DevOps/SRE engineer needs a clear plan to handle cluster issues. This guide provides a systematic strategy and the essential tools to diagnose any problem, from pod health to the control plane.</p>
<h2 id="heading-the-first-steps-observing-the-problem">The First Steps: Observing the Problem</h2>
<p>When a pod is failing, your first task is to become a detective. You need to gather clues and observations before you jump to conclusions. Fortunately, Kubernetes provides a suite of essential commands for this initial investigation. Mastering these fundamentals will save you a lot of time and frustration.</p>
<h3 id="heading-1-the-overview-kubectl-get-pods"><strong>1. The Overview: kubectl get pods</strong></h3>
<p>The most basic used command is kubectl get pods. It provides a quick, high-level snapshot of your pods’ current state.</p>
<pre><code class="lang-bash">kubectl get pods -n &lt;namespace&gt;
</code></pre>
<p>By running this, you can immediately see:</p>
<ul>
<li><p>The pod's STATUS (Running, Pending, CrashLoopBackOff, etc.).</p>
</li>
<li><p>The number of times the pod has RESTARTED.</p>
</li>
<li><p>How long the pod has been running (AGE).</p>
</li>
</ul>
<p>A pod in a CrashLoopBackOff state is a clear sign of a repeated failure, while a pod stuck in Pending indicates a scheduling issue.</p>
<h3 id="heading-2-the-details-kubectl-describe-pod"><strong>2. The Details: kubectl describe pod</strong></h3>
<p>Once you have a suspicious-looking pod, the next step is to run a more detailed inspection with kubectl describe pod.</p>
<pre><code class="lang-bash">kubectl describe pod &lt;pod-name&gt; -n &lt;namespace&gt;
</code></pre>
<p>This command provides a wealth of information, including:</p>
<ul>
<li><p><strong>Events:</strong> A list of recent events related to the pod, which can show you exactly why a container failed to start or why a volume couldn't be mounted.</p>
</li>
<li><p><strong>Containers:</strong> Details about the containers within the pod, including their image, state, and restartCount.</p>
</li>
<li><p><strong>Status &amp; Exit Reason:</strong> Details about the containers within the pod, their image, and most importantly, the State and Exit Code if a container has terminated. An exit code of 1 or a specific error message can be your first solid clue.</p>
</li>
</ul>
<pre><code class="lang-plaintext">Events:
  Type     Reason     Age                  From               Message
  ----     ------     ----                 ----               -------
  Normal   Scheduled  4m1s                 default-scheduler  Successfully assigned my-app-pod to node-01
  Normal   Pulling    4m                   kubelet            Pulling image "my-app:v1"
  Normal   Pulled     3m59s                kubelet            Successfully pulled image "my-app:v1" in 987ms
  Normal   Created    3m59s                kubelet            Created container my-app-container
  Normal   Started    3m59s                kubelet            Started container my-app-container
  Warning  Failed     3m1s (x3 over 3m1s)  kubelet            Failed to pull image "my-app:v2": rpc error: code = NotFound
</code></pre>
<h3 id="heading-3-the-output-kubectl-logs">3. <strong>The Output: kubectl logs</strong></h3>
<p>The kubectl logs command is your window into what's happening inside the container itself.</p>
<pre><code class="lang-bash">kubectl logs &lt;pod-name&gt; -n &lt;namespace&gt;
</code></pre>
<p>By default, this shows you the standard output and error streams from your container. It's the go-to command for finding application-level errors, startup failures, or unexpected behavior.</p>
<h2 id="heading-advanced-pod-troubleshooting-when-a-pod-is-running-but-not-responding">Advanced Pod Troubleshooting: When a Pod is Running but Not Responding</h2>
<p>What do you do when kubectl get pods shows a pod is Running, but your application still isn't working?</p>
<h3 id="heading-1-the-first-test-is-the-application-itself-unresponsive"><strong>1. The First Test: Is the Application Itself Unresponsive?</strong></h3>
<p>The quickest way to check if your application is simply hung is by trying to access it from a shell inside the container. This tests the application directly, bypassing the Kubernetes service layer and network policies.</p>
<p>Use <code>kubectl exec</code> to run a simple connectivity test.</p>
<pre><code class="lang-bash">kubectl <span class="hljs-built_in">exec</span> -it &lt;pod-name&gt; -n &lt;namespace&gt; -- curl localhost:&lt;app-port&gt;
</code></pre>
<p>If the <code>curl</code> command fails to connect or gets a timeout, you know the problem is within the container itself. If it returns a correct response, the issue is likely with the Kubernetes networking or service configuration.</p>
<h3 id="heading-2-the-network-check-can-the-pod-reach-out"><strong>2. The Network Check: Can the Pod Reach Out?</strong></h3>
<p>If the pod is supposed to be making external connections but isn't, you need to check its network connectivity. Since many images don't contain standard network tools, you can use kubectl exec to run a few commands if available.</p>
<ul>
<li><p><strong>DNS Resolution:</strong> Use <code>nslookup</code> or <code>dig</code> to check if the pod can resolve a service name or an external domain.</p>
</li>
<li><p><strong>Connectivity:</strong> Use <code>ping</code>, <code>nc</code>, or <code>curl</code> to test connectivity to a service, database, or external API.</p>
</li>
</ul>
<p>For example, to check DNS resolution for a service:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># If the service is in the same namespace as the pod</span>
kubectl <span class="hljs-built_in">exec</span> -it &lt;pod-name&gt; -n &lt;namespace&gt; -- nslookup &lt;service-name&gt;

<span class="hljs-comment"># If the service is in a different namespace,</span>
<span class="hljs-comment"># use the fully qualified domain name (FQDN) for reliability.</span>
kubectl <span class="hljs-built_in">exec</span> -it &lt;pod-name&gt; -n &lt;namespace&gt; -- nslookup &lt;service-name&gt;.&lt;service-namespace&gt;.svc.cluster.local
</code></pre>
<p>If these tests fail, it points to a network configuration issue (like a misconfigured DNS or Network Policy) rather than an application-level bug.</p>
<h3 id="heading-3-process-and-resource-checks"><strong>3. Process and Resource Checks</strong></h3>
<p>Even if the application is reachable, its internal state might be unhealthy. You can use process inspection tools to see if a process has a high CPU or is hung.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Check running processes and their status</span>
kubectl <span class="hljs-built_in">exec</span> -it &lt;pod-name&gt; -- ps aux

<span class="hljs-comment"># Check resource usage (if available in the image)</span>
kubectl <span class="hljs-built_in">exec</span> -it &lt;pod-name&gt; -- top
</code></pre>
<p>These commands give you a live view of the pod's workload and can help identify bottlenecks or application deadlocks.</p>
<h3 id="heading-4-filesystem-and-configuration-inspection"><strong>4. Filesystem and Configuration Inspection</strong></h3>
<p>Sometimes a pod fails because a required file is missing or a volume has the wrong permissions.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Check if a mount point is full on the pod</span>
kubectl <span class="hljs-built_in">exec</span> -it &lt;pod-name&gt; -- df -h

<span class="hljs-comment"># List files and check permissions</span>
kubectl <span class="hljs-built_in">exec</span> -it &lt;pod-name&gt; -- ls -la /app/config

<span class="hljs-comment"># View the contents of a configuration file</span>
kubectl <span class="hljs-built_in">exec</span> -it &lt;pod-name&gt; -- cat /app/config/settings.yaml
</code></pre>
<p>These commands help you quickly rule out common configuration and filesystem-related issues.</p>
<h3 id="heading-5-the-problem-with-kubectl-exec"><strong>5. The Problem with kubectl exec</strong></h3>
<blockquote>
<p>While <code>kubectl exec</code> is a familiar command, its significant flaw is that it only works on containers that have a shell and tools. This makes it impossible for troubleshooting secure, distroless containers.</p>
</blockquote>
<p><strong>The Solution:</strong> kubectl debug</p>
<p>To solve this, we can use kubectl debug to inject a new, ephemeral container into the pod that contains the tools we need. The command to do this is as follows:</p>
<p>This below command adds a temporary 'busybox' container to your pod and shares the process namespace, allowing you to debug the original container.</p>
<pre><code class="lang-bash">
kubectl debug -it &lt;pod-name&gt; --image=busybox --share-processes --container=debugger
</code></pre>
<p>In this command:</p>
<ul>
<li><p>--image=busybox tells Kubernetes to use a standard debug image that contains essential Linux utilities like ps and ls.</p>
</li>
<li><p>--share-processes is a critical flag that allows the new debugger container to see and interact with the processes running in the original application container.</p>
</li>
<li><p>--container=debugger gives our temporary debugging container a clear, identifiable name.</p>
</li>
</ul>
<p>Once the command runs, you will be dropped into a shell inside the busybox container, where you can run commands like ps aux to inspect the processes of the main application container.</p>
<blockquote>
<p>Troubleshoot smarter. Not harder.</p>
</blockquote>
]]></content:encoded></item></channel></rss>