Skip to main content

Command Palette

Search for a command to run...

Day 48: Kubernetes Basics - Creating Your First Pod ๐ŸŽฏ

Updated
โ€ข9 min read
Day 48: Kubernetes Basics - Creating Your First Pod ๐ŸŽฏ

Welcome back! ๐Ÿ‘‹ Day 48 of the 100 Days Cloud DevOps Challenge, and today we're entering the Kubernetes world! This is container orchestration at scale - moving from Docker to production-grade K8s. Let's orchestrate! ๐Ÿš€

๐ŸŽฏ The Mission - Create First Kubernetes Pod

๐Ÿ“‹ TASK TICKET #DEV-8048 - Kubernetes Pod Creation
Priority: HIGH | Type: K8s Pod Deployment
Server: jump_host | kubectl: Pre-configured

REQUIREMENTS:
1. Pod Name: pod-httpd
2. Image: httpd:latest (exact tag required)
3. Container Name: httpd-container
4. Label: app=httpd_app

VERIFICATION:
- kubectl get pods
- kubectl describe pod pod-httpd
- Pod in Running state

This is your Kubernetes journey beginning! ๐ŸŽฏ

๐Ÿค” Why Kubernetes?

Docker limitations at scale:

  • โŒ Single host deployments

  • โŒ Manual scaling

  • โŒ No self-healing

  • โŒ Manual load balancing

Kubernetes benefits:

  • โœ… Multi-host orchestration

  • โœ… Auto-scaling

  • โœ… Self-healing (automatic restarts)

  • โœ… Built-in load balancing

  • โœ… Rolling updates

  • โœ… Service discovery

Architecture:

Docker World:           Kubernetes World:
docker run httpd    โ†’   kubectl create pod
Single container    โ†’   Pods (1+ containers)
Manual management   โ†’   Declarative config
One host            โ†’   Cluster of nodes

๐Ÿ“ Kubernetes Pod Fundamentals

What is a Pod?

  • Smallest deployable unit in K8s

  • Can contain 1+ containers

  • Shared network namespace (same IP)

  • Shared storage volumes

  • Scheduled together on same node

Pod vs Container:

Container (Docker):     Pod (Kubernetes):
โ”œโ”€ Single process      โ”œโ”€ 1+ containers
โ”œโ”€ Isolated            โ”œโ”€ Shared network/storage
โ”œโ”€ docker run          โ”œโ”€ kubectl create
โ””โ”€ Docker manages      โ””โ”€ K8s orchestrates

๐Ÿ› ๏ธ Complete Implementation

Method 1: Imperative (Command-line)

Step 1: Verify kubectl Access

# Check kubectl configured
kubectl version --short

# Check cluster connection
kubectl cluster-info

# View cluster nodes
kubectl get nodes

Expected output:

Client Version: v1.28.0
Server Version: v1.28.0

Kubernetes control plane is running at https://...

Step 2: Create Pod Imperatively

# Create pod with all specifications
kubectl run pod-httpd \
  --image=httpd:latest \
  --labels=app=httpd_app \
  --port=80 \
  -- /bin/sh -c "httpd-foreground"

# Note: Container name set via --container-port or editing

Problem: Can't set container name imperatively!

Step 3: Better - Dry Run to Generate YAML

# Generate YAML without creating
kubectl run pod-httpd \
  --image=httpd:latest \
  --labels=app=httpd_app \
  --dry-run=client \
  -o yaml > pod-httpd.yaml

Edit generated YAML:

vi pod-httpd.yaml

Modify to add container name:

apiVersion: v1
kind: Pod
metadata:
  labels:
    app: httpd_app
  name: pod-httpd
spec:
  containers:
  - image: httpd:latest
    name: httpd-container  # Add this line!
    ports:
    - containerPort: 80

Create from YAML:

kubectl apply -f pod-httpd.yaml

Step 1: Create Pod YAML Manifest

cat > pod-httpd.yaml << 'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: pod-httpd
  labels:
    app: httpd_app
spec:
  containers:
  - name: httpd-container
    image: httpd:latest
    ports:
    - containerPort: 80
EOF

YAML Breakdown:

apiVersion: v1              # API version for Pod resource
kind: Pod                   # Resource type
metadata:                   # Pod metadata
  name: pod-httpd          # REQUIRED: Pod name
  labels:                   # Key-value pairs for identification
    app: httpd_app         # REQUIRED: Label app=httpd_app
spec:                       # Pod specification
  containers:               # List of containers (minimum 1)
  - name: httpd-container  # REQUIRED: Container name
    image: httpd:latest    # REQUIRED: Image with exact tag
    ports:                  # Optional but recommended
    - containerPort: 80    # Container listens on port 80

Step 2: Apply the Manifest

# Create pod from YAML
kubectl apply -f pod-httpd.yaml

Expected output:

pod/pod-httpd created

Step 3: Verification

# Check pod status
kubectl get pods

# Detailed pod info
kubectl get pods -o wide

# Full pod description
kubectl describe pod pod-httpd

