Table of Contents
- Prerequisites: What You’ll Need
- Setting Up a Local Kubernetes Cluster
- Creating a Sample Application
- Containerizing the Application with Docker
- Writing Kubernetes Manifests
- 5.1 Deployment Manifest
- 5.2 Service Manifest
- Deploying the Application to Kubernetes
- Verifying the Deployment
- Accessing Your Application
- Troubleshooting Common Issues
- Cleaning Up Resources
- References
Prerequisites: What You’ll Need
Before diving in, ensure you have the following tools installed. We’ll use these to set up a local cluster, build containers, and interact with Kubernetes:
1. kubectl
kubectl is the command-line tool for interacting with Kubernetes clusters. It lets you create, update, and delete resources like deployments and services.
- Installation:
- Windows: Use Chocolatey:
choco install kubernetes-cli - macOS: Use Homebrew:
brew install kubectl - Linux: Use
curl:curl -LO "https://dl.k8s.io/release/v1.28.0/bin/linux/amd64/kubectl" chmod +x kubectl sudo mv kubectl /usr/local/bin/ - Verify installation:
kubectl version --client
- Windows: Use Chocolatey:
2. A Local Kubernetes Cluster
For beginners, we recommend minikube (a lightweight tool to run Kubernetes locally) or Docker Desktop (with Kubernetes enabled). We’ll use minikube in this guide.
- Install minikube:
- Windows/macOS/Linux: Follow the official minikube docs.
- Verify installation:
minikube version
3. Docker
You’ll need Docker to build container images for your application.
- Install Docker:
- Download from Docker’s official site.
- Verify installation:
docker --version
4. A Docker Hub Account
Docker Hub is a public registry to store your container images (free for public repos). Sign up at hub.docker.com.
Setting Up a Local Kubernetes Cluster
With minikube installed, let’s start a local cluster. This cluster will run on your machine and simulate a production Kubernetes environment.
-
Start minikube:
minikube startThis downloads a Kubernetes ISO, starts a VM (or uses Docker as the driver), and initializes a single-node cluster.
-
Verify the cluster is running:
minikube statusYou should see output like:
minikube type: Control Plane host: Running kubelet: Running apiserver: Running kubeconfig: Configured -
Check cluster nodes:
kubectl get nodesYou’ll see one node (e.g.,
minikube) in theReadystate.
Creating a Sample Application
Let’s build a simple “Hello World” application to deploy. We’ll use Node.js (but feel free to adapt this to Python, Go, or another language).
Step 1: Set Up the App Files
Create a new directory (e.g., k8s-first-app) and add these files:
app.js (the application code):
const express = require('express');
const app = express();
const port = 3000;
app.get('/', (req, res) => {
res.send('Hello from Kubernetes! 🚀');
});
app.listen(port, () => {
console.log(`App running on port ${port}`);
});
package.json (dependencies):
{
"name": "k8s-first-app",
"version": "1.0.0",
"dependencies": {
"express": "^4.18.2"
}
}
Step 2: Test the App Locally
Before containerizing, test the app to ensure it works:
# Install dependencies
npm install
# Start the app
node app.js
Visit http://localhost:3000 in your browser—you should see “Hello from Kubernetes! 🚀“.
Containerizing the Application with Docker
Next, we’ll package the app into a Docker container. Containers ensure your app runs consistently across environments (your laptop, Kubernetes, etc.).
Step 1: Create a Dockerfile
In the k8s-first-app directory, create a file named Dockerfile (no extension) with:
# Use Node.js 18 as the base image
FROM node:18-alpine
# Set working directory in the container
WORKDIR /app
# Copy package files and install dependencies
COPY package*.json ./
RUN npm install
# Copy the rest of the app code
COPY . .
# Expose port 3000 (the port the app runs on)
EXPOSE 3000
# Command to start the app
CMD ["node", "app.js"]
Step 2: Build the Docker Image
Build the image, tagging it with your Docker Hub username (replace YOUR_DOCKER_HUB_USERNAME with your actual username):
docker build -t YOUR_DOCKER_HUB_USERNAME/k8s-first-app:v1 .
-t: Tags the image (format:registry/username/image-name:tag).v1: A version tag (helps track updates).
Step 3: Push the Image to Docker Hub
Push the image to Docker Hub so Kubernetes can pull it:
-
Log in to Docker Hub:
docker loginEnter your Docker Hub username and password.
-
Push the image:
docker push YOUR_DOCKER_HUB_USERNAME/k8s-first-app:v1
Kubernetes Manifests: Defining Your Application
Kubernetes uses YAML manifests to define how to run your application. We’ll create two manifests:
- Deployment: Manages a set of identical pods (the smallest deployable units in Kubernetes) and ensures they stay running.
- Service: Exposes your deployment to the outside world (or other apps in the cluster).
5.1 Deployment Manifest
A Deployment ensures your app has a specified number of replicas (pods) running. If a pod fails, the Deployment replaces it.
Create a file named deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: k8s-first-app-deployment
spec:
replicas: 2 # Run 2 pods
selector:
matchLabels:
app: k8s-first-app # Matches labels on pods
template:
metadata:
labels:
app: k8s-first-app # Label for pods
spec:
containers:
- name: k8s-first-app-container
image: YOUR_DOCKER_HUB_USERNAME/k8s-first-app:v1 # Your Docker Hub image
ports:
- containerPort: 3000 # Port the container exposes
Key Fields Explained:
replicas: 2: Runs 2 copies of your app (for redundancy).selector.matchLabels: Tells the Deployment which pods to manage (must matchtemplate.metadata.labels).containers.image: The Docker image to run (replace with your Docker Hub image!).
5.2 Service Manifest
A Service exposes your Deployment so you can access the app. We’ll use a NodePort service, which opens a port on every cluster node to route traffic to the pods.
Create a file named service.yaml:
apiVersion: v1
kind: Service
metadata:
name: k8s-first-app-service
spec:
selector:
app: k8s-first-app # Matches pods with this label
ports:
- protocol: TCP
port: 80 # Service port (internal to the cluster)
targetPort: 3000 # Port on the pod to forward to
nodePort: 30080 # Port on the node (30000-32767 range)
type: NodePort # Expose on a node port
Key Fields Explained:
selector: Routes traffic to pods with labelapp: k8s-first-app.nodePort: 30080: The port on the cluster node you’ll use to access the app (must be between 30000–32767).
Deploying the Application to Kubernetes
Now, let’s deploy the app using kubectl and the manifests.
Step 1: Apply the Deployment
Run:
kubectl apply -f deployment.yaml
Output:
deployment.apps/k8s-first-app-deployment created
Step 2: Apply the Service
Run:
kubectl apply -f service.yaml
Output:
service/k8s-first-app-service created
Verifying the Deployment
Let’s check if everything is running correctly.
1. Check Deployments
kubectl get deployments
Output (look for READY: 2/2):
NAME READY UP-TO-DATE AVAILABLE AGE
k8s-first-app-deployment 2/2 2 2 1m
2. Check Pods
kubectl get pods
Output (you’ll see 2 pods, status Running):
NAME READY STATUS RESTARTS AGE
k8s-first-app-deployment-7f9b6c5d8-abc123 1/1 Running 0 2m
k8s-first-app-deployment-7f9b6c5d8-def456 1/1 Running 0 2m
3. Check the Service
kubectl get services
Output (look for k8s-first-app-service):
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10m
k8s-first-app-service NodePort 10.102.235.78 <none> 80:30080/TCP 3m
4. Check Pod Logs
Ensure the app is running inside the pod:
kubectl logs <POD_NAME> # Replace with a pod name from `kubectl get pods`
Output:
App running on port 3000
Accessing Your Application
Now, let’s access the app from your local machine!
Step 1: Get the Cluster Node IP
Minikube runs the cluster in a VM, so we need its IP:
minikube ip
Output (example): 192.168.49.2
Step 2: Access the App
Use the node IP and the nodePort (30080) from the service:
curl http://<MINIKUBE_IP>:30080
Or open http://<MINIKUBE_IP>:30080 in your browser. You’ll see:
Hello from Kubernetes! 🚀
Pro Tip: Use minikube service
For convenience, minikube can open the app automatically:
minikube service k8s-first-app-service
Troubleshooting Common Issues
If things aren’t working, here are fixes for common problems:
Pod Not Starting?
Check pod details to see errors:
kubectl describe pod <POD_NAME>
- ImagePullBackOff: Kubernetes can’t pull the image. Fix:
- Ensure the image name in
deployment.yamlmatches your Docker Hub image (e.g.,YOUR_USERNAME/k8s-first-app:v1). - Verify the image exists on Docker Hub: hub.docker.com/repository/docker/YOUR_USERNAME/k8s-first-app.
- Ensure the image name in
Service Not Accessible?
- Labels Mismatch: Ensure
service.spec.selectormatchesdeployment.spec.template.metadata.labels(both should beapp: k8s-first-app). - Incorrect NodePort: Use a port in the 30000–32767 range (e.g., 30080).
App Crashes Immediately?
Check pod logs:
kubectl logs <POD_NAME>
Common issues: Missing dependencies (ensure npm install ran in the Docker build) or port conflicts.
Cleaning Up Resources
When you’re done, delete the deployment and service to free resources:
kubectl delete deployment k8s-first-app-deployment
kubectl delete service k8s-first-app-service
Stop the minikube cluster:
minikube stop
(Optional) Delete the minikube VM:
minikube delete
References
- Kubernetes Official Documentation
- minikube Documentation
- Docker Documentation
- kubectl Cheat Sheet
- Kubernetes Deployment Guide
Congratulations! You’ve deployed your first Kubernetes application. 🎉 This is just the start—next, explore scaling, rolling updates, or deploying to a cloud Kubernetes service like EKS, GKE, or AKS.