coderain guide

Kubernetes Workshop: Hands-on Labs and Real-World Applications

In today’s fast-paced tech landscape, containerization has revolutionized how applications are built, shipped, and scaled. At the heart of this revolution lies **Kubernetes** (K8s)—an open-source container orchestration platform that automates deployment, scaling, and management of containerized applications. Whether you’re a developer, DevOps engineer, or IT professional, mastering Kubernetes is no longer optional; it’s a critical skill for building resilient, cloud-native systems. While theoretical knowledge of Kubernetes concepts (Pods, Deployments, Services, etc.) is essential, **hands-on practice** is where true expertise is gained. This blog serves as a comprehensive guide to a Kubernetes workshop, walking you through step-by-step labs, real-world application scenarios, and troubleshooting tips. By the end, you’ll not only understand Kubernetes fundamentals but also how to apply them to solve practical problems.

Table of Contents

  1. Why Kubernetes Matters: Beyond the Hype
  2. Workshop Prerequisites: What You’ll Need
  3. Setting Up Your Kubernetes Environment
  4. Hands-on Labs: From Basics to Advanced
  5. Real-World Kubernetes Applications: Case Studies
  6. Troubleshooting Common Kubernetes Issues
  7. Conclusion
  8. References

Why Kubernetes Matters: Beyond the Hype

Kubernetes has emerged as the de facto standard for container orchestration for three key reasons:

  • Scalability: Automatically scale applications up or down based on demand (e.g., Black Friday traffic spikes).
  • Resilience: Self-heal by replacing failed containers, ensuring high availability.
  • Portability: Run applications consistently across on-premises, public clouds (AWS, GCP, Azure), and edge environments.

Today, 78% of organizations use Kubernetes in production (CNCF Survey 2023), powering everything from startups to enterprises (e.g., Netflix, Airbnb, Shopify). By mastering Kubernetes, you’ll gain the ability to deploy and manage modern applications efficiently—an in-demand skill in DevOps, SRE, and cloud engineering roles.

Workshop Prerequisites: What You’ll Need

Before diving in, ensure you have the following tools installed:

ToolPurposeInstallation Link
kubectlKubernetes command-line toolKubectl Install Guide
DockerContainer runtime (for building images)Docker Desktop
Minikube (Optional)Local Kubernetes cluster (for development)Minikube Setup
Cloud Account (Optional)For cloud-based clusters (AWS, GCP, Azure)AWS Free Tier, GCP Free Tier

Basic Knowledge: Familiarity with containers (Docker), command-line interfaces (CLI), and YAML syntax will help, but we’ll explain key concepts as we go.

Setting Up Your Kubernetes Environment

We’ll cover two common setups: local development (Minikube) and cloud deployment (Amazon EKS). Choose the one that fits your needs!

3.1 Local Setup with Minikube

Minikube creates a single-node Kubernetes cluster on your laptop, ideal for learning:

  1. Install Minikube (follow the official guide).
  2. Start the cluster:
    minikube start --driver=docker  # Uses Docker as the runtime  
  3. Verify the cluster:
    kubectl get nodes  # Should show a "Ready" node named "minikube"  

3.2 Cloud Setup with Amazon EKS (Example)

For production-like environments, use a managed Kubernetes service like AWS EKS:

  1. Install AWS CLI and configure credentials:
    aws configure  # Enter your AWS access key, secret key, region, etc.  
  2. Install eksctl (EKS command-line tool):
    curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp  
    sudo mv /tmp/eksctl /usr/local/bin  
  3. Create an EKS cluster (takes ~15 minutes):
    eksctl create cluster --name my-eks-cluster --region us-east-1 --nodegroup-name standard-workers --node-type t3.medium --nodes 2  
  4. Verify the cluster:
    kubectl get nodes  # Should show 2 "Ready" nodes  

Hands-on Labs: From Basics to Advanced

Let’s dive into labs that build practical Kubernetes skills, from deploying apps to securing them!

Lab 1: Deploy a Stateless Web Application

Objective: Deploy a simple “Hello World” web app using Kubernetes Deployments and expose it via a Service.

Step 1: Create a Deployment YAML

A Deployment manages a set of identical pods (containers). Create hello-world-deployment.yaml:

apiVersion: apps/v1  
kind: Deployment  
metadata:  
  name: hello-world-deploy  
spec:  
  replicas: 2  # Run 2 pods  
  selector:  
    matchLabels:  
      app: hello-world  
  template:  
    metadata:  
      labels:  
        app: hello-world  
    spec:  
      containers:  
      - name: hello-world-container  
        image: gcr.io/google-samples/hello-app:1.0  # Pre-built hello-world image  
        ports:  
        - containerPort: 8080  # Port the app listens on  

