Skip to main content

Kubernetes Security:

 Kubernetes Security: RBAC, Network Policies, and Pod Security

Kubernetes security is a shared responsibility. The cluster administrator secures the infrastructure, while application teams secure their workloads. This guide covers the essential security controls you need to protect your Kubernetes environment.


📅 Published: May 2026

⏱️ Estimated Reading Time: 18 minutes
🏷️ Tags: Kubernetes Security, RBAC, Network Policies, Pod Security, DevSecOps


Introduction: The Kubernetes Security Challenge

Kubernetes is powerful, but power comes with risk. A compromised container can potentially affect other containers, access sensitive data, or even take over nodes. Unlike traditional virtual machines with strong isolation boundaries, Kubernetes relies on proper configuration and security practices.

Kubernetes security has three critical layers:

Layer 1: Authentication and Authorization (RBAC) – Who can do what. This is your front door security.

Layer 2: Network Security (Network Policies) – What traffic is allowed where. This is your internal firewall.

Layer 3: Workload Security (Pod Security) – How Pods can run. This protects your applications at runtime.

This guide covers each layer in depth, providing practical configurations and real-world examples.


Part 1: RBAC (Role-Based Access Control)

What is RBAC?

RBAC controls who has access to the Kubernetes API and what actions they can perform. It is the primary mechanism for securing the Kubernetes control plane.

Think of RBAC as a security badge system for your cluster. Each user gets a badge (authentication). The badge has certain permissions (authorization). A developer can read and create Pods. An auditor can only read resources. A cluster admin can do anything.

The Four RBAC Objects

ObjectPurpose
RoleDefines permissions within a specific Namespace
ClusterRoleDefines permissions cluster-wide or across all Namespaces
RoleBindingAttaches a Role to a user or group within a Namespace
ClusterRoleBindingAttaches a ClusterRole to a user or group cluster-wide

RBAC Hierarchy

text
ClusterRoleBinding → ClusterRole (cluster-wide)
        ↓
RoleBinding → Role (namespace-specific)
        ↓
    User/Group/ServiceAccount

Role Example (Namespace-Specific)

yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
  namespace: development
rules:
- apiGroups: [""]              # Core API group
  resources: ["pods"]          # Resource type
  verbs: ["get", "list", "watch"]  # Allowed actions
- apiGroups: [""]
  resources: ["pods/log"]
  verbs: ["get", "list"]

ClusterRole Example (Cluster-Wide)

yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: secret-reader
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "list"]

RoleBinding Example

yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: development
subjects:
- kind: User
  name: alice@example.com    # User email
  apiGroup: rbac.authorization.k8s.io
- kind: Group
  name: developers
  apiGroup: rbac.authorization.k8s.io
- kind: ServiceAccount
  name: my-sa               # Service account in this namespace
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

ClusterRoleBinding Example

yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: read-secrets-global
subjects:
- kind: User
  name: auditor@example.com
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

Useful Verbs

VerbDescription
getRetrieve a specific resource
listList all resources of a type
watchWatch for changes
createCreate new resources
updateUpdate existing resources
patchPartially update resources
deleteDelete resources
deletecollectionDelete collections of resources

Common RBAC Patterns

1. Read-only access for a namespace

yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: read-only
  namespace: development
rules:
- apiGroups: ["*"]
  resources: ["*"]
  verbs: ["get", "list", "watch"]

2. Full access to a specific namespace

yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: namespace-admin
  namespace: development
rules:
- apiGroups: ["*"]
  resources: ["*"]
  verbs: ["*"]

3. Pod exec access (for debugging)

yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-exec
  namespace: development
rules:
- apiGroups: [""]
  resources: ["pods/exec"]
  verbs: ["create"]

Service Account Permissions

A ServiceAccount is an identity for Pods, not humans.

yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: my-app-sa
  namespace: production
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: my-app-binding
  namespace: production
subjects:
- kind: ServiceAccount
  name: my-app-sa
  namespace: production
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

RBAC Commands

bash
# Check if RBAC is enabled
kubectl api-versions | grep rbac

# List Roles
kubectl get roles --all-namespaces
kubectl get clusterroles

# List RoleBindings
kubectl get rolebindings --all-namespaces
kubectl get clusterrolebindings

# Check permissions for current user
kubectl auth can-i create pods
kubectl auth can-i delete secrets --namespace=production

