- Docker Compose 简化了本地环境和测试;Kubernetes 通过自动扩缩容、滚动更新和自我修复功能,大规模地协调工作负载。
- Compose 可在单个主机上运行,并支持 Docker;K8s 支持多种运行时、多节点集群和云部署。
- Kompose 加速了从 Compose 到 Kubernetes 的迁移;它支持提供程序、替代对象和标签来微调服务。
- 使用场景:Compose 用于开发/持续集成;Kubernetes 用于生产、物联网/边缘计算、大数据/机器学习以及多云/混合云场景。
如果你从事容器开发,迟早会遇到一个关键问题:Docker Compose还是 Kubernetes?这两种工具都用于容器化应用的生命周期管理,但它们的设计初衷并非解决完全相同的问题,也并非在相同的场景下使用。本文将深入比较这两种工具,并提供实际案例、真实场景以及从一种工具平滑迁移到另一种工具的技巧。
除了技术层面的考量,这项决策还会影响日常运营:部署时间、可扩展性、弹性、安全性以及成本。它还会影响典型的数据工程用例——管道、数据库、流处理、批处理、数据格式和治理——在这些用例中,编排对于提高生产力至关重要。
Docker 和 Docker Compose 是什么(它们真正的用途是什么)?
当我们谈论 Docker 时,我们实际上是在谈论一个生态系统:Docker Engine、Docker Hub、Dockerfile、Docker Compose ……引擎从镜像创建和运行容器;Hub 使共享容器变得容易;而 Compose 允许你在 YAML 文件中定义堆栈的多个部分,以便使用单个命令启动它们。
Compose 的诞生是为了让我们摆脱无休止的脚本和孤立的命令。只需一个 docker-compose.yml 文件,即可描述服务、网络和卷,然后通过一条“docker compose up”(或 V1 版本中的“docker-compose up”)命令即可启动并运行所有服务。它非常适合本地开发、集成测试、演示或CI 环境。
Compose 的一个典型示例可能是这样的,它包含一个 API 和一个 Postgres 数据库。请注意依赖项、变量和端口是如何在一个易于阅读的代码块中声明的:
version: '3.8'
services:
db:
image: postgres:latest
restart: always
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=postgres
ports:
- '5432:5432'
volumes:
- db:/var/lib/postgresql/data
networks:
- mynet
my-api:
container_name: my-api
build:
context: ./
image: my-api
depends_on:
- db
ports:
- '8080:8080'
environment:
DB_HOST: db
DB_PORT: 5432
DB_USER: postgres
DB_PASSWORD: postgres
DB_NAME: postgres
networks:
- mynet
networks:
mynet:
driver: bridge
volumes:
db:
driver: local
要在 Compose 中手动扩展,可以使用服务的扩展选项。在 Compose V2 中,通常使用 `up --scale` 命令(在 V1 中是 `docker-compose scale`):
docker compose up -d --scale my-api=3
请注意其局限性:Compose 是为单个主机设计的,它不会在节点之间进行负载均衡或自动扩缩容,更新通常是使用“build”和“up -d”手动重新创建容器。
什么是 Kubernetes?它相比 Compose 有哪些优势?
Kubernetes (K8s) 是一个分布式容器编排平台。它利用 Pod、Deployment 和 Service 等概念,在多节点集群上大规模管理部署,以运行生产工作负载。
在 Kubernetes 中,你不管理单个容器,而是管理 Pod(一个 Pod 可以包含一个或多个容器)。控制平面负责调度每个 Pod 的运行位置、暴露服务、分配流量、进行水平扩展以及监控工作负载的健康状况。
一个基本的部署可能如下所示,其中包含 3 个 Web 服务副本。定义模板、标签和暴露的端口:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deployment
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: my-web-image
ports:
- containerPort: 8000
为了实现负载均衡,云端通常会使用 LoadBalancer 服务。选择器会根据 Pod 的标签来路由流量。
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
selector:
app: web
ports:
- protocol: TCP
port: 80
targetPort: 8000
type: LoadBalancer
在生产环境中,Kubernetes 的优势在于其高性能自动化 (HPA)、滚动更新和自我恢复等功能。HPA会根据指标(例如 CPU 使用率)调整副本数量:
apiVersion: autoscaling/v2beta2
kind: HorizontalPodAutoscaler
metadata:
name: web-hpa
spec:
minReplicas: 1
maxReplicas: 10
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web-deployment
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
容器健康状况通过探针进行监控;如果探针失效,Kubernetes 会重启容器。这就是“自愈”的基础:
apiVersion: v1
kind: Pod
metadata:
name: web-pod
spec:
containers:
- name: web
image: my-web-image
ports:
- containerPort: 8000
livenessProbe:
httpGet:
path: /healthcheck
port: 8000
initialDelaySeconds: 15
periodSeconds: 15