Step 2: Deploy the App

kubectl apply -f hello-world-deployment.yaml  

Step 3: Expose the App with a Service

A Service makes the app accessible internally or externally. Create hello-world-service.yaml:

apiVersion: v1  
kind: Service  
metadata:  
  name: hello-world-service  
spec:  
  selector:  
    app: hello-world  # Matches pods with label "app: hello-world"  
  ports:  
    - protocol: TCP  
      port: 80        # Service port  
      targetPort: 8080  # Pod port  
  type: NodePort  # Expose on a static port on each node (for local clusters)  
  # For cloud clusters, use type: LoadBalancer to get a public IP  

Apply the Service:

kubectl apply -f hello-world-service.yaml  

Step 4: Access the App

  • Minikube: Get the node port and access via Minikube IP:
    minikube service hello-world-service --url  # Returns a URL like http://192.168.49.2:30080  
  • EKS: Use kubectl get svc hello-world-service to get the LoadBalancer Ingress (public IP), then visit http://<INGRESS-IP>.

Expected Output: A webpage saying “Hello, World! Version: 1.0”

Lab 2: Scaling and Load Balancing

Objective: Scale the app horizontally and test load balancing across pods.

Step 1: Manual Scaling

Scale the Deployment to 4 pods:

kubectl scale deployment hello-world-deploy --replicas=4  
kubectl get pods  # Should show 4 running pods  

Step 2: Autoscaling with HPA

Use the Horizontal Pod Autoscaler (HPA) to scale based on CPU usage. First, enable metrics-server (required for HPA):

minikube addons enable metrics-server  # For Minikube  
# For EKS: Follow the [metrics-server guide](https://docs.aws.amazon.com/eks/latest/userguide/metrics-server.html)  

Create an HPA:

apiVersion: autoscaling/v2  
kind: HorizontalPodAutoscaler  
metadata:  
  name: hello-world-hpa  
spec:  
  scaleTargetRef:  
    apiVersion: apps/v1  
    kind: Deployment  
    name: hello-world-deploy  
  minReplicas: 2  
  maxReplicas: 10  
  metrics:  
  - type: Resource  
    resource:  
      name: cpu  
      target:  
        type: Utilization  
        averageUtilization: 50  # Scale up if CPU > 50%  

Apply the HPA:

kubectl apply -f hpa.yaml  

Step 3: Test Load Balancing

Use kubectl logs <pod-name> on different pods to see request distribution. Kubernetes Services automatically load-balance traffic across pods!

Lab 3: Stateful Applications with Persistent Storage

Objective: Deploy a stateful application (MySQL) with persistent storage to retain data across pod restarts.

Key Concepts:

  • StatefulSet: Manages stateful apps with stable network identities (e.g., mysql-0, mysql-1).
  • PersistentVolume (PV): Cluster-wide storage resource.
  • PersistentVolumeClaim (PVC): Request for storage by a pod.

Step 1: Create a PV and PVC

# pv.yaml  
apiVersion: v1  
kind: PersistentVolume  
metadata:  
  name: mysql-pv  
spec:  
  capacity:  
    storage: 10Gi  
  accessModes:  
    - ReadWriteOnce  # Mountable by one node at a time  
  hostPath:  
    path: /data/mysql  # Local path (use AWS EBS/GCP PD in production)  
---  
# pvc.yaml  
apiVersion: v1  
kind: PersistentVolumeClaim  
metadata:  
  name: mysql-pvc  
spec:  
  accessModes:  
    - ReadWriteOnce  
  resources:  
    requests:  
      storage: 5Gi  # Requests 5Gi from the PV  

Apply:

kubectl apply -f pv.yaml -f pvc.yaml  

Step 2: Deploy MySQL with StatefulSet

# mysql-statefulset.yaml  
apiVersion: apps/v1  
kind: StatefulSet  
metadata:  
  name: mysql  
spec:  
  serviceName: mysql  # Headless service for DNS records  
  replicas: 1  
  selector:  
    matchLabels:  
      app: mysql  
  template:  
    metadata:  
      labels:  
        app: mysql  
    spec:  
      containers:  
      - name: mysql  
        image: mysql:8.0  
        env:  
        - name: MYSQL_ROOT_PASSWORD  
          value: "password"  # Use Secrets in production!  
        ports:  
        - containerPort: 3306  
        volumeMounts:  
        - name: data  
          mountPath: /var/lib/mysql  # Where MySQL stores data  
  volumeClaimTemplates:  
  - metadata:  
      name: data  
    spec:  
      accessModes: [ "ReadWriteOnce" ]  
      resources:  
        requests:  
          storage: 5Gi  

Apply and verify:

