Kubernetes 实战练习指南
🎯 练习目标
通过循序渐进的实战练习,掌握Kubernetes核心概念和操作技能。每个练习都包含目标 、步骤 、验证 和清理四个部分。
📚 练习前准备
环境要求
- 可用的Kubernetes集群(minikube、kind或云厂商集群)
- kubectl命令行工具
- 基础的Linux命令知识
验证环境
bash
# 检查kubectl连接
kubectl cluster-info
# 检查节点状态
kubectl get nodes
# 创建练习命名空间
kubectl create namespace k8s-labs
kubectl config set-context --current --namespace=k8s-labs
🚀 入门级练习
练习1:创建和管理Pod
目标:学会创建、查看和删除Pod
步骤:
bash
# 1. 创建一个简单的Pod
cat > nginx-pod.yaml << EOF
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
namespace: k8s-labs
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.20
ports:
- containerPort: 80
EOF
# 2. 应用配置
kubectl apply -f nginx-pod.yaml
# 3. 查看Pod状态
kubectl get pods
kubectl get pods -o wide
# 4. 查看Pod详情
kubectl describe pod nginx-pod
# 5. 查看Pod日志
kubectl logs nginx-pod
# 6. 进入Pod内部
kubectl exec -it nginx-pod -- /bin/bash
# 在容器内执行: curl localhost
# 退出: exit
验证:
bash
# Pod应该处于Running状态
kubectl get pod nginx-pod | grep Running
# 能够访问nginx服务
kubectl port-forward nginx-pod 8080:80 &
curl http://localhost:8080
清理:
bash
kubectl delete pod nginx-pod
pkill -f "port-forward"
练习2:使用Deployment管理应用
目标:学会创建Deployment并进行扩缩容、更新操作
步骤:
bash
# 1. 创建Deployment
cat > nginx-deployment.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
namespace: k8s-labs
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.20
ports:
- containerPort: 80
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "200m"
EOF
# 2. 部署应用
kubectl apply -f nginx-deployment.yaml
# 3. 查看Deployment和Pod
kubectl get deployments
kubectl get pods -l app=nginx
# 4. 扩容到5个副本
kubectl scale deployment nginx-deployment --replicas=5
kubectl get pods -l app=nginx
# 5. 更新镜像版本
kubectl set image deployment/nginx-deployment nginx=nginx:1.21
kubectl rollout status deployment/nginx-deployment
# 6. 查看更新历史
kubectl rollout history deployment/nginx-deployment
# 7. 回滚到上一版本
kubectl rollout undo deployment/nginx-deployment
kubectl rollout status deployment/nginx-deployment
验证:
bash
# 检查副本数量
kubectl get deployment nginx-deployment
# 检查Pod标签
kubectl get pods -l app=nginx --show-labels
清理:
bash
kubectl delete deployment nginx-deployment
练习3:创建Service暴露应用
目标:学会创建不同类型的Service
步骤:
bash
# 1. 先创建一个Deployment(如果前面删除了)
kubectl create deployment web-app --image=nginx:1.20 --replicas=3
# 2. 创建ClusterIP Service
cat > clusterip-service.yaml << EOF
apiVersion: v1
kind: Service
metadata:
name: web-clusterip
namespace: k8s-labs
spec:
type: ClusterIP
selector:
app: web-app
ports:
- port: 80
targetPort: 80
EOF
kubectl apply -f clusterip-service.yaml
# 3. 测试ClusterIP Service
kubectl run -it --rm debug --image=busybox --restart=Never -- wget -qO- http://web-clusterip
# 4. 创建NodePort Service
cat > nodeport-service.yaml << EOF
apiVersion: v1
kind: Service
metadata:
name: web-nodeport
namespace: k8s-labs
spec:
type: NodePort
selector:
app: web-app
ports:
- port: 80
targetPort: 80
nodePort: 30080
EOF
kubectl apply -f nodeport-service.yaml
# 5. 查看Service信息
kubectl get services
kubectl describe service web-nodeport
验证:
bash
# 检查端点
kubectl get endpoints
# 测试NodePort访问(如果是minikube)
minikube ip # 获取IP
curl http://$(minikube ip):30080
清理:
bash
kubectl delete service web-clusterip web-nodeport
kubectl delete deployment web-app
🎯 进阶级练习
练习4:ConfigMap和Secret使用
目标:学会使用ConfigMap和Secret管理应用配置
步骤:
bash
# 1. 创建ConfigMap
cat > app-config.yaml << EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: k8s-labs
data:
database_host: "mysql.example.com"
database_port: "3306"
log_level: "INFO"
app.properties: |
spring.datasource.url=jdbc:mysql://mysql.example.com:3306/mydb
logging.level.root=INFO
server.port=8080
EOF
# 2. 创建Secret
cat > app-secret.yaml << EOF
apiVersion: v1
kind: Secret
metadata:
name: app-secret
namespace: k8s-labs
type: Opaque
data:
database_user: YWRtaW4= # base64 encoded "admin"
database_password: cGFzc3dvcmQ= # base64 encoded "password"
EOF
# 3. 应用配置
kubectl apply -f app-config.yaml
kubectl apply -f app-secret.yaml
# 4. 创建使用配置的Pod
cat > config-pod.yaml << EOF
apiVersion: v1
kind: Pod
metadata:
name: config-test-pod
namespace: k8s-labs
spec:
containers:
- name: test-container
image: busybox
command: ["sleep", "3600"]
env:
- name: DATABASE_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: database_host
- name: DATABASE_USER
valueFrom:
secretKeyRef:
name: app-secret
key: database_user
envFrom:
- configMapRef:
name: app-config
volumeMounts:
- name: config-volume
mountPath: /etc/config
- name: secret-volume
mountPath: /etc/secrets
volumes:
- name: config-volume
configMap:
name: app-config
- name: secret-volume
secret:
secretName: app-secret
EOF
kubectl apply -f config-pod.yaml
# 5. 验证配置加载
kubectl exec -it config-test-pod -- env | grep DATABASE
kubectl exec -it config-test-pod -- ls -la /etc/config
kubectl exec -it config-test-pod -- cat /etc/config/app.properties
kubectl exec -it config-test-pod -- ls -la /etc/secrets
验证:
bash
# 检查环境变量
kubectl exec config-test-pod -- printenv | grep DATABASE
# 检查挂载的文件
kubectl exec config-test-pod -- cat /etc/config/database_host
清理:
bash
kubectl delete pod config-test-pod
kubectl delete configmap app-config
kubectl delete secret app-secret
练习5:持久化存储使用
目标:学会使用PV和PVC进行数据持久化
步骤:
bash
# 1. 创建PersistentVolume(本地存储示例)
cat > local-pv.yaml << EOF
apiVersion: v1
kind: PersistentVolume
metadata:
name: local-pv
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
persistentVolumeReclaimPolicy: Delete
storageClassName: local-storage
local:
path: /tmp/k8s-data
nodeAffinity:
required:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/hostname
operator: In
values:
- $(kubectl get nodes -o jsonpath='{.items[0].metadata.name}')
EOF
# 2. 创建目录(在节点上)
kubectl get nodes -o wide # 查看节点
# 如果是单节点集群,在本地执行:
sudo mkdir -p /tmp/k8s-data
kubectl apply -f local-pv.yaml
# 3. 创建PersistentVolumeClaim
cat > local-pvc.yaml << EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: local-pvc
namespace: k8s-labs
spec:
accessModes:
- ReadWriteOnce
storageClassName: local-storage
resources:
requests:
storage: 500Mi
EOF
kubectl apply -f local-pvc.yaml
# 4. 创建使用存储的Pod
cat > storage-pod.yaml << EOF
apiVersion: v1
kind: Pod
metadata:
name: storage-test-pod
namespace: k8s-labs
spec:
containers:
- name: test-container
image: busybox
command: ["sleep", "3600"]
volumeMounts:
- name: storage-volume
mountPath: /data
volumes:
- name: storage-volume
persistentVolumeClaim:
claimName: local-pvc
EOF
kubectl apply -f storage-pod.yaml
# 5. 测试数据持久化
kubectl exec -it storage-test-pod -- sh -c 'echo "Hello K8s Storage!" > /data/test.txt'
kubectl exec -it storage-test-pod -- cat /data/test.txt
# 6. 删除Pod后重新创建,验证数据仍在
kubectl delete pod storage-test-pod
kubectl apply -f storage-pod.yaml
# 等待Pod启动
kubectl wait --for=condition=Ready pod/storage-test-pod
kubectl exec -it storage-test-pod -- cat /data/test.txt
验证:
bash
# 检查PV和PVC状态
kubectl get pv
kubectl get pvc
# 检查绑定关系
kubectl describe pvc local-pvc
清理:
bash
kubectl delete pod storage-test-pod
kubectl delete pvc local-pvc
kubectl delete pv local-pv
sudo rm -rf /tmp/k8s-data
练习6:健康检查配置
目标:学会配置Liveness和Readiness探针
步骤:
bash
# 1. 创建带健康检查的应用
cat > health-check-app.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: health-app
namespace: k8s-labs
spec:
replicas: 2
selector:
matchLabels:
app: health-app
template:
metadata:
labels:
app: health-app
spec:
containers:
- name: app
image: nginx:1.20
ports:
- containerPort: 80
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 5
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "200m"
---
apiVersion: v1
kind: Service
metadata:
name: health-app-service
namespace: k8s-labs
spec:
selector:
app: health-app
ports:
- port: 80
targetPort: 80
EOF
kubectl apply -f health-check-app.yaml
# 2. 观察Pod启动过程
kubectl get pods -l app=health-app -w
# 3. 检查健康检查状态
kubectl describe pod -l app=health-app
# 4. 模拟应用故障
POD_NAME=$(kubectl get pods -l app=health-app -o jsonpath='{.items[0].metadata.name}')
kubectl exec -it $POD_NAME -- rm /usr/share/nginx/html/index.html
# 5. 观察Pod重启
kubectl get pods -l app=health-app -w
验证:
bash
# 检查探针配置
kubectl get pod $POD_NAME -o yaml | grep -A 10 "livenessProbe\|readinessProbe"
# 查看重启次数
kubectl get pods -l app=health-app
清理:
bash
kubectl delete -f health-check-app.yaml
🏆 高级练习
练习7:完整Web应用部署
目标:部署一个包含前端、后端和数据库的完整应用
步骤:
bash
# 1. 创建MySQL数据库
cat > mysql-deployment.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
namespace: k8s-labs
spec:
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:5.7
env:
- name: MYSQL_ROOT_PASSWORD
value: "rootpassword"
- name: MYSQL_DATABASE
value: "webapp"
- name: MYSQL_USER
value: "webuser"
- name: MYSQL_PASSWORD
value: "webpassword"
ports:
- containerPort: 3306
volumeMounts:
- name: mysql-storage
mountPath: /var/lib/mysql
volumes:
- name: mysql-storage
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: mysql-service
namespace: k8s-labs
spec:
selector:
app: mysql
ports:
- port: 3306
targetPort: 3306
EOF
# 2. 创建后端应用配置
cat > backend-config.yaml << EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: backend-config
namespace: k8s-labs
data:
DATABASE_HOST: "mysql-service"
DATABASE_NAME: "webapp"
DATABASE_PORT: "3306"
---
apiVersion: v1
kind: Secret
metadata:
name: backend-secret
namespace: k8s-labs
type: Opaque
data:
DATABASE_USER: d2VidXNlcg== # webuser
DATABASE_PASSWORD: d2VicGFzc3dvcmQ= # webpassword
EOF
# 3. 创建后端应用(使用nginx模拟)
cat > backend-deployment.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
namespace: k8s-labs
spec:
replicas: 2
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: backend
image: nginx:1.20
ports:
- containerPort: 80
env:
- name: DATABASE_HOST
valueFrom:
configMapKeyRef:
name: backend-config
key: DATABASE_HOST
- name: DATABASE_USER
valueFrom:
secretKeyRef:
name: backend-secret
key: DATABASE_USER
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 10
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: backend-service
namespace: k8s-labs
spec:
selector:
app: backend
ports:
- port: 80
targetPort: 80
EOF
# 4. 创建前端应用
cat > frontend-deployment.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
namespace: k8s-labs
spec:
replicas: 3
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: frontend
image: nginx:1.20
ports:
- containerPort: 80
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/conf.d
volumes:
- name: nginx-config
configMap:
name: nginx-config
---
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
namespace: k8s-labs
data:
default.conf: |
server {
listen 80;
server_name _;
location /api/ {
proxy_pass http://backend-service/;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
}
location / {
root /usr/share/nginx/html;
index index.html;
try_files \$uri \$uri/ /index.html;
}
}
---
apiVersion: v1
kind: Service
metadata:
name: frontend-service
namespace: k8s-labs
spec:
type: NodePort
selector:
app: frontend
ports:
- port: 80
targetPort: 80
nodePort: 30081
EOF
# 5. 按顺序部署所有组件
kubectl apply -f mysql-deployment.yaml
kubectl apply -f backend-config.yaml
kubectl apply -f backend-deployment.yaml
kubectl apply -f frontend-deployment.yaml
# 6. 等待所有Pod就绪
kubectl wait --for=condition=Ready pod -l app=mysql --timeout=120s
kubectl wait --for=condition=Ready pod -l app=backend --timeout=120s
kubectl wait --for=condition=Ready pod -l app=frontend --timeout=120s
# 7. 查看部署状态
kubectl get all
验证:
bash
# 检查所有组件状态
kubectl get pods,svc
# 测试前端访问
curl http://$(minikube ip):30081
# 测试后端API
kubectl port-forward svc/backend-service 8080:80 &
curl http://localhost:8080
清理:
bash
kubectl delete -f frontend-deployment.yaml
kubectl delete -f backend-deployment.yaml
kubectl delete -f backend-config.yaml
kubectl delete -f mysql-deployment.yaml
pkill -f "port-forward"
练习8:自动扩缩容配置
目标:配置HPA实现Pod自动扩缩容
步骤:
bash
# 1. 确保metrics-server运行(minikube用户)
minikube addons enable metrics-server
# 2. 创建测试应用
cat > hpa-test-app.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: hpa-test
namespace: k8s-labs
spec:
replicas: 1
selector:
matchLabels:
app: hpa-test
template:
metadata:
labels:
app: hpa-test
spec:
containers:
- name: php-apache
image: k8s.gcr.io/hpa-example
ports:
- containerPort: 80
resources:
requests:
cpu: 200m
limits:
cpu: 500m
---
apiVersion: v1
kind: Service
metadata:
name: hpa-test-service
namespace: k8s-labs
spec:
selector:
app: hpa-test
ports:
- port: 80
targetPort: 80
EOF
kubectl apply -f hpa-test-app.yaml
# 3. 创建HPA
kubectl autoscale deployment hpa-test --cpu-percent=50 --min=1 --max=10
# 4. 查看HPA状态
kubectl get hpa
# 5. 生成负载测试扩缩容
kubectl run -it --rm load-generator --image=busybox --restart=Never -- sh -c "while true; do wget -q -O- http://hpa-test-service; done"
# 在另一个终端窗口观察扩缩容
kubectl get hpa -w
kubectl get pods -l app=hpa-test -w
验证:
bash
# 查看HPA详情
kubectl describe hpa hpa-test
# 查看Pod数量变化
kubectl get deployment hpa-test
清理:
bash
kubectl delete hpa hpa-test
kubectl delete -f hpa-test-app.yaml
🎓 挑战练习
挑战1:蓝绿部署
目标:实现应用的蓝绿部署
提示:
- 创建两个版本的Deployment(blue和green)
- 使用Service标签选择器切换流量
- 验证新版本后切换流量
挑战2:多环境配置
目标:为同一应用配置开发、测试、生产三套环境
提示:
- 使用不同的Namespace
- 配置不同的资源限制
- 使用不同的ConfigMap和Secret
挑战3:故障演练
目标:模拟各种故障场景并排查
提示:
- 模拟Pod崩溃
- 模拟网络不通
- 模拟存储故障
- 模拟资源不足
📊 练习进度跟踪
入门级 ✅
- 练习1:Pod基本操作
- 练习2:Deployment管理
- 练习3:Service使用
进阶级 ✅
- 练习4:配置管理
- 练习5:存储使用
- 练习6:健康检查
高级 ✅
- 练习7:完整应用部署
- 练习8:自动扩缩容
挑战级 🎯
- 挑战1:蓝绿部署
- 挑战2:多环境配置
- 挑战3:故障演练
🎉 总结
恭喜您完成所有练习!通过这些实战练习,您已经掌握了:
- 基础操作:Pod、Deployment、Service的创建和管理
- 配置管理:ConfigMap和Secret的使用
- 存储管理:持久化数据的处理
- 健康检查:应用可靠性保障
- 完整应用:多组件应用的部署
- 自动化:扩缩容和运维自动化
继续实践和探索,成为Kubernetes专家!🚀
📚 下一步学习建议
- 深入学习:Helm、Operator、Istio等高级工具
- 云原生生态:了解CNCF生态系统
- 生产实践:参与实际项目的K8s运维
- 社区参与:加入K8s社区,贡献开源项目
加油,K8s专家之路就在脚下!💪