---
title: "Kubernetes"
description: "Kubernetes is an open-source container orchestration platform for automating deployment, scaling, and management of containerized applications."
author: "Mohammad Abu Mattar"
canonical: https://mkabumattar.com/cheatsheets/kubernetes
---

# Kubernetes

Kubernetes is the de facto standard for container orchestration. It automates deployment, scaling, and management of containerized applications across clusters of machines. Configuration is declarative, and the control plane restarts failed containers on its own.

## Key features

- Deploys containers to nodes automatically
- Restarts failed containers and replaces unhealthy pods
- Distributes traffic across pod replicas
- Rolling updates that change application versions without downtime
- Quotas and limits to control cluster resource use
- Network policies, RBAC, and secret management
- DNS-based service discovery with load balancing
- Persistent and ephemeral storage orchestration

## Quick start

**Install kubectl**: Follow the Install and Configure kubectl section.

**Access cluster**: `kubectl cluster-info`

**Create deployment**: `kubectl create deployment web --image=nginx`

**List resources**: `kubectl get pods,svc,deployments`

**Check application status**: `kubectl describe deployment web`

## Common workflows

1. **Deploy Application**: Create Deployment with image, replicas, and resources
2. **Expose Service**: Create Service to access pods internally or externally
3. **Configure Access**: Set up Ingress or LoadBalancer for external traffic
4. **Monitor Health**: Check pod status, logs, and events regularly
5. **Update Application**: Use rolling updates or blue-green deployments
6. **Scale Load**: Adjust replicas manually or enable HPA for automatic scaling
7. **Debug Issues**: Examine logs, describe resources, execute debugging containers

The sections above cover pod management, deployments, services, storage, RBAC, and cluster operations.

## Getting Started

Core Kubernetes concepts and initial setup for beginners

### Kubernetes Basics

Introduction to Kubernetes architecture and core concepts

**Keywords:** kubernetes, container, orchestration, pods, clusters, nodes, master

#### Understand Kubernetes architecture

```bash
# Kubernetes architecture consists of:
# 1. Control Plane (Master): Manages cluster state and decisions
# 2. Worker Nodes: Run containerized applications
# 3. Pods: Smallest deployable units (wrappers around containers)
# 4. Services: Expose pods to network traffic
# 5. Storage: Persistent data storage for pods

# Analogy to VMs:
# Traditional: Cluster -> Node -> VM -> Application
# Kubernetes: Cluster -> Node -> Pod -> Container

# Key resources:
# - Pod: Single or multiple containers sharing network
# - Deployment: Manages pod replicas
# - Service: Network access to pods
# - ConfigMap: Configuration data
# - PersistentVolume: Storage resources
```

_exec_
```bash
kubectl cluster-info
```

_output_
```bash
Kubernetes control plane is running at https://127.0.0.1:6443
CoreDNS is running at https://127.0.0.1:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
```

Shows your Kubernetes cluster endpoints and components

- Requires kubectl and KUBECONFIG configured
- Control plane manages cluster operations
- Worker nodes run actual workloads

#### Check cluster nodes and capacity

```bash
# Get list of all nodes in cluster
kubectl get nodes

# Get detailed node information
kubectl get nodes -o wide

# View node resource capacities and allocations
kubectl top nodes

# Describe specific node
kubectl describe node node-1
```

_exec_
```bash
kubectl get nodes -o wide
```

_output_
```bash
NAME       STATUS   ROLES    AGE   VERSION   INTERNAL-IP   EXTERNAL-IP
minikube   Ready    master   10d   v1.24.0   192.168.1.1   <none>
```

Lists all nodes in your cluster with their status and information

- STATUS Ready means node is healthy and accepting workloads
- Roles indicate control plane vs worker nodes
- top requires metrics-server to be installed

#### Verify kubectl installation and context

```bash
# Check kubectl version
kubectl version --client

# View current context
kubectl config current-context

# List all available contexts
kubectl config get-contexts

# Switch to different context
kubectl config use-context docker-desktop

# Get cluster information
kubectl config view
```

_exec_
```bash
kubectl version --client
```

_output_
```bash
Client Version: v1.26.0
Kustomize Version: v4.5.4
```

Verifies kubectl installation and shows active cluster context

- Context determines which cluster kubectl connects to
- KUBECONFIG can contain multiple clusters
- Switch contexts for multi-cluster environments

**Best practices:**

- Understand cluster architecture before deploying applications
- Organize resources using namespaces for multi-team environments
- Monitor node capacity to prevent resource exhaustion

**Common errors:**

- **Unable to connect to the server**: Check KUBECONFIG, verify cluster availability with kubectl cluster-info

### Install and Configure kubectl

Set up kubectl CLI tool and configure cluster access

**Keywords:** install, kubectl, setup, kubeconfig, context

#### Install kubectl on Linux

```bash
# Download kubectl binary
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"

# Make it executable
chmod +x kubectl

# Move to PATH
sudo mv kubectl /usr/local/bin/

# Verify installation
kubectl version --client

# Using package manager (Ubuntu/Debian)
sudo apt-get update
sudo apt-get install -y kubectl
```

_exec_
```bash
kubectl version --client
```

_output_
```bash
Client Version: v1.26.0
Kustomize Version: v4.5.4
```

Installs kubectl CLI tool required for managing Kubernetes clusters

- Always download from official Kubernetes release repository
- Version should be within 1 minor version of cluster API

#### Configure kubectl with cloud clusters

```bash
# AWS EKS - Get cluster config
aws eks update-kubeconfig --region us-east-1 --name my-cluster

# Google GKE - Get cluster credentials
gcloud container clusters get-credentials my-cluster --zone us-central1-a

# Azure AKS - Get cluster credentials
az aks get-credentials --resource-group myResourceGroup --name myAKSCluster

# Verify kubectl can access cluster
kubectl cluster-info
```

_exec_
```bash
kubectl config view
```

_output_
```bash
apiVersion: v1
clusters:
- cluster:
    server: https://example.com
  name: my-cluster
contexts:
- context:
    cluster: my-cluster
    user: my-user
  name: my-context
```

Configures kubectl to access cloud-managed Kubernetes clusters

- Each cloud provider has specific commands for credential setup
- Kubeconfig stored in ~/.kube/config by default

#### Set up kubectl shell completion

```bash
# Bash completion
echo "source <(kubectl completion bash)" >> ~/.bashrc
source ~/.bashrc

# Zsh completion
echo "source <(kubectl completion zsh)" >> ~/.zshrc
source ~/.zshrc

# Fish completion
kubectl completion fish | source

# Temporary completion (current session)
source <(kubectl completion bash)
```

_exec_
```bash
kubectl completion bash
```

_output_
```bash
# bash completion for kubectl
_kubectl_complete() { ... }
```

Enables tab completion for kubectl commands in your shell

- Cuts typing for long resource names and flags
- Available for bash, zsh, fish, and powershell

**Best practices:**

- Install kubectl matching cluster version (±1 minor version)
- Use kubeconfig file for cluster authentication
- Enable shell completion for faster CLI navigation

**Common errors:**

- **unknown command**: Confirm kubectl is in PATH with `which kubectl`

### Namespaces and Basic Navigation

Organize resources using namespaces and navigate clusters

**Keywords:** namespace, organize, isolation, multi-tenant

#### Explore and create namespaces

```bash
# List all namespaces
kubectl get namespaces

# Create new namespace
kubectl create namespace development

# Create namespace with YAML
kubectl apply -f - <<EOF
apiVersion: v1
kind: Namespace
metadata:
  name: production
EOF

# Get default namespaces
# default - for user workloads
# kube-system - for system components
# kube-public - world-readable resources
# kube-node-lease - node heartbeats
```

_exec_
```bash
kubectl get ns
```

