<?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: The Cyber Sidekick</title>
    <description>The latest articles on DEV Community by The Cyber Sidekick (@thecybersidekick).</description>
    <link>https://dev.to/thecybersidekick</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%2F3987699%2F79b4c7af-5633-4f83-a6d5-03651461b293.png</url>
      <title>DEV Community: The Cyber Sidekick</title>
      <link>https://dev.to/thecybersidekick</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thecybersidekick"/>
    <language>en</language>
    <item>
      <title>AI Agents in DevOps: Why Traditional CI/CD Pipelines Break at 1000 Deployments Per Month</title>
      <dc:creator>The Cyber Sidekick</dc:creator>
      <pubDate>Wed, 08 Jul 2026 19:03:00 +0000</pubDate>
      <link>https://dev.to/thecybersidekick/ai-agents-in-devops-why-traditional-cicd-pipelines-break-at-1000-deployments-per-month-eoh</link>
      <guid>https://dev.to/thecybersidekick/ai-agents-in-devops-why-traditional-cicd-pipelines-break-at-1000-deployments-per-month-eoh</guid>
      <description>&lt;p&gt;&lt;em&gt;How LLM-driven orchestration agents are replacing rule-based pipeline automation to sustain hyperscale deployment velocities that static DSLs were never designed to handle.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;At hyperscale deployment velocities, traditional CI/CD pipelines built on sequential, rule-based automation collapse under the cognitive load of thousands of concurrent deployment decisions that require real-time reasoning across telemetry signals, failure modes, and risk tolerances. A new class of autonomous deployment agents, combining LLM-based orchestration, GitOps declarative state management, and eBPF-powered observability, is emerging as the only viable architecture for platforms that must ship reliably at this scale.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Scaling Wall That Rules-Based Pipelines Cannot Climb
&lt;/h2&gt;

&lt;p&gt;Traditional CI/CD pipelines were architected for deployment velocities measured in dozens of releases per day, using sequential stage gates, hardcoded approval thresholds, and static rollback conditions encoded in Jenkinsfiles or GitHub Actions YAML. At 1000 deployments per month across heterogeneous Kubernetes clusters, these pipelines do not simply slow down; they produce compounding decision debt, where a misconfigured canary threshold written six months ago now governs a microservice that serves ten times the original traffic volume. Google's internal Borg-derived systems already handle over 4 billion container launches per week, a scale that makes the limitations of rule-based scheduling immediately visible, since no human-authored ruleset can evaluate scheduling and deployment constraints within the sub-second latency budgets those systems require. The fundamental architectural mismatch is not one of tooling performance but of decision architecture: static pipelines can execute instructions, but they cannot reason about novel failure combinations, predict cascading degradations across service meshes, or rewrite their own deployment strategies in response to real-time SLO signals.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Agentic Orchestration Layers Replace Static Pipeline DSLs
&lt;/h2&gt;

&lt;p&gt;The ecosystem is actively transitioning from imperative pipeline scripting toward agentic orchestration layers where LLMs serve as meta-controllers, dynamically composing deployment strategies by consuming Prometheus metrics, distributed traces, and changelog semantics simultaneously. Projects like Argo Rollouts are embedding AI-augmented analysis templates that ingest Datadog and Prometheus metric providers to make autonomous canary promotion decisions, eliminating the manual threshold tuning that becomes untenable across hundreds of services. Fluxcd paired with OpenAI function-calling agents enables intelligent drift detection and self-correcting GitOps reconciliation loops, where the agent can distinguish between an intentional declarative state change and an unauthorized configuration drift without requiring a human to inspect the diff. Keptn v2 Lifecycle Toolkit extends this further by providing OpenTelemetry-native evaluation hooks that AI agents consume for SLO-driven deployment gating, meaning a deployment can be autonomously promoted, paused, or rolled back based on a structured conversation between the orchestration agent and a unified observability substrate rather than a brittle shell script comparing integer thresholds. Platforms like Dagger are enabling portable, composable pipeline primitives that LLM agents can assemble on-demand, shifting engineering teams from maintaining pipeline code to expressing desired deployment outcomes and acceptable risk tolerances as declarative intent.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Observability and Infrastructure Substrate That Makes Agents Viable
&lt;/h2&gt;

&lt;p&gt;Autonomous deployment agents require a standardized signal vocabulary to reason reliably, and the maturation of OpenTelemetry as a universal observability substrate across traces, metrics, and logs is providing exactly that foundation at a moment when it is most needed. Without a consistent schema for telemetry signals, an LLM-based agent cannot reliably distinguish a latency spike caused by a flawed deployment from one caused by an upstream dependency degrading independently, making autonomous rollback decisions dangerous rather than helpful. The infrastructure layer is also evolving to meet agents where they need to operate: Kubernetes Gateway API and WASM-based extensibility now allow AI agents to manipulate traffic routing at a granularity that previously required manual SRE intervention, enabling progressive delivery patterns like weighted traffic splits and header-based routing to be adjusted dynamically as canary analysis proceeds. Kubernetes-native admission webhooks and CEL-based policy surfaces give agents a programmable enforcement plane they can update at runtime without requiring cluster restarts or human-authored policy changes. Datadog's 2024 Container Report quantifies what happens when this infrastructure is absent, finding that organizations running more than 500 Kubernetes nodes experience incident rates 3.2 times higher during deployment windows, with the average cost per major outage reaching approximately $2.3 million, a figure that makes the ROI case for AI-driven progressive delivery and automated rollback straightforward to calculate.&lt;/p&gt;

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

&lt;p&gt;The 2023 DORA State of DevOps Report found that elite performers deploy 182 times more frequently than low performers, and analysts project that AI-assisted pipelines will push that multiplier beyond 500 times by 2026 as autonomous deployment agents eliminate manual approval bottlenecks and replace them with SLO-aware, telemetry-driven decision loops. The path forward is not incrementally smarter pipeline scripts but a wholesale architectural shift toward declarative intent expression, where engineering teams define outcomes and risk tolerances while agents handle tactical execution across multi-cluster federation topologies, availability zone-aware scheduling, and real-time traffic shaping. Organizations that begin this transition now, starting with AI-augmented canary analysis on top of existing Argo Rollouts or Flux installations, will build the operational muscle memory and telemetry hygiene needed to run fully autonomous deployment systems before the next generation of deployment velocity expectations arrives. Those that wait for the tools to mature further may find that the velocity gap between elite and average performers has grown too wide to close through iteration alone.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Technologies covered:&lt;/strong&gt; AI agents (LLM-based orchestration), GitOps with intelligent rollback, Kubernetes native auto-scaling, Observability platforms (Datadog, Prometheus), Self-healing infrastructure&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sources aggregated from: DevOps Weekly, GitHub Trending, Hacker News, InfoQ&lt;/em&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  📬 Stay current with cloud-native
&lt;/h3&gt;

&lt;p&gt;Get the latest Kubernetes, DevOps, and platform engineering insights delivered to your inbox.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://thecybersidekick.beehiiv.com/subscribe" rel="noopener noreferrer"&gt;Subscribe to The Cyber SideKick Newsletter&lt;/a&gt;&lt;/strong&gt; — free, no spam, unsubscribe anytime.&lt;/p&gt;

</description>
      <category>aiagents</category>
      <category>devopsautomation</category>
      <category>cicdpipelines</category>
      <category>gitops</category>
    </item>
    <item>
      <title>GitOps at Scale: How Event-Driven and AI-Assisted Deployments Are Replacing Manual Environment Promotion</title>
      <dc:creator>The Cyber Sidekick</dc:creator>
      <pubDate>Thu, 02 Jul 2026 19:51:44 +0000</pubDate>
      <link>https://dev.to/thecybersidekick/gitops-at-scale-how-event-driven-and-ai-assisted-deployments-are-replacing-manual-environment-4lj5</link>
      <guid>https://dev.to/thecybersidekick/gitops-at-scale-how-event-driven-and-ai-assisted-deployments-are-replacing-manual-environment-4lj5</guid>
      <description>&lt;p&gt;&lt;em&gt;Event-driven architectures and AI-powered validation are automating the entire GitOps promotion pipeline, eliminating the manual bottlenecks that throttle release velocity in large-scale Kubernetes environments.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Organizations managing hundreds of microservices are discovering that traditional GitOps promotion workflows, built around manual approval gates and human intervention, cannot scale to meet the demands of modern cloud-native delivery. Event-driven automation combined with ML-based quality gates is now enabling fully autonomous promotion decisions driven by real-time observability signals, policy-as-code enforcement, and historical deployment telemetry.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Scaling Ceiling of Manual GitOps Promotion
&lt;/h2&gt;

&lt;p&gt;Traditional GitOps pipelines treat environment promotion as a human-coordinated handoff: an engineer reviews test results, eyeballs dashboards, and clicks an approval button to advance a workload from staging to production. This model collapses under the weight of scale. When a platform team is responsible for hundreds of microservices across dozens of clusters, manual gates become the rate-limiting step in every release cycle. According to the 2023 DORA State of DevOps Report, elite performers deploy 127 times more frequently than low performers, and automated promotion pipelines are consistently cited as a key differentiator that keeps change failure rates below five percent. The problem is not that engineers make poor decisions; it is that the volume of decisions required in a large-scale Kubernetes environment exceeds what any team can handle reliably and quickly without automation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Event-Driven Promotion: Wiring Observability Signals Into the GitOps Control Loop
&lt;/h2&gt;

&lt;p&gt;The practical solution emerging across the CNCF ecosystem is to replace human approval gates with event-driven promotion logic that consumes signals from the observability stack in real time. Progressive delivery controllers like Argo Rollouts and Flagger connect directly to Prometheus, Datadog, and OpenTelemetry data sources, using metric-driven analysis templates to make canary and blue-green promotion decisions without waiting for a human to read a dashboard. Platform teams are routing Kubernetes events through NATS, Kafka, and CloudEvents-compliant brokers into GitOps reconcilers, so that SLO breaches, security scan failures, and load test outcomes can automatically trigger or block ArgoCD ApplicationSet promotions the moment the signal is available. Argo Rollouts alone has accumulated more than 5,800 GitHub stars and is running in production environments managing thousands of workloads, with documented case studies reporting a 60 to 70 percent reduction in deployment incidents attributable to analysis-based automated promotion. The CNCF's convergence on CloudEvents as a universal eventing substrate is accelerating interoperability between Tekton, Argo Events, Keptn, and external vendors, making it increasingly practical to compose these signals into a single, coherent promotion control plane.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI-Augmented Quality Gates and Policy-as-Code Guardrails
&lt;/h2&gt;

&lt;p&gt;Event-driven promotion handles the mechanics of signal routing, but AI and ML layers are adding a higher-order capability: deployment risk scoring based on patterns in historical telemetry that no human analyst would have the bandwidth to synthesize in real time. Tools like Keptn are integrating ML models trained on past deployment outcomes to score incoming releases and automate rollback decisions before a bad deployment can propagate to production. OpenFeature and custom admission webhooks are emerging as integration points for embedding these models directly into the Kubernetes API surface, while the Flux CD Notification Controller extends GitOps reconciliation triggers to respond to external quality signals via CloudEvents. Alongside AI scoring, policy-as-code frameworks are shifting compliance enforcement left: OPA Gatekeeper and Kyverno are now validating promotion eligibility before a Git commit is even merged, not just at deployment time, creating a continuous compliance loop across the entire software development lifecycle. Gartner projects that by 2026, more than 60 percent of organizations with mature DevOps practices will implement AI-augmented continuous delivery pipelines, up from fewer than 10 percent in 2023, driven by the economics of reducing mean time to recovery in cloud-native environments.&lt;/p&gt;

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

&lt;p&gt;The convergence of event-driven architecture, progressive delivery controllers, and AI-augmented quality gates is fundamentally reshaping what a GitOps promotion pipeline looks like at scale. Platform engineering teams are already standardizing on Internal Developer Platforms that abstract promotion complexity behind golden paths, embedding these capabilities directly into Backstage templates and Crossplane compositions so that individual service teams inherit automated, policy-compliant promotion by default rather than by custom effort. The trajectory is clear: the approval button is being replaced by a scoring model, the Slack notification is being replaced by a CloudEvent, and the manual rollback is being replaced by an analysis-driven controller acting within seconds of a signal breach. Organizations that invest now in the observability instrumentation, eventing infrastructure, and policy-as-code discipline required to feed these systems will be positioned to treat safe, frequent, autonomous deployment not as an aspirational benchmark but as a daily operational baseline.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Technologies covered:&lt;/strong&gt; GitOps, Event-Driven Architecture, Kubernetes, CI/CD Pipelines, Machine Learning Operations, ArgoCD, Flux CD, Policy as Code&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sources aggregated from: CNCF Blog, Kubernetes.io, DevOps Weekly&lt;/em&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  📬 Stay current with cloud-native
&lt;/h3&gt;

