Docker 与 Kubernetes:主要区别、它们如何协同工作以及您需要哪些

  1. 首页
  2. 博客
  3. 开发运营

开发运营

Docker 与 Kubernetes:主要区别、它们如何协同工作以及您需要哪些

Docker 和 Kubernetes 并不是真正的竞争对手。一台打包并运行容器,而另一台在多台机器上管理容器。了解两者的适用范围,查看一个应用程序同时运行这两种方法,并确定您的项目需要什么。

阅读约 9 分钟
Docker 与 Kubernetes:主要区别、它们如何协同工作以及您需要哪些

要点速览

  • Docker 通常在一台机器上构建映像并运行容器。
  • Kubernetes 跨机器集群调度和管理容器。
  • 它们通常一起使用:Docker 构建镜像,Kubernetes 在生产中运行它。
  • 更公平的比较是 Kubernetes 与 Docker Swarm 或 Compose,许多小型项目根本不需要 Kubernetes。

搜索 Docker vs Kubernetes 表明您必须选择一个,但该框架会导致很多混乱。这有点像将一个集装箱与容纳数千个集装箱的港口进行比较。它们在不同的级别上运行,并且经常同时使用。

本指南解释了每个应用程序的用途,在两个应用程序中显示了相同的小应用程序,并以一种实用的方法结束。此处的命令和文件是我们在本文中未执行的标准示例,因此请根据您安装的版本检查它们。

简短的回答

Docker 是一个平台,用于将应用程序及其依赖项打包到映像中,然后将该映像作为容器运行。它回答了“如何让这个应用程序在任何地方都以相同的方式运行?”的问题。

Kubernetes,通常写作 K8s,是一个容器编排器。它决定容器在多台机器上运行的位置,在发生故障时重新启动它们,并根据需求进行扩展。它回答了“如何保持数百个容器可靠运行?”的问题。

Docker 与 Kubernetes 对比

方面 码头工人 库伯内斯
主要工作 构建并运行容器 编排容器
适用范围 通常一台主机 由许多节点组成的集群
构建图像? 是的 否
基本单位 集装箱 Pod(一个或多个容器)
配置 Dockerfile, compose.yaml YAML 清单
失败的容器 该主机上的可选重启策略 自动替换,即使在另一个节点上也是如此
缩放 手动,在一台主机上使用 Compose 声明式,具有自动缩放选项
网络 主机上的桥接网络 集群范围的服务和 DNS
学习曲线 温柔 陡峭
最适合 开发和小型部署 大型生产系统

Docker 是做什么的

在容器出现之前,“它可以在我的机器上运行”是一个日常问题,因为每个服务器都有不同的版本。 Docker 将您的代码、运行时和库捆绑到一个 映像 中。该映像的运行副本是一个容器,它共享主机的内核,因此与完整的虚拟机相比,它启动速度更快,使用的内存更少。

工作流程分为三个步骤:

  1. Build:a Dockerfile 描述如何创建映像。
  2. Ship: 将映像推送到注册表,例如 Docker Hub。
  3. 运行: 在任何兼容计算机上从该映像启动容器。

要进行实践,请从我们的 Docker 初学者教程 开始,然后阅读我们的 Dockerfile 最佳实践 。

库伯内特斯是做什么的

一台服务器上的 Docker 运行良好,直到该服务器发生故障、流量超出其容量或者您有数十个服务需要协调。 Kubernetes 负责这些操作工作:

  • 调度:将容器放置在有足够可用容量的机器上。
  • 自我修复:替换故障容器并将工作从故障节点移开。
  • 扩展:手动或基于指标添加或删除副本。
  • 服务发现:为一组不断变化的容器提供一个稳定的名称。
  • 滚动更新:逐步发布新版本,并进行简单的回滚。
  • 配置:与图像分开管理设置和机密。

核心思想是期望状态。您声明应该存在三个副本,控制者会不断将其与现实进行比较并纠正任何差异。我们的 Kubernetes 初学者教程 在本地集群上演练了这一过程。

Docker 和 Kubernetes 如何协同工作

