一、为什么需要从Docker Compose迁移到Kubernetes
刚开始接触容器编排时,大多数人会选择Docker Compose,因为它简单易用,适合单机环境下的服务编排。但随着业务规模扩大,单机部署的局限性逐渐暴露:缺乏高可用性、难以动态扩缩容、服务发现能力弱等。这时候,Kubernetes(简称K8s)就成了更合适的选择。
举个例子,假设你有一个基于Node.js的微服务应用,最初用Docker Compose部署:
# docker-compose.yml (Node.js技术栈示例)
version: '3.8'
services:
web:
image: node:14
ports:
- "3000:3000"
volumes:
- ./app:/usr/src/app
working_dir: /usr/src/app
command: npm start
redis:
image: redis:alpine
ports:
- "6379:6379"
这个配置在开发环境运行良好,但如果要部署到生产环境,你会面临几个问题:
- 如果
web服务崩溃,需要手动重启; - 无法根据流量自动扩展实例数量;
- Redis没有持久化配置,数据可能丢失。
二、如何将Docker Compose配置转换为Kubernetes资源
Kubernetes的核心概念包括Deployment、Service、ConfigMap等。我们可以将上述Compose文件逐步转换。
1. 转换Node.js服务为Deployment
# web-deployment.yaml (Node.js技术栈示例)
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 3 # 默认启动3个副本
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: node:14
workingDir: /usr/src/app
command: ["npm", "start"]
ports:
- containerPort: 3000
volumeMounts:
- mountPath: /usr/src/app
name: app-volume
volumes:
- name: app-volume
hostPath:
path: ./app # 生产环境建议换成PersistentVolumeClaim
2. 转换Redis服务为StatefulSet
对于有状态服务(如Redis),建议使用StatefulSet:
# redis-statefulset.yaml (Node.js技术栈示例)
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: redis
spec:
serviceName: redis
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:alpine
ports:
- containerPort: 6379
volumeMounts:
- mountPath: /data
name: redis-data
volumeClaimTemplates:
- metadata:
name: redis-data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 1Gi
三、关键差异与迁移注意事项
1. 网络模型差异
Docker Compose默认创建桥接网络,而Kubernetes的Pod网络更复杂:
- 每个Pod有独立IP,容器共享网络命名空间
- 需要显式定义Service来实现服务发现
# web-service.yaml
apiVersion: v1
kind: Service
metadata:
name: web
spec:
selector:
app: web
ports:
- protocol: TCP
port: 80
targetPort: 3000
type: LoadBalancer # 生产环境可以用ClusterIP+Ingress
2. 配置管理方式
Compose使用环境变量或文件挂载,K8s推荐ConfigMap/Secret:
# configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: web-config
data:
NODE_ENV: production
API_ENDPOINT: "http://api.example.com"
四、渐进式迁移策略
推荐采用"双轨制"迁移:
- 阶段一:非核心服务先迁移,保留Compose用于开发环境
- 阶段二:使用Kompose工具自动转换(适合简单应用)
kompose convert -f docker-compose.yml - 阶段三:手动优化生成的K8s配置,添加健康检查、资源限制等
完整示例:添加资源限制和健康检查
# 优化后的web-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 3
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
spec:
containers:
- name: web
resources:
limits:
cpu: "1"
memory: "512Mi"
requests:
cpu: "0.5"
memory: "256Mi"
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
五、技术选型建议
适用场景
- 适合K8s:需要弹性伸缩、多环境部署、微服务架构
- 保留Compose:本地开发、单服务测试、CI/CD流水线
性能对比
- 启动速度:Compose > K8s
- 资源开销:K8s > Compose(约多消耗500MB内存)
- 网络延迟:K8s Service Mesh更优
六、常见问题解决方案
问题1:如何共享开发配置?
方案:使用Skaffold实现"热重载"开发体验:
# skaffold.yaml
apiVersion: skaffold/v2
kind: Config
deploy:
kubectl:
manifests:
paths: ["k8s/*.yaml"]
build:
local:
push: false
artifacts:
- image: web
context: .
docker:
dockerfile: Dockerfile
问题2:数据库迁移如何处理?
方案:对于MySQL/PostgreSQL,建议:
- 使用Operator(如KubeDB)
- 配置定期备份到对象存储
- 测试时使用临时实例
# mysql-operator示例(需预先安装Operator)
apiVersion: kubedb.com/v1alpha2
kind: MySQL
metadata:
name: mysql
spec:
version: "8.0"
storageType: Durable
storage:
storageClassName: "standard"
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
terminationPolicy: WipeOut
七、总结
从Docker Compose迁移到Kubernetes不仅是工具的更换,更是架构思维的升级。关键点在于:
- 理解K8s的核心抽象(Pod/Service/Ingress等)
- 设计适合业务的渐进式迁移路径
- 建立完善的监控告警体系
对于中小团队,可以先用Minikube或Kind搭建本地K8s环境测试。记住:没有完美的方案,只有最适合当前业务阶段的决策。
评论