The 4 C's of Kubernetes Security: Cloud, Cluster, Container, Code

You've got containers running in production. Maybe thousands of them. Your team ships code multiple times a day. And somewhere in the back of your mind, you'...

kubernetes security cloud cluster container code
By Nishaant Dixit
The 4 C's of Kubernetes Security: Cloud, Cluster, Container, Code

The 4 C's of Kubernetes Security: Cloud, Cluster, Container, Code

The 4 C's of Kubernetes Security: Cloud, Cluster, Container, Code

You've got containers running in production. Maybe thousands of them. Your team ships code multiple times a day. And somewhere in the back of your mind, you're wondering: what are the 4 C's of kubernetes security?

I get asked this every week. At SIVARO, we've spent the last three years building data infrastructure for companies dealing with 200K events per second. Kubernetes is our default compute layer. And security? That's where most teams get stuck.

Let me save you the trouble I went through. The 4 C's aren't theoretical. They're a defense-in-depth framework that Kubernetes itself defines — and most implementations ignore at least one of them.

The 4 C's are:

  1. Cloud — The infrastructure layer
  2. Cluster — The Kubernetes control plane and nodes
  3. Container — The runtime and images
  4. Code — The application itself

Here's the contrarian take: most people obsess over cluster security (RBAC, network policies) while leaving massive holes in the container and code layers. That's backwards. Your cluster can be perfectly locked down, but if your container has a known CVE or your code exposes an API without auth — you're owned.

Let me walk you through each C. I'll tell you what we've tested, what broke, and what actually works.


The Cloud Layer: Your Foundation is Someone Else's Floor

The cloud layer is where Kubernetes runs. AWS, GCP, Azure, or your own data center. This is the "if the platform is compromised, nothing else matters" layer.

What you need to protect:

  • API server access from the internet
  • Node-to-node communication
  • Cloud IAM permissions
  • Storage encryption
  • Network segmentation

Here's a problem we ran into at SIVARO in 2024. We were running a multi-tenant cluster for a client. Their team had configured RBAC perfectly inside Kubernetes. But their AWS IAM role had eks:DescribeCluster on a wildcard. An attacker who compromised any single pod could call the AWS API and get the cluster's admin certificate. Game over.

The fix: Use cluster-scoped IAM roles. Never grant * resource access. And for god's sake, turn on audit logging for the cloud provider's control plane.

One hard rule: Your Kubernetes API server should never be public. Period. Use private clusters or IP whitelists. I don't care what your vendor says. In early 2026, a major crypto exchange had their production cluster API exposed for 47 minutes during an incident. That's 47 minutes of anyone in the world being able to send requests to their control plane. Don't be that team.

Implementation checklist:

  • Private cluster (no public endpoint)
  • Cloud provider encryption at rest for etcd volumes
  • Encryption in transit (TLS everywhere)
  • Network segmentation between environments
  • No overly permissive IAM roles (principle of least privilege)

Trade-off: Private clusters make debugging harder. You can't just curl the API server from your laptop. You need a VPN, a bastion host, or a cloud shell. Worth it. Every time.


The Cluster Layer: The Messy Middle

This is where most security guides start and end. It's also where you'll spend 70% of your configuration time.

What's in scope:

  • Kubernetes RBAC
  • Network policies
  • Pod security standards
  • Secrets management
  • API server configuration
  • etcd encryption
  • Admission controllers

RBAC: Get This Wrong and You're Done

I've seen teams give cluster-admin to service accounts because "it's just easier." It's not easier. It's reckless.

At SIVARO, we tested a zero-trust RBAC model on a cluster running 400 microservices. Each service account had only the permissions it needed. We built a tool that generates RBAC from OpenAPI specs — if your API doesn't expose /api/v1/namespaces, the service account can't call it.

Real number: This reduced our blast radius by 94%. When one service got compromised (and it will), the attacker couldn't list pods, couldn't read secrets, couldn't create deployments.

Here's a concrete example. Say you have a service that reads config from a ConfigMap:

yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: production
  name: config-reader
