Selector and kubectl explain Solutions
SummaryStep-by-step solutions for Exercises 3 and 4: filtering...
Step-by-step solutions for Exercises 3 and 4: filtering...
Step-by-step solutions for Exercises 3 and 4: filtering resources with equality-based and set-based label selectors, and navigating resource schemas with kubectl explain to discover field paths and types.
Selector and kubectl explain Solutions
Exercise 3: Filter Resources with Label Selectors
This exercise builds a set of labeled Pods and uses both equality-based and set-based selectors to query them. The expected state before starting: the nginx Pod from Exercise 1–2 is still running with labels env=staging, run=nginx, tier=frontend.
Step 1: Create Three Additional Pods
kubectl run web1 --image=nginx:1.25 -l app=web,env=dev,tier=frontend
kubectl run web2 --image=nginx:1.25 -l app=web,env=prod,tier=frontend
kubectl run api1 --image=nginx:1.25 -l app=api,env=dev,tier=backend
Expected output for each:
pod/web1 created
pod/web2 created
pod/api1 created
The -l flag (short for --labels) sets labels at creation time. Multiple labels are comma-separated with no spaces. This is faster than creating the Pod and then adding labels separately.
Verify all Pods are running:
kubectl get pods --show-labels
Expected output:
NAME READY STATUS RESTARTS AGE LABELS
api1 1/1 Running 0 10s app=api,env=dev,tier=backend
nginx 1/1 Running 0 5m env=staging,run=nginx,tier=frontend
web1 1/1 Running 0 12s app=web,env=dev,tier=frontend
web2 1/1 Running 0 11s app=web,env=prod,tier=frontend
You now have four Pods with different label combinations. This is your dataset for the selector queries.
Step 2: List All Pods Where env=dev
kubectl get pods -l env=dev
Expected output:
NAME READY STATUS RESTARTS AGE
api1 1/1 Running 0 30s
web1 1/1 Running 0 32s
Two Pods match: web1 and api1 both have env=dev. The nginx Pod has env=staging and web2 has env=prod, so neither appears.
The -l flag accepts an equality-based selector. The = operator checks for exact value match. You could also use == — it is identical to = in Kubernetes selectors.
Step 3: List All Pods Where env is dev or staging
kubectl get pods -l 'env in (dev,staging)'
Expected output:
NAME READY STATUS RESTARTS AGE
api1 1/1 Running 0 1m
nginx 1/1 Running 0 6m
web1 1/1 Running 0 1m
Three Pods match: api1 and web1 have env=dev, nginx has env=staging. The in operator matches any value in the parenthesized set.
Important: The single quotes around the expression are required. Without them, the shell interprets the parentheses as subshell syntax:
# This FAILS with a shell error:
kubectl get pods -l env in (dev,staging)
# This works:
kubectl get pods -l 'env in (dev,staging)'
Step 4: List All Pods Where app=web AND tier=frontend
kubectl get pods -l app=web,tier=frontend
Expected output:
NAME READY STATUS RESTARTS AGE
web1 1/1 Running 0 2m
web2 1/1 Running 0 2m
Two Pods match. Both web1 and web2 have app=web and tier=frontend. The api1 Pod has app=api (not web), so it is excluded. The nginx Pod does not have an app label at all.
Comma-separated selectors are combined with AND logic. The resource must satisfy every condition. There is no OR operator in the comma-separated syntax — use in for OR logic on a single key.
Step 5: List All Pods That Have the Label tier (Any Value)
kubectl get pods -l 'tier'
Expected output:
NAME READY STATUS RESTARTS AGE
api1 1/1 Running 0 3m
nginx 1/1 Running 0 8m
web1 1/1 Running 0 3m
web2 1/1 Running 0 3m
All four Pods have a tier label (values: frontend, frontend, frontend, backend). The existence selector does not check the value — it checks whether the key exists at all.
If you wanted the inverse — Pods that do not have a tier label:
kubectl get pods -l '!tier'
This would return no Pods in our current setup because all four have the tier label.
Step 6: List All Pods Across All Namespaces That Have the Label app
kubectl get pods -l app --all-namespaces
Or using the short form:
kubectl get pods -l app -A
Expected output:
NAMESPACE NAME READY STATUS RESTARTS AGE
default api1 1/1 Running 0 4m
default web1 1/1 Running 0 4m
default web2 1/1 Running 0 4m
Three Pods match — the three you created with the app label. The nginx Pod does not have an app label (it has run=nginx instead), so it is excluded.
The -A or --all-namespaces flag searches across every namespace in the cluster. Without it, kubectl only queries your current namespace context. On the exam, tasks sometimes require finding resources across namespaces — --all-namespaces combined with a label selector is the fastest way.
Note that the output now includes a NAMESPACE column. This appears automatically whenever you use -A.
Selector Quick Reference
| Selector Type | Syntax | Meaning |
|---|---|---|
| Equality | -l app=nginx | app equals nginx |
| Inequality | -l env!=prod | env does not equal prod |
| Set membership | -l 'env in (dev,staging)' | env is dev or staging |
| Set exclusion | -l 'env notin (prod)' | env is not prod (or key absent) |
| Existence | -l 'tier' | tier label exists (any value) |
| Non-existence | -l '!tier' | tier label does not exist |
| Combined (AND) | -l app=web,tier=frontend | Both conditions must match |
Exercise 4: Use kubectl explain to Find Resource Limit Fields
This exercise builds your ability to navigate the Kubernetes resource schema without leaving the terminal — a workflow that directly replaces browser documentation lookups during the exam.
Step 1: Explore Container Resource Fields
kubectl explain pod.spec.containers.resources
Expected output (abbreviated):
KIND: Pod
VERSION: v1
FIELD: resources <ResourceRequirements>
DESCRIPTION:
Compute Resources required by this container...
FIELDS:
claims <[]ResourceClaim>
limits <map[string]Quantity>
requests <map[string]Quantity>
Three fields appear under resources:
limits— the maximum resources the container can use. If the container exceeds its memory limit, the kubelet kills it (OOMKilled). If it exceeds its CPU limit, it is throttled.requests— the minimum resources the container needs. The scheduler uses requests to decide which node has enough capacity. A Pod cannot be scheduled if no node can satisfy its requests.claims— used for dynamic resource allocation (DRA), an advanced feature not tested on the CKAD.
Step 2: Explore the Limits Field
kubectl explain pod.spec.containers.resources.limits
Expected output:
KIND: Pod
VERSION: v1
FIELD: limits <map[string]Quantity>
DESCRIPTION:
Limits describes the maximum amount of compute resources allowed...
The type map[string]Quantity tells you the format: keys are resource type names (strings), values are quantities. The two standard resource types are:
cpu— measured in millicores.250mmeans 250 millicores, or 0.25 of a CPU core.1means one full core.memory— measured in bytes with SI or binary suffixes.128Mimeans 128 mebibytes (128 × 1024 × 1024 bytes).256Mmeans 256 megabytes (256 × 1000 × 1000 bytes). On the exam, useMi(mebibytes) unless the task specifies otherwise.
Step 3: Find the restartPolicy Path
kubectl explain pod.spec --recursive | grep -i restart
Expected output:
restartPolicy <string>
The indentation shows restartPolicy is a direct child of pod.spec — its full path is pod.spec.restartPolicy. Drill in for details:
kubectl explain pod.spec.restartPolicy
Expected output:
KIND: Pod
VERSION: v1
FIELD: restartPolicy <string>
DESCRIPTION:
Restart policy for all containers within the pod.
One of Always, OnFailure, Never.
...
Three valid values:
Always(default) — the kubelet restarts the container whenever it exits, regardless of exit code. This is the default for Pods in Deployments.OnFailure— the kubelet restarts the container only if it exits with a non-zero exit code. Used by Jobs.Never— the container is not restarted. Used for one-shot tasks where you want to inspect the exit state.
Step 4: Add Resource Limits to the Pod Manifest
Based on what you found, update pod.yaml to include resource limits:
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
labels:
run: nginx
env: dev
name: nginx
spec:
containers:
- image: nginx:1.25
name: nginx
resources:
limits:
memory: "128Mi"
cpu: "250m"
requests:
memory: "64Mi"
cpu: "125m"
dnsPolicy: ClusterFirst
restartPolicy: Always
status: {}
The resources block replaces the empty resources: {} from the generated manifest. Requests are set to half the limits — a common pattern that gives the container room to burst without requesting more resources than it needs on average.
Now apply the updated manifest. Since the Pod already exists and Pod specs are largely immutable (you cannot change resource limits on a running Pod), you need to delete and recreate:
kubectl delete pod nginx
kubectl apply -f pod.yaml
Expected output:
pod "nginx" deleted
pod/nginx created
Alternatively, use the --force and --grace-period=0 flags with replace:
kubectl replace -f pod.yaml --force --grace-period=0
This deletes and recreates the Pod in one command. On the exam, this is the faster approach for immutable field changes.
Verify the Resource Limits
kubectl describe pod nginx | grep -A 6 "Limits\|Requests"
Expected output:
Limits:
cpu: 250m
memory: 128Mi
Requests:
cpu: 125m
memory: 64Mi
The limits and requests match what you specified in the manifest.
Why Resource Limits Matter
This exercise illustrates a pattern you encounter repeatedly on the CKAD:
- You need to set a field you do not remember the exact syntax for.
- You use
kubectl explainto find the field path and type. - You write the YAML based on what
explaintells you. - You apply and verify.
On the exam, resource limits appear in multiple contexts — Pod specs, container definitions within Deployments, LimitRanges, ResourceQuotas. The kubectl explain workflow gives you a reliable way to get the syntax right without memorizing every field across every resource type.
Common Mistakes
- Indentation errors in the resources block:
limitsandrequestsare children ofresources, which is a child of the container entry. Each level adds two spaces of indentation. Getting this wrong produces a validation error. - Confusing
MandMi:128Mis 128,000,000 bytes.128Miis 134,217,728 bytes. The difference matters when you are close to a limit threshold. UseMifor memory on the exam unless told otherwise. - Forgetting that Pod specs are immutable: You cannot change resource limits on a running Pod. You must delete and recreate. Deployments handle this automatically (they create a new ReplicaSet), but bare Pods require manual replacement.
- Setting limits without requests: If you set limits but not requests, Kubernetes sets requests equal to limits. This means the container gets a guaranteed QoS class (
Guaranteed), which affects eviction priority. On the exam, set both explicitly to demonstrate understanding.