_output_
```bash
NAME              STATUS   AGE
default           Active   10d
kube-system       Active   10d
kube-public       Active   10d
kube-node-lease   Active   10d
```

Lists and creates Kubernetes namespaces for resource organization

- Default namespace is used if not specified
- Namespaces isolate resources within same cluster
- Good for multi-team or multi-environment setups

#### Set default namespace and switch between them

```bash
# Set permanent default namespace
kubectl config set-context --current --namespace=development

# View current namespace
kubectl config view --minify --output=jsonpath='{..namespace}'

# View resources in specific namespace
kubectl get pods --namespace=production
kubectl get pods -n production  # short form

# Switch context with different namespace
kubectl config use-context dev-context
```

_exec_
```bash
kubectl config set-context --current --namespace=default
```

_output_
```bash
Context "minikube" modified.
```

Sets default namespace for kubectl commands without -n flag

- Default context is stored in ~/.kube/config
- -n flag overrides default namespace per command

#### View all resources across namespaces

```bash
# List pods across all namespaces
kubectl get pods --all-namespaces
kubectl get pods -A  # short form

# View services across all namespaces
kubectl get svc -A

# Get all resources in all namespaces
kubectl get all -A

# Describe resource in specific namespace
kubectl describe pod my-pod -n production
```

_exec_
```bash
kubectl get pods -A
```

_output_
```bash
NAMESPACE     NAME                             READY   STATUS    RESTARTS
default       nginx-pod                        1/1     Running   0
kube-system   coredns-64897fb6d9-x8z5k         1/1     Running   0
production    app-deployment-abc123-xyz789     1/1     Running   1
```

Lists resources across all namespaces for cluster-wide visibility

- -A flag is equivalent to --all-namespaces
- Useful for troubleshooting across entire cluster

**Best practices:**

- Use namespaces for environment separation (dev, staging, prod)
- Apply RBAC policies per namespace for security
- Set default namespace in kubeconfig to reduce flag typing

**Common errors:**

- **pods not found in default namespace**: Check active namespace with kubectl config view or specify -n flag

## Cluster Management

Manage cluster configuration, nodes, resources, and monitoring

### Cluster Context and Configuration

Manage multiple clusters and kubeconfig contexts

**Keywords:** context, kubeconfig, configuration, cluster, authentication

#### Manage kubeconfig contexts and clusters

```bash
# View all contexts and clusters
kubectl config get-contexts
kubectl config get-clusters

# Get current context
kubectl config current-context

# Switch to different context
kubectl config use-context another-cluster

# Create new context
kubectl config set-context production --cluster=prod-cluster --user=prod-user

# Delete context
kubectl config delete-context old-context
```

_exec_
```bash
kubectl config get-contexts
```

_output_
```bash
CURRENT   NAME              CLUSTER         AUTHINFO        NAMESPACE
*         minikube          minikube        minikube        default
          docker-desktop    docker-desktop  docker-desktop  default
          kind-cluster1     kind-cluster1   kind-cluster1   default
```

Shows all available contexts and allows switching between clusters

- Context combines cluster, user, and namespace information
- * indicates current context

#### Configure cluster authentication

```bash
# Set cluster details
kubectl config set-cluster my-cluster \
  --server=https://kubernetes.example.com:6443 \
  --certificate-authority=/path/to/ca.crt

# Set user authentication
kubectl config set-credentials my-user \
  --client-certificate=/path/to/client.crt \
  --client-key=/path/to/client.key

# Create context binding user to cluster
kubectl config set-context my-context \
  --cluster=my-cluster \
  --user=my-user \
  --namespace=default

# Verify configuration
kubectl config view
```

_exec_
```bash
kubectl config view
```

_output_
```bash
apiVersion: v1
clusters:
- cluster:
    server: https://kubernetes.example.com:6443
users:
- name: my-user
contexts:
- context:
    cluster: my-cluster
    user: my-user
```

Manually configure cluster, user, and context settings

- Certificates can be base64-encoded in kubeconfig
- kubectl config view shows merged configuration

#### Merge kubeconfig files and manage credentials

```bash
# View kubeconfig location
echo $KUBECONFIG

# Merge multiple kubeconfig files
export KUBECONFIG=~/.kube/config:~/.kube/prod-config:/tmp/temp-config
kubectl config view --merge

# Flatten kubeconfig (consolidate into single file)
kubectl config view --flatten > ~/.kube/consolidated-config

# Set KUBECONFIG permanently
echo "export KUBECONFIG=$HOME/.kube/config" >> ~/.bashrc

# Verify current kubeconfig
kubectl config view --minify
```

_exec_
```bash
echo $KUBECONFIG
```

_output_
```bash
/home/user/.kube/config
```

Manage multiple kubeconfig files for different clusters

- Multiple KUBECONFIG files are separated by colon (:)
- Useful for managing dev, staging, and production clusters

**Best practices:**

- Organize kubeconfig for easy context switching
- Use meaningful names for contexts (e.g., prod-us-east)
- Limit kubeconfig credentials to necessary clusters

**Common errors:**

- **current-context is not set**: Set default context with kubectl config use-context

### Cluster Information and Monitoring

Monitor cluster health, resources, and component status

**Keywords:** cluster-info, monitoring, metrics, health, status

#### Check cluster health and component status

```bash
# Get cluster information
kubectl cluster-info

# Get system components (requires metrics-server)
kubectl get componentstatuses

# Check API server and cluster version
kubectl api-versions

# List all API resources available
kubectl api-resources

# View cluster details
kubectl describe cluster
```

_exec_
```bash
kubectl cluster-info
```

_output_
```bash
Kubernetes control plane is running at https://127.0.0.1:6443
CoreDNS is running at https://127.0.0.1:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
```

Shows running components and their endpoints

- Confirms kubectl can reach the cluster
- Dump shows more detailed debug information

#### Monitor node resources and health

```bash
# List nodes with resource information
kubectl get nodes --show-labels

# Get node resource usage
kubectl top nodes

# Describe specific node for details
kubectl describe node minikube

# Check node logs (requires SSH or specific monitoring)
kubectl logs -f -n kube-system --tail=50 <pod-name>

# Get node conditions
kubectl get nodes -o jsonpath='{.items[*].status.conditions}' | jq .
```

_exec_
```bash
kubectl top nodes
```

_output_
```bash
NAME       CPU(cores)   CPU%   MEMORY(Mi)   MEMORY%
minikube   245m         12%    1234Mi       32%
```

Shows CPU and memory usage for all cluster nodes

- Requires metrics-server installed for top command
- CPU in millicores, memory in megabytes

#### Check persistent volume and storage status

```bash
# List persistent volumes
kubectl get pv

# List persistent volume claims
kubectl get pvc --all-namespaces

# Check storage classes
kubectl get storageclass

# Describe specific PV
kubectl describe pv pv-name

# Check PVC status
kubectl describe pvc pvc-name -n namespace
```

_exec_
```bash
kubectl get pv
```

_output_
```bash
NAME       CAPACITY   ACCESS MODES   RECLAIM   STATUS   CLAIM
pv-001     10Gi       RWO            Delete    Bound    ns/pvc-001
```

Lists persistent storage resources in the cluster

- PV is cluster-level, PVC is namespace-level
- Status should be Bound for normal operation

**Best practices:**

- Monitor node capacity regularly to avoid resource exhaustion
- Keep system components healthy in kube-system namespace
- Set up resource monitoring with Prometheus or similar

**Common errors:**

- **metrics not available**: Install metrics-server with kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

### Node and Resource Management

Manage cluster nodes, taints, and resource quotas

**Keywords:** node, taint, toleration, resource-quota, drain, cordon

#### Cordon and drain nodes for maintenance

