跳到主要内容
预计阅读 31 分钟

驶向深海:编排集群与生产实践 —— Swarm与Kubernetes初探,以及生产环境中的最佳实践

Docker Compose能指挥一台机器上的容器协奏曲,但当你的业务需要跨越多台服务器时,就需要更强大的指挥系统了。这一章,我们驶向容器技术的深海。

📋 开篇自测:你已经知道多少?

  1. Docker Compose和Docker Swarm的区别是什么?
  2. 你听说过Kubernetes吗?它和Docker是什么关系?
  3. 容器在生产环境中运行,你觉得需要关注哪些方面?

一、单机编排的天花板

前面几章我们一直在单台机器上玩Docker。Docker Compose帮我们管理一台机器上的多个容器,跑个开发环境、搭个小型应用绰绰有余。

但是,当你的应用面临以下场景时,单机就不够用了:

高可用:如果唯一的服务器挂了,所有服务全部宕机。你的用户会看到一片空白,你的老板会看到你的辞职信。

弹性伸缩:电商大促期间流量暴增十倍,一台服务器扛不住。你需要快速扩展到多台机器来分担压力。

滚动更新:更新应用时不能停服务。你需要在多台机器上分批替换旧版本,确保始终有实例在处理请求。

资源调度:你有十台服务器、三十个服务。哪个服务跑在哪台机器上?怎么充分利用资源?手动规划太累了。

这些问题,都需要容器编排(Container Orchestration) 来解决。容器编排工具的核心职责就是:在一个由多台机器组成的集群中,自动化地管理容器的部署、扩展、网络、存储和故障恢复。

打个比方:Docker Compose是一家小餐厅的经理,管理着厨房里的几个厨师。容器编排工具是一个连锁餐饮集团的总部,管理着全国几百家分店的运营调度。


二、Docker Swarm:Docker的亲生编排方案

Docker Swarm是Docker官方内置的集群管理和编排工具。它的最大优势是简单——如果你已经会用Docker和Docker Compose,学Swarm几乎没有额外的学习成本。

核心概念

节点(Node):集群中的每一台机器。分为两种角色:

  • Manager节点:负责集群管理和任务调度,相当于公司的管理层
  • Worker节点:负责实际运行容器,相当于一线员工

服务(Service):Swarm中的核心调度单元。你不再直接创建容器,而是声明一个服务及其期望状态(比如”我需要3个Nginx实例”),Swarm会自动在集群中创建和管理容器。

任务(Task):Service的具体执行单元,每个Task对应一个容器。

栈(Stack):一组相关服务的集合,用docker-compose.yml文件定义。可以理解为”分布式版的Docker Compose”。

快速搭建一个Swarm集群

# 在第一台机器上初始化Swarm(这台机器成为Manager)
docker swarm init --advertise-addr 192.168.1.100

# 初始化成功后会输出一条加入命令,复制它
# 在其他机器上执行这条命令加入集群
docker swarm join --token SWMTKN-1-xxxxx 192.168.1.100:2377

# 在Manager上查看集群节点
docker node ls

就这么简单——几条命令就组建了一个容器集群。

部署服务

# 创建一个Nginx服务,运行3个副本
docker service create \
  --name web \
  --replicas 3 \
  --publish 80:80 \
  nginx:1.28

# 查看服务状态
docker service ls

# 查看服务的各个副本分布在哪些节点上
docker service ps web

# 扩展副本数
docker service scale web=5

# 更新服务(滚动更新)
docker service update --image nginx:1.29 web

# 删除服务
docker service rm web

当你执行 docker service create --replicas 3 时,Swarm会在集群的不同节点上分配3个容器。如果某个节点宕机了,Swarm会自动在其他节点上重新创建容器,确保始终有3个实例在运行。这就是自愈能力。

使用Stack部署

你可以用类似docker-compose.yml的文件来定义Swarm Stack:

# docker-stack.yml
services:
  web:
    image: nginx:1.28-alpine
    ports:
      - "80:80"
    deploy:
      replicas: 3
      update_config:
        parallelism: 1          # 每次更新1个容器
        delay: 10s              # 每个容器更新间隔10秒
        failure_action: rollback # 更新失败自动回滚
      restart_policy:
        condition: on-failure
        max_attempts: 3
    networks:
      - app-net

  api:
    image: myapp/backend:v1.0
    deploy:
      replicas: 2
      resources:
        limits:
          cpus: "0.5"
          memory: 256M
    environment:
      - DB_HOST=postgres
    networks:
      - app-net

  postgres:
    image: postgres:16-alpine
    deploy:
      placement:
        constraints:
          - node.role == manager  # 只在Manager节点上运行
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      - POSTGRES_PASSWORD_FILE=/run/secrets/db_password
    secrets:
      - db_password
    networks:
      - app-net

networks:
  app-net:
    driver: overlay  # Swarm使用overlay网络实现跨节点通信

volumes:
  pgdata:

secrets:
  db_password:
    external: true
# 部署Stack
docker stack deploy -c docker-stack.yml bookstore

# 查看Stack中的服务
docker stack services bookstore

# 查看Stack中所有任务
docker stack ps bookstore

# 删除Stack
docker stack rm bookstore

Swarm的内置功能

Swarm虽然相对简单,但该有的功能都不缺:

  • 服务发现:同一个overlay网络中的服务可以通过服务名互相访问
  • 负载均衡:内置了Ingress负载均衡,外部请求会自动分配到各副本
  • 滚动更新:支持配置更新策略(并行度、间隔、失败回滚)
  • 健康检查:不健康的容器自动重启
  • 密钥管理(Secrets):安全地管理密码、证书等敏感数据
  • 配置管理(Configs):分发配置文件到指定服务

📌 关于 Swarm 的生态现状 Swarm 的最大优势是简单易用,但需要坦诚地说:截至目前,Swarm 已长期未有重大功能更新,社区活跃度显著下降,云厂商的支持也非常有限。Mirantis(Docker Enterprise 的接手方)承诺支持到 2030 年,但新功能的迭代基本停滞。如果你是为生产环境做技术选型,建议优先考虑 Kubernetes(尤其是云厂商的托管服务);如果你的场景是小团队、少量节点、追求快速搭建,Swarm 仍然是一个务实的选择——只是要清楚它的生态已趋于稳定而非活跃发展。

🤔 想一想 Swarm这么简单好用,为什么在大型企业中使用率不如Kubernetes?简单就一定不好吗?


三、Kubernetes:容器编排的航空母舰

如果说Docker Swarm是一艘巡洋舰——功能齐全、操作简便、适合中小规模舰队,那Kubernetes(常简称K8s)就是航空母舰——功能强大到令人眼花缭乱,但也需要一整个团队来驾驭。

K8s简史

Kubernetes诞生于Google内部。Google从2003年开始用一个叫Borg的系统管理其全球数据中心中的容器(每周要处理数十亿个容器的启停)。2014年,Google把Borg的核心理念开源,这就是Kubernetes。

2017年,Docker官方宣布在Docker Enterprise中支持Kubernetes,标志着K8s成为容器编排领域的事实标准。如今,几乎所有的云服务商(AWS、Azure、GCP、阿里云、腾讯云)都提供了托管的Kubernetes服务。

核心概念(只讲理解,不求精通)

K8s的概念体系非常庞大,这里我们只介绍最核心的几个:

Pod:K8s中最小的调度单元。一个Pod可以包含一个或多个紧密协作的容器。你可以把Pod理解为”一间办公室”,里面的容器是”同一个工位上的同事”,它们共享网络和存储。

Deployment:管理Pod的”上级”。你告诉Deployment:“我需要3个Pod来跑我的Web服务”,它会确保始终有3个Pod在运行,挂了自动补上。

