Kubernetes Security Fundamentals (22%)¶
This domain covers core Kubernetes security features and configurations.
Pod Security¶
Security Context¶
Define security settings at the Pod or container level:
apiVersion: v1
kind: Pod
metadata:
name: secure-pod
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: nginx:1.21
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
Security Context Fields¶
| Field | Level | Description |
|---|---|---|
runAsUser | Pod/Container | UID to run as |
runAsGroup | Pod/Container | GID to run as |
runAsNonRoot | Pod/Container | Must run as non-root |
fsGroup | Pod | Group for volumes |
allowPrivilegeEscalation | Container | Prevent privilege escalation |
readOnlyRootFilesystem | Container | Read-only root filesystem |
capabilities | Container | Linux capabilities |
seccompProfile | Pod/Container | Seccomp profile |
seLinuxOptions | Pod/Container | SELinux context |
Pod Security Standards¶
Three policy levels:
| Level | Description |
|---|---|
| Privileged | Unrestricted, allows known privilege escalations |
| Baseline | Minimally restrictive, prevents known privilege escalations |
| Restricted | Heavily restricted, follows security best practices |
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/audit: restricted
pod-security.kubernetes.io/warn: restricted
Network Policies¶
Default Behavior¶
By default, all pods can communicate with all other pods.
Deny All Ingress¶
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-ingress
namespace: default
spec:
podSelector: {}
policyTypes:
- Ingress
Allow Specific Ingress¶
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend
namespace: default
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
Egress Policy¶
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns-only
namespace: default
spec:
podSelector:
matchLabels:
app: restricted
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53
Network Policy Selectors¶
| Selector | Description |
|---|---|
podSelector | Select pods by labels |
namespaceSelector | Select namespaces by labels |
ipBlock | Select by IP CIDR range |
RBAC Deep Dive¶
Role vs ClusterRole¶
| Type | Scope | Use Case |
|---|---|---|
| Role | Namespace | Namespace-specific permissions |
| ClusterRole | Cluster-wide | Cluster resources or aggregation |
RoleBinding vs ClusterRoleBinding¶
| Type | Scope | Can Reference |
|---|---|---|
| RoleBinding | Namespace | Role or ClusterRole |
| ClusterRoleBinding | Cluster-wide | ClusterRole only |
RBAC Best Practices¶
# Least privilege Role example
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: app-namespace
name: app-deployer
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
resourceNames: ["my-app"] # Specific resource
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list"]
Checking Permissions¶
# Check if you can perform an action
kubectl auth can-i create pods
kubectl auth can-i create pods --as=system:serviceaccount:default:my-sa
kubectl auth can-i --list --namespace=default
Service Accounts¶
Default Service Account¶
Every namespace has a default service account.
apiVersion: v1
kind: ServiceAccount
metadata:
name: my-service-account
namespace: default
automountServiceAccountToken: false
Using Service Accounts¶
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
serviceAccountName: my-service-account
automountServiceAccountToken: false # Disable if not needed
containers:
- name: app
image: my-app:v1
Token Projection¶
apiVersion: v1
kind: Pod
metadata:
name: pod-with-projected-token
spec:
containers:
- name: app
image: my-app:v1
volumeMounts:
- name: token
mountPath: /var/run/secrets/tokens
volumes:
- name: token
projected:
sources:
- serviceAccountToken:
path: token
expirationSeconds: 3600
audience: my-audience
Resource Quotas and Limits¶
LimitRange¶
apiVersion: v1
kind: LimitRange
metadata:
name: resource-limits
namespace: default
spec:
limits:
- type: Container
default:
cpu: "500m"
memory: "256Mi"
defaultRequest:
cpu: "100m"
memory: "128Mi"
max:
cpu: "2"
memory: "1Gi"
min:
cpu: "50m"
memory: "64Mi"
ResourceQuota¶
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-quota
namespace: default
spec:
hard:
requests.cpu: "4"
requests.memory: "8Gi"
limits.cpu: "8"
limits.memory: "16Gi"
pods: "10"
secrets: "10"
configmaps: "10"
Image Security¶
Image Pull Policies¶
| Policy | Behavior |
|---|---|
Always | Always pull image |
IfNotPresent | Pull only if not cached |
Never | Never pull, use cached only |
Private Registry Authentication¶
apiVersion: v1
kind: Secret
metadata:
name: regcred
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: <base64-encoded-docker-config>
---
apiVersion: v1
kind: Pod
metadata:
name: private-pod
spec:
containers:
- name: app
image: private-registry.io/my-app:v1
imagePullSecrets:
- name: regcred
Image Digest¶
Use image digests for immutability:
Key Concepts to Remember¶
- Security contexts - Define at Pod and container level
- Pod Security Standards - Privileged, Baseline, Restricted
- Network Policies - Default allow, explicit deny
- RBAC - Roles, ClusterRoles, Bindings
- Service Accounts - Disable auto-mount when not needed
Practice Questions¶
- What is the difference between
runAsUserandrunAsNonRoot? - What happens if no Network Policy exists in a namespace?
- Can a RoleBinding reference a ClusterRole?
- How do you prevent a container from escalating privileges?
- What are the three Pod Security Standards levels?
← Previous: Cluster Component Security | Back to KCSA Overview | Next: Kubernetes Threat Model →