```bash
# Cordon node (prevent new pods from scheduling)
kubectl cordon node-1

# Drain node (evict all pods safely)
kubectl drain node-1 --ignore-daemonsets --delete-emptydir-data

# Uncordon node (allow scheduling again)
kubectl uncordon node-1

# Check node status
kubectl get nodes
kubectl describe node node-1
```

_exec_
```bash
kubectl get nodes
```

_output_
```bash
NAME       STATUS                     ROLES   AGE
node-1     Ready,SchedulingDisabled   <none>  10d
node-2     Ready                      <none>  10d
```

Safely cordons and drains nodes for maintenance

- SchedulingDisabled status indicates cordoned node
- Drain evicts pods so they shut down gracefully

#### Add and remove node taints

```bash
# Add taint to node (prevents scheduling unless tolerated)
kubectl taint nodes node-1 key=value:NoSchedule

# Add effect types:
# NoSchedule - new pods won't be scheduled
# NoExecute - existing pods will be evicted
# PreferNoSchedule - prefer not to schedule but may

# Remove taint from node
kubectl taint nodes node-1 key=value:NoSchedule-

# View node taints
kubectl describe node node-1 | grep Taints
```

_exec_
```bash
kubectl describe node node-1 | grep Taints
```

_output_
```bash
Taints: gpu=true:NoSchedule
```

Adds and removes taints to control pod scheduling

- Pods need matching tolerations to schedule on tainted nodes
- Common for GPU nodes or specialized hardware

#### Set resource quotas and limits per namespace

```bash
# Create resource quota for namespace
kubectl create quota myrquota --hard=pods=10,cpu=3,memory=10Gi -n development

# View resource quotas
kubectl get resourcequota -n development

# Describe quota details
kubectl describe resourcequota myrquota -n development

# Create with YAML for more control
kubectl apply -f - <<EOF
apiVersion: v1
kind: ResourceQuota
metadata:
  name: compute-quota
  namespace: development
spec:
  hard:
    requests.cpu: "10"
    requests.memory: "20Gi"
    limits.cpu: "20"
    limits.memory: "40Gi"
EOF
```

_exec_
```bash
kubectl get resourcequota -A
```

_output_
```bash
NAMESPACE    NAME         AGE   REQUEST.CPU   REQUESTMEMORY
development  myrquota     5d    500m / 3      2Gi / 10Gi
```

Sets resource limits for namespaces to prevent overallocation

- Quotas prevent namespace from consuming excessive cluster resources
- Pods larger than quota cannot be created

**Best practices:**

- Drain nodes gracefully before maintenance or removal
- Use taints for specialized hardware (GPU, high-memory)
- Set resource quotas to prevent namespace resource hogging

**Common errors:**

- **cannot drain node, pods without controllers**: Use --force flag to forcefully remove pods (use with caution)

## Pod Management

Create, manage, inspect, and debug Kubernetes pods

### Creating and Listing Pods

Create pods imperatively and declaratively, list and filter them

**Keywords:** pod, create, run, yaml, manifest

#### Create pods imperatively with kubectl run

```bash
# Create simple pod from image
kubectl run nginx-pod --image=nginx

# Create pod with port mapping
kubectl run web --image=nginx --port=8080

# Create pod with resource requests/limits
kubectl run app --image=myapp --requests=cpu=100m,memory=128Mi --limits=cpu=500m,memory=512Mi

# Create pod with command
kubectl run busybox --image=busybox --command -- sleep 3600

# Create pod in specific namespace
kubectl run test-pod --image=alpine -n development

# Create pod and output YAML (dry-run)
kubectl run nginx-pod --image=nginx --dry-run=client -o yaml
```

_exec_
```bash
kubectl run test-pod --image=alpine --dry-run=client -o yaml
```

_output_
```bash
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  name: test-pod
spec:
  containers:
  - image: alpine
    name: test-pod
```

Creates pods using imperative kubectl run command

- Imperative approach is fast for quick testing
- Use dry-run to preview YAML before creating

#### Create pods declaratively with YAML manifests

```bash
# Create pod from YAML file
kubectl apply -f pod.yaml

# Create pod from inline YAML
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: web-pod
  namespace: default
  labels:
    app: web
spec:
  containers:
  - name: nginx
    image: nginx:latest
    ports:
    - containerPort: 80
    resources:
      requests:
        cpu: 100m
        memory: 128Mi
      limits:
        cpu: 500m
        memory: 512Mi
  - name: sidecar
    image: busybox
    command: ['sleep', '3600']
EOF

# Verify pod creation
kubectl get pods
```

_exec_
```bash
kubectl get pods
```

_output_
```bash
NAME      READY   STATUS    RESTARTS   AGE
web-pod   2/2     Running   0          2m
```

Creates pods using declarative YAML manifests

- Declarative approach is preferred for reproducibility
- YAML files can be version controlled
- Multiple containers can run in same pod

#### List and filter pods

```bash
# List pods in current namespace
kubectl get pods

# List pods with detailed info
kubectl get pods -o wide

# List pods across all namespaces
kubectl get pods -A

# List pods with labels
kubectl get pods --show-labels

# Filter pods by label
kubectl get pods -l app=web

# Filter by multiple labels
kubectl get pods -l app=web,tier=frontend

# List pods with custom columns
kubectl get pods -o custom-columns=NAME:metadata.name,STATUS:status.phase,IP:status.podIP
```

_exec_
```bash
kubectl get pods -o wide
```

_output_
```bash
NAME      STATUS   IP           NODE      NOMINATED
web-pod   Running  10.244.0.5   minikube  <none>
```

Lists pods with various filtering and output options

- Default shows only current namespace
- -o flag controls output format (json, yaml, custom-columns)

**Best practices:**

- Use Deployments instead of bare Pods for production
- Define resource requests and limits on all containers
- Use labels for organizing and filtering pods

**Common errors:**

- **pods are forbidden**: Check RBAC permissions with kubectl auth can-i get pods

### Inspecting and Debugging Pods

Describe, view logs, and debug pod issues

**Keywords:** describe, logs, events, debug, troubleshot

#### Describe pods and view details

```bash
# Get basic information about pod
kubectl get pod web-pod

# Get detailed pod information
kubectl describe pod web-pod

# View pod definition in YAML
kubectl get pod web-pod -o yaml

# View pod in JSON format
kubectl get pod web-pod -o json

# Extract specific fields with JSONPath
kubectl get pod web-pod -o jsonpath='{.status.phase}'
kubectl get pod web-pod -o jsonpath='{.spec.containers[0].image}'
```

_exec_
```bash
kubectl describe pod web-pod
```

_output_
```bash
Name:         web-pod
Namespace:    default
Status:       Running
IP:           10.244.0.5
Containers:
  nginx:
    Image: nginx:latest
  State: Running
```

Shows detailed pod information including events and status

- describe shows useful events and error messages
- Events help identify why pods fail to start

#### View pod logs and stream output

```bash
# View logs from pod
kubectl logs web-pod

# View logs from specific container in multi-container pod
kubectl logs web-pod -c nginx

# Stream logs in real-time
kubectl logs -f web-pod

# View logs from previous container (crashed pods)
kubectl logs web-pod --previous

# Show logs with timestamps
kubectl logs web-pod --timestamps=true

# Tail last 50 lines
kubectl logs web-pod --tail=50

# View logs from deployment pods
kubectl logs -l app=web --max-log-requests=10
```

_exec_
```bash
kubectl logs web-pod --tail=20
```

_output_
```bash
192.168.1.1 - - [28/Feb/2025:10:30:00] "GET / HTTP/1.1" 200 612
192.168.1.2 - - [28/Feb/2025:10:30:01] "GET /index.html HTTP/1.1" 200 612
```

Shows container logs for debugging application issues

- -f flag tails logs in real-time like tail -f
- --previous shows logs from before container restart

#### Interactive debugging and shell access

