一、为什么需要从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"

这个配置在开发环境运行良好,但如果要部署到生产环境,你会面临几个问题:

  1. 如果web服务崩溃,需要手动重启;
  2. 无法根据流量自动扩展实例数量;
  3. 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"

四、渐进式迁移策略

推荐采用"双轨制"迁移:

  1. 阶段一:非核心服务先迁移,保留Compose用于开发环境
  2. 阶段二:使用Kompose工具自动转换(适合简单应用)
    kompose convert -f docker-compose.yml
    
  3. 阶段三:手动优化生成的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,建议:

  1. 使用Operator(如KubeDB)
  2. 配置定期备份到对象存储
  3. 测试时使用临时实例
# 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不仅是工具的更换,更是架构思维的升级。关键点在于:

  1. 理解K8s的核心抽象(Pod/Service/Ingress等)
  2. 设计适合业务的渐进式迁移路径
  3. 建立完善的监控告警体系

对于中小团队,可以先用Minikube或Kind搭建本地K8s环境测试。记住:没有完美的方案,只有最适合当前业务阶段的决策。