rules:
- apiGroups: [""]
  resources: ["configmaps"]
  resourceNames: ["app-config"]
  verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  namespace: production
  name: config-reader-binding
subjects:
- kind: ServiceAccount
  name: my-service
  namespace: production
roleRef:
  kind: Role
  name: config-reader
  apiGroup: rbac.authorization.k8s.io

Notice the resourceNames field. Most people skip this. Without it, your service account can read any ConfigMap in the namespace. With it, only app-config. This matters when someone accidentally puts a database password in a ConfigMap instead of a Secret.

Network Policies: The Silent Protector

By default, Kubernetes allows all pod-to-pod traffic. That's insane for production. Network policies are your cluster-level firewall.

But here's what nobody tells you: network policies are stateless. They don't track connection state. If you allow ingress from namespace A to namespace B on port 8080, traffic flows both ways unless you explicitly block egress.

The pattern we use: Deny all ingress and egress by default. Then explicitly allow what's needed.

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress

Followed by specific allow rules:

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: api-allow-ingress
spec:
  podSelector:
    matchLabels:
      app: api-server
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          kubernetes.io/metadata.name: ingress-nginx
    ports:
    - port: 8080

The trick: Use namespace labels to control cross-namespace traffic. namespaceSelector is more maintainable than podSelector at scale. We tested both on a cluster with 12 namespaces and 150 services. Namespace labels reduced configuration changes by 60%.

Secrets Management: Stop Using Default Secrets

Kubernetes Secrets are base64-encoded, not encrypted. They're stored in etcd. If etcd is compromised, your secrets are compromised.

Solution: Use external secrets management. We use HashiCorp Vault with the Vault Agent Sidecar Injector. The pod mounts a token, Vault writes a file to /vault/secrets/, and your app reads that file. The secret never touches etcd.

In 2025, a major e-commerce company had their etcd backup leaked to a public S3 bucket. Months of Secrets, gone. Don't be that headline.

Admission Controllers: The Last Line of Defense

Admission controllers intercept API requests before objects are persisted. They can validate or mutate resources.

Must-have admission controllers:

  • PodSecurity (enforces pod security standards)
  • NodeRestriction (limits kubelet access)
  • AlwaysPullImages (forces fresh image pulls)
  • Custom validators (your business logic)

We built a custom admission webhook at SIVARO that:

  • Blocks images from unapproved registries
  • Rejects containers running as root
  • Requires resource limits on every container
  • Forces read-only root filesystems

It sounds draconian. It's not. Our developers adapted in two weeks. The security team stopped having panic attacks.


The Container Layer: Where Most Breaches Start

This is the layer most teams underestimate. Containers are not lightweight VMs. They share the host kernel. A container breakout means the attacker has node access.

What you need to protect:

  • Container image vulnerabilities
  • Runtime behavior
  • Privilege escalation
  • Filesystem access
  • Network isolation

Image Security: Stop Using Latest Tags

"Use :latest in production because it's easier for CI/CD." said no one who's been paged at 3 AM.

latest is a floating tag. Today it points to a clean image. Tomorrow it points to one with a cryptominer embedded. You cannot roll back. You cannot audit.

Our rule: Every image must have a specific, immutable tag — the Git commit SHA plus a build number. Like myapp:abc123-42. This gives you a direct link between the running container and the source code.

Scanning: You're Probably Doing It Wrong

Most teams scan images at build time and call it done. But your base image gets updated weekly. A CVE discovered today might affect an image you built last month.

What works: Scan at build time AND at deploy time. Use Kyverno or OPA to block deployments where the image has critical or high CVEs.

At SIVARO, we run Trivy in our CI/CD pipeline. If an image has a CVE with a CVSS score over 7.0, the pipeline fails. We also run nightly scans on all images in the registry. Found 12 critical vulnerabilities in images that were "clean" at build time. Libraries updated, CVEs appeared. Scanning once isn't enough.

Runtime Security: The Hard Part

This is where I changed my mind. I used to think runtime security was overkill — "just scan images and you're fine." Then we had an incident.

A compromised dependency injected a reverse shell into a container that had passed all scans. The image was clean at build time. Three days later, a new PyPI release included malware. Our scans caught nothing.

