<?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: devtocash</title>
    <description>The latest articles on DEV Community by devtocash (@devtocash).</description>
    <link>https://dev.to/devtocash</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%2F4002560%2F6ede7663-58de-4c06-a945-113cc245c5c6.png</url>
      <title>DEV Community: devtocash</title>
      <link>https://dev.to/devtocash</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/devtocash"/>
    <language>en</language>
    <item>
      <title>Platform Engineering 2.0 in 2026: How Internal Developer Platforms Are Eating DevOps</title>
      <dc:creator>devtocash</dc:creator>
      <pubDate>Fri, 26 Jun 2026 10:29:05 +0000</pubDate>
      <link>https://dev.to/devtocash/platform-engineering-20-in-2026-how-internal-developer-platforms-are-eating-devops-k6k</link>
      <guid>https://dev.to/devtocash/platform-engineering-20-in-2026-how-internal-developer-platforms-are-eating-devops-k6k</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In 2023, platform engineering was a buzzword. In 2026, it's eating DevOps.&lt;/p&gt;

&lt;p&gt;The data tells the story: Gartner predicts 80% of large engineering organizations will have a platform engineering team by 2026. The CNCF Platform Working Group released its Platform Engineering Maturity Model in late 2025. And at KubeCon North America 2025, platform engineering talks outnumbered pure Kubernetes talks for the first time.&lt;/p&gt;

&lt;p&gt;Here's what happened: DevOps promised self-service. Developers would own their infrastructure, deploy their own code, manage their own observability. In practice, that meant every developer needed to understand Docker, Kubernetes, Terraform, Helm, PromQL, LogQL, and twelve different YAML dialects. The cognitive load crushed productivity. Developers spent 40% of their time on infrastructure toil that wasn't their specialty.&lt;/p&gt;

&lt;p&gt;Platform Engineering fixes this. An Internal Developer Platform (IDP) takes all that infrastructure complexity and packages it behind a self-service interface that developers actually want to use. The platform team builds and runs the platform as a &lt;strong&gt;product&lt;/strong&gt;, with the developers as their customers.&lt;/p&gt;

&lt;p&gt;This guide covers what Platform Engineering 2.0 looks like in 2026 — the tools, the patterns, the anti-patterns, and a concrete path to build your first IDP.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Is an Internal Developer Platform?
&lt;/h2&gt;

&lt;p&gt;An Internal Developer Platform (IDP) is a curated, self-service layer that abstracts infrastructure complexity for application developers. It's the &lt;strong&gt;paved road&lt;/strong&gt; — developers stay on the road and move fast; if they need to go off-road, they can, but the platform makes the common path effortless.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Golden Path
&lt;/h3&gt;

&lt;p&gt;Imagine an engineer joins your company on Monday. By Tuesday morning, they've spun up a new microservice with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A GitHub repository with CI/CD pipelines pre-configured&lt;/li&gt;
&lt;li&gt;A Kubernetes namespace with resource quotas, network policies, and RBAC&lt;/li&gt;
&lt;li&gt;TLS certificates provisioned automatically via cert-manager&lt;/li&gt;
&lt;li&gt;Observability: metrics, logs, and traces flowing to Grafana&lt;/li&gt;
&lt;li&gt;A database instance with backups configured&lt;/li&gt;
&lt;li&gt;Their service registered in the internal service catalog&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All of this happens from a single &lt;code&gt;catalog-info.yaml&lt;/code&gt; in their repo, or a self-service UI. No Kubernetes manifests. No Terraform modules. No JIRA ticket to the "DevOps team." That's an IDP.&lt;/p&gt;

&lt;h3&gt;
  
  
  IDP != DevOps Team
&lt;/h3&gt;

&lt;p&gt;This is the most common misconception. An IDP is not a centralized DevOps team that manually provisions infrastructure for developers. That's just re-creating the pre-DevOps silo with a new name. A real IDP is &lt;strong&gt;automated, self-service, and governed&lt;/strong&gt; — the platform team writes software and config that enables developer self-service. The developer clicks a button (or pushes YAML to a repo), and infrastructure appears.&lt;/p&gt;

&lt;p&gt;For the broader context of how Platform Engineering fits alongside DevOps and SRE, see our &lt;a href="https://dev.to/blog/sre-vs-devops-vs-platform-engineering-2026"&gt;SRE vs DevOps vs Platform Engineering comparison&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Platform Engineering vs. DevOps vs. SRE: The 2026 Dynamic
&lt;/h2&gt;

&lt;p&gt;These three disciplines are distinct but overlapping. In 2026, the boundaries are clearer:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Discipline&lt;/th&gt;
&lt;th&gt;Primary Customer&lt;/th&gt;
&lt;th&gt;Primary Concern&lt;/th&gt;
&lt;th&gt;Key Metric&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;DevOps&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The deployment pipeline&lt;/td&gt;
&lt;td&gt;Speed of delivery&lt;/td&gt;
&lt;td&gt;Deployment frequency, lead time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SRE&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The production system&lt;/td&gt;
&lt;td&gt;Reliability&lt;/td&gt;
&lt;td&gt;SLO attainment, error budget burn&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Platform Engineering&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;The developer&lt;/td&gt;
&lt;td&gt;Cognitive load, productivity&lt;/td&gt;
&lt;td&gt;Developer onboarding time, time-to-10th-deployment&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Platform Engineering is what makes DevOps scalable. When you have 5 engineers, DevOps works fine — everyone understands the infrastructure. At 50 engineers, DevOps becomes a bottleneck. At 200 engineers, without a platform, it collapses into tribal knowledge and operational chaos.&lt;/p&gt;

&lt;h3&gt;
  
  
  How They Interact
&lt;/h3&gt;

&lt;p&gt;In a mature 2026 organization:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Platform Engineering&lt;/strong&gt; builds and runs the IDP. They own the CI/CD templates, the infrastructure provisioning system, the service catalog, and the developer portal.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SRE&lt;/strong&gt; owns reliability SLOs, incident response, and observability standards. They provide the platform team with reliability requirements (like "every service must expose RED metrics").&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DevOps&lt;/strong&gt; — as a dedicated role — is fading into Platform Engineering. The remaining "DevOps" is a &lt;strong&gt;culture&lt;/strong&gt;: teams that build software also participate in its operation, enabled by the platform.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The platform engineering team's golden rule: &lt;strong&gt;platform teams build platform, stream-aligned teams build product.&lt;/strong&gt; Neither builds both.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Core Components of an IDP in 2026
&lt;/h2&gt;

