Skip to content

Basic Bash Commands for CKA

Essential commands for navigating and manipulating output during CKA exam. Master these to solve problems faster and more efficiently.


1. Text Processing – The Power Tools

grep – Search/Filter (Your First Line of Defense)

What it does: Searches for patterns in text. Think of it as Ctrl+F for the terminal.

Core Concepts:

  • Regular Expressions: grep supports regex for complex pattern matching
  • Context Lines: Show surrounding lines for better debugging
  • Pipeline Integration: Works perfectly with kubectl output
bash
# Basic search
kubectl get pods | grep nginx

# Case insensitive (-i flag)
kubectl get pods | grep -i NGINX

# Invert match (exclude lines with pattern using -v)
kubectl get pods | grep -v Running          # Show only non-Running pods

# Context lines (critical for debugging Events/Logs)
kubectl describe pod nginx | grep -A5 "Events"   # 5 lines AFTER match
kubectl describe pod nginx | grep -B3 "Error"    # 3 lines BEFORE match
kubectl logs nginx | grep -C2 "error"            # 2 lines before AND after (Context)

# Count matches (-c flag)
kubectl get pods -A | grep -c Running            # How many Running pods?

# Multiple patterns (Extended regex with -E)
kubectl get pods | grep -E "nginx|apache|tomcat"

# Regular expressions
kubectl get pods | grep "nginx-[0-9]\+"          # Match nginx-1, nginx-2, etc.
kubectl get pods | grep "^nginx"                 # Starts with nginx
kubectl get pods | grep "nginx$"                 # Ends with nginx

# Quiet mode (just exit code, no output - useful in scripts)
if kubectl get pods | grep -q "nginx"; then
  echo "Found nginx pod"
fi

# Show only matching part (-o flag)
kubectl get pods -o wide | grep -oP '\d+\.\d+\.\d+\.\d+'  # Extract IPs only

Pro Tips:

  • Use -A and -B to grab Events sections in describe output
  • -v is perfect for filtering out headers or unwanted states
  • Combine with wc -l to count matches: kubectl get pods | grep -c Running

awk – The Swiss Army Knife of Column Extraction

What it does: Processes text line-by-line and extracts/transforms columns. Your go-to for parsing kubectl tabular output.

Core Concepts:

  • Field Separator: By default, whitespace. Change with -F
  • Built-in Variables: $1, $2, $NF (last field), NR (line number), NF (number of fields)
  • Pattern Matching: Filter rows based on conditions
bash
# Print specific columns
kubectl get pods | awk '{print $1}'              # Column 1: Pod name
kubectl get pods | awk '{print $3}'              # Column 3: Status
kubectl get pods | awk '{print $1, $3}'          # Multiple columns with space

# Skip header (NR = Number of Records/Lines)
kubectl get pods | awk 'NR>1 {print $1}'         # Start from line 2

# Conditional filtering
kubectl get pods | awk '$3=="Running" {print $1}'           # Only Running pods
kubectl get pods | awk '$3!="Running" {print $1, $3}'       # Non-Running with status
kubectl get pods -o wide | awk '$7=="node-1" {print $1}'    # Pods on specific node

# Custom field separator (handle multiple spaces)
# Custom field separator (handle multiple spaces)
kubectl get pods -o wide | awk -F' +' '{print $7}'           # Node column
echo "name:value:other" | awk -F':' '{print $2}'             # Use colon as separator

# Print last field ($NF = Number of Fields)
echo "a b c d e" | awk '{print $NF}'                         # Prints "e"

# Formatted output
kubectl get pods | awk '{printf "%-30s %s\n", $1, $3}'       # Aligned columns

# Math operations
kubectl top pods | awk 'NR>1 {print $1, $2, $3; sum+=$2} END {print "Total CPU:", sum}'

# BEGIN and END blocks
kubectl get pods | awk 'BEGIN {print "=== POD LIST ==="} NR>1 {print $1} END {print "=== END ==="}'

Pro Tips:

  • $NF always gets the last column (useful when column count varies)
  • Use printf for aligned, readable output
  • NR==1 to process only the header, NR>1 to skip it
  • Combine with grep: kubectl get pods | grep Running | awk '{print $1}'

sed – Stream Editor for Text Transformation

What it does: Edits text streams (search/replace, delete, insert). Essential for quick YAML edits and text manipulation.

Core Concepts:

  • Substitution: s/pattern/replacement/flags
  • Deletion: d command
  • In-place Editing: -i flag modifies files directly
  • Address Ranges: Specify which lines to operate on