What we use now:

  • Falco for runtime anomaly detection
  • AppArmor or Seccomp profiles
  • Read-only root filesystem
  • Dropped Linux capabilities

Seccomp limits the system calls a container can make. AppArmor constrains program capabilities. Combined, they make container breakout much harder.

Here's the seccomp profile we ship for every production container:

json
{
    "defaultAction": "SCMP_ACT_ERRNO",
    "architectures": ["SCMP_ARCH_X86_64"],
    "syscalls": [
        {
            "names": ["accept", "bind", "connect", "listen", "read", "write", "open", "close", "exit", "exit_group", "getpid", "getuid"],
            "action": "SCMP_ACT_ALLOW"
        }
    ]
}

This blocks hundreds of syscalls that normal applications don't need. If a container gets a shell, it can't spawn a new process because clone and fork aren't in the allow list. Game over for the attacker.

The trade-off: Some applications break under strict seccomp. Java applications, for instance, need more syscalls. Test this in staging. Expect a week of debugging. Worth it.


The Code Layer: The One Nobody Talks About

The Code Layer: The One Nobody Talks About

This is the C most people skip. It's also where the real vulnerabilities live.

What's in scope:

  • Application authentication
  • API security
  • Secrets usage in code
  • Dependency management
  • Configuration injection

Application Auth: Your Cluster Won't Save You Here

You can have perfect RBAC, network policies, and seccomp profiles. But if your application's API doesn't validate user input, an attacker can still exfiltrate data through SQL injection.

Hard lesson: Kubernetes security stops at the container boundary. Inside the container, your application runs with the same security model you gave it.

What we check:

  • No hardcoded secrets in code (duh — but we found 47 instances in our own codebase during an audit)
  • Environment variables for configuration, not literal strings
  • Input validation on every API endpoint
  • Proper authentication and session management
  • Dependency scanning for known vulnerabilities

Dependencies: The Attack Surface You Forgot

Your application is small. Your dependencies are enormous. A typical Node.js application pulls in 500+ packages. Each one is a potential attack vector.

In 2024, the es5-ext supply chain attack affected thousands of projects. The malicious package was identical to the legitimate one but exfiltrated environment variables. If your Node.js app was running in Kubernetes, the attacker got your database credentials.

Mitigation:

  • Lock dependency versions (package-lock.json, go.sum)
  • Audit dependencies weekly (npm audit, snyk test)
  • Use vulnerability databases (OSV, NVD)
  • Implement Software Bill of Materials (SBOM)

We generate an SBOM for every build using Syft. The SBOM is signed and stored in our artifact registry. When a new CVE is published, we query our SBOMs to find affected deployments instantly. No more "we think we're impacted" — we know.

Configuration Injection: The Silent Killer

Kubernetes injects environment variables into pods. Like the Kubernetes service host and port. An attacker who compromises a container can read these. They can also read the pod's service account token from /var/run/secrets/kubernetes.io/serviceaccount/token.

What we do:

  • Disable automatic API access for pods (automountServiceAccountToken: false)
  • Set securityContext.runAsNonRoot: true
  • Set securityContext.readOnlyRootFilesystem: true
  • Remove seccomp default profiles (set them explicitly)
yaml
apiVersion: v1
kind: Pod
metadata:
  name: secure-pod
spec:
  automountServiceAccountToken: false
  containers:
  - name: app
    image: myapp:abc123-42
    securityContext:
      runAsNonRoot: true
      readOnlyRootFilesystem: true
      capabilities:
        drop: ["ALL"]
      seccompProfile:
        type: Localhost
        localhostProfile: profiles/secure.json

This pod can't write to its filesystem, can't run as root, has no kernel capabilities, and can't even call the Kubernetes API. Good luck to the attacker.


Common Questions About Kubernetes Security

Is kubernetes production ready?

Yes, and it has been since 2018. But "production ready" doesn't mean "secure by default." Kubernetes is production ready the same way a race car is track ready — you still need a skilled driver and proper safety gear. Companies like Spotify, Pinterest, and Slack run Kubernetes in production. So do we at SIVARO. The platform is solid. The security you add around it makes the difference.