&lt;p&gt;Get the latest Kubernetes, DevOps, and platform engineering insights delivered to your inbox.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://thecybersidekick.beehiiv.com/subscribe" rel="noopener noreferrer"&gt;Subscribe to The Cyber SideKick Newsletter&lt;/a&gt;&lt;/strong&gt; — free, no spam, unsubscribe anytime.&lt;/p&gt;

</description>
      <category>gitops</category>
      <category>eventdrivenarchitecture</category>
      <category>kubernetes</category>
      <category>cicd</category>
    </item>
    <item>
      <title>Autoscale a Deployment with an HPA, including the field kubectl autoscale can't set (CKA Workloads)</title>
      <dc:creator>The Cyber Sidekick</dc:creator>
      <pubDate>Wed, 01 Jul 2026 14:56:10 +0000</pubDate>
      <link>https://dev.to/thecybersidekick/autoscale-a-deployment-with-an-hpa-including-the-field-kubectl-autoscale-cant-set-cka-workloads-2gn0</link>
      <guid>https://dev.to/thecybersidekick/autoscale-a-deployment-with-an-hpa-including-the-field-kubectl-autoscale-cant-set-cka-workloads-2gn0</guid>
      <description>&lt;h2&gt;
  
  
  Autoscale a Deployment with an HPA
&lt;/h2&gt;

&lt;p&gt;A Deployment named apache-server is running, and the exam wants it autoscaled on CPU: a 50 percent target, between one and four pods, and a 30 second scaleDown stabilization window. Let's build the HorizontalPodAutoscaler, and see why the obvious one-line command can't finish it.&lt;/p&gt;

&lt;p&gt;🎥 &lt;strong&gt;Watch the video:&lt;/strong&gt; &lt;a href="https://www.youtube.com/watch?v=G4ZFpOXMJD8" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=G4ZFpOXMJD8&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a CKA Workloads &amp;amp; Scheduling walkthrough. Every command below is real output from a live cluster, and you can reproduce the whole thing yourself (scripts at the end).&lt;/p&gt;

&lt;h2&gt;
  
  
  The scenario
&lt;/h2&gt;

&lt;p&gt;Here is the task. In the autoscale namespace, create a HorizontalPodAutoscaler named apache-server that targets the existing apache-server Deployment. Set the CPU target to 50 percent average utilization per pod, allow a minimum of one pod and a maximum of four, and set the scaleDown stabilization window to 30 seconds.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Namespace autoscale, HPA named apache-server&lt;/li&gt;
&lt;li&gt;Target the existing apache-server Deployment&lt;/li&gt;
&lt;li&gt;CPU target: 50% average utilization per pod&lt;/li&gt;
&lt;li&gt;minReplicas 1, maxReplicas 4, scaleDown window 30s&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How a HorizontalPodAutoscaler works
&lt;/h2&gt;

&lt;p&gt;Two things have to be true before an HPA can do anything. The Pod needs a CPU request, because a 50 percent target is a percentage of that request; with no request the HPA can't compute utilization. And metrics-server has to be running, because that's where the HPA reads live CPU. Given both, the HPA watches CPU and adjusts replicas between your min and max. The scaleDown stabilization window tells it how long to wait on falling load before removing pods, which damps flapping.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the YAML comes from (official docs)
&lt;/h2&gt;

&lt;p&gt;Before you apply anything, know that there is no kubectl create that emits a behavior block, so part of this is copy-paste from the official docs, which you are allowed to use in the exam. Two pages on kubernetes dot io cover it. Search HPA and open the HorizontalPodAutoscaler Walkthrough; it shows the autoscaling v2 object with the metrics array, the shape for the CPU target. Then open the Horizontal Pod Autoscaling concept page and find the section called Configurable scaling behavior, with its Stabilization window example; lift the scaleDown block straight from there. In practice: generate the skeleton with kubectl autoscale dry-run, paste the behavior block from that section, and set the window to 30.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;HPA object: &lt;a href="https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/" rel="noopener noreferrer"&gt;https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;behavior block: &lt;a href="https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#configurable-scaling-behavior" rel="noopener noreferrer"&gt;https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/#configurable-scaling-behavior&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Inspect the Deployment
&lt;/h2&gt;

&lt;p&gt;Start by reading what's there. The apache-server Deployment and its Service are running in the autoscale namespace. Open the Deployment manifest and look at the container's resources. Crucially, the Pod template sets a CPU request of 200 millicores. That request is what makes a percentage target meaningful: 50 percent of 200 millicores is 100 millicores per pod.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; autoscale get deploy,svc
&lt;span class="go"&gt;NAME                            READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/apache-server   1/1     1            1           125m

NAME                    TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
&lt;/span&gt;&lt;span class="gp"&gt;service/apache-server   ClusterIP   10.96.182.94   &amp;lt;none&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;80/TCP    125m
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;apache-app.yaml
&lt;span class="c"&gt;...
&lt;/span&gt;&lt;span class="go"&gt;      labels:
        app: apache-server
    spec:
      containers:
        - name: php-apache
          image: registry.k8s.io/hpa-example
          ports:
            - containerPort: 80
          resources:
            requests:
              cpu: 200m
            limits:
              cpu: 500m
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Metrics are flowing
&lt;/h2&gt;

&lt;p&gt;Confirm the HPA will have data to read. kubectl top pods returns live CPU and memory from metrics-server. If this command errored or showed nothing, the HPA would sit at TARGETS unknown and never scale, so verifying metrics first saves you a confusing debug later.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; autoscale top pods
&lt;span class="go"&gt;NAME                             CPU(cores)   MEMORY(bytes)   
apache-server-748dd94f84-2h56f   1m           9Mi
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Where kubectl autoscale stops
&lt;/h2&gt;

&lt;p&gt;Now the fast path: kubectl autoscale. Pass the target, min, and max, and it builds an HPA in one line. On a current cluster the dry-run even emits apiVersion autoscaling slash v2, with the CPU target already inside a metrics array, so it looks like you're done. But scan the whole object: there is no behavior section anywhere. The scaleDown stabilization window has no flag on this command, so the imperative path gets you three of the four requirements and stops.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; autoscale autoscale deployment apache-server &lt;span class="nt"&gt;--cpu-percent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;50 &lt;span class="nt"&gt;--min&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;1 &lt;span class="nt"&gt;--max&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;4 &lt;span class="nt"&gt;--dry-run&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;client &lt;span class="nt"&gt;-o&lt;/span&gt; yaml
&lt;span class="c"&gt;...
&lt;/span&gt;&lt;span class="go"&gt;      name: cpu
      target:
        averageUtilization: 50
        type: Utilization
    type: Resource
  minReplicas: 1
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: apache-server
status:
  currentMetrics: null
  desiredReplicas: 0
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Author the v2 HPA
&lt;/h2&gt;

&lt;p&gt;So finish it in YAML. Take the skeleton and add the one piece the command can't give you: a behavior block where scaleDown stabilizationWindowSeconds is 30. Watch the trap the walkthrough hit: in autoscaling slash v2 the CPU target belongs inside the metrics array as averageUtilization, so don't paste an old v1 targetCPUUtilizationPercentage field next to behavior, or the apiserver rejects it as an unknown field. Apply it, then list the HPA: it shows the target against 50 percent, with min 1 and max 4.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; hpa.yaml
&lt;span class="go"&gt;horizontalpodautoscaler.autoscaling/apache-server created

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; autoscale get hpa apache-server
&lt;span class="go"&gt;NAME            REFERENCE                  TARGETS       MINPODS   MAXPODS   REPLICAS   AGE
apache-server   Deployment/apache-server   cpu: 0%/50%   1         4         1          5s
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Verify the HPA
&lt;/h2&gt;

&lt;p&gt;Verify every field, because each is a separate mark. describe confirms the reference to the Deployment, the 50 percent CPU target, and the one-to-four range. Then read the stabilization window straight from the spec: 30 seconds, exactly as asked. With the CPU target reading a real percentage, the autoscaler is live and complete.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; autoscale describe hpa apache-server
&lt;span class="c"&gt;...
&lt;/span&gt;&lt;span class="go"&gt;  Scale Down:
    Stabilization Window: 30 seconds
    Select Policy: Max
    Policies:
      - Type: Percent  Value: 100  Period: 15 seconds
Deployment pods:       1 current / 1 desired
Conditions:
  Type            Status  Reason            Message
  ----            ------  ------            -------
  AbleToScale     True    ReadyForNewScale  recommended size matches current size
  ScalingActive   True    ValidMetricFound  the HPA was able to successfully calculate a replica count from cpu resource utilization (percentage of request)
  ScalingLimited  True    TooFewReplicas    the desired replica count is less than the minimum replica count
&lt;/span&gt;&lt;span class="gp"&gt;Events:           &amp;lt;none&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; autoscale get hpa apache-server &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;jsonpath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;'{.spec.behavior.scaleDown.stabilizationWindowSeconds}'&lt;/span&gt;
&lt;span class="go"&gt;scaleDown stabilizationWindowSeconds = 30
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Exam tips
&lt;/h2&gt;

&lt;p&gt;A few traps to remember. kubectl autoscale is fine for min, max, and the CPU target, but it has no flag for a stabilization window, so when behavior is required you finish the HPA in YAML. In autoscaling v2 the CPU target lives inside the metrics array, not as targetCPUUtilizationPercentage; mixing the two is the unknown field error. The Pod needs a CPU request or the percentage target is meaningless. And if TARGETS shows unknown, suspect metrics-server before the HPA itself.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;kubectl autoscale has no flag for a scaleDown stabilization window; add it in YAML&lt;/li&gt;
&lt;li&gt;v2: CPU target goes in metrics[], not targetCPUUtilizationPercentage&lt;/li&gt;
&lt;li&gt;No CPU request on the Pod means no usable utilization target&lt;/li&gt;
&lt;li&gt;TARGETS ? Check metrics-server before blaming the HPA&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Recap
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prereqs: a CPU request on the Pod + a running metrics-server&lt;/li&gt;
&lt;li&gt;v2 manifest: metrics[] for the CPU target, behavior for scaleDown&lt;/li&gt;
&lt;li&gt;stabilizationWindowSeconds 30 is the field kubectl autoscale can't set&lt;/li&gt;
&lt;li&gt;Subscribe + dev.to writeup&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Reproduce this yourself
&lt;/h2&gt;

&lt;p&gt;The entire scenario is scripted on a throwaway &lt;code&gt;kind&lt;/code&gt; cluster: &lt;a href="https://github.com/The-Cyber-Sidekick/TCS_CKA_2026_Exam_Scenarios" rel="noopener noreferrer"&gt;https://github.com/The-Cyber-Sidekick/TCS_CKA_2026_Exam_Scenarios&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/The-Cyber-Sidekick/TCS_CKA_2026_Exam_Scenarios.git
&lt;span class="nb"&gt;cd &lt;/span&gt;TCS_CKA_2026_Exam_Scenarios/learning/scenarios/scenario7-hpa-cpu-autoscale
./setup.sh        &lt;span class="c"&gt;# creates the cluster AND arms the scenario&lt;/span&gt;
&lt;span class="c"&gt;# solve it by hand, or:&lt;/span&gt;
./solution.sh     &lt;span class="c"&gt;# apply the answer key and verify&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;If this helped, &lt;strong&gt;subscribe to The Cyber SideKick&lt;/strong&gt; on YouTube for more CKA drills, and grab the newsletter at &lt;a href="https://thecybersidekick.beehiiv.com" rel="noopener noreferrer"&gt;https://thecybersidekick.beehiiv.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>cka</category>
      <category>autoscaling</category>
      <category>workloads</category>
    </item>
    <item>
      <title>CKA Exam 2026 - Scenario 6 Migrate an Ingress to the Gateway API without dropping HTTPS (CKA Services &amp; Networking)</title>
      <dc:creator>The Cyber Sidekick</dc:creator>
      <pubDate>Mon, 29 Jun 2026 18:29:18 +0000</pubDate>
      <link>https://dev.to/thecybersidekick/migrate-an-ingress-to-the-gateway-api-without-dropping-https-cka-services-networking-549l</link>
      <guid>https://dev.to/thecybersidekick/migrate-an-ingress-to-the-gateway-api-without-dropping-https-cka-services-networking-549l</guid>
      <description>&lt;h2&gt;
  
  
  Migrate Ingress to the Gateway API
