cat > app.py << 'EOF'
from fastapi import FastAPI
import socket
import uvicorn
app = FastAPI()
@app.get("/")
def hello():
hostname = socket.gethostname()
return {"message": f"✅ 我的后端服务运行中!Pod 名称: {hostname}"}
@app.get("/health")
def health():
return {"status": "healthy", "hostname": socket.gethostname()}
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", port=5000)
EOF
cat > requirements.txt << 'EOF'
fastapi
uvicorn
EOF
创建DockerFile
cat > Dockerfile << 'EOF'
FROM python:3.11-slim
WORKDIR /app
# 复制依赖文件并安装
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# 复制应用代码
COPY app.py .
# 暴露端口
EXPOSE 5000
# 使用 uvicorn 运行(性能更好)
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "5000"]
EOF
# 构建镜像(使用 Docker)
docker build -t my-app:v1 .
# 查看镜像
docker images | grep my-app
导入镜像到 Containerd
# 因为你的集群使用 containerd,需要导入镜像
docker save my-app:v1 -o my-app.tar
sudo ctr -n k8s.io images import my-app.tar
# 验证导入成功
sudo crictl images | grep my-app
# 先复制 tar 文件到 node01
scp my-app.tar node01:~/
# 然后 SSH 到 node01 执行导入
ssh node01 "sudo ctr -n k8s.io images import ~/my-app.tar"
创建Pod,Deployment
cat > deployment.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-deployment
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: my-app:v1
ports:
- containerPort: 5000
imagePullPolicy: IfNotPresent
EOF
# 创建 deployment
kubectl apply -f deployment.yaml
# 查看 deployment 状态
kubectl get deployments
# 查看 Pod 状态(应该很快变成 Running)
kubectl get pods -w
测试
# 方法1:端口转发到本地
kubectl port-forward deployment/my-backend 5000:5000
# 打开另一个终端,测试
curl http://localhost:5000/
# 方法2:查看 Pod 日志
kubectl logs -l app=my-backend
kubectl delete pod my-backend-xxxxxx-xxxxx
设置 Requests 和 Limits
cat > deployment.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-deployment
spec:
replicas: 2 # 初始 2 个副本
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: my-app
image: my-app:v1
ports:
- containerPort: 5000
imagePullPolicy: IfNotPresent
resources:
requests:
cpu: "100m" # 请求 0.1 核 CPU
memory: "128Mi" # 请求 128MB 内存
limits:
cpu: "200m" # 最多使用 0.2 核 CPU
memory: "256Mi" # 最多使用 256MB 内存
EOF
# 应用更新
kubectl apply -f deployment.yaml
创建 HPA(Horizontal Pod Autoscaler)
cat > hpa.yaml << 'EOF'
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app-deployment
minReplicas: 2
maxReplicas: 4
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50 # CPU 使用率超过 50% 时扩容
EOF
# 创建 HPA
kubectl apply -f hpa.yaml
# 查看 HPA 状态
kubectl get hpa
创建 Service
cat > service.yaml << 'EOF'
apiVersion: v1
kind: Service
metadata:
name: my-app-service
spec:
selector:
app: my-app
ports:
- port: 5000
targetPort: 5000
EOF
kubectl apply -f service.yaml
创建 HPA
cat > hpa.yaml << 'EOF'
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: my-app-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: my-app-deployment
minReplicas: 2
maxReplicas: 4
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
EOF
kubectl apply -f hpa.yaml
# 查看 HPA 状态
kubectl get hpa
安装 metrics-server
# 下载并安装 metrics-server
kubectl apply -f https://github.com/kubernetes-sigs/metrics-
# 查看状态
kubectl get pods -n kube-system -l k8s-app=metrics-server
# 1. 删除所有 metrics-server 相关资源
kubectl delete deployment metrics-server -n kube-system --ignore-not-found=true
kubectl delete service metrics-server -n kube-system --ignore-not-found=true
kubectl delete apiservice v1beta1.metrics.k8s.io --ignore-not-found=true
# 2. 等待删除完成
sleep 5
# 3. 重新部署正确的配置
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: metrics-server
namespace: kube-system
labels:
k8s-app: metrics-server
spec:
replicas: 1
selector:
matchLabels:
k8s-app: metrics-server
template:
metadata:
labels:
k8s-app: metrics-server
spec:
serviceAccountName: metrics-server
containers:
- name: metrics-server
image: registry.k8s.io/metrics-server/metrics-server:v0.6.4
args:
- --kubelet-insecure-tls
- --kubelet-preferred-address-types=InternalIP,Hostname
- --cert-dir=/tmp
ports:
- containerPort: 10250
name: https
protocol: TCP
volumeMounts:
- name: tmp-dir
mountPath: /tmp
volumes:
- name: tmp-dir
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: metrics-server
namespace: kube-system
spec:
ports:
- port: 443
protocol: TCP
targetPort: 10250
selector:
k8s-app: metrics-server
---
apiVersion: apiregistration.k8s.io/v1
kind: APIService
metadata:
name: v1beta1.metrics.k8s.io
spec:
service:
name: metrics-server
namespace: kube-system
group: metrics.k8s.io
version: v1beta1
insecureSkipTLSVerify: true
groupPriorityMinimum: 100
versionPriority: 100
EOF
# 4. 等待 Pod 启动
sleep 10
# 5. 查看 Pod 状态(应该是 Running)
kubectl get pods -n kube-system -l k8s-app=metrics-server
# 6. 查看日志
kubectl logs -n kube-system -l k8s-app=metrics-server --tail=20
kubectl top nodes
创建压测 Pod
cat > load-generator.yaml << 'EOF'
apiVersion: v1
kind: Pod
metadata:
name: load-generator
spec:
containers:
- name: loader
image: busybox
command:
- /bin/sh
- -c
- |
echo "开始压测..."
while true; do
wget -q -O- http://my-app-service:5000/ > /dev/null 2>&1
done
EOF
kubectl apply -f load-generator.yaml
监控扩容
kubectl get pods -l app=my-app -w
kubectl get hpa -w
watch -n 2 'kubectl top pods -l app=my-app'
清理实验环境
# 删除压测 Pod
kubectl delete -f load-generator.yaml --ignore-not-found=true
kubectl delete pod load-generator-1 load-generator-2 load-generator-3 --ignore-not-found=true
# 等待5分钟,HPA 会自动缩容回 2
kubectl get pods -l app=my-app -w
# 完全清理(可选)
kubectl delete hpa my-app-hpa
kubectl delete service my-app-service
kubectl delete deployment my-app-deployment