Week 5 - Lab 3: Introduction to
Kubernetes (Minikube)
Module: Operating Systems 3 (Virtualisation & Cloud Technologies)
Topic: Kubernetes Orchestration & Management
Estimated Time: 60 Minutes
Instructor: KT Nshimba
Lab Overview
In Lab 2, you deployed WordPress using Docker Compose. This was excellent for a single server. However, what if that server fails? What if you need 50 copies of WordPress to handle Black Friday traffic?
Docker Compose cannot handle multi-server scaling or self-healing automatically. Kubernetes (K8s) can.
In this lab, you will "graduate" your application from Docker Compose to Kubernetes. You will use Minikube (a local single-node Kubernetes cluster) to deploy the same WordPress stack, first using the CLI, and then managing it with Portainer.
Objectives:
- Understand the shift from Containers (Docker) to Pods (Kubernetes).
- Deploy MySQL and WordPress using K8s Manifests (YAML).
- Expose applications using K8s Services.
- Deploy Portainer into the cluster to manage Kubernetes visually.
Prerequisites: - The Ubuntu Server VM from previous labs. - Minikube is pre-installed on this VM. - Kubectl is pre-installed on this VM.
Part 1: The CLI Approach (Kubectl)
We will manually define our infrastructure using YAML manifests, similar to Docker Compose but with more power components.
Step 1: Start the Cluster
- Log in to your Ubuntu VM. Start Minikube:
minikube start --driver=docker
Note: This creates a Kubernetes cluster inside a Docker container! Verify connection:
kubectl get nodes
Field Report:
- Node Name:
[ _________________ ](e.g., minikube) - Status:
[ _______________ ](e.g., Ready)
Step 2: Deploy MySQL (The Database)
In Kubernetes, we don't just run a container; we run a Deployment (which manages the
Pods) and a Service (which gives networking).
Create the file mysql-k8s.yaml:
apiVersion: v1
kind: Service
metadata:
name: wordpress-db
spec:
ports:
- port: 3306
selector:
app: wordpress-db
clusterIP: None # Headless service for internal DB communication
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: wordpress-db
spec:
selector:
matchLabels:
app: wordpress-db
template:
metadata:
labels:
app: wordpress-db
spec:
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
value: somewordpress
- name: MYSQL_DATABASE
value: wordpress
- name: MYSQL_USER
value: wordpress
- name: MYSQL_PASSWORD
value: wordpress
Apply it:
kubectl apply -f mysql-k8s.yaml
Step 3: Deploy WordPress (The Frontend)
Now the web server. This needs a Service accessible from outside the cluster.
Create wordpress-k8s.yaml:
apiVersion: v1
kind: Service
metadata:
name: wordpress
spec:
ports:
- port: 80
targetPort: 80
nodePort: 30000 # Expose on port 30000
selector:
app: wordpress
type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: wordpress
spec:
replicas: 1
selector:
matchLabels:
app: wordpress
template:
metadata:
labels:
app: wordpress
spec:
containers:
- name: wordpress
image: wordpress:latest
env:
- name: WORDPRESS_DB_HOST
value: wordpress-db
- name: WORDPRESS_DB_USER
value: wordpress
- name: WORDPRESS_DB_PASSWORD
value: wordpress
- name: WORDPRESS_DB_NAME
value: wordpress
Apply it:
kubectl apply -f wordpress-k8s.yaml
Step 4: Verify and Access
Check the pods:
kubectl get pods
Wait until Status is Running.
Get the access URL:
minikube service wordpress --url
Field Report:
- WordPress URL: _________________
- Pod Status: _________________
4. Open that URL in your browser. You should see the WordPress installer!
Step 5: Critical Thinking - Self Healing
Delete the WordPress pod manually:
# Replace pod-name with your actual pod name
kubectl delete pod <wordpress-pod-name>
Immediately check pods again:
kubectl get pods
Observation:
- Did the pod stay deleted? [ Yes / No ] (Hint: No)
- Why did Kubernetes recreate it? _______________________
This is the power of a Deployment controller!
Part 2: Managing K8s with Portainer
Just like with Docker, CLI is good, but a Dashboard helps visualize complexity. We will deploy Portainer inside your Kubernetes cluster.
Step 1: Deploy Portainer
Download and apply the Portainer manifest:
kubectl apply -n portainer -f https://raw.githubusercontent.com/portainer/k8s/master/deploy/manifests/portainer/portainer.yaml
Note: If the namespace doesn't exist, create it first:
kubectl create namespace portainer. Expose Portainer via NodePort (so we can access it):
kubectl expose deploy portainer -n portainer --type=NodePort --name=portainer-svc --port=9000
Step 2: Access Portainer
Get the URL:
minikube service portainer-svc -n portainer --url
- Open the URL in your browser.
- Create an admin user. 4. Select Get Started -> Connect to your local Kubernetes environment.
Step 3: Explore Kubernetes UI
- Click on your local cluster.
- Navigate to Namespaces -> default.
- Look at Applications. Do you see
wordpressandwordpress-db? 4. Look at Cluster -> Nodes.
Field Report
- Total Pods showing in Portainer:
[ ______ ] - Visual Check: Does Portainer show the relationship between the Service and the
Deployment?
[ Yes / No ]
Lab Checkpoint
Practical Skills Checklist
- Started Minikube cluster
- Created and Applied Kubernetes Manifests
(
.yaml) - Verified Pod self-healing
(
delete pod) - Deployed Portainer into the K8s cluster
- Accessed the running WordPress site via Minikube Service URL
Theoretical Understanding Checklist
- Explained why we use Deployments (Scaling/Healing) instead of just single containers
- Understood the purpose of a Service (Networking/Stable IP)
- Differentiated between NodePort (External Access) and ClusterIP (Internal Only)
Troubleshooting Scenarios
- Scenario 1:
kubectl get podsshowsErrImagePullorImagePullBackOff.
Diagnosis: _______________________ (Hint: Can the VM reach Docker Hub?) - Scenario 2: WordPress shows "Error establishing database connection".
Diagnosis: _______________________ (Hint: Service name vs Env Variable)
Lab Reflection
- Complexity: Compare the
docker-compose.yaml(Lab 2) with the K8s YAMLs. Which was simpler to write? - Scalability: If we needed 10 copies of WordPress, what one command (or line change) would do it in K8s?
- The "Why": For a simple blog, is Kubernetes overkill? When does it become necessary?