&lt;/h2&gt;

&lt;p&gt;A web application is exposed over HTTPS with a classic Ingress, and the exam wants it migrated to the Gateway API while keeping HTTPS working. The GatewayClass is already installed. Let's recreate the routing with a Gateway and an HTTPRoute, then retire the Ingress.&lt;/p&gt;

&lt;p&gt;🎥 &lt;strong&gt;Watch the video:&lt;/strong&gt; &lt;a href="https://www.youtube.com/watch?v=v5_1KKFWLGE" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=v5_1KKFWLGE&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a CKA Services &amp;amp; Networking walkthrough. Every command below is real output from a live cluster, and you can reproduce the whole thing yourself (scripts at the end).&lt;/p&gt;

&lt;h2&gt;
  
  
  The scenario
&lt;/h2&gt;

&lt;p&gt;Here is the setup. A Deployment named web sits behind a Service, and an Ingress named web terminates TLS for the host gateway.web.k8s.local and routes to it. A GatewayClass is already installed. Your task is to migrate this to the Gateway API, keep the same HTTPS host, and once it works, delete the old Ingress.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An Ingress named 'web' serves HTTPS for gateway.web.k8s.local&lt;/li&gt;
&lt;li&gt;A GatewayClass is already installed in the cluster&lt;/li&gt;
&lt;li&gt;Recreate the routing with a Gateway + HTTPRoute&lt;/li&gt;
&lt;li&gt;Keep HTTPS, then delete the old Ingress&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How an Ingress maps onto the Gateway API
&lt;/h2&gt;

&lt;p&gt;The Gateway API splits what one Ingress did into three objects. The GatewayClass is the controller, like the ingress class. The Gateway is the listener: the port and the TLS the Ingress used to own. The HTTPRoute holds the routing rules: the hostname, the paths, and the backend Service. Map the Ingress onto those three and the migration is mechanical.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where the YAML comes from (you author it, not &lt;code&gt;apply -f&lt;/code&gt;)
&lt;/h2&gt;

&lt;p&gt;There is no imperative &lt;code&gt;kubectl create&lt;/code&gt; for a Gateway or HTTPRoute, so in the exam you&lt;br&gt;
write the YAML yourself, copying a starting template from the Gateway API docs (linked from&lt;br&gt;
the Kubernetes documentation, which is allowed during the exam):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gateway + TLS:&lt;/strong&gt; &lt;a href="https://gateway-api.sigs.k8s.io/guides/" rel="noopener noreferrer"&gt;Simple Gateway&lt;/a&gt; and
&lt;a href="https://gateway-api.sigs.k8s.io/guides/tls/" rel="noopener noreferrer"&gt;TLS termination&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;HTTPRoute:&lt;/strong&gt; &lt;a href="https://gateway-api.sigs.k8s.io/guides/http-routing/" rel="noopener noreferrer"&gt;HTTP routing&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Field reference:&lt;/strong&gt; &lt;a href="https://gateway-api.sigs.k8s.io/reference/spec/" rel="noopener noreferrer"&gt;API spec&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;From kubernetes.io:&lt;/strong&gt; &lt;a href="https://kubernetes.io/docs/concepts/services-networking/gateway/" rel="noopener noreferrer"&gt;Gateway API&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Every value is something you already have. &lt;code&gt;gatewayClassName&lt;/code&gt; is the class from&lt;br&gt;
&lt;code&gt;kubectl get gatewayclass&lt;/code&gt;. The HTTPS listener port and the &lt;code&gt;certificateRefs&lt;/code&gt; Secret are&lt;br&gt;
carried over from the existing Ingress's &lt;code&gt;tls&lt;/code&gt; block. The &lt;code&gt;hostname&lt;/code&gt;, the path, and the&lt;br&gt;
backend Service (&lt;code&gt;web:80&lt;/code&gt;) are the Ingress's own routing rule, re-expressed as an HTTPRoute.&lt;br&gt;
You can see both files (&lt;code&gt;cat&lt;/code&gt;) right before each &lt;code&gt;kubectl apply&lt;/code&gt; below.&lt;/p&gt;
&lt;h2&gt;
  
  
  Inspect what's running
&lt;/h2&gt;

&lt;p&gt;Start by reading the current state. The web Deployment and Service are running, and the Ingress named web is serving the host gateway.web.k8s.local on ports 80 and 443. The GatewayClass is present and Accepted, so the controller is ready for a Gateway to bind to it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; web get deploy,svc,ingress
&lt;span class="go"&gt;NAME                     READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/tester   1/1     1            1           117m
deployment.apps/web      1/1     1            1           117m

NAME          TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
&lt;/span&gt;&lt;span class="gp"&gt;service/web   ClusterIP   10.96.31.154   &amp;lt;none&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;80/TCP    117m
&lt;span class="go"&gt;
NAME                            CLASS   HOSTS                   ADDRESS     PORTS     AGE
ingress.networking.k8s.io/web   nginx   gateway.web.k8s.local   localhost   80, 443   74m

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl get gatewayclass
&lt;span class="go"&gt;NAME   CONTROLLER                                      ACCEPTED   AGE
eg     gateway.envoyproxy.io/gatewayclass-controller   True       117m
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Ingress serves HTTPS today
&lt;/h2&gt;

&lt;p&gt;Prove the starting point. A client that resolves gateway.web.k8s.local to the Ingress controller gets the page back over HTTPS, returning WEB APP OK. This is the behavior we must preserve through the migration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;curl &lt;span class="nt"&gt;-k&lt;/span&gt; https://gateway.web.k8s.local/
&lt;span class="go"&gt;WEB APP OK
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create the Gateway
&lt;/h2&gt;

&lt;p&gt;There is no kubectl create for these, so you author the YAML by hand from the Gateway API docs, the Simple Gateway and TLS termination examples, which are linked from the Kubernetes docs. Look at the file. apiVersion and kind declare a Gateway. The gatewayClassName is eg, the class you just saw was Accepted. Then one listener: HTTPS on port 443 for the hostname gateway.web.k8s.local. Under tls, mode Terminate with a certificateRef to web-tls, the very same Secret the Ingress used, so HTTPS is preserved. Every value came from the GatewayClass or the old Ingress. Apply it and wait until it reports Programmed, which means the controller has provisioned the data plane and assigned an address.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;gateway.yaml
&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Gateway: an HTTPS listener on 443 that terminates TLS with the web-tls Secret.
&lt;span class="go"&gt;apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: web-gateway
  namespace: web
spec:
  gatewayClassName: eg
  listeners:
    - name: https
      protocol: HTTPS
      port: 443
      hostname: gateway.web.k8s.local
      tls:
        mode: Terminate
        certificateRefs:
          - name: web-tls

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; gateway.yaml
&lt;span class="go"&gt;gateway.gateway.networking.k8s.io/web-gateway created

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; web get gateway web-gateway
&lt;span class="go"&gt;NAME          CLASS   ADDRESS         PROGRAMMED   AGE
web-gateway   eg      10.96.138.181   True         9s
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create the HTTPRoute
&lt;/h2&gt;

&lt;p&gt;Now the routing, from the docs HTTP routing example. Read the file. It is an HTTPRoute. parentRefs attaches it to the web-gateway you just made, so this route is served by that Gateway. hostnames matches gateway.web.k8s.local, the same host as before. And the one rule matches the path prefix slash and sends it to backendRefs, the web Service on port 80. The host, the path, and the backend are lifted straight from the old Ingress rule. Apply it and confirm the hostname is bound.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;httproute.yaml
&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;HTTPRoute: same host as the Ingress, path / -&amp;gt; the web Service on port 80.
&lt;span class="go"&gt;apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: web-route
  namespace: web
spec:
  parentRefs:
    - name: web-gateway
  hostnames:
    - gateway.web.k8s.local
  rules:
    - matches:
        - path:
            value: /
      backendRefs:
        - name: web
          port: 80

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; httproute.yaml
&lt;span class="go"&gt;httproute.gateway.networking.k8s.io/web-route created

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; web get httproute web-route
&lt;span class="go"&gt;NAME        HOSTNAMES                   AGE
web-route   ["gateway.web.k8s.local"]   0s
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Verify, then delete the Ingress
&lt;/h2&gt;

&lt;p&gt;Verify before you remove anything. The same request, now routed through the Gateway, returns WEB APP OK over HTTPS. Only once that works do you delete the old Ingress. Test one more time: traffic still flows through the Gateway, with the Ingress gone. The migration is complete with no outage.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;curl &lt;span class="nt"&gt;-k&lt;/span&gt; https://gateway.web.k8s.local/
&lt;span class="go"&gt;WEB APP OK

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; web delete ingress web
&lt;span class="go"&gt;ingress.networking.k8s.io "web" deleted from web namespace

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;curl &lt;span class="nt"&gt;-k&lt;/span&gt; https://gateway.web.k8s.local/
&lt;span class="go"&gt;WEB APP OK
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Exam tips
&lt;/h2&gt;

&lt;p&gt;A few traps. There is no kubectl create for Gateways or HTTPRoutes, so keep the Gateway API docs open and copy the manifests. Reuse the same TLS Secret on the Gateway listener so HTTPS keeps working. Wait for Programmed before testing, or you will curl a listener that is not up yet. And delete the Ingress last, only after the Gateway is verified, so you never drop traffic.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No imperative command: copy Gateway + HTTPRoute YAML from gateway-api.sigs.k8s.io&lt;/li&gt;
&lt;li&gt;Reuse the same TLS Secret on the Gateway listener to keep HTTPS&lt;/li&gt;
&lt;li&gt;Wait for the Gateway to be Programmed before you test&lt;/li&gt;
&lt;li&gt;Delete the Ingress LAST, only after the Gateway is verified&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Recap
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Gateway = listener + TLS; HTTPRoute = host + path -&amp;gt; Service&lt;/li&gt;
&lt;li&gt;Reuse the TLS Secret; wait for Programmed&lt;/li&gt;
&lt;li&gt;Verify HTTPS, then delete the Ingress last&lt;/li&gt;
&lt;li&gt;Subscribe + dev.to writeup&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Reproduce this yourself
&lt;/h2&gt;

&lt;p&gt;The entire scenario is scripted on a throwaway &lt;code&gt;kind&lt;/code&gt; cluster: &lt;a href="https://github.com/The-Cyber-Sidekick/TCS_CKA_2026_Exam_Scenarios" rel="noopener noreferrer"&gt;https://github.com/The-Cyber-Sidekick/TCS_CKA_2026_Exam_Scenarios&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/The-Cyber-Sidekick/TCS_CKA_2026_Exam_Scenarios.git
&lt;span class="nb"&gt;cd &lt;/span&gt;TCS_CKA_2026_Exam_Scenarios/learning/scenarios/scenario6-ingress-to-gateway
./setup.sh        &lt;span class="c"&gt;# creates the cluster AND arms the scenario&lt;/span&gt;
&lt;span class="c"&gt;# solve it by hand, or:&lt;/span&gt;
./solution.sh     &lt;span class="c"&gt;# apply the answer key and verify&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;If this helped, &lt;strong&gt;subscribe to The Cyber SideKick&lt;/strong&gt; on YouTube for more CKA drills, and grab the newsletter at &lt;a href="https://thecybersidekick.beehiiv.com" rel="noopener noreferrer"&gt;https://thecybersidekick.beehiiv.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>cka</category>
      <category>gatewayapi</category>
      <category>networking</category>
    </item>
    <item>
      <title>CKA Scenario 5 - Force nginx to TLS 1.3 with a ConfigMap edit + rolling restart (CKA Workloads)</title>
      <dc:creator>The Cyber Sidekick</dc:creator>
      <pubDate>Mon, 29 Jun 2026 12:53:22 +0000</pubDate>
      <link>https://dev.to/thecybersidekick/force-nginx-to-tls-13-with-a-configmap-edit-rolling-restart-cka-workloads-4cmb</link>
      <guid>https://dev.to/thecybersidekick/force-nginx-to-tls-13-with-a-configmap-edit-rolling-restart-cka-workloads-4cmb</guid>
      <description>&lt;h2&gt;
  
  
  Force nginx to TLS 1.3
&lt;/h2&gt;