```bash
# Execute command in running pod
kubectl exec web-pod -- ls -la

# Get interactive shell in pod
kubectl exec -it web-pod -- /bin/bash
kubectl exec -it web-pod -- /bin/sh

# Execute command in specific container
kubectl exec -it web-pod -c nginx -- /bin/bash

# Run debugging sidecar in pod
kubectl debug web-pod -it --image=busybox

# Copy files from pod
kubectl cp web-pod:/var/www/html/index.html ./index.html
# Copy files to pod
kubectl cp ./config.yaml web-pod:/etc/config.yaml
```

_exec_
```bash
kubectl exec -it web-pod -- hostname
```

_output_
```bash
web-pod
```

Executes commands and provides shell access to running pods

- -i flag keeps stdin open, -t allocates tty
- Useful for runtime troubleshooting and inspection

**Best practices:**

- Always check describe and events first when debugging
- Use logs to find application errors and issues
- Create debug containers instead of modifying production pods

**Common errors:**

- **command not found in container**: Check if base image has the command (alpine lacks some utilities)

### Deleting and Cleaning Up Pods

Delete pods and manage pod lifecycle

**Keywords:** delete, remove, cleanup, termination, grace-period

#### Delete single and multiple pods

```bash
# Delete single pod
kubectl delete pod web-pod

# Delete multiple pods by name
kubectl delete pod web-pod app-pod db-pod

# Delete all pods in namespace
kubectl delete pods --all

# Delete all pods in all namespaces
kubectl delete pods -A --all

# Delete with confirmation
kubectl delete pod web-pod  # will prompt for confirmation
```

_exec_
```bash
kubectl delete pod web-pod
```

_output_
```bash
pod "web-pod" deleted
```

Deletes pods from the cluster

- Delete operations are immediate (use graceful termination)
- Bare pods are not recreated; use Deployments for self-healing

#### Graceful pod termination and force delete

```bash
# Delete with grace period (seconds to shutdown cleanly)
kubectl delete pod web-pod --grace-period=30

# Force delete immediately (no grace period)
kubectl delete pod web-pod --grace-period=0 --force

# Delete using label selector
kubectl delete pods -l app=web

# Delete using field selector
kubectl delete pods --field-selector=status.phase=Failed

# Check termination status during deletion
kubectl get pod web-pod --watch
```

_exec_
```bash
kubectl delete pod web-pod --grace-period=10
```

_output_
```bash
pod "web-pod" deleted
```

Gracefully terminates pods with shutdown timeout

- Default grace period is 30 seconds
- Pod has time to close connections and save state

**Best practices:**

- Let Deployments manage pod deletion instead of manual deletion
- Use graceful termination for stateful applications
- Clean up resources regularly to save cluster resources

**Common errors:**

- **the server doesn't have a resource type**: Check spelling of resource type (e.g., Pod vs pod)

## Deployment Management

Deploy applications, manage replicas, and perform rolling updates

### Creating Deployments

Create deployments imperatively and declaratively

**Keywords:** deployment, create, replicas, selector, template

#### Create deployments imperatively

```bash
# Create deployment from image
kubectl create deployment web --image=nginx

# Create deployment with replicas
kubectl create deployment web --image=nginx --replicas=3

# Create deployment and save YAML
kubectl create deployment web --image=nginx --dry-run=client -o yaml > web-deployment.yaml

# Create deployment with port
kubectl run web --image=nginx --port=80 --replicas=3

# Verify deployment creation
kubectl get deployments
kubectl get pods
```

_exec_
```bash
kubectl create deployment web --image=nginx --replicas=3
```

_output_
```bash
deployment.apps/web created
```

Creates deployments using imperative kubectl commands

- create is imperative, while apply is declarative
- Deployments automatically create ReplicaSet

#### Create deployments with YAML manifests

```bash
# Create deployment from YAML
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-deployment
  labels:
    app: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: nginx
        image: nginx:1.21
        ports:
        - containerPort: 80
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 500m
            memory: 512Mi
        livenessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 30
          periodSeconds: 10
EOF

# List deployments
kubectl get deployments
```

_exec_
```bash
kubectl get deployments -o wide
```

_output_
```bash
NAME             READY   UP-TO-DATE   AVAILABLE   AGE
web-deployment   3/3     3            3           2m
```

Creates deployments declaratively with full control

- YAML approach is reproducible and version-controllable
- spec.replicas defines number of pod replicas
- selector must match template labels

#### Create deployments with health checks

```bash
# Create deployment with liveness and readiness probes
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: app
  template:
    metadata:
      labels:
        app: app
    spec:
      containers:
      - name: app
        image: myapp:v1
        ports:
        - containerPort: 8080
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /ready
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5
EOF
```

_exec_
```bash
kubectl describe deployment app-deployment
```

_output_
```bash
Name:                   app-deployment
Replicas:               2 desired | 2 updated | 2 ready
Strategy:               RollingUpdate
```

Creates deployments with health checks for better reliability

- Liveness probe restarts unhealthy containers
- Readiness probe controls traffic to pods

**Best practices:**

- Use deployments for stateless applications
- Always define resource requests and limits
- Include health checks for reliability

**Common errors:**

- **invalid value for selector**: Make the label selector match the pod labels exactly

### Scaling Deployments

Scale deployments up and down dynamically

**Keywords:** scale, replicas, hpa, autoscale, load

#### Manually scale deployments

```bash
# Get deployment info
kubectl get deployments

# Scale deployment to 5 replicas
kubectl scale deployment web-deployment --replicas=5

# Scale multiple deployments
kubectl scale deployment web-deployment app-deployment --replicas=3

# Verify scaling
kubectl get deployments
kubectl get pods

# Scale down to 0 (stop deployment)
kubectl scale deployment web-deployment --replicas=0
```

_exec_
```bash
kubectl scale deployment web-deployment --replicas=5
```

_output_
```bash
deployment.apps/web-deployment scaled
```

Scales deployments manually by changing replica count

- Scaling is immediate
- Previous pods will be terminated gracefully

#### Set up horizontal pod autoscaling

```bash
# Create HPA imperatively
kubectl autoscale deployment web-deployment --min=1 --max=10 --cpu-percent=80

# View HPA status
kubectl get hpa

# Describe HPA details
kubectl describe hpa web-deployment

# Create HPA with YAML for more control
kubectl apply -f - <<EOF
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: web-hpa
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: web-deployment
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 80
EOF
```

_exec_
```bash
kubectl get hpa
```

_output_
```bash
NAME          REFERENCE                  TARGETS   MINPODS  MAXPODS
web-hpa       Deployment/web-deployment  45%/80%   2        10
```

Sets up automatic scaling based on metrics

- Requires metrics-server for CPU/memory metrics
- HPA v2 supports custom metrics

#### Monitor scaling events and history

```bash
# Monitor scaling in real-time
kubectl get hpa --watch

# Check HPA events
kubectl describe hpa web-hpa

# View scaling history
kubectl get events --field-selector involvedObject.name=web-deployment

# Check deployment history
kubectl rollout history deployment web-deployment
```

_exec_
```bash
kubectl get hpa --watch
```

_output_
```bash
NAME      REFERENCE             TARGETS   MINPODS  MAXPODS  REPLICAS  AGE
web-hpa   Deployment/web-deploy 88%/80%   2        10       8         3m
```

Monitors horizontal pod autoscaling events

- HPA cooldown prevents rapid scaling churn
- Monitor targets to verify autoscaling behavior

**Best practices:**

- Set appropriate min/max replicas to prevent excessive scaling
- Use HPA for variable load applications (web servers)
- Monitor metrics to tune autoscaling thresholds

**Common errors:**

- **unable to compute replica count**: Check that metrics-server is running and reporting metrics

### Updating and Rolling Back Deployments

Update application versions and manage rollouts

**Keywords:** update, rollout, rollback, strategy, revision

