<?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: Devam Parikh</title>
    <description>The latest articles on DEV Community by Devam Parikh (@devamparikh).</description>
    <link>https://dev.to/devamparikh</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%2F1110609%2Fd7405a68-8311-4b31-847d-522a6b0b0c95.jpeg</url>
      <title>DEV Community: Devam Parikh</title>
      <link>https://dev.to/devamparikh</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/devamparikh"/>
    <language>en</language>
    <item>
      <title>GitOps Without Surprises: Generate, Review, Then Reconcile</title>
      <dc:creator>Devam Parikh</dc:creator>
      <pubDate>Tue, 14 Jul 2026 14:29:59 +0000</pubDate>
      <link>https://dev.to/devamparikh/gitops-without-surprises-generate-review-then-reconcile-296c</link>
      <guid>https://dev.to/devamparikh/gitops-without-surprises-generate-review-then-reconcile-296c</guid>
      <description>&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%2Fk0zy86kglbgp3uclyr2n.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%2Fk0zy86kglbgp3uclyr2n.png" alt="Rendered manifest workflow" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;GitOps is supposed to make production changes boring: review a pull request, merge it, and let the controller reconcile the desired state.&lt;/p&gt;

&lt;p&gt;But there is a subtle gap in many Kubernetes delivery flows.&lt;/p&gt;

&lt;p&gt;When a repository stores Helm charts, Helm values, Kustomize bases, or overlays, Git often contains the &lt;strong&gt;inputs&lt;/strong&gt; to the desired state. The actual Kubernetes objects are created later, usually inside Argo CD at sync time.&lt;/p&gt;

&lt;p&gt;That is convenient. It is also where surprises hide.&lt;/p&gt;

&lt;h2&gt;
  
  
  The problem: Git may not show what Kubernetes will receive
&lt;/h2&gt;

&lt;p&gt;Helm and Kustomize are excellent authoring tools. They reduce duplication, let teams share common patterns, and make multi-environment delivery manageable.&lt;/p&gt;

&lt;p&gt;The problem is not the tools. The problem is where rendering happens.&lt;/p&gt;

&lt;p&gt;If rendering happens only inside the GitOps controller, reviewers may approve a change without seeing the exact final YAML. A one-line values change can modify a Deployment, Service, ConfigMap, HPA, RBAC rule, or annotation in ways that are not obvious from the pull request.&lt;/p&gt;

&lt;p&gt;That hurts in a few places:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reviews focus on abstraction changes, not final Kubernetes objects.&lt;/li&gt;
&lt;li&gt;Audits require re-rendering with matching tool versions and inputs.&lt;/li&gt;
&lt;li&gt;Rollbacks are harder to reason about.&lt;/li&gt;
&lt;li&gt;Incident debugging starts with “what did Argo CD actually apply?”&lt;/li&gt;
&lt;li&gt;Policy and API deprecation checks happen later than they should.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For platform teams, this becomes painful as more teams and environments onboard onto the same GitOps platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  The pattern: generate, review, then reconcile
&lt;/h2&gt;

&lt;p&gt;A safer GitOps flow looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Developers keep authoring with Helm, Helmfile, or Kustomize.&lt;/li&gt;
&lt;li&gt;CI renders the final Kubernetes manifests.&lt;/li&gt;
&lt;li&gt;CI commits the rendered output back to the pull request branch.&lt;/li&gt;
&lt;li&gt;Reviewers inspect the exact YAML diff.&lt;/li&gt;
&lt;li&gt;Policy, security, and API deprecation checks run against rendered objects.&lt;/li&gt;
&lt;li&gt;Argo CD reconciles from &lt;code&gt;generated-manifest/&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In other words:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Author with abstractions, but reconcile reviewed YAML.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is usually called the &lt;strong&gt;rendered manifests pattern&lt;/strong&gt; or &lt;strong&gt;hydrated manifests pattern&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this works well with Argo CD
&lt;/h2&gt;

&lt;p&gt;Argo CD ultimately applies Kubernetes manifests. Even when you point Argo CD at a Helm chart, Argo CD renders that chart and applies the resulting YAML.&lt;/p&gt;

&lt;p&gt;The rendered-manifest pattern moves that rendering step earlier so humans and automation can inspect the result before reconciliation.&lt;/p&gt;

&lt;p&gt;A deployment repository can look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;k8s/
  demo/
    demo-api/
      Chart.yaml
      values.yaml
      staging-nam-values.yaml
      production-nam-values.yaml

generated-manifest/
  staging/
    nam/
      demo/
        demo-api/
          manifest.lock.yaml
  production/
    nam/
      demo/
        demo-api/
          manifest.lock.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Argo CD then points to the rendered path:&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;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;argoproj.io/v1alpha1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Application&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;demo-api-staging&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;project&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;
  &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;repoURL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://github.com/your-org/your-deploy-repo.git&lt;/span&gt;
    &lt;span class="na"&gt;targetRevision&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;generated-manifest/staging/nam/demo/demo-api&lt;/span&gt;
  &lt;span class="na"&gt;destination&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://kubernetes.default.svc&lt;/span&gt;
    &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;demo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now a pull request does not only show a values file change. It also shows the resulting &lt;code&gt;manifest.lock.yaml&lt;/code&gt; change.&lt;/p&gt;

&lt;p&gt;That is the part reviewers actually need.&lt;/p&gt;

&lt;h2&gt;
  
  
  A reusable GitHub Action for this flow
&lt;/h2&gt;