# Check permissions for specific user
kubectl auth can-i list pods --as=alice@example.com

# Describe a Role
kubectl describe role pod-reader -n development

Part 2: Network Policies

What are Network Policies?

Network Policies control traffic flow between Pods and external endpoints. By default, all Pods can communicate with all other Pods. Network Policies restrict this.

Think of Network Policies as firewall rules for your Pods. You define which Pods can talk to which other Pods, and on which ports.

Network Policy Example

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: backend-policy
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    - namespaceSelector:
        matchLabels:
          name: monitoring
    ports:
    - protocol: TCP
      port: 8080
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: database
    ports:
    - protocol: TCP
      port: 5432
  - to:
    - ipBlock:
        cidr: 10.0.0.0/8
    ports:
    - protocol: TCP
      port: 443

Deny All Traffic (Default Deny)

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

Allow All Traffic (Default Allow)

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-all
  namespace: production
spec:
  podSelector: {}
  ingress:
  - {}
  egress:
  - {}
  policyTypes:
  - Ingress
  - Egress

Allow Only Within Namespace

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-same-namespace
spec:
  podSelector: {}
  ingress:
  - from:
    - podSelector: {}
  policyTypes:
  - Ingress

Allow from Specific Namespace

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-from-monitoring
spec:
  podSelector:
    matchLabels:
      app: backend
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: monitoring
    ports:
    - protocol: TCP
      port: 9090

Allow from Specific Pod

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-from-frontend
spec:
  podSelector:
    matchLabels:
      app: database
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - protocol: TCP
      port: 5432

Allow to External IP (Egress)

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-to-external-api
spec:
  podSelector:
    matchLabels:
      app: myapp
  egress:
  - to:
    - ipBlock:
        cidr: 192.168.1.0/24
    ports:
    - protocol: TCP
      port: 443
  policyTypes:
  - Egress

Network Policy Commands

bash
# List Network Policies
kubectl get networkpolicies
kubectl get netpol

# Describe a policy
kubectl describe networkpolicy backend-policy

# Delete a policy
kubectl delete networkpolicy deny-all

Network Policy Requirements

Network Policies are implemented by a CNI plugin that supports them. Popular options include:

CNI PluginNetwork Policy Support
CalicoFull support
CiliumFull support
WeaveFull support
FlannelNo support
Amazon VPC CNILimited (requires Calico)

Part 3: Pod Security

What is Pod Security?

Pod Security controls how Pods can run. It restricts privileged operations, host access, and resource usage. This is your last line of defense before a container can compromise the node.

Pod Security Standards

Kubernetes defines three Pod Security Standards:

StandardDescriptionUse Case
PrivilegedNo restrictionsSystem components, CI/CD runners
BaselineMinimal restrictions, prevents known privilege escalationsGeneral purpose applications
RestrictedHeavily restricted, follows hardening best practicesHighly sensitive workloads

Pod Security Admission (PSA)

Pod Security Admission (PSA) is the built-in Kubernetes feature for enforcing Pod Security Standards.

yaml
apiVersion: v1
kind: Namespace
metadata:
  name: production
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/enforce-version: latest
    pod-security.kubernetes.io/warn: baseline
    pod-security.kubernetes.io/audit: restricted

Labels explained:

LabelPurpose
enforceViolations block Pod creation
warnViolations emit warnings (non-blocking)
auditViolations are recorded in audit logs

What Restricted Mode Enforces

yaml
# Restricted mode prevents:
- privileged: true
- hostPID: true
- hostIPC: true
- hostNetwork: true
- allowPrivilegeEscalation: true
- readOnlyRootFilesystem: false
- seccompProfile: Unconfined

Example: Pod That Complies with Restricted Mode

yaml
apiVersion: v1
kind: Pod
metadata:
  name: secure-pod
  namespace: production
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    seccompProfile:
      type: RuntimeDefault
  containers:
  - name: app
    image: nginx
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop:
        - ALL

Pod SecurityContext

SecurityContext applies to a Pod or individual container.

yaml
apiVersion: v1
kind: Pod
metadata:
  name: secure-pod
spec:
  securityContext:           # Pod-level (applies to all containers)
    runAsNonRoot: true
    runAsUser: 1000
    fsGroup: 2000
    seccompProfile:
      type: RuntimeDefault
  containers:
  - name: app
    image: myapp
    securityContext:         # Container-level (overrides Pod-level)
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop: ["ALL"]
        add: ["NET_BIND_SERVICE"]