#### Update deployment images

```bash
# Update image in deployment
kubectl set image deployment/web-deployment nginx=nginx:1.22

# Update multiple containers
kubectl set image deployment/app app=myapp:v2 sidecar=sidecar:v1 --record

# Update from file
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-deployment
spec:
  template:
    spec:
      containers:
      - name: nginx
        image: nginx:1.22
EOF

# Watch rollout progress
kubectl rollout status deployment/web-deployment
```

_exec_
```bash
kubectl set image deployment/web-deployment nginx=nginx:1.22
```

_output_
```bash
deployment.apps/web-deployment image updated
```

Updates deployment image to new version

- Triggers rolling update by default
- Old pods are gradually replaced with new version

#### Perform rolling updates and monitor progress

```bash
# Apply updated deployment
kubectl apply -f web-deployment.yaml

# Watch rollout status
kubectl rollout status deployment/web-deployment

# Check rollout history
kubectl rollout history deployment/web-deployment

# View specific revision details
kubectl rollout history deployment/web-deployment --revision=2

# Pause rollout if issues detected
kubectl rollout pause deployment/web-deployment

# Resume paused rollout
kubectl rollout resume deployment/web-deployment
```

_exec_
```bash
kubectl rollout status deployment/web-deployment
```

_output_
```bash
deployment "web-deployment" successfully rolled out
```

Monitors and controls rolling update process

- Pause allows verification before continuing update
- History shows all previous revisions

#### Rollback deployments to previous versions

```bash
# Rollback to previous revision
kubectl rollout undo deployment/web-deployment

# Rollback to specific revision
kubectl rollout undo deployment/web-deployment --to-revision=2

# Check rollback status
kubectl rollout status deployment/web-deployment

# Verify rollback with describe
kubectl describe deployment web-deployment

# Check pod images to confirm rollback
kubectl get pods -o wide
```

_exec_
```bash
kubectl rollout undo deployment/web-deployment
```

_output_
```bash
deployment.apps/web-deployment rolled back
```

Reverts deployment to previous working version

- Undo creates new ReplicaSet with old version
- Useful for quick recovery from bad deployments

**Best practices:**

- Use image tags (not latest) for tracking versions
- Test updates in staging before production
- Keep revision limit to manage history

**Common errors:**

- **no change**: New image must be different from current (use new tag)

## Service & Ingress

Expose applications with Services and Ingress

### Creating Services

Expose pods with ClusterIP, NodePort, and LoadBalancer services

**Keywords:** service, expose, clusterip, nodeport, loadbalancer

#### Create services imperatively

```bash
# Expose deployment as ClusterIP service
kubectl expose deployment web-deployment --type=ClusterIP --port=80

# Expose as NodePort service
kubectl expose deployment web-deployment --type=NodePort --port=80 --target-port=8080

# Expose as LoadBalancer service
kubectl expose deployment web-deployment --type=LoadBalancer --port=80

# List created services
kubectl get svc

# Get service details
kubectl describe svc web-deployment
```

_exec_
```bash
kubectl expose deployment web-deployment --type=ClusterIP --port=80
```

_output_
```bash
service/web-deployment exposed
```

Creates services to expose deployments within or outside cluster

- ClusterIP: internal only
- NodePort: accessible on node IP
- LoadBalancer: managed external IP

#### Create services with YAML

```bash
# Create ClusterIP service
kubectl apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  type: ClusterIP
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP
EOF

# Create NodePort service
kubectl apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
  name: web-nodeport
spec:
  type: NodePort
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 8080
    nodePort: 30080
EOF

# Create LoadBalancer service
kubectl apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
  name: web-lb
spec:
  type: LoadBalancer
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 8080
EOF
```

_exec_
```bash
kubectl get svc
```

_output_
```bash
NAME          TYPE        CLUSTER-IP  PORT(S)
web-service   ClusterIP   10.0.0.1    80/TCP
```

Creates services declaratively with full control

- selector determines which pods receive traffic
- targetPort is container port, port is service port

#### List and inspect services

```bash
# List services
kubectl get svc

# List in all namespaces
kubectl get svc -A

# Get service endpoints
kubectl get endpoints

# Describe service details
kubectl describe svc web-service

# Get service YAML
kubectl get svc web-service -o yaml

# Watch for external IP (LoadBalancer)
kubectl get svc -w
```

_exec_
```bash
kubectl get svc -o wide
```

_output_
```bash
NAME          TYPE       SELECTOR   IP         EXTERNAL-IP
web-service   ClusterIP  app=web    10.0.0.1   <none>
```

Lists services and their endpoints

- Endpoints show which pods the service routes to
- EXTERNAL-IP may take time for LoadBalancer type

**Best practices:**

- Use ClusterIP initially, add external access only when needed
- Avoid NodePort in production; use LoadBalancer or Ingress
- Use label selectors to control pod membership

**Common errors:**

- **service not found/no endpoints**: Check selector matches pod labels with kubectl get pods --show-labels

### Setting up Ingress

Configure Ingress for HTTP/HTTPS routing

**Keywords:** ingress, routing, hostname, tls, ingress-controller

#### Create basic Ingress routes

```bash
# Create simple path-based Ingress
kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web-ingress
spec:
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80
EOF

# List ingresses
kubectl get ingress

# Get Ingress IP address
kubectl get ingress -o wide
```

_exec_
```bash
kubectl get ingress
```

_output_
```bash
NAME          CLASS   HOSTS   ADDRESS       PORTS
web-ingress   nginx   *       192.168.1.1   80
```

Creates basic Ingress for routing HTTP traffic

- Requires Ingress Controller (nginx, traefik, etc.)
- Address is Ingress Controller's IP

#### Configure hostname-based routing

```bash
# Create host-based Ingress
kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web-ingress
spec:
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80
  - host: api.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 8080
EOF
```

_exec_
```bash
kubectl describe ingress web-ingress
```

_output_
```bash
Name:             web-ingress
Rules:
  Host            Path Backends
  example.com     /    web-service:80
  api.example.com /    api-service:8080
```

Routes different hosts to different services

- Requires DNS pointing to Ingress IP
- Multiple rules for VHOST configuration

#### Configure TLS termination with Ingress

```bash
# Create TLS secret
kubectl create secret tls web-tls --cert=cert.pem --key=key.pem

# Create Ingress with TLS
kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web-ingress-tls
spec:
  tls:
  - hosts:
    - example.com
      secretName: web-tls
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80
EOF

# Verify TLS setup
kubectl describe ingress web-ingress-tls
```

_exec_
```bash
kubectl get secrets
```

_output_
```bash
NAME       TYPE                DATA   AGE
web-tls    kubernetes.io/tls   2      3m
```

Configures HTTPS/TLS termination for Ingress

- TLS certificate stored as Secret
- Ingress Controller terminates SSL

**Best practices:**

- Use Ingress for HTTP/HTTPS routing instead of NodePort
- Enable TLS for production Ingresses
- Use cert-manager with Let's Encrypt for automatic certificates

**Common errors:**

- **no ingress controller found**: Install Ingress Controller (nginx, traefik) first

### Port Forwarding and Debugging

Forward local ports to cluster resources for debugging

**Keywords:** port-forward, localhost, debug, testing

#### Forward local port to pod

```bash
# Forward local to pod
kubectl port-forward pod/web-pod 8000:80

# Forward with background process
kubectl port-forward pod/web-pod 8000:80 &

# Forward to specific pod in deployment
kubectl port-forward deployment/web-deployment 8000:80

# Forward with address binding
kubectl port-forward pod/web-pod 127.0.0.1:8000:80

# Forward random local port
kubectl port-forward pod/web-pod :80
```

_exec_
```bash
kubectl port-forward pod/web-pod 8000:80 &
```