&lt;p&gt;An nginx server is accepting an old TLS version, and the exam wants it locked to TLS one point three. The config lives in a ConfigMap. The catch is that editing the ConfigMap alone changes nothing. Let's do it the way the CKA expects.&lt;/p&gt;

&lt;p&gt;🎥 &lt;strong&gt;Watch the video:&lt;/strong&gt; &lt;a href="https://www.youtube.com/watch?v=rx-77YBw99w" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=rx-77YBw99w&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a CKA Workloads &amp;amp; Scheduling walkthrough. Every command below is real output from a live cluster, and you can reproduce the whole thing yourself (scripts at the end).&lt;/p&gt;

&lt;h2&gt;
  
  
  The scenario
&lt;/h2&gt;

&lt;p&gt;An nginx-static Deployment serves HTTPS, and its server config comes from a ConfigMap named nginx-config. Right now it allows both TLS one point two and one point three. Your task is to allow only TLS one point three, then make nginx actually use the change, so that a TLS one point two request fails.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;nginx-static serves HTTPS from the nginx-config ConfigMap&lt;/li&gt;
&lt;li&gt;It currently allows TLS 1.2 AND 1.3&lt;/li&gt;
&lt;li&gt;Restrict ssl_protocols to TLS 1.3 only&lt;/li&gt;
&lt;li&gt;A TLS 1.2 request to the Service must then fail&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How nginx, ConfigMaps, and rolling restarts fit together
&lt;/h2&gt;

&lt;p&gt;Two ideas drive this. First, ssl_protocols is an allow list; leave only TLSv1.3 and nginx rejects any older handshake. Second, a ConfigMap mounted into a pod updates the file on disk, but nginx only reads ssl_protocols when it starts. So you must roll the Deployment, with kubectl rollout restart, for the new value to take effect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspect the current state
&lt;/h2&gt;

&lt;p&gt;Start by seeing what is running and what the config says. The nginx-static Deployment, its Service on port four forty three, and the nginx-config ConfigMap are all here. Grep the rendered ConfigMap for the ssl_protocols line: it lists TLSv1.2 and TLSv1.3, so old clients still get in.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; nginx-static get deploy,svc,configmap
&lt;span class="go"&gt;NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-static   1/1     1            1           17h
deployment.apps/tester         1/1     1            1           17h

NAME                   TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
&lt;/span&gt;&lt;span class="gp"&gt;service/nginx-static   ClusterIP   10.96.13.162   &amp;lt;none&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;443/TCP   17h
&lt;span class="go"&gt;
NAME                         DATA   AGE
configmap/kube-root-ca.crt   1      17h
configmap/nginx-config       1      2s

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; nginx-static get configmap nginx-config &lt;span class="nt"&gt;-o&lt;/span&gt; yaml | &lt;span class="nb"&gt;grep &lt;/span&gt;ssl_protocols
&lt;span class="gp"&gt;        ssl_protocols TLSv1.2 TLSv1.3;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Confirm TLS 1.2 works today
&lt;/h2&gt;

&lt;p&gt;Prove the starting point from a real client. The tester pod curls the Service, pinned to a maximum of TLS one point two. It returns the page, which confirms the server accepts TLS one point two right now. That is exactly what we are about to stop.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; nginx-static &lt;span class="nb"&gt;exec &lt;/span&gt;deploy/tester &lt;span class="nt"&gt;--&lt;/span&gt; curl &lt;span class="nt"&gt;-sk&lt;/span&gt; &lt;span class="nt"&gt;--tlsv1&lt;/span&gt;.2 &lt;span class="nt"&gt;--tls-max&lt;/span&gt; 1.2 https://nginx-static.nginx-static.svc.cluster.local
&lt;span class="go"&gt;TLS OK
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Roll the Deployment
&lt;/h2&gt;

&lt;p&gt;Make nginx use it. A rolling restart replaces the pod, and the new pod reads the updated ssl_protocols on startup. Wait for the rollout to finish so you are testing the new pod, not the old one. This is the step people skip, and it is where the marks are.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; nginx-static rollout restart deploy/nginx-static
&lt;span class="go"&gt;deployment.apps/nginx-static restarted

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; nginx-static rollout status deploy/nginx-static
&lt;span class="go"&gt;Waiting for deployment "nginx-static" rollout to finish: 1 old replicas are pending termination...
Waiting for deployment "nginx-static" rollout to finish: 1 old replicas are pending termination...
deployment "nginx-static" successfully rolled out
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Prove it both ways. The same TLS one point two request now fails the handshake; curl reports an alert and exits non-zero, which is what we want. A normal request, letting curl negotiate, connects over TLS one point three and still returns the page. Old TLS is gone, the service still works.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; nginx-static &lt;span class="nb"&gt;exec &lt;/span&gt;deploy/tester &lt;span class="nt"&gt;--&lt;/span&gt; curl &lt;span class="nt"&gt;-sSk&lt;/span&gt; &lt;span class="nt"&gt;--tlsv1&lt;/span&gt;.2 &lt;span class="nt"&gt;--tls-max&lt;/span&gt; 1.2 https://nginx-static.nginx-static.svc.cluster.local
&lt;span class="go"&gt;curl: (35) OpenSSL/3.3.2: error:0A00042E:SSL routines::tlsv1 alert protocol version
command terminated with exit code 35

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; nginx-static &lt;span class="nb"&gt;exec &lt;/span&gt;deploy/tester &lt;span class="nt"&gt;--&lt;/span&gt; curl &lt;span class="nt"&gt;-skv&lt;/span&gt; https://nginx-static.nginx-static.svc.cluster.local | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-iE&lt;/span&gt; &lt;span class="s1"&gt;'SSL connection|TLS OK'&lt;/span&gt;
&lt;span class="go"&gt;* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 / x25519 / RSASSA-PSS
TLS OK
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Exam tips
&lt;/h2&gt;

&lt;p&gt;A few traps to remember. Editing a ConfigMap does not restart anything; without a rollout restart your change is invisible. ssl_protocols is an allow list, so list only the versions you want. Test with the client version pinned, because curl will quietly use TLS one point three and hide the problem otherwise. And always verify against the Service name, not just the pod.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Editing a ConfigMap does nothing until you roll the Deployment&lt;/li&gt;
&lt;li&gt;ssl_protocols is an allow-list: leave only TLSv1.3&lt;/li&gt;
&lt;li&gt;Pin the client (curl --tls-max 1.2) or you won't see the failure&lt;/li&gt;
&lt;li&gt;Verify against the Service, not just the pod&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Recap
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Set ssl_protocols to TLSv1.3 in the ConfigMap&lt;/li&gt;
&lt;li&gt;kubectl rollout restart so nginx re-reads it&lt;/li&gt;
&lt;li&gt;Verify TLS 1.2 fails, TLS 1.3 still serves&lt;/li&gt;
&lt;li&gt;Subscribe + dev.to writeup&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Reproduce this yourself
&lt;/h2&gt;

&lt;p&gt;The entire scenario is scripted on a throwaway &lt;code&gt;kind&lt;/code&gt; cluster: &lt;a href="https://github.com/The-Cyber-Sidekick/TCS_CKA_2026_Exam_Scenarios" rel="noopener noreferrer"&gt;https://github.com/The-Cyber-Sidekick/TCS_CKA_2026_Exam_Scenarios&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/The-Cyber-Sidekick/TCS_CKA_2026_Exam_Scenarios.git
&lt;span class="nb"&gt;cd &lt;/span&gt;TCS_CKA_2026_Exam_Scenarios/learning/scenarios/scenario5-nginx-tls-configmap
./setup.sh        &lt;span class="c"&gt;# creates the cluster AND arms the scenario&lt;/span&gt;
&lt;span class="c"&gt;# solve it by hand, or:&lt;/span&gt;
./solution.sh     &lt;span class="c"&gt;# apply the answer key and verify&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;If this helped, &lt;strong&gt;subscribe to The Cyber SideKick&lt;/strong&gt; on YouTube for more CKA drills, and grab the newsletter at &lt;a href="https://thecybersidekick.beehiiv.com" rel="noopener noreferrer"&gt;https://thecybersidekick.beehiiv.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>cka</category>
      <category>devops</category>
      <category>tls</category>
    </item>
    <item>
      <title>AI-Driven DevOps Is Reshaping CI/CD: From Pipeline Mechanics to Autonomous Orchestration</title>
      <dc:creator>The Cyber Sidekick</dc:creator>
      <pubDate>Mon, 29 Jun 2026 11:31:15 +0000</pubDate>
      <link>https://dev.to/thecybersidekick/ai-driven-devops-is-reshaping-cicd-from-pipeline-mechanics-to-autonomous-orchestration-3m3d</link>
      <guid>https://dev.to/thecybersidekick/ai-driven-devops-is-reshaping-cicd-from-pipeline-mechanics-to-autonomous-orchestration-3m3d</guid>
      <description>&lt;p&gt;&lt;em&gt;How ML agents and LLM-powered observability are moving DevOps teams from reactive pipeline management to predictive, self-healing infrastructure automation.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;AI-driven DevOps is eliminating manual CI/CD bottlenecks by turning pipelines into autonomous systems that detect, diagnose, and fix deployment issues before they reach production. The convergence of large language models, ML-based anomaly detection, and durable workflow orchestration is compressing mean-time-to-recovery from hours to minutes, with Gartner projecting that 40% of large enterprises will autonomously resolve infrastructure incidents without human intervention by 2027.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Reactive Pipeline Problem and Why It Is Breaking Under Modern Scale
&lt;/h2&gt;

&lt;p&gt;Traditional DevOps pipelines are fundamentally reactive: alerts fire after production metrics degrade, rollbacks trigger after error budgets are burned, and on-call engineers diagnose failures that users have already encountered. This approach creates mean-time-to-recovery gaps measured in minutes to hours, with threshold-based alerting generating noise that masks real signals until damage is done. The structural problem is that pipelines were designed as linear executors, not intelligent decision-makers, so every anomaly outside a predefined threshold requires human judgment to classify, prioritize, and remediate. Organizations using ML-based anomaly detection on deployment pipelines are reporting mean-time-to-detect reductions of 60 to 70 percent compared to threshold-based alerting, according to Dynatrace's 2024 State of Observability report, which illustrates the scale of the opportunity left untapped by conventional tooling.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Emerging AI-Agentic Infrastructure Stack
&lt;/h2&gt;

&lt;p&gt;The ecosystem is moving rapidly from AI-assisted tooling toward AI-agentic infrastructure, where platforms make autonomous decisions within policy-encoded boundaries rather than merely surfacing recommendations to humans. Dynatrace Davis combines causal AI topology mapping with LLM-generated root cause explanations, correlating logs, traces, and metrics simultaneously rather than in isolation. GitOps controllers like Argo CD are being extended with Keptn integrations that evaluate deployment risk scores derived from historical telemetry and automatically pause or roll back Helm releases based on SLO breach signals, effectively encoding SRE judgment as executable policy. Temporal.io has emerged as a critical durable execution backbone for these autonomous remediation agents, providing retry semantics, state persistence, and full workflow auditability across multi-step sequences; the platform reported over 500 billion workflow actions executed in 2024, reflecting how quickly durable orchestration is becoming the control plane for complex automated remediation. Startups including Cortex, Harness, and Port are layering ML models trained on deployment patterns directly into internal developer portals, surfacing reliability recommendations before code reaches merge.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Trends Defining the Next Generation of Intelligent Pipelines
&lt;/h2&gt;

&lt;p&gt;Four converging trends are shaping how AI integrates into DevOps workflows at scale. First, the standardization of OpenTelemetry as a unified telemetry substrate is giving AI models consistent, vendor-agnostic data to reason over, removing the fragmentation that previously made cross-stack correlation impractical. Second, GitOps-native AI policy engines are encoding remediation runbooks as version-controlled code reviewed alongside application manifests, making autonomous decisions auditable and reversible through standard pull request workflows. Third, SRE copilots powered by LLMs fine-tuned on incident postmortems, Kubernetes event streams, and infrastructure runbooks are generating contextual remediation playbooks in real time, reducing the cognitive load on engineers during active incidents. Fourth, the combination of these signals into unified AI observability agents is enabling platforms to move from detecting that something is wrong to explaining why it is wrong and executing a fix, all within a single automated feedback loop.&lt;/p&gt;

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

