Skip to main content
mastering ckad certified kubernetes application developer

Selector and kubectl explain Solutions

9 min read Chapter 15 of 87
Summary

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 TypeSyntaxMeaning
Equality-l app=nginxapp equals nginx
Inequality-l env!=prodenv 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=frontendBoth 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. 250m means 250 millicores, or 0.25 of a CPU core. 1 means one full core.
  • memory — measured in bytes with SI or binary suffixes. 128Mi means 128 mebibytes (128 × 1024 × 1024 bytes). 256M means 256 megabytes (256 × 1000 × 1000 bytes). On the exam, use Mi (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:

  1. You need to set a field you do not remember the exact syntax for.
  2. You use kubectl explain to find the field path and type.
  3. You write the YAML based on what explain tells you.
  4. 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: limits and requests are children of resources, which is a child of the container entry. Each level adds two spaces of indentation. Getting this wrong produces a validation error.
  • Confusing M and Mi: 128M is 128,000,000 bytes. 128Mi is 134,217,728 bytes. The difference matters when you are close to a limit threshold. Use Mi for 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.