&lt;p&gt;A well-architected IDP has six core components. Every platform team should have a plan for each.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Developer Portal (Service Catalog)
&lt;/h3&gt;

&lt;p&gt;The developer portal is the front door to your platform. It's where developers go to see all services, their owners, documentation, dependencies, and operational health.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Backstage&lt;/strong&gt; remains the dominant open-source portal, with v3.0 released in late 2025 bringing native plugin federation. &lt;strong&gt;Port&lt;/strong&gt; has gained significant market share by positioning itself as "Backstage without the maintenance burden" — a managed SaaS offering with a polished UI and simpler onboarding. &lt;strong&gt;Cortex&lt;/strong&gt; leads in engineering teams focused on service quality scores and team health metrics.&lt;/p&gt;

&lt;p&gt;Key capability in 2026 portals: &lt;strong&gt;scorecards&lt;/strong&gt;. These automatically grade services on production readiness — is observability configured? Are SLOs defined? Is security scanning passing? Scorecards make governance visible and gamified.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Infrastructure Orchestration
&lt;/h3&gt;

&lt;p&gt;This is the engine room of the IDP. When a developer declares "I need a Postgres database and a Kafka topic," the orchestration layer provisions them. In 2026, the leading approaches are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Crossplane&lt;/strong&gt; — Kubernetes-native infrastructure composition. You define a &lt;code&gt;PostgreSQLInstance&lt;/code&gt; Custom Resource, and Crossplane provisions it in AWS/GCP/Azure. This is the CNCF approach and the most popular for greenfield platforms in 2026.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Terraform (HCP)&lt;/strong&gt; — HashiCorp Cloud Platform with no-code modules lets platform teams define "golden path" Terraform modules that developers instantiate without writing HCL.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kubernetes Operators&lt;/strong&gt; — For Kubernetes-native workloads, operators abstract Day 2 operations. The platform team wires operators together behind a self-service interface.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. CI/CD Templates
&lt;/h3&gt;

&lt;p&gt;Developers should not write CI/CD pipelines from scratch for every service. The platform provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Golden pipeline templates&lt;/strong&gt;: A single canonical pipeline that covers build → test → scan → deploy for 90% of services.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Language-specific templates&lt;/strong&gt;: Python, Go, Node.js, Java — each with the right build tools and test frameworks pre-configured.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deployment strategies&lt;/strong&gt;: canary, blue-green, and rolling updates as configurable options, not custom code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;GitHub Actions reusable workflows (v2 with composable actions) and GitLab CI/CD templates dominate this space. ArgoCD remains the standard for GitOps-based deployment.&lt;/p&gt;

&lt;p&gt;For the security side of platform pipelines, see our &lt;a href="https://dev.to/blog/kubernetes-security-best-practices-2026"&gt;Kubernetes Security Best Practices guide&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Observability Integration
&lt;/h3&gt;

&lt;p&gt;The platform doesn't just provision infrastructure — it provisions observability. When a new service is created, the platform automatically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scrapes Prometheus metrics via a ServiceMonitor or PodMonitor&lt;/li&gt;
&lt;li&gt;Ships logs to Loki via the OTel Collector&lt;/li&gt;
&lt;li&gt;Enables distributed tracing via Tempo&lt;/li&gt;
&lt;li&gt;Creates a Grafana dashboard from the service template&lt;/li&gt;
&lt;li&gt;Configures basic SLO-based alerts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The developer writes zero observability config. The platform handles it, with sensible defaults and an escape hatch for customization. For a complete observability implementation guide, check our &lt;a href="https://dev.to/blog/open-telemetry-tutorial-setup-guide-2026"&gt;OpenTelemetry Tutorial 2026&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Security &amp;amp; Compliance Guardrails
&lt;/h3&gt;

&lt;p&gt;A platform that's fast but insecure is not fast — it's reckless. IDP guardrails include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Container image scanning (Trivy, Grype) as a pipeline gate&lt;/li&gt;
&lt;li&gt;Kubernetes network policies applied by namespace&lt;/li&gt;
&lt;li&gt;OPA/Gatekeeper policies enforcing deployment standards&lt;/li&gt;
&lt;li&gt;Secret management (Vault, External Secrets Operator) with no hardcoded credentials&lt;/li&gt;
&lt;li&gt;SBOM generation and vulnerability tracking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The platform doesn't ask developers to "be secure." It makes security the path of least resistance.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Developer CLI &amp;amp; API
&lt;/h3&gt;

&lt;p&gt;Every IDP needs a programmatic interface. &lt;strong&gt;Backstage CLI&lt;/strong&gt; and the &lt;strong&gt;Platform API&lt;/strong&gt; (REST or gRPC) let developers interact with the platform from their terminal and from automated tooling. In 2026, the CLI trend is toward &lt;strong&gt;natural language interfaces&lt;/strong&gt; — see the AI section below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Platform as Product: The Mindset Shift
&lt;/h2&gt;

&lt;p&gt;The single most important idea in Platform Engineering 2.0 is treating the platform as a product. Your developers are not your subordinates — they're your customers. If your platform doesn't solve their problems, they'll route around it.&lt;/p&gt;

&lt;h3&gt;
  
  
  What "Platform as Product" Means in Practice
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;You hire (or designate) a Platform Product Manager.&lt;/strong&gt; This person's job is not writing code. It's understanding developer pain points through user research, prioritizing the platform roadmap, and measuring adoption.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You define platform SLOs.&lt;/strong&gt; The platform team commits to uptime, latency, and self-service SLAs. If a developer can't provision a new service in under 10 minutes, that's a platform incident.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You measure DevEx.&lt;/strong&gt; DORA metrics measure delivery speed. DevEx metrics measure developer satisfaction: Net Promoter Score for the platform, time-to-10th-deployment, friction logs, and quarterly developer surveys.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You dogfood the platform.&lt;/strong&gt; Platform engineers use the platform for their own tooling. If it's painful for them, it's painful for everyone.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The platform has a marketing function.&lt;/strong&gt; Internal newsletters, office hours, and documentation that developers actually read. Adoption is built, not assumed.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  The "Thinnest Viable Platform" Principle
&lt;/h3&gt;

&lt;p&gt;The most common Platform Engineering mistake is building an IDP too big, too soon. Teams spend 12 months building a beautiful developer portal with every feature imaginable. They launch it. Nobody uses it.&lt;/p&gt;