&lt;p&gt;The trajectory of AI-driven DevOps points toward infrastructure that is less a pipeline to be managed and more an autonomous system to be governed. The foundational pieces are already in production: OpenTelemetry provides the data substrate, Temporal provides the execution durability, Argo CD and Keptn provide the GitOps enforcement layer, and LLMs provide the contextual reasoning that previously required senior engineers. The near-term challenge for platform teams is not adoption but governance: defining the policy boundaries within which AI agents are permitted to act autonomously, ensuring auditability trails satisfy compliance requirements, and building the human-in-the-loop escalation paths that preserve trust when autonomous decisions fail. With Gartner projecting that fewer than 5% of enterprises autonomously resolve infrastructure incidents today versus 40% by 2027, the organizations that invest now in durable orchestration, telemetry standardization, and AI policy frameworks will hold a compounding reliability and velocity advantage over those still waiting for the tooling to mature.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Technologies covered:&lt;/strong&gt; LLMs for log analysis and root cause detection, ML-based anomaly detection in deployment patterns, Autonomous workflow orchestration (Temporal, Dagster), GitOps + AI decision engines, Observability platforms with AI correlation&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sources aggregated from: DevOps Weekly, GitHub Trending, Hacker News, The New Stack&lt;/em&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  📬 Stay current with cloud-native
&lt;/h3&gt;

&lt;p&gt;Get the latest Kubernetes, DevOps, and platform engineering insights delivered to your inbox.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://thecybersidekick.beehiiv.com/subscribe" rel="noopener noreferrer"&gt;Subscribe to The Cyber SideKick Newsletter&lt;/a&gt;&lt;/strong&gt; — free, no spam, unsubscribe anytime.&lt;/p&gt;

</description>
      <category>aidrivendevops</category>
      <category>cicdautomation</category>
      <category>llmloganalysis</category>
      <category>mlanomalydetection</category>
    </item>
    <item>
      <title>Prepare a node for kubeadm with cri-dockerd (CKA Installation)</title>
      <dc:creator>The Cyber Sidekick</dc:creator>
      <pubDate>Fri, 26 Jun 2026 19:46:46 +0000</pubDate>
      <link>https://dev.to/thecybersidekick/prepare-a-node-for-kubeadm-with-cri-dockerd-cka-installation-3936</link>
      <guid>https://dev.to/thecybersidekick/prepare-a-node-for-kubeadm-with-cri-dockerd-cka-installation-3936</guid>
      <description>&lt;h2&gt;
  
  
  Prepare a Node for kubeadm with cri-dockerd
&lt;/h2&gt;

&lt;p&gt;This is one of those CKA tasks with no manifest to copy from the docs. You prepare a plain Linux box so kubeadm can use Docker as the runtime. It is pure system administration, and you have to know the steps cold. Let's walk through it.&lt;/p&gt;

&lt;p&gt;This is a CKA Cluster Architecture, Installation &amp;amp; Configuration walkthrough. Every command below is real output from a live cluster, and you can reproduce the whole thing yourself (scripts at the end).&lt;/p&gt;

&lt;h2&gt;
  
  
  The scenario
&lt;/h2&gt;

&lt;p&gt;Docker is already installed on this node, but kubeadm cannot talk to Docker directly anymore. You install cri-dockerd, the shim that lets the kubelet use Docker as a container runtime, then enable its service, then set the kernel parameters Kubernetes networking depends on and load them without a reboot.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Debian node with Docker present, but no CRI shim&lt;/li&gt;
&lt;li&gt;Install the cri-dockerd package with dpkg&lt;/li&gt;
&lt;li&gt;Enable and start the cri-docker service&lt;/li&gt;
&lt;li&gt;Set the required sysctl params and load them now&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why cri-dockerd and these kernel params
&lt;/h2&gt;

&lt;p&gt;Since Kubernetes 1.24 the kubelet only speaks the Container Runtime Interface. Docker does not implement it, so cri-dockerd sits in between: the kubelet connects to the cri-docker socket, and cri-dockerd translates to Docker. On top of that, the kubelet and kube-proxy need bridged traffic to be visible to iptables and need IP forwarding on, which is what the sysctl settings provide.&lt;/p&gt;

&lt;h2&gt;
  
  
  Confirm the gap
&lt;/h2&gt;

&lt;p&gt;Start by confirming the gap. The cri-dockerd package is not installed, so the kubelet would have nothing to connect to and kubeadm init would fail before it even starts. And this is a Debian box with Docker already present, so we will grab the debian-built package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;dpkg &lt;span class="nt"&gt;-l&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;cri-dockerd &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'cri-dockerd: not installed'&lt;/span&gt;
&lt;span class="go"&gt;cri-dockerd: not installed

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;grep &lt;/span&gt;PRETTY_NAME /etc/os-release
&lt;span class="go"&gt;PRETTY_NAME="Debian GNU/Linux 13 (trixie)"
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Install the package
&lt;/h2&gt;

&lt;p&gt;Install the package the exam way, with dpkg. Here the .deb is fetched from the cri-dockerd releases; in the exam it is already staged on the box. Run &lt;code&gt;dpkg -i&lt;/code&gt;, then confirm dpkg lists it. If dpkg reported missing dependencies you would run &lt;code&gt;apt-get install -f&lt;/code&gt; to fix them, but a single static package like this usually needs nothing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;wget &lt;span class="nt"&gt;-q&lt;/span&gt; https://github.com/Mirantis/cri-dockerd/releases/download/v0.4.3/cri-dockerd_0.4.3.3-0.debian-bookworm_amd64.deb &lt;span class="nt"&gt;-O&lt;/span&gt; cri-dockerd.deb &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-lh&lt;/span&gt; cri-dockerd.deb
&lt;span class="go"&gt;-rw-r--r-- 1 root root 11M Apr 28 09:59 cri-dockerd.deb

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;dpkg &lt;span class="nt"&gt;-i&lt;/span&gt; cri-dockerd.deb
&lt;span class="go"&gt;Selecting previously unselected package cri-dockerd.
(Reading database ... 24903 files and directories currently installed.)
Preparing to unpack cri-dockerd.deb ...
Unpacking cri-dockerd (0.4.3~3-0~debian-bookworm) ...
Setting up cri-dockerd (0.4.3~3-0~debian-bookworm) ...
Created symlink '/etc/systemd/system/multi-user.target.wants/cri-docker.service' → '/usr/lib/systemd/system/cri-docker.service'.
Created symlink '/etc/systemd/system/sockets.target.wants/cri-docker.socket' → '/usr/lib/systemd/system/cri-docker.socket'.
/usr/sbin/policy-rc.d returned 101, not running 'start cri-docker.service cri-docker.socket'

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;dpkg &lt;span class="nt"&gt;-l&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;cri-dockerd
&lt;span class="go"&gt;ii  cri-dockerd                      0.4.3~3-0~debian-bookworm            amd64        cri-dockerd is a lightweight implementation of the CRI specification which talks to docker.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Enable + start the service
&lt;/h2&gt;

