Docker 从 0 到 1 再到 Kubernetes 实战:第18篇 从 Docker Compose 到 Kubernetes 的思考

0 阅读8分钟

IT策士 10余年一线大厂经验,专注 IT 思维、架构、职场进阶。我会在各个平台持续发布最新文章,助你少走弯路。

18 篇文章,从第一行 docker run hello-world,到能够用 Compose 编排 WordPress + MySQL 这样的完整应用栈。你亲手经历了:编写 Dockerfile 把应用打成镜像,用 Volume 实现数据持久化,用自定义网络让容器互访,用 Compose 一键启停多服务,用健康检查和 depends_on 控制启动顺序,用多文件和环境变量实现多环境切换。

现在,我们要迈出整个系列中最重要的一步:从单机编排走向集群编排,从 Docker Compose 走向 Kubernetes。

这也是我们整个大纲的分水岭——前 18 篇是基础,后 32 篇是核心。这篇文章不是教你具体的 K8s 命令,而是帮你建立概念映射。当你理解了 Compose 中的每一个概念在 K8s 中对应什么、为什么这样设计,你后续的学习就不再是“从零开始”,而是“在已有的认知框架上叠加新知识”。

一、从第 1 篇到第 17 篇:我们究竟掌握了什么?

先快速回顾一下我们走过的完整技术演进路线,这能帮你锚定当前所处的位置。

阶段一:单容器(第 1-6 篇)——让应用跑起来

我们学会了用 Dockerfile 构建镜像,管理容器的生命周期,配置重启策略和健康检查。核心价值是让单机应用具备了可移植性——不再有“我机器上能跑,你机器上不行”的问题。

阶段二:多容器手动编排(第 7-10 篇)——让多个服务协同工作

我们引入了 Volume 做数据持久化(容器删了数据还在),通过自定义网络让容器之间互访,手动创建网络和卷来启动 Flask + Redis 应用。用脚本把多个手动命令串起来,但仍然是“过程式”的——需要告诉机器每一步怎么做。

阶段三:声明式单机编排(第 11-17 篇)——用 YAML 描述期望状态

Compose 的核心突破在于:你不再需要告诉 Docker“怎么做”(先创建网络,再启动 Redis,sleep 3 秒,再启动 Flask),而是用 YAML 描述“我想要什么”(两个服务、一个网络、两个卷、Redis 健康后启动 Flask)。Compose 自己决定执行顺序。环境变量和多文件组合进一步实现了“同一份描述,适配多套环境”。

二、Compose 的能力边界:为什么需要 Kubernetes?

Compose 已经很好用了,但它有一个根本性的局限:Compose 只能管理单台宿主机上的容器。

现实世界中的生产环境可不止一台机器。当你的应用需要跨多台服务器部署、需要在流量突增时自动扩容、需要在某台服务器宕机时自动迁移容器、需要灰度发布(让 10% 的用户先体验新版本)、需要按服务粒度控制网络隔离——这些需求全都指向一个事实:你需要一个跨主机的容器编排平台

以下是 Compose 无法解决的核心生产需求:

三、概念映射:Compose 的每件事,K8s 都是谁在做?

你现在脑海中的 Compose 模型是这样的:docker-compose.yml 里定义了几个 services,每个 service 有一些 environmentvolumesports,通过 networks 互通,通过 depends_on 控制启动顺序。在 K8s 中,这些概念被拆解为更细粒度的“对象”,各司其职。

下面这张对照表是你从 Compose 到 K8s 的“概念翻译词典”:

关键思维转换:在 Compose 中,docker compose up -d 是直接操作容器——创建、启动、连接网络。在 K8s 中,kubectl apply -f 是把 YAML 提交到 API Server,然后控制器(Controller) 在后台持续工作,确保集群的实际状态与你声明的一致。你不再直接对容器下命令,而是告诉 K8s “我要 3 个副本”,控制循环自己会去创建、监控、修复。

四、同一个应用,两种声明方式

拿我们最熟悉的 Flask + Redis 计数器应用来看,Compose 和 K8s 的表达方式有什么异同。

Compose 版本(你已经熟悉的):

services:
  redis:
    image: redis:alpine
    volumes:
      - redis-data:/data
    networks:
      - app-net
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]

  flask-app:
    image: flask-redis-counter:2.0
    ports:
      - "5000:5000"
    environment:
      - REDIS_HOST=redis
    networks:
      - app-net
    depends_on:
      redis:
        condition: service_healthy

volumes:
  redis-data:

networks:
  app-net:

K8s 版本(你现在可以先看懂大意):

# Redis Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
        - name: redis
          image: redis:alpine
          ports:
            - containerPort: 6379
          volumeMounts:
            - name: redis-data
              mountPath: /data
      volumes:
        - name: redis-data
          persistentVolumeClaim:
            claimName: redis-pvc