&lt;p&gt;The alternative: build the &lt;strong&gt;Thinnest Viable Platform&lt;/strong&gt; (TVP). Ship something that solves one concrete problem within 4 weeks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Week 1-2: Deploy Backstage with the GitHub integration. Now developers can see all services in one place. That's it. That's your v0.1.&lt;/li&gt;
&lt;li&gt;Week 3-4: Add the CI/CD plugin so developers can see build status. v0.2.&lt;/li&gt;
&lt;li&gt;Month 2: Add scaffolder templates for one language (say, Python). Now developers can create new Python services from a template. v0.3.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each increment adds real value that developers can feel. Adoption grows organically.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 2026 Tool Landscape
&lt;/h2&gt;

&lt;p&gt;The Platform Engineering tool ecosystem has exploded since 2023. Here's the landscape organizations are navigating in 2026.&lt;/p&gt;

&lt;h3&gt;
  
  
  Developer Portals (The Front Door)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;Best For&lt;/th&gt;
&lt;th&gt;2026 Differentiator&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Backstage&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Open-source (CNCF)&lt;/td&gt;
&lt;td&gt;Large orgs with dedicated platform investment&lt;/td&gt;
&lt;td&gt;Plugin ecosystem, v3.0 federation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Port&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;SaaS&lt;/td&gt;
&lt;td&gt;Mid-size orgs prioritizing time-to-value&lt;/td&gt;
&lt;td&gt;UX polish, no maintenance overhead&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Cortex&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;SaaS + self-hosted&lt;/td&gt;
&lt;td&gt;Engineering managers needing team health data&lt;/td&gt;
&lt;td&gt;Scorecards, DORA metric dashboards&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;OpsLevel&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;SaaS&lt;/td&gt;
&lt;td&gt;Service maturity tracking&lt;/td&gt;
&lt;td&gt;Catalog-driven standards enforcement&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Infrastructure Orchestration (The Engine)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Model&lt;/th&gt;
&lt;th&gt;2026 Position&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Crossplane&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Open-source (CNCF)&lt;/td&gt;
&lt;td&gt;The standard for Kubernetes-native IaC. Compositions define platform APIs.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Terraform HCP&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;SaaS + open-source&lt;/td&gt;
&lt;td&gt;Mature, but facing competition from Crossplane for k8s-native use cases&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Pulumi&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Open-source + SaaS&lt;/td&gt;
&lt;td&gt;Real language IaC (TypeScript/Python/Go); strong for platform teams that prefer code over YAML&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;AWS Proton / GCP Config Connector&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Cloud-managed&lt;/td&gt;
&lt;td&gt;Cloud-specific IDP building blocks; limited by vendor lock-in&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  CI/CD Integration
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;2026 Role in IDP&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GitHub Actions&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Reusable workflows + composable actions. Most popular for IDP pipeline templates&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;GitLab CI/CD&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Strong CI/CD catalog; good for self-hosted requirements&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ArgoCD&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Standard for GitOps deploys; ApplicationSets for multi-service templating&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dagger&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Container-native CI/CD; good for platform teams that want portable pipelines&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  2026 Trend: Convergence Around Backstage + Crossplane + ArgoCD
&lt;/h3&gt;

&lt;p&gt;The most common IDP stack observed in 2026 mid-size orgs (50-200 engineers) is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Backstage (or Port)&lt;/strong&gt; as the developer portal&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Crossplane&lt;/strong&gt; for infrastructure composition&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ArgoCD&lt;/strong&gt; for GitOps deployment&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GitHub Actions&lt;/strong&gt; for CI pipeline templates&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OpenTelemetry + Grafana&lt;/strong&gt; for observability&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;External Secrets Operator&lt;/strong&gt; for secret management&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This stack is 100% open-source, CNCF-graduated or incubating, and avoids vendor lock-in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Anti-Patterns: The Platform Engineering Graveyard
&lt;/h2&gt;

&lt;p&gt;More platform initiatives fail than succeed. Here are the patterns to avoid, based on real-world postmortems from 2023-2025.&lt;/p&gt;

&lt;h3&gt;
  
  
  Anti-Pattern 1: "Build It and They Will Come"
&lt;/h3&gt;

&lt;p&gt;The platform team spends 8 months building a perfect IDP in isolation. Launch day: developers log in, click around, and go back to their existing workflows. The platform team gets frustrated. Developers get defensive.&lt;/p&gt;

&lt;p&gt;Fix: Involve 3-5 developer "champions" from stream-aligned teams from day one. They co-design the platform, test early versions, and become advocates within their teams. Platform adoption is a &lt;strong&gt;social engineering&lt;/strong&gt; problem, not a technical one.&lt;/p&gt;

&lt;h3&gt;
  
  
  Anti-Pattern 2: The Platform Becomes a Bottleneck
&lt;/h3&gt;

&lt;p&gt;An IDP should reduce time-to-provision from days to minutes. But bad platforms become the new bottleneck: "I need a Redis cluster" → ticket to platform team → 3 days later → "It's ready." This is worse than the DevOps silo it replaced.&lt;/p&gt;

&lt;p&gt;Fix: If a platform action requires manual approval or manual execution by the platform team more than 10% of the time, it's not self-service. Measure time-to-provision and keep it under 10 minutes for common requests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Anti-Pattern 3: Golden Path That's a Straitjacket
&lt;/h3&gt;

&lt;p&gt;The golden path is meant to handle 80% of use cases. But if the escape hatch is sealed shut, teams with legitimate edge cases suffer. A platform that can't accommodate the data engineering team's GPU workloads or the mobile team's build requirements will be bypassed.&lt;/p&gt;

&lt;p&gt;Fix: Golden path for common cases. Well-documented, well-tested "off-road" paths for everything else. The platform must say "here's the easy way, and here's how to go custom if you need to."&lt;/p&gt;

&lt;h3&gt;
  
  
  Anti-Pattern 4: Ignoring Developer Experience
&lt;/h3&gt;

&lt;p&gt;A platform with powerful infrastructure capabilities but terrible UX will fail. Confusing UI, undocumented APIs, 10-step provisioning processes — developers will route around you.&lt;/p&gt;

&lt;p&gt;Fix: Invest in UX. A platform engineer who can write Terraform but can't empathize with a frontend developer's workflow will build the wrong thing. Hire or train for product thinking.&lt;/p&gt;

&lt;h3&gt;
  
  
  Anti-Pattern 5: No Platform SLOs
&lt;/h3&gt;