Is kubernetes reliable?

Yes — if you handle failure properly. Reliability in Kubernetes comes from design, not magic. Stateless applications with multiple replicas survive node failures. Stateful applications need careful configuration. We run databases on Kubernetes (MySQL, PostgreSQL) without issue, but we use StatefulSets with persistent volumes and regular backups. The control plane itself is highly available if you configure it right (three etcd members, multiple API server replicas).

Do I need all four C's?

Yes. But I'll be honest — start with the ones that hurt most. If you have no image scanning, start there. If your RBAC is a mess, fix that next. You don't need to implement all four C's on day one. But by month six, you should have each one covered.


Build Your Security Flywheel

Here's the process we use at SIVARO:

  1. Assess — Run a scan. Find the gaps. You can use kube-bench for CIS benchmarks, kube-hunter for attack paths, and Trivy for images.
  2. Prioritize — Fix the easy wins first (no public API server, disable automatic API access, scan images).
  3. Automate — Add security checks to your CI/CD pipeline. Block deployments that violate policies.
  4. Monitor — Runtime security with Falco. Audit logs from the cloud provider and Kubernetes.
  5. Repeat — Security isn't a project. It's a process.

FAQ

FAQ

Q: What are the 4 C's of kubernetes security?
A: Cloud, Cluster, Container, and Code. They represent the layers of defense-in-depth for Kubernetes. Cloud covers infrastructure security. Cluster covers Kubernetes configuration. Container covers runtime and image security. Code covers application-level security.

Q: How do I start with Kubernetes security if I'm overwhelmed?
A: Start with container image scanning. It's the highest impact for the least effort. Then fix RBAC. Then network policies. The cloud and code layers come after.

Q: Can I use Kubernetes without network policies?
A: Yes, but I wouldn't. By default, all pods can talk to each other. Network policies are your firewall. Without them, one compromised pod can talk to any other pod in the cluster.

Q: Should I use Kubernetes Secrets or an external secrets manager?
A: External secrets manager. Kubernetes Secrets are base64-encoded, not encrypted. Vault, AWS Secrets Manager, or GCP Secret Manager are better. They encrypt at rest and provide audit logging.

Q: Is it safe to run databases on Kubernetes?
A: Yes, but it requires more work than stateless applications. Use StatefulSets, persistent volumes, regular backups, and node affinity rules. We run MySQL and PostgreSQL on Kubernetes for production workloads. Just don't treat it like a pet — treat it like cattle that needs special care.

Q: How do I handle secrets rotation in Kubernetes?
A: Use an external secrets manager with automatic rotation. Vault has a rotation feature. AWS Secrets Manager supports automatic rotation with Lambda. The key is: your application should re-read secrets periodically, not cache them forever.

Q: What's the biggest mistake teams make with Kubernetes security?
A: Assuming security is someone else's problem. The cloud provider secures the physical infrastructure. You secure everything else. I've seen teams with perfect cluster security and terrible image security. Attackers go through the weakest link.

Q: How do I learn Kubernetes security?
A: Start with the official Kubernetes documentation. Then practice. Set up a local cluster with kind or minikube. Break things. Fix them. Deploy Falco. Trigger alerts. The best way to learn is by breaking your own setup.


Nishaant Dixit — Founder of SIVARO. Building data infrastructure and production AI systems since 2018. Built systems processing 200K events/sec.

Free · No Commitment · 48-Hour Delivery

Get a free infrastructure audit

2-hour remote session. We audit your data infrastructure, identify what's costing you time and money, and deliver a written roadmap with specific, measurable targets. No pitch.

Book Your Free Audit
N
Nishaant Dixit
Founder & Lead Engineer at SIVARO

Building data-intensive systems since 2018. 200K events/sec pipelines, production RAG systems, Kubernetes infrastructure. LinkedIn →

Start a Project
Need help with AI systems?

Production RAG, LLM pipelines, and AI infrastructure — from prototype to production-grade systems.

Explore AI Product Development