目录

Docker Compose vs Kubernetes:2023 年该如何选择

前言

“小项目用 Compose,大项目上 K8s”——这句在开发者社区流传的话,大致方向是对的,但实际的技术选型远比这复杂。2023 年,Kubernetes 的复杂度依然让人望而却步,而 Docker Compose 也在逐步进化。本文将抛开"K8s 就是高大上"的滤镜,从你真实的业务场景出发,帮你做选择。

核心差异一览

先看一张总览表——两种方案的定位完全不同:

对比维度 Docker Compose Kubernetes
定位 单机容器编排 集群容器编排
学习成本 低(1-2 天) 高(数周至数月)
运维成本 几乎为零 需要专业运维团队
高可用 ❌ 不支持 ✅ 原生支持
自动伸缩 ❌ 不支持 ✅ HPA 自动伸缩
服务发现 DNS 内部解析 Service + DNS
滚动更新 基本支持 丰富策略
存储卷 本地绑定 多种 CSI 驱动
网络模型 简单桥接 CNI 插件(Calico、Flannel 等)
监控日志 docker logs Prometheus + EFK/Loki
安装复杂度 apt install docker-compose kubeadm / 托管集群

Docker Compose 的目标是让单机容器管理变得简单,K8s 的目标是让大规模集群变得可控

Docker Compose 详解

适合的场景

  • 个人项目 / 小团队:1-5 个微服务,单台服务器
  • 开发环境标准化:让团队所有人用相同的本地环境
  • CI/CD 中的测试环境:临时启停集成测试依赖
  • 小规模生产部署:无高可用要求的小型 SaaS 或 API

一个典型的 Compose 文件

version: "3.9"

services:
  # Web 后端
  api:
    build: ./api
    ports:
      - "8080:8080"
    environment:
      - DB_HOST=postgres
      - REDIS_HOST=redis
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_started

  # 数据库
  postgres:
    image: postgres:16
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=myapp
      - POSTGRES_PASSWORD_FILE=/run/secrets/db_password
    secrets:
      - db_password
    healthcheck:
      test: ["CMD-SHELL", "pg_isready"]
      interval: 5s

  # 缓存
  redis:
    image: redis:7-alpine
    volumes:
      - redisdata:/data

  # 前端静态文件
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./static:/usr/share/nginx/html:ro
    depends_on:
      - api

volumes:
  pgdata:
  redisdata:

secrets:
  db_password:
    file: ./secrets/db_password.txt

Compose 的进化:Docker Compose v2

2023 年,Docker Compose 从 Python 实现的 v1 全面转向 Go 实现的 v2(作为 Docker CLI 插件 docker compose,不带短横线):

# 新版本用法(docker compose 替代 docker-compose)
docker compose up -d          # 启动所有服务
docker compose ps              # 查看状态
docker compose logs -f         # 跟踪日志
docker compose exec api sh     # 进入容器
docker compose down            # 停止并清理
docker compose pull            # 拉取镜像更新

新版的改进:

  • 更快的解析速度:Go 原生实现,启动比 v1 快 3-5 倍
  • 更好的资源隔离:支持 --scale 实现简单的水平扩展
  • Watch 模式docker compose watch 自动同步文件变更到容器

Kubernetes 详解

适合的场景

  • 中大型团队:10 个以上微服务
  • 高可用要求:99.9% 以上可用性
  • 弹性伸缩需求:流量波动大,需要自动扩缩容
  • 多环境管理:开发 / 预发布 / 生产多套环境
  • 混合云 / 多云部署:需要跨云平台调度

必知的核心概念

概念 类比 说明
Pod 容器实例 K8s 的最小调度单元,一个或多个容器
Deployment 无状态应用 管理 Pod 的副本数和滚动更新
Service 稳定网络端点 为 Pod 提供固定的 DNS 和负载均衡
Ingress 反向代理 HTTP/HTTPS 路由到不同 Service
ConfigMap 配置文件 将配置从容器镜像中解耦
Secret 密钥 敏感信息存储
PersistentVolume 存储卷 有状态应用的数据持久化

一个简单的 K8s 部署

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
spec:
  replicas: 3
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      containers:
      - name: api
        image: myapp/api:latest
        ports:
        - containerPort: 8080
        env:
        - name: DB_HOST
          value: "postgres-service"
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 10
---
# service.yaml
apiVersion: v1
kind: Service
metadata:
  name: api-service
spec:
  selector:
    app: api
  ports:
  - port: 80
    targetPort: 8080
  type: ClusterIP