从开发人员的笔记本电脑到生产环境的典型路径如下所示:

  1. 开发人员编写 Dockerfile 并在本地测试容器。
  2. CI/CD 管道 构建映像并运行测试。
  3. 管道将版本化映像推送到注册表。
  4. Kubernetes 清单已更新以使用该映像版本。
  5. Kubernetes 提取镜像并将其部署到集群中。

所以Docker的工作在Kubernetes启动之前就基本完成了。该图像是它们之间的交接点。

一个应用程序,两种方式

这是一个小型网络服务。无论哪个工具运行该映像,其构建方式都相同:

# Dockerfile
FROM python:3.13-slim
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
CMD ["python", "app.py"]

使用 Docker 运行它

docker build -t shop-api:1.0 .
docker run -d --name shop -p 8080:8000 --restart unless-stopped shop-api:1.0

两个命令,它正在运行。这很简单,适合许多小型项目。但一台机器上只有一份副本,如果机器死机,服务也会随之消失。

使用 Kubernetes 运行它

# shop.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: shop
spec:
  replicas: 3
  selector:
    matchLabels:
      app: shop
  template:
    metadata:
      labels:
        app: shop
    spec:
      containers:
        - name: api
          image: registry.example.com/shop-api:1.0
          ports:
            - containerPort: 8000
---
apiVersion: v1
kind: Service
metadata:
  name: shop
spec:
  selector:
    app: shop
  ports:
    - port: 80
      targetPort: 8000
kubectl apply -f shop.yaml
kubectl get pods -l app=shop

还有很多东西要写,并且您需要一个集群来运行它。作为回报,您将获得三份副本、稳定的内部地址和自动替换。这种权衡是整个决策的缩影:更多的复杂性换取更多的弹性。

当容器发生故障时会发生什么?

活动 一台主机上的 Docker 库伯内斯
应用程序崩溃 重新启动(如果设置了重新启动策略) 自动重启
应用程序挂起但仍保持运行 除非您为其添加处理,否则保持挂起状态 活性探针可以重新启动它
整个服务器死掉 服务会一直中断,直到有人采取行动为止 Pod 在健康节点上重新创建
流量增加三倍 您可以在一台主机上手动扩展 自动缩放器可以添加副本
糟糕的发布 您手动重新部署旧映像 kubectl 部署撤消

dockershim 的混乱

您可能已经读过“Kubernetes 抛弃了 Docker”。这在狭义上是正确的,并且不必要地吓坏了很多人。 Kubernetes 通过称为容器运行时接口的标准来运行容器。 Docker Engine 没有直接实现它,因此 Kubernetes 包含了一个名为 dockershim 的适配器。该适配器在 1.24 版本中被删除。

集群现在通常使用 containerd 或 CRI-O 等运行时。 使用 Docker 构建的映像仍然有效,因为它们遵循开放容器计划 (OCI) 映像标准。因此,您可以继续使用 Docker 进行构建,并且您的集群会使用不同的运行时来运行结果。

Docker Compose、Swarm 和 Kubernetes

更有意义的比较是协调容器的工具之间的比较:

工具 适用范围 设置工作量 适合
Docker 组合 一台主机 很低 本地开发、小型应用程序
码头工人群 小簇 低 简单的多服务器设置
库伯内斯 大集群 高 复杂的大型系统

Docker Compose 从一个文件启动多个相关容器,它非常适合 Web 应用程序和笔记本电脑上的数据库。 Swarm 内置于 Docker 中,比 Kubernetes 更容易学习,但它的生态系统要小得多。 Kubernetes 拥有最大的社区和工具,这也是它成为大型部署默认设置的重要原因。

提示:比较实际成本。除了学习之外,Kubernetes 还意味着持续升级、安全工作和监控。 Amazon EKS、Google GKE 或 Azure AKS 等托管服务可以减少这项工作,但不会消除它。

你需要哪一个?

在以下情况下,单独使用 Docker 通常就足够了:

  • 您正在本地开发或在一台服务器上运行小型应用程序。
  • 您的团队很小,没有专门的运营人员。
  • 偶尔短暂的停机是可以接受的。

