部署Web应用 #
一、应用架构 #
本案例部署一个典型的三层Web应用。
text
应用架构
│
├── 前端层
│ └── Nginx静态页面
│
├── 后端层
│ └── API服务
│
└── 数据层
└── MySQL数据库
二、命名空间创建 #
yaml
apiVersion: v1
kind: Namespace
metadata:
name: webapp
labels:
app: webapp
bash
kubectl apply -f namespace.yaml
三、部署数据库 #
3.1 创建Secret #
yaml
apiVersion: v1
kind: Secret
metadata:
name: mysql-secret
namespace: webapp
type: Opaque
stringData:
mysql-root-password: rootpassword
mysql-user: webapp
mysql-password: webapppassword
3.2 创建PVC #
yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-pvc
namespace: webapp
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
3.3 部署MySQL #
yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
namespace: webapp
spec:
serviceName: mysql
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: mysql-root-password
- name: MYSQL_USER
valueFrom:
secretKeyRef:
name: mysql-secret
key: mysql-user
- name: MYSQL_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: mysql-password
- name: MYSQL_DATABASE
value: webapp
ports:
- containerPort: 3306
volumeMounts:
- name: data
mountPath: /var/lib/mysql
livenessProbe:
exec:
command:
- mysqladmin
- ping
- -h
- localhost
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
exec:
command:
- mysql
- -h
- 127.0.0.1
- -e
- SELECT 1
initialDelaySeconds: 5
periodSeconds: 2
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
volumes:
- name: data
persistentVolumeClaim:
claimName: mysql-pvc
---
apiVersion: v1
kind: Service
metadata:
name: mysql
namespace: webapp
spec:
selector:
app: mysql
ports:
- port: 3306
targetPort: 3306
四、部署后端API #
4.1 创建ConfigMap #
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: api-config
namespace: webapp
data:
DB_HOST: mysql
DB_PORT: "3306"
DB_NAME: webapp
4.2 部署API服务 #
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: api
namespace: webapp
spec:
replicas: 3
selector:
matchLabels:
app: api
template:
metadata:
labels:
app: api
spec:
containers:
- name: api
image: node:18-alpine
command: ["node", "server.js"]
workingDir: /app
env:
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: api-config
key: DB_HOST
- name: DB_USER
valueFrom:
secretKeyRef:
name: mysql-secret
key: mysql-user
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secret
key: mysql-password
ports:
- containerPort: 3000
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 5
periodSeconds: 5
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 200m
memory: 256Mi
---
apiVersion: v1
kind: Service
metadata:
name: api
namespace: webapp
spec:
selector:
app: api
ports:
- port: 3000
targetPort: 3000
五、部署前端 #
5.1 创建Nginx配置 #
yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
namespace: webapp
data:
nginx.conf: |
events {
worker_connections 1024;
}
http {
server {
listen 80;
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}
location /api {
proxy_pass http://api:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
}
5.2 部署前端 #
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: frontend
namespace: webapp
spec:
replicas: 2
selector:
matchLabels:
app: frontend
template:
metadata:
labels:
app: frontend
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
volumeMounts:
- name: config
mountPath: /etc/nginx/nginx.conf
subPath: nginx.conf
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 10
periodSeconds: 10
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 5
resources:
requests:
cpu: 50m
memory: 64Mi
limits:
cpu: 100m
memory: 128Mi
volumes:
- name: config
configMap:
name: nginx-config
---
apiVersion: v1
kind: Service
metadata:
name: frontend
namespace: webapp
spec:
selector:
app: frontend
ports:
- port: 80
targetPort: 80
六、配置Ingress #
yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: webapp-ingress
namespace: webapp
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: webapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend
port:
number: 80
七、完整部署脚本 #
bash
#!/bin/bash
# deploy.sh
echo "Creating namespace..."
kubectl apply -f namespace.yaml
echo "Deploying database..."
kubectl apply -f mysql-secret.yaml
kubectl apply -f mysql-pvc.yaml
kubectl apply -f mysql-statefulset.yaml
echo "Waiting for MySQL to be ready..."
kubectl wait --for=condition=ready pod -l app=mysql -n webapp --timeout=300s
echo "Deploying API..."
kubectl apply -f api-config.yaml
kubectl apply -f api-deployment.yaml
echo "Waiting for API to be ready..."
kubectl wait --for=condition=ready pod -l app=api -n webapp --timeout=300s
echo "Deploying frontend..."
kubectl apply -f nginx-config.yaml
kubectl apply -f frontend-deployment.yaml
echo "Configuring Ingress..."
kubectl apply -f ingress.yaml
echo "Deployment completed!"
kubectl get all -n webapp
八、验证部署 #
8.1 检查状态 #
bash
# 查看所有资源
kubectl get all -n webapp
# 查看Pod状态
kubectl get pods -n webapp
# 查看服务状态
kubectl get svc -n webapp
# 查看Ingress
kubectl get ingress -n webapp
8.2 测试访问 #
bash
# 获取Ingress地址
kubectl get ingress -n webapp
# 测试前端
curl -H "Host: webapp.example.com" http://<ingress-ip>
# 测试API
curl -H "Host: webapp.example.com" http://<ingress-ip>/api/health
九、扩缩容 #
9.1 手动扩容 #
bash
# 扩容API
kubectl scale deployment api --replicas=5 -n webapp
# 扩容前端
kubectl scale deployment frontend --replicas=3 -n webapp
9.2 自动扩容 #
yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api-hpa
namespace: webapp
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
十、清理资源 #
bash
# 删除所有资源
kubectl delete namespace webapp
# 或逐个删除
kubectl delete -f ingress.yaml
kubectl delete -f frontend-deployment.yaml
kubectl delete -f api-deployment.yaml
kubectl delete -f mysql-statefulset.yaml
kubectl delete -f mysql-pvc.yaml
kubectl delete -f mysql-secret.yaml
kubectl delete -f namespace.yaml
十一、总结 #
本案例展示了完整的Web应用部署流程:
| 组件 | 资源类型 | 说明 |
|---|---|---|
| 数据库 | StatefulSet | 有状态应用 |
| API | Deployment | 无状态应用 |
| 前端 | Deployment | 无状态应用 |
| Ingress | Ingress | 外部访问入口 |
下一步 #
让我们学习 部署数据库,深入了解有状态应用的部署方法。
最后更新:2026-03-28