ICA — Istio Certified Associate
ICA Mock Exam A
This is ICA Mock Exam A. The time limit is 120 minutes, there are 17 tasks, and the passing line is 68%. Scoring is partial, so it is better to skip a task you get stuck on and come back to it later.
Because this is a mock exam, do not look at hints or answers; try to finish it all first. Not solving something because you ran out of time and not solving it because you did not know it are different problems, and you must distinguish the two to decide what to study next. Open them only after you have solved everything and graded.
The real exam environment
During the exam you can view istio.io/docs, istio.io/blog, and kubernetes.io/docs.
Searching inside the documentation site with istio.io/search/ is allowed, but you must not click external search
results. The k alias, bash completion, and istioctl
completion are already set up. You work by using ssh to the host specified for each task,
and nested ssh is not supported. Copying in the terminal is Ctrl+Shift+C,
and pasting is Ctrl+Shift+V.
This mock exam environment
You work directly in a single-user cluster inside the Pod (ssh is not needed). The kube-apiserver is real, so an incorrect manifest is actually rejected, but sidecars do not come up and traffic does not flow. Grading works by re-reading the configuration you left on the cluster.
Task 1 is the premise for most of the rest. Until the Istio resource kinds are registered,
kubectl apply will not accept a VirtualService. Finish it first.
1. Generate the Istio installation manifest for the default profile and save it to /root/ica/install/manifest.yaml.
Then pick out only the CustomResourceDefinition objects in that manifest and register them
in the cluster. Since the istiod Pod does not come up in this environment, all you need are the
API types.
2. Create three namespaces and attach the sidecar injection labels.
istio-injection=enabledonica-shopistio-injection=disabledonica-legacyistio.io/rev=1-24onica-rev. Do not leave anistio-injectionlabel on this namespace.
3. Reverse the namespace's decision at the Pod level. Both Deployments have
1 replica and the image nginx:1.27-alpine.
batch-runnerinica-shop: Pod template labelsidecar.istio.io/inject: "false"legacy-apiinica-legacy: Pod template labelsapp: legacy-apiandsidecar.istio.io/inject: "true"
4. In ica-shop, bring up the reviews service in three versions and define the subsets.
- Deployments
reviews-v1,reviews-v2, andreviews-v3, 1 replica each. The Pod labels areapp=reviewsandversion=v1/v2/v3. The image isnginx:1.27-alpine, and the container port is 9080. - Service
reviews: port 9080, port namehttp. Use onlyapp=reviewsas the selector. - DestinationRule
reviews:spec.hostisreviews.ica-shop.svc.cluster.local. Define subsetsv1,v2, andv3with their respectiveversionlabels, and settrafficPolicy.loadBalancer.simpletoLEAST_REQUEST.
5. Create a VirtualService reviews in ica-shop. The host is
reviews.ica-shop.svc.cluster.local, and with a single rule with no conditions, split
80 to subset v1 and 20 to subset v2.
6. Add two more rules in front of the VirtualService reviews from task 5 to make
three in all. The order is what is graded.
- If the header
end-useris exactlytester, subsetv3 - If the
uriprefix is/api/v2and at the same time the method isGET, subsetv2 - The weighted rule from task 5 remains as the last rule with no conditions
7. Attach resilience settings to the last (no-condition) rule of the same VirtualService reviews. The overall timeout is 2s, 3 retries, a per-try timeout of 500ms, and the retry
conditions are 5xx, reset, and connect-failure.
8. Add limits and outlier detection to the trafficPolicy of the DestinationRule reviews.
connectionPool.tcp.maxConnectionsis 100connectionPool.http.http1MaxPendingRequestsis 10connectionPool.http.maxRequestsPerConnectionis 1outlierDetectionisconsecutive5xxErrors5,interval10s,baseEjectionTime30s,maxEjectionPercent50
9. Set up ingress in ica-shop.
- Gateway
shop-gateway: the selector isistio: ingressgateway. Port 80 (namehttp, protocol HTTP) accepts the hostshop.example.comand redirects it to HTTPS. Port 443 (namehttps, protocol HTTPS) terminates the same host inSIMPLEmode, and the certificate Secret name isshop-cert. - VirtualService
shop-edge: hostshop.example.com, bound to the gatewayshop-gateway, and sends theuriprefix/reviewsto port 9080 ofreviews.ica-shop.svc.cluster.local.
10. Enforce mTLS mesh-wide but make only the outdated namespace an exception.
- Create the
istio-systemnamespace and put a PeerAuthenticationdefaultin it asSTRICT. Do not attach a selector. - In
ica-legacy, put a PeerAuthenticationdefaultasPERMISSIVE. Do not attach a selector here either.
11. Raise only the legacy-api workload in ica-legacy to STRICT, but make port 8080 an
exception. The PeerAuthentication name is legacy-api, the selector is
app: legacy-api, mtls.mode is STRICT, and 8080 in portLevelMtls is
DISABLE.
12. Create two authorization policies in ica-shop. Both have the selector
app: reviews.
reviews-allow:ALLOW. The source principal iscluster.local/ns/ica-shop/sa/productpage, and the allowed operation is the methodGETand the path/reviews*.reviews-deny-admin:DENY. It blocks the path/admin*.
13. Attach JWT verification to the app: reviews workload in ica-shop.
- RequestAuthentication
shop-jwt: the issuer ishttps://auth.shop.example.com, and the jwksUri ishttps://auth.shop.example.com/.well-known/jwks.json - AuthorizationPolicy
require-jwt:ALLOW. The requestPrincipals ishttps://auth.shop.example.com/*
14. A team said it would write to the ica-fix namespace and handed over only the VirtualService below. As it stands, istioctl analyze reports errors. Diagnose
what is missing and fill it in, and make istioctl analyze -n ica-fix report no Errors at all.
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: payments
namespace: ica-fix
spec:
hosts:
- payments.ica-fix.svc.cluster.local
http:
- route:
- destination:
host: payments.ica-fix.svc.cluster.local
subset: stable
The specification of what to fill in is this. The Deployment payments has the Pod labels
app=payments and version=v1, the Service payments has port 9090 with the port name
http, and the DestinationRule payments uses the same FQDN as above as its host and defines the subset
stable as version: v1. Do not leave resources unrelated to the task in this namespace. If any remain, analyze catches those too.
15. After applying the VirtualService below in the ica-triage namespace,
traffic always goes to stable even when the x-beta: true header is attached. Diagnose the cause and apply your fix.
Keep the two rules as they are.
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: checkout
namespace: ica-triage
spec:
hosts:
- checkout.ica-triage.svc.cluster.local
http:
- route:
- destination:
host: checkout.ica-triage.svc.cluster.local
subset: stable
- match:
- headers:
x-beta:
exact: "true"
route:
- destination:
host: checkout.ica-triage.svc.cluster.local
subset: beta
16. After putting in the policy below, the payments workload in ica-triage rejects every request.
Diagnose the cause and fix it so that only cluster.local/ns/ica-triage/sa/frontend accessing
/pay* with POST is allowed.
apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: payments-allow
namespace: ica-triage
spec:
selector:
matchLabels:
app: payments
action: ALLOW
rules: []
17. After putting the two resources below in ica-triage, every caller of orders
fails. Leave the server-side requirement as it is and fix the client side.
apiVersion: security.istio.io/v1
kind: PeerAuthentication
metadata:
name: default
namespace: ica-triage
spec:
mtls:
mode: STRICT
---
apiVersion: networking.istio.io/v1
kind: DestinationRule
metadata:
name: orders
namespace: ica-triage
spec:
host: orders.ica-triage.svc.cluster.local
trafficPolicy:
tls:
mode: DISABLE
For tasks 15 to 17, there is no need to create workloads in ica-triage. What you must fix
is the configuration.
Registering the mesh API types in the cluster
istioctl manifest generate carries the charts inside the binary and works without the internet. Its result even includes istiod and the services, but all you need in this environment is the CRDs, so filter them out by kind. When applying, use --server-side. Istio CRDs have large annotations and exceed the last-applied-configuration limit (262144 bytes) of a regular apply.
Attaching sidecar injection labels per namespace
If a revision label and the istio-injection label are on a namespace together, istio-injection wins. So if you do not remove the old label while moving to a revision, the new revision is silently ignored. To remove it, add a minus sign after the label name.
Reversing injection at the Pod level
sidecar.istio.io/inject goes on the label of the Pod template. It is not a label or annotation of the Deployment itself. The value must be a string wrapped in quotes. Kubernetes label values accept only strings, so if you write it without quotes, the apiserver rejects it.
Creating per-version workloads and subsets
If you put version in the Service's selector, only one version is caught and weighted distribution becomes impossible altogether. Splitting versions is the job of the DestinationRule's subsets. A subset's labels must be literally the same as the Pod labels, not the subset name, and write spec.host as an FQDN instead of a short name. The service port name is the basis on which Istio determines the protocol.
Splitting 80 to 20 by weight
Weights attach to each destination in the route array and must sum to 100. Do not put a match in this rule. In the later tasks, rules with conditions come in front of this one, and the rule with no conditions must always be at the very end.
Putting specific rules in front of the catch-all
Rules are evaluated from top to bottom and the first match wins. If the rule with no conditions is at the very front, the rules behind it are never evaluated. And to combine two conditions with AND, you must write them side by side inside the same match block. If you split them into two blocks, it becomes OR.
Matching the relationship between timeout and retries
timeout is the overall deadline including retries. If perTryTimeout times the number of attempts exceeds timeout, the last attempt is cut off before it even starts. Here 500ms times 3 is 1.5 seconds, which fits within 2 seconds. retryOn is a string joined with commas, and if you leave it empty, which failures to retry on is not determined.
Applying connection pool limits and outlier detection
The two are inside the same trafficPolicy but do different things. connectionPool restrains the load going out from this side, and outlierDetection temporarily removes an instance on the other side if it keeps giving 5xx. If you do not write maxEjectionPercent, the field is not stored at all, so state the value explicitly. Be careful not to delete the loadBalancer you created in an earlier task.
Setting up the ingress gateway
A Gateway only opens ports and does not do routing. If you do not attach a VirtualService by writing the name in its spec.gateways, that rule applies only inside the mesh and external requests get a 404. httpsRedirect goes under the tls of the port 80 server. The certificate is looked up by credentialName in the gateway Pod's namespace.
Mesh-wide STRICT and a namespace exception
PeerAuthentication applies in three layers. If there is no selector and it is in the root namespace (istio-system), it is mesh-wide; if there is no selector and it is in another namespace, it is that entire namespace; and if there is a selector, it is a workload. The narrower scope wins over the wider. The moment you attach a selector to the global policy, it is no longer global.
Putting a port exception on a workload STRICT
portLevelMtls works only in a workload policy that has a selector. If you use it without a selector, the apiserver rejects it. And the port number you write here is not the Service port but the Pod's container port. If you write the Service port, the exception hooks onto nothing, and that fact passes quietly without an error.
Using ALLOW and DENY policies separately
DENY is evaluated before ALLOW, and if even one matches, it ends there. The evaluation order is CUSTOM, DENY, ALLOW. A principal is a service account's SPIFFE identity and its format is cluster.local/ns/<네임스페이스>/sa/<서비스계정> (the placeholders are the namespace and the service account). An asterisk at the end of a path is a prefix match.
Applying JWT verification and a token requirement together
RequestAuthentication only verifies a token if there is one, and lets a request without a token just pass. To require a token, you must also apply an AuthorizationPolicy that uses requestPrincipals. The format of requestPrincipals is the issuer and the subject joined with a slash, and to restrict only the issuer, put an asterisk after it.
Filling in what analyze catches
Run istioctl analyze -n ica-fix first and read what it says it cannot find. IST0101 means it could not find the referenced host or the pairing of host and subset. The same code appears whether the Service is missing or the DestinationRule lacks that subset. If you fill in one at a time and run it again, you can see what remains shrinking.
Reviving an unreachable rule
Rules are evaluated from top to bottom and the first match wins. A rule with no conditions matches every request, so if it is at the very front, the rules behind it are not evaluated for any request. No error appears and the configuration stays valid, so you have no choice but to find it by eye.
Fixing an empty ALLOW policy that blocks every request
If even one AuthorizationPolicy applies to a workload, that workload turns to default deny. In that state, if the ALLOW rules are empty, no request can match a rule and all are denied. No policy and an empty policy produce opposite results.
Fixing client TLS that conflicts with the server requirement
PeerAuthentication decides what the server will accept, and the DestinationRule's trafficPolicy.tls decides how the client connects. If the server is STRICT but the client is DISABLE, it connects in plaintext and is cut off. Both are valid configurations, so neither gives an error, which is what makes this outage hard. Choose the mode in which the sidecar handles the certificates for you.