_output_
```bash
Forwarding from 127.0.0.1:8000 -> 80
Forwarding from [::1]:8000 -> 80
```

Creates local port forward to pod

- Access pod at localhost:8000 from host
- Useful for testing without exposing service

#### Access services through port forwarding

```bash
# Forward to service
kubectl port-forward service/web-service 8000:80

# Forward to service in specific namespace
kubectl port-forward -n production service/db-service 5432:5432

# Forward multiple ports
kubectl port-forward pod/app 8000:8000 8080:8080

# Kill port forward
# Use Ctrl+C or kill process
ps aux | grep port-forward
kill <pid>
```

_exec_
```bash
kubectl port-forward service/web-service 8000:80
```

_output_
```bash
Forwarding from 127.0.0.1:8000 -> 80
```

Forwards to Service which routes to backend pods

- Service provides load balancing across pods
- Random pod is selected if multiple exist

**Best practices:**

- Use port-forward for temporary debugging only
- Use Services for permanent application access
- Close port-forward when done to free local ports

**Common errors:**

- **address already in use**: Kill existing process with same port or use different port

## Storage Management

Manage persistent storage with volumes and storage classes

### Persistent Volumes and Claims

Create and manage persistent storage

**Keywords:** pv, pvc, volume, storage, persistence

#### Create persistent volumes and claims

```bash
# Create Persistent Volume
kubectl apply -f - <<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-001
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: manual
  hostPath:
    path: /data/pv-001
EOF

# Create Persistent Volume Claim
kubectl apply -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-001
  namespace: default
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: manual
  resources:
    requests:
      storage: 5Gi
EOF

# List PVs and PVCs
kubectl get pv
kubectl get pvc
```

_exec_
```bash
kubectl get pv,pvc
```

_output_
```bash
NAME     CAPACITY  ACCESSMODES  STATUS   CLAIM
pv-001   10Gi      RWO          Bound    default/pvc-001
```

Creates persistent storage volumes and claims

- PV is cluster resource, PVC is namespace resource
- Status Bound means PVC successfully claimed PV

#### Use volumes in pod specifications

```bash
# Create pod with PVC volume
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: data-app
spec:
  containers:
  - name: app
    image: busybox
    command: ['sleep', '3600']
    volumeMounts:
    - name: data-volume
      mountPath: /data
  volumes:
  - name: data-volume
    persistentVolumeClaim:
      claimName: pvc-001
EOF

# Verify PVC is mounted
kubectl get pod data-app -o yaml | grep -A5 volumes
```

_exec_
```bash
kubectl describe pod data-app | grep -A5 Mounts
```

_output_
```bash
Mounts:
  /data from data-volume (rw)
```

Mounts persistent volume in pod using PVC

- mountPath is where volume appears in container
- Volume must exist or pod will not start

#### Manage storage lifecycle

```bash
# Check PVC details
kubectl describe pvc pvc-001

# View PV details
kubectl describe pv pv-001

# Delete PVC
kubectl delete pvc pvc-001

# Delete PV
kubectl delete pv pv-001

# Check reclaim policy behavior
# - Retain: Keep PV after PVC deletion
# - Delete: Remove PV after PVC deletion
# - Recycle: Clear PV data (deprecated)
```

_exec_
```bash
kubectl describe pvc pvc-001
```

_output_
```bash
Name:          pvc-001
Status:        Bound
Volume:        pv-001
Capacity:      5Gi
```

Manages PV/PVC lifecycle and reclamation policies

- Reclaim policy determines what happens after PVC deletion
- Retain preserves data for manual recovery

**Best practices:**

- Use StorageClass for dynamic provisioning instead of manual PVs
- Set appropriate reclaim policies for your use case
- Monitor storage usage to prevent disk full

**Common errors:**

- **pod does not have permission to access volume**: Check volume access mode (RWO, RWX) and pod selector

### Storage Classes and Dynamic Provisioning

Use storage classes for dynamic volume provisioning

**Keywords:** storageclass, provisioner, dynamic, dynamic-provisioning

#### Create and list storage classes

```bash
# Create storage class
kubectl apply -f - <<EOF
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast-storage
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp3
  iops: "3000"
  throughput: "125"
reclaimPolicy: Delete
allowVolumeExpansion: true
EOF

# List storage classes
kubectl get storageclass

# Set default storage class
kubectl patch storageclass fast-storage -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'
```

_exec_
```bash
kubectl get storageclass
```

_output_
```bash
NAME           PROVISIONER             RECLAIMPOLICY
fast-storage   kubernetes.io/aws-ebs   Delete
```

Creates storage classes for automatic volume provisioning

- Provisioner depends on cloud provider
- Parameters vary by provisioner

#### Use storage class in PVC

```bash
# Create PVC using storage class
kubectl apply -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: app-storage
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: fast-storage
  resources:
    requests:
      storage: 50Gi
EOF

# Monitor dynamic PV creation
kubectl get pv -w
```

_exec_
```bash
kubectl get pvc
```

_output_
```bash
NAME          STATUS   VOLUME         CAPACITY
app-storage   Bound    pvc-abc123     50Gi
```

Automatically provisions PV when PVC is created

- Storage class provisioner automatically creates PV
- No need to manually create PV first

#### Expand persistent volumes

```bash
# Edit PVC to increase size
kubectl patch pvc app-storage -p '{"spec":{"resources":{"requests":{"storage":"100Gi"}}}}'

# Or edit directly
kubectl edit pvc app-storage

# Monitor expansion progress
kubectl describe pvc app-storage

# Verify expansion in pod
kubectl exec -it <pod> -- df /data
```

_exec_
```bash
kubectl describe pvc app-storage
```

_output_
```bash
Name:          app-storage
Capacity:      100Gi
```

Expands PVC size without downtime

- allowVolumeExpansion must be true in StorageClass
- Some filesystems require filesystem expansion in pod

**Best practices:**

- Use storage classes for dynamic provisioning
- Set default storage class for convenience
- Enable volume expansion for flexibility

**Common errors:**

- **provisioner not found**: Install the cloud provisioner (CSI driver) first

### Volume Types and EmptyDir

Use different volume types for various scenarios

**Keywords:** volume, emptydir, configmap, secret, hostpath

#### Use emptyDir and hostPath volumes

```bash
# Create pod with emptyDir and hostPath
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: app-with-volumes
spec:
  containers:
  - name: app
    image: nginx
    volumeMounts:
    - name: cache
      mountPath: /cache
    - name: host-data
      mountPath: /host-data
  volumes:
  - name: cache
    emptyDir: {}
  - name: host-data
    hostPath:
      path: /data
      type: Directory
EOF
```

_exec_
```bash
kubectl get pod app-with-volumes -o yaml
```

_output_
```bash
volumes:
- name: cache
  emptyDir: {}
```

Uses emptyDir for temporary storage and hostPath for node access

- emptyDir deleted when pod terminates
- hostPath accesses node filesystem

#### Mount ConfigMaps and Secrets as volumes

```bash
# Create ConfigMap
kubectl create configmap app-config --from-literal=key1=value1

# Create Secret
kubectl create secret generic app-secret --from-literal=password=secret

# Create pod mounting both
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: app-with-config
spec:
  containers:
  - name: app
    image: busybox
    command: ['sleep', '3600']
    volumeMounts:
    - name: config
      mountPath: /etc/config
    - name: secret
      mountPath: /etc/secrets
  volumes:
  - name: config
    configMap:
      name: app-config
  - name: secret
    secret:
      secretName: app-secret
EOF
```

_exec_
```bash
kubectl get configmap,secret
```

_output_
```bash
NAME                 DATA   AGE
configmap/app-config 1      2m
```

Mounts ConfigMaps and Secrets as volumes

- ConfigMap/Secret updates appear in mounted files
- Good for configuration without pod restart

**Best practices:**