---
# Flask Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
  name: flask-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: flask-app
  template:
    metadata:
      labels:
        app: flask-app
    spec:
      containers:
        - name: flask-app
          image: flask-redis-counter:2.0
          ports:
            - containerPort: 5000
          env:
            - name: REDIS_HOST
              value: redis-service
---
# Services
apiVersion: v1
kind: Service
metadata:
  name: redis-service
spec:
  selector:
    app: redis
  ports:
    - port: 6379
---
apiVersion: v1
kind: Service
metadata:
  name: flask-service
spec:
  type: NodePort
  selector:
    app: flask-app
  ports:
    - port: 5000
      nodePort: 30080

核心差异一览

K8s 的 YAML 看起来更长,因为它把每个关注点(调度、网络、存储、配置)都拆成了独立的对象。这种拆解初看增加了复杂度,但它带来了更精细的控制能力——你可以独立地更新网络策略而不碰 Deployment,可以单独扩容某个服务而不影响其他配置。这种“关注点分离”是 K8s 应对大规模集群管理的核心设计思想。

五、从“手动管理”到“控制器驱动”:思维方式的根本转变

理解 Compose 和 K8s 的区别,最关键的不是记住对象名称的对应关系,而是理解管理模式的差异

Compose 的思维模型:你发出一条命令(docker compose up -d),Docker 同步执行一系列操作(创建网络、创建卷、启动容器),执行完毕返回结果。这是命令式 + 同步的模式——你告诉 Docker “做这个”,Docker 做完之后告诉你结果。

K8s 的思维模型:你用 kubectl apply -f 提交一份 YAML 到 API Server,K8s 的控制器组件(如 Deployment Controller、ReplicaSet Controller)在后台异步工作,持续监控集群状态,一旦发现“实际运行的 Pod 数量不等于你声明的 replicas”,就自动创建或删除 Pod。这是声明式 + 异步的模式——你告诉 K8s “我想要这样”,K8s 不断地自我调整直到达成目标。

这一转变带来的好处是巨大的:你不再需要写脚本处理“如果容器挂了怎么办”、“如果节点宕机了怎么办”——K8s 的控制循环会自动处理这些故障。你只需要声明期望状态,剩下的交给平台。

六、系列第三部分预告:Kubernetes 核心全景

从第 19 篇开始,我们将正式进入 Kubernetes 核心的系统学习。以下是后续 20 篇的路线图:

第 19-20 篇:入门与实验环境。先整体理解 K8s 架构(控制平面、工作节点、核心组件),然后动手搭建 Minikube 本地集群,安装 kubectl,跑通第一个 Pod。

第 21-27 篇:Pod 与控制器。深入 Pod 的 YAML 结构、生命周期、多容器设计模式(Sidecar),再掌握 Deployment、DaemonSet、Job/CronJob 等控制器的使用。

第 28-31 篇:网络与服务发现。学习 Service(ClusterIP/NodePort/LoadBalancer)、Ingress(域名路由、TLS)、以及 K8s DNS 解析机制。

第 32-33 篇:配置管理。ConfigMap 与 Secret 的创建、挂载、更新策略。

第 34-38 篇:存储、资源与安全。PV/PVC/StorageClass 动态供应,Requests 与 Limits 资源管理,亲和性调度,RBAC 权限控制。

学完这 20 篇,你就能独立把一个应用从 Docker 镜像变成 K8s 集群上可运维的服务。然后再进入第四部分(第 39-50 篇)的生产级生态——Helm、监控、日志、CI/CD、服务网格。

七、本篇总结

这篇文章的核心目的,是在你头脑中建立一张“概念映射表”,让你带着 Compose 的经验进入 K8s 时不会感到陌生。几个关键要点:

  • Compose 管理单机容器,K8s 管理跨主机集群——这是两者最根本的能力差异。

  • Compose 的 service → K8s 的 Deployment + Pod + Service——原本一个 service 承载的所有职责,在 K8s 中被拆解为多个独立对象,各司其职。

  • Compose 的环境变量 → K8s 的 ConfigMap / Secret——配置与镜像解耦的思想一致,但 K8s 提供了更安全的敏感信息管理。

  • Compose 的 volumes → K8s 的 PV/PVC/StorageClass——持久化存储的声明式管理,K8s 实现了真正的“动态供应”。

  • 命令式 vs 声明式:Compose 是“你下命令,Docker 执行”,K8s 是“你声明期望状态,控制器持续调和”——这是思维方式的根本转变。

从下一篇开始,我们将正式学习 Kubernetes 的架构和核心组件,动手搭建实验集群。

想了解更多还可以去各个平台搜索「IT策士」,一起升级 IT 思维 !