当满足以下条件时,Kubernetes 就开始有意义:

  • 您运行不同团队自行部署的许多服务。
  • 您需要跨多个计算机或区域的高可用性。
  • 流量变化很大,自动扩展可以节省真正的资金。
  • 您拥有操作它的技能或预算。

还有一个中间立场。托管容器平台(例如 AWS Fargate、Google Cloud Run 或 PaaS)可以运行 Docker 映像,无需维护集群。对于许多成长型公司来说,这是正确的下一步,而不是直接跳到 Kubernetes。

如果您出于职业原因想学习两者,那么顺序很明确:首先是 Docker,然后是 Kubernetes。如果不先了解镜像、端口和容器日志,就无法轻松调试 Pod。

常见错误

  • 过早采用 Kubernetes。 复制大公司的架构可能会让小团队埋头于运营工作。
  • 在生产中使用latest标签。您无法可靠地判断什么正在运行或回滚。使用特定版本标签。
  • 在容器内存储数据。 容器是一次性的,因此请使用卷或托管数据库。
  • 跳过运行状况检查。 如果没有就绪性和活跃性探测,Kubernetes 就无法对您的应用程序做出正确的决策。
  • 忘记资源限制。 一个贪婪的容器可能会使节点上的其他所有容器都挨饿。

最后的话

Docker 打包您的软件,然后 Kubernetes 大规模运行它。与其问哪个更好,不如问你今天遇到了什么问题。如果是“我的应用程序很难安装”,请使用 Docker。如果是“我的 40 个服务需要在服务器故障中幸存下来”,请看看 Kubernetes。从解决实际问题的最简单的工具开始,当您看到需要时再升级。

常见问题

Kubernetes 能取代 Docker 吗?

不完全是,因为他们从事不同的工作。 Kubernetes 不构建镜像,因此团队仍然使用 Docker 或类似的工具,然后 Kubernetes 运行结果。

我可以在没有 Docker 的情况下使用 Kubernetes 吗?

是的。集群通常使用 containerd 或 CRI-O 来运行容器。使用 Docker 构建的镜像仍然有效,因为它们遵循 OCI 标准。

我应该先学习 Docker 还是 Kubernetes?

首先学习 Docker。 Kubernetes 假设您已经了解图像、容器、端口和日志,因此这些基础知识将使学习变得更加容易。

Docker Swarm 死了吗?

不,它仍然可用并且适合简单的集群。然而,它的生态系统和采用率比 Kubernetes 小得多,因此请检查它是否满足您的长期需求。

小公司需要 Kubernetes 吗?

通常一开始不会。 Docker Compose 或托管容器平台通常可以很好地为他们服务,直到规模或团队结构使 Kubernetes 物有所值。

继续学习

与Stack Quora合作

需要测试、WordPress 或 SEO 方面的帮助?

我们帮助团队交付更好的软件并发展他们的网站。告诉我们您正在做什么,我们将建议明确的下一步。

继续阅读

更多指南 测试、人工智能和现代开发

喜欢这篇文章吗?选择一个主题并直接跳至我们最新的教程。

人工智能

人工智能幻觉解释:语言模型为何会产生幻觉以及如何减少它

人工智能幻觉解释:它们是什么,为什么语言模型产生它们,常见类型,如何通过基础和提示来减少它们,以及我们进行的简单检查。

阅读文章 →
DevOps

环境变量解释:.env 文件、秘密和配置正确完成

使用我们运行的 Python 示例解释环境变量:读取和设置它们、为什么每个值都是字符串、.env 文件、进程继承、秘密和验证。

阅读文章 →
软件开发

API 速率限制解释:算法、标头和处理 429 错误

API 速率限制通过我们运行的模拟进行了解释:令牌桶、固定窗口、滑动窗口、429 响应、速率限制标头、带回退的重试和测试限制。

阅读文章 →
测试自动化

Python 中的模拟:unittest.mock、补丁以及导致测试谎言的错误

使用unittest.mock 在Python 中进行模拟,经过测试:模拟和return_value、side_effect、修补使用名称的位置、spec 和autospec、模拟日期以及常见错误。