# Check pod labels
kubectl get pods --show-labels

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

Expected outputs:

# kubectl get pods
NAME        READY   STATUS    RESTARTS   AGE
pod-httpd   1/1     Running   0          30s

# kubectl get pods -o wide
NAME        READY   STATUS    RESTARTS   AGE   IP           NODE
pod-httpd   1/1     Running   0          30s   10.244.0.5   node01

# kubectl get pods --show-labels
NAME        READY   STATUS    RESTARTS   AGE   LABELS
pod-httpd   1/1     Running   0          1m    app=httpd_app

Step 4: Detailed Verification

# Verify all requirements
echo "=== Pod Verification ==="
echo "1. Pod name:"
kubectl get pod pod-httpd --no-headers | awk '{print "   โœ“", $1}'

echo "2. Image:"
kubectl get pod pod-httpd -o jsonpath='{.spec.containers[0].image}' && echo ""

echo "3. Container name:"
kubectl get pod pod-httpd -o jsonpath='{.spec.containers[0].name}' && echo ""

echo "4. Labels:"
kubectl get pod pod-httpd -o jsonpath='{.metadata.labels.app}' && echo ""

echo "5. Status:"
kubectl get pod pod-httpd -o jsonpath='{.status.phase}' && echo ""

Expected output:

=== Pod Verification ===
1. Pod name:
   โœ“ pod-httpd
2. Image:
   httpd:latest
3. Container name:
   httpd-container
4. Labels:
   httpd_app
5. Status:
   Running

Step 5: Access the Pod

# Get pod IP
POD_IP=$(kubectl get pod pod-httpd -o jsonpath='{.status.podIP}')
echo "Pod IP: $POD_IP"

# Access from within cluster (if you have access)
kubectl run test-pod --rm -it --image=busybox -- wget -O- http://$POD_IP

# Check pod logs
kubectl logs pod-httpd

# Execute command in pod
kubectl exec pod-httpd -- ps aux

# Interactive shell
kubectl exec -it pod-httpd -- /bin/bash

๐Ÿ” Understanding Kubernetes Concepts

Pod Lifecycle

Pending โ†’ ContainerCreating โ†’ Running โ†’ Succeeded/Failed

Pending:
โ”œโ”€ Pod accepted by K8s
โ”œโ”€ Waiting for scheduling
โ””โ”€ Node assignment pending

ContainerCreating:
โ”œโ”€ Pulling image
โ”œโ”€ Starting containers
โ””โ”€ Initialization

Running:
โ”œโ”€ All containers started
โ”œโ”€ At least one container running
โ””โ”€ Healthy state

Succeeded/Failed:
โ”œโ”€ Containers terminated
โ””โ”€ Exit codes recorded

Labels and Selectors

Why labels matter:

# Pods with labels
metadata:
  labels:
    app: httpd_app
    env: production
    version: v1.0

# Select pods
kubectl get pods -l app=httpd_app           # One label
kubectl get pods -l env=production          # Different label
kubectl get pods -l app=httpd_app,env=prod  # Multiple labels

Real-world usage:

# Services select pods by label
# Deployments manage pods by label
# Operations target pods by label

# Examples:
kubectl delete pods -l app=httpd_app
kubectl logs -l app=httpd_app
kubectl describe pods -l env=production

Container vs Pod

Key differences:

AspectDocker ContainerKubernetes Pod
Smallest unitContainerPod (1+ containers)
NetworkIsolatedShared within pod
Creationdocker runkubectl create
ManagementManualK8s orchestrates
ScalingManualAutomatic
UpdatesManualRolling updates

๐Ÿ’ก Key Takeaways

โœจ Pods are smallest K8s units
โœจ kubectl is K8s CLI tool
โœจ YAML manifests define resources declaratively
โœจ Labels organize and select resources
โœจ Declarative approach preferred over imperative
โœจ Image tags should be explicit (not :latest in prod)
โœจ Container name identifies container within pod
โœจ kubectl get/describe for verification

๐ŸŽ“ Quick Interview Q&A

Q: What's the difference between a Docker container and a Kubernetes pod?
A: Pod is K8s smallest unit, can have 1+ containers sharing network/storage. Container is single process. Pods enable multi-container patterns (sidecar, ambassador). Docker manages containers, K8s orchestrates pods.

Q: Why use YAML manifests instead of kubectl run?
A: Manifests are declarative (desired state), version controlled, reusable, complete configuration. kubectl run is imperative (one-time command), hard to reproduce, limited options. Production uses manifests (GitOps).

Q: What happens if you don't specify image tag?
A: Defaults to :latest tag. Problem: "latest" changes over time, unpredictable deployments, no version tracking. Production rule: always specify exact version (httpd:2.4.58, not httpd:latest).

Q: How do labels help in Kubernetes?
A: Labels organize resources (key-value pairs). Enable selection (kubectl get -l), grouping (services find pods), filtering (delete by label). Services use selectors to route traffic. Essential for multi-resource management.