kubectl apply -f mysql-statefulset.yaml  
kubectl get statefulsets  # Should show "READY 1/1"  

Test Persistence: Delete the pod with kubectl delete pod mysql-0—the new pod will retain data thanks to the PVC!

Lab 4: Configuring and Securing Applications

Objective: Manage configuration (ConfigMaps) and sensitive data (Secrets) securely.

Step 1: ConfigMaps for Non-Sensitive Data

Store app config (e.g., environment variables) in a ConfigMap:

# configmap.yaml  
apiVersion: v1  
kind: ConfigMap  
metadata:  
  name: app-config  
data:  
  APP_COLOR: "blue"  
  LOG_LEVEL: "info"  

Apply:

kubectl apply -f configmap.yaml  

Step 2: Secrets for Sensitive Data

Store passwords/tokens in a Secret (base64-encoded):

# Encode "mypassword" as base64  
echo -n "mypassword" | base64  # Output: bXlwYXNzd29yZA==  

Create secret.yaml:

apiVersion: v1  
kind: Secret  
metadata:  
  name: app-secret  
type: Opaque  
data:  
  DB_PASSWORD: bXlwYXNzd29yZA==  # Encoded password  

Apply:

kubectl apply -f secret.yaml  

Step 3: Inject Config into a Pod

Update the hello-world-deployment.yaml to use ConfigMap and Secret:

spec:  
  containers:  
  - name: hello-world-container  
    image: gcr.io/google-samples/hello-app:1.0  
    env:  
    - name: APP_COLOR  
      valueFrom:  
        configMapKeyRef:  
          name: app-config  
          key: APP_COLOR  
    - name: DB_PASSWORD  
      valueFrom:  
        secretKeyRef:  
          name: app-secret  
          key: DB_PASSWORD  

Apply and verify:

kubectl apply -f hello-world-deployment.yaml  
kubectl exec -it <pod-name> -- env | grep APP_COLOR  # Should show "blue"  

Lab 5: Monitoring and Logging

Objective: Monitor cluster health with Prometheus and Grafana, and aggregate logs with ELK Stack.

Step 1: Deploy Prometheus and Grafana (with Helm)

Helm is a package manager for Kubernetes. Install Helm first:

curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash  

Add the Prometheus repo and install:

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts  
helm install prometheus prometheus-community/kube-prometheus-stack  

Access Grafana:

kubectl port-forward svc/prometheus-grafana 3000:80  

Visit http://localhost:3000 (default credentials: admin/prom-operator). Explore dashboards like “Kubernetes Cluster Monitoring”.

Step 2: Log Aggregation with ELK Stack

Deploy Elasticsearch, Logstash, and Kibana (simplified with Helm):

helm repo add elastic https://helm.elastic.co  
helm install elasticsearch elastic/elasticsearch --set replicas=1  
helm install kibana elastic/kibana  

Stream logs to Kibana: Use Filebeat (installed via Helm) to ship pod logs to Elasticsearch. Kibana lets you search and visualize logs!

Real-World Kubernetes Applications: Case Studies

1. Microservices at Netflix

Netflix uses Kubernetes to deploy thousands of microservices (e.g., recommendation engines, video encoding). Each service runs in its own pod, scaled independently based on demand.

2. CI/CD Pipelines at Shopify

Shopify automates deployments with Kubernetes: Code is built into containers, tested in a staging cluster, and promoted to production—all managed via GitOps tools like ArgoCD.

3. Edge Computing at John Deere

John Deere deploys Kubernetes on tractors and farm equipment to process sensor data locally, reducing latency and bandwidth costs.

Troubleshooting Common Kubernetes Issues

IssueTroubleshooting Steps
Pod stuck in “Pending”Check node resources: kubectl describe pod <pod-name> → Look for “Insufficient CPU/Memory”.
ImagePullBackOffVerify image name/tag: kubectl describe pod <pod-name> → Check “Events” for image pull errors.
Service not reachableEnsure Service selector matches pod labels: kubectl get svc <svc-name> -o yaml vs kubectl get pods --show-labels.
Data loss in stateful appsCheck PVC status: kubectl get pvc → Ensure it’s “Bound”. Verify PV storage backend (e.g., AWS EBS).

Conclusion

Kubernetes is a powerful tool for modern application deployment, but mastery comes through practice. This workshop covered core concepts—from Deployments and Services to StatefulSets and Secrets—with hands-on labs that mirror real-world scenarios.

As you continue your journey, explore advanced topics like Kubernetes Operators (for managing complex apps), Istio (service mesh), and GitOps (declarative deployments). The Kubernetes ecosystem is vast, but with the foundation built here, you’re ready to tackle production challenges!

References