Service:为一组Pod提供稳定的网络入口。Pod可能会被创建和销毁,IP会变,但Service提供了一个固定的地址,就像公司的总机号码不会因为员工离职而改变。

Namespace:逻辑隔离空间。就像同一栋大楼的不同楼层,开发环境和生产环境可以在同一个集群中共存但互不干扰。

ConfigMap / Secret:管理配置信息和敏感数据。

Ingress:管理外部流量的入口规则,通常是HTTP/HTTPS的路由和负载均衡。

一个简单的K8s部署示例

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: bookstore-api
  labels:
    app: bookstore-api
spec:
  replicas: 3
  selector:
    matchLabels:
      app: bookstore-api
  template:
    metadata:
      labels:
        app: bookstore-api
    spec:
      containers:
        - name: api
          image: myregistry/bookstore-api:v1.0.0
          ports:
            - containerPort: 4000
          env:
            - name: DB_HOST
              value: postgres-service
            - name: DB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: db-credentials
                  key: password
          resources:
            requests:
              memory: "128Mi"
              cpu: "250m"
            limits:
              memory: "256Mi"
              cpu: "500m"
          readinessProbe:
            httpGet:
              path: /health
              port: 4000
            initialDelaySeconds: 5
            periodSeconds: 10
          livenessProbe:
            httpGet:
              path: /health
              port: 4000
            initialDelaySeconds: 15
            periodSeconds: 20

---
apiVersion: v1
kind: Service
metadata:
  name: bookstore-api-service
spec:
  selector:
    app: bookstore-api
  ports:
    - port: 80
      targetPort: 4000
  type: ClusterIP
# 应用配置
kubectl apply -f deployment.yaml

# 查看Pod状态
kubectl get pods

# 查看服务
kubectl get services

# 查看某个Pod的日志
kubectl logs bookstore-api-xxx-yyy

# 进入Pod内的容器
kubectl exec -it bookstore-api-xxx-yyy -- bash

# 扩缩容
kubectl scale deployment bookstore-api --replicas=5

Swarm vs Kubernetes

维度Docker SwarmKubernetes
学习曲线平缓陡峭
安装复杂度Docker自带需要专门安装配置
适用规模中小规模任意规模
生态丰富度一般极其丰富
社区活跃度一般极高
云厂商支持有限全面
功能完整度满足基本需求功能极其强大
运维负担高(但托管服务降低了这个门槛)

选择建议

  • 团队人数少于10人、节点数少于20个 → Swarm够用了
  • 需要与云平台深度集成、或者未来有大规模扩展的计划 → Kubernetes
  • 预算有限、不想维护集群 → 云厂商的托管K8s服务(EKS、AKS、GKE等)

⚠️ 常见误区

  • 误区一:“用K8s就必须自己搭建集群”。不是。云厂商的托管K8s服务帮你管理了控制平面,你只需要关注自己的应用。
  • 误区二:“所有项目都应该用K8s”。杀鸡焉用牛刀。如果你的应用只有三五个容器、跑在两三台服务器上,Docker Compose甚至Swarm就足够了。
  • 误区三:“Docker和Kubernetes是竞争关系”。K8s是容器的管理者,Docker(或其他容器运行时)是容器的创建者和运行者。它们是不同层次的工具。

📌 阶段小结:到这里,你已经了解了容器编排的两大方案——Swarm适合中小规模、追求简单易用的团队,Kubernetes适合需要大规模部署和丰富生态的场景。接下来我们进入生产环境最佳实践,这些知识无论你选择哪种编排方案都用得上。


四、生产环境最佳实践

不管你用Swarm还是K8s,或者只是在单台服务器上跑Docker,以下这些实践在生产环境中都很重要。

安全加固

1. 不用root运行容器

# 在Dockerfile中创建非root用户
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser

默认情况下容器内的进程以root身份运行。如果容器被攻破,攻击者就获得了root权限。使用非root用户能大大降低这个风险。

2. 使用只读文件系统