Pod SecurityContext Fields

FieldPurpose
privilegedRun as privileged container (dangerous)
runAsUserUser ID to run processes
runAsGroupGroup ID to run processes
runAsNonRootPrevent running as root
fsGroupFilesystem group for volumes
allowPrivilegeEscalationPrevent gaining more privileges
readOnlyRootFilesystemMake root filesystem read-only
capabilitiesLinux capabilities (drop/add)
seccompProfileSeccomp profile for system calls

Linux Capabilities

yaml
securityContext:
  capabilities:
    drop:        # Remove dangerous capabilities
    - ALL
    add:         # Add only needed capabilities
    - NET_BIND_SERVICE  # Bind to ports below 1024
    - CHOWN             # Change file ownership

Pod Security Admission (PSA) Commands

bash
# Check what a namespace enforces
kubectl get namespace production -o yaml | grep pod-security

# Test if a Pod would be allowed
kubectl apply --dry-run=server -f pod.yaml

# Evaluate namespace against standard
kubectl label namespace production pod-security.kubernetes.gov/check-strict=restricted

Real-World Security Scenarios

Scenario 1: Multi-Tenant Cluster

A cluster serves three teams: frontend, backend, and data. Each team needs isolation.

yaml
# Create namespaces per team
kubectl create namespace frontend
kubectl create namespace backend
kubectl create namespace data

# Apply RBAC per namespace
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: team-admin
  namespace: frontend