bash
# Basic substitution (replaces FIRST occurrence per line)
echo "app=nginx" | sed 's/nginx/apache/'                     # app=apache

# Global replace (all occurrences using /g flag)
echo "nginx nginx nginx" | sed 's/nginx/apache/g'            # apache apache apache

# Case-insensitive replace
echo "NGINX nginx Nginx" | sed 's/nginx/apache/gi'           # apache apache apache

# Delete lines
kubectl get pods | sed '1d'                                  # Delete first line (header)
kubectl get pods | sed '/Running/d'                          # Delete all lines containing "Running"
kubectl get pods | sed '/^$/d'                               # Delete empty lines

# Delete line ranges
sed '1,5d' file.yaml                                         # Delete lines 1-5
sed '10,$d' file.yaml                                        # Delete from line 10 to end

# In-place file editing (DANGEROUS - make backups!)
sed -i 's/replicas: 1/replicas: 3/' deployment.yaml         # Edit file directly
sed -i.bak 's/old/new/' file.txt                            # Create backup as file.txt.bak

# Multiple operations (-e flag or semicolon separator)
sed 's/nginx/apache/; s/port: 80/port: 8080/' pod.yaml
sed -e 's/nginx/apache/' -e 's/80/8080/' pod.yaml

# Insert/Append lines
sed '2i\  replicas: 5' deployment.yaml                       # Insert before line 2
sed '2a\  replicas: 5' deployment.yaml                       # Append after line 2

# Replace specific line number
sed '5s/.*/  replicas: 10/' deployment.yaml                  # Replace entire line 5

# Advanced: Extract between patterns
sed -n '/Events:/,/Conditions:/p' pod-describe.txt           # Print from Events to Conditions

Pro Tips:

  • Always test without -i first! Pipe to | head or redirect to a new file
  • Use sed -i.bak to create backups automatically
  • Combine with kubectl: kubectl get deploy nginx -o yaml | sed 's/replicas: 1/replicas: 3/' | kubectl apply -f -

cut – Simple Field Extraction

What it does: Extracts columns from delimited text. Simpler than awk for straightforward tasks.

Core Concepts:

  • Delimiter-based: -d sets delimiter, -f specifies field number
  • Character-based: -c extracts by character position
  • Zero-indexed: Fields start at 1 (not 0)
bash
# By delimiter
echo "name:value:other" | cut -d':' -f1                     # Get "name"
echo "name:value:other" | cut -d':' -f2                     # Get "value"
echo "name:value:other" | cut -d':' -f1,3                   # Get "name:other"

# Character position
echo "hello world" | cut -c1-5                              # "hello"
echo "kubernetes" | cut -c1,3,5                             # "kbr"

# With kubectl (extract namespace from full pod name)
kubectl get pods -A -o name | cut -d'/' -f2                 # pod/nginx-xxx -> nginx-xxx

# Extract IPs from CSV-like output
echo "10.0.1.5,nginx,Running" | cut -d',' -f1               # 10.0.1.5

# Multiple fields with different output delimiter
echo "a:b:c:d" | cut -d':' -f1,3 --output-delimiter=' '     # "a c"

When to use cut vs awk:

  • cut: Simple, single delimiter, fixed columns
  • awk: Complex filtering, multiple conditions, math operations

sort & uniq – Data Organization

What it does: Sorts lines and removes duplicates. Critical for analyzing resource distributions.

bash
# Basic sort
kubectl get pods | sort                                      # Alphabetical
kubectl get pods | sort -r                                   # Reverse

# Numeric sort (-n flag - CRITICAL for numbers!)
kubectl top pods | sort -k2 -n                              # Sort by CPU (column 2, numeric)
kubectl top pods | sort -k3 -nr                             # Sort by Memory, descending

# Sort by specific column (-k flag)
kubectl get pods -o wide | sort -k7                         # Sort by Node name (column 7)

# Unique values
kubectl get pods -A -o jsonpath='{.items[*].spec.nodeName}' | tr ' ' '\n' | sort -u

# Count occurrences of unique values (classic pattern)
kubectl get pods -A | awk '{print $3}' | sort | uniq -c
# Output:
#   45 Running
#    3 Pending
#    2 CrashLoopBackOff

# Remove adjacent duplicates (requires sort first!)
kubectl get pods -A -o jsonpath='{.items[*].spec.nodeName}' | tr ' ' '\n' | sort | uniq

# Case-insensitive unique
sort -u -f file.txt

Pro Tips:

  • Always use -n for numeric sorts! Otherwise "10" < "2" alphabetically
  • uniq only removes adjacent duplicates - always sort first
  • sort -k2,2 sorts by column 2 only (not from column 2 to end)