- Use ConfigMap/Secret volumes for configuration
- Use emptyDir for temporary pod data
- Avoid hostPath in production (not portable)

**Common errors:**

- **volume not found**: Verify the ConfigMap or Secret exists under the name referenced

## Security & RBAC

Secure cluster with authentication, authorization, and policies

### RBAC Roles and Bindings

Control access with Roles and RoleBindings

**Keywords:** rbac, role, rolebinding, serviceaccount, permission

#### Create RBAC roles and bindings

```bash
# Create service account
kubectl create serviceaccount app-sa -n development

# Create role with permissions
kubectl apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
  namespace: development
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list", "watch"]
- apiGroups: [""]
  resources: ["pods/logs"]
  verbs: ["get"]
EOF

# Create role binding
kubectl apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pod-reader-binding
  namespace: development
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: pod-reader
subjects:
- kind: ServiceAccount
  name: app-sa
  namespace: development
EOF

# List RBAC resources
kubectl get roles,rolebindings -n development
```

_exec_
```bash
kubectl get serviceaccounts,roles,rolebindings -n development
```

_output_
```bash
NAME                     SECRETS   AGE
serviceaccount/app-sa    1         2m
NAME                 CREATED AT
role.rbac...pod-reader  2m
```

Creates RBAC roles and grants permissions to service accounts

- verbs define allowed actions (get, list, create, delete)
- apiGroups depend on resource type (empty = core API)

#### Create ClusterRoles for cluster-wide permissions

```bash
# Create cluster role
kubectl apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: node-reader
rules:
- apiGroups: [""]
  resources: ["nodes"]
  verbs: ["get", "list", "watch"]
- apiGroups: [""]
  resources: ["nodes/stats"]
  verbs: ["get"]
EOF

# Create cluster role binding
kubectl apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: node-reader-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: node-reader
subjects:
- kind: ServiceAccount
  name: monitoring-sa
  namespace: monitoring
EOF
```

_exec_
```bash
kubectl get clusterroles,clusterrolebindings
```

_output_
```bash
NAME                                           CREATED AT
clusterrole.rbac.../monitoring-binding     2m
```

Grants cluster-wide permissions across all namespaces

- ClusterRole is cluster-scoped, not namespace-scoped
- Use for cluster admins and system components

#### Check permissions and debug RBAC

```bash
# Check what user can do
kubectl auth can-i get pods -n development --as=system:serviceaccount:development:app-sa

# Check multiple permissions
kubectl auth can-i create deployments -n default
kubectl auth can-i delete pods -n default

# List all role bindings for user
kubectl get rolebinding,clusterrolebinding -A

# Describe role to see permissions
kubectl describe role pod-reader -n development
```

_exec_
```bash
kubectl auth can-i get pods --as=system:serviceaccount:development:app-sa
```

_output_
```bash
yes
```

Verifies RBAC permissions and troubleshoots access issues

- can-i helps verify permissions before assigning access
- Format: system:serviceaccount:namespace:name

**Best practices:**

- Follow least privilege principle (minimum needed permissions)
- Use namespace-scoped Roles instead of ClusterRole when possible
- Regularly audit and review RBAC configuration

**Common errors:**

- **forbidden - user cannot get pods**: Create appropriate Role/RoleBinding for the user

### Network Policies

Control network traffic with network policies

**Keywords:** networkpolicy, ingress, egress, network, traffic

#### Create network policies for traffic control

```bash
# Create deny-all network policy
kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: deny-all
  namespace: production
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
EOF

# Create allow policy for specific pods
kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-web-traffic
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: web
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          role: frontend
    ports:
    - protocol: TCP
      port: 80
EOF
```

_exec_
```bash
kubectl get networkpolicies -n production
```

_output_
```bash
NAME               POD-SELECTOR   AGE
deny-all           <none>         2m
allow-web-traffic  app=web        1m
```

Creates network policies to restrict traffic

- NetworkPolicy requires network plugin with support
- podSelector: {} matches all pods

#### Configure egress policies

```bash
# Allow specific egress traffic
kubectl apply -f - <<EOF
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-egress
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: api
  policyTypes:
  - Egress
  egress:
  - to:
    - podSelector:
        matchLabels:
          app: database
    ports:
    - protocol: TCP
      port: 5432
  - to:
    - namespaceSelector:
        matchLabels:
          name: kube-system
    ports:
    - protocol: UDP
      port: 53
EOF
```

_exec_
```bash
kubectl describe networkpolicy allow-egress -n production
```

_output_
```bash
Name:         allow-egress
Namespace:    production
Egress:
  To: app=database, port: 5432
```

Restricts outbound traffic from pods

- Egress allows specifying allowed destination pods
- DNS access usually required for pod-to-pod communication

**Best practices:**

- Start with deny-all policy, then add allowed traffic
- Use network policies to enforce security boundaries
- Test policies before production deployment

**Common errors:**

- **network policy not working**: Verify network plugin supports NetworkPolicy (Calico, Weave)

### Secrets and Secret Management

Securely store and manage sensitive data

**Keywords:** secret, sensitive, password, token, encryption

#### Create and manage secrets

```bash
# Create secret from literals
kubectl create secret generic db-secret \
  --from-literal=user=admin \
  --from-literal=password=secretpass

# Create secret from file
kubectl create secret generic app-config \
  --from-file=config.yaml

# Create docker registry secret
kubectl create secret docker-registry regcred \
  --docker-server=myregistry.com \
  --docker-username=user \
  --docker-password=pass

# List secrets
kubectl get secrets
```

_exec_
```bash
kubectl get secrets
```

_output_
```bash
NAME         TYPE                  DATA   AGE
db-secret    Opaque                2      2m
app-config   Opaque                1      1m
```

Creates secrets to store sensitive data

- Secrets are base64-encoded, not encrypted by default
- Consider using encryption at rest in production

#### Use secrets in pod specifications

```bash
# Create pod using secret as environment variables
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: app-with-secret
spec:
  containers:
  - name: app
    image: myapp
    env:
    - name: DB_USER
      valueFrom:
        secretKeyRef:
          name: db-secret
          key: user
    - name: DB_PASSWORD
      valueFrom:
        secretKeyRef:
          name: db-secret
          key: password
  imagePullSecrets:
  - name: regcred
EOF

# Verify secret is applied
kubectl describe pod app-with-secret
```

_exec_
```bash
kubectl get pod app-with-secret -o yaml
```

_output_
```bash
env:
- name: DB_USER
  valueFrom:
    secretKeyRef:
      name: db-secret
      key: user
```

Uses secrets as environment variables in pods

- imagePullSecrets for private registry authentication
- Secret data injected at runtime

#### View and update secrets

```bash
# View decoded secret
kubectl get secret db-secret -o jsonpath='{.data.password}' | base64 -d

# Edit secret
kubectl edit secret db-secret

# Delete secret
kubectl delete secret db-secret

# Get secret as YAML
kubectl get secret db-secret -o yaml
```

_exec_
```bash
kubectl describe secret db-secret
```

_output_
```bash
Name:         db-secret
Type:         Opaque
Data
user:    5 bytes
password: 10 bytes
```

Views and manages secrets

- Base64 decoding shows actual values
- Be careful with secret exposure in logs

**Best practices:**

- Use encrypted storage for secrets at rest
- Limit secret access with RBAC
- Rotate secrets regularly

**Common errors:**

- **secret not found**: Verify secret exists and is in same namespace

## Advanced Operations

Logging, debugging, resource management, and advanced queries

### Logging and Debugging

Collect and analyze logs for troubleshooting

**Keywords:** logs, debug, troubleshoot, events, tracing

#### Advanced logging and filtering

