Namespaces, Labels, Selectors, and kubectl explain
SummaryCovers Kubernetes namespaces for logical isolation, labels and...
Covers Kubernetes namespaces for logical isolation, labels and...
Covers Kubernetes namespaces for logical isolation, labels and annotations for metadata, equality-based and set-based selectors for filtering, and kubectl explain as the built-in manifest reference for the exam.
Namespaces, Labels, Selectors, and kubectl explain
Kubernetes gives you four organizational tools that appear in nearly every exam task: namespaces partition a cluster into logical segments, labels tag resources with queryable key-value pairs, selectors filter resources by those labels, and kubectl explain provides built-in documentation for every field in every manifest. Mastering these primitives is not optional — they are the grammar of Kubernetes resource management.
Namespaces: Logical Isolation
A namespace is a virtual partition within a Kubernetes cluster. Resources in one namespace are invisible to queries against another namespace (unless you explicitly ask for all namespaces). Namespaces provide:
- Scope isolation — two Pods in different namespaces can have the same name without conflict.
- Access control boundaries — RBAC policies can restrict users to specific namespaces.
- Resource quota boundaries — you can cap CPU, memory, and object counts per namespace.
Every cluster starts with four namespaces:
| Namespace | Purpose |
|---|---|
default | Where resources land if you do not specify a namespace |
kube-system | Control plane components (API server, scheduler, CoreDNS) |
kube-public | Publicly readable data (rarely used directly) |
kube-node-lease | Node heartbeat leases for failure detection |
The Default Namespace Pitfall
When a task does not specify a namespace, kubectl targets default. When a task does specify a namespace (and exam tasks almost always do), you must include -n <namespace> in every command — or set the namespace context before starting the task.
This is the most common mistake on the CKAD: creating the right resource in the wrong namespace. The scoring is binary — if the grader checks namespace finance and your Pod is in default, you get zero points.
Creating and Managing Namespaces
# Create a namespace imperatively
kubectl create ns dev
# Create a namespace from YAML
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Namespace
metadata:
name: staging
EOF
# List all namespaces
kubectl get ns
# Delete a namespace (deletes ALL resources inside it)
kubectl delete ns dev
Warning: Deleting a namespace is a cascading operation. Every Pod, Service, ConfigMap, and Secret inside that namespace is destroyed. There is no undo.
Setting Your Default Namespace
Instead of typing -n dev on every command, set the namespace for your current context:
kubectl config set-context --current --namespace=dev
Now every kubectl command targets the dev namespace unless you override with -n. On the exam, run this immediately when a task specifies a namespace. It prevents the “right resource, wrong namespace” failure mode.
Verify your current context:
kubectl config get-contexts
The NAMESPACE column shows your active default. If it is blank, you are targeting default.
Labels: Queryable Metadata
Labels are key-value pairs attached to resources. They serve one critical purpose: identification for selection. Services route traffic to Pods based on labels. Deployments manage Pods based on labels. NetworkPolicies target Pods based on labels. Without labels, Kubernetes has no way to express “this group of resources belongs together.”
Label Syntax Rules
- Keys can include an optional prefix and a required name:
app.kubernetes.io/nameorapp. - Prefixes must be DNS subdomains (e.g.,
company.com/). Thekubernetes.io/andk8s.io/prefixes are reserved. - Names must be 63 characters or fewer, start and end with alphanumeric characters, and can include
-,_, and.internally. - Values follow the same 63-character alphanumeric rules.
Adding Labels
Labels can be set in the manifest or added after creation:
# In a manifest
apiVersion: v1
kind: Pod
metadata:
name: web-server
labels:
app: nginx
env: prod
tier: frontend
spec:
containers:
- name: nginx
image: nginx:1.25
# Add a label to a running Pod
kubectl label pod web-server version=v2
# Overwrite an existing label
kubectl label pod web-server env=staging --overwrite
# Remove a label (note the trailing minus sign)
kubectl label pod web-server version-
Common Label Conventions
Kubernetes recommends a standard set of labels for application identification:
| Label | Example Value | Purpose |
|---|---|---|
app.kubernetes.io/name | nginx | Application name |
app.kubernetes.io/version | 1.25.0 | Application version |
app.kubernetes.io/component | webserver | Role within the architecture |
app.kubernetes.io/part-of | ecommerce | Higher-level application |
On the exam, you will typically use short-form labels (app, env, tier) for speed. In production, the prefixed form provides structure across teams.
Annotations: Metadata for Tools
Annotations look like labels — key-value pairs in metadata — but they serve a different purpose. Annotations store non-identifying metadata: build timestamps, git commit hashes, configuration for ingress controllers, tool-specific directives.
metadata:
name: web-server
annotations:
build.company.com/commit: "a1b2c3d"
build.company.com/timestamp: "2025-01-15T10:30:00Z"
nginx.ingress.kubernetes.io/rewrite-target: /
The key difference: labels are for selectors, annotations are not. You cannot query resources by annotation value with kubectl get -l. Annotations have no length limit on values (labels are capped at 63 characters), which makes them suitable for structured data like JSON configuration blobs.
# Add an annotation
kubectl annotate pod web-server description="Primary frontend server"
# Remove an annotation
kubectl annotate pod web-server description-
Exam relevance: The CKAD occasionally requires setting annotations, particularly for Ingress resources. Know how to add them imperatively and in YAML.
Selectors: Filtering by Labels
Selectors are the query language for labels. Every time Kubernetes needs to find “which Pods does this Service target?” or “which Pods does this NetworkPolicy apply to?”, it uses a selector.
Equality-Based Selectors
Match labels using =, == (identical to =), or !=:
# Get all Pods where app equals nginx
kubectl get pods -l app=nginx
# Get all Pods where env does NOT equal prod
kubectl get pods -l env!=prod
# Combine multiple conditions (AND logic)
kubectl get pods -l app=nginx,env=prod
Multiple selectors separated by commas are combined with AND logic — the resource must match all conditions.
Set-Based Selectors
Match labels using in, notin, and exists:
# Get Pods where env is dev OR staging
kubectl get pods -l 'env in (dev,staging)'
# Get Pods where env is NOT prod and NOT staging
kubectl get pods -l 'env notin (prod,staging)'
# Get Pods that HAVE the label "tier" (any value)
kubectl get pods -l 'tier'
# Get Pods that do NOT have the label "tier"
kubectl get pods -l '!tier'
Note: Set-based selectors require single quotes around the expression to prevent shell interpretation of parentheses and exclamation marks.
Selectors in Manifests
Services and Deployments use selectors in their specs to target Pods:
# Service selector — routes traffic to Pods with matching labels
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
selector:
app: nginx
tier: frontend
ports:
- port: 80
targetPort: 80
# Deployment selector — manages Pods with matching labels
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
The Deployment’s spec.selector.matchLabels must match spec.template.metadata.labels. If they do not match, the Deployment cannot find the Pods it creates, and you get a validation error. This is a common manifest mistake and a frequent exam pitfall.
kubectl explain: The Exam Documentation Tool
The CKAD exam allows access to the official Kubernetes documentation at kubernetes.io/docs, but navigating a browser is slow. kubectl explain provides the same information directly in the terminal — field names, types, descriptions, and nesting — without leaving your workflow.
Basic Usage
# Top-level fields of a Pod
kubectl explain pod
Output:
KIND: Pod
VERSION: v1
DESCRIPTION:
Pod is a collection of containers that can run on a host...
FIELDS:
apiVersion <string>
kind <string>
metadata <ObjectMeta>
spec <PodSpec>
status <PodStatus>
Drilling Into Nested Fields
Use dot notation to navigate deeper:
# Container fields within a Pod spec
kubectl explain pod.spec.containers
# Resource limits within a container
kubectl explain pod.spec.containers.resources
# Specific field: memory limits
kubectl explain pod.spec.containers.resources.limits
Each level shows the field’s type, whether it is required, and a description. This is your substitute for memorizing every field name in every resource.
Recursive Output
To see the full tree structure at once:
kubectl explain pod.spec --recursive
This dumps every field under pod.spec with its type, but without descriptions. It is useful when you know the field name exists somewhere and need to find its exact path.
# Find where readinessProbe lives
kubectl explain pod.spec --recursive | grep -i readiness
Output:
readinessProbe <Probe>
Now you know it is at pod.spec.containers.readinessProbe. Drill in for details:
kubectl explain pod.spec.containers.readinessProbe
Why This Matters on the Exam
During the exam, you will need to write fields you have not memorized. Instead of switching to a browser, searching documentation, and finding the right page:
- Use
kubectl explain <resource>to find the top-level structure. - Drill into the section you need with dot notation.
- Read the field description and type.
- Write the YAML.
This workflow keeps you in the terminal and saves minutes per task. Over a 2-hour exam with 15-20 tasks, those minutes compound into the difference between passing and failing.
Exercises
Work through these exercises in your Kind cluster. Solutions are provided in the next chapter.
Exercise 1: Create a Pod Imperatively and Declaratively
- Generate a Pod manifest using the dry-run technique:
kubectl run nginx --image=nginx:1.25 --dry-run=client -o yaml > pod.yaml - Open
pod.yamland add a labelenv: devundermetadata.labels. - Apply the manifest:
kubectl apply -f pod.yaml. - Verify the Pod is running:
kubectl get pods. - Verify the label is present:
kubectl get pod nginx --show-labels.
Exercise 2: Add Labels to a Running Pod
- Add two labels to the running
nginxPod:kubectl label pod nginx tier=frontend version=v1 - Verify the labels:
kubectl get pod nginx --show-labels. - Overwrite the
envlabel fromdevtostaging:kubectl label pod nginx env=staging --overwrite - Remove the
versionlabel:kubectl label pod nginx version- - Confirm the final label set with
--show-labels.
Exercise 3: Filter Resources with Label Selectors
- Create three additional Pods with different labels:
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 - List all Pods where
env=dev. - List all Pods where
envisdevorstaging. - List all Pods where
app=webANDtier=frontend. - List all Pods that have the label
tier(any value). - List all Pods across all namespaces that have the label
app.
Exercise 4: Use kubectl explain to Find Resource Limit Fields
- Run
kubectl explain pod.spec.containers.resourcesand identify the fields for setting CPU and memory limits. - Run
kubectl explain pod.spec.containers.resources.limitsto see what resource types are available. - Use
kubectl explain pod.spec --recursive | grep -i restartto find the exact path forrestartPolicy. - Based on what you find, add a resource limit of
128Mimemory and250mCPU to yournginxPod manifest, then re-apply.