docker run --read-only --tmpfs /tmp my-app

让容器的文件系统只读,只有 /tmp 等必要目录可写。这样即使容器被入侵,攻击者也无法修改系统文件或植入后门。

3. 限制系统能力

docker run --cap-drop ALL --cap-add NET_BIND_SERVICE my-app

Docker容器默认拥有很多Linux capabilities(能力)。--cap-drop ALL 先禁用所有能力,再用 --cap-add 只添加需要的。最小权限原则。

4. 镜像安全扫描

定期扫描镜像中的安全漏洞:

# 使用Trivy扫描
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock aquasec/trivy image myapp:v1.0

5. 不要在镜像中存储机密信息

密码、API密钥等敏感数据应该通过环境变量、Docker Secrets或外部密钥管理系统(HashiCorp Vault等)注入,绝不应该打包在镜像中。

日志管理

容器的标准输出(stdout/stderr)会被Docker捕获为容器日志。但在生产环境中,你需要一个集中式的日志收集方案:

# docker-compose.yml中配置日志驱动
services:
  app:
    image: myapp
    logging:
      driver: json-file
      options:
        max-size: "10m"    # 单个日志文件最大10MB
        max-file: "3"      # 最多保留3个文件

更专业的做法是使用ELK Stack(Elasticsearch + Logstash + Kibana)或Loki + Grafana来收集和分析日志。

监控与告警

你需要知道容器运行的状态:CPU使用率、内存占用、网络流量、健康检查状态等。

Prometheus + Grafana 是容器监控的标配组合:

  • Prometheus负责收集和存储指标数据
  • Grafana负责可视化展示
  • cAdvisor或Docker的内置指标接口负责暴露容器级别的数据
# 一个简单的监控Stack
services:
  prometheus:
    image: prom/prometheus
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
    ports:
      - "9090:9090"

  grafana:
    image: grafana/grafana
    ports:
      - "3000:3000"
    volumes:
      - grafana-data:/var/lib/grafana

  cadvisor:
    image: ghcr.io/google/cadvisor:0.56.2
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:ro
      - /sys:/sys:ro
      - /var/lib/docker/:/var/lib/docker:ro
    ports:
      - "8080:8080"

💡 提示:cAdvisor 的官方镜像从 v0.54.0 起已完全迁移到 ghcr.io/google/cadvisor(v0.53.0 是最后一个同时发布到旧地址的版本),旧的 gcr.io/cadvisor/cadvisor 地址已停止更新。注意从 v0.54.0 起镜像标签不再使用 v 前缀(如 0.56.2 而非 v0.56.2)。

资源管理

给容器设置资源限制,防止”一颗老鼠屎坏了一锅粥”:

docker run -d \
  --memory="512m" \
  --memory-swap="1g" \
  --cpus="0.5" \
  --pids-limit=100 \
  myapp
  • --memory:内存上限
  • --memory-swap:内存+交换空间上限
  • --cpus:CPU份额限制
  • --pids-limit:进程数上限(防止fork炸弹)

备份与灾难恢复

  1. 定期备份Volume数据:数据库等有状态服务的Volume必须有备份策略
  2. 镜像仓库的高可用:镜像仓库挂了,新容器就创建不了
  3. 基础设施即代码:所有的docker-compose.yml、Dockerfile、CI/CD配置都应该在版本控制中
  4. 定期演练恢复流程:备份不验证等于没备份

🤔 想一想 你们公司的生产环境中,如果需要把所有Docker容器迁移到另一套服务器上,你需要迁移哪些东西?(提示:镜像、Volume数据、配置文件、网络设置、密钥…)

📌 阶段小结:生产环境最佳实践涵盖了安全加固(非root用户、只读文件系统、最小权限、镜像扫描、密钥管理)、日志管理、监控告警、资源限制和备份恢复五大方面。这些实践是保障容器化应用稳定运行的基石。


五、Docker生态全景图