阅读文章 →
软件测试

代码覆盖率解释:行覆盖率与分支覆盖率以及 100% 的真正含义

用真实的coverage.py运行来解释代码覆盖率:行、分支和条件覆盖率,阅读报告,为什么100%覆盖率仍然会错过错误,以及合理的目标。

阅读文章 →
数据库与 SQL

SQL 中的 DELETE、TRUNCATE 和 DROP:差异、回滚以及何时使用它们

DELETE、TRUNCATE 和 DROP 通过经过测试的 SQL 进行了解释:各自删除什么、回滚、触发器、身份重置、速度,以及 PostgreSQL、MySQL、SQL Server 和 SQLite 有何不同。

阅读文章 →
数据库与 SQL

SQL 视图解释:创建、使用和避免陷阱(附示例)

SQL 视图通过我们运行的查询进行解释:创建视图、实时结果、隐藏列、性能、可更新和物化视图、破坏的依赖关系和最佳实践。

阅读文章 →
软件开发

TypeScript 接口与类型:真正的差异,使用编译器进行测试

TypeScript 接口与类型,使用真实编译器进行检查:两者都可以做什么,只有一个可以做什么,声明合并,扩展与交集以及要遵循的简单规则。

阅读文章 →
软件开发

Python *args 和 **kwargs 解释:灵活的函数和清晰的示例

Python *args 和 **kwargs 用我们运行的代码进行了解释:打包和解包、参数顺序、仅关键字和仅位置参数、装饰器和常见错误。

阅读文章 →
软件开发

Python Lambda 函数:语法、实际用途以及何时不使用它们

Python lambda 函数用我们运行的代码进行了解释:语法、使用键排序、映射和过滤器、闭包、后期绑定陷阱,以及何时普通 def 是更好的选择。

阅读文章 →
人工智能

什么是人工智能代理?它们是如何工作的,只需运行一个简单的代理循环

什么是人工智能代理?关于代理循环、工具、内存和护栏的简单指南,以及我们运行的一个小型 Python 循环、真正的风险以及何时简单的聊天机器人是更好的选择。

阅读文章 →
DevOps

监控与可观察性:真正的区别,包括日志、指标和跟踪

监控与可观察性解释:已知和未知的故障、日志、指标和跟踪、检查事件演练、黄金信号、OpenTelemetry 和有用的警报。

阅读文章 →
DevOps

Docker Volumes 与 Bind Mounts:以正确的方式保留容器数据

Docker 卷与绑定挂载解释:为什么容器数据消失、命名卷、绑定挂载、tmpfs、Compose 示例、备份、权限以及何时使用它们。

阅读文章 →
测试自动化

TDD 与 BDD:主要区别、以两种方式构建的一个功能以及何时使用每种方式

TDD 与 BDD 的解释是通过一种双向构建的折扣功能:使用我们运行的代码进行红绿重构、Given-When-Then 场景、工具、权衡以及何时使用每种方案。

阅读文章 →
软件测试

用户验收测试 (UAT):流程、清单和真实示例

用户验收测试解释:谁运行它、它与 QA 有何不同、七步流程、UAT 测试用例模板、清单、签核标准和常见错误。

阅读文章 →
数据库与 SQL

SQL NULL 值解释:IS NULL、COALESCE、NULLIF 和要避免的陷阱

通过我们运行的查询解释了 SQL NULL 值:三值逻辑、IS NULL、COALESCE、NULLIF,聚合、连接和排序如何处理 NULL,以及它悄悄引起的错误。

阅读文章 →
数据库与 SQL

SQL CASE WHEN 语句:语法、实例和常见错误

SQL CASE WHEN 解释了我们运行的查询:简单和搜索表单、条件顺序、SUM 透视、COUNT 技巧、自定义排序、更新和要避免的 NULL 陷阱。

阅读文章 →
软件开发

什么是智威汤逊?通过工作示例解释 JSON Web 令牌