2. kubectl Output Formatting – Precision Extraction

JSONPath – The Query Language

What it does: Extracts specific fields from JSON output. Most powerful kubectl output method.

Core Concepts:

  • Dot Notation: .field.subfield
  • Array Access: [*] for all items, [0] for first
  • Filters: [?(@.field=="value")] for conditional selection
  • Range: Iterate over arrays
bash
# Single field from single resource
kubectl get pod nginx -o jsonpath='{.status.phase}'                     # Running
kubectl get pod nginx -o jsonpath='{.spec.containers[0].image}'         # nginx:latest

# All items (note the .items[*])
kubectl get pods -o jsonpath='{.items[*].metadata.name}'                # space-separated names

# With newlines (critical for readability!)
kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\n"}{end}'

# Multiple fields per line
kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.phase}{"\n"}{end}'

# Nested array access
kubectl get nodes -o jsonpath='{.items[*].status.addresses[?(@.type=="InternalIP")].address}'

# Conditional filtering
kubectl get pods -o jsonpath='{.items[?(@.status.phase=="Running")].metadata.name}'
kubectl get pods -o jsonpath='{.items[?(@.spec.nodeName=="node-1")].metadata.name}'

# Complex example: Get all container images from all pods
kubectl get pods -o jsonpath='{range .items[*]}{range .spec.containers[*]}{.image}{"\n"}{end}{end}'

# Array length
kubectl get pods -o jsonpath='{.items[*].metadata.name}' | wc -w        # Count pods

Advanced Patterns:

bash
# Get pod name and all container names
kubectl get pod nginx -o jsonpath='{.metadata.name}: {.spec.containers[*].name}'

# Node IPs
kubectl get nodes -o jsonpath='{.items[*].status.addresses[?(@.type=="InternalIP")].address}'

# All pod IPs in namespace
kubectl get pods -n kube-system -o jsonpath='{.items[*].status.podIP}'

Pro Tips:

  • Use {range...}{end} for clean line-by-line output
  • {"\n"} for newline, {"\t"} for tab
  • Test with | head to avoid overwhelming output
  • Wrap in quotes to handle spaces: jsonpath='{.items[*].metadata.name}'

Custom Columns – Human-Readable Tables

What it does: Creates formatted tables with only the fields you need.

bash
# Basic syntax
kubectl get pods -o custom-columns=NAME:.metadata.name,STATUS:.status.phase

# Multiple columns (comma-separated)
kubectl get pods -o custom-columns=NAME:.metadata.name,NODE:.spec.nodeName,IP:.status.podIP

# With custom headers
kubectl get pods -o custom-columns="POD NAME":.metadata.name,"CURRENT STATUS":.status.phase

# Complex nested fields
kubectl get pods -o custom-columns=NAME:.metadata.name,IMAGE:.spec.containers[0].image,STATUS:.status.phase

# All namespaces
kubectl get pods -A -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name,STATUS:.status.phase

# From file (reusable templates!)
cat > columns.txt << EOF
NAME:.metadata.name
STATUS:.status.phase
NODE:.spec.nodeName
IP:.status.podIP
EOF
kubectl get pods -o custom-columns-file=columns.txt

When to use:

  • Need formatted output for humans (not for parsing)
  • Want column headers
  • Prefer readability over scriptability

3. File Operations – Working with Manifests

cat/head/tail – File Reading

bash
# View entire file
cat pod.yaml

# First 10 lines (default) or N lines
head pod.yaml
head -n 5 pod.yaml                                          # First 5 lines

# Last 10 lines or N lines
tail pod.yaml
tail -n 20 pod.yaml                                         # Last 20 lines

# Skip first N lines (useful to remove headers)
tail -n +2 file.txt                                         # Start from line 2

# Follow file in real-time (-f flag - CRITICAL for logs!)
tail -f /var/log/syslog
kubectl logs -f nginx                                        # Built-in follow
kubectl logs --tail=50 -f nginx                             # Last 50 lines, then follow

# Combine with grep for filtered real-time logs
kubectl logs -f nginx | grep ERROR

wc – Word/Line/Character Count

bash
# Count lines (-l flag)
kubectl get pods | wc -l                                    # Total lines (includes header!)
kubectl get pods --no-headers | wc -l                       # Accurate pod count

# Count words (-w flag)
echo "hello world test" | wc -w                             # 3

# Count characters/bytes (-c flag)
echo "hello" | wc -c                                        # 6 (includes newline!)

# Count without newline
echo -n "hello" | wc -c                                     # 5