&lt;p&gt;The platform team that doesn't define SLOs can't tell if they're succeeding. "Developers seem happy" is not a metric.&lt;/p&gt;

&lt;p&gt;Fix: Define platform SLOs: "99.9% of service provisioning requests succeed within 5 minutes," "95% of CI pipeline runs complete within 10 minutes." These are the platform's own SLOs — and the platform should burn its own error budget.&lt;/p&gt;

&lt;h2&gt;
  
  
  Case Study: 50-Engineer Fintech Org
&lt;/h2&gt;

&lt;p&gt;Let's make this concrete with a composite case study based on real 2025-2026 implementations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Organization:&lt;/strong&gt; A fintech with 50 engineers, 35 microservices, running on AWS EKS. 18 months ago, they had 12 engineers and DevOps was "Søren knows Terraform."&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Problem (at 35 engineers):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;New service creation took 3-5 days: JIRA ticket → wait → manual Terraform → wait → manual CI setup&lt;/li&gt;
&lt;li&gt;4 different CI pipeline patterns across teams — no standardization&lt;/li&gt;
&lt;li&gt;Security scanning was inconsistent; 30% of services had no vulnerability scanning&lt;/li&gt;
&lt;li&gt;On-call engineers couldn't find which team owned a service during incidents&lt;/li&gt;
&lt;li&gt;Søren was the bottleneck for everything infrastructure-related&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;The Solution (phased over 8 months):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Month 1-2:&lt;/em&gt; Formed a Platform Engineering team (3 people: 2 engineers + 1 product manager from engineering). Deployed Backstage with GitHub catalog integration. Immediate win: everyone could see all services and their owners.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Month 3-4:&lt;/em&gt; Built Crossplane compositions for the 5 most-requested infrastructure patterns: stateless API service, Kafka consumer, cron job, Postgres RDS instance, Redis cluster. Built Backstage scaffolder templates for each. Result: new service provisioning went from 3-5 days to under 15 minutes.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Month 5-6:&lt;/em&gt; Standardized CI/CD pipelines using GitHub Actions reusable workflows. Enforced Trivy image scanning and OPA policies as pipeline gates. Created Backstage scorecards that gamified compliance.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Month 7-8:&lt;/em&gt; Integrated observability: every scaffolded service automatically got Prometheus metrics scraping, Loki log shipping, Tempo tracing, and a baseline Grafana dashboard. Defined platform SLOs and started measuring.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Results (after 12 months):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Time to 10th deployment for new engineers: from 14 days to 2 days&lt;/li&gt;
&lt;li&gt;Service provisioning time: from 3-5 days to under 15 minutes&lt;/li&gt;
&lt;li&gt;Security scanning coverage: from 70% to 100%&lt;/li&gt;
&lt;li&gt;Developer NPS for infrastructure tooling: from -12 to +38&lt;/li&gt;
&lt;li&gt;Platform team size: remained at 3 people serving 50 engineers (a 1:17 ratio that scales to roughly 200 engineers)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The key to success: they didn't build everything at once. They shipped incrementally, measured adoption, and iterated based on developer feedback.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Originally published at &lt;a href="https://devtocash.com/blog/platform-engineering-2-0-idp-devops-2026" rel="noopener noreferrer"&gt;devtocash.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>devops</category>
      <category>platformengineering</category>
      <category>sre</category>
      <category>kubernetes</category>
    </item>
    <item>
      <title>Kubernetes Security Best Practices 2026: Complete Hardening Guide</title>
      <dc:creator>devtocash</dc:creator>
      <pubDate>Fri, 26 Jun 2026 06:35:33 +0000</pubDate>
      <link>https://dev.to/devtocash/kubernetes-security-best-practices-2026-complete-hardening-guide-5hk5</link>
      <guid>https://dev.to/devtocash/kubernetes-security-best-practices-2026-complete-hardening-guide-5hk5</guid>
      <description>&lt;h1&gt;
  
  
  Kubernetes Security Best Practices 2026: The Complete Hardening Guide
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;A single misconfigured Kubernetes cluster can expose your entire infrastructure in minutes. In 2025 alone, over 60% of organizations reported at least one Kubernetes security incident — and the majority traced back to preventable misconfigurations, not zero-day exploits.&lt;/p&gt;

&lt;p&gt;Kubernetes ships with minimal security defaults. Everything is open. Pods can talk to each other freely. Service accounts carry cluster-admin privileges by default. Secrets sit in etcd unencrypted. If you deploy a vanilla cluster and walk away, you are effectively running with the doors unlocked.&lt;/p&gt;

&lt;p&gt;This guide walks through &lt;strong&gt;4 critical security layers&lt;/strong&gt; you must implement in any production Kubernetes cluster. Each section includes real, copy-paste-ready YAML manifests and CLI commands. Whether you run EKS, GKE, AKS, or bare-metal kubeadm clusters, these practices apply universally.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Who this is for:&lt;/strong&gt; DevOps engineers, SREs, platform engineers, and anyone responsible for production Kubernetes clusters. You should be comfortable with &lt;code&gt;kubectl&lt;/code&gt; and basic YAML. No prior security specialization required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What you will implement by the end of this guide:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fine-grained RBAC with least-privilege principles&lt;/li&gt;
&lt;li&gt;Pod Security Admission replacing deprecated PSPs&lt;/li&gt;
&lt;li&gt;Zero-trust network policies with default-deny&lt;/li&gt;
&lt;li&gt;Image vulnerability scanning with Trivy in CI/CD&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's lock it down.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. RBAC: Least Privilege from Day One
&lt;/h2&gt;

&lt;p&gt;Role-Based Access Control (RBAC) is your first and most important line of defense. The principle is simple: every user, service account, and application should have &lt;strong&gt;exactly&lt;/strong&gt; the permissions it needs — nothing more.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Problem with Default RBAC
&lt;/h3&gt;

&lt;p&gt;Out of the box, Kubernetes grants the &lt;code&gt;system:masters&lt;/code&gt; group (used by &lt;code&gt;kubeadm init&lt;/code&gt;) cluster-admin. Every default service account in the &lt;code&gt;kube-system&lt;/code&gt; namespace gets elevated privileges. The &lt;code&gt;default&lt;/code&gt; service account in every namespace exists automatically and — unless you explicitly bind it — has no permissions. But many teams accidentally grant it broad access during development and forget to revoke it.&lt;/p&gt;