主要异同点(直奔主题,不拐弯抹角)
它们的共同点在于:都使用容器,并通过 YAML 定义部署。这两种方案对开发人员和运维人员都很有用,并且在开发到生产的工作流程中能够很好地互补。
关键区别在于范围:Compose 以 Docker 为中心,并且是单主机的;Kubernetes 支持多种运行时和多节点集群,并可直接集成到云和托管服务中。
更重要的区别在于:Kubernetes 提供自动扩缩容、滚动更新和自我修复功能;而 Compose 则不具备这些功能。Kubernetes 使用 Pod 进行抽象;Compose 则直接与 Docker 容器交互。
此外,Kubernetes 还包含用于执行一次性任务或定时任务的 Jobs 和 CronJobs。这避免了系统定时任务和额外的容器化进程,使该平台成为定义自动化流程的天然场所。
在本地部署方面,Compose 的优势在于速度和简易性。但对于扩展到数百个节点或多云环境,Kubernetes 才是更合理的选择。Compose 可以利用 Docker Swarm 进行多主机部署,但其普及率和功能与 Kubernetes 的生态系统和成熟度相比仍有差距。
为什么需要管弦乐编排(以及每种编排方式最适合何时使用)
一个好的编排器可以为您提供:统一的配置和部署、定时启动、服务间的通信、负载均衡,以及通过对每个服务进行额外的治理来增强安全性。
Compose 以简洁易懂的方式涵盖了基础知识,使其成为开发、测试和演示的理想工具。然而,当您需要多节点、原生负载均衡和自动扩展,或者无需停机即可进行增量部署时,它的局限性就会显现出来。
另一方面,Kubernetes 是负载增长时的“平台”:多节点、自动扩展、高可用性和庞大的生态系统,原生支持 AWS、Azure、GCP 和托管选项。
实际应用案例(开发、数据等)
Compose 在以下方面表现出色:可复现的本地环境、端到端测试、持续集成/持续交付 (CI/CD) 和培训。使用 YAML 定义整个技术栈并通过单个命令启动,可以消除很多冗余信息。
Kubernetes 非常适合以下应用场景:生产应用、物联网和边缘计算、大数据和机器学习,以及多云/混合云环境。它能够管理对延迟、弹性和可观测性要求较高的分布式工作负载。
在数据工程领域,K8s 非常适合流式和批处理管道、数据库、队列和分析引擎,具有每个 pod 的资源控制和峰值自动扩展功能。
如果你的项目规模较小,只需一台主机即可运行,那么 Compose 就能轻松胜任。但当你的用户群不断增长,需要强大的容错能力和负载均衡功能时,就该考虑 Kubernetes 了。
网络、扩展和升级:实用性比较
Compose 会为每个项目创建一个网络,并解析每个服务的名称。在项目内部与容器通信非常简单且安全,但外部负载均衡和多主机托管并非其原生功能。
在 Kubernetes 中,Service 提供集群内部的DNS 发现和负载均衡;向外,您可以使用 LoadBalancer、NodePort 或 Ingress 来路由 HTTP/S 流量。
扩展性:Compose 只能手动在单个主机上扩展。Kubernetes 可以通过 HPA 进行水平扩展,也可以通过指标和/或事件进行编程式扩展。如果集群允许,它还可以扩展到更多节点。
更新:在 Compose 中,这些通常是手动重新创建。而 Kubernetes 采用滚动更新,并带有进度控制(kubectl rollout),而且如果出现问题,还可以回滚,从而最大限度地减少影响。
自愈能力:Compose 可以重启容器,但无法解决主机或运行时崩溃问题。Kubernetes会将 Pod 迁移到健康的节点,整个过程对用户透明。
开发人员生产力和运营经验
Compose 是 Docker 之上的一个轻量级层。它易于学习,反馈循环即时,非常适合迭代开发。
Kubernetes 引入了新的概念(Pod、Deployment、Service、Ingress、ConfigMap、PVC 等)。虽然学习曲线较为陡峭,但作为回报,您可以获得对部署、安全性、可观测性和可扩展性的精细控制。
在兼容性方面,Compose 优先考虑 Docker。Kubernetes支持多种运行时环境,并可与云服务提供商集成,这对于采用多云或混合云策略的公司至关重要。
如何顺利地从 Docker Compose 迁移到 Kubernetes
何时迁移?当您的应用程序不再“小”时,您需要多节点、可观测性、可扩展性和高可用性,或者您被要求进行金丝雀部署和蓝绿部署。
典型挑战:绘制服务网络图、设计带有 PV/PVC 的存储、将配置分离为 ConfigMaps/Secrets 以及审查每个容器的健康状况和就绪模式。
架构也需要重新考虑:Pod 作为部署单元,服务用于暴露端点,以及每个容器的资源(CPU/内存),以便调度程序能够完成其工作。
Kompose:只需几步即可从 Compose 过渡到 K8s
Kompose 可以将 docker-compose.yml 文件转换为 Kubernetes 或 OpenShift 清单文件。这是启动迁移的最直接方法,无需手动重写所有 YAML 文件。
开始之前,您需要一个 Kubectl 集群并配置好 kubectl。如果您要测试任何有状态的功能,建议至少使用两个工作节点(而非控制平面节点)。使用 `kubectl version` 命令检查您的 kubectl 版本。
安装:推荐的方法是从最新的 GitHub 发布版本下载二进制文件。您也可以使用 tar 包、macOS 上的 Homebrew 或“go get”(最后一种方法使用包含开发更改的 master 分支)。
基本转换:导航到 docker-compose.yml 目录并运行:
kompose convert
kubectl apply -f <archivos-generados>
Kompose 默认会生成 Deployment 和 Service。日志通常会列出创建的每个文件,应用更改后,您将在集群中看到已“创建”的 Deployment 和 Service。
访问:如果您使用 Minikube,可以轻松地暴露或查询服务。在云端,勾选“LoadBalancer Ingress”即可获取 LoadBalancer 服务的公网 IP 地址;使用 NodePort,您将在节点上打开一个端口。
清理:测试完成后,请移除已应用的资源。保持集群清洁,避免迭代之间发生冲突。
Kompose 高级选项(提供程序、对象和标签)
Kompose 支持 Kubernetes 和 OpenShift。如果您不指定“--provider”参数,则默认使用 Kubernetes。对于 OpenShift,它可以生成 DeploymentConfigs 和 ImageStreams,如果您使用构建指令,甚至可以生成 BuildConfigs。
它还支持多种输出格式:使用“-j”参数的 JSON、复制控制器 (ReplicationControllers)、守护进程集 (DaemonSets) 或 Helm Charts。“--replicas”标志允许您更改复制控制器中的副本数量;对于 Helm,它会生成基本的图表结构。
Kompose 特有的标签会影响 compose 流程中的转换。例如,您可以定义 Service 类型,或者是否通过 Ingress/Route公开端点。
| 标签 | 值 |
|---|---|
| kompose.service.type | 节点端口/集群IP/负载均衡器 |
| kompose.service.expose | true / 主机名 |
需要注意的细节:名称中带有“_”的将转换为“-”(K8s 不允许下划线),并且,如果服务使用卷,则部署策略将更改为“重新创建”,以避免与多个写入器发生冲突。
Kompose 支持多个版本和文件
Kompose 支持 Compose V1、V2 和 V3(由于 2.1 和 3.2 仍处于实验阶段,因此支持有限)。如果您一次传递多个 docker-compose 文件,它们将被合并,并且公共元素将被最新的文件覆盖,就像您使用覆盖命令一样。
在 Kubernetes 转换过程中,如果存在不兼容的密钥,您会看到类似“警告:不支持的密钥构建 - 已忽略”的消息。请放心,该工具会继续处理它能够识别的部分,其余部分留待稍后手动调整。
Kompose 之外:Move2Kube 和手动迁移
如果您需要更精细的控制,可以使用像 Move2Kube 这样的工具,它们可以分析您的 Compose 文件并生成更优化的 Kubernetes 工件。当您想要借鉴平台中的业务模式或模板时,这些工具非常有用。
手动迁移完全可行,并且在初始迁移之后几乎总是建议进行手动迁移。典型步骤包括:将服务转换为 Deployment/StatefulSet,将网络转换为 Services/Ingress,以及将卷转换为具有存储类别的 PV/PVC。
将 Compose 服务转换为 Deployment 的一个最简示例可能如下所示:将端口、镜像和标签传输到 Pod 模板:
# docker-compose.yml
version: '3'
services:
web:
build: .
ports:
- '8000:8000'
depends_on:
- db
# Kubernetes
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deployment
spec:
replicas: 1
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: my-web-image
ports:
- containerPort: 8000
对于状态管理(数据库、队列),请考虑使用 StatefulSet 和 PersistentVolumes。并非所有在 Compose 中“一起”部署的内容都应该放在同一个 Pod 中;应分离职责,并使用 Service 在组件之间进行通信。
数据场景:流式处理、批处理和治理
在复杂的数据管道中,K8s 非常适用:Jobs 用于批处理,CronJobs 用于时间窗口,Deployment 用于 API,Operator 用于 Kafka、Spark 或 Flink 等系统。
对于流媒体和数据库,社区运营商和图表有助于启动。与单主机解决方案相比,服务网格网络和资源控制可确保更可预测的延迟和服务级别目标 (SLO)。
在数据治理和安全方面,Kubernetes 提供了命名空间、策略和基于角色的访问控制 (RBAC) 机制,用于审计和隔离环境。这比 Compose 的本地部署方式更具实用优势。
最佳实践和一些小操作技巧
在 Compose 中:保持 YAML 文件简洁模块化;使用环境变量和 .env 文件;记录端口和依赖项;并在 CI 中反映本地运行的内容。
在 Kubernetes 中:定义CPU 和内存请求/限制,使用就绪/存活探测,将配置分离到 ConfigMap/Secret 中,并为每个服务应用适当的部署策略。
对于 Kubectl 的更新:使用 `kubectl set image` 和 `kubectl rollout status` 命令来监控进度,并在出现问题时回滚。这将防止生产环境停机。
如果你需要在 Compose 中执行特定的任务,你可以模拟它们,但在 Kubernetes 中使用 CronJobs/Jobs 会更简洁;你不会用额外的进程或主机 cron 来污染容器。
快速常见问题解答,避免混淆
Compose 能取代 Kubernetes 吗?不能。Compose 简化了单个主机上的多容器堆栈;Kubernetes 则以集群规模进行编排,并具有高可用性。
Compose 现在还在用吗?是的,用得非常多。它是一款理想的开发和测试工具,只需几个命令就能搭建完整的开发环境。
Kubernetes 比 Docker “更好”吗?它们是不同的东西:Docker 是容器平台;Kubernetes 则在集群中编排容器并添加高级操作。
我可以在不手动重写的情况下将我的 Compose 配置迁移到 Kubernetes 吗?可以,通过 Kompose 或 Docker Desktop 集成即可。这可以让你快速迈出第一步,之后你可以逐步完善。
细节:编程、OpenShift 和其他转换方案
K8s 不仅仅是持续部署:Jobs 和 CronJobs 可以处理一次性或计划性任务,而无需您管理系统 cron。
在 OpenShift 中,Kompose 可以生成DeploymentConfigs 和 ImageStreams,如果 Compose 有与 Git 仓库关联的构建,甚至可以生成 BuildConfigs。“--build-repo”和“--build-branch”标志用于调整源。
如果您需要不同的输出格式,Kompose 允许使用DaemonSet、ReplicationController 或 Helm Chart,而不是默认的 Deployment 和 Service。它还可以生成 JSON 文件,而不仅仅是 YAML 文件。
兼容性、警告和一些小问题
Kompose 支持 Compose V1/V2/V3(2.1 和 3.2 版本存在一些限制)。不支持的键会被忽略并显示警告信息,以便用户手动调整。
如果您的服务包含卷,Kompose 会将策略更改为“重新创建”,以避免对同一卷的并发访问。这对于有状态服务来说是正常的。
名称中的下划线会被转换为连字符。这是 Kubernetes 对对象名称的限制,因此请确保在 Compose 中正确命名,以免转换过程中出现意外情况。
要从外部访问,请检查服务类型:ClusterIP(内部)、NodePort(节点端口)或 LoadBalancer(云端公网 IP)。使用 Ingress,您将拥有清晰的 HTTP/S 路由和集中式 TLS。
如果在 Minikube 中进行测试,类似“minikube service <svc> --url”这样的命令会返回一个快速 URL。在 Cloud 中,请查看描述 Service 时的“LoadBalancer Ingress”字段。
一个有趣的现象是:在社区中,你会发现有关 Kubernetes 相关职位薪资和生产环境采用率接近 88% 的信息。这并不奇怪:它已成为事实上的标准。
总的来说,Kubernetes 的功能远不止 HTTP:服务网格、Operator 和 CRD进一步扩展了 Kubernetes 的应用范围。如果您之前使用过 Compose,一开始可能会感到不知所措,但这额外的功能最终会带来更强大的运维能力。
重置策略:有用的等效项
Compose 允许设置“restart: always/on-failure/no”。在 Kubernetes 中,根据具体情况,您将拥有具有相应重启策略的独立 Pod 或控制器(Deployment 或 RC)。
| docker-compose 重启 | K8s 中的对象 | 重启策略 |
|---|---|---|
| ““ / 总是 | 控制器(部署/RC) | 总是 |
| 失败时 | 下 | 失败时 |
| 没有 | 下 | 沒有時效 |
如果在 Compose 中有“计算”容器或临时任务(例如快速计算“π”),只需在 K8s 中将其实现为 Job 或 CronJob,并设置相应的策略,一切就绪。
选择 Compose 实现快速本地部署,当您的环境需要更强大的功能时,则选择 Kubernetes:它支持多节点、自动扩缩容、无缝部署,并具备真正的弹性。借助 Compose、Move2Kube 和一些必要的配置,过渡过程将非常顺畅。
最终,选择取决于规模和复杂性:Compose 非常适合开发、测试和单主机堆栈;Kubernetes 是企业、多云部署以及需要高级自动化、高可用性和拥有数千个集成的生态系统的团队的理想选择。