什么是智威汤逊? JSON Web Tokens 解释:这三个部分,在我们运行的代码中构建和篡改的令牌,JWT 与会话,存储,刷新令牌和安全错误。

阅读文章 →
软件开发

JavaScript 事件循环解释:调用堆栈、微任务和计时器以及示例

JavaScript 事件循环用我们运行的代码进行了解释:调用堆栈、任务和微任务队列、为什么 setTimeout 0 不是立即执行、阻塞、饥饿和面试测验。

阅读文章 →
软件开发

Python 生成器和 Yield 解释:通过真实示例节省内存

Python 生成器和yield 用我们运行的代码进行了解释:它们如何暂停和恢复、测量内存节省、管道、无限序列、yield from、发送和常见陷阱。

阅读文章 →
人工智能

什么是嵌入?向量和余弦相似度简单解释

什么是嵌入?关于向量、余弦相似度和语义搜索的简单语言指南,其中包含我们运行的一个小示例、常见用途、选择模型和已知限制。

阅读文章 →
DevOps

蓝绿部署与金丝雀部署:差异、权衡以及如何选择

蓝绿部署与金丝雀部署解释:每种部署的工作原理、成本、风险和回滚、我们测试的稳定用户分桶、数据库迁移、滚动更新以及如何选择。

阅读文章 →
测试自动化

不稳定的测试:造成这些问题的原因以及如何彻底解决它们

我们运行的演示解释了不稳定的测试:主要原因、如何确认和诊断、正确的时间修复、共享状态和日期以及隔离过程。

阅读文章 →
软件测试

负载测试与压力测试:差异、指标和 k6 示例

负载测试与压力测试的解释:各自证明什么、峰值和浸泡测试、重要的指标、为什么平均值会误导、k6 个示例以及如何计划测试。

阅读文章 →
软件测试

测试用例与测试场景:主要区别、示例以及何时使用它们

测试用例与测试场景的解释:清晰的定义、并排的表格、从场景到案例的密码重置功能、模板以及何时使用每个功能。

阅读文章 →
数据库与 SQL

SQL 查询优化:读取执行计划并修复慢速查询(带计时)

对一百万行进行 SQL 查询优化测试:读取执行计划、添加正确的索引、修复不可控制的过滤器、使用复合索引和键集分页。

阅读文章 →
数据库与 SQL

SQL UNION 与 UNION ALL:差异、示例和性能测试

SQL UNION 与 UNION ALL 通过我们运行的查询进行了解释:重复、都遵循的规则、真实的数据错误、测量的性能、INTERSECT 和 EXCEPT 以及何时使用它们。

阅读文章 →
软件开发

JavaScript Fetch API 教程:GET、POST、错误处理和超时

针对本地服务器测试的 JavaScript Fetch API 教程:GET 和 POST、为什么不抛出 404、可重用的帮助程序、查询字符串、超时、CORS 和常见错误。

阅读文章 →
软件开发

Python 文件处理:读取、写入、CSV、JSON 和 pathlib 以及示例

使用我们运行的代码解释了 Python 文件处理:打开模式、使用、读取大文件、CSV、JSON、pathlib、二进制文件、安全写入、错误处理和常见错误。

阅读文章 →
软件开发

Python 类和对象:带有实际示例的 OOP 教程

用我们运行的代码解释 Python 类和对象:__init__、方法、类与实例属性、继承、属性、dunder 方法、数据类和常见错误。

阅读文章 →
人工智能

什么是大语言模型?法学硕士如何运作,在没有炒作的情况下进行解释

什么是大语言模型?法学硕士用简单的语言解释:标记、嵌入、注意力、训练、温度和上下文窗口、一个微小的下一个单词演示和真正的限制。

阅读文章 →
DevOps

适合初学者的 Linux 命令:带有示例的基本终端指南

适合初学者的 Linux 命令,按任务分组:导航、文件、查看日志、grep、管道、权限、进程和档案,并附有实用的日志分析示例。

阅读文章 →
测试自动化

Selenium 与 Playwright:主要区别、代码比较以及选择

Selenium 与 Playwright 比较:架构、等待、浏览器和语言支持、调试、两种工具中的相同测试、迁移建议以及如何选择。

