Deployment Tutorials
Learn by example with these practical deployment tutorials for Mycelium Cloud.
Prerequisites
Before starting these tutorials, ensure you have:
- ✅ Deployed cluster with kubectl access
- ✅ Mycelium running for network access
- ✅ kubectl configured with your cluster
# Verify your setup
kubectl get nodes
# Should show your cluster nodes
Tutorial 1: Hello World with Nginx
Deploy a simple web server to verify your cluster is working.
Step 1: Create the Deployment
Save as hello-world-deploy.yaml
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-world
spec:
replicas: 1
selector:
matchLabels:
app: hello-world
template:
metadata:
labels:
app: hello-world
spec:
containers:
- name: nginx
image: nginx:1.21
ports:
- containerPort: 80
Apply it:
kubectl apply -f hello-world-deploy.yaml
Step 2: Expose the Service
Save as hello-world-svc.yaml
:
apiVersion: v1
kind: Service
metadata:
name: hello-world-service
spec:
selector:
app: hello-world
ports:
- port: 80
targetPort: 80
type: ClusterIP
Apply it:
kubectl apply -f hello-world-svc.yaml
Step 3: Access Your Application
# Port forward to local machine
kubectl port-forward service/hello-world-service 8080:80
Open http://localhost:8080
- you should see the Nginx welcome page!
Cleanup
kubectl delete -f hello-world-deploy.yaml
kubectl delete -f hello-world-svc.yaml
Tutorial 2: Python Servers with Load Balancing
Deploy multiple Python HTTP servers to demonstrate load balancing.
Step 1: Create the Deployments
Save as python-servers.yaml
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: python-server-1
spec:
replicas: 2
selector:
matchLabels:
app: python-server
server-id: "1"
template:
metadata:
labels:
app: python-server
server-id: "1"
spec:
containers:
- name: python-server
image: python:3.9-slim
command: ["python", "-c"]
args:
- |
import http.server, socketserver, json
class Handler(http.server.SimpleHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
response = {"server": "Python Server 1", "pod": "$(hostname)"}
self.wfile.write(json.dumps(response).encode())
with socketserver.TCPServer(("", 8000), Handler) as httpd:
httpd.serve_forever()
ports:
- containerPort: 8000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: python-server-2
spec:
replicas: 2
selector:
matchLabels:
app: python-server
server-id: "2"
template:
metadata:
labels:
app: python-server
server-id: "2"
spec:
containers:
- name: python-server
image: python:3.9-slim
command: ["python", "-c"]
args:
- |
import http.server, socketserver, json
class Handler(http.server.SimpleHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
response = {"server": "Python Server 2", "pod": "$(hostname)"}
self.wfile.write(json.dumps(response).encode())
with socketserver.TCPServer(("", 8000), Handler) as httpd:
httpd.serve_forever()
ports:
- containerPort: 8000
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: python-server-3
spec:
replicas: 2
selector:
matchLabels:
app: python-server
server-id: "3"
template:
metadata:
labels:
app: python-server
server-id: "3"
spec:
containers:
- name: python-server
image: python:3.9-slim
command: ["python", "-c"]
args:
- |
import http.server, socketserver, json
class Handler(http.server.SimpleHTTPRequestHandler):
def do_GET(self):
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
response = {"server": "Python Server 3", "pod": "$(hostname)"}
self.wfile.write(json.dumps(response).encode())
with socketserver.TCPServer(("", 8000), Handler) as httpd:
httpd.serve_forever()
ports:
- containerPort: 8000
Step 2: Create Load Balancing Service
Save as python-lb-service.yaml
:
apiVersion: v1
kind: Service
metadata:
name: python-lb
spec:
selector:
app: python-server
ports:
- port: 80
targetPort: 8000
type: ClusterIP
Step 3: Deploy Everything
kubectl apply -f python-servers.yaml
kubectl apply -f python-lb-service.yaml
# Wait for pods to be ready
kubectl get pods -l app=python-server
Step 4: Test Load Balancing
# Port forward the service
kubectl port-forward service/python-lb 8080:80
# In another terminal, test the load balancing
for i in {1..10}; do
curl http://localhost:8080
done
You'll see responses from different servers and pods, showing the load balancing in action!
Cleanup
kubectl delete -f python-servers.yaml
kubectl delete -f python-lb-service.yaml
Tutorial 3: Stateful Application with Persistent Storage
Deploy a simple application that persists data.
Step 1: Create Persistent Volume Claim
Save as storage.yaml
:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: data-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
Step 2: Create Stateful Deployment
Save as stateful-app.yaml
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: data-app
spec:
replicas: 1
selector:
matchLabels:
app: data-app
template:
metadata:
labels:
app: data-app
spec:
containers:
- name: app
image: busybox:latest
command: ["sh", "-c"]
args:
- |
echo "Starting data application..."
while true; do
date >> /data/log.txt
echo "Written at $(date)" >> /data/log.txt
sleep 10
done
volumeMounts:
- name: data
mountPath: /data
volumes:
- name: data
persistentVolumeClaim:
claimName: data-pvc
Step 3: Deploy and Verify
kubectl apply -f storage.yaml
kubectl apply -f stateful-app.yaml
# Wait for pod to be ready
kubectl get pods -l app=data-app
# Check the logs being written
kubectl exec -it $(kubectl get pod -l app=data-app -o name) -- cat /data/log.txt
Step 4: Test Persistence
# Delete the pod
kubectl delete pod -l app=data-app
# Wait for new pod to start
kubectl get pods -l app=data-app
# Check data persisted
kubectl exec -it $(kubectl get pod -l app=data-app -o name) -- cat /data/log.txt
The data from before the pod deletion should still be there!
Cleanup
kubectl delete -f stateful-app.yaml
kubectl delete -f storage.yaml
Tutorial 4: Multi-Tier Application
Deploy a simple web app with a database backend.
Step 1: Deploy Redis Database
Save as redis.yaml
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:7-alpine
ports:
- containerPort: 6379
---
apiVersion: v1
kind: Service
metadata:
name: redis
spec:
selector:
app: redis
ports:
- port: 6379
targetPort: 6379
type: ClusterIP
Step 2: Deploy Frontend Application
Save as frontend.yaml
:
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
spec:
replicas: 3
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: frontend
image: nginx:alpine
ports:
- containerPort: 80
env:
- name: REDIS_HOST
value: "redis"
- name: REDIS_PORT
value: "6379"
---
apiVersion: v1
kind: Service
metadata:
name: frontend
spec:
selector:
app: frontend
ports:
- port: 80
targetPort: 80
type: ClusterIP
Step 3: Deploy and Access
kubectl apply -f redis.yaml
kubectl apply -f frontend.yaml
# Wait for all pods
kubectl get pods
# Port forward to access frontend
kubectl port-forward service/frontend 8080:80
Open http://localhost:8080
to access your multi-tier application.
Cleanup
kubectl delete -f frontend.yaml
kubectl delete -f redis.yaml
Best Practices
Resource Limits
Always set resource limits:
resources:
requests:
memory: "64Mi"
cpu: "250m"
limits:
memory: "128Mi"
cpu: "500m"
Health Checks
Add liveness and readiness probes:
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
Labels and Annotations
Use descriptive labels:
metadata:
labels:
app: myapp
version: v1.0
environment: production
Troubleshooting
Pods Not Starting
# Check pod status
kubectl describe pod <pod-name>
# Check logs
kubectl logs <pod-name>
# Check events
kubectl get events --sort-by='.lastTimestamp'
Service Not Accessible
# Check service
kubectl describe service <service-name>
# Check endpoints
kubectl get endpoints <service-name>
# Test from within cluster
kubectl run -it --rm debug --image=alpine --restart=Never -- sh
# Then: wget -O- http://service-name
Resource Issues
# Check node resources
kubectl top nodes
# Check pod resources
kubectl top pods
# Check resource requests/limits
kubectl describe nodes
Next Steps
Now that you've completed these tutorials:
- Deploy your own applications
- Explore Helm for package management
- Learn about Ingress controllers for advanced routing
- Study StatefulSets for databases
- Explore ConfigMaps and Secrets for configuration management
These tutorials cover the basics. The real power of Kubernetes comes from combining these concepts to build complex, scalable applications on the ThreeFold Grid!