Q: Can a pod have multiple containers?
A: Yes! Multi-container patterns: Sidecar (logging, monitoring), Ambassador (proxy), Adapter (transform output). Containers share network (localhost), storage (volumes), lifecycle. Schedule together, scale together.

Q: What's the pod lifecycle?
A: Pending (scheduled) โ†’ ContainerCreating (pulling image) โ†’ Running (healthy) โ†’ Succeeded/Failed (terminated). Check with kubectl get pods. Debugging: kubectl describe shows events, kubectl logs shows output.

๐ŸŒŸ Essential kubectl Commands

Pod operations:

# Create
kubectl apply -f pod.yaml
kubectl run pod-name --image=nginx

# View
kubectl get pods
kubectl get pods -o wide
kubectl describe pod pod-name

# Update
kubectl apply -f pod.yaml  # Declarative update
kubectl edit pod pod-name  # Interactive edit

# Delete
kubectl delete pod pod-name
kubectl delete -f pod.yaml

Debugging:

# Logs
kubectl logs pod-name
kubectl logs pod-name -f  # Follow
kubectl logs pod-name --previous  # Previous container

# Execute
kubectl exec pod-name -- command
kubectl exec -it pod-name -- /bin/bash

# Events
kubectl get events
kubectl describe pod pod-name  # Shows events

Labels:

# Show labels
kubectl get pods --show-labels

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

# Add/update label
kubectl label pod pod-name env=prod

# Remove label
kubectl label pod pod-name env-

๐Ÿš€ Common Pod Patterns

1. Simple single-container pod:

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
spec:
  containers:
  - name: nginx
    image: nginx:1.24

2. Multi-container pod (sidecar pattern):

apiVersion: v1
kind: Pod
metadata:
  name: app-with-logging
spec:
  containers:
  - name: app
    image: myapp:1.0
  - name: log-agent
    image: fluentd:v1.16

3. Pod with resource limits:

apiVersion: v1
kind: Pod
metadata:
  name: resource-pod
spec:
  containers:
  - name: app
    image: nginx
    resources:
      requests:
        memory: "128Mi"
        cpu: "250m"
      limits:
        memory: "256Mi"
        cpu: "500m"

4. Pod with environment variables:

apiVersion: v1
kind: Pod
metadata:
  name: env-pod
spec:
  containers:
  - name: app
    image: nginx
    env:
    - name: ENV
      value: "production"
    - name: LOG_LEVEL
      value: "info"

๐Ÿ”ง Troubleshooting

Pod stuck in Pending:

# Check events
kubectl describe pod pod-name

# Common causes:
# - No nodes available
# - Insufficient resources
# - PersistentVolume issues

# Check nodes
kubectl get nodes
kubectl describe node node-name

Pod in CrashLoopBackOff:

# Check logs
kubectl logs pod-name
kubectl logs pod-name --previous

# Common causes:
# - Application crash
# - Wrong command/args
# - Missing dependencies

# Check container status
kubectl describe pod pod-name

ImagePullBackOff:

# Check events
kubectl describe pod pod-name

# Common causes:
# - Typo in image name
# - Image doesn't exist
# - No pull permissions
# - Registry unreachable

# Verify image exists
docker pull httpd:latest

๐ŸŽฏ Best Practices

1. Always specify image tags:

# Bad
image: httpd

# Good
image: httpd:2.4.58

2. Use meaningful labels:

labels:
  app: httpd_app
  component: frontend
  version: v1.0
  environment: production

3. Set resource limits:

resources:
  requests:
    memory: "64Mi"
    cpu: "100m"
  limits:
    memory: "128Mi"
    cpu: "200m"

4. Add health checks:

livenessProbe:
  httpGet:
    path: /
    port: 80
  initialDelaySeconds: 30
readinessProbe:
  httpGet:
    path: /
    port: 80
  initialDelaySeconds: 5

5. Use namespaces:

# Create in namespace
kubectl apply -f pod.yaml -n production

# Default namespace
kubectl config set-context --current --namespace=production

๐ŸŽ‰ Final Thoughts

Congratulations! You've created your first Kubernetes pod!

What you accomplished: โœ… Created pod with specific name
โœ… Used httpd:latest image
โœ… Set custom container name
โœ… Applied labels for organization
โœ… Verified pod is running

Key learnings:

  • Pods are K8s fundamental building blocks

  • YAML manifests define desired state

  • Labels enable resource organization

  • kubectl is your K8s control tool

  • Declarative > Imperative

Next steps:

  • Deployments (manage multiple pods)

  • Services (expose pods)

  • ConfigMaps/Secrets (configuration)

  • Persistent volumes (storage)

This is your Kubernetes journey! ๐Ÿš€


Day: 48/100
Challenge: KodeKloud Cloud DevOps
Date: December 23, 2025
Topic: Kubernetes Pod Creation

Share your K8s learning journey! ๐ŸŽฏ

More from this blog

๐Ÿš€ DevOps Challenge- KodeKloud Solutions

73 posts