```bash
# Get logs from all containers in pod
kubectl logs pod-name --all-containers=true

# Get logs from previous pod instance
kubectl logs pod-name --previous

# Stream logs with timestamps
kubectl logs pod-name --timestamps=true -f

# Get logs from specific time range
kubectl logs pod-name --since=1h
kubectl logs pod-name --since-time='2025-02-28T10:00:00Z'

# Get logs from multiple pods
kubectl logs -f -l app=web --max-log-requests=10

# Tail specific number of lines
kubectl logs pod-name --tail=100
```

_exec_
```bash
kubectl logs -f pod-name --tail=50
```

_output_
```bash
2025-02-28T10:30:01.123Z INFO Starting application
2025-02-28T10:30:02.456Z INFO Connected to database
```

Gets detailed logs with filtering and streaming

- -f flag streams logs in real-time
- --previous useful for crashed containers

#### Describe and inspect resources for debugging

```bash
# Get full resource details
kubectl describe pod pod-name

# Get resource events
kubectl get events

# Watch resource for changes
kubectl get pods --watch

# Get events for specific resource
kubectl get events --field-selector involvedObject.name=pod-name

# Describe deployment to see replica status
kubectl describe deployment web-deployment

# Check resource conditions
kubectl get pod pod-name -o jsonpath='{.status.conditions}' | jq .
```

_exec_
```bash
kubectl describe pod pod-name
```

_output_
```bash
Name:         pod-name
Status:       Running
Conditions:
  Type    Status  Reason
  Ready   True    ContainersReady
```

Examines resource details and troubleshoots issues

- Events show resource state changes
- Conditions show readiness and health status

#### Advanced debugging with temporary containers

```bash
# Create debug container in running pod
kubectl debug pod-name -it --image=busybox

# Debug specific container
kubectl debug pod-name -c container-name -it --image=busybox

# Debug with node access
kubectl debug node/node-name -it --image=ubuntu

# Create copy of pod for debugging
kubectl debug pod-name -it --copy-to=debug-pod

# Share process namespace for debugging
kubectl debug pod-name --target=container-name
```

_exec_
```bash
kubectl debug pod-name -it --image=busybox
```

_output_
```bash
Debugger started, running in pod-name ephemeral-debug-xyz
/ #
```

Creates temporary debugging containers

- Debug containers have tools for troubleshooting
- Copy-to creates standalone pod for destructive testing

**Best practices:**

- Check logs first when diagnosing pod issues
- Use describe to view pod events and conditions
- Create debug containers instead of modifying production pods

**Common errors:**

- **not found**: Verify pod you're debugging still exists

### JSONPath Queries and Output Formatting

Extract specific data with JSONPath queries

**Keywords:** jsonpath, query, extract, formatting, filter

#### Extract data with JSONPath

```bash
# Get pod names
kubectl get pods -o jsonpath='{.items[*].metadata.name}'

# Get pod IPs
kubectl get pods -o jsonpath='{.items[*].status.podIP}'

# Get image names from deployment
kubectl get deployment web -o jsonpath='{.spec.template.spec.containers[*].image}'

# Get container names and images
kubectl get pods -o jsonpath='{.items[*].spec.containers[*].name}'

# Format output with custom columns
kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.phase}{"\n"}{end}'
```

_exec_
```bash
kubectl get pods -o jsonpath='{.items[*].metadata.name}'
```

_output_
```bash
pod1 pod2 pod3
```

Extracts specific fields using JSONPath syntax

- jsonpath extracts nested data
- Can combine with other tools like awk

#### Custom columns and wide output

```bash
# Define custom columns
kubectl get pods \
  -o custom-columns=NAME:.metadata.name,READY:.status.conditions[?(@.type=="Ready")].status,IMAGE:.spec.containers[0].image,IP:.status.podIP

# Format with custom columns shorthand
kubectl get pods --sort-by=.metadata.creationTimestamp

# Get pods with sorted output
kubectl get pods --sort-by='{.status.phase}'

# Wide format (standard custom columns)
kubectl get pods -o wide
```

_exec_
```bash
kubectl get pods -o custom-columns=NAME:.metadata.name,STATUS:.status.phase,IP:.status.podIP
```

_output_
```bash
NAME        STATUS    IP
pod1        Running   10.244.0.1
pod2        Running   10.244.0.2
```

Creates custom output columns for better readability

- Custom columns can format complex nested data
- Sorting by specific fields helps organize output

#### Complex JSONPath queries with filters

```bash
# Get pods that are currently running
kubectl get pods -o jsonpath='{.items[?(@.status.phase=="Running")].metadata.name}'

# Get pods with specific label
kubectl get pods -o jsonpath='{.items[?(@.metadata.labels.tier=="web")].metadata.name}'

# Get containers with specific resource requests
kubectl get pods -o jsonpath='{.items[?(@.spec.containers[0].resources.requests.cpu)].metadata.name}'

# Format with line breaks for readability
kubectl get pods -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.phase}{"\t"}{.status.podIP}{"\n"}{end}'
```

_exec_
```bash
kubectl get pods -o jsonpath='{.items[?(@.status.phase=="Running")].metadata.name}'
```

_output_
```bash
pod1 pod3
```

Filters resources based on conditions in JSONPath

- Filter expressions use @.field syntax
- Complex queries can extract specific information

**Best practices:**

- Use JSONPath for scripting and automation
- Custom columns improve readability of output
- Combine with grep/awk for further filtering

**Common errors:**

- **unable to parse query**: Check JSONPath syntax and verify field paths exist

### Dry-Run and Testing Patterns

Test changes before applying with dry-run

**Keywords:** dry-run, test, validation, preview, simulation

#### Preview changes with dry-run

```bash
# Preview pod creation
kubectl run test-pod --image=nginx --dry-run=client -o yaml

# Preview deployment creation
kubectl create deployment web --image=nginx --dry-run=server -o yaml

# Preview manifest application
kubectl apply -f deployment.yaml --dry-run=client

# Apply with server-side validation
kubectl apply -f deployment.yaml --dry-run=server

# Save dry-run output for review
kubectl apply -f - --dry-run=client -o yaml > deployment-preview.yaml <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: nginx
        image: nginx:latest
EOF
```

_exec_
```bash
kubectl apply -f deployment.yaml --dry-run=client
```

_output_
```bash
deployment.apps/web created (dry run)
```

Tests manifest application without creating resources

- client: validates locally, server: validates on server
- Useful for checking YAML syntax before applying

#### Validate resources and configurations

```bash
# Validate YAML syntax
kubectl apply -f deployment.yaml --dry-run=server

# Check if resource would be created
kubectl create deployment test --image=alpine --dry-run=client

# Validate all manifests in directory
kubectl apply -f ./manifests/ --dry-run=server

# Test with specific namespace
kubectl apply -f deployment.yaml --namespace=test --dry-run=client

# Get validation details
kubectl apply -f deployment.yaml --dry-run=server -o yaml
```

_exec_
```bash
kubectl apply -f deployment.yaml --dry-run=server -o jsonpath='{.metadata.name}'
```

_output_
```bash
web
```

Validates manifests before actual deployment

- Server-side dry-run catches API errors
- Good for CI/CD pipeline validation

#### Test resource limits and constraints

```bash
# Create pod with resource limits to test
kubectl apply -f - --dry-run=server <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: resource-test
spec:
  containers:
  - name: app
    image: myapp
    resources:
      requests:
        cpu: 100m
        memory: 128Mi
      limits:
        cpu: 500m
        memory: 512Mi
EOF

# Check if quota allows creation
kubectl apply -f deployment.yaml --dry-run=server --validate=strict

# Test PVC binding
kubectl apply -f pvc.yaml --dry-run=server
```

_exec_
```bash
echo '{"apiVersion":"v1","kind":"Pod","metadata":{"name":"test"},"spec":{"containers":[{"name":"app","image":"nginx"}]}}' | kubectl apply -f - --dry-run=server --validate=strict
```