&lt;p&gt;Here is the most common anti-pattern we see in production audits:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# BAD: cluster-admin bound to default service account&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterRoleBinding&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dangerous-binding&lt;/span&gt;
&lt;span class="na"&gt;roleRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;apiGroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io&lt;/span&gt;
  &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ClusterRole&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cluster-admin&lt;/span&gt;
&lt;span class="na"&gt;subjects&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ServiceAccount&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives every pod in the &lt;code&gt;default&lt;/code&gt; namespace unrestricted control over the entire cluster. If any pod gets compromised, the attacker owns everything.&lt;/p&gt;

&lt;h3&gt;
  
  
  RBAC Best Practices
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. Use namespace-scoped Roles, not ClusterRoles, whenever possible.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;Role&lt;/code&gt; is bound to a single namespace. A &lt;code&gt;ClusterRole&lt;/code&gt; is cluster-wide. Most applications only need access to resources in their own namespace.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# GOOD: namespace-scoped Role for a web application&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Role&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;webapp-role&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;
&lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;apiGroups&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pods"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;services"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;configmaps"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;secrets"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;verbs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;get"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;list"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;watch"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;apiGroups&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;apps"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;deployments"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
  &lt;span class="na"&gt;verbs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;get"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;list"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;watch"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;update"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;2. Create a dedicated ServiceAccount for every application.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Never use the &lt;code&gt;default&lt;/code&gt; service account. Always create a named ServiceAccount and bind it to a specific Role.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ServiceAccount&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;webapp-sa&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;RoleBinding&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;webapp-binding&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;
&lt;span class="na"&gt;roleRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;apiGroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;rbac.authorization.k8s.io&lt;/span&gt;
  &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Role&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;webapp-role&lt;/span&gt;
&lt;span class="na"&gt;subjects&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ServiceAccount&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;webapp-sa&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then reference it in your Deployment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;serviceAccountName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;webapp-sa&lt;/span&gt;
  &lt;span class="na"&gt;automountServiceAccountToken&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;3. Avoid wildcard verbs and resources.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every &lt;code&gt;*&lt;/code&gt; in your RBAC rules is a potential escalation path. Be specific:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# BAD&lt;/span&gt;
&lt;span class="na"&gt;verbs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="c1"&gt;# GOOD: explicit&lt;/span&gt;
&lt;span class="na"&gt;verbs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;get"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;list"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;watch"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="na"&gt;resources&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pods"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;services"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Use &lt;code&gt;kubectl auth can-i&lt;/code&gt; to verify permissions.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before deploying, test what a service account can actually do:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl auth can-i create deployments &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--as&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;system:serviceaccount:production:webapp-sa &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--namespace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;production
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;5. Separate human users from machine accounts.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Use OIDC (OpenID Connect) for human authentication. Service accounts are for pods and CI/CD pipelines. Map OIDC groups to Kubernetes roles — never give individual users cluster-admin. Tools like Dex, Keycloak, or cloud-provider IAM (aws-iam-authenticator for EKS, GCP IAM for GKE) handle this cleanly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Audit your RBAC regularly.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Run this one-liner to find overly permissive bindings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get clusterrolebindings &lt;span class="nt"&gt;-o&lt;/span&gt; json | &lt;span class="se"&gt;\&lt;/span&gt;
  jq &lt;span class="s1"&gt;'.items[] | select(.roleRef.name=="cluster-admin") | .subjects'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will be surprised how many cluster-admin bindings accumulate over time. RBAC auditing tools like &lt;code&gt;kubescape&lt;/code&gt;, &lt;code&gt;kube-bench&lt;/code&gt;, or &lt;code&gt;popeye&lt;/code&gt; can automate this check.&lt;/p&gt;

&lt;h3&gt;
  
  
  RBAC for CI/CD Pipelines
&lt;/h3&gt;

&lt;p&gt;CI/CD systems (GitHub Actions, GitLab CI, ArgoCD) need API access to deploy. The pattern: create a ServiceAccount with the minimum permissions required for deployments, extract its token, and inject it into your pipeline secrets.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl create serviceaccount cicd-deployer &lt;span class="nt"&gt;-n&lt;/span&gt; production
kubectl create rolebinding cicd-deployer-binding &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;webapp-role &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--serviceaccount&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;production:cicd-deployer &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-n&lt;/span&gt; production

&lt;span class="c"&gt;# For Kubernetes 1.24+, create a long-lived token:&lt;/span&gt;
kubectl create token cicd-deployer &lt;span class="nt"&gt;-n&lt;/span&gt; production &lt;span class="nt"&gt;--duration&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;8760h
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Store that token in your CI secrets manager — never in source code.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Pod Security Standards &amp;amp; Pod Security Admission
&lt;/h2&gt;

&lt;p&gt;Pod Security Policies (PSPs) were deprecated in Kubernetes 1.21 and removed in 1.25. The replacement is &lt;strong&gt;Pod Security Admission (PSA)&lt;/strong&gt; — a built-in admission controller that enforces Pod Security Standards at the namespace level.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Three Pod Security Standards
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Standard&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Key Restrictions&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Privileged&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Unrestricted. Equivalent to no policy.&lt;/td&gt;
&lt;td&gt;None. Use only for system namespaces.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Baseline&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Prevents known privilege escalations. Minimum for production.&lt;/td&gt;
&lt;td&gt;No hostNetwork, hostPID, hostIPC, hostPorts, privileged containers, or hostPath volumes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Restricted&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hardened following Pod hardening best practices.&lt;/td&gt;
&lt;td&gt;Everything Baseline restricts, plus: must run as non-root, seccomp profile required, capabilities dropped to NET_BIND_SERVICE only, read-only root filesystem.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Enforcing PSA with Namespace Labels
&lt;/h3&gt;

&lt;p&gt;PSA uses namespace labels — no separate CRD needed. Apply a label to any namespace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Enforce the restricted policy on a namespace&lt;/span&gt;
kubectl label namespace production &lt;span class="se"&gt;\&lt;/span&gt;
  pod-security.kubernetes.io/enforce&lt;span class="o"&gt;=&lt;/span&gt;restricted