最后,让我们站在高处,俯瞰整个Docker和容器化技术的生态全景:

┌────────────────────────────────────────────────────────┐
│                   应用层                                │
│  微服务  │  Serverless  │  边缘计算  │  AI/ML Pipeline  │
├────────────────────────────────────────────────────────┤
│                   编排层                                │
│  Kubernetes  │  Docker Swarm  │  Nomad  │  ECS         │
├────────────────────────────────────────────────────────┤
│                   工具层                                │
│  Docker Compose │ Helm │ Terraform │ Ansible           │
├────────────────────────────────────────────────────────┤
│                   镜像层                                │
│  Docker Hub │ Harbor │ ECR │ GCR │ ACR                 │
├────────────────────────────────────────────────────────┤
│                   运行时层                              │
│  Docker Engine │ containerd │ CRI-O │ Podman           │
├────────────────────────────────────────────────────────┤
│                   操作系统层                             │
│  Linux Kernel (Namespaces + cgroups)                   │
└────────────────────────────────────────────────────────┘

Docker是这个生态的起点和基石。即使你未来转向Kubernetes,Docker中学到的核心概念(镜像、容器、Dockerfile、网络、存储)全都用得上。


六、学完这门课,你的下一步

恭喜你走到了最后一章!让我帮你梳理一下从这里出发可以去往哪些方向:

如果你想深入容器编排 → 学习Kubernetes。推荐从minikube(本地K8s环境)开始,逐步理解Pod、Deployment、Service、Ingress等概念。

如果你想提升DevOps能力 → 学习Terraform(基础设施即代码)、Ansible(自动化配置管理),以及完善CI/CD流水线。

如果你想做微服务架构 → 研究服务网格(Istio、Linkerd)、API网关、分布式追踪(Jaeger)、熔断限流等话题。

如果你想保持Docker技能的锋利 → 找一个自己的项目,完整地走一遍”编写Dockerfile → Docker Compose编排 → CI/CD流水线 → 部署上线”的全流程。实践是最好的老师。


📝 掌握度自测

  1. Docker Compose适合管理单机上的多容器应用。当你需要跨越多台机器部署时,应该使用什么工具?简述Swarm和K8s的各自定位。

  2. 在Kubernetes中,Pod、Deployment、Service分别扮演什么角色?用一个生活中的比喻来解释它们的关系。

  3. 列举三项容器在生产环境中的安全最佳实践,并说明每一项解决什么问题。

  4. 为什么要给容器设置资源限制(CPU和内存)?不设置会有什么风险?

  5. 你要为一个日活10万用户的Web应用选择容器编排方案,你会选Swarm还是K8s?请说明你的理由。

💡 自我评估

  • 全部答对:你已经建立了从Docker单机到集群编排的完整知识体系。接下来就是在实际项目中不断实践和深化了。
  • 答对3-4题:对生产环境的容器化实践有了很好的理解。建议选一个编排工具(Swarm或K8s)深入学习。
  • 答对1-2题:这一章涵盖的内容比较广,一次消化不完是正常的。建议先吃透前9章的内容,然后再回来研读这一章。

写在最后

十章的旅程到此结束。从”在我电脑上能跑”的痛点出发,我们一起走过了安装Docker、理解镜像和容器、编写Dockerfile、配置网络和存储、使用Compose编排、搭建开发环境、打通CI/CD流水线,直到今天站在集群编排和生产实践的高度回望来路。

Docker不是银弹,它不能解决所有问题。但它确确实实改变了软件的构建、交付和运行方式,让”在我电脑上能跑”这句话不再是一个令人沮丧的托词,而是一个可以兑现的承诺。

技术在不断进化,容器生态也在持续演进。但你在这门课程中建立的基础认知——隔离、标准化、声明式配置、不可变基础设施——这些思想会陪伴你走得更远。

祝你在容器化的道路上一帆风顺。

购买课程解锁全部内容

告别「在我电脑上能跑」:Docker 容器化实战

¥29.90