Home › CKS › Topics › Practice tasks › Service Mesh Security
CKS · Cluster Hardening

Enable Istio Sidecar Injection and Enforce Strict mTLS

Istio is installed in the cluster. Deployment target-app runs in namespace app-ns, but the namespace was never enabled for sidecar injection, so its pods are not in the mesh.

Check live lab access → All CKS tasks

Live lab access

This task description is public. Live practice requires full access unless this is the selected free weekly task. AI Lab Coach is available in single-task labs, including the free weekly task. See this week's free task.

Create an account to continue →

Read this week's free task →

On a phone? Read the task and create your account here, then sign in on a desktop or laptop for the terminal lab. Nothing starts until you choose Start.

The task

Task

Istio is installed in the cluster. Deployment target-app runs in namespace app-ns, but the namespace was never enabled for sidecar injection, so its pods are not in the mesh.

Requirements

  1. Enable Istio sidecar injection on namespace app-ns (the namespace label documented on Istio's sidecar-injection page)
  2. Roll the target-app workload so its pods are recreated and would be admitted with the sidecar injected - existing pods are never injected retroactively
  3. Create a PeerAuthentication named default in namespace app-ns that enforces STRICT mutual TLS for the whole namespace

Note

This lab ships the Istio security CRDs without the istiod webhook, so no istio-proxy container is literally added to the pods - do not wait for 2/2. Grading checks the work you do: the namespace label, the re-roll, and the policy.

Original Prepium guide · Written for Kubernetes v1.35 and checked against the official documentation on 6 October 2026. Use a disposable practice cluster. The commands assume a working Istio control plane with its injection webhook; check the Istio docs for your installed release.

Put workloads in the Istio mesh and require mutual TLS

Istio adds an istio-proxy sidecar to Pods through a mutating admission webhook, so injection only happens when a Pod is created. Once workloads have proxies, a PeerAuthentication policy decides whether they still accept plaintext or insist on mutual TLS. The classic trap is a correct namespace label whose Pods were never recreated.

namespace label ──→ webhook mutates NEW Pods ──→ app + istio-proxy (2/2)
PeerAuthentication: workload selector  >  namespace-wide  >  mesh-wide (root namespace)

1. Inspect what is in the mesh today

kubectl create namespace prepium-tutorial
kubectl -n prepium-tutorial create deployment ledger --image=nginx:1.27-alpine --port=80
kubectl -n prepium-tutorial expose deployment ledger --port=80
kubectl get mutatingwebhookconfigurations | grep -i istio
kubectl get namespace -L istio-injection
kubectl -n prepium-tutorial get pod -l app=ledger -o jsonpath='{.items[*].spec.containers[*].name}'

The -L flag adds an ISTIO-INJECTION column. Pods outside the mesh show 1/1 under READY and list only the application container.

2. Enable injection, then recreate the Pods

kubectl label namespace prepium-tutorial istio-injection=enabled --overwrite
kubectl -n prepium-tutorial rollout restart deployment ledger
kubectl -n prepium-tutorial rollout status deployment ledger

The label alone changes nothing for Pods that already run: the webhook only sees create requests. A rollout restart creates replacement Pods through the normal Deployment rollout, and those pass through the webhook. Injected Pods report 2/2 and include istio-proxy in the container list. Labels are evaluated in a fixed way: if either istio-injection on the namespace or sidecar.istio.io/inject on the Pod says disabled, there is no injection, and istio-injection wins over istio.io/rev when both sit on one namespace.

3. Choose a mutual TLS mode and a scope

Modes: PERMISSIVE accepts both plaintext and mTLS (the migration setting), STRICT accepts only mTLS, DISABLE turns it off, and an unset mode inherits from the parent scope. Scope comes from where the policy lives and whether it has a selector. This example locks down just one workload:

apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
  name: ledger-only
  namespace: prepium-tutorial
spec:
  selector:
    matchLabels:
      app: ledger
  mtls:
    mode: STRICT

Remove the selector and the same object covers every workload in its namespace; put a selector-less policy in the root namespace (usually istio-system) and it covers the mesh. Istio applies the narrowest match per workload. Only one namespace-wide policy is honoured per namespace: if you create a second one, the newer one is ignored.

4. Verify with a client outside the mesh

kubectl create namespace prepium-outside
kubectl -n prepium-outside run probe --image=curlimages/curl:8.10.1 --command -- sleep 3600
kubectl -n prepium-outside exec probe -- \
  curl -s -o /dev/null -w "%{http_code}\n" http://ledger.prepium-tutorial/

Before the policy a plaintext client gets a normal HTTP code. Under STRICT, the Istio docs show this kind of request printing 000 with curl exit code 56, because the client cannot present a mesh certificate. An injected client in the mesh keeps working, since its sidecar upgrades the connection automatically.

Common mistakes

Example checkEvidence
Namespace opted inkubectl get namespace -L istio-injection shows enabled
Pods recreated after labellingPod AGE is newer than the label change; READY 2/2
Policy scope is what you meantspec.selector present or absent, policy namespace
mTLS enforcedPlaintext client fails, in-mesh client succeeds

Cleanup: kubectl delete namespace prepium-tutorial prepium-outside. References: Installing the sidecar, Istio security concepts, Authentication policy task. Next, try namespace isolation with NetworkPolicy or TLS on an Ingress.

Exam
CKS
Domain
Cluster Hardening
Grading
Programmatic · partial credit

What this tests

Restrict RBAC and service accounts, tighten API server flags, and keep the cluster patched. On the CKS exam, Cluster Hardening tasks are graded purely on what you build in the cluster - not multiple choice - so the only way to get faster is to do them on a real cluster against a clock.

Practice it for real

The public description lets you study the task before signing up. Full access includes this live lab; the selected Task of the Week is free with an account. You solve the task in a real terminal, hit validate, and a programmatic checker scores exactly what you got right and wrong (with partial credit). You can open the solution while practising, then retry and use the failed checks to improve your score.

Related CKS tasks