&lt;span class="c"&gt;# Also set audit and warn modes for visibility&lt;/span&gt;
kubectl label namespace production &lt;span class="se"&gt;\&lt;/span&gt;
  pod-security.kubernetes.io/audit&lt;span class="o"&gt;=&lt;/span&gt;restricted &lt;span class="se"&gt;\&lt;/span&gt;
  pod-security.kubernetes.io/warn&lt;span class="o"&gt;=&lt;/span&gt;restricted
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three enforcement modes exist for each label:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;enforce&lt;/strong&gt;: reject pods that violate the policy&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;audit&lt;/strong&gt;: allow but log violations to the audit log&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;warn&lt;/strong&gt;: allow but show a warning to the user&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Gradual rollout strategy:&lt;/strong&gt; Start with &lt;code&gt;warn&lt;/code&gt; and &lt;code&gt;audit&lt;/code&gt; modes for a week. Fix all warnings. Then switch to &lt;code&gt;enforce&lt;/code&gt;. Never jump straight to &lt;code&gt;enforce=restricted&lt;/code&gt; on existing production namespaces — you will break running workloads.&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing a Restricted-Compliant Pod
&lt;/h3&gt;

&lt;p&gt;Here is a pod that passes the &lt;code&gt;restricted&lt;/code&gt; Pod Security Standard:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;secure-nginx&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;securityContext&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runAsNonRoot&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;runAsUser&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1000&lt;/span&gt;
    &lt;span class="na"&gt;runAsGroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3000&lt;/span&gt;
    &lt;span class="na"&gt;fsGroup&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;2000&lt;/span&gt;
    &lt;span class="na"&gt;seccompProfile&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;RuntimeDefault&lt;/span&gt;
  &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx&lt;/span&gt;
    &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx:1.25-alpine&lt;/span&gt;
    &lt;span class="na"&gt;securityContext&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;allowPrivilegeEscalation&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
      &lt;span class="na"&gt;capabilities&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;drop&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ALL"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
        &lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;NET_BIND_SERVICE"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;readOnlyRootFilesystem&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
    &lt;span class="na"&gt;volumeMounts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tmp&lt;/span&gt;
      &lt;span class="na"&gt;mountPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/tmp&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx-cache&lt;/span&gt;
      &lt;span class="na"&gt;mountPath&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/var/cache/nginx&lt;/span&gt;
  &lt;span class="na"&gt;volumes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;tmp&lt;/span&gt;
    &lt;span class="na"&gt;emptyDir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx-cache&lt;/span&gt;
    &lt;span class="na"&gt;emptyDir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;runAsNonRoot: true&lt;/code&gt; — the container must not run as UID 0&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;seccompProfile: RuntimeDefault&lt;/code&gt; — blocks dangerous syscalls by default&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;capabilities.drop: ["ALL"]&lt;/code&gt; — strip all Linux capabilities&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;readOnlyRootFilesystem: true&lt;/code&gt; — attackers cannot write to the filesystem&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;allowPrivilegeEscalation: false&lt;/code&gt; — no setuid binaries&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Exemptions (When You Need Them)
&lt;/h3&gt;

&lt;p&gt;Some system workloads genuinely need privileged access — CNI plugins, CSI drivers, monitoring agents. Use namespace exemptions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# In kube-apiserver.yaml&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Pod&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;containers&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;command&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;kube-apiserver&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;--admission-control-config-file=/etc/kubernetes/admission.yaml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in the admission configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;apiserver.config.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AdmissionConfiguration&lt;/span&gt;
&lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PodSecurity&lt;/span&gt;
  &lt;span class="na"&gt;configuration&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pod-security.admission.config.k8s.io/v1&lt;/span&gt;
    &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;PodSecurityConfiguration&lt;/span&gt;
    &lt;span class="na"&gt;defaults&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;enforce&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;restricted"&lt;/span&gt;
    &lt;span class="na"&gt;exemptions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;namespaces&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;kube-system"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cert-manager"&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ingress-nginx"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
      &lt;span class="na"&gt;usernames&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;system:serviceaccount:kube-system:calico-node"&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Network Policies: Zero-Trust Inside the Cluster
&lt;/h2&gt;

&lt;p&gt;Kubernetes networking is flat by default. Every pod can reach every other pod in the cluster, across all namespaces — with zero built-in filtering. If one pod gets compromised, it can scan your entire internal network, hit internal APIs, and pivot to databases.&lt;/p&gt;

&lt;p&gt;Network Policies are your internal firewall. They are Kubernetes-native resources that control traffic flow at Layers 3 and 4 (IP and port level). Think of them as security group rules for pods.&lt;/p&gt;

&lt;h3&gt;
  
  
  Default-Deny: Lock Everything First
&lt;/h3&gt;

&lt;p&gt;Start by denying all ingress and egress traffic. Then selectively open only what each application needs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Default deny all ingress&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networking.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NetworkPolicy&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default-deny-ingress&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;podSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;          &lt;span class="c1"&gt;# selects all pods&lt;/span&gt;
  &lt;span class="na"&gt;policyTypes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Ingress&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Default deny all egress&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networking.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NetworkPolicy&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default-deny-egress&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;podSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;{}&lt;/span&gt;
  &lt;span class="na"&gt;policyTypes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Egress&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With these two policies in place, no pod can receive or initiate traffic. Then layer on &lt;strong&gt;allow rules&lt;/strong&gt; for specific flows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Allow frontend → backend on port 8080&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;networking.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;NetworkPolicy&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;allow-frontend-to-backend&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;production&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;podSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;backend&lt;/span&gt;
  &lt;span class="na"&gt;policyTypes&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;Ingress&lt;/span&gt;
  &lt;span class="na"&gt;ingress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;podSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend&lt;/span&gt;
    &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
      &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Real-World Zero-Trust Policy Patterns
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Pattern 1: Allow only from the ingress controller&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;ingress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;from&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;namespaceSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ingress-nginx&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;podSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app.kubernetes.io/name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ingress-nginx&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pattern 2: Allow DNS egress only (block everything else)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;egress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;namespaceSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;kubernetes.io/metadata.name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kube-system&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;podSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;k8s-app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;kube-dns&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;UDP&lt;/span&gt;
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;53&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Pattern 3: Allow egress only to specific external IPs&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;egress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;ipBlock&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;cidr&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;10.0.0.0/8&lt;/span&gt;    &lt;span class="c1"&gt;# internal VPC only&lt;/span&gt;
      &lt;span class="na"&gt;except&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;10.0.0.0/28&lt;/span&gt;        &lt;span class="c1"&gt;# except management subnet&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Cilium: Beyond Basic Network Policies
&lt;/h3&gt;

