ICA — Istio Certified Associate
Watch What the Mesh Actually Enforces
This lab runs on a real Istio
k3s + Istio are actually running inside the VM. Sidecars are really injected, mTLS is really enforced, and a VirtualService really redirects traffic.
The other labs of the ICA course run on a fake cluster with only CRDs loaded. There,
kubectl apply just passes and nothing happens.
It takes 2–3 minutes to come up the first time.
Goal
You confirm where the sidecar is injected, and tell apart by response code what mTLS and authorization policy actually block.
Why it matters
The value of a service mesh is not "we wrote the configuration" but "that configuration is enforced." But the trap of this topic is that a state where it is not enforced looks normal.
The most common one is missing sidecar injection. A Pod created before you attached
the label to the namespace has no sidecar. The Pod is Running and the service responds.
But because traffic does not pass through the mesh, neither mTLS, nor authorization policy, nor routing
nor anything else is applied. It becomes a state in which you have written all the security policies and nothing
is being protected.
And these days the way of checking itself has changed. Istio now uses Kubernetes
native sidecars. istio-proxy goes into spec.initContainers rather than spec.containers
(with restartPolicy: Always). So the habit of checking with
kubectl get pod -o jsonpath='{.spec.containers[*].name}'
now says there is no sidecar even when there is one.
Steps
- Check
istioctl versionand the injection label, and save them to/root/ica/install.txt. - Create a
webPod (nginx), check whereistio-proxywent, and save it to/root/ica/sidecar.txt. You must print bothspec.containersandspec.initContainers. - Make mTLS STRICT with a
strictPeerAuthentication, send requests from inside and outside the mesh respectively, and save them to/root/ica/mtls.txt. - With a
web-vsVirtualService, make only the/teapotpath return 418, and save the result to/root/ica/routing.txt. - With a
web-authzAuthorizationPolicy, allow only a specific service account, test the allowed side and the non-allowed side, and save it to/root/ica/authz.txt. - Check the workload's SPIFFE identity and save it to
/root/ica/identity.txt. - Put a workload outside the mesh (the
nomeshnamespace), and write in/root/ica/outside.txtwhy it is dangerous to switch to STRICT all at once. - In
/root/ica/report.md, write three lines,sidecar_location=,authz_denied_code=, andmesh_identity=, along with an explanation.
Notes
- Only Pods created after you attach the label are injected. Pods that already existed need
kubectl rollout restartor recreation. - When you
kubectl execinto a Pod that has a sidecar, it is safer to give-c <앱컨테이너>(the placeholder is the app container). If you do not, it depends on which container is the default. - Istio's authorization denial is a 403 (
RBAC: access denied). When mTLS is not satisfied, the connection itself is reset and there is no response code (curl shows000or exit 56). Telling these two apart is the heart of diagnosis. - A SPIFFE identity has the format
spiffe://cluster.local/ns/<네임스페이스>/sa/<서비스어카운트>(the placeholders are the namespace and the service account). You can view the certificate withistioctl proxy-config secret <파드>(the placeholder is the Pod). - Common mistake 1: the order of the VirtualService's
httplist. The first matching rule from the top is used, so if you put a catch-all rule on top, the rules below it never match. - Common mistake 2: leaving Pods created before attaching the label as they are and saying "the policy doesn't take effect." If there is no sidecar, nothing is applied.
What is running
Check istioctl version and the injection label, and save them to /root/ica/install.txt.
Use istioctl version to view the control plane and data plane versions together. And check the istio-injection label of the default namespace.
Where does the sidecar go
Create a web Pod (nginx), check where istio-proxy went, and save it to /root/ica/sidecar.txt. You must print both spec.containers and spec.initContainers.
Print both .spec.containers and .spec.initContainers. These days Istio uses native sidecars.
STRICT really blocks
Make mTLS STRICT with a strict PeerAuthentication, send requests from inside and outside the mesh respectively, and save them to /root/ica/mtls.txt.
Send requests from inside the mesh (a Pod with a sidecar) and from outside the mesh (a namespace without a sidecar). From outside, not even a response code comes back.
Rule order changes the result
With a web-vs VirtualService, make only the /teapot path return 418, and save the result to /root/ica/routing.txt.
The http list uses the first match from the top. Put the specific rule on top and the catch-all rule below.
Allow by identity
With a web-authz AuthorizationPolicy, allow only a specific service account, test the allowed side and the non-allowed side, and save it to /root/ica/authz.txt.
Write a service account in SPIFFE format in principals. A denial is a 403.
Where is the identity held
Check the workload's SPIFFE identity and save it to /root/ica/identity.txt.
View the certificate the sidecar holds with istioctl proxy-config secret <파드> (the placeholder is the Pod). The SPIFFE URI is in the SAN.
Why you must not switch to STRICT all at once
Put a workload outside the mesh (the nomesh namespace), and write in /root/ica/outside.txt why it is dangerous to switch to STRICT all at once.
If even one workload outside the mesh remains, STRICT cuts that communication immediately. Write why you split the steps with PERMISSIVE.
What you learned
In /root/ica/report.md, write three lines, sidecar_location=, authz_denied_code=, and mesh_identity=, along with an explanation.
Along with the three lines sidecar_location=, authz_denied_code=, and mesh_identity=, write how you tell the two kinds of "it doesn't work" apart.