&lt;p&gt;I created a reusable GitHub Action for this pattern:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Devamparikh/gitops-render-manifests-action" rel="noopener noreferrer"&gt;https://github.com/Devamparikh/gitops-render-manifests-action&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;helm&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;helmfile&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;kustomize&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;none&lt;/code&gt; for repositories that already store raw YAML&lt;/li&gt;
&lt;li&gt;optional shared-directory detection&lt;/li&gt;
&lt;li&gt;optional commit-back to the pull request branch&lt;/li&gt;
&lt;li&gt;optional Kubernetes API deprecation checks with Pluto&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A basic caller workflow looks like this:&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;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Render Kubernetes manifests&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;paths&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;k8s/**"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;common-values/**"&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;.github/workflows/render-manifests.yaml"&lt;/span&gt;

&lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;
  &lt;span class="na"&gt;pull-requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;render&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Checkout pull request branch&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ github.event.pull_request.head.ref }}&lt;/span&gt;
          &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
          &lt;span class="na"&gt;fetch-depth&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Render manifests&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Devamparikh/gitops-render-manifests-action@v0&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;package_manager&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;helm&lt;/span&gt;
          &lt;span class="na"&gt;shared_dirs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;common-values&lt;/span&gt;
          &lt;span class="na"&gt;target_k8s_version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1.33.0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Kustomize:&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="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Render manifests&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Devamparikh/gitops-render-manifests-action@v0&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;package_manager&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kustomize&lt;/span&gt;
    &lt;span class="na"&gt;kustomize_load_restrictor_none&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Helmfile:&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="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Render manifests&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Devamparikh/gitops-render-manifests-action@v0&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;package_manager&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;helmfile&lt;/span&gt;
    &lt;span class="na"&gt;shared_dirs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;common-values,charts&lt;/span&gt;
    &lt;span class="na"&gt;parallel&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;4"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The review experience changes
&lt;/h2&gt;

&lt;p&gt;Before rendered manifests, a reviewer might see:&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;replicaCount&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After rendered manifests, the reviewer also sees:&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;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apps/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Deployment&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;demo-api&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;replicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That sounds small, but it changes the conversation.&lt;/p&gt;

&lt;p&gt;Reviewers can ask:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Did this change the expected namespace?&lt;/li&gt;
&lt;li&gt;Did the image tag move?&lt;/li&gt;
&lt;li&gt;Did RBAC expand?&lt;/li&gt;
&lt;li&gt;Did resource requests change?&lt;/li&gt;
&lt;li&gt;Did labels, annotations, selectors, or topology rules change?&lt;/li&gt;
&lt;li&gt;Will this API still work on the target Kubernetes version?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those are production questions. They deserve to be answered before Argo CD syncs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trade-offs
&lt;/h2&gt;

&lt;p&gt;This pattern is not free.&lt;/p&gt;

&lt;p&gt;It adds generated files to Git. It can make pull requests larger. It requires CI to have the right rendering tools. It also requires a clear repository contract so teams know where source inputs live and where generated manifests go.&lt;/p&gt;

&lt;p&gt;You should also be careful with secrets. Rendered manifests should not commit plaintext secrets. Use External Secrets Operator, Sealed Secrets, SOPS, secret references, or another secret-management pattern that fits your organization.&lt;/p&gt;

&lt;p&gt;The pattern is worth considering when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;multiple teams deploy through a shared platform,&lt;/li&gt;
&lt;li&gt;reviewers need stronger auditability,&lt;/li&gt;
&lt;li&gt;regulated environments need explicit change records,&lt;/li&gt;
&lt;li&gt;Argo CD sync-time rendering has caused surprises,&lt;/li&gt;
&lt;li&gt;you want policy and deprecation checks before sync,&lt;/li&gt;
&lt;li&gt;you want ApplicationSets to reconcile plain generated YAML.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For very small teams or simple services, direct Helm or Kustomize in Argo CD may still be enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this fits with Source Hydrator and other tools
&lt;/h2&gt;

&lt;p&gt;Argo CD Source Hydrator is making hydrated manifests a more first-class workflow inside Argo CD itself. Kargo and OCI-based promotion patterns can also solve parts of this problem, especially around environment promotion.&lt;/p&gt;

&lt;p&gt;The action in this post is intentionally simple: it gives teams a CI-based way to try the pattern without changing their entire platform.&lt;/p&gt;

&lt;p&gt;Start small. Render one service. Review the manifest diff. Point Argo CD at the generated path. Then decide whether the pattern should become part of your platform contract.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;GitOps is not just “put YAML in Git.”&lt;/p&gt;

&lt;p&gt;The stronger promise is this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The desired state that humans review is the same desired state the controller reconciles.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is the heart of GitOps without surprises.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>kubernetes</category>
      <category>gitops</category>
      <category>argocd</category>
    </item>
    <item>
      <title>When the Agent Is Wrong: Surface Real Kubernetes Errors, Not Model Guesses</title>
      <dc:creator>Devam Parikh</dc:creator>
      <pubDate>Tue, 14 Jul 2026 10:05:02 +0000</pubDate>
      <link>https://dev.to/devamparikh/when-the-agent-is-wrong-surface-real-kubernetes-errors-not-model-guesses-5ank</link>
      <guid>https://dev.to/devamparikh/when-the-agent-is-wrong-surface-real-kubernetes-errors-not-model-guesses-5ank</guid>
      <description>&lt;p&gt;AI agents are good at producing explanations.&lt;/p&gt;

&lt;p&gt;That is useful until the explanation is wrong.&lt;/p&gt;

&lt;p&gt;In Kubernetes operations, a failed tool call often already contains the truth:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error from server (Forbidden): cannot patch resource "deployments/scale"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But if the agent summarizes too aggressively, it may say something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;This may have been blocked by a policy engine or GitOps drift prevention.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That might sound plausible. It might also be completely wrong.&lt;/p&gt;

&lt;p&gt;For operational agents, tool output must be treated as evidence. The model's explanation is secondary.&lt;/p&gt;

&lt;h2&gt;
  
  
  The source of truth
&lt;/h2&gt;

&lt;p&gt;When a Kubernetes tool fails, preserve the real error:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;command or tool name&lt;/li&gt;
&lt;li&gt;target cluster&lt;/li&gt;
&lt;li&gt;namespace&lt;/li&gt;
&lt;li&gt;resource&lt;/li&gt;
&lt;li&gt;Kubernetes API error&lt;/li&gt;
&lt;li&gt;stderr&lt;/li&gt;
&lt;li&gt;exit code&lt;/li&gt;
&lt;li&gt;admission response if present&lt;/li&gt;
&lt;li&gt;RBAC denial if present&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent can summarize this, but it should not replace it with a guess.&lt;/p&gt;

&lt;p&gt;Good:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The scale operation failed because Kubernetes RBAC denied patch access to deployments/scale for the tool service account.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bad:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The scale operation likely failed because GitOps reverted it.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Unless the tool output proves GitOps was involved, that is speculation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Kubernetes failures agents misread
&lt;/h2&gt;

&lt;h3&gt;
  
  
  RBAC denial
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cannot patch resource "deployments/scale"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is not an application failure. It is not a model failure. It is not necessarily a policy failure.&lt;/p&gt;

&lt;p&gt;It means the service account does not have the requested permission.&lt;/p&gt;

&lt;h3&gt;
  
  
  Missing binary in a container
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;executable file not found in $PATH
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This often happens with distroless or minimal images.&lt;/p&gt;

&lt;p&gt;The exec path may be working perfectly. The target container just does not have &lt;code&gt;sh&lt;/code&gt;, &lt;code&gt;bash&lt;/code&gt;, &lt;code&gt;curl&lt;/code&gt;, or &lt;code&gt;ps&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Namespace or tool guardrail
&lt;/h3&gt;

&lt;p&gt;Some Kubernetes tools intentionally block sensitive namespaces.&lt;/p&gt;

&lt;p&gt;If a tool refuses to operate in &lt;code&gt;kube-system&lt;/code&gt;, that may be a built-in guardrail rather than an RBAC issue.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resource not found
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;deployments.apps "api" not found
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This might mean:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;wrong namespace&lt;/li&gt;
&lt;li&gt;wrong cluster&lt;/li&gt;
&lt;li&gt;stale incident context&lt;/li&gt;
&lt;li&gt;typo&lt;/li&gt;
&lt;li&gt;resource renamed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent should verify before inventing a root cause.&lt;/p&gt;

&lt;h2&gt;
  
  
  Show evidence in the response
&lt;/h2&gt;

&lt;p&gt;For incident workflows, I prefer this response shape:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Result: Failed
Operation: scale deployment
Target: namespace/app
Reason: RBAC denied
Evidence: service account cannot patch deployments/scale
Next step: grant scoped RBAC if this operation should be allowed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is much better than a paragraph of uncertain explanation.&lt;/p&gt;

&lt;p&gt;It gives the human a clear path:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;fix RBAC&lt;/li&gt;
&lt;li&gt;choose a different action&lt;/li&gt;
&lt;li&gt;reject the operation&lt;/li&gt;
&lt;li&gt;escalate to someone with permissions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Distinguish diagnosis from speculation
&lt;/h2&gt;

&lt;p&gt;Agents should use language carefully.&lt;/p&gt;

&lt;p&gt;Evidence-backed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The API server denied this request because...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Speculative:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;This could be related to...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Speculation is allowed, but it must be labeled as speculation.&lt;/p&gt;

&lt;p&gt;In production operations, confident wrong answers are worse than cautious incomplete answers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use tool traces for debugging the agent itself
&lt;/h2&gt;

&lt;p&gt;When testing an operational agent, inspect the tool trace:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Did it choose the right tool?&lt;/li&gt;
&lt;li&gt;Did it choose the right cluster?&lt;/li&gt;
&lt;li&gt;Did it pass the right namespace?&lt;/li&gt;
&lt;li&gt;Did it ask for approval when required?&lt;/li&gt;
&lt;li&gt;Did it preserve stderr?&lt;/li&gt;
&lt;li&gt;Did it summarize the actual error?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the model explanation does not match the tool trace, fix the prompt, tool description, or response formatter.&lt;/p&gt;

&lt;p&gt;Do not train users to trust polished guesses.&lt;/p&gt;

&lt;h2&gt;
  
  
  Improve prompts, but do not rely only on prompts
&lt;/h2&gt;

&lt;p&gt;Prompts can help:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;When a tool call fails, quote the concrete error category and do not invent causes that are not present in the tool output.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But prompts are not enough.&lt;/p&gt;

&lt;p&gt;The platform should structure tool results so the model receives:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;status&lt;/li&gt;
&lt;li&gt;error category&lt;/li&gt;
&lt;li&gt;raw error&lt;/li&gt;
&lt;li&gt;target metadata&lt;/li&gt;
&lt;li&gt;suggested remediation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Structured evidence gives the agent less room to improvise.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;The best Kubernetes agents are not the ones that sound most confident.&lt;/p&gt;

&lt;p&gt;They are the ones that preserve operational truth.&lt;/p&gt;

&lt;p&gt;Let the model explain, summarize, and guide. But keep Kubernetes errors visible, structured, and auditable.&lt;/p&gt;

&lt;p&gt;When the system fails, the human should be able to answer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What exactly happened, and what evidence do we have?&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>kubernetes</category>
      <category>ai</category>
      <category>sre</category>
      <category>devops</category>
    </item>
    <item>
      <title>Exposing Internal Kubernetes Agent UIs: Lessons from VPC Lattice, DNS, and Private Access</title>
      <dc:creator>Devam Parikh</dc:creator>
      <pubDate>Tue, 14 Jul 2026 10:05:01 +0000</pubDate>
      <link>https://dev.to/devamparikh/exposing-internal-kubernetes-agent-uis-lessons-from-vpc-lattice-dns-and-private-access-2oah</link>
      <guid>https://dev.to/devamparikh/exposing-internal-kubernetes-agent-uis-lessons-from-vpc-lattice-dns-and-private-access-2oah</guid>
      <description>&lt;p&gt;A Kubernetes UI can be healthy and still unreachable from your browser.&lt;/p&gt;

&lt;p&gt;That sounds contradictory until you debug private networking.&lt;/p&gt;

&lt;p&gt;This post covers a common pattern: exposing an internal Kubernetes UI through AWS VPC Lattice, Route53, and private network access.&lt;/p&gt;

&lt;p&gt;The examples are generic, but the lesson is practical:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A working backend does not guarantee a reachable human URL.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The symptom
&lt;/h2&gt;

&lt;p&gt;The UI is deployed. The pod is running. The Kubernetes Service has endpoints. The route is accepted. Health checks are passing.&lt;/p&gt;

&lt;p&gt;But the browser times out.&lt;/p&gt;

&lt;p&gt;At this point, it is tempting to blame the application.&lt;/p&gt;

&lt;p&gt;In many private-network cases, the application is fine. The problem is the access path.&lt;/p&gt;

&lt;h2&gt;
  
  
  Trace from the browser inward
&lt;/h2&gt;

&lt;p&gt;Debug in this order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;DNS resolution&lt;/li&gt;
&lt;li&gt;local route table&lt;/li&gt;
&lt;li&gt;VPN/private network routing&lt;/li&gt;
&lt;li&gt;Lattice or ingress listener&lt;/li&gt;
&lt;li&gt;route attachment&lt;/li&gt;
&lt;li&gt;target group health&lt;/li&gt;
&lt;li&gt;Kubernetes Service endpoints&lt;/li&gt;
&lt;li&gt;pod readiness&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Do not start at the pod if the user cannot reach the hostname.&lt;/p&gt;

&lt;p&gt;Start with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dig internal-ui.example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then check what kind of IP the hostname resolves to.&lt;/p&gt;

&lt;h2&gt;
  
  
  Link-local addresses are a clue
&lt;/h2&gt;

&lt;p&gt;If a private UI hostname resolves to something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;169.254.x.x
fd00:...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;your laptop may not be able to route it, even if you are on VPN.&lt;/p&gt;

&lt;p&gt;Many VPN clients route VPC CIDRs such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10.0.0.0/8
172.16.0.0/12
192.168.0.0/16
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They may not route Lattice link-local addresses from your machine into AWS.&lt;/p&gt;

&lt;p&gt;So the backend can be reachable from inside the VPC, while the browser on your laptop cannot reach the same DNS target.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compare with a known working service
&lt;/h2&gt;

&lt;p&gt;The fastest way to find the difference is to compare with another internal UI that already works.&lt;/p&gt;

&lt;p&gt;Check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What does its Route53 record point to?&lt;/li&gt;
&lt;li&gt;Does it resolve to VPC-routable private IPs?&lt;/li&gt;
&lt;li&gt;Does it use HTTPS?&lt;/li&gt;
&lt;li&gt;Does it have an ACM certificate attached?&lt;/li&gt;
&lt;li&gt;Does it point to a VPC endpoint association DNS name?&lt;/li&gt;
&lt;li&gt;Does the non-working service point directly to a raw service DNS name?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In one common working pattern, Route53 points to a VPC endpoint association DNS name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;vpce-...-snsa-....vpc-lattice-svcs.region.on.aws
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That may resolve to private VPC IPs reachable over VPN.&lt;/p&gt;

&lt;p&gt;A broken pattern may point directly to a Lattice service-assigned domain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;service-name-....vpc-lattice-svcs.region.on.aws
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That can resolve to link-local addresses that are not reachable from a user's laptop.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fix is usually DNS target ownership
&lt;/h2&gt;

&lt;p&gt;For human browser access, Route53 should point at the DNS target that matches the intended access path.&lt;/p&gt;

&lt;p&gt;If users connect over VPN, the hostname should resolve to addresses their VPN routes.&lt;/p&gt;

&lt;p&gt;That often means using the VPC endpoint association path rather than the raw service domain.&lt;/p&gt;

&lt;p&gt;The exact implementation can be owned by Terraform, Crossplane, or another platform controller. The important part is not the tool. The important part is the contract:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Human UI hostname -&amp;gt; private routable endpoint -&amp;gt; Lattice/ingress -&amp;gt; Kubernetes Service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Human UI hostname -&amp;gt; link-local service address unreachable from laptop
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Keep service-to-service and human access separate
&lt;/h2&gt;

&lt;p&gt;The best endpoint for service-to-service traffic is not always the best endpoint for browser access.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MCP or internal service traffic may use one Lattice path.&lt;/li&gt;
&lt;li&gt;Human UI access may need a different private DNS and endpoint association path.&lt;/li&gt;
&lt;li&gt;Public access may be forbidden entirely.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is fine.&lt;/p&gt;

&lt;p&gt;Platform teams should make the access modes explicit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;agent-to-tool traffic: internal service path
human UI traffic: private browser-accessible path
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Verification checklist
&lt;/h2&gt;

&lt;p&gt;Before declaring the UI broken, verify:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pod is running.&lt;/li&gt;
&lt;li&gt;Service has endpoints.&lt;/li&gt;
&lt;li&gt;Route is accepted.&lt;/li&gt;
&lt;li&gt;Lattice target is healthy.&lt;/li&gt;
&lt;li&gt;DNS resolves to the expected target.&lt;/li&gt;
&lt;li&gt;Resolved IPs are routable from the client network.&lt;/li&gt;
&lt;li&gt;HTTPS listener and certificate match the hostname.&lt;/li&gt;
&lt;li&gt;Security groups and network policy allow the path.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If steps 1-4 pass and step 6 fails, the application is not the problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;Private access bugs are often naming bugs in disguise.&lt;/p&gt;

&lt;p&gt;The hostname exists. The service exists. The route exists. But the DNS target points to the wrong kind of network address for the client.&lt;/p&gt;

&lt;p&gt;For internal Kubernetes UIs, always ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Does this hostname resolve to something the user can actually route to?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That question saves a surprising amount of time.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>aws</category>
      <category>networking</category>
      <category>devops</category>
    </item>
    <item>
      <title>Read-Only First: A Safer Adoption Model for Agentic Platform Engineering</title>
      <dc:creator>Devam Parikh</dc:creator>
      <pubDate>Tue, 14 Jul 2026 10:04:27 +0000</pubDate>
      <link>https://dev.to/devamparikh/read-only-first-a-safer-adoption-model-for-agentic-platform-engineering-8ik</link>
      <guid>https://dev.to/devamparikh/read-only-first-a-safer-adoption-model-for-agentic-platform-engineering-8ik</guid>
      <description>&lt;p&gt;The fastest way to make people nervous about AI agents is to start with:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Let the agent fix production.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;For platform teams, a better starting point is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Let the agent inspect production safely and help humans make better decisions faster.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is the read-only-first model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why read-only first works
&lt;/h2&gt;

&lt;p&gt;Most incidents do not begin with a fix. They begin with questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What changed?&lt;/li&gt;
&lt;li&gt;Which pods are failing?&lt;/li&gt;
&lt;li&gt;Are events showing scheduling issues?&lt;/li&gt;
&lt;li&gt;Did a rollout just happen?&lt;/li&gt;
&lt;li&gt;Are logs showing one error or many?&lt;/li&gt;
&lt;li&gt;Is the issue isolated to one namespace or many?&lt;/li&gt;
&lt;li&gt;Is the service routing to ready endpoints?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are inspection tasks.&lt;/p&gt;

&lt;p&gt;An agent that answers them quickly is already useful, even if it cannot mutate anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read-only is not useless
&lt;/h2&gt;

&lt;p&gt;A read-only Kubernetes agent can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;list pods, deployments, services, ingresses, gateways, and routes&lt;/li&gt;
&lt;li&gt;summarize events&lt;/li&gt;
&lt;li&gt;inspect rollout state&lt;/li&gt;
&lt;li&gt;fetch logs&lt;/li&gt;
&lt;li&gt;compare resources across clusters&lt;/li&gt;
&lt;li&gt;identify missing endpoints&lt;/li&gt;
&lt;li&gt;explain likely failure modes&lt;/li&gt;
&lt;li&gt;generate a human-readable incident summary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That can reduce time-to-context without increasing blast radius.&lt;/p&gt;

&lt;p&gt;The first adoption goal should be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Can the agent help a human understand the system faster?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Can the agent autonomously remediate production?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Make read-only tools boring
&lt;/h2&gt;

&lt;p&gt;Read-only tools should be boring in the best way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;declarative&lt;/li&gt;
&lt;li&gt;versioned&lt;/li&gt;
&lt;li&gt;reviewed&lt;/li&gt;
&lt;li&gt;scoped by RBAC&lt;/li&gt;
&lt;li&gt;observable&lt;/li&gt;
&lt;li&gt;easy to disable&lt;/li&gt;
&lt;li&gt;attached explicitly to agents&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Avoid giving the agent a giant toolbox and hoping the prompt keeps it safe.&lt;/p&gt;

&lt;p&gt;Prefer explicit tool lists:&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;toolNames&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;k8s_get_resources&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;k8s_describe_resource&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;k8s_get_events&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;k8s_get_logs&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The smaller the first tool surface, the easier it is to reason about.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add governance before mutation
&lt;/h2&gt;

&lt;p&gt;Before adding write tools, answer these questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Who can invoke the agent?&lt;/li&gt;
&lt;li&gt;Where can it be invoked from?&lt;/li&gt;
&lt;li&gt;Which clusters can it reach?&lt;/li&gt;
&lt;li&gt;Which namespaces are allowed?&lt;/li&gt;
&lt;li&gt;Which tools require approval?&lt;/li&gt;
&lt;li&gt;How are approvals logged?&lt;/li&gt;
&lt;li&gt;What counts as a high-risk request?&lt;/li&gt;
&lt;li&gt;Can the agent access secrets indirectly?&lt;/li&gt;
&lt;li&gt;How are failed tool calls surfaced?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If those answers are unclear, write access is premature.&lt;/p&gt;

&lt;h2&gt;
  
  
  A staged rollout model
&lt;/h2&gt;

&lt;p&gt;I like this progression:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Stage 1: Read-only single-cluster inspection
Stage 2: Read-only multi-cluster inspection
Stage 3: ChatOps integration with approved channels
Stage 4: Approval-gated diagnostic exec
Stage 5: Approval-gated low-risk remediation
Stage 6: Pull-request based config fixes
Stage 7: Policy-backed automated remediation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each stage earns the next one.&lt;/p&gt;

&lt;p&gt;The platform should prove reliability, auditability, and user trust before gaining more power.&lt;/p&gt;

&lt;h2&gt;
  
  
  Read-only still needs guardrails
&lt;/h2&gt;

&lt;p&gt;Read-only does not mean zero risk.&lt;/p&gt;

&lt;p&gt;Logs can contain sensitive data. Resource names can reveal architecture. Events can expose internal details. Cross-cluster access can broaden visibility.&lt;/p&gt;

&lt;p&gt;So even read-only agents need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;authentication&lt;/li&gt;
&lt;li&gt;authorization&lt;/li&gt;
&lt;li&gt;audit logs&lt;/li&gt;
&lt;li&gt;namespace scoping&lt;/li&gt;
&lt;li&gt;rate limits&lt;/li&gt;
&lt;li&gt;clear data handling rules&lt;/li&gt;
&lt;li&gt;private or gateway-controlled model options&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The difference is that read-only failures usually have a smaller blast radius than write failures.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to introduce write tools
&lt;/h2&gt;

&lt;p&gt;Add write tools when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;users trust read-only responses&lt;/li&gt;
&lt;li&gt;tool traces are observable&lt;/li&gt;
&lt;li&gt;RBAC is scoped&lt;/li&gt;
&lt;li&gt;approval gates work&lt;/li&gt;
&lt;li&gt;risk classification is understandable&lt;/li&gt;
&lt;li&gt;the team has tested failure modes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Start with reversible operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;rollout restart&lt;/li&gt;
&lt;li&gt;scale within safe bounds&lt;/li&gt;
&lt;li&gt;patch a known annotation&lt;/li&gt;
&lt;li&gt;run a narrow diagnostic exec&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Avoid starting with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;delete arbitrary resources&lt;/li&gt;
&lt;li&gt;apply arbitrary manifests&lt;/li&gt;
&lt;li&gt;broad shell execution&lt;/li&gt;
&lt;li&gt;secret inspection&lt;/li&gt;
&lt;li&gt;cluster-wide mutation&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The best first demo
&lt;/h2&gt;

&lt;p&gt;The best first demo is not deleting a pod.&lt;/p&gt;

&lt;p&gt;A better demo:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ask the agent why a deployment is unhealthy.&lt;/li&gt;
&lt;li&gt;Agent gathers pods, events, rollout, and logs.&lt;/li&gt;
&lt;li&gt;Agent summarizes the likely cause.&lt;/li&gt;
&lt;li&gt;Agent proposes a safe next step.&lt;/li&gt;
&lt;li&gt;Human decides.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That demonstrates value without pretending the system is ready for autonomy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;Read-only-first is not a timid approach. It is a platform engineering approach.&lt;/p&gt;

&lt;p&gt;It lets teams introduce agentic workflows while preserving the trust model that production systems need.&lt;/p&gt;

&lt;p&gt;The goal is not to make the agent powerless.&lt;/p&gt;

&lt;p&gt;The goal is to make each new capability earned, observable, and reversible.&lt;/p&gt;

</description>
      <category>platformengineering</category>
      <category>kubernetes</category>
      <category>ai</category>
      <category>sre</category>
    </item>
    <item>
      <title>From Tool Discovery to Real Execution: Verifying a Multi-Cluster MCP Path</title>
      <dc:creator>Devam Parikh</dc:creator>
      <pubDate>Tue, 14 Jul 2026 10:04:26 +0000</pubDate>
      <link>https://dev.to/devamparikh/from-tool-discovery-to-real-execution-verifying-a-multi-cluster-mcp-path-4fk5</link>
      <guid>https://dev.to/devamparikh/from-tool-discovery-to-real-execution-verifying-a-multi-cluster-mcp-path-4fk5</guid>
      <description>&lt;p&gt;Seeing tools in an agent UI is not the same as proving the platform works.&lt;/p&gt;

&lt;p&gt;In a multi-cluster MCP setup, there are many layers between a user prompt and a Kubernetes API response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prompt
  -&amp;gt; agent
  -&amp;gt; MCP client
  -&amp;gt; gateway route
  -&amp;gt; federated backend
  -&amp;gt; remote MCP server
  -&amp;gt; Kubernetes API
  -&amp;gt; tool result
  -&amp;gt; agent response
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If any layer is misconfigured, the final experience may fail in confusing ways.&lt;/p&gt;

&lt;p&gt;This post is a verification checklist for multi-cluster MCP paths.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with the backend tools
&lt;/h2&gt;

&lt;p&gt;Before involving the agent, verify the application-cluster MCP server directly.&lt;/p&gt;

&lt;p&gt;Questions to answer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the MCP server running?&lt;/li&gt;
&lt;li&gt;Is it reachable over the expected network path?&lt;/li&gt;
&lt;li&gt;Can it list tools?&lt;/li&gt;
&lt;li&gt;Can it execute a simple read-only tool?&lt;/li&gt;
&lt;li&gt;Does its Kubernetes service account have the intended RBAC?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not start debugging the agent until the backend tool server works independently.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verify the gateway backend
&lt;/h2&gt;

&lt;p&gt;If Agentgateway or another gateway is federating MCP servers, verify the backend object next.&lt;/p&gt;

&lt;p&gt;For each target:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;is the host correct?&lt;/li&gt;
&lt;li&gt;is the port correct?&lt;/li&gt;
&lt;li&gt;is the MCP path correct?&lt;/li&gt;
&lt;li&gt;is the protocol correct?&lt;/li&gt;
&lt;li&gt;is the target name stable?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Target names often become tool prefixes.&lt;/p&gt;

&lt;p&gt;If the target is named &lt;code&gt;cluster-a&lt;/code&gt;, a backend tool like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;k8s_get_resources
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;may appear to the agent as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cluster-a_k8s_get_resources
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That prefix is part of the operator experience. Choose names humans can recognize.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verify routing
&lt;/h2&gt;

&lt;p&gt;Next, confirm the route that publishes the federated MCP endpoint.&lt;/p&gt;

&lt;p&gt;Check:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the route is accepted&lt;/li&gt;
&lt;li&gt;backend references are resolved&lt;/li&gt;
&lt;li&gt;the path matches the URL configured in the agent&lt;/li&gt;
&lt;li&gt;the gateway listener is attached&lt;/li&gt;
&lt;li&gt;network policy or service mesh rules are not blocking traffic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is where many failures hide. The backend may be healthy, but the route may point at the wrong path or namespace.&lt;/p&gt;

&lt;h2&gt;
  
  
  List tools from the federated endpoint
&lt;/h2&gt;

&lt;p&gt;Now connect directly to the federated MCP endpoint and list tools.&lt;/p&gt;

&lt;p&gt;You want to see tools from every expected cluster with the right prefixes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cluster-a_k8s_get_resources
cluster-a_k8s_describe_resource
cluster-b_k8s_get_resources
cluster-b_k8s_describe_resource
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If tools are missing, the problem is likely gateway federation, backend reachability, or tool server discovery.&lt;/p&gt;

&lt;p&gt;If tools are present, you have proven discovery, but not execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Execute a safe read-only tool
&lt;/h2&gt;

&lt;p&gt;Pick a boring command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;list namespaces
list pods in a non-sensitive namespace
describe a known deployment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The goal is not to show off. The goal is to prove:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the tool call reaches the correct cluster&lt;/li&gt;
&lt;li&gt;RBAC allows the action&lt;/li&gt;
&lt;li&gt;the response returns through the gateway&lt;/li&gt;
&lt;li&gt;the MCP client receives structured output&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keep the first test read-only.&lt;/p&gt;

&lt;h2&gt;
  
  
  Attach the tool to the agent
&lt;/h2&gt;

&lt;p&gt;Only after direct MCP verification should you attach the tools to the agent.&lt;/p&gt;

&lt;p&gt;In the agent definition, explicitly list allowed tools:&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;toolNames&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cluster-a_k8s_get_resources&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cluster-a_k8s_describe_resource&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cluster-b_k8s_get_resources&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cluster-b_k8s_describe_resource&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Explicit tool lists are easier to review than broad access.&lt;/p&gt;

&lt;p&gt;They also make it obvious which clusters and actions the agent can use.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test the agent with specific prompts
&lt;/h2&gt;

&lt;p&gt;Avoid vague prompts at first.&lt;/p&gt;

&lt;p&gt;Use prompts that force the intended route:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;List pods in Cluster A in the default namespace.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Describe the frontend deployment in Cluster B.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Compare pod readiness between Cluster A and Cluster B for this namespace.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent should select the correctly prefixed tool.&lt;/p&gt;

&lt;p&gt;If it chooses the wrong cluster, fix the system prompt or tool descriptions before adding more tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Watch for false success
&lt;/h2&gt;

&lt;p&gt;An agent can produce a confident answer even when the tool failed.&lt;/p&gt;

&lt;p&gt;For verification, inspect the actual tool calls and tool outputs.&lt;/p&gt;

&lt;p&gt;Look for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;wrong tool name&lt;/li&gt;
&lt;li&gt;wrong namespace&lt;/li&gt;
&lt;li&gt;RBAC denial&lt;/li&gt;
&lt;li&gt;network timeout&lt;/li&gt;
&lt;li&gt;empty result interpreted as success&lt;/li&gt;
&lt;li&gt;model explanation that does not match tool stderr&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent's natural-language answer is not enough. The tool trace is the source of truth.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add write access last
&lt;/h2&gt;

&lt;p&gt;Once read-only federation works, write tools can be added carefully:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;separate service account&lt;/li&gt;
&lt;li&gt;smaller RBAC surface&lt;/li&gt;
&lt;li&gt;explicit tool list&lt;/li&gt;
&lt;li&gt;human approval&lt;/li&gt;
&lt;li&gt;risk classification&lt;/li&gt;
&lt;li&gt;audit logging&lt;/li&gt;
&lt;li&gt;namespace restrictions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not mix early read-only validation with write-tool debugging. You want a clean baseline first.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final checklist
&lt;/h2&gt;

&lt;p&gt;Use this rollout order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Direct MCP server health.&lt;/li&gt;
&lt;li&gt;Direct read-only tool call.&lt;/li&gt;
&lt;li&gt;Gateway backend accepted.&lt;/li&gt;
&lt;li&gt;Route accepted.&lt;/li&gt;
&lt;li&gt;Federated endpoint lists tools.&lt;/li&gt;
&lt;li&gt;Federated endpoint executes a read-only tool.&lt;/li&gt;
&lt;li&gt;Agent discovers tools.&lt;/li&gt;
&lt;li&gt;Agent selects the correct prefixed tool.&lt;/li&gt;
&lt;li&gt;Agent response matches real tool output.&lt;/li&gt;
&lt;li&gt;Approval-gated write tools added later.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The important idea:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Tool discovery proves the menu exists. Real execution proves the kitchen works.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>kubernetes</category>
      <category>mcp</category>
      <category>sre</category>
      <category>devops</category>
    </item>
    <item>
      <title>Designing ChatOps Sessions for Kubernetes Agents</title>
      <dc:creator>Devam Parikh</dc:creator>
      <pubDate>Tue, 14 Jul 2026 10:04:24 +0000</pubDate>
      <link>https://dev.to/devamparikh/designing-chatops-sessions-for-kubernetes-agents-106n</link>
      <guid>https://dev.to/devamparikh/designing-chatops-sessions-for-kubernetes-agents-106n</guid>
      <description>&lt;p&gt;Running a Kubernetes agent from Slack or Teams sounds simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Mention the bot and ask it to inspect the cluster.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The hard part is not sending a message to an agent. The hard part is deciding what context that message belongs to.&lt;/p&gt;

&lt;p&gt;In incident response, context boundaries matter.&lt;/p&gt;

&lt;p&gt;If two unrelated incident threads share the same agent memory, the agent may mix assumptions. If a bot can be invoked from any channel or personal chat, sensitive operations can drift outside approved spaces.&lt;/p&gt;

&lt;p&gt;This post covers a practical model for ChatOps sessions with Kubernetes agents.&lt;/p&gt;

&lt;h2&gt;
  
  
  The core rule
&lt;/h2&gt;

&lt;p&gt;For incident workflows, the safest default is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;one chat thread = one agent context
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That means:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Incident thread A -&amp;gt; agent session A
Incident thread B -&amp;gt; agent session B
Personal chat      -&amp;gt; blocked or separate session
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This keeps debugging context, approvals, tool results, and follow-up questions scoped to one operational conversation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Chat threads are not always obvious to bots
&lt;/h2&gt;

&lt;p&gt;Humans see a thread as a clear conversation.&lt;/p&gt;

&lt;p&gt;Bot frameworks may expose several identifiers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;team ID&lt;/li&gt;
&lt;li&gt;channel ID&lt;/li&gt;
&lt;li&gt;conversation ID&lt;/li&gt;
&lt;li&gt;message ID&lt;/li&gt;
&lt;li&gt;reply/root thread ID&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Depending on the platform, multiple channel threads may share a conversation ID and differ only by reply metadata.&lt;/p&gt;

&lt;p&gt;If your bot stores agent state only by &lt;code&gt;conversation.id&lt;/code&gt;, two threads may accidentally share an agent session.&lt;/p&gt;

&lt;p&gt;A better session key includes the thread root:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;session_key = channel_id + thread_root_id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact fields vary by provider, but the intent is stable:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;bind the agent session to the incident thread, not only to the channel.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The bot may not see old thread history
&lt;/h2&gt;

&lt;p&gt;Another subtle issue: if an agent is mentioned halfway through a long thread, it may not automatically receive the previous messages.&lt;/p&gt;

&lt;p&gt;The bot might only receive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@agent can you inspect this?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It may not receive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Earlier: deployment failed after rollout
Earlier: image pull errors were seen
Earlier: only one namespace is affected
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There are three ways to handle this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ask users to include context when mentioning the agent.&lt;/li&gt;
&lt;li&gt;Use the chat provider API to fetch thread history.&lt;/li&gt;
&lt;li&gt;Summarize thread history before sending it to the agent.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For production usage, fetching thread context requires careful permissions and data handling. Do not add broad chat-read permissions casually.&lt;/p&gt;

&lt;h2&gt;
  
  
  Control where the agent can be used
&lt;/h2&gt;

&lt;p&gt;There are two layers of access control:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Where the app can be installed.&lt;/li&gt;
&lt;li&gt;Where the runtime will actually respond.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first layer is app configuration. For example, you might remove personal chat or group chat support and allow only team/channel usage.&lt;/p&gt;

&lt;p&gt;The second layer is runtime enforcement.&lt;/p&gt;

&lt;p&gt;A Kubernetes operations bot should support allowlists such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ALLOWED_TEAM_IDS
ALLOWED_CHANNEL_IDS
ALLOWED_CONVERSATION_IDS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The bot should reject normal messages and approval actions outside approved locations.&lt;/p&gt;

&lt;p&gt;This matters because an approval click is operational authority. It should be constrained to the same trusted space as the request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Approval state belongs to the session
&lt;/h2&gt;

&lt;p&gt;If the agent asks to run a protected tool, the approval decision should be tied to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;user&lt;/li&gt;
&lt;li&gt;request&lt;/li&gt;
&lt;li&gt;tool&lt;/li&gt;
&lt;li&gt;target cluster/namespace/resource&lt;/li&gt;
&lt;li&gt;chat thread&lt;/li&gt;
&lt;li&gt;timestamp&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Avoid approval flows that can be replayed or detached from their context.&lt;/p&gt;

&lt;p&gt;An approval should mean:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I approve this specific tool call for this specific target in this specific thread.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Not:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I approve the agent to do something generally.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Make the agent summarize risk before approval
&lt;/h2&gt;

&lt;p&gt;A useful ChatOps flow looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User:
  Check this workload and restart it if needed.

Agent:
  I found failing readiness probes.
  Restarting the deployment is a Yellow operation because it mutates live workload state.

Approval card:
  Tool: restart deployment
  Target: namespace/app
  Risk: Yellow
  Approve / Reject
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent explains. The platform enforces.&lt;/p&gt;

&lt;p&gt;That separation keeps the UX friendly without relying on the model as the policy boundary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;Chat is a great interface for Kubernetes incident response because it is where people already coordinate.&lt;/p&gt;

&lt;p&gt;But a chat interface is not automatically safe.&lt;/p&gt;

&lt;p&gt;Design the session model deliberately:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;one incident thread maps to one agent context&lt;/li&gt;
&lt;li&gt;approved channels are enforced at runtime&lt;/li&gt;
&lt;li&gt;old thread history is handled intentionally&lt;/li&gt;
&lt;li&gt;approval actions are bound to a specific request&lt;/li&gt;
&lt;li&gt;sensitive Kubernetes tools require real gates&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent should feel easy to use, but the boundaries should be boringly explicit.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>chatops</category>
      <category>sre</category>
      <category>ai</category>
    </item>
    <item>
      <title>Why Kubernetes Exec Is Secret-Adjacent in Agentic Operations</title>
      <dc:creator>Devam Parikh</dc:creator>
      <pubDate>Tue, 14 Jul 2026 10:04:23 +0000</pubDate>
      <link>https://dev.to/devamparikh/why-kubernetes-exec-is-secret-adjacent-in-agentic-operations-40i4</link>
      <guid>https://dev.to/devamparikh/why-kubernetes-exec-is-secret-adjacent-in-agentic-operations-40i4</guid>
      <description>&lt;p&gt;When teams connect AI agents to Kubernetes, they often start the security review with one question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can this agent read Kubernetes Secrets?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is a good question, but it is not sufficient.&lt;/p&gt;

&lt;p&gt;An agent may be blocked from the Kubernetes Secrets API and still be able to expose sensitive data indirectly through &lt;code&gt;exec&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That makes Kubernetes exec a &lt;strong&gt;secret-adjacent&lt;/strong&gt; capability.&lt;/p&gt;

&lt;h2&gt;
  
  
  The misleading comfort of blocked Secret API access
&lt;/h2&gt;

&lt;p&gt;Imagine a Kubernetes tool service account with this posture:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;get/list/watch secrets: no
create pods/exec: yes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the API layer, this looks reassuring. The agent cannot run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get secrets
kubectl describe secret
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But if the same agent can exec into a running pod, it may be able to inspect what the container can see at runtime.&lt;/p&gt;

&lt;p&gt;That can include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mounted Secret volumes&lt;/li&gt;
&lt;li&gt;service account tokens&lt;/li&gt;
&lt;li&gt;environment variables&lt;/li&gt;
&lt;li&gt;application config files&lt;/li&gt;
&lt;li&gt;credentials cached on disk&lt;/li&gt;
&lt;li&gt;cloud identity tokens&lt;/li&gt;
&lt;li&gt;files written by init containers or sidecars&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the real posture is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Kubernetes Secret API access: blocked
Runtime secret exposure through pod exec: possible
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That distinction matters a lot when the user interface is natural language.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why exec is powerful
&lt;/h2&gt;

&lt;p&gt;Exec is not one permission. It is a door into a process environment.&lt;/p&gt;

&lt;p&gt;Even harmless-looking prompts can become risky:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Can you check the environment of this pod?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Can you cat the config directory?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Can you print the token file?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Kubernetes API may not expose Secrets to the agent, but the application container might.&lt;/p&gt;

&lt;p&gt;This is why &lt;code&gt;pods/exec&lt;/code&gt; should not be treated like a normal read-only permission. It is interactive runtime access.&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical risk classification
&lt;/h2&gt;

&lt;p&gt;For agentic Kubernetes workflows, I like to classify exec requests separately from ordinary reads.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Green:  Pure Kubernetes API reads
Yellow: Exec with safe diagnostic intent
Red:    Exec that may expose secrets, credentials, tokens, or broad filesystem state
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Examples:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Request&lt;/th&gt;
&lt;th&gt;Suggested Risk&lt;/th&gt;
&lt;th&gt;Reason&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;List pods&lt;/td&gt;
&lt;td&gt;Green&lt;/td&gt;
&lt;td&gt;Kubernetes API read&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Describe deployment&lt;/td&gt;
&lt;td&gt;Green&lt;/td&gt;
&lt;td&gt;Kubernetes API read&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Get pod logs&lt;/td&gt;
&lt;td&gt;Green/Yellow&lt;/td&gt;
&lt;td&gt;Logs may contain sensitive data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Exec &lt;code&gt;uname -a&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Yellow&lt;/td&gt;
&lt;td&gt;Runtime access, but narrow output&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Exec &lt;code&gt;ps aux&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Yellow&lt;/td&gt;
&lt;td&gt;Process details may be sensitive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Exec &lt;code&gt;printenv&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Red&lt;/td&gt;
&lt;td&gt;Environment variables often contain secrets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Exec &lt;code&gt;cat /var/run/secrets/...&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Red&lt;/td&gt;
&lt;td&gt;Explicit token/secret access&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Exec &lt;code&gt;find / -type f&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Red&lt;/td&gt;
&lt;td&gt;Broad filesystem inspection&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;This model is intentionally simple. It is designed to make risk visible before execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use approval gates, not just polite prompts
&lt;/h2&gt;

&lt;p&gt;An LLM asking "Do you approve?" is not an enforcement mechanism.&lt;/p&gt;

&lt;p&gt;For sensitive tools, the platform should pause the actual tool call and require a real approval decision before execution.&lt;/p&gt;

&lt;p&gt;A better flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User:
  Run uname in this pod.

Agent:
  Risk: Yellow
  Reason: pod exec enters a live container, but the requested command is narrow.

Approval gate:
  Approve / Reject

Tool:
  Runs only after approval.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Red requests, the platform can either block them outright or require a stronger approval path.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add command-level guardrails
&lt;/h2&gt;

&lt;p&gt;Start with obvious patterns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;secret
token
password
credential
kubeconfig
printenv
/var/run/secrets
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will not catch everything, but it catches the requests that should never slip through casually.&lt;/p&gt;

&lt;p&gt;Then add context:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is the namespace sensitive?&lt;/li&gt;
&lt;li&gt;Is the pod part of the platform control plane?&lt;/li&gt;
&lt;li&gt;Is the user asking for broad filesystem access?&lt;/li&gt;
&lt;li&gt;Is the command trying to dump environment variables?&lt;/li&gt;
&lt;li&gt;Is the command wrapped in a shell?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An exec request is not just a command. It is a command plus a target plus a user plus an operational context.&lt;/p&gt;

&lt;h2&gt;
  
  
  RBAC still matters
&lt;/h2&gt;

&lt;p&gt;Guardrails do not replace Kubernetes RBAC.&lt;/p&gt;

&lt;p&gt;RBAC should still be scoped tightly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;avoid broad cluster-wide exec permissions&lt;/li&gt;
&lt;li&gt;prefer namespace scoping where possible&lt;/li&gt;
&lt;li&gt;separate read-only tools from write/exec tools&lt;/li&gt;
&lt;li&gt;use different service accounts for different risk tiers&lt;/li&gt;
&lt;li&gt;keep destructive tools out of default agents&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent should not have more power than the platform team is willing to expose through a normal operational workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;Agentic Kubernetes platforms should treat exec with respect.&lt;/p&gt;

&lt;p&gt;It is not the same as &lt;code&gt;get pods&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It is closer to temporary access into the runtime boundary of an application. Sometimes that access is exactly what an incident needs, but it should be visible, approved, logged, and risk-classified.&lt;/p&gt;

&lt;p&gt;The safest rule is simple:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If an agent can exec into a pod, assume it may be able to see what that pod can see.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>kubernetes</category>
      <category>security</category>
      <category>sre</category>
      <category>devops</category>
    </item>
    <item>
      <title>Guardrails Before Write Access: Building Agentic Kubernetes Operations with Human Approval</title>
      <dc:creator>Devam Parikh</dc:creator>
      <pubDate>Tue, 14 Jul 2026 10:04:22 +0000</pubDate>
      <link>https://dev.to/devamparikh/guardrails-before-write-access-building-agentic-kubernetes-operations-with-human-approval-5244</link>
      <guid>https://dev.to/devamparikh/guardrails-before-write-access-building-agentic-kubernetes-operations-with-human-approval-5244</guid>
      <description>&lt;p&gt;Agentic operations for Kubernetes sound exciting until the agent asks to run a production command.&lt;/p&gt;

&lt;p&gt;That is the moment the architecture stops being a demo and starts becoming a platform problem.&lt;/p&gt;

&lt;p&gt;It is not enough to connect an LLM to Kubernetes tools. A real platform needs boundaries:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What can the agent read?&lt;/li&gt;
&lt;li&gt;What can it change?&lt;/li&gt;
&lt;li&gt;Who approves risky actions?&lt;/li&gt;
&lt;li&gt;Can the agent retrieve secrets?&lt;/li&gt;
&lt;li&gt;How do we stop a chat interface from becoming a cluster-admin shortcut?&lt;/li&gt;
&lt;li&gt;How do we prove the request actually went through the intended path?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This post walks through a practical pattern for building a guarded Kubernetes agent workflow using chat-based invocation, MCP tools, risk classification, RBAC, and human approval.&lt;/p&gt;

&lt;p&gt;The examples are intentionally anonymized and use generic names, but the lessons come from real implementation work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The platform shape
&lt;/h2&gt;

&lt;p&gt;The architecture had three layers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Chat surface
  |
  | user asks for inspection/remediation
  v
Agent runtime
  |
  | calls approved tools through MCP
  v
Kubernetes tool server
  |
  | uses a scoped Kubernetes service account
  v
Application cluster
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The chat surface can be Slack, Microsoft Teams, or another collaboration tool. The important part is that the agent is invoked where incident response already happens.&lt;/p&gt;

&lt;p&gt;The agent runtime is responsible for interpreting the request, selecting tools, summarizing results, and asking for approval when needed.&lt;/p&gt;

&lt;p&gt;The Kubernetes tool server is the dangerous part. It is where natural language becomes Kubernetes API access, so it must be designed as a platform boundary rather than a convenience script.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start with read-only operations
&lt;/h2&gt;

&lt;p&gt;The safest starting point is read-only inspection:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;list pods&lt;/li&gt;
&lt;li&gt;describe deployments&lt;/li&gt;
&lt;li&gt;read events&lt;/li&gt;
&lt;li&gt;fetch logs&lt;/li&gt;
&lt;li&gt;inspect services, ingresses, gateways, and routes&lt;/li&gt;
&lt;li&gt;compare resource state across namespaces or clusters&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This already supports many incident workflows.&lt;/p&gt;

&lt;p&gt;During an incident, a useful agent does not need to delete a pod immediately. It first needs to gather context quickly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What changed?&lt;/li&gt;
&lt;li&gt;Which pods are unhealthy?&lt;/li&gt;
&lt;li&gt;Are there recent restarts?&lt;/li&gt;
&lt;li&gt;Are events showing image pull errors, scheduling failures, or failed probes?&lt;/li&gt;
&lt;li&gt;Is the service routing to ready endpoints?&lt;/li&gt;
&lt;li&gt;Is this isolated to one namespace, one cluster, or many clusters?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read-only tools let the team gain speed without handing the agent mutation rights on day one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Add write tools behind approval
&lt;/h2&gt;

&lt;p&gt;Eventually, teams will want remediation actions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;restart a deployment&lt;/li&gt;
&lt;li&gt;scale a workload&lt;/li&gt;
&lt;li&gt;patch a resource&lt;/li&gt;
&lt;li&gt;execute a command in a container&lt;/li&gt;
&lt;li&gt;apply a manifest&lt;/li&gt;
&lt;li&gt;delete a stuck pod&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These tools should not be exposed as ordinary chat commands. They should be protected tools with explicit approval.&lt;/p&gt;

&lt;p&gt;A good flow looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User:
  Run a diagnostic command in this pod.

Agent:
  Risk: Yellow
  Operation: pod exec
  Target: namespace/app-pod
  Reason: exec is read-only in intent, but the target namespace is sensitive.

Approval gate:
  Approve / Reject

Agent:
  Runs the tool only after approval and returns the result.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent should explain the risk before the tool runs, but the actual enforcement should live in the platform approval mechanism.&lt;/p&gt;

&lt;p&gt;That distinction matters. A model politely asking "Do you approve?" is not the same as an approval gate that pauses the tool call.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use simple risk classes
&lt;/h2&gt;

&lt;p&gt;You do not need a perfect policy engine on the first day. A simple risk model is already useful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Green   Low-risk read-only inspection
Yellow  Sensitive read-only action or limited operational change
Red     Destructive, secret-adjacent, broad, or hard-to-reverse action
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example classification:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Request&lt;/th&gt;
&lt;th&gt;Risk&lt;/th&gt;
&lt;th&gt;Why&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;List pods in a namespace&lt;/td&gt;
&lt;td&gt;Green&lt;/td&gt;
&lt;td&gt;Read-only inspection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Get logs from an application pod&lt;/td&gt;
&lt;td&gt;Green/Yellow&lt;/td&gt;
&lt;td&gt;Depends on log sensitivity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Exec &lt;code&gt;uname -a&lt;/code&gt; in a pod&lt;/td&gt;
&lt;td&gt;Yellow&lt;/td&gt;
&lt;td&gt;Exec is powerful even if command is harmless&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Scale a deployment&lt;/td&gt;
&lt;td&gt;Yellow&lt;/td&gt;
&lt;td&gt;Mutates live workload capacity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Delete a pod&lt;/td&gt;
&lt;td&gt;Red or Yellow&lt;/td&gt;
&lt;td&gt;Depends on namespace, controller, and blast radius&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Print environment variables&lt;/td&gt;
&lt;td&gt;Red&lt;/td&gt;
&lt;td&gt;Secret-adjacent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Read mounted service account token&lt;/td&gt;
&lt;td&gt;Red&lt;/td&gt;
&lt;td&gt;Secret exposure&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The goal is not to make the agent "smart" in a vague way. The goal is to make risk visible before execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Treat exec as secret-adjacent
&lt;/h2&gt;

&lt;p&gt;One of the most important lessons: blocking Kubernetes Secret API access is not enough.&lt;/p&gt;

&lt;p&gt;A service account may have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;get/list/watch secrets: no
create pods/exec: yes
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At first glance, that sounds safe. The agent cannot call &lt;code&gt;kubectl get secret&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;But &lt;code&gt;exec&lt;/code&gt; can still enter a running container. From inside that container, a user might read:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mounted secret files&lt;/li&gt;
&lt;li&gt;service account tokens&lt;/li&gt;
&lt;li&gt;environment variables&lt;/li&gt;
&lt;li&gt;app config files&lt;/li&gt;
&lt;li&gt;credentials written to disk&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the real security posture is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Kubernetes Secret API access: blocked
Secret exposure through pod runtime/exec: still possible
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That does not mean exec must be forbidden everywhere. It means exec deserves special handling:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;require approval&lt;/li&gt;
&lt;li&gt;classify suspicious commands as Red&lt;/li&gt;
&lt;li&gt;block obvious secret-reading patterns&lt;/li&gt;
&lt;li&gt;scope RBAC carefully&lt;/li&gt;
&lt;li&gt;prefer diagnostic commands with predictable output&lt;/li&gt;
&lt;li&gt;avoid exec into sensitive namespaces unless there is a clear reason&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Good guardrails understand that Kubernetes permissions and runtime access are related but not identical.&lt;/p&gt;

&lt;h2&gt;
  
  
  RBAC is part of the product experience
&lt;/h2&gt;

&lt;p&gt;When an agent fails to execute a command, the model may guess why.&lt;/p&gt;

&lt;p&gt;For example, it might say:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The operation may have been blocked by policy or GitOps drift prevention.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But the actual reason could simply be Kubernetes RBAC:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cannot patch resource "deployments/scale"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That distinction matters. If the agent guesses, users lose trust.&lt;/p&gt;

&lt;p&gt;The platform should capture and surface the real tool error:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;RBAC denied&lt;/li&gt;
&lt;li&gt;resource not found&lt;/li&gt;
&lt;li&gt;container binary not found&lt;/li&gt;
&lt;li&gt;namespace blocked by tool guardrail&lt;/li&gt;
&lt;li&gt;admission denied&lt;/li&gt;
&lt;li&gt;network timeout&lt;/li&gt;
&lt;li&gt;invalid command arguments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent can summarize, but it should not invent the root cause when the tool already returned one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Distroless containers change your demo plan
&lt;/h2&gt;

&lt;p&gt;Another practical lesson: many containers do not have a shell.&lt;/p&gt;

&lt;p&gt;Commands like these may fail:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sh &lt;span class="nt"&gt;-c&lt;/span&gt; &lt;span class="s2"&gt;"..."&lt;/span&gt;
bash
ps
curl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That does not mean exec is broken. It may just mean the target image is distroless or minimal.&lt;/p&gt;

&lt;p&gt;For a reliable demo or diagnostic workflow:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;pick commands that exist in the target image&lt;/li&gt;
&lt;li&gt;do not assume a shell is available&lt;/li&gt;
&lt;li&gt;test against known-good pods&lt;/li&gt;
&lt;li&gt;treat "executable file not found" as a container/runtime fact, not an agent failure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is mundane, but it saves a lot of confusion.&lt;/p&gt;

&lt;h2&gt;
  
  
  Chat permissions need their own boundary
&lt;/h2&gt;

&lt;p&gt;If an agent is available from a collaboration tool, the chat surface also needs access control.&lt;/p&gt;

&lt;p&gt;There are two separate layers:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Where the app can be installed or invoked.&lt;/li&gt;
&lt;li&gt;Which teams, channels, or conversations the bot will actually serve.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The first layer is app configuration. The second layer is runtime enforcement.&lt;/p&gt;

&lt;p&gt;For sensitive operational agents, runtime allowlists are useful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ALLOWED_TEAM_IDS
ALLOWED_CHANNEL_IDS
ALLOWED_CONVERSATION_IDS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent should reject messages and approval actions from unapproved locations.&lt;/p&gt;

&lt;p&gt;This matters because an approval button is also an operational action. It should not be usable from a random personal chat or copied into an uncontrolled place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Thread context is subtle
&lt;/h2&gt;

&lt;p&gt;Chat threads look obvious to humans, but bot frameworks may not automatically provide the full thread history to the bot.&lt;/p&gt;

&lt;p&gt;If the agent is mentioned halfway through a long incident thread, it may only receive the message where it was tagged, not every previous reply.&lt;/p&gt;

&lt;p&gt;That means the platform has to choose:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;require users to include relevant context in the prompt&lt;/li&gt;
&lt;li&gt;fetch thread history through the chat provider API&lt;/li&gt;
&lt;li&gt;summarize thread history before passing it to the agent&lt;/li&gt;
&lt;li&gt;map each chat thread to a separate agent context&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For incident response, the safest model is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;one chat thread = one agent context
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That prevents unrelated incidents from accidentally sharing memory.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would build first
&lt;/h2&gt;

&lt;p&gt;For an early production version, I would keep the first iteration intentionally conservative:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;read-only Kubernetes tools enabled by default&lt;/li&gt;
&lt;li&gt;write tools disabled until RBAC and approvals are ready&lt;/li&gt;
&lt;li&gt;exec treated as approval-required&lt;/li&gt;
&lt;li&gt;secret-looking commands classified as Red&lt;/li&gt;
&lt;li&gt;chat channel allowlists enabled&lt;/li&gt;
&lt;li&gt;one chat thread mapped to one agent context&lt;/li&gt;
&lt;li&gt;real Kubernetes errors surfaced clearly&lt;/li&gt;
&lt;li&gt;all tool calls logged with actor, target, risk, and decision&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then I would add automation gradually:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Read-only triage.&lt;/li&gt;
&lt;li&gt;Approved exec for diagnostic commands.&lt;/li&gt;
&lt;li&gt;Approved rollout restart or scale operations.&lt;/li&gt;
&lt;li&gt;Policy-backed remediation.&lt;/li&gt;
&lt;li&gt;Pull-request based fixes for configuration changes.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;Agentic Kubernetes operations should not start with "let the AI fix production."&lt;/p&gt;

&lt;p&gt;They should start with:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can we help humans gather context faster, classify risk clearly, and execute approved actions through a controlled platform path?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That framing is less flashy, but it is much closer to how platform teams can actually adopt agentic systems.&lt;/p&gt;

&lt;p&gt;The interesting work is not just connecting an LLM to Kubernetes.&lt;/p&gt;

&lt;p&gt;The interesting work is building the boundaries around it.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>ai</category>
      <category>devops</category>
      <category>sre</category>
    </item>
    <item>
      <title>One Agent, Many Clusters: Federating Kubernetes MCP Tools with Kagent and Agentgateway</title>
      <dc:creator>Devam Parikh</dc:creator>
      <pubDate>Tue, 14 Jul 2026 10:04:21 +0000</pubDate>
      <link>https://dev.to/devamparikh/one-agent-many-clusters-federating-kubernetes-mcp-tools-with-kagent-and-agentgateway-5c5f</link>
      <guid>https://dev.to/devamparikh/one-agent-many-clusters-federating-kubernetes-mcp-tools-with-kagent-and-agentgateway-5c5f</guid>
      <description>&lt;p&gt;Platform teams rarely operate one Kubernetes cluster.&lt;/p&gt;

&lt;p&gt;A more realistic environment has a management or agent cluster, several application clusters, and a growing set of operational tools that need to work across all of them.&lt;/p&gt;

&lt;p&gt;That creates an interesting question for Kubernetes-native agents:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;How can one Kagent agent inspect multiple clusters without embedding every cluster connection directly into the agent?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This post walks through a practical pattern: run Kagent in an agent cluster, expose Kubernetes MCP servers from application clusters, and federate those MCP servers through Agentgateway Virtual MCP.&lt;/p&gt;

&lt;p&gt;The result is a single MCP endpoint where tools are namespaced by cluster, such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cluster-a_k8s_get_resources
cluster-a_k8s_describe_resource
cluster-b_k8s_get_resources
cluster-b_k8s_describe_resource
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The cluster names above are examples. In your own environment, the prefixes should be boring, obvious identifiers: &lt;code&gt;prod_eu&lt;/code&gt;, &lt;code&gt;stage_us&lt;/code&gt;, &lt;code&gt;payments&lt;/code&gt;, &lt;code&gt;search&lt;/code&gt;, or whatever matches your operating model.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this pattern matters
&lt;/h2&gt;

&lt;p&gt;Kagent is Kubernetes-native: agents, model configuration, and tool connections are represented as Kubernetes resources.&lt;/p&gt;

&lt;p&gt;That is powerful because platform teams can manage agents the same way they manage the rest of their platform: declaratively, with GitOps, RBAC, reviews, and repeatable rollouts.&lt;/p&gt;

&lt;p&gt;MCP gives agents a standard way to discover and call tools. Agentgateway adds the routing layer that makes MCP manageable in a platform setting.&lt;/p&gt;

&lt;p&gt;Instead of every agent talking directly to every MCP server, Agentgateway can expose a stable endpoint, route to one or more MCP backends, and make the resulting tool surface easier to govern.&lt;/p&gt;

&lt;p&gt;For multi-cluster operations, the important bit is Virtual MCP: multiple MCP servers can be federated behind a single gateway endpoint. Each backend contributes tools, and the gateway prefixes those tools so clients can tell which backend they are calling.&lt;/p&gt;

&lt;p&gt;That gives you a useful separation of concerns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Application clusters own their local Kubernetes MCP servers.&lt;/li&gt;
&lt;li&gt;The agent cluster owns Kagent, the &lt;code&gt;RemoteMCPServer&lt;/code&gt;, and the agent definitions.&lt;/li&gt;
&lt;li&gt;Agentgateway owns the federated MCP endpoint that joins those worlds.&lt;/li&gt;
&lt;li&gt;Agents choose the correct cluster by selecting the correctly prefixed tool.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The architecture
&lt;/h2&gt;

&lt;p&gt;At a high level, the setup looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Kagent Agent
  |
  | RemoteMCPServer
  v
Agentgateway endpoint
  |
  | Virtual MCP targets
  +--&amp;gt; Cluster A Kubernetes MCP server
  |
  +--&amp;gt; Cluster B Kubernetes MCP server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each application cluster exposes a Kubernetes MCP server over HTTP. The agent cluster does not need to run all of those MCP servers locally. It only needs network reachability to their MCP endpoints.&lt;/p&gt;

&lt;p&gt;Agentgateway is configured with an &lt;code&gt;AgentgatewayBackend&lt;/code&gt; that contains one target per application cluster.&lt;/p&gt;

&lt;p&gt;In this example, the gateway uses static targets because the MCP servers live behind cross-cluster addresses rather than ordinary in-cluster Services:&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;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;agentgateway.dev/v1alpha1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AgentgatewayBackend&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application-clusters-k8s-readonly&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;platform-mcps&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;mcp&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;failureMode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;FailOpen&lt;/span&gt;
    &lt;span class="na"&gt;sessionRouting&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Stateless&lt;/span&gt;
    &lt;span class="na"&gt;targets&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cluster-a&lt;/span&gt;
        &lt;span class="na"&gt;static&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cluster-a-mcp.example.internal&lt;/span&gt;
          &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/mcp&lt;/span&gt;
          &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;StreamableHTTP&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cluster-b&lt;/span&gt;
        &lt;span class="na"&gt;static&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cluster-b-mcp.example.internal&lt;/span&gt;
          &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;80&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/mcp&lt;/span&gt;
          &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;StreamableHTTP&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The target names matter. They become part of the tool names that the agent sees.&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;cluster-a&lt;/code&gt; exposes a tool named &lt;code&gt;k8s_get_resources&lt;/code&gt;, the federated endpoint exposes it as &lt;code&gt;cluster-a_k8s_get_resources&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;An &lt;code&gt;HTTPRoute&lt;/code&gt; then publishes the federated backend on a stable path:&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;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gateway.networking.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HTTPRoute&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application-clusters-k8s-readonly&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;platform-mcps&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;parentRefs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;group&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gateway.networking.k8s.io&lt;/span&gt;
      &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Gateway&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;shared-mcps&lt;/span&gt;
      &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;platform-mcps&lt;/span&gt;
  &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;backendRefs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;group&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;agentgateway.dev&lt;/span&gt;
          &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AgentgatewayBackend&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application-clusters-k8s-readonly&lt;/span&gt;
          &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;platform-mcps&lt;/span&gt;
          &lt;span class="na"&gt;weight&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
      &lt;span class="na"&gt;matches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PathPrefix&lt;/span&gt;
            &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/mcps/application-clusters-k8s-readonly&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From Kagent's point of view, this is just a remote MCP server:&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;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kagent.dev/v1alpha2&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;RemoteMCPServer&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application-clusters-k8s-readonly&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kagent&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Federated read-only Kubernetes MCP tools for application clusters&lt;/span&gt;
  &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;STREAMABLE_HTTP&lt;/span&gt;
  &lt;span class="na"&gt;terminateOnClose&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;http://shared-mcps.platform-mcps.svc.cluster.local:80/mcps/application-clusters-k8s-readonly/mcp&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, the agent can be configured to use the federated MCP server and explicitly list the tools it is allowed to call:&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;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kagent.dev/v1alpha2&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Agent&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application-clusters-mcp-test-agent&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kagent&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Test agent for federated application-cluster Kubernetes MCP access&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Declarative&lt;/span&gt;
  &lt;span class="na"&gt;declarative&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;modelConfig&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default-model-config&lt;/span&gt;
    &lt;span class="na"&gt;runtime&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;python&lt;/span&gt;
    &lt;span class="na"&gt;systemMessage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
      &lt;span class="s"&gt;You are a read-only Kubernetes assistant for application clusters.&lt;/span&gt;
      &lt;span class="s"&gt;Use cluster-prefixed MCP tools to inspect live resources.&lt;/span&gt;
      &lt;span class="s"&gt;Use cluster-a_* tools for Cluster A and cluster-b_* tools for Cluster B.&lt;/span&gt;
      &lt;span class="s"&gt;Do not suggest or perform write operations.&lt;/span&gt;
    &lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;McpServer&lt;/span&gt;
        &lt;span class="na"&gt;mcpServer&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;apiGroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kagent.dev&lt;/span&gt;
          &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;RemoteMCPServer&lt;/span&gt;
          &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;application-clusters-k8s-readonly&lt;/span&gt;
          &lt;span class="na"&gt;toolNames&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cluster-a_k8s_describe_resource&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cluster-a_k8s_get_resources&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cluster-a_k8s_get_resource_yaml&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cluster-b_k8s_describe_resource&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cluster-b_k8s_get_resources&lt;/span&gt;
            &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cluster-b_k8s_get_resource_yaml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What worked well
&lt;/h2&gt;

&lt;p&gt;The cleanest part of the design is that the agent only needs one MCP connection. Tool selection becomes a routing decision expressed in the tool name.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"List pods in Cluster A" maps to &lt;code&gt;cluster-a_k8s_get_resources&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;"Show events in Cluster B" maps to &lt;code&gt;cluster-b_k8s_get_events&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;"Describe this deployment in Cluster A" maps to &lt;code&gt;cluster-a_k8s_describe_resource&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That makes the agent prompt simpler and makes operational boundaries easier to see.&lt;/p&gt;

&lt;p&gt;You can also keep the tools read-only, which is a good default for early production experiments. The agent can inspect resources, summarize state, compare clusters, and gather troubleshooting context without being able to mutate the environment.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;failureMode: FailOpen&lt;/code&gt; is also useful for multi-cluster setups. If one target is unavailable, the gateway can continue serving tools from healthy targets instead of failing the entire federated session. That is often the behavior you want when clusters are managed independently.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical lesson: static targets vs. selectors
&lt;/h2&gt;

&lt;p&gt;Agentgateway supports selector-based MCP federation, which is a nice fit when the MCP servers are ordinary Kubernetes Services in the same cluster.&lt;/p&gt;

&lt;p&gt;In cross-cluster setups, though, the MCP endpoints may be represented by external DNS names, service network addresses, or other forms of cross-cluster connectivity. In that case, static targets are often the more predictable model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The target name is explicit.&lt;/li&gt;
&lt;li&gt;The host, port, path, and protocol are explicit.&lt;/li&gt;
&lt;li&gt;Tool prefixes are stable.&lt;/li&gt;
&lt;li&gt;The agent-facing endpoint stays the same as clusters are added or removed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Selectors are still worth considering when your MCP servers are discoverable as regular in-cluster Services with the expected labels and protocol metadata.&lt;/p&gt;

&lt;p&gt;For cross-cluster endpoints, start with static targets and automate their generation later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Verification checklist
&lt;/h2&gt;

&lt;p&gt;A good rollout should prove each layer independently:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Confirm each application-cluster MCP endpoint responds directly.&lt;/li&gt;
&lt;li&gt;Confirm the &lt;code&gt;AgentgatewayBackend&lt;/code&gt; is accepted.&lt;/li&gt;
&lt;li&gt;Confirm the &lt;code&gt;HTTPRoute&lt;/code&gt; is accepted and resolves the backend reference.&lt;/li&gt;
&lt;li&gt;Connect to the federated MCP endpoint and list tools.&lt;/li&gt;
&lt;li&gt;Verify that tools from every cluster are present with the expected prefixes.&lt;/li&gt;
&lt;li&gt;Create or update the Kagent &lt;code&gt;RemoteMCPServer&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Confirm Kagent discovers the federated tools.&lt;/li&gt;
&lt;li&gt;Invoke the agent and ask it to query both clusters.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The most important test is the last one.&lt;/p&gt;

&lt;p&gt;A tool list proves discovery. An agent invocation proves the complete path: prompt, tool selection, MCP call, gateway routing, backend MCP server, and response synthesis.&lt;/p&gt;

&lt;p&gt;The screenshot below shows the kind of tool discovery output you want to see: prefixed Kubernetes tools from more than one application cluster available through a single federated MCP server.&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%2F7rfkplr62vcjqsws9x9d.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%2F7rfkplr62vcjqsws9x9d.png" alt="Kagent federated MCP tool discovery screenshot" width="800" height="396"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Design principles for production use
&lt;/h2&gt;

&lt;p&gt;This pattern is intentionally simple, but it benefits from a few production-minded constraints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start read-only. Inspection tools are enough for a lot of platform and SRE workflows.&lt;/li&gt;
&lt;li&gt;Use clear cluster prefixes. Humans should be able to predict the right tool name.&lt;/li&gt;
&lt;li&gt;Keep the agent prompt explicit. Tell the agent how prefixes map to clusters.&lt;/li&gt;
&lt;li&gt;Treat the gateway endpoint as a platform API. Review it, version it, and observe it.&lt;/li&gt;
&lt;li&gt;Prefer least privilege. The MCP server in each cluster should only have the permissions it needs.&lt;/li&gt;
&lt;li&gt;Add write tools later, behind approvals and stronger policy.&lt;/li&gt;
&lt;li&gt;Verify with real agent invocations, not only resource status.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Where this goes next
&lt;/h2&gt;

&lt;p&gt;Once the basic pattern works, the next step is automation.&lt;/p&gt;

&lt;p&gt;Platform teams can generate Agentgateway targets from a cluster registry, cloud service discovery, GitOps inventory, or another source of truth. They can also attach policies for tool access, rate limits, audit logging, and identity-aware authorization.&lt;/p&gt;

&lt;p&gt;The bigger idea is not just "one agent can see many clusters." It is that MCP tools can become a governed platform surface.&lt;/p&gt;

&lt;p&gt;Kagent provides the Kubernetes-native agent model, application clusters provide local operational tools, and Agentgateway gives the platform a single place to federate, route, and control access.&lt;/p&gt;

&lt;p&gt;That is a practical foundation for multi-cluster agentic operations: one agent-facing endpoint, many cluster-local tools, and a clear path from read-only inspection toward safer automated remediation.&lt;/p&gt;




&lt;p&gt;This post is based on a KAgent website contribution draft: &lt;a href="https://github.com/kagent-dev/website/pull/401" rel="noopener noreferrer"&gt;https://github.com/kagent-dev/website/pull/401&lt;/a&gt;&lt;/p&gt;

</description>
      <category>kagent</category>
      <category>kubernetes</category>
      <category>mcp</category>
      <category>devops</category>
    </item>
    <item>
      <title>Testing Application Resilience: How to Stop Amazon ElastiCache Cluster and Manage Traffic</title>
      <dc:creator>Devam Parikh</dc:creator>
      <pubDate>Fri, 13 Oct 2023 06:02:29 +0000</pubDate>
      <link>https://dev.to/devamparikh/testing-application-resilience-how-to-stop-amazon-elasticache-cluster-and-manage-traffic-58ep</link>
      <guid>https://dev.to/devamparikh/testing-application-resilience-how-to-stop-amazon-elasticache-cluster-and-manage-traffic-58ep</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;As developers, it is crucial to test the resiliency of our applications and understand how they handle failures or disruptions. In this blog post, we will explore a scenario where we need to stop an Amazon ElastiCache cluster to see how our application behaves when Redis is unavailable. Although ElastiCache clusters cannot be stopped, we will discuss alternative approaches to achieve our testing objective.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding Amazon ElastiCache
&lt;/h2&gt;

&lt;p&gt;Amazon ElastiCache for Redis is a powerful in-memory data structure service that provides real-time performance for modern applications. It serves as a cache or a data store, delivering high-speed access to data. ElastiCache uses a synchronous replication mechanism to maintain data consistency across its nodes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenges with Stopping ElastiCache Cluster
&lt;/h2&gt;

&lt;p&gt;Stopping an ElastiCache cluster is not possible due to the synchronous replication mechanism. If we stop a node, the cluster's redundancy is compromised, potentially leading to instability or complete failure. However, we can explore other methods to create scenarios where our application experiences Redis unavailability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Blocking Incoming Traffic using Security Groups
&lt;/h2&gt;

&lt;p&gt;To simulate Redis unavailability, we can block incoming traffic to the ElastiCache cluster. Security groups act as virtual firewalls, controlling inbound and outbound traffic. By removing all the inbound rules for the ElastiCache cluster, we can prevent any incoming requests from reaching it. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu6zl8qoe4aww4jb8dsuu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu6zl8qoe4aww4jb8dsuu.png" alt="Security Groups"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, it is essential to understand that security groups are stateful[1]. This means that existing connections are not interrupted when security group rules are changed. Thus, our application may still be connected to the ElastiCache cluster.&lt;/p&gt;

&lt;h2&gt;
  
  
  Addressing the Issue
&lt;/h2&gt;

&lt;p&gt;Two methods can be used to tackle this issue:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Restarting the Application:&lt;/strong&gt; By restarting the application, existing connections will be terminated, forcing the application to establish new connections. This can validate the application's ability to handle Redis unavailability.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Using Network ACLs:&lt;/strong&gt; Network Access Control Lists (ACLs)[2] operate at the subnet level and allow or deny specific inbound or outbound traffic. Unlike security groups, network ACLs are stateless, meaning they don't automatically allow response traffic. Introducing a network ACL that blocks traffic in either direction can break existing connections.&lt;/p&gt;

&lt;h2&gt;
  
  
  Network ACL in Depth
&lt;/h2&gt;

&lt;p&gt;You can either use the default VPC network ACL or create a custom one with rules similar to security groups for extra VPC security at no extra cost.&lt;/p&gt;

&lt;p&gt;The following diagram depicts a VPC with two subnets, each having its network ACL. When traffic enters the VPC (such as from a peered VPC, VPN connection, or the internet) the router directs it to its destination.&lt;/p&gt;

&lt;p&gt;Network ACL A controls which traffic can enter subnet 1 and leaves it to destination outside subnet 1. Similarly, network ACL B regulates traffic entering and leaving subnet 2.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftuug5werqp1j1x4hhmx6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftuug5werqp1j1x4hhmx6.png" alt="Network ACL"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating a Custom Network ACL
&lt;/h2&gt;

&lt;p&gt;As illustrated in the figure below, this is how I've configured the denial of incoming traffic from my application to the ElastiCache cluster.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo1ybhuht7stha2np3hxd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo1ybhuht7stha2np3hxd.png" alt="Custom Network ACL"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A network ACL comprises both inbound and outbound rules, each capable of allowing or denying traffic. These rules are numbered from 1 to 32766.&lt;/p&gt;

&lt;p&gt;When determining whether to allow or deny traffic, we evaluate the rules sequentially, starting with the lowest numbered rule. If a rule matches the traffic, it is applied, and no further rules are assessed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Testing application resilience is essential to ensure smooth operation in challenging scenarios. While stopping an ElastiCache cluster is not feasible due to its replication mechanism, alternative approaches such as blocking incoming traffic using security groups or employing network ACLs can help simulate Redis unavailability. By understanding the statefulness of security groups and the statelessness of network ACLs, we can effectively test our application's behaviour when critical resources are not available.&lt;/p&gt;

&lt;p&gt;In summary, remember these key points:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;ElastiCache clusters cannot be stopped and rely on synchronous replication for real-time performance.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Security groups are stateful, meaning existing connections persist when rules are modified.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Network ACLs are stateless and can be used to block traffic, potentially breaking existing connections.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Reference: &lt;br&gt;
[1] &lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-connection-tracking.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/security-group-connection-tracking.html&lt;/a&gt;&lt;br&gt;
[2] &lt;a href="https://docs.aws.amazon.com/vpc/latest/userguide/vpc-network-acls.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/vpc/latest/userguide/vpc-network-acls.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>networking</category>
      <category>devops</category>
    </item>
    <item>
      <title>Demystifying DDoS Attacks and CloudFront: A DevSecOps Guide</title>
      <dc:creator>Devam Parikh</dc:creator>
      <pubDate>Fri, 21 Jul 2023 10:49:11 +0000</pubDate>
      <link>https://dev.to/devamparikh/demystifying-ddos-attacks-and-cloudfront-a-devsecops-guide-50jb</link>
      <guid>https://dev.to/devamparikh/demystifying-ddos-attacks-and-cloudfront-a-devsecops-guide-50jb</guid>
      <description>&lt;p&gt;The IT industry is currently facing the worst crisis in its history, with numerous factors affecting its stability. One significant factor that demands attention is the rising number of DDoS attacks. According to the &lt;a href="https://www.radware.com/newsevents/pressreleases/2023/radware-full-year-2022-report-malicious-ddos-attacks/" rel="noopener noreferrer"&gt;reports&lt;/a&gt; available to me, there was a 150% increase in DDoS attacks in 2022 compared to 2021. Moreover, experts predict a continued upward trend in the upcoming years.&lt;/p&gt;

&lt;p&gt;Attacks such as DDoS can have a significant impact on organizations, causing service disruptions, financial losses, reputation damage, data loss, increased vulnerability to other attacks, and more.&lt;/p&gt;

&lt;p&gt;In today's digital landscape, understanding and mitigating DDoS attacks is crucial for DevSecOps professionals. In this blog post, we'll explore the intricacies of DDoS attacks and how CloudFront, Amazon Web Services' (AWS) content delivery network (CDN) service, can be a valuable tool in protecting your applications and infrastructure. By answering key questions along the way, we'll unravel the mysteries surrounding DDoS attacks and equip you with the knowledge to fortify your systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  What do you need to know about DDoS attackt as DevSecOps?
&lt;/h2&gt;

&lt;p&gt;A DDoS attack, or distributed denial-of-service attack, is a cyber-attack that targets a website or server by flooding it with so much traffic that it becomes unavailable to legitimate users. The goal of a DDoS attack is to disrupt the targeted website or server's services, making it inaccessible to users.&lt;/p&gt;

&lt;p&gt;There are two main types of DDoS attacks: volume-based attacks and application-layer attacks. Volume-based attacks flood the target with a large amount of traffic, overwhelming its resources and making it unable to handle legitimate requests. Application-layer attacks exploit vulnerabilities in the targeted website or server's applications, causing them to crash or malfunction.&lt;/p&gt;

&lt;p&gt;To launch a DDoS attack, the attacker first identifies the target website or server. Then, they gather a large number of infected computers, called "zombies," to flood the target with traffic. This overwhelms the website or server, making it unable to handle legitimate requests. As a result, users are unable to access the website or server.&lt;/p&gt;

&lt;h2&gt;
  
  
  How can CloudFront help with hosting and DDoS attackts?
&lt;/h2&gt;

&lt;p&gt;CloudFront is a content delivery network (CDN) service that speeds up the delivery of your content to users all over the world by caching your content in edge locations. These edge locations are servers that are located close to your users. When a user requests your content, CloudFront delivers it from the edge location that is closest to them, which reduces latency and improves performance.&lt;/p&gt;

&lt;p&gt;As most requests are answered by the edge location (from the cache), this significantly reduces the load on the origin server. The edge location acts as an absorbing agent, preventing requests from reaching the origin server directly, as they only need to pass through the edge location.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why do you need to have WAF protection enabled for CloudFront distribution?
&lt;/h2&gt;

&lt;p&gt;As discussed above, DDoS attacks rely on "zombies" to attack. Therefore, blocking the requests from IP addresses of zombie machines can help us to stop DDoS attacks.&lt;/p&gt;

&lt;p&gt;A web application firewall (WAF) serves as a protective layer in front of web applications, shielding them from common web exploits. WAFs function by inspecting HTTP requests and blocking those that match known attack patterns.&lt;/p&gt;

&lt;p&gt;CloudFront has a built-in integration with WAF, which implies that if WAF is enabled for any CloudFront distribution, AWS will automatically create and handle the WAF Rules for you. These rules include the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Protect against the most common vulnerabilities found in web applications.&lt;/li&gt;
&lt;li&gt;Protect against malicious actors discovering application vulnerabilities.&lt;/li&gt;
&lt;li&gt;Block IP addresses from potential threats based on Amazon internal threat intelligence.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After enabling WAF for a CloudFront distribution, it would appear similar to the below image.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk6lb2kaoy4zy9gs3hxhk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk6lb2kaoy4zy9gs3hxhk.png" alt="WAF for a CloudFront distribution"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How to setup logging for CloudFront?
&lt;/h2&gt;

&lt;p&gt;Before delving into the process of setting up logging, let's first understand why logging is crucial. Logging plays a pivotal role in enabling you to identify the source of an attack, mitigate the attack, and prevent future attacks.&lt;/p&gt;

&lt;p&gt;You can easily set up logging with just one click to send your logs to CloudWatch, S3, or Kinesis Data Firehose. Among these options, S3 is the most cost-effective choice.&lt;/p&gt;

&lt;h2&gt;
  
  
  Bonus
&lt;/h2&gt;

&lt;p&gt;Utilize Athena to query data from any S3 bucket. It is recommended to use separate S3 buckets for different environments as this will enhance Athena's performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By delving into the above subtopics, we've gained a comprehensive understanding of DDoS attacks and how CloudFront can fortify your DevSecOps practices. Armed with this knowledge, you're better equipped to protect your applications and infrastructure against potential threats. Stay vigilant, stay informed, and leverage the power of CloudFront to bolster your defenses.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>aws</category>
      <category>cloud</category>
      <category>security</category>
    </item>
  </channel>
</rss>
