Security is not an afterthought. This module builds defense-in-depth from authentication through admission control, with production-ready patterns for GKE.
Module 6 of 8 | Difficulty: Intermediate to Advanced
In previous chapters you learned to persist data with StatefulSets. But what happens when anyone who reaches your cluster can delete anything? All that precious state is one malicious kubectl delete away from disaster. Security is the foundation everything stands on.
This chapter covers Authentication (proving identity) and Authorization (checking permissions). We'll use a building security analogy, then translate it into commands and YAML.
6.1.1 The Kubernetes Security Model: The Three A's
Analogy: The Corporate Building Security System
Imagine walking into a corporate headquarters. To reach a sensitive server room, you pass three checkpoints. First, the lobby guard checks your government ID—proving who you are. Second, you swipe a keycard at the elevator—determining which floors you can access. Third, a policy checker verifies you're following safety protocols before you enter the server room.
These map directly to Kubernetes:
| Building Checkpoint | Kubernetes Layer | Question It Answers |
|---|---|---|
| ID check at lobby | Authentication (AuthN) | "Who are you?" |
| Keycard floor access | Authorization (AuthZ) | "What are you allowed to do?" |
| Policy checker at server room | Admission Control | "Are you following the rules?" |
Every API request—whether from kubectl or a Pod—flows through these three gates before reaching etcd.
Visual Description:
GKE Note: On GKE, Authentication is handled through GCP IAM. When you run
gcloud container clusters get-credentials, gcloud obtains an OAuth2 token and inserts it into your kubeconfig. The API Server validates it against Google's identity services. No manual client certificate management needed.
Zero-Trust Principles. Kubernetes embraces zero-trust: never trust, always verify. Even internal traffic requires authentication. A Pod calling the API must present credentials like a human user. Defense in depth means each layer provides independent protection.
Threat Model. The API Server is the cluster boundary. Anything that can authenticate to it can control the cluster. Production clusters should use private endpoints and authorized networks.
🛑 PAUSE & RECALL — 2 minutes
- What are the three A's of Kubernetes security, and what question does each answer?
- What HTTP status code does rejected Authentication return? What about rejected Authorization?
- In the building analogy, what is the equivalent of a ServiceAccount token?
Rate your confidence (0-4).
6.1.2 Authentication: Proving Who You Are
Authentication answers: who are you? Kubernetes has no built-in user database. Instead, it delegates identity verification to external systems via authentication plugins.
Client Certificate Authentication. An admin creates a private key and CSR, then a cluster CA signs the certificate. The user presents this certificate with every request. Works well for small teams but scales poorly.
Bearer Tokens. Presented in the Authorization: Bearer <token> header:
- ServiceAccount tokens: JWT tokens auto-mounted into Pods at
/var/run/secrets/kubernetes.io/serviceaccount/token. How applications authenticate to the API Server from inside the cluster. - OIDC tokens: Integration with external identity providers (Google Identity, Okta, Azure AD). Preferred for enterprise—enables single sign-on and centralized user management.
- Webhook token authentication: The API Server forwards tokens to an external service for validation.
⚠️ Common Misconception: Many beginners think Kubernetes has a built-in user database with passwords. It does not. There is no kubectl create user command. Users exist only in certificates, OIDC claims, or webhook responses.
6.1.3 Authorization: RBAC Deep Dive
Once the API Server knows who you are, it decides what you can do. Modern Kubernetes uses RBAC (Role-Based Access Control).
Analogy: The Building Keycard System
The security office maintains a permission matrix. "Floor 3 Employee" can access Floor 3 offices. "Building Manager" can access all floors. "Visitor" can only access the lobby. The matrix itself is the Role. When the security office assigns a keycard to a person, that's the RoleBinding. No keycard, no access.
In Kubernetes, RBAC uses four resource types:
| Resource | Scope | Purpose |
|---|---|---|
| Role | Namespace | Defines permissions (verbs on resources) within one namespace |
| ClusterRole | Cluster-wide | Defines permissions across all namespaces or on cluster-level resources |
| RoleBinding | Namespace | Assigns a Role or ClusterRole to subjects within one namespace |
| ClusterRoleBinding | Cluster-wide | Assigns a ClusterRole to subjects across the entire cluster |
Complete Role Example:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: development
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
Bound subjects can read Pods but not create, update, or delete them.
ClusterRole Example:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: node-reader
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list"]
Nodes are cluster-scoped—they don't live in a namespace. Only a ClusterRole can grant access to them.
RoleBinding Example:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods-binding
namespace: development
subjects:
- kind: ServiceAccount
name: cicd-pipeline
namespace: development
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
This RoleBinding connects the cicd-pipeline ServiceAccount to the pod-reader Role, granting it read-only Pod access in the development namespace. The subjects field accepts Users, Groups, or ServiceAccounts.
Key verbs: get, list, watch, create, update, patch, delete, impersonate, bind, escalate. Note escalate: controls whether a user can grant permissions they don't possess.
Default ClusterRoles:
| Role | Purpose |
|---|---|
cluster-admin |
Full control over every resource. The superuser role. |
admin |
Full control within a namespace, including RBAC inside it |
edit |
Read/write most namespace-scoped resources, no RBAC management |
view |
Read-only access to most namespace-scoped resources |
A powerful pattern: bind ClusterRoles with a RoleBinding to scope them to one namespace. The ClusterRole defines permissions; the RoleBinding determines where they apply.
Visual Description: RBAC Resource Relationships
6.1.4 RBAC Best Practices
Avoid ClusterRole Unless Necessary. If a CI/CD pipeline only needs Deployments in dev, bind a Role to its ServiceAccount. Every unnecessary ClusterRole expands your blast radius.
Namespace-Scoped Roles for Teams. Give each team a namespace with a RoleBinding to the admin ClusterRole.
Audit Regularly:
# Check if the current user can create pods
kubectl auth can-i create pods
# Check if a specific ServiceAccount can delete secrets in a namespace
kubectl auth can-i delete secrets \
--as=system:serviceaccount:development:cicd-pipeline \
-n development
# List ALL permissions for a ServiceAccount
kubectl auth can-i --list \
--as=system:serviceaccount:development:cicd-pipeline \
-n development
Avoid Wildcard Permissions. Never use verbs: ["*"] or resources: ["*"] in production. Be explicit. Wildcards violate least privilege and make auditing nearly impossible.
🤔 TRY BEFORE YOU SEE
A developer needs to deploy to the staging namespace: create/update/delete Deployments and Services, read Pod logs. They must NOT modify Secrets, RBAC, or access other namespaces.
Design the RBAC objects yourself. How many Roles? What verbs? What binding?
Reveal: One Role with two rules (Deployments/Services: create/update/patch/delete; Pods: get/list; Pod logs: get), plus one RoleBinding. No ClusterRole needed—everything is namespace-scoped.
🛑 PAUSE & RECALL — 2 minutes
- What is the difference between a Role and a ClusterRole?
- Can a RoleBinding reference a ClusterRole? What does that mean in practice?
- What is the default RBAC behavior when no permission matches—allow or deny?
Rate your confidence (0-4).
6.1.5 GKE Security Integration
GKE Note: GKE integrates Kubernetes RBAC with Google Cloud IAM in a layered model. GKE operates two independent authorization layers: Cloud IAM controls who can access the GKE API (get-credentials, console access), and Kubernetes RBAC controls what users can do inside the cluster. Both must grant permission.
Common GKE IAM roles:
roles/container.admin: Full cluster administrationroles/container.clusterAdmin: Manage clusters but not K8s objectsroles/container.developer: Standard developer accessroles/container.viewer: Read-only access
Workload Identity. GKE's most powerful Pod-to-GCP authentication feature. Without it, a Pod accessing Cloud Storage would need a downloaded service account key—a static credential that could leak. With Workload Identity, a Kubernetes ServiceAccount maps to a GCP IAM service account, and the Pod receives a short-lived OAuth2 token automatically.
Visual Description: Workload Identity Flow
Identity-Aware Proxy (IAP). Adds an authentication layer in front of GKE workloads. Routes traffic through IAP to enforce Google Identity authentication—only authenticated users reach your applications.
VPC Service Controls. Creates security perimeters preventing data exfiltration from authorized GCP projects and regions. Even compromised credentials cannot transfer data outside the perimeter.
Lab: LAB-6.1 — RBAC in Practice (60 min)
Create a ServiceAccount, grant it limited permissions, verify they work, attempt unauthorized actions (and observe failures), and explore Workload Identity.
Part 1: Create Namespace and ServiceAccount
kubectl create namespace rbac-lab
kubectl create serviceaccount pod-reader-sa -n rbac-lab
Part 2: Create a Role
# pod-reader-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: rbac-lab
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "list", "watch"]
kubectl apply -f pod-reader-role.yaml
Part 3: Create a RoleBinding
# pod-reader-binding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: pod-reader-binding
namespace: rbac-lab
subjects:
- kind: ServiceAccount
name: pod-reader-sa
namespace: rbac-lab
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
kubectl apply -f pod-reader-binding.yaml
Part 4: Verify Authorized Access Works
# List pods (should succeed)
kubectl auth can-i list pods \
--as=system:serviceaccount:rbac-lab:pod-reader-sa \
-n rbac-lab
# Expected: yes
# Get a specific pod (should succeed)
kubectl auth can-i get pods \
--as=system:serviceaccount:rbac-lab:pod-reader-sa \
-n rbac-lab
# Expected: yes
Part 5: Attempt Unauthorized Actions (Expect Failure)
Each of these should fail. Observe the denials carefully—understanding what denial looks like is as important as understanding access.
# CREATE a pod (should fail — no create permission)
kubectl auth can-i create pods \
--as=system:serviceaccount:rbac-lab:pod-reader-sa \
-n rbac-lab
# Expected: no
# DELETE a pod (should fail — no delete permission)
kubectl auth can-i delete pods \
--as=system:serviceaccount:rbac-lab:pod-reader-sa \
-n rbac-lab
# Expected: no
# List pods in a DIFFERENT namespace (should fail — Role is namespace-scoped)
kubectl auth can-i list pods \
--as=system:serviceaccount:rbac-lab:pod-reader-sa \
-n default
# Expected: no
Part 6: List All Permissions
kubectl auth can-i --list \
--as=system:serviceaccount:rbac-lab:pod-reader-sa \
-n rbac-lab
Notice Pods show [get list watch] while everything else shows [].
Part 7: Configure Workload Identity (GKE)
GKE Note: Requires a GKE cluster with Workload Identity enabled.
# Create GCP service account
gcloud iam service-accounts create gke-lab-sa \
--display-name="GKE Lab Workload Identity"
# Allow K8s SA to impersonate GCP SA
gcloud iam service-accounts add-iam-policy-binding \
--role roles/iam.workloadIdentityUser \
--member "serviceAccount:PROJECT_ID.svc.id.goog[rbac-lab/pod-reader-sa]" \
gke-lab-sa@PROJECT_ID.iam.gserviceaccount.com
# Annotate the K8s ServiceAccount
kubectl annotate serviceaccount pod-reader-sa \
--namespace rbac-lab \
iam.gke.io/gcp-service-account=gke-lab-sa@PROJECT_ID.iam.gserviceaccount.com
Cleanup
kubectl delete namespace rbac-lab
Chapter Summary
This chapter covered Kubernetes security foundations. Every API request passes through three gates: Authentication, Authorization, and Admission Control. We explored the four RBAC resources and how they implement least privilege. You saw how GKE layers Cloud IAM on Kubernetes RBAC and how Workload Identity enables secure Pod-to-GCP authentication. The lab provided hands-on RBAC experience including permission verification and authorization failures.
📇 KEY CONCEPT CARDS
- Q: What are the three A's of Kubernetes security?
A: Authentication (who are you?), Authorization (what can you do?), Admission Control (are you following the rules?). Requests flow through in that order.
- Q: Role vs. ClusterRole?
A: A Role is namespace-scoped (permissions within one namespace). A ClusterRole is cluster-scoped (permissions on cluster-level resources or across all namespaces).
- Q: Default RBAC decision when no permission matches?
A: Default deny. If no Role or ClusterRole grants the permission, the request is rejected with 403 Forbidden.
- Q: What is GKE Workload Identity?
A: It maps a Kubernetes ServiceAccount to a GCP IAM service account, providing Pods with short-lived OAuth2 tokens instead of static credentials.