rules:
- apiGroups: ["*"]
  resources: ["*"]
  verbs: ["*"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: frontend-binding
  namespace: frontend
subjects:
- kind: Group
  name: frontend-team
roleRef:
  kind: Role
  name: team-admin
  apiGroup: rbac.authorization.k8s.io

# Apply Network Policies to isolate namespaces
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-cross-namespace
  namespace: frontend
spec:
  podSelector: {}
  ingress:
  - from:
    - podSelector: {}
  policyTypes:
  - Ingress

Scenario 2: Secure Database Access

A database Pod should only accept traffic from the application Pod.

yaml
# Database Pod with restrictive Pod Security
apiVersion: v1
kind: Pod
metadata:
  name: postgres
  labels:
    app: database
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 999
    seccompProfile:
      type: RuntimeDefault
  containers:
  - name: postgres
    image: postgres:15
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop: ["ALL"]
        add: ["CHOWN", "DAC_OVERRIDE", "SETGID", "SETUID"]
---
# Network Policy: Only allow app Pods
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: database-policy
spec:
  podSelector:
    matchLabels:
      app: database
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: webapp
    ports:
    - protocol: TCP
      port: 5432
  policyTypes:
  - Ingress
---
# RBAC: Only service account can access
apiVersion: v1
kind: ServiceAccount
metadata:
  name: database-sa
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: database-binding
subjects:
- kind: ServiceAccount
  name: webapp-sa
roleRef:
  kind: Role
  name: database-access

Scenario 3: Pod Security Enforcement

Production namespace requires Restricted security standard.

yaml
# Namespace with enforce=restricted
apiVersion: v1
kind: Namespace
metadata:
  name: production
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/warn: baseline
    pod-security.kubernetes.io/audit: restricted

# This Pod will be BLOCKED in production
apiVersion: v1
kind: Pod
metadata:
  name: unsafe-pod
  namespace: production
spec:
  securityContext:
    privileged: true    # ← Violation!
    runAsUser: 0        # ← Violation!
  containers:
  - name: app
    image: nginx

Scenario 4: Service Account for CI/CD

A CI/CD pipeline needs to deploy applications.

yaml
# Create service account
apiVersion: v1
kind: ServiceAccount
metadata:
  name: ci-cd-sa
  namespace: development

# Grant deployment permissions
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: ci-cd-role
  namespace: development
rules:
- apiGroups: ["apps"]
  resources: ["deployments", "statefulsets"]
  verbs: ["get", "list", "create", "update", "delete"]
- apiGroups: [""]
  resources: ["services", "configmaps", "secrets"]
  verbs: ["get", "list", "create", "update"]

# Bind to service account
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: ci-cd-binding
  namespace: development
subjects:
- kind: ServiceAccount
  name: ci-cd-sa
roleRef:
  kind: Role
  name: ci-cd-role
  apiGroup: rbac.authorization.k8s.io

Summary

Security LayerPurposeKey Features
RBACWho can do whatRoles, ClusterRoles, RoleBindings, ClusterRoleBindings
Network PoliciesWhat traffic is allowedIngress rules, Egress rules, Pod selectors, Namespace selectors
Pod SecurityHow Pods can runSecurityContext, RunAsNonRoot, Capabilities, Seccomp, Pod Security Admission

Security Checklist

RBAC

  • Default service account has minimal permissions

  • Users assigned to groups, not individual permissions

  • Service accounts for Pods, not default

  • Regular audit of RBAC permissions

Network Policies

  • Default deny all Network Policy applied

  • Ingress policies defined for each service

  • Egress policies for external communication

  • Cross-namespace communication restricted

Pod Security

  • Run as non-root user

  • Read-only root filesystem

  • Drop all capabilities, add only needed

  • Seccomp profile set to RuntimeDefault

  • Pod Security Admission enforced on namespaces


Practice Questions

  1. What is the difference between a Role and a ClusterRole?

  2. How does a Network Policy differ from a firewall rule in a load balancer?

  3. Why should you drop all capabilities and add only needed ones?

  4. What happens when you set runAsNonRoot: true but the container image runs as root?

  5. How would you prevent Pods in the development namespace from accessing Pods in the production namespace?


Learn More

Practice Kubernetes security with hands-on exercises in our interactive labs:
https://devops.trainwithsky.com/

Comments

Popular posts from this blog

📊 Monitoring & Logging in Kubernetes – Tools like Prometheus, Grafana, and Fluentd

  Monitoring & Logging in Kubernetes – Tools like Prometheus, Grafana, and Fluentd Monitoring and logging are essential for maintaining a healthy and well-performing Kubernetes cluster. In this guide, we’ll cover why monitoring is important, key monitoring tools like Prometheus and Grafana, and logging tools like Fluentd to help you gain visibility into your cluster’s performance and logs. Shape Your Future with AI & Infinite Knowledge...!! Want to Generate Text-to-Voice, Images & Videos? http://www.ai.skyinfinitetech.com Read In-Depth Tech & Self-Improvement Blogs http://www.skyinfinitetech.com Watch Life-Changing Videos on YouTube https://www.youtube.com/@SkyInfinite-Learning Transform Your Skills, Business & Productivity – Join Us Today! 🚀 Introduction In today’s fast-paced cloud-native environment, Kubernetes has emerged as the de-facto container orchestration platform. But deploying and managing applications in Kubernetes is just half the ba...

How to Use SKY TTS: The Complete, Step-by-Step Guide for 2025

 What is SKY TTS? SKY TTS  is a free, next-generation  AI audio creation platform  that brings together high-quality  Text-to-Speech ,  Speech-to-Text , and a full suite of professional  audio editing tools  in one seamless experience. Our vision is simple — to make advanced audio technology  free, accessible, and effortless  for everyone. From creators and educators to podcasters, developers, and businesses, SKY TTS helps users produce  studio-grade voice content  without expensive software or technical skills. With support for  70+ languages, natural voices, audio enhancement, waveform generation, and batch automation , SKY TTS has become a trusted all-in-one toolkit for modern digital audio workflows. Why Choose SKY TTS? Instant Conversion:  Enjoy rapid text-to-speech generation, even with large documents. Advanced Voice Settings:   Adjust speed, pitch, and style for a personalized listening experience. Multi-...

Introduction to Terraform – The Future of Infrastructure as Code

  Introduction to Terraform – The Future of Infrastructure as Code In today’s fast-paced DevOps world, managing infrastructure manually is outdated . This is where Terraform comes in—a powerful Infrastructure as Code (IaC) tool that allows you to define, provision, and manage cloud infrastructure efficiently . Whether you're working with AWS, Azure, Google Cloud, or on-premises servers , Terraform provides a declarative, automation-first approach to infrastructure deployment. Shape Your Future with AI & Infinite Knowledge...!! Read In-Depth Tech & Self-Improvement Blogs http://www.skyinfinitetech.com Watch Life-Changing Videos on YouTube https://www.youtube.com/@SkyInfinite-Learning Transform Your Skills, Business & Productivity – Join Us Today! In today’s digital-first world, agility and automation are no longer optional—they’re essential. Companies across the globe are rapidly shifting their operations to the cloud to keep up with the pace of innovatio...