Chapter 1: Kubernetes Fundamentals - Complete Container Orchestration Guide
Authored by syscook.dev
What is Kubernetes?
Kubernetes (often abbreviated as K8s) is an open-source container orchestration platform that automates the deployment, scaling, and management of containerized applications. This comprehensive guide will teach you everything you need to know about Kubernetes and how to use it effectively for modern application deployment.
Why Learn Kubernetes?
Kubernetes has become the industry standard for container orchestration because it:
- Automates Deployment: Deploy and manage applications at scale
- Scales Applications: Automatically scale based on demand
- Manages Resources: Efficiently allocate CPU, memory, and storage
- Ensures Reliability: Self-healing and high availability
- Cloud Agnostic: Works across different cloud providers and on-premises
- Industry Standard: Used by Google, Microsoft, Amazon, and thousands of companies
Kubernetes (K8s) is an open-source container orchestration platform that automates the deployment, scaling, and management of containerized applications. Originally developed by Google and now maintained by the Cloud Native Computing Foundation (CNCF), Kubernetes provides a robust framework for running distributed systems reliably and efficiently.
Key Concepts:
- Container Orchestration: Managing and coordinating multiple containers across multiple hosts
- Declarative Configuration: Describing desired state rather than imperative commands
- Self-Healing: Automatically restarting failed containers and replacing unhealthy nodes
- Horizontal Scaling: Automatically scaling applications based on demand
- Service Discovery: Automatic discovery and load balancing of services
- Rolling Updates: Zero-downtime deployments with automatic rollback capabilities
Why Use Kubernetes?
1. Container Management at Scale
Kubernetes simplifies the management of hundreds or thousands of containers across multiple servers.
# Example: Simple deployment configuration
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
labels:
app: web-app
spec:
replicas: 3 # Run 3 instances of the application
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
containers:
- name: web-app
image: nginx:1.20
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
What this configuration does:
- Creates a deployment named
web-app
- Runs 3 replicas of the nginx container
- Allocates specific CPU and memory resources
- Exposes port 80 for web traffic
2. High Availability and Fault Tolerance
Kubernetes automatically handles failures and ensures your applications remain available.
# Example: Service configuration for load balancing
apiVersion: v1
kind: Service
metadata:
name: web-app-service
spec:
selector:
app: web-app
ports:
- protocol: TCP
port: 80
targetPort: 80
type: LoadBalancer # Exposes the service externally
What this configuration does:
- Creates a service that load balances traffic across all web-app pods
- Exposes the service on port 80
- Uses LoadBalancer type for external access
- Automatically routes traffic to healthy pods
3. Automatic Scaling
Kubernetes can automatically scale your applications based on CPU usage, memory consumption, or custom metrics.
# Example: Horizontal Pod Autoscaler
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web-app
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
What this configuration does:
- Automatically scales the web-app deployment
- Maintains between 2 and 10 replicas
- Scales up when CPU usage exceeds 70%
- Scales down when CPU usage is below the threshold
How Does Kubernetes Work?
1. Kubernetes Architecture
Master Node Components
# Check cluster information
kubectl cluster-info
# Output example:
# Kubernetes control plane is running at https://kubernetes.docker.internal:6443
# CoreDNS is running at https://kubernetes.docker.internal:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
Key Master Components:
- API Server: Central management point for all cluster operations
- etcd: Distributed key-value store for cluster state
- Scheduler: Assigns pods to nodes based on resource requirements
- Controller Manager: Ensures desired state is maintained
Worker Node Components
# Check node information
kubectl get nodes -o wide
# Output example:
# NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
# docker-desktop Ready control-plane 1d v1.28.0 192.168.65.4 <none> Docker Desktop 5.15.0-91-generic docker://24.0.7
Key Worker Components:
- kubelet: Agent that runs on each node and manages pods
- kube-proxy: Network proxy that maintains network rules
- Container Runtime: Software responsible for running containers (Docker, containerd, etc.)
2. Core Kubernetes Objects
Pods
Pods are the smallest deployable units in Kubernetes. They can contain one or more containers.
# Example: Simple pod configuration
apiVersion: v1
kind: Pod
metadata:
name: simple-pod
labels:
app: simple-app
spec:
containers:
- name: nginx-container
image: nginx:1.20
ports:
- containerPort: 80
env:
- name: ENV_VAR
value: "production"
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
Configuration Explanation:
apiVersion
: Kubernetes API version (v1 for core objects)kind
: Type of Kubernetes object (Pod)metadata
: Object metadata including name and labelsspec
: Pod specification defining containers and their propertiescontainers
: Array of containers to run in the podimage
: Container image to useports
: Ports to expose from the containerenv
: Environment variables for the containerresources
: CPU and memory requests and limits
Deployments
Deployments manage ReplicaSets and provide declarative updates to pods.
# Example: Deployment with detailed configuration
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deployment
namespace: production
labels:
app: web-app
version: v1.0
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
version: v1.0
spec:
containers:
- name: web-container
image: nginx:1.20
ports:
- containerPort: 80
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 5
resources:
requests:
memory: "128Mi"
cpu: "250m"
limits:
memory: "256Mi"
cpu: "500m"
Configuration Explanation:
replicas
: Number of pod replicas to maintainstrategy
: Deployment strategy (RollingUpdate, Recreate)rollingUpdate
: Configuration for rolling updatesmaxUnavailable
: Maximum pods that can be unavailable during updatemaxSurge
: Maximum pods that can be created above desired replicas
selector
: Label selector to identify managed podstemplate
: Pod template for creating new podslivenessProbe
: Health check to determine if container is alivereadinessProbe
: Health check to determine if container is ready to serve traffic
Services
Services provide stable network access to a set of pods.
# Example: Service with multiple configurations
apiVersion: v1
kind: Service
metadata:
name: web-service
namespace: production
labels:
app: web-app
spec:
type: ClusterIP # Service type: ClusterIP, NodePort, LoadBalancer, ExternalName
selector:
app: web-app
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
- name: https
protocol: TCP
port: 443
targetPort: 443
sessionAffinity: ClientIP # Session affinity configuration
sessionAffinityConfig:
clientIP:
timeoutSeconds: 10800
Configuration Explanation:
type
: Service type determining how the service is exposedClusterIP
: Exposes service on cluster-internal IPNodePort
: Exposes service on each node's IP at a static portLoadBalancer
: Exposes service externally using cloud provider's load balancerExternalName
: Maps service to external DNS name
selector
: Label selector to identify target podsports
: Array of port configurationssessionAffinity
: Session affinity type (None, ClientIP)sessionAffinityConfig
: Configuration for session affinity
3. Namespaces and Resource Organization
Namespaces
Namespaces provide logical separation of resources within a cluster.
# Example: Creating a namespace
apiVersion: v1
kind: Namespace
metadata:
name: development
labels:
environment: dev
team: frontend
# Create namespace via command line
kubectl create namespace development
# Apply resources to specific namespace
kubectl apply -f deployment.yaml -n development
# Get resources from specific namespace
kubectl get pods -n development
Namespace Benefits:
- Resource isolation and organization
- Access control and security boundaries
- Resource quotas and limits
- Logical grouping of related resources
Resource Quotas
Resource quotas limit resource consumption within namespaces.
# Example: Resource quota configuration
apiVersion: v1
kind: ResourceQuota
metadata:
name: dev-quota
namespace: development
spec:
hard:
requests.cpu: "2"
requests.memory: 4Gi
limits.cpu: "4"
limits.memory: 8Gi
persistentvolumeclaims: "10"
pods: "20"
services: "5"
secrets: "10"
configmaps: "10"
Quota Explanation:
requests.cpu
: Total CPU requests allowedrequests.memory
: Total memory requests allowedlimits.cpu
: Total CPU limits allowedlimits.memory
: Total memory limits allowedpersistentvolumeclaims
: Maximum number of PVCspods
: Maximum number of podsservices
: Maximum number of servicessecrets
: Maximum number of secretsconfigmaps
: Maximum number of config maps
4. Labels and Selectors
Labels
Labels are key-value pairs attached to objects for identification and selection.
# Example: Pod with multiple labels
apiVersion: v1
kind: Pod
metadata:
name: labeled-pod
labels:
app: web-app
version: v1.0
environment: production
tier: frontend
team: frontend-team
owner: john-doe
spec:
containers:
- name: web-container
image: nginx:1.20
# Query pods using label selectors
kubectl get pods -l app=web-app
kubectl get pods -l environment=production
kubectl get pods -l 'tier in (frontend,backend)'
kubectl get pods -l 'version!=v1.0'
kubectl get pods -l 'app=web-app,environment=production'
Label Selector Operators:
=
: Equality!=
: Inequalityin
: Set membershipnotin
: Set exclusionexists
: Key existencedoesnotexist
: Key non-existence
Annotations
Annotations provide additional metadata that is not used for selection.
# Example: Pod with annotations
apiVersion: v1
kind: Pod
metadata:
name: annotated-pod
annotations:
description: "Web application pod for production"
contact: "[email protected]"
last-modified: "2024-01-15T10:30:00Z"
build-info: "build-123"
monitoring: "enabled"
spec:
containers:
- name: web-container
image: nginx:1.20
Practical Examples
1. Complete Web Application Setup
Step 1: Create Namespace
# namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: web-app
labels:
environment: production
Step 2: Create Deployment
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deployment
namespace: web-app
labels:
app: web-app
spec:
replicas: 3
selector:
matchLabels:
app: web-app
template:
metadata:
labels:
app: web-app
spec:
containers:
- name: web-container
image: nginx:1.20
ports:
- containerPort: 80
env:
- name: ENV
value: "production"
resources:
requests:
memory: "128Mi"
cpu: "250m"
limits:
memory: "256Mi"
cpu: "500m"
Step 3: Create Service
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: web-service
namespace: web-app
spec:
selector:
app: web-app
ports:
- port: 80
targetPort: 80
type: LoadBalancer
Step 4: Deploy the Application
# Apply all configurations
kubectl apply -f namespace.yaml
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
# Verify deployment
kubectl get all -n web-app
# Check pod status
kubectl get pods -n web-app -o wide
# Check service
kubectl get service -n web-app
2. Health Checks and Probes
Liveness Probe Example
apiVersion: v1
kind: Pod
metadata:
name: liveness-pod
spec:
containers:
- name: web-container
image: nginx:1.20
ports:
- containerPort: 80
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 30 # Wait 30 seconds before first probe
periodSeconds: 10 # Check every 10 seconds
timeoutSeconds: 5 # Timeout after 5 seconds
failureThreshold: 3 # Restart after 3 consecutive failures
successThreshold: 1 # Consider healthy after 1 success
Readiness Probe Example
apiVersion: v1
kind: Pod
metadata:
name: readiness-pod
spec:
containers:
- name: web-container
image: nginx:1.20
ports:
- containerPort: 80
readinessProbe:
httpGet:
path: /health
port: 80
initialDelaySeconds: 5 # Wait 5 seconds before first probe
periodSeconds: 5 # Check every 5 seconds
timeoutSeconds: 3 # Timeout after 3 seconds
failureThreshold: 3 # Mark unready after 3 failures
successThreshold: 1 # Mark ready after 1 success
3. Resource Management
Resource Requests and Limits
apiVersion: v1
kind: Pod
metadata:
name: resource-pod
spec:
containers:
- name: web-container
image: nginx:1.20
resources:
requests:
memory: "128Mi" # Minimum memory required
cpu: "250m" # Minimum CPU required (250 millicores)
limits:
memory: "256Mi" # Maximum memory allowed
cpu: "500m" # Maximum CPU allowed (500 millicores)
Quality of Service Classes
# Check pod QoS class
kubectl get pod resource-pod -o jsonpath='{.status.qosClass}'
# QoS Classes:
# - Guaranteed: requests == limits for all resources
# - Burstable: requests < limits for some resources
# - BestEffort: no requests or limits specified
Best Practices
1. Resource Naming and Organization
# Good: Consistent naming convention
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app-frontend-v1
namespace: production
labels:
app: web-app
component: frontend
version: v1.0
environment: production
team: frontend-team
2. Health Check Configuration
# Good: Comprehensive health checks
livenessProbe:
httpGet:
path: /health/live
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /health/ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
timeoutSeconds: 3
failureThreshold: 3
3. Resource Limits
# Good: Always specify resource requests and limits
resources:
requests:
memory: "128Mi"
cpu: "250m"
limits:
memory: "256Mi"
cpu: "500m"
Common Pitfalls and Solutions
1. Missing Resource Limits
# ❌ Bad: No resource limits
spec:
containers:
- name: web-container
image: nginx:1.20
# ✅ Good: Proper resource limits
spec:
containers:
- name: web-container
image: nginx:1.20
resources:
requests:
memory: "128Mi"
cpu: "250m"
limits:
memory: "256Mi"
cpu: "500m"
2. Inadequate Health Checks
# ❌ Bad: No health checks
spec:
containers:
- name: web-container
image: nginx:1.20
# ✅ Good: Proper health checks
spec:
containers:
- name: web-container
image: nginx:1.20
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 5
3. Poor Label Organization
# ❌ Bad: Inconsistent or missing labels
metadata:
name: pod1
labels:
app: web
# ✅ Good: Consistent and comprehensive labels
metadata:
name: web-app-frontend-pod
labels:
app: web-app
component: frontend
version: v1.0
environment: production
team: frontend-team
Conclusion
Kubernetes fundamentals provide the foundation for understanding container orchestration. By understanding:
- What Kubernetes is and its core concepts
- Why it's essential for modern containerized applications
- How its architecture and components work together
You can begin your journey into container orchestration. Kubernetes provides powerful abstractions for managing complex distributed systems, making it easier to deploy, scale, and maintain applications in production environments.
Next Steps
- Practice with basic Kubernetes commands
- Set up a local development cluster
- Move on to Chapter 2: Installation & Setup
This tutorial is part of the Kubernetes Mastery series by syscook.dev