# Practical: How many Running pods?
kubectl get pods | grep Running | wc -l

bash
# Find by name
find /etc -name "*.conf"                                    # All .conf files in /etc
find /var/log -name "*.log"                                 # All log files

# Find by type
find /tmp -type f                                           # Files only
find /tmp -type d                                           # Directories only

# Find and execute command on results
find /etc -name "*.yaml" -exec grep "apiVersion" {} \;      # Grep in all YAML files
find . -name "*.yaml" -exec kubectl apply -f {} \;          # Apply all YAMLs

# Find modified in last N days
find /var/log -mtime -7                                     # Modified in last 7 days
find /tmp -mtime +30                                        # Modified more than 30 days ago

# Find by size
find / -type f -size +100M                                  # Files larger than 100MB
find /var/log -type f -size +1G -delete                     # Delete files > 1GB

# Practical: Find all Kubernetes manifests
find /etc/kubernetes -name "*.yaml" -o -name "*.conf"

4. Redirection & Pipes – Data Flow Control

Understanding File Descriptors:

  • 0 = stdin (standard input)
  • 1 = stdout (standard output)
  • 2 = stderr (standard error)
bash
# Overwrite file (>)
kubectl get pods > pods.txt

# Output to file (append)
kubectl get pods >> pods.txt

# Redirect stderr
kubectl get badresource 2> error.txt

# Redirect both stdout and stderr
kubectl get pods &> all.txt

# Pipe to another command
kubectl get pods | grep nginx

# Here document
cat << EOF > pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx
EOF

5. Variables

bash
# Set variable
NAME="nginx"
kubectl get pod $NAME

# Command substitution
POD=$(kubectl get pods -o jsonpath='{.items[0].metadata.name}')
kubectl exec $POD -- ls

# Get node name
NODE=$(kubectl get nodes -o name | head -1 | cut -d'/' -f2)

6. Loops

bash
# For loop
for pod in $(kubectl get pods -o name); do
  kubectl describe $pod
done

# Delete all pods with pattern
for pod in $(kubectl get pods | grep test | awk '{print $1}'); do
  kubectl delete pod $pod
done

# While read
kubectl get pods -o name | while read pod; do
  echo "Processing $pod"
done

7. Conditions

bash
# Check if command succeeded
if kubectl get pod nginx; then
  echo "Pod exists"
else
  echo "Pod not found"
fi

# Check string equality
STATUS=$(kubectl get pod nginx -o jsonpath='{.status.phase}')
if [ "$STATUS" == "Running" ]; then
  echo "Pod is running"
fi

8. Quick CKA Patterns

Get Pod Names Only

bash
kubectl get pods -o name
kubectl get pods -o jsonpath='{.items[*].metadata.name}'
kubectl get pods --no-headers | awk '{print $1}'

Get Node Names

bash
kubectl get nodes -o name | cut -d'/' -f2
kubectl get nodes -o jsonpath='{.items[*].metadata.name}'

Get Pod IPs

bash
kubectl get pods -o wide | awk '{print $6}'
kubectl get pods -o jsonpath='{.items[*].status.podIP}'

Get Image Names

bash
kubectl get pods -o jsonpath='{.items[*].spec.containers[*].image}'
kubectl get pod nginx -o jsonpath='{.spec.containers[0].image}'

Filter by Status

bash
kubectl get pods --field-selector=status.phase=Running
kubectl get pods | awk '$3=="Running"'

Count Resources

bash
kubectl get pods --no-headers | wc -l
kubectl get pods -A --no-headers | wc -l

Export YAML

bash
kubectl get pod nginx -o yaml > nginx.yaml
kubectl get pod nginx -o yaml --export > nginx-clean.yaml  # deprecated

Dry Run

bash
kubectl run nginx --image=nginx --dry-run=client -o yaml > pod.yaml
kubectl create deployment nginx --image=nginx --dry-run=client -o yaml > deploy.yaml

9. Base64 (for Secrets)

bash
# Encode
echo -n "password" | base64

# Decode
echo "cGFzc3dvcmQ=" | base64 -d

# Decode secret
kubectl get secret db-creds -o jsonpath='{.data.password}' | base64 -d

10. Quick Reference

TaskCommand
Filter linesgrep pattern
Extract columnawk '{print $N}'
Replace textsed 's/old/new/g'
Skip headertail -n +2 or awk 'NR>1'
Count lineswc -l
Sort outputsort
Unique valuessort -u or sort | uniq
First N lineshead -n N
Last N linestail -n N
JSONPath-o jsonpath='{.field}'

Released under the MIT License.