&lt;p&gt;If your CNI is Cilium (increasingly common in 2026 for eBPF-based networking), you get Layer 7 policies — filtering by HTTP method, path, or DNS name:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;cilium.io/v2"&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CiliumNetworkPolicy&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;l7-policy&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;endpointSelector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;api&lt;/span&gt;
  &lt;span class="na"&gt;ingress&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;fromEndpoints&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;matchLabels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;frontend&lt;/span&gt;
    &lt;span class="na"&gt;toPorts&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;8080"&lt;/span&gt;
        &lt;span class="na"&gt;protocol&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;TCP&lt;/span&gt;
      &lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;http&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;GET"&lt;/span&gt;
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;/api/v1/.*"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Layer 7 policies let you declare: only GET requests to &lt;code&gt;/api/v1/&lt;/code&gt; endpoints are allowed — no POST, no DELETE, no &lt;code&gt;/admin&lt;/code&gt;. A compromised frontend pod cannot abuse backend endpoints it should not access.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing Network Policies
&lt;/h3&gt;

&lt;p&gt;Use &lt;code&gt;netshoot&lt;/code&gt; (a network debugging container) to verify connectivity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl run netshoot &lt;span class="nt"&gt;--rm&lt;/span&gt; &lt;span class="nt"&gt;-it&lt;/span&gt; &lt;span class="nt"&gt;--image&lt;/span&gt; nicolaka/netshoot &lt;span class="nt"&gt;--&lt;/span&gt; /bin/bash

&lt;span class="c"&gt;# From inside, test connectivity:&lt;/span&gt;
curl backend-service.production.svc.cluster.local:8080

&lt;span class="c"&gt;# Test DNS:&lt;/span&gt;
nslookup kubernetes.default
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Always test both positive (traffic that should flow) and negative (traffic that should be blocked) cases. Network policies are easy to misconfigure — a single missing label selector can leave a hole wide open.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Image Security: Scan Every Container with Trivy
&lt;/h2&gt;

&lt;p&gt;Running containers from untrusted or unverified images is the most common entry point for supply-chain attacks. In 2024, a compromised &lt;code&gt;xz-utils&lt;/code&gt; backdoor nearly made it into production containers worldwide. In 2025, multiple malicious NPM and PyPI packages were found embedded in popular Docker images.&lt;/p&gt;

&lt;p&gt;The rule: every image that enters your cluster must be scanned. &lt;strong&gt;Trivy&lt;/strong&gt;, by Aqua Security, is the de-facto open-source scanner — fast, comprehensive, and CI/CD-friendly. It scans OS packages, language dependencies, and misconfigurations in a single pass.&lt;/p&gt;

&lt;h3&gt;
  
  
  Scanning Images
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;trivy image nginx:1.25-alpine

&lt;span class="c"&gt;# Filter by severity — only flag HIGH and CRITICAL&lt;/span&gt;
trivy image &lt;span class="nt"&gt;--severity&lt;/span&gt; HIGH,CRITICAL nginx:1.25-alpine

&lt;span class="c"&gt;# Output as JSON for pipeline integration&lt;/span&gt;
trivy image &lt;span class="nt"&gt;--format&lt;/span&gt; json &lt;span class="nt"&gt;--output&lt;/span&gt; trivy-report.json myapp:latest

&lt;span class="c"&gt;# Scan filesystem for IaC misconfigurations&lt;/span&gt;
trivy config ./kubernetes/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Integrating Trivy into CI/CD
&lt;/h3&gt;

&lt;p&gt;The most effective pattern: scan in your pipeline and &lt;strong&gt;block deployments&lt;/strong&gt; for HIGH or CRITICAL findings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Actions — Trivy scan step:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Scan container image with Trivy&lt;/span&gt;
  &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aquasecurity/trivy-action@master&lt;/span&gt;
  &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;image-ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;myapp:${{ github.sha }}&lt;/span&gt;
    &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;sarif&lt;/span&gt;
    &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;trivy-results.sarif&lt;/span&gt;
    &lt;span class="na"&gt;severity&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;HIGH,CRITICAL&lt;/span&gt;
    &lt;span class="na"&gt;exit-code&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;GitLab CI — Trivy scan job:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;trivy-scan&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;stage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;security&lt;/span&gt;
  &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;aquasec/trivy:latest&lt;/span&gt;
  &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;trivy image --severity HIGH,CRITICAL --exit-code 1 $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA&lt;/span&gt;
  &lt;span class="na"&gt;allow_failure&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Trivy Operator: Continuous Cluster Scanning
&lt;/h3&gt;

&lt;p&gt;For runtime scanning of images already deployed in your cluster, install the &lt;strong&gt;Trivy Operator&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;helm repo add aqua https://aquasecurity.github.io/helm-charts/
helm &lt;span class="nb"&gt;install &lt;/span&gt;trivy-operator aqua/trivy-operator &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--namespace&lt;/span&gt; trivy-system &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--create-namespace&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--set&lt;/span&gt; trivy.ignoreUnfixed&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Query vulnerability reports across your namespaces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get vulnerabilityreports &lt;span class="nt"&gt;-n&lt;/span&gt; production
kubectl describe vulnerabilityreport replicaset-myapp-7d4f8b9c6d-nginx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Image Pinning and Digest-Based References
&lt;/h3&gt;

&lt;p&gt;Never use floating tags like &lt;code&gt;:latest&lt;/code&gt; in production. Pin to a content-addressable digest:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# BAD: floating tag, can change underneath you&lt;/span&gt;
&lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx:latest&lt;/span&gt;

&lt;span class="c1"&gt;# GOOD: digest pinning, immutable reference&lt;/span&gt;
&lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;nginx@sha256:aed492c4d72c4a4e2f4d7d5e1f3b6c8a9d0e1f2a3b4c5d6e7f8a9b0c1d2e3f4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Extract the digest of any image:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker inspect nginx:1.25-alpine | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.[0].RepoDigests[0]'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Combine digest pinning with automated PRs from Renovate or Dependabot to keep digests updated without manual toil.&lt;/p&gt;

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

&lt;p&gt;Kubernetes security is a layered defense. Start with RBAC — if every pod runs as cluster-admin, nothing else matters. Then enforce Pod Security Standards to prevent containers from escaping their sandbox. Lock down the network with default-deny policies so a compromised pod can't pivot. Finally, scan every image with Trivy to catch vulnerabilities before they reach production.&lt;/p&gt;