阅读文章 →
软件测试

等价划分:通过实例解释测试设计技术

等效分区解释:如何找到有效和无效分区,年龄、密码和优惠券的工作示例,我们运行的测试,以及为什么将其与边界配对。

阅读文章 →
软件测试

软件测试中的严重性与优先级:差异、矩阵和实例

软件测试中的严重性与优先级解释:清晰的定义、带有示例的四向矩阵、级别尺度、谁设置每个级别以及如何运行错误分类。

阅读文章 →
数据库与 SQL

SQL 子查询教程:类型、相关子查询和 EXISTS 以及示例

SQL 子查询教程,其中包含我们运行的查询:标量、IN、FROM 和 SELECT 子查询、相关子查询、EXISTS、NOT IN NULL 陷阱以及子查询与 JOIN 与 CTE。

阅读文章 →
数据库与 SQL

SQL 事务和 ACID 解释:COMMIT、ROLLBACK 和隔离级别

SQL 事务和 ACID 通过我们运行的银行转账进行了解释:COMMIT、ROLLBACK、保存点、锁、隔离级别、脏读、死锁和最佳实践。

阅读文章 →
软件开发

Git 命令备忘单:您实际使用的命令,以及示例

Git 命令备忘单按任务分组:设置、暂存、分支、远程、存储、历史记录和撤消错误,以及来自真实演示存储库的输出。

阅读文章 →
软件开发

JavaScript Promise 解释:then、catch、Promise.all 和常见错误

JavaScript 承诺用我们运行的代码进行了解释:状态、then 和 catch 链、错误处理、Promise.all、allSettled、race 和 any、事件循环和常见错误。

阅读文章 →
软件开发

Python 字典教程:方法、示例和常见模式

Python 字典教程,包含我们运行的代码:创建、读取和更新字典、关键方法、合并、理解、计数和分组模式以及常见错误。

阅读文章 →
人工智能

什么是 RAG?通过工作示例解释检索增强生成

什么是RAG?检索增强生成逐步解释:索引、分块、嵌入、检索、一个小型的 Python 工作示例、评估和常见故障。

阅读文章 →
DevOps

Terraform 初学者教程:从第一个文件到模块的基础设施即代码

适合初学者的 Terraform 教程:从没有云帐户开始,学习初始化、计划和应用,然后是变量、输出、状态、模块和安全的团队工作流程。

阅读文章 →
DevOps

Docker 与 Kubernetes:主要区别、它们如何协同工作以及您需要哪些

Docker 与 Kubernetes 的解释:各自的作用、同一个应用程序同时运行、Docker Compose 和 Swarm 的比较、dockershim 的变化以及如何决定您需要什么。

阅读文章 →
测试自动化

Pytest 初学者教程:夹具、参数化和真实示例

面向初学者的 pytest 教程,其中包含我们在 pytest 9.2 上运行的测试:断言、固定装置、参数化、conftest、标记、tmp_path、monkeypatch、有用的标志和 CI。

阅读文章 →
软件测试

软件测试生命周期 (STLC):6 个阶段、进入和退出标准、示例

软件测试生命周期解释:六个 STLC 阶段,包括进入和退出标准、可交付成果、有效的登录功能示例、STLC 与 SDLC 以及敏捷中的 STLC。

阅读文章 →
软件开发

Git merge 与 rebase 的区别:示例及如何选择

用真实的 log 输出、对比表、rebase 黄金法则和安全的团队工作流,讲清 Git merge 与 rebase 的区别。

阅读文章 →
软件开发

Python 列表推导式:语法、示例与何时避免使用

Python 列表推导式详解:语法、过滤、if-else、嵌套循环、实测耗时,以及何时普通 for 循环更合适。

阅读文章 →
数据库与 SQL

SQL JOIN 详解:附示例(INNER、LEFT、RIGHT、FULL)

通过示例表和查询,一步步讲解 SQL JOIN:INNER、LEFT、RIGHT、FULL、CROSS 和 SELF,并介绍常见错误与性能技巧。

阅读文章 →