在企业级应用开发中,容器化与编排技术已经成为基础设施的基石。本文将从实际生产场景出发,系统讲解 Docker 容器化到 Kubernetes 编排部署的完整工作流,帮助 DevOps 工程师和后端开发者构建可靠、高效的云原生应用交付体系。
一、Docker 容器化最佳实践
1.1 多阶段构建
多阶段构建是生产环境镜像优化的核心手段,能够将构建依赖与运行时环境严格分离,显著减小最终镜像体积。
# ===== 阶段一:构建阶段 =====
FROM node:20-alpine AS builder
WORKDIR /app
# 先复制依赖文件,利用 Docker 缓存层加速构建
COPY package.json package-lock.json ./
RUN npm ci --only=production
# 复制源码并构建
COPY . .
RUN npm run build
# ===== 阶段二:运行阶段 =====
FROM node:20-alpine AS runtime
# 创建非 root 用户
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
WORKDIR /app
# 仅从构建阶段复制必要产物
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/package.json ./
USER appuser
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
CMD ["node", "dist/server.js"]
1.2 镜像优化要点
-
选择精简基础镜像:优先使用
alpine、slim等变体,避免安装不必要的系统包 -
合并 RUN 指令:减少镜像层数,将相关操作用
&&连接 - 利用构建缓存:将不常变化的文件(如依赖声明)放在 Dockerfile 前部
-
设置
.dockerignore:排除.git、node_modules、*.md等无关文件
# .dockerignore
.git
.gitignore
node_modules
npm-debug.log
README.md
.env.local
二、Docker Compose 开发环境配置
在开发阶段,Docker Compose 能够快速搭建包含应用、数据库、缓存等完整依赖的本地环境。
# docker-compose.yml
version: "3.9"
services:
app:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "3000:3000"
environment:
- NODE_ENV=development
- DB_HOST=postgres
- DB_PORT=5432
- REDIS_HOST=redis
volumes:
- .:/app # 挂载源码实现热重载
- /app/node_modules
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
postgres:
image: postgres:16-alpine
environment:
POSTGRES_DB: myapp
POSTGRES_USER: appuser
POSTGRES_PASSWORD: secretpassword
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U appuser -d myapp"]
interval: 5s
timeout: 3s
retries: 5
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redisdata:/data
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
volumes:
pgdata:
redisdata:
三、Kubernetes 核心概念
在深入部署配置之前,先梳理 K8s 中最核心的几个资源对象:
| 资源对象 | 职责 |
|---|---|
| Pod | 最小调度单元,包含一个或多个共享网络与存储的容器 |
| Deployment | 声明式管理 Pod 副本数,支持滚动更新与回滚 |
| Service | 为 Pod 提供稳定的网络访问入口与负载均衡 |
| ConfigMap | 存储非敏感配置数据,以环境变量或卷挂载方式注入 Pod |
| Secret | 存储敏感数据(密码、证书等),Base64 编码存储 |
四、生产级 Kubernetes 部署配置
以下是一个完整的生产级部署方案,包含 Deployment、Service、ConfigMap、Secret 和 Ingress。
4.1 Namespace 与 ConfigMap
# namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
env: production
team: backend
---
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: production
data:
NODE_ENV: "production"
DB_HOST: "postgres-service"
DB_PORT: "5432"
DB_NAME: "myapp"
REDIS_HOST: "redis-service"
LOG_LEVEL: "info"
4.2 Secret
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: app-secrets
namespace: production
type: Opaque
data:
# 值需经过 base64 编码
DB_PASSWORD: c2VjcmV0cGFzc3dvcmQ=
JWT_SECRET: eW91ci1qd3Qtc2VjcmV0LWtleS0yMDI2
API_KEY: YWJjZGVmZzEyMzQ1Njc4
注意:生产环境中建议使用 Sealed Secrets、HashiCorp Vault 或云厂商的密钥管理服务来管理敏感数据,避免将 Secret 明文提交到代码仓库。
4.3 Deployment
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
namespace: production
labels:
app: myapp
version: v1.2.0
spec:
replicas: 3
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 滚动更新时最多多出 1 个 Pod
maxUnavailable: 0 # 更新期间不允许有 Pod 不可用
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
version: v1.2.0
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "3000"
prometheus.io/path: "/metrics"
spec:
serviceAccountName: myapp-sa
terminationGracePeriodSeconds: 60
# 反亲和性:确保 Pod 分散在不同节点
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- myapp
topologyKey: kubernetes.io/hostname
containers:
- name: myapp
image: registry.example.com/myapp:v1.2.0
ports:
- containerPort: 3000
protocol: TCP
# 资源限制与请求
resources:
requests:
cpu: "250m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "512Mi"
# 环境变量注入
envFrom:
- configMapRef:
name: app-config
- secretRef:
name: app-secrets
# 健康检查
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 15
periodSeconds: 20
timeoutSeconds: 5
failureThreshold: 3
readinessProbe:
httpGet:
path: /ready
port: 3000
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 3
failureThreshold: 3
startupProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 0
periodSeconds: 5
failureThreshold: 12 # 最多等待 60 秒启动
# 生命周期钩子
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 15"]
# 安全上下文
securityContext:
runAsNonRoot: true
runAsUser: 1000
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
4.4 Service 与 Ingress
# service.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-service
namespace: production
spec:
type: ClusterIP
selector:
app: myapp
ports:
- name: http
port: 80
targetPort: 3000
protocol: TCP
---
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp-ingress
namespace: production
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/rate-limit: "100"
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- app.example.com
secretName: app-tls-secret
rules:
- host: app.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp-service
port:
number: 80
五、健康检查与自动扩缩容
5.1 健康检查设计
K8s 提供三种探针(Probe),分别应对不同场景:
- livenessProbe:检测容器是否存活,失败则重启容器
- readinessProbe:检测容器是否就绪,失败则从 Service Endpoints 中摘除
- startupProbe:检测容器是否启动完成,适用于启动较慢的应用
5.2 HPA 自动扩缩容
# hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: myapp-hpa
namespace: production
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: myapp
minReplicas: 3
maxReplicas: 15
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
behavior:
scaleUp:
stabilizationWindowSeconds: 60
policies:
- type: Percent
value: 50
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 10
periodSeconds: 60
HPA 的 behavior 配置至关重要:扩容可以激进一些以快速响应流量增长,缩容则应保守以避免频繁波动。
六、滚动更新与回滚策略
6.1 滚动更新
K8s Deployment 默认采用滚动更新策略。在上述 Deployment 配置中,我们设置了 maxSurge: 1 和 maxUnavailable: 0,这意味着更新时会先创建新 Pod,确认其就绪后再终止旧 Pod,实现零停机部署。
# 执行滚动更新
kubectl set image deployment/myapp \
myapp=registry.example.com/myapp:v1.3.0 \
-n production
# 查看更新状态
kubectl rollout status deployment/myapp -n production
# 查看更新历史
kubectl rollout history deployment/myapp -n production
6.2 回滚
当新版本出现问题时,可以快速回滚到上一个稳定版本:
# 回滚到上一版本
kubectl rollout undo deployment/myapp -n production
# 回滚到指定版本
kubectl rollout undo deployment/myapp --to-revision=2 -n production
# 查看当前版本
kubectl rollout history deployment/myapp -n production
七、监控与日志
7.1 Prometheus + Grafana 监控栈
在 Deployment 中已通过注解暴露了 /metrics 端点。以下是 Prometheus 的 ServiceMonitor 配置:
# servicemonitor.yaml
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: myapp-monitor
namespace: production
labels:
release: prometheus
spec:
selector:
matchLabels:
app: myapp
endpoints:
- port: http
path: /metrics
interval: 15s
scrapeTimeout: 10s
7.2 日志收集
生产环境推荐使用 EFK(Elasticsearch + Fluentd + Kibana)或 PLG(Promtail + Loki + Grafana)日志栈。以下是一个 Fluentd DaemonSet 的核心配置片段:
yaml
# fluentd-configmap.yaml(节选)
apiVersion: v1
kind: ConfigMap
metadata:
---
> 📢 **本文为精简版,完整版包含独家工具推荐和深度分析,请访问 [WD Tech Blog](https://wdsega.github.io) 查看!**
*关注我的博客获取最新科技资讯、AI教程和效率工具推荐!*

Top comments (0)