1. What Problem Kubernetes Solves
When we run applications in containers, we need to handle:
| Task | Problem | Example |
|---|---|---|
| Running many containers | Who will start them? Restart them if they die? |
docker run many times (manual) |
| Scaling up/down | What if traffic increases 10x? | Need auto-scaling |
| Load Balancing | How to route traffic across containers? | Need a load balancer |
| Updates with zero downtime | How to release new versions safely? | Need rolling updates |
| Manage containers across many servers | Need centralized control | Need orchestration |
Kubernetes is an Orchestrator.
It automatically manages containers across multiple servers.
Kubernetes = Robot Manager for your Docker containers.
2. Kubernetes Architecture (Simple)
+---------------------------------------------------+
| CLUSTER |
| |
| +--------------------+ +--------------------+ |
| | WORKER NODE #1 | | WORKER NODE #2 | |
| | | | | |
| | PODs (containers) | | PODs (containers) | |
| +--------------------+ +--------------------+ |
| |
| +--------------------+ |
| | MASTER/CONTROL | |
| | (brain of cluster)| -> API Server, Scheduler |
| +--------------------+ |
+---------------------------------------------------+
Key Terms (Very Important)
| Term | Meaning | Think of it as |
|---|---|---|
| Cluster | Whole Kubernetes environment | Company |
| Node | Machine (VM/EC2/Server) | Employee |
| Pod | Smallest unit; runs container(s) | Desk |
| Deployment | Ensures how many Pods must run | Manager giving orders |
| Service | Exposes your application for access | Door/phone number to reach the app |
3. Install Kubernetes Locally (Minikube)
Since you already use Docker Desktop → Kubernetes is likely included.
Step 1: Enable Kubernetes in Docker Desktop
Docker Desktop → Settings → Kubernetes → Enable → Apply → Wait.
Verify installation:
kubectl version --client
kubectl get nodes
You should see:
NAME STATUS ROLES AGE VERSION
docker-desktop Ready master ...
If not using Docker Desktop → install Minikube:
brew install minikube
minikube start
kubectl get nodes
4. First Hands-on Kubernetes Commands
See the cluster nodes
kubectl get nodes
Deploy a test application
kubectl create deployment myapp --image=nginx
Check pods
kubectl get pods
Expose the application
kubectl expose deployment myapp --port=80 --type=NodePort
Get service info
kubectl get svc
Access application (Minikube):
minikube service myapp
5. Scaling Your App (Zero Downtime)
kubectl scale deployment myapp --replicas=5
kubectl get pods
This runs 5 nginx containers automatically.
6. Deploy Using YAML (DevOps Way)
Create a file: deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
replicas: 3
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: nginx
ports:
- containerPort: 80
Apply:
kubectl apply -f deployment.yaml
kubectl get pods
7. Update Container Version (Rolling Update)
kubectl set image deployment/myapp myapp=nginx:latest
Check rollout status:
kubectl rollout status deployment/myapp
Rollback:
kubectl rollout undo deployment/myapp
8. Delete Apps
kubectl delete deployment myapp
kubectl delete svc myapp
9. Summary (Core Concepts to Remember)
| Component | Purpose |
|---|---|
| Pod | Runs containers |
| Node | Server that runs Pods |
| Deployment | Manages scaling + updates |
| Service | Exposes apps |
| kubectl | Kubernetes command-line |
Next Step You Should Learn (We will do next):
- Namespaces
- Ingress
- ConfigMap & Secrets
- Persistent Volumes
- Helm
- OPA Gatekeeper (Your goal)
PROJECT: Secure Kubernetes with OPA Gatekeeper
Goal:
Deploy a sample application to Kubernetes and enforce security policies using OPA Gatekeeper so users cannot deploy insecure workloads.
1. What is OPA (Open Policy Agent)? (Beginner Explanation)
| Concept | Meaning | Example |
|---|---|---|
| OPA | Policy Engine | Like a security officer checking rules |
| Rego | Policy Language (used by OPA) | The rules themselves |
| Gatekeeper | OPA plugin for Kubernetes | Enforces policies on Kubernetes API |
In simple words:
Kubernetes lets anyone deploy anything unless we restrict it.
OPA acts like a security guard at the API level:
kubectl apply manifest.yaml
|
v
+-------------------+
| OPA Gatekeeper | <-- Checks rules
+-------------------+
|
Allow or Deny
2. Common Real-World Policies OPA Enforces
| Policy | Why |
|---|---|
| No containers run as root | Security Best Practice |
| Each pod must have limits/requests | Prevent cluster resource abuse |
| Only approved container registries allowed | Prevent malware images |
| Block privileged containers | Prevent host takeover |
We will apply these.
3. Setup Kubernetes Cluster (Local Minikube or Docker Desktop)
Verify cluster:
kubectl get nodes
If using Minikube:
minikube start
4. Install OPA Gatekeeper
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/master/deploy/gatekeeper.yaml
Wait for pods:
kubectl get pods -n gatekeeper-system
Expected:
NAME READY STATUS AGE
gatekeeper-controller-manager-xxxx 1/1 Running 1m
5. Deploy a Sample Application (Without Policy Yet)
kubectl create deployment insecure-app --image=nginx
kubectl expose deployment insecure-app --port=80 --type=NodePort
kubectl get pods
This will work normally.
6. Apply a Security Policy (Block Running as Root)
OPA policies are created in two parts:
| File | Purpose |
|---|---|
| ConstraintTemplate | Defines the rule logic (Rego) |
| Constraint | Applies rule to the cluster |
Step 6.1 Create the ConstraintTemplate
Create file: disallow-root-template.yaml
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: k8sdisallowroot
spec:
crd:
spec:
names:
kind: K8sDisallowRoot
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8sdisallowroot
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
container.securityContext.runAsUser == 0
msg := "Running containers as root is not allowed"
}
Apply it:
kubectl apply -f disallow-root-template.yaml
Step 6.2 Create the Constraint
Create file: disallow-root-constraint.yaml
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sDisallowRoot
metadata:
name: no-root-users
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
Apply it:
kubectl apply -f disallow-root-constraint.yaml
7. Test the Policy (Deploy a Root Pod) — It Should Fail
kubectl run test-root --image=nginx --command -- sleep 3600
Expected Output:
Error from server (Forbidden): admission webhook "validation.gatekeeper.sh" denied the request: Running containers as root is not allowed
✅ OPA is working. Policy is enforced.
8. Deploy a Secure Pod (Non-root) — It Should Work
Create secure-pod.yaml:
apiVersion: v1
kind: Pod
metadata:
name: secure-pod
spec:
containers:
- name: nginx
image: nginx
securityContext:
runAsUser: 1000
Apply:
kubectl apply -f secure-pod.yaml
kubectl get pods
✅ This pod runs successfully — Policy allows it.
9. What We Have Built
| Component | Result |
|---|---|
| Kubernetes App | Running |
| OPA Gatekeeper | Installed |
| Policy | Blocks root containers |
| Enforcement | Verified (blocked insecure pod) |
This is real production knowledge.
10. Real DevOps Interview Explanation
“We use OPA Gatekeeper in Kubernetes to enforce governance and security policies at admission time. Policies are written in Rego and applied using ConstraintTemplates and Constraints. For example, we enforce that no container runs as root and that resource limits are mandatory. This prevents insecure workloads before they are deployed into the cluster.”
We will add 3 more critical security policies:
| Policy | Purpose | Real Impact |
|---|---|---|
| Require Resource Limits | Prevent cluster from crashing due to a single bad container | Protects cluster stability |
| Disallow Privileged Pods | Prevent pods from gaining host-level access | Security compliance |
| Allow Images Only from Approved Registry | Prevent malware or unknown container images | Supply chain protection |
1) Policy: Require CPU/Memory Limits
Pods must include resources.limits.
Step 1: Create Template
require-limits-template.yaml:
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: k8srequirelimits
spec:
crd:
spec:
names:
kind: K8sRequireLimits
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8srequirelimits
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
not container.resources.limits
msg := "Container must have CPU and memory limits set"
}
Apply:
kubectl apply -f require-limits-template.yaml
Step 2: Create Constraint
require-limits-constraint.yaml:
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequireLimits
metadata:
name: enforce-resource-limits
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
Apply:
kubectl apply -f require-limits-constraint.yaml
Test (Should Fail):
kubectl run no-limits --image=nginx
Test (Correct Pod):
apiVersion: v1
kind: Pod
metadata:
name: with-limits
spec:
containers:
- name: nginx
image: nginx
resources:
limits:
cpu: "500m"
memory: "256Mi"
2) Policy: Disallow Privileged Pods
Template
no-privileged-template.yaml:
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: k8sdisallowprivileged
spec:
crd:
spec:
names:
kind: K8sDisallowPrivileged
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8sdisallowprivileged
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
container.securityContext.privileged == true
msg := "Privileged containers are not allowed"
}
Apply:
kubectl apply -f no-privileged-template.yaml
Constraint
no-privileged-constraint.yaml:
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sDisallowPrivileged
metadata:
name: prevent-privileged-containers
spec:
match:
kinds:
- apiGroups: [""]
kinds: ["Pod"]
Apply:
kubectl apply -f no-privileged-constraint.yaml
Test (Should Fail):
apiVersion: v1
kind: Pod
metadata:
name: privileged-pod
spec:
containers:
- name: alpine
image: alpine
securityContext:
privileged: true
3) Policy: Only Allow Containers from Approved Registry
Your company typically uses:
- AWS ECR →
*.amazonaws.com - GCR →
gcr.io/* - DockerHub private
mycompany/*
Template
allowed-registries-template.yaml:
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: k8sallowedregistries
spec:
crd:
spec:
names:
kind: K8sAllowedRegistries
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package k8sallowedregistries
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
approved := input.parameters.allowedRegistries[_]
not startswith(container.image, approved)
msg := sprintf("Container image '%v' is not from an approved registry", [container.image])
}
Apply:
kubectl apply -f allowed-registries-template.yaml
Constraint
allowed-registries-constraint.yaml:
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sAllowedRegistries
metadata:
name: only-approved-registries
spec:
parameters:
allowedRegistries:
- "gcr.io"
- "docker.io/library"
- "registry.k8s.io"
Apply:
kubectl apply -f allowed-registries-constraint.yaml
Test (Should Fail):
kubectl run hacked --image=badimage.com/virus
✅ Rejected.
✅ What You Have Now (This is Enterprise-Ready)
| Policy | Status |
|---|---|
| No running as root | ✅ Enforced |
| Must define memory/CPU limits | ✅ Enforced |
| No privileged pods | ✅ Enforced |
| Only approved registry images | ✅ Enforced |
You now have security and governance enforced exactly like:
- Google Cloud SRE teams
- AWS Well-Architected security controls
- Bank / fintech regulated clusters
✅ Real Interview Answer
“We use OPA Gatekeeper to enforce Kubernetes security best practices. We define policies as ConstraintTemplates in Rego, and apply them as Constraints to namespaces or cluster-wide. Our policies prevent privileged containers, require resource limits, enforce non-root execution, and restrict images to approved registries. This ensures strong governance, reduces attack surface, and prevents misconfiguration before deployment.”
Top comments (0)