&lt;p&gt;Each of these four layers independently raises the bar. Together, they turn a wide-open cluster into a hardened environment where an attacker needs to defeat multiple defenses to cause real damage. The YAML in this guide is production-ready — copy, adapt, and apply it today.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://devtocash.com/blog/kubernetes-security-best-practices-2026" rel="noopener noreferrer"&gt;devtocash.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>security</category>
      <category>devops</category>
      <category>sre</category>
    </item>
    <item>
      <title>Docker Multi-Stage Builds: Slash Your Image Size by 90%</title>
      <dc:creator>devtocash</dc:creator>
      <pubDate>Thu, 25 Jun 2026 16:06:27 +0000</pubDate>
      <link>https://dev.to/devtocash/docker-multi-stage-builds-slash-your-image-size-by-90-3k34</link>
      <guid>https://dev.to/devtocash/docker-multi-stage-builds-slash-your-image-size-by-90-3k34</guid>
      <description>&lt;p&gt;A typical Node.js Docker image weighs 1.2 GB. A Go binary image can be 800 MB. Most of that weight comes from build tooling, dev dependencies, and operating system packages that have no business being in a production container.&lt;/p&gt;

&lt;p&gt;Docker multi-stage builds solve this by separating the build environment from the runtime environment. You compile your application in a fat container with all the tools, then copy only the final artifact into a minimal runtime image.&lt;/p&gt;

&lt;p&gt;The result: images that are 10x to 50x smaller, faster to deploy, and more secure.&lt;/p&gt;

&lt;p&gt;A multi-stage Dockerfile has multiple FROM statements. Each FROM begins a new stage. You can copy artifacts from earlier stages into later ones, leaving behind everything you do not need.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Topics
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;How Multi-Stage Builds Work&lt;/li&gt;
&lt;li&gt;Real-World Examples by Language&lt;/li&gt;
&lt;li&gt;Advanced Multi-Stage Patterns&lt;/li&gt;
&lt;li&gt;Image Size Optimization Techniques&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Read the full article:&lt;/strong&gt; &lt;a href="https://devtocash.com/blog/docker-multi-stage-builds" rel="noopener noreferrer"&gt;https://devtocash.com/blog/docker-multi-stage-builds&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://devtocash.com/blog/docker-multi-stage-builds" rel="noopener noreferrer"&gt;devtocash.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>devops</category>
      <category>containers</category>
      <category>cicd</category>
    </item>
    <item>
      <title>Error Budgets: Stop Wasting Your SRE Team's Time</title>
      <dc:creator>devtocash</dc:creator>
      <pubDate>Thu, 25 Jun 2026 15:56:19 +0000</pubDate>
      <link>https://dev.to/devtocash/error-budgets-stop-wasting-your-sre-teams-time-4c08</link>
      <guid>https://dev.to/devtocash/error-budgets-stop-wasting-your-sre-teams-time-4c08</guid>
      <description>&lt;p&gt;You have a 99.9 percent SLO target. Your team is on-call, paged for every 500 error, and deployments freeze because error rates are slightly elevated. Meanwhile, your feature velocity has ground to a halt.&lt;/p&gt;

&lt;p&gt;Error budgets exist to break this cycle. They provide a clear, data-driven framework for deciding when to prioritize reliability and when to prioritize feature development. This guide covers what error budgets are, how to calculate them, how to implement them with Prometheus, and how to build an error budget policy your team will actually use.&lt;/p&gt;

&lt;p&gt;An error budget is the maximum amount of time or number of failures your service can experience in a given period before violating its SLO.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Topics Covered
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Introduction&lt;/li&gt;
&lt;li&gt;What is an Error Budget?&lt;/li&gt;
&lt;li&gt;Calculating Error Budgets&lt;/li&gt;
&lt;li&gt;Implementing Error Budgets with Prometheus&lt;/li&gt;
&lt;li&gt;Burn Rate Alerts&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Read the full article on DevToCash:&lt;/strong&gt; &lt;a href="https://devtocash.com/blog/error-budgets-sre-guide" rel="noopener noreferrer"&gt;https://devtocash.com/blog/error-budgets-sre-guide&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Originally published at &lt;a href="https://devtocash.com/blog/error-budgets-sre-guide" rel="noopener noreferrer"&gt;devtocash.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>sre</category>
      <category>devops</category>
      <category>reliability</category>
    </item>
    <item>
      <title>Test Post - Error Budgets Guide</title>
      <dc:creator>devtocash</dc:creator>
      <pubDate>Thu, 25 Jun 2026 15:54:00 +0000</pubDate>
      <link>https://dev.to/devtocash/test-post-error-budgets-guide-1lh1</link>
      <guid>https://dev.to/devtocash/test-post-error-budgets-guide-1lh1</guid>
      <description>&lt;p&gt;This is a test article about error budgets in SRE.&lt;/p&gt;

&lt;p&gt;Error budgets are a critical concept in Site Reliability Engineering that help teams balance reliability with feature velocity.&lt;/p&gt;

&lt;p&gt;Read more at &lt;a href="https://devtocash.com/blog/error-budgets-sre-guide" rel="noopener noreferrer"&gt;devtocash.com&lt;/a&gt;&lt;/p&gt;

</description>
      <category>sre</category>
      <category>devops</category>
    </item>
    <item>
      <title>Error Budgets Will Save Your SRE Team (If You Actually Use Them)</title>
      <dc:creator>devtocash</dc:creator>
      <pubDate>Thu, 25 Jun 2026 15:28:56 +0000</pubDate>
      <link>https://dev.to/devtocash/error-budgets-will-save-your-sre-team-if-you-actually-use-them-1gpb</link>
      <guid>https://dev.to/devtocash/error-budgets-will-save-your-sre-team-if-you-actually-use-them-1gpb</guid>
      <description>&lt;p&gt;Error budgets will save your SRE team.&lt;/p&gt;

&lt;p&gt;Most teams set a 99.9% SLO then burn out engineers paging for every 500 error. That's anti-SRE.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is an Error Budget?
&lt;/h2&gt;

&lt;p&gt;1 minus your SLO target. For 99.9% over 30 days, that's 43.2 minutes of allowed downtime.&lt;/p&gt;

&lt;h2&gt;
  
  
  Burn Rate Alerts
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Fast burn (14.4x): page-level alert&lt;/li&gt;
&lt;li&gt;Slow burn (2x): ticket-level&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read the complete guide: &lt;a href="https://devtocash.com/blog/error-budgets-sre-guide" rel="noopener noreferrer"&gt;https://devtocash.com/blog/error-budgets-sre-guide&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>sre</category>
      <category>errorbudgets</category>
      <category>prometheus</category>
    </item>
  </channel>
</rss>