&lt;p&gt;Now enable and start cri-docker. The kubelet connects through the socket unit, so &lt;code&gt;enable --now&lt;/code&gt; on cri-docker.socket, and enable the service so it survives a reboot. The socket comes up listening immediately; the service itself starts on demand the first time the kubelet connects.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable&lt;/span&gt; &lt;span class="nt"&gt;--now&lt;/span&gt; cri-docker.socket
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl &lt;span class="nb"&gt;enable &lt;/span&gt;cri-docker.service
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;systemctl is-enabled cri-docker.socket cri-docker.service
&lt;span class="go"&gt;enabled
enabled

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;systemctl status cri-docker.socket &lt;span class="nt"&gt;--no-pager&lt;/span&gt;
&lt;span class="go"&gt;● cri-docker.socket - CRI Docker Socket for the API
&lt;/span&gt;&lt;span class="gp"&gt;     Loaded: loaded (/usr/lib/systemd/system/cri-docker.socket;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;enabled&lt;span class="p"&gt;;&lt;/span&gt; preset: enabled&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;     Active: active (listening) since Thu 2026-06-25 17:59:47 UTC;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;447ms ago
&lt;span class="go"&gt; Invocation: f4095949423e40418fecae56ada9ccc1
   Triggers: ● cri-docker.service
     Listen: /run/cri-dockerd.sock (Stream)
      Tasks: 0 (limit: 19008)
     Memory: 0B (peak: 256K)
        CPU: 693us
     CGroup: /system.slice/cri-docker.socket

Jun 25 17:59:47 cka-scenario4-control-plane systemd[1]: Starting cri-docker.socket - CRI Docker Socket for the API...
Jun 25 17:59:47 cka-scenario4-control-plane systemd[1]: Listening on cri-docker.socket - CRI Docker Socket for the API.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Configure kernel params
&lt;/h2&gt;

&lt;p&gt;Next, the kernel parameters. The bridge keys only exist once the &lt;code&gt;br_netfilter&lt;/code&gt; module is loaded, and nf_conntrack_max needs the nf_conntrack module, so load both and record them in modules-load.d so they come back after a reboot. Then drop the four parameters into a dedicated file under sysctl.d, which is the persistent, best-practice place for them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;modprobe br_netfilter nf_conntrack
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;' | sudo tee /etc/modules-load.d/k8s.conf
&lt;/span&gt;&lt;span class="go"&gt;br_netfilter
nf_conntrack
EOF
br_netfilter
nf_conntrack

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;' | sudo tee /etc/sysctl.d/k8s.conf
&lt;/span&gt;&lt;span class="go"&gt;net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
net.netfilter.nf_conntrack_max      = 131072
EOF
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
net.netfilter.nf_conntrack_max      = 131072

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cat&lt;/span&gt; /etc/sysctl.d/k8s.conf
&lt;span class="go"&gt;net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
net.netfilter.nf_conntrack_max      = 131072
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Load + verify
&lt;/h2&gt;

&lt;p&gt;Apply the settings without rebooting and verify. &lt;code&gt;sysctl --system&lt;/code&gt; re-reads every file under sysctl.d, so the new values take effect right now. Then read the keys back: bridged traffic is now visible to iptables on IPv4 and IPv6, and forwarding is on. The conntrack maximum is written into the same file, so it is in place for the node too. The box is ready for kubeadm.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;sysctl &lt;span class="nt"&gt;--system&lt;/span&gt;
&lt;span class="go"&gt;* Applying /etc/sysctl.d/k8s.conf ...

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward
&lt;span class="go"&gt;net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Exam tips
&lt;/h2&gt;

&lt;p&gt;A few things that trip people up. Use the package they tell you to and install it with &lt;code&gt;dpkg -i&lt;/code&gt;, not apt. The kubelet talks to the socket, so enable the socket, not just the service. The bridge sysctls silently fail to apply if &lt;code&gt;br_netfilter&lt;/code&gt; is not loaded, so modprobe it first. And always finish with &lt;code&gt;sysctl --system&lt;/code&gt; and read the values back, because a config file that is never loaded scores zero.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install the given .deb with dpkg -i (apt-get -f install only if deps complain)&lt;/li&gt;
&lt;li&gt;Enable cri-docker.socket, not just the service, the kubelet uses the socket&lt;/li&gt;
&lt;li&gt;modprobe br_netfilter first or the bridge keys never appear&lt;/li&gt;
&lt;li&gt;Finish with sysctl --system and verify each value&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Recap
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;dpkg -i the cri-dockerd package&lt;/li&gt;
&lt;li&gt;enable --now cri-docker.socket + enable the service&lt;/li&gt;
&lt;li&gt;Persist modules + four sysctl params, then sysctl --system&lt;/li&gt;
&lt;li&gt;Subscribe + dev.to writeup&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Reproduce this yourself
&lt;/h2&gt;

&lt;p&gt;The entire scenario is scripted on a throwaway &lt;code&gt;kind&lt;/code&gt; cluster: &lt;a href="https://github.com/The-Cyber-Sidekick/TCS_CKA_2026_Exam_Scenarios" rel="noopener noreferrer"&gt;https://github.com/The-Cyber-Sidekick/TCS_CKA_2026_Exam_Scenarios&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/The-Cyber-Sidekick/TCS_CKA_2026_Exam_Scenarios.git
&lt;span class="nb"&gt;cd &lt;/span&gt;TCS_CKA_2026_Exam_Scenarios/learning/scenarios/scenario4-cri-dockerd-system-prep
./setup.sh        &lt;span class="c"&gt;# creates the cluster AND arms the scenario&lt;/span&gt;
&lt;span class="c"&gt;# solve it by hand, or:&lt;/span&gt;
./solution.sh     &lt;span class="c"&gt;# apply the answer key and verify&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;If this helped, &lt;strong&gt;subscribe to The Cyber SideKick&lt;/strong&gt; on YouTube for more CKA drills, and grab the newsletter at &lt;a href="https://thecybersidekick.beehiiv.com" rel="noopener noreferrer"&gt;https://thecybersidekick.beehiiv.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>cka</category>
      <category>devops</category>
      <category>linux</category>
    </item>
    <item>
      <title>WebAssembly on Kubernetes: The Next Generation Runtime for Edge and Serverless Workloads</title>
      <dc:creator>The Cyber Sidekick</dc:creator>
      <pubDate>Tue, 23 Jun 2026 19:46:58 +0000</pubDate>
      <link>https://dev.to/thecybersidekick/webassembly-on-kubernetes-the-next-generation-runtime-for-edge-and-serverless-workloads-2kid</link>
      <guid>https://dev.to/thecybersidekick/webassembly-on-kubernetes-the-next-generation-runtime-for-edge-and-serverless-workloads-2kid</guid>
      <description>&lt;p&gt;&lt;em&gt;How WASM is moving from browser curiosity to production-grade orchestration with Kubernetes as the control plane.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;WebAssembly has evolved far beyond its browser origins, emerging as a serious contender for edge and serverless runtimes thanks to sub-millisecond cold starts, compact binary sizes, and a robust security sandbox model. With Kubernetes now capable of scheduling WASM workloads as first-class citizens alongside OCI containers, platform engineers have a credible path to adopting WASM at scale without abandoning existing orchestration infrastructure.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  From Browser Sandbox to Server-Side Runtime: The Role of WASI
&lt;/h2&gt;

&lt;p&gt;WebAssembly was originally designed as a portable binary instruction format for executing compute-intensive workloads in browser sandboxes at near-native speeds, but its utility was fundamentally constrained by the absence of any standardized system interface. The WebAssembly System Interface (WASI) changed that trajectory by providing a capability-based API surface for system-level interactions including file I/O, networking, and environment access, effectively decoupling WASM from the browser and making it a viable candidate for server-side and edge execution environments. This architectural shift is significant because WASI enforces a least-privilege model by design: a WASM module receives only the capabilities explicitly granted to it at runtime, giving platform operators a security isolation model that sits between traditional process-level sandboxing and full VM overhead, which is particularly appealing for multi-tenant FaaS platforms looking to minimize blast radius without the cost of hardware virtualization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Kubernetes as the WASM Orchestration Plane: runwasi, Spin, and SpinKube
&lt;/h2&gt;

&lt;p&gt;The critical enabler for WASM adoption at scale is the containerd shim ecosystem, specifically the runwasi project, which implements a containerd shim host that allows Kubernetes kubelets to manage WASM runtimes such as Wasmtime and WasmEdge directly through the Container Runtime Interface (CRI). This means a Kubernetes scheduler can treat a WASM workload with the same lifecycle semantics it applies to any OCI container, with no changes required to the control plane itself. Fermyon's Spin framework builds on this foundation by providing a developer-focused abstraction for authoring and deploying WASM microservices, and SpinKube, accepted into the CNCF sandbox in 2024, consolidates the containerd-wasm-shims project with the Spin Operator to deliver a production-grade pattern for running Spin applications on Kubernetes clusters at scale. The graduation of SpinKube into the CNCF sandbox is a meaningful signal of industry consensus: Kubernetes is becoming the primary orchestration plane for WASM workloads, and the tooling is maturing fast enough to support production adoption.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cold Starts, Binary Size, and the Edge Computing Value Proposition
&lt;/h2&gt;

&lt;p&gt;The performance characteristics of WASM runtimes are what make the edge and serverless case compelling for practitioners who have grown frustrated with container cold-start penalties. Wasmtime and WasmEdge achieve cold-start times under 1 millisecond, compared to the 50 to 500 millisecond range typical of container-based functions, a 100 to 500x improvement that is directly relevant for latency-sensitive workloads such as edge inference pipelines and API gateway request handlers. The binary size advantage compounds this: a simple Spin HTTP handler compiles to under 2MB, while a functionally equivalent Alpine-based container image typically lands between 10 and 20MB, translating to a 10 to 100x reduction in storage and bandwidth requirements that matters enormously when deploying to constrained edge nodes. KubeEdge is already integrating WASM runtimes for exactly this reason, pushing lightweight workloads to edge hardware where the overhead of a full container stack would be prohibitive, and where the rapid instantiation of WASM modules directly supports the bursty, event-driven traffic patterns common in IoT and real-time data processing scenarios.&lt;/p&gt;

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

&lt;p&gt;WebAssembly's trajectory from browser novelty to production runtime is no longer speculative. The combination of WASI standardization, mature containerd shim implementations, and Kubernetes operator patterns for lifecycle management has created an ecosystem that practitioners can adopt today with reasonable confidence. The WASM component model, still stabilizing in 2024, promises to further simplify composition of WASM modules across language boundaries, which will lower the authoring barrier and accelerate adoption in polyglot microservices environments. Platform engineers evaluating serverless and edge runtimes should treat WASM not as a replacement for containers but as a complementary execution tier optimized for startup latency, binary portability, and security isolation, with Kubernetes providing the unified control plane that makes operating both tiers tractable. The projects and cloud provider investments landing right now suggest that organizations who build WASM operational experience in 2024 and 2025 will be positioned significantly ahead of those who wait for the ecosystem to fully stabilize.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Technologies covered:&lt;/strong&gt; WebAssembly (WASM), Kubernetes, Wasmtime, Containerd shims, KubeEdge, Spin, Fermyon, WASI&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sources aggregated from: CNCF Blog, Kubernetes.io, DevOps Weekly, Hacker News, InfoQ, The New Stack&lt;/em&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  📬 Stay current with cloud-native
&lt;/h3&gt;

&lt;p&gt;Get the latest Kubernetes, DevOps, and platform engineering insights delivered to your inbox.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://thecybersidekick.beehiiv.com/subscribe" rel="noopener noreferrer"&gt;Subscribe to The Cyber SideKick Newsletter&lt;/a&gt;&lt;/strong&gt; — free, no spam, unsubscribe anytime.&lt;/p&gt;

</description>
      <category>webassembly</category>
      <category>kubernetes</category>
      <category>edgecomputing</category>
      <category>serverless</category>
    </item>
    <item>
      <title>AI Inference Optimization in Cloud-Native Environments: GPU Orchestration, Edge Deployment, and Latency Reduction at Scale</title>
      <dc:creator>The Cyber Sidekick</dc:creator>
      <pubDate>Tue, 23 Jun 2026 19:41:06 +0000</pubDate>
      <link>https://dev.to/thecybersidekick/ai-inference-optimization-in-cloud-native-environments-gpu-orchestration-edge-deployment-and-22n7</link>
      <guid>https://dev.to/thecybersidekick/ai-inference-optimization-in-cloud-native-environments-gpu-orchestration-edge-deployment-and-22n7</guid>
      <description>&lt;p&gt;&lt;em&gt;How enterprises are containerizing LLM workloads on Kubernetes, managing heterogeneous GPU fleets, and pushing inference to the edge to control costs and meet sub-50ms latency targets.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;As AI inference workloads surge in production, cloud-native teams are building specialized infrastructure disciplines around GPU-accelerated Kubernetes clusters, optimized runtime engines, and edge deployment patterns. The convergence of large language model demands with Kubernetes-native tooling has made inference infrastructure a first-class engineering concern, where decisions about schedulers, memory management, and observability pipelines directly translate to cost efficiency and user experience.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Containerizing GPU Workloads: The Kubernetes Inference Stack Takes Shape
&lt;/h2&gt;

&lt;p&gt;Enterprises migrating LLM inference onto Kubernetes are assembling a layered stack that spans hardware automation, model serving, and runtime optimization. The NVIDIA GPU Operator handles the unglamorous but critical work of automating driver installation, CUDA toolkit deployment, device plugin lifecycle management, and MIG partitioning configuration, allowing platform teams to treat GPU nodes as cattle rather than pets. On top of that foundation, KServe has matured into a production-grade serving platform with InferenceService CRDs that support canary rollouts, transformer pipelines, and multi-framework inference, while MLflow integration enables CI/CD-driven model promotion pipelines from experiment registry to live endpoint. The dominant inference engine choice is vLLM, whose PagedAttention algorithm reduces GPU KV cache memory waste from the 60-80% typical of naive implementations down to under 4%, translating to throughput gains of up to 24x on equivalent hardware; NVIDIA's Triton Inference Server complements this by providing dynamic batching and ONNX/TensorRT backend support for non-LLM workloads deployed as standard Kubernetes Deployments. Cold-start latency remains a persistent operational pain point, with containerized 7B parameter models averaging 8 to 15 minutes to initialize due to registry pull times, a problem teams are solving by pre-staging model weights on local NVMe storage using init containers or CSI volume pre-population to bring startup time below 30 seconds.&lt;/p&gt;

&lt;h2&gt;
  
  
  GPU Resource Allocation and the Rise of Prefill-Decode Disaggregation
&lt;/h2&gt;

&lt;p&gt;Efficient GPU resource allocation in Kubernetes requires moving beyond simple device requests and into architectural patterns that match compute characteristics to workload phases. The most significant emerging pattern is prefill-decode disaggregation, pioneered by projects like MoonCake and DistServe, which splits the computationally dense prefill phase and the memory-bandwidth-bound decode phase of LLM inference across separate Kubernetes node pools, allowing each pool to be sized and scaled independently for cost optimization. NVIDIA MIG partitioning on H100 GPUs adds another dimension to resource granularity, allowing a single physical GPU to be divided into up to 7 isolated instances, each with dedicated VRAM and compute slices, so Kubernetes schedulers can place smaller inference workloads with full hardware-level isolation rather than requiring a whole GPU per replica. Quantization techniques including GPTQ, AWQ, and FP8 are compressing models by 2 to 4x with minimal accuracy degradation, directly reducing the VRAM footprint per replica and enabling denser bin-packing across node pools. The industry is simultaneously standardizing on OpenAI-compatible REST APIs as the inference contract, meaning platform teams can swap vLLM for Triton or a future backend without touching client code, preserving flexibility as the hardware and software landscape continues to shift rapidly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Edge Inference, Sub-50ms Latency, and Full-Stack Observability
&lt;/h2&gt;

&lt;p&gt;For latency-sensitive applications where round-trip times to centralized cloud regions are unacceptable, enterprises are deploying GPU-attached edge clusters using lightweight Kubernetes distributions like K3s and MicroK8s, running quantized models with FP8 or INT4 precision to fit within the constrained VRAM of edge-class accelerators and achieve sub-50ms inference latency. This edge pattern is not a replacement for centralized inference fleets but a complement, with routing logic directing latency-critical requests to the nearest edge node while batch and background workloads run on cheaper, centralized A100 or H100 capacity. Observability across this distributed topology requires stitching together multiple telemetry layers: DCGM Exporter surfaces GPU utilization, memory bandwidth, and SM occupancy metrics that are federated into OpenTelemetry pipelines, while eBPF-based tools such as Pixie, Hubble, and Tetragon capture syscall traces and network-level telemetry that can be correlated with GPU kernel execution timelines in unified dashboards. This combination gives platform teams the ability to trace a single inference request from the client HTTP call through the service mesh, into the container runtime, and down to the GPU kernel, an observability depth that was practically impossible before the convergence of eBPF tooling with GPU metrics exporters. KEDA and Knative autoscaling integrations within KServe close the loop by allowing inference deployments to scale replica counts based on queue depth or custom GPU utilization thresholds rather than CPU-centric HPA metrics that are poorly suited to accelerator workloads.&lt;/p&gt;

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

&lt;p&gt;The cloud-native AI inference stack is consolidating rapidly around a recognizable set of components: the NVIDIA GPU Operator for hardware lifecycle management, vLLM or Triton for runtime efficiency, KServe for serving orchestration, and eBPF-based observability pipelines for full-stack visibility. The next phase of maturity will be defined by prefill-decode disaggregation becoming a default deployment pattern, MIG partitioning enabling finer-grained multi-tenancy on expensive H100 and Blackwell hardware, and edge inference clusters becoming standard extensions of enterprise AI infrastructure rather than experimental outliers. Platform teams that invest now in model caching infrastructure, quantization pipelines, and GPU-aware autoscaling policies will be positioned to serve the next generation of AI applications at scale without allowing costs and latency to spiral; those that treat inference as a simple container deployment problem will find themselves rebuilding their infrastructure under production pressure, a far more expensive lesson to learn.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Technologies covered:&lt;/strong&gt; Kubernetes GPU scheduling and resource management, Container image optimization for LLMs, KServe and MLflow for model serving, eBPF monitoring for AI workload observability, vLLM and similar inference engines, NVIDIA container toolkit and GPU device plugins&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sources aggregated from: CNCF Blog, Kubernetes.io, DevOps Weekly, Hacker News, InfoQ, The New Stack&lt;/em&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  📬 Stay current with cloud-native
&lt;/h3&gt;

&lt;p&gt;Get the latest Kubernetes, DevOps, and platform engineering insights delivered to your inbox.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://thecybersidekick.beehiiv.com/subscribe" rel="noopener noreferrer"&gt;Subscribe to The Cyber SideKick Newsletter&lt;/a&gt;&lt;/strong&gt; — free, no spam, unsubscribe anytime.&lt;/p&gt;

</description>
      <category>kubernetesgpuscheduling</category>
      <category>aiinferenceoptimization</category>
      <category>llmdeployment</category>
      <category>vllm</category>
    </item>
    <item>
      <title>CKA Exam 2026 Scenario 3 - Pick the least-permissive NetworkPolicy to connect two namespaces (CKA)</title>
      <dc:creator>The Cyber Sidekick</dc:creator>
      <pubDate>Mon, 22 Jun 2026 14:28:10 +0000</pubDate>
      <link>https://dev.to/thecybersidekick/pick-the-least-permissive-networkpolicy-to-connect-two-namespaces-cka-1f53</link>
      <guid>https://dev.to/thecybersidekick/pick-the-least-permissive-networkpolicy-to-connect-two-namespaces-cka-1f53</guid>
      <description>&lt;h2&gt;
  
  
  The Least-Permissive Policy
&lt;/h2&gt;

&lt;p&gt;Two deployments in two namespaces need to talk, but a default-deny policy is in the way. The exam does not just want them connected. It wants the least permissive policy that does the job. Let's do it the way the CKA expects.&lt;/p&gt;

&lt;p&gt;🎥 &lt;strong&gt;Watch the video:&lt;/strong&gt; &lt;a href="https://www.youtube.com/watch?v=tgfQlTP2NqI" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=tgfQlTP2NqI&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a CKA Services &amp;amp; Networking walkthrough. Every command below is real output from a live cluster, and you can reproduce the whole thing yourself (scripts at the end).&lt;/p&gt;

&lt;h2&gt;
  
  
  The scenario
&lt;/h2&gt;

&lt;p&gt;A frontend deployment in the frontend namespace must reach a backend deployment in the backend namespace. The backend already has a default-deny ingress policy that you must not touch. Three candidate policies sit in a netpol directory. Your task is to apply only the one that is correct and least permissive.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;frontend namespace must reach the backend namespace&lt;/li&gt;
&lt;li&gt;Backend has a default-deny ingress policy (do not modify it)&lt;/li&gt;
&lt;li&gt;Three candidate policies wait in netpol/&lt;/li&gt;
&lt;li&gt;Apply only the correct, least-permissive one&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How NetworkPolicy works
&lt;/h2&gt;

&lt;p&gt;A default-deny policy selects every pod in a namespace and allows no ingress, so all incoming traffic is dropped. You restore traffic by adding an allow policy alongside it. Policies are additive. The least permissive allow names both the source namespace and the source pod label, and a port, so nothing else gets in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Inspect the lockdown
&lt;/h2&gt;

&lt;p&gt;Start by seeing what is already there. The backend namespace has one policy, default-deny. Describe it: an empty pod selector, so it matches every pod, and an ingress type with no rules, which means deny everything.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; backend get networkpolicy
&lt;span class="go"&gt;NAME           POD-SELECTOR   AGE
&lt;/span&gt;&lt;span class="gp"&gt;default-deny   &amp;lt;none&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;78m
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; backend describe networkpolicy default-deny
&lt;span class="go"&gt;Name:         default-deny
Namespace:    backend
Created on:   2026-06-22 09:08:14 -0400 EDT
&lt;/span&gt;&lt;span class="gp"&gt;Labels:       &amp;lt;none&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;Annotations:  &amp;lt;none&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="go"&gt;Spec:
&lt;/span&gt;&lt;span class="gp"&gt;  PodSelector:     &amp;lt;none&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;Allowing the specific traffic to all pods &lt;span class="k"&gt;in &lt;/span&gt;this namespace&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;  Allowing ingress traffic:
&lt;/span&gt;&lt;span class="gp"&gt;    &amp;lt;none&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;Selected pods are isolated &lt;span class="k"&gt;for &lt;/span&gt;ingress connectivity&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;  Not affecting egress traffic
  Policy Types: Ingress
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Reproduce symptom
&lt;/h2&gt;

&lt;p&gt;Confirm the symptom from inside the cluster. Exec into the frontend pod and try to fetch the backend service. The request times out. The default-deny is doing exactly its job.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; frontend &lt;span class="nb"&gt;exec &lt;/span&gt;deploy/frontend &lt;span class="nt"&gt;--&lt;/span&gt; wget &lt;span class="nt"&gt;-T&lt;/span&gt; 5 &lt;span class="nt"&gt;-qO-&lt;/span&gt; http://backend.backend.svc.cluster.local
&lt;span class="go"&gt;wget: download timed out
command terminated with exit code 1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Review the candidates
&lt;/h2&gt;

&lt;p&gt;Now read the three candidates. The first allows the whole frontend namespace, which works but is too open. The third has an empty ingress list, so it allows nothing. The second allows only pods labelled frontend, in the frontend namespace, on port 80. The namespace selector and pod selector share one from entry, so both must match. That is the least permissive policy that still connects them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;netpol/
&lt;span class="go"&gt;netpol1-allow-namespace.yaml
netpol2-allow-frontend.yaml
netpol3-empty-ingress.yaml

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;netpol/netpol1-allow-namespace.yaml
&lt;span class="c"&gt;...
&lt;/span&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;the frontend namespace &lt;span class="o"&gt;(&lt;/span&gt;namespaceSelector only, no podSelector, no port&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; It would
&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;work, but it opens the backend to any workload that lands &lt;span class="k"&gt;in &lt;/span&gt;that namespace.
&lt;span class="go"&gt;spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
    - Ingress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: frontend

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;netpol/netpol3-empty-ingress.yaml
&lt;span class="c"&gt;...
&lt;/span&gt;&lt;span class="go"&gt;metadata:
  name: deny-frontend
  namespace: backend
&lt;/span&gt;&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Candidate 3 — WRONG. It selects the backend pods but its ingress list is empty, so
&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;it allows nothing. Applying this does not restore communication&lt;span class="p"&gt;;&lt;/span&gt; it is just a second
&lt;span class="gp"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;deny on top of the existing default-deny.
&lt;span class="go"&gt;spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
    - Ingress
  ingress: []

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;netpol/netpol2-allow-frontend.yaml
&lt;span class="c"&gt;...
&lt;/span&gt;&lt;span class="go"&gt;  policyTypes:
    - Ingress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: frontend
          podSelector:
            matchLabels:
              app: frontend
      ports:
        - protocol: TCP
          port: 80
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Apply the fix
&lt;/h2&gt;

&lt;p&gt;Apply the second policy, and only that one. The default-deny stays exactly where it was. The backend namespace now has two policies working together.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; netpol/netpol2-allow-frontend.yaml
&lt;span class="go"&gt;networkpolicy.networking.k8s.io/allow-frontend created

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; backend get networkpolicy
&lt;span class="go"&gt;NAME             POD-SELECTOR   AGE
allow-frontend   app=backend    0s
&lt;/span&gt;&lt;span class="gp"&gt;default-deny     &amp;lt;none&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;         &lt;/span&gt;78m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Prove it. The same probe from the frontend pod now returns the nginx welcome page, and the describe shows the allow rule scoped to the frontend pod label on port 80. Communication is restored, with the tightest possible rule.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; frontend &lt;span class="nb"&gt;exec &lt;/span&gt;deploy/frontend &lt;span class="nt"&gt;--&lt;/span&gt; wget &lt;span class="nt"&gt;-T&lt;/span&gt; 5 &lt;span class="nt"&gt;-qO-&lt;/span&gt; http://backend.backend.svc.cluster.local | &lt;span class="nb"&gt;grep &lt;/span&gt;title
&lt;span class="gp"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Welcome to nginx!&amp;lt;/title&amp;gt;
&lt;span class="go"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; backend describe networkpolicy allow-frontend
&lt;span class="go"&gt;Name:         allow-frontend
Namespace:    backend
Created on:   2026-06-22 10:26:19 -0400 EDT
&lt;/span&gt;&lt;span class="gp"&gt;Labels:       &amp;lt;none&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="gp"&gt;Annotations:  &amp;lt;none&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="go"&gt;Spec:
  PodSelector:     app=backend
  Allowing ingress traffic:
    To Port: 80/TCP
    From:
      NamespaceSelector: kubernetes.io/metadata.name=frontend
      PodSelector: app=frontend
  Not affecting egress traffic
  Policy Types: Ingress
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Exam tips
&lt;/h2&gt;

&lt;p&gt;A few traps to remember. Policies are additive, so you add an allow next to the deny, you never edit the deny. A namespace selector and a pod selector in the same from entry are ANDed; split them into two entries and you accidentally OR them, which is more permissive. Least permissive means name the pod label and the port, not just the namespace. And always verify from a real pod, because a policy that parses can still be wrong.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Policies are additive: add an allow, never edit the default-deny&lt;/li&gt;
&lt;li&gt;namespaceSelector + podSelector in one from entry = AND (both match)&lt;/li&gt;
&lt;li&gt;Least permissive: pin the pod label and the port, not just the namespace&lt;/li&gt;
&lt;li&gt;Verify from inside a real pod, not just by reading the YAML&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Recap
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Default-deny blocks all ingress; allow policies are additive&lt;/li&gt;
&lt;li&gt;Pick the policy scoped to pod label + port (least permissive)&lt;/li&gt;
&lt;li&gt;Leave the existing deny untouched&lt;/li&gt;
&lt;li&gt;Subscribe + dev.to writeup&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Reproduce this yourself
&lt;/h2&gt;

&lt;p&gt;The entire scenario is scripted on a throwaway &lt;code&gt;kind&lt;/code&gt; cluster (with Calico so policies are actually enforced):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/The-Cyber-Sidekick/TCS_CKA_2026_Exam_Scenarios &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;learning/scenarios/scenario3-network-policy
./setup.sh        &lt;span class="c"&gt;# creates the cluster, installs Calico, and arms it (backend locked down)&lt;/span&gt;
&lt;span class="c"&gt;# solve it by hand, or:&lt;/span&gt;
./solution.sh     &lt;span class="c"&gt;# apply the answer key (netpol2) and verify connectivity&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;If this helped, &lt;strong&gt;subscribe to The Cyber SideKick&lt;/strong&gt; on YouTube for more CKA drills, and grab the newsletter at &lt;a href="https://thecybersidekick.beehiiv.com" rel="noopener noreferrer"&gt;https://thecybersidekick.beehiiv.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>cka</category>
      <category>devops</category>
      <category>networking</category>
    </item>
    <item>
      <title>Kubernetes as the Default AI Operating System: DRA, GPU Scheduling, and the AI Conformance Program</title>
      <dc:creator>The Cyber Sidekick</dc:creator>
      <pubDate>Mon, 22 Jun 2026 10:26:29 +0000</pubDate>
      <link>https://dev.to/thecybersidekick/kubernetes-as-the-default-ai-operating-system-dra-gpu-scheduling-and-the-ai-conformance-program-359b</link>
      <guid>https://dev.to/thecybersidekick/kubernetes-as-the-default-ai-operating-system-dra-gpu-scheduling-and-the-ai-conformance-program-359b</guid>
      <description>&lt;p&gt;&lt;em&gt;How Dynamic Resource Allocation, topology-aware scheduling, and emerging conformance standards are positioning Kubernetes as the native control plane for enterprise AI infrastructure.&lt;/em&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Kubernetes is undergoing a fundamental architectural shift to support GPU-accelerated AI workloads, moving beyond the legacy Device Plugin framework toward the more expressive Dynamic Resource Allocation (DRA) API that reached beta in Kubernetes 1.31. Enterprises building production AI systems need to understand this transition now, because infrastructure decisions made against the legacy model will constrain flexibility as DRA-native drivers from NVIDIA, Intel, and AMD become the standard.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  From Device Plugins to DRA: Why the Old Model Could Not Keep Up
&lt;/h2&gt;

&lt;p&gt;Kubernetes Device Plugins, introduced in version 1.8, solved the immediate problem of exposing GPUs to the scheduler, but they were fundamentally too coarse for the hardware realities of modern AI clusters. A Device Plugin can advertise a GPU as an integer resource, but it cannot express NVLink interconnect bandwidth, multi-instance GPU (MIG) partition profiles, or the affinity constraints that matter when placing a 32-GPU PyTorch training job across a DGX rack. Dynamic Resource Allocation (KEP-3063), now in beta as of Kubernetes 1.31, replaces this model with structured ResourceClaim objects that carry vendor-defined parameters, allowing allocation logic to live in a driver-specific controller rather than being forced into scheduler annotations and node labels. NVIDIA's GPU Operator v24.x already ships DRA alpha support alongside the legacy Device Plugin, managing MIG configuration and NVLink topology via Kubernetes CRDs, and the CNCF 2024 Annual Survey found that GPU workload scheduling was cited as the top infrastructure gap by the 96% of organizations using or evaluating Kubernetes for AI and ML workloads.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gang Scheduling and Topology Awareness: Eliminating the Distributed Training Deadlock
&lt;/h2&gt;

&lt;p&gt;Distributed training jobs using frameworks like PyTorch and JAX do not tolerate partial allocation; if nine of ten required pods schedule but the tenth cannot, all nine sit idle consuming GPU hours while holding resources that block other jobs. The upstream Coscheduling plugin in the scheduler-plugins repository (sigs.k8s.io/scheduler-plugins) addresses this with all-or-nothing PodGroup semantics, and Meta's internal benchmarks showed a 40% reduction in distributed training job queue time after adopting it, specifically because partial-allocation deadlocks were eliminated. The Topology Manager and the TopologySpread plugin complement this by enforcing NUMA and PCIe locality constraints so that gang-scheduled pods land on nodes with the right interconnect topology, not just available GPU count. Together, these primitives close a gap that historically kept HPC teams on Slurm, and as DRA allows topology constraints to be expressed natively in ResourceClaim objects rather than through fragile node label conventions, the operational burden of maintaining those workarounds disappears.&lt;/p&gt;

&lt;h2&gt;
  
  
  The AI Conformance Program: Certifying the Kubernetes AI Stack
&lt;/h2&gt;

&lt;p&gt;As Kubernetes becomes the default control plane for the full ML lifecycle, from distributed training through inference serving via KServe and Triton, the question of what it means for a Kubernetes distribution to correctly support AI workloads becomes commercially significant. The emerging Kubernetes AI Conformance Program, being formalized under SIG-testing with input from the AI and ML working group (wg-serving), aims to define a testable conformance surface covering GPU scheduling behavior, DRA driver interactions, fractional resource allocation, and workload identity for model serving pipelines. Workload Identity Federation (KEP-4193), which enables keyless ServiceAccount token projection to cloud AI services like Vertex AI, SageMaker, and Azure OpenAI, is expected to be part of that surface, removing static credential management from model serving deployments. Platform teams evaluating managed Kubernetes offerings for AI infrastructure should treat conformance certification as a procurement requirement rather than a nice-to-have, because uncertified distributions will increasingly diverge from upstream DRA behavior in ways that are difficult to debug at 3 AM during a training run.&lt;/p&gt;

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

&lt;p&gt;Kubernetes has crossed the threshold from a container orchestrator that happens to support GPUs into genuine AI operating system territory, and the architectural evidence is in the API surface: structured ResourceClaims that understand NVLink topology, gang scheduling that eliminates distributed training deadlocks, eBPF-based observability via tools like Kepler providing the GPU utilization visibility ML platform teams need for job packing and chargeback, and conformance testing that will hold distributions accountable to a defined AI workload behavior contract. The transition from DRA alpha to beta in 1.31 is the inflection point, not a distant roadmap item, and NVIDIA, Intel, and AMD have already committed to DRA-native drivers that will deprecate the Device Plugin model on a timeline measured in releases rather than years. Enterprises that standardize their AI infrastructure on Kubernetes now, with DRA-aware tooling and gang scheduling primitives in place, will find the path to multi-tenant GPU pools, GitOps-native model deployment, and hybrid cloud AI platforms significantly smoother than those who defer the migration and inherit technical debt tied to a scheduling model the community is actively moving past.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Technologies covered:&lt;/strong&gt; Dynamic Resource Allocation (DRA), GPU scheduling and resource management, AI Conformance Program, Device Plugins, Workload Identity, Kube-scheduler enhancements&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Sources aggregated from: CNCF Blog, Kubernetes.io, DevOps Weekly, GitHub Trending, Hacker News, InfoQ, The New Stack&lt;/em&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  📬 Stay current with cloud-native
&lt;/h3&gt;

&lt;p&gt;Get the latest Kubernetes, DevOps, and platform engineering insights delivered to your inbox.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;a href="https://thecybersidekick.beehiiv.com/subscribe" rel="noopener noreferrer"&gt;Subscribe to The Cyber SideKick Newsletter&lt;/a&gt;&lt;/strong&gt; — free, no spam, unsubscribe anytime.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>gpuscheduling</category>
      <category>dynamicresourceallocation</category>
      <category>aiinfrastructure</category>
    </item>
    <item>
      <title>Scenario 2 - Recover a deleted Deployment from a Retain-policy volume (CKA Storage)</title>
      <dc:creator>The Cyber Sidekick</dc:creator>
      <pubDate>Sat, 20 Jun 2026 20:12:53 +0000</pubDate>
      <link>https://dev.to/thecybersidekick/recover-a-deleted-deployment-from-a-retain-policy-volume-cka-storage-5cjc</link>
      <guid>https://dev.to/thecybersidekick/recover-a-deleted-deployment-from-a-retain-policy-volume-cka-storage-5cjc</guid>
      <description>&lt;h2&gt;
  
  
  The Retained Volume
&lt;/h2&gt;

&lt;p&gt;Someone deleted a database deployment by accident. The good news: the data is still on disk. In the next few minutes you'll reconnect it the way the CKA exam expects.&lt;/p&gt;

&lt;p&gt;🎥 &lt;strong&gt;Watch the video:&lt;/strong&gt; &lt;a href="https://www.youtube.com/watch?v=0GvawTDSyiU" rel="noopener noreferrer"&gt;https://www.youtube.com/watch?v=0GvawTDSyiU&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a CKA Storage walkthrough. Every command below is real output from a live cluster, and you can reproduce the whole thing yourself (scripts at the end).&lt;/p&gt;

&lt;h2&gt;
  
  
  The scenario
&lt;/h2&gt;

&lt;p&gt;A MariaDB deployment in the mariadb namespace was deleted. Its volume uses the Retain reclaim policy, so the data survived. Your task: create a claim for that volume, point the deployment at it, apply, and verify the pod is running with no restarts.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MariaDB Deployment in namespace mariadb was deleted&lt;/li&gt;
&lt;li&gt;Its PV uses Retain, so the data is still there&lt;/li&gt;
&lt;li&gt;Create a PVC bound to that PV&lt;/li&gt;
&lt;li&gt;Re-wire the Deployment, apply, and verify&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How storage binding works
&lt;/h2&gt;

&lt;p&gt;Storage in Kubernetes is a chain. A Deployment mounts a persistent volume claim. The claim binds to a persistent volume, which is the actual disk. Delete the claim and the deployment, and with Retain the volume keeps the data, waiting for a new claim to pick it back up.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reproduce symptom
&lt;/h2&gt;

&lt;p&gt;First, confirm the symptom. The mariadb namespace has no deployment and no pods. The workload is simply gone.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; mariadb get deploy,pods
&lt;span class="go"&gt;No resources found in mariadb namespace.
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Confirm the data survived
&lt;/h2&gt;

&lt;p&gt;Now the good news. The persistent volume still exists, its reclaim policy is Retain, and it is Available. That Retain policy is why your data outlived the deployment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl get pv mariadb
&lt;span class="go"&gt;NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   VOLUMEATTRIBUTESCLASS   REASON   AGE
&lt;/span&gt;&lt;span class="gp"&gt;mariadb   250Mi      RWO            Retain           Available                          &amp;lt;unset&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;                          &lt;/span&gt;10h
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Create the claim
&lt;/h2&gt;

&lt;p&gt;Create a file, mariadb-pvc.yaml. Two details matter: an empty storage class name, so Kubernetes binds the existing volume instead of provisioning a new one, and a volume name that points straight at the PV. Apply it, and it binds immediately.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cat &lt;/span&gt;mariadb-pvc.yaml
&lt;span class="c"&gt;...
&lt;/span&gt;&lt;span class="go"&gt;metadata:
  name: mariadb
  namespace: mariadb
spec:
  accessModes:
    - ReadWriteOnce
&lt;/span&gt;&lt;span class="gp"&gt;  #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Must match the PV: empty class &lt;span class="o"&gt;(&lt;/span&gt;static, no dynamic provisioning&lt;span class="o"&gt;)&lt;/span&gt; and an explicit
&lt;span class="gp"&gt;  #&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;volumeName so it binds to the retained &lt;span class="s2"&gt;"mariadb"&lt;/span&gt; PV rather than a new one.
&lt;span class="go"&gt;  storageClassName: ""
  volumeName: mariadb
  resources:
    requests:
      storage: 250Mi

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; mariadb-pvc.yaml
&lt;span class="go"&gt;persistentvolumeclaim/mariadb created

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; mariadb get pvc
&lt;span class="go"&gt;NAME      STATUS   VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   VOLUMEATTRIBUTESCLASS   AGE
&lt;/span&gt;&lt;span class="gp"&gt;mariadb   Bound    mariadb   250Mi      RWO                           &amp;lt;unset&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;                 &lt;/span&gt;1s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Apply the wired deployment, and prove it. The pod is Running with zero restarts, on top of the original data. The deployment is recovered.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; mariadb-deployment.yaml
&lt;span class="go"&gt;deployment.apps/mariadb created

&lt;/span&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;kubectl &lt;span class="nt"&gt;-n&lt;/span&gt; mariadb get pods
&lt;span class="go"&gt;NAME                       READY   STATUS    RESTARTS   AGE
mariadb-68cd856df4-jx6mm   1/1     Running   0          0s
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Exam tips
&lt;/h2&gt;

&lt;p&gt;A few traps to remember. Use an empty storage class name to force a static bind, or the cluster's default provisioner will hand you a brand new empty volume. After you delete a claim, a Retain volume goes to Released, not Available; clear its claimRef to make it bindable again. And always confirm the claim is Bound before you expect the pod to start.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;storageClassName "" = static bind (avoid the default provisioner)&lt;/li&gt;
&lt;li&gt;volumeName targets a specific PV&lt;/li&gt;
&lt;li&gt;Retain PV goes Released after PVC delete; clear claimRef to rebind&lt;/li&gt;
&lt;li&gt;Confirm PVC is Bound before expecting the pod to run&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Recap
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Retain preserves data past the claim's life&lt;/li&gt;
&lt;li&gt;Re-bind: PVC with empty class + volumeName&lt;/li&gt;
&lt;li&gt;Wire the Deployment, then verify Bound + Running&lt;/li&gt;
&lt;li&gt;Subscribe + dev.to writeup&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Reproduce this yourself
&lt;/h2&gt;

&lt;p&gt;The entire scenario is scripted on a throwaway &lt;code&gt;kind&lt;/code&gt; cluster:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &amp;lt;repo&amp;gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;cd &lt;/span&gt;learning/scenarios/scenario2-retained-pv-recovery
./setup.sh        &lt;span class="c"&gt;# creates the cluster AND arms it (namespace + retained PV, deployment gone)&lt;/span&gt;
&lt;span class="c"&gt;# solve it by hand, or:&lt;/span&gt;
./solution.sh     &lt;span class="c"&gt;# apply the answer key and verify recovery&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;If this helped, &lt;strong&gt;subscribe to The Cyber SideKick&lt;/strong&gt; on YouTube for more CKA drills, and grab the newsletter at &lt;a href="https://thecybersidekick.beehiiv.com" rel="noopener noreferrer"&gt;https://thecybersidekick.beehiiv.com&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>cka</category>
      <category>devops</category>
      <category>storage</category>
    </item>
  </channel>
</rss>