---
# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api-ingress
spec:
  rules:
  - host: api.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 80

这只是最基础的部署配置。实际生产还需要配置 HPA、NetworkPolicy、PodDisruptionBudget、RBAC 等,复杂度可见一斑。

2023 年的 K8s 趋势

  1. Sidecar-less 服务网格:Istio Ambient Mesh 在 2023 年进入 Beta,不再需要每个 Pod 挂载 Sidecar
  2. Gateway API 取代 Ingress:K8s 官方的新一代 API 网关标准,功能远超传统 Ingress
  3. K8s on the Edge:K3s、KubeEdge 等轻量级 K8s 发行版让容器编排走向边缘
  4. eBPF 深度集成:Cilium 成为 CNI 首选,eBPF 替代 iptables 带来性能飞跃

决策树:你到底该选哪个?

用下面的问题走一遍,就能明确方向:

你的应用需要运行在几台机器上?
├── 1 台 → Docker Compose(足够用了)
└── 多台 → 继续看下一个问题

你需要自愈(宕机自动重启)吗?
├── 是 → 考虑 K8s(Swarm 已边缘化)
└── 否 → 继续看

你的团队有专职运维吗?
├── 有 → K8s(托管集群更省心)
└── 无 → 继续看

你的服务数量?
├── 3 个以下 → Docker Compose + 单机 + 定时备份
├── 3-10 个 → Docker Compose / 托管 K8s(折中)
└── 10 个以上 → 托管 K8s(EKS/GKE/ACK)

折中方案:托管 K8s + Compose 本地开发

2023 年最常见的实际做法是两者都要

开发环境        → Docker Compose(本地快速启动)
CI 集成测试     → Docker Compose(轻量、无依赖)
预发布环境      → 托管 K8s(与生产一致)
生产环境        → 托管 K8s(高可用、弹性伸缩)

托管 K8s(EKS / GKE / AKS / ACK)可以大幅降低运维成本——你只管 kubectl apply,集群管理交给云厂商。

用 Compose 模拟 K8s 本地开发

2023 年的工具生态已经可以让你在本地用 Compose 风格的配置,跑出接近 K8s 的效果:

# docker-compose.yml 模拟 K8s 的 Secret 和 ConfigMap
version: "3.9"

configs:
  app_config:
    file: ./config/app.yaml

secrets:
  db_password:
    file: ./secrets/db_password.txt

services:
  api:
    image: myapp/api
    configs:
      - source: app_config
        target: /etc/config/app.yaml
    secrets:
      - db_password
    environment:
      - K8S_NAMESPACE=development

配合 kind(Kubernetes in Docker)或 k3d,也可以在本地启动一个真实的 K8s 集群:

# 用 kind 在本地启动一个 3 节点的 K8s 集群
kind create cluster --config kind-config.yaml --name dev

# 查看集群
kubectl cluster-info
kubectl get nodes

误区澄清

“K8s 就是 YAML 复杂?”

更准确的说法是:容器化本身就有一套抽象概念——网络、存储、配置、安全——在 Compose 中这些概念被简化,在 K8s 中被完整暴露。不是 K8s 的问题,而是你的应用复杂度到了需要这些抽象的时候。

“用 K8s 就不需要 Compose?”

❌ 实际上 K8s 官方也在自己的项目中大量使用 Compose。两个工具解决的是不同层面的事情。

“小项目用 Compose 以后能平滑迁移到 K8s?”

⚠️ 部分可以。如果你的 Compose 配置遵循了微服务的最佳实践(环境变量注入、无状态、健康检查),迁移成本可控。但如果用了大量 Compose 特有的特性(如 depends_on 隐式依赖、links),迁移会比较痛苦。

总结

你的情况 推荐方案
个人项目 / 小团队·单机 Docker Compose
小团队·多机·无专人运维 Docker Compose + 简单自动化部署脚本
中型团队·3-10 服务 托管 K8s(EKS/GKE)
大型团队·10+ 服务·高可用 托管 K8s + 专业运维
开发 / 测试环境 Docker Compose(不管线上用啥)

选择容器编排工具的核心原则:用最少的工具复杂度和运维成本,解决你的实际问题。 如果你的项目只有两个微服务 + 一个数据库,跑在一台 4 核 8G 的服务器上,Docker Compose 就是最好的选择——K8s 带来的高可用和弹性伸缩对你毫无意义,只会增加痛苦。

2023 年,容器编排的正确态度是:不要为了 K8s 而 K8s,但也别在需要它的时候硬扛。