SECURITY / Kubernetes · 40 min

Put boundaries around Kubernetes workloads

Review access, introduce Pod Security carefully, and test network isolation in a dedicated namespace.

Before you start

Environment: A disposable Linux Kubernetes cluster, kubectl access, Pod Security Admission enabled, and a network plugin that enforces NetworkPolicy. Use the documentation matching your cluster version.

Confirm the current context. Create a new, empty namespace named opsrung-security-lab only if it does not already exist. These examples must not target default, kube-system, or a production namespace.

Commands run in your own terminal. This website cannot inspect or secure your environment.

Inspect first · then create a dedicated lab namespace

1. Review the identity and namespace first

The same kubectl command can affect very different environments depending on the selected context.

Bash · review before running
kubectl config current-context
kubectl version
kubectl get namespace opsrung-security-lab
# Continue only if the previous result is NotFound, in your disposable cluster.
kubectl create namespace opsrung-security-lab
kubectl auth can-i --list -n opsrung-security-lab

What to check

You recognize the cluster and identity. Review whether your account can read secrets or alter workloads. Your administrator identity is not an appropriate default for application automation.

Try it deliberately

Design a namespace-scoped Role for a specific task, grant only needed resources and verbs, and test both allowed and forbidden actions using the actual test identity. Avoid wildcard verbs and cluster-admin for routine delivery. Never print secret values as proof.

Recovery & cleanup

These access checks do not change RBAC. Namespace creation is the only change here; keep a record that it belongs to this exercise.

Official guidance: Kubernetes security checklist ↗

Change · lab namespace labels

2. Warn before enforcing Pod Security

A new admission rule can stop future rollouts even when existing Pods keep running.

Bash · review before running
kubectl label namespace opsrung-security-lab \
  pod-security.kubernetes.io/warn=restricted \
  pod-security.kubernetes.io/audit=restricted
kubectl label --dry-run=server namespace opsrung-security-lab \
  pod-security.kubernetes.io/enforce=restricted

What to check

The warning/audit labels apply. The enforce dry run evaluates the change without saving it. An empty namespace proves little: validate representative workload manifests and fix warnings before enforcing.

Try it deliberately

Use kubectl apply --dry-run=server -f workload.yaml -n opsrung-security-lab for your reviewed manifest. Test warn/audit with an intentionally noncompliant lab Pod, then add enforce=restricted only when the valid Pod passes and the invalid Pod is rejected. Pin the policy version to your reviewed cluster minor for repeatable production rollout.

Recovery & cleanup

In this new lab namespace, remove only the labels you added: kubectl label ns opsrung-security-lab pod-security.kubernetes.io/warn- pod-security.kubernetes.io/audit-. If you later added enforce, remove that label with pod-security.kubernetes.io/enforce-.

Official guidance: Namespace Pod Security labels ↗

Manifest fragment · merge into a reviewed Linux Pod spec

3. Set the workload security context

Admission validates a policy; the workload must also declare the runtime restrictions it needs.

Example configuration · review before applying
spec:
  automountServiceAccountToken: false
  securityContext:
    runAsNonRoot: true
    runAsUser: 10001
    seccompProfile:
      type: RuntimeDefault
  containers:
    - name: app
      image: YOUR_REVIEWED_IMAGE_BY_DIGEST
      securityContext:
        allowPrivilegeEscalation: false
        readOnlyRootFilesystem: true
        capabilities:
          drop: ["ALL"]

What to check

This is a fragment, not a complete deployable manifest. Replace the image with one that supports UID 10001, include required ports/resources/volumes, then server-dry-run and test its real startup and health path.

Try it deliberately

Use a dedicated ServiceAccount if the app needs API access and scope its RBAC. A read-only root filesystem may need an emptyDir for scratch space. Avoid privileged mode, host namespaces, and hostPath mounts unless their risk has been explicitly reviewed.

Recovery & cleanup

Keep the last working workload manifest in version control. If rollout health fails, restore that version; a dry run checks admission and schema, not application behavior.

Official guidance: Kubernetes Pod Security Standards ↗

Change · save as lab-deny-ingress.yaml in the empty lab namespace

4. Test blocked traffic, not just policy creation

A NetworkPolicy object can exist without blocking traffic when the network plugin does not implement it.

Example configuration · review before applying
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: lab-deny-ingress
  namespace: opsrung-security-lab
spec:
  podSelector: {}
  policyTypes: [Ingress]
Verify · run after the reviewed change
kubectl apply --dry-run=server -f lab-deny-ingress.yaml
kubectl apply -f lab-deny-ingress.yaml
kubectl describe networkpolicy lab-deny-ingress -n opsrung-security-lab

What to check

With a test server and separate client Pod, a connection that worked before should time out after policy enforcement. This ingress-only example does not restrict outbound traffic; it leaves egress and DNS unchanged.

Try it deliberately

Before trying this on workloads, confirm the plugin supports enforcement and record a baseline TCP connection. Add a narrow allow rule for an intended client and test allowed and denied sources again. Inspect other policies: their allow rules combine. Plan egress/DNS controls separately.

Recovery & cleanup

Remove only this policy with kubectl delete networkpolicy lab-deny-ingress -n opsrung-security-lab. At the end, delete the namespace only after confirming it contains exclusively your disposable lab resources; namespace deletion destroys everything in it.

Official guidance: Kubernetes NetworkPolicy behavior ↗

Reviewed 31 October 2026. Adapt to your installed versions and environment; these guides cover selected controls, not a compliance certification.