Docker学习笔记——DockerSwarm

cuixiaogang

概述

Docker Swarm是Docker引擎内置的容器编排工具,可以将多台Docker主机组成一个集群,统一调度和管理容器服务。

单机跑Docker够用,但到了生产环境——服务要多副本、要高可用、某台机器挂了容器得自动迁移——就需要把多台机器组成集群来调度。Docker Swarm就是Docker原生的集群编排方案,不需要额外装东西,docker swarm init一条命令就能把当前节点变成集群管理节点。

本篇记录Swarm的核心概念、集群搭建、服务管理、网络与负载均衡、stack部署,以及和Kubernetes的对比与K8s核心概念速览。Docker基础和Compose的内容已在《Docker基础篇》《Docker进阶篇》里讲过,这里不重复。

核心概念

节点(Node)

Swarm集群由多个Docker主机组成,每台主机就是一个节点,分两种角色:

  • Manager节点:负责集群管理——接收用户命令、调度任务、维护集群状态(用Raft协议做一致性)。Manager同时也能跑容器任务。
  • Worker节点:纯干活——接收Manager分配的任务,运行容器。

一个集群可以有多个Manager(建议奇数个,如3或5,保证Raft选举正常),其中一个是Leader,其余是备。Worker数量不限。

如下图所示,swarm 集群由管理节点(manager)和工作节点(work node)构成:

image.png
image.png

Leader 与 Raft 选举

多个Manager中只有一个是Leader,负责实际的调度决策和集群状态变更(创建/更新服务等)。其余Manager是Follower,同步Leader的状态,随时准备接替。

Leader选举靠Raft一致性协议,核心机制:

  • 心跳:Leader定期向Follower发心跳,Follower收到就重置计时器。
  • 选举触发:某个Follower超时没收到心跳,就认为Leader挂了,把自己变成Candidate发起投票。
  • 多数派(Quorum):Candidate获得超过半数Manager的投票就成为新Leader。这就是为什么Manager数量必须是奇数——偶数个在网络分区时可能两边票数相等,谁也选不出来。
  • 日志复制:所有状态变更先写入Leader的日志,Leader复制到多数Follower确认后才算提交。

Manager数量与容错:

Manager数 Quorum(多数派) 可容忍故障数
1 1 0(单点,不推荐)
3 2 1
5 3 2
7 4 3

不建议超过7个Manager——Manager越多Raft同步开销越大,写性能下降。大集群里Manager保持3~5个,其余全做Worker。

Leader挂了后选举通常在秒级完成,选举期间集群不能执行新的调度操作(如创建/更新服务),但已经运行的容器不受影响,继续正常服务。

服务(Service)与任务(Task)

这是Swarm里最核心的一对概念:

  • Service:用户定义的”期望状态”——跑什么镜像、几个副本、怎么更新、端口怎么映射。Swarm的调度单位。
  • Task:Service的一个执行实例,对应一个具体的容器。3个副本就是3个Task,分布在不同节点上。

关系:Service → 拆成多个 Task → 每个Task在某个节点上跑一个 Container

栈(Stack)与栈名

Stack是一组相关Service的集合,用一个Compose文件(docker-compose.yml)声明,通过docker stack deploy一次性部署。《Docker进阶篇》里那个下载器服务栈示例,就是典型的stack用法。

栈名docker stack deploy时指定的名字(如docker stack deploy -c xxx.yml my_stack里的my_stack),它的意义:

  • 命名空间隔离:栈内所有资源(服务、网络、卷)都会自动加上栈名_前缀。比如栈名my_stack里的web服务实际名称是my_stack_web,网络是my_stack_default。这样同一集群里可以部署多个栈,资源名不会冲突。
  • 批量管理docker stack services my_stackdocker stack rm my_stack都是按栈名整体操作,不用逐个服务处理。
  • 多环境部署:同一份Compose文件可以用不同栈名部署多套(如devstagingprod),互不干扰。

部署模式

模式 说明 适用场景
replicated(默认) 指定副本数,Swarm自动分配到各节点 大多数无状态服务
global 每个节点跑且仅跑一个实例 监控Agent、日志收集器等需要每台机器都跑的
replicated-job 指定总任务数和并发数,跑完即退出 批处理、数据迁移等一次性任务(Docker 20.10+)
global-job 每个节点跑一次,跑完即退出 全集群一次性操作(如清理脚本)

replicatedglobal是常驻服务,容器退出会被重新拉起;*-job是一次性任务,跑完就算结束、不重启。

下面是一个 global 模式的真实示例(android-safe 安全检测服务):

1
2
3
4
5
6
7
8
9
10
11
version: '3.7'

services:
android-safe:
image: "harbor.qihoo.net/ybjcjdz-android-platform/android-safe:20260527190135"
ports:
- 8361:8361
volumes:
- "/home/search/logs/android.safe.360.net/:/service/logs"
deploy:
mode: global

这个服务用 deploy.mode: global,集群里每个节点都会跑且仅跑一个 android-safe 实例——新增节点时自动补一个,不用手动扩容。它还做了两件 global 服务常见的事:

  • ports: 8361:8361 把端口发布出去,配合 Routing Mesh,从任意节点的 8361 都能访问到本机实例;
  • volumes 把宿主机的日志目录挂进容器,每个节点的日志各自落在本机磁盘上。

android-safe服务的部署情况
android-safe服务的部署情况

这正是「监控 Agent、日志收集器等需要每台机器都跑」的典型用法——每个节点一个实例、就近处理本机数据。

集群搭建与运维

初始化集群

在第一台机器上执行:

1
docker swarm init --advertise-addr 192.168.1.10

--advertise-addr指定本节点的通信IP(多网卡时必须指定)。执行后当前节点成为Manager(同时也是Leader),命令输出会给出一条docker swarm join命令,里面带着加入集群用的token。

加入节点

在其他机器上执行上一步输出的join命令:

1
2
3
4
5
6
# 加入为 Worker
docker swarm join --token SWMTKN-1-xxx 192.168.1.10:2377

# 如果要加入为 Manager,需要先在已有 Manager 上获取 Manager token
docker swarm join-token manager
# 然后在新节点上用输出的命令加入

Worker token和Manager token是不同的,分开管理。

查看集群状态

1
2
3
4
5
docker node ls                  # 列出所有节点及角色、状态
docker node inspect <节点ID> # 查看节点详情
docker node promote <节点ID> # 把 Worker 提升为 Manager
docker node demote <节点ID> # 把 Manager 降为 Worker
docker node rm <节点ID> # 移除节点(需先 drain)

节点可用性

状态 说明
active 正常接收任务(默认)
pause 不接收新任务,已有任务继续运行
drain 不接收新任务,已有任务迁移到其他节点。常用于维护前
1
2
docker node update --availability drain <节点ID>   # 维护前排空节点
docker node update --availability active <节点ID> # 维护完恢复

异构节点与配置建议

实际环境中各节点的硬件配置未必一致,比如32C/288G和24C/64G混在同一个集群。Swarm的默认调度器不感知节点硬件差异——它只按”哪个节点任务少”来分配,不会自动把吃内存的服务调度到大内存机器上。这会导致几个问题:

  • 内存不均衡:大内存消耗的服务可能被调度到64G的小节点上,直接OOM。
  • CPU不均衡:计算密集型任务调度到小核机器上,性能下降。
  • 难以预测:副本分布随机,每次部署结果可能不同。

应对方式:

方式 做法 说明
标签约束(推荐) 给节点打标签,服务用--constraint绑定 最常用,精准控制
资源预留 deploy.resources.reservations声明最低要求 Swarm会跳过资源不足的节点
配置统一 同一集群尽量用相同配置的机器 最省心,消除调度的不确定性

标签约束示例:

1
2
3
4
5
6
7
# 给大内存节点打标签
docker node update --label-add mem=high node-32c-288g

# 创建服务时约束只跑在 mem=high 的节点上
docker service create --name bigapp \
--constraint 'node.labels.mem == high' \
myapp:latest

建议:同一集群尽量用相同配置的机器。配置一致时调度最简单、行为最可预测,不需要靠标签约束来弥补硬件差异。如果确实有异构节点,用标签把节点分组、服务用--constraint绑定到对应组,配合resources.reservations做兜底。

离开与解散集群

1
2
3
4
5
6
7
8
# Worker 离开集群
docker swarm leave

# Manager 离开需要加 --force(会导致集群丢一个管理节点)
docker swarm leave --force

# 在 Manager 上移除已离开的节点(状态变为 Down 后才能移除)
docker node rm <节点ID>

解散整个集群没有专门的命令——每个节点各自docker swarm leave,最后一个Manager用--force退出,集群就自然消失了。离开前记得先drain该节点,让上面的任务迁走。

服务管理

创建服务

1
2
3
4
5
# 创建一个 3 副本的 Nginx 服务,映射 80 端口
docker service create --name web --replicas 3 -p 80:80 nginx

# 创建 global 模式的监控服务(每个节点一个)
docker service create --name monitor --mode global prom/node-exporter

常用命令

命令 作用
docker service ls 列出所有服务
docker service ps web 查看服务的各个任务(哪些节点在跑、状态如何)
docker service inspect web 查看服务详细配置
docker service logs -f web 查看服务日志(聚合所有副本)
docker service scale web=5 扩缩容——把副本数调到5
docker service rm web 删除服务

docker service scale可以同时调多个服务:docker service scale web=5 api=3

滚动更新与回滚

更新镜像版本时,Swarm不会一次性替换所有副本,而是分批滚动替换:

1
docker service update --image nginx:1.25 web

更新行为可以在创建服务时或更新时配置:

参数 含义
--update-parallelism N 每批同时更新N个副本
--update-delay 10s 每批之间间隔10秒
--update-failure-action pause 更新失败时暂停(还可选continuerollback
--update-order stop-first 先停旧的再起新的(默认),另一个是start-first

如果更新出了问题,可以一键回滚:

1
docker service rollback web

这些参数对应的就是《Docker进阶篇》Compose示例里deploy.update_config下面的那些配置。

调度约束(placement)

控制服务的副本”往哪放”。命令行用--constraint--placement-pref指定,Compose 文件里对应deploy.placement(见后面「deploy 配置项详解」)。

机制 参数 作用
约束(constraint) --constraint 'node.role==worker' 硬性条件——不满足就不调度
偏好(preference) --placement-pref 'spread=node.labels.zone' 软性策略——尽量均匀分散

常用约束条件:

条件 示例
节点角色 node.role == worker
节点标签 node.labels.mem == high
节点主机名 node.hostname == node-01
引擎标签 engine.labels.os == linux

偏好的典型场景:跨机房/可用区部署时,用spread=node.labels.zone让副本尽量分散到不同zone,避免单zone故障时所有副本都挂。

配置与密钥管理(configs / secrets)

Swarm内置了配置和敏感信息的管理,不需要把配置文件bake进镜像、也不用靠环境变量传密码。

  • config:存储非敏感配置(如nginx.conf),以文件形式挂载到容器内。
  • secret:存储敏感信息(如数据库密码、TLS证书),加密存储在Raft日志里,只有被授权的服务才能读取,挂载到容器的/run/secrets/目录下(tmpfs,不落盘)。
1
2
3
4
5
6
7
8
9
10
11
# 创建 secret
echo "my_password" | docker secret create db_password -

# 创建 config
docker config create nginx_conf ./nginx.conf

# 服务使用 secret 和 config
docker service create --name web \
--secret db_password \
--config source=nginx_conf,target=/etc/nginx/nginx.conf \
nginx

在Compose文件里:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
services:
web:
image: nginx
secrets:
- db_password
configs:
- source: nginx_conf
target: /etc/nginx/nginx.conf

secrets:
db_password:
external: true # 引用已存在的 secret

configs:
nginx_conf:
file: ./nginx.conf # 从本地文件创建

config和secret更新后不会自动生效——需要docker service update重新挂载(或用版本化命名,如nginx_conf_v2,然后更新服务指向新版本)。

健康检查

Swarm可以在服务级别配置健康检查,决定容器是否”真正可用”。不健康的容器会被停掉并重新调度。

1
2
3
4
5
6
7
docker service create --name web \
--health-cmd "curl -f http://localhost/ || exit 1" \
--health-interval 30s \
--health-timeout 5s \
--health-retries 3 \
--health-start-period 60s \
nginx
参数 含义
--health-cmd 检查命令,返回0为健康、返回1为不健康
--health-interval 检查间隔(默认30s)
--health-timeout 单次检查超时(默认30s)
--health-retries 连续几次不健康才判定为故障(默认3)
--health-start-period 容器启动后的宽限期,期间失败不计入retries

健康检查在滚动更新时尤其关键——配合update_config.monitor,Swarm会等新容器健康检查通过后才继续更新下一批,避免一次性把所有副本换成有问题的版本。

网络与负载均衡

overlay 网络

Swarm集群中跨主机的容器通信靠overlay网络。docker swarm init时会自动创建一个名为ingress的overlay网络用于Routing Mesh,用户也可以自建:

1
2
docker network create --driver overlay --subnet 10.1.0.0/16 mynet
docker service create --name web --network mynet -p 80:80 nginx

overlay网络基于VXLAN隧道,把不同宿主机上的容器虚拟到同一个二层网络里,容器之间可以直接用服务名互访——和《Docker进阶篇》讲的自定义bridge的DNS解析是同一个道理,只是扩展到了跨主机场景。

Routing Mesh(路由网格)

Swarm内置的负载均衡机制。原理:服务发布端口后,集群中每个节点都会监听这个端口,不管请求打到哪个节点、该节点上有没有这个服务的容器,都会被自动转发到实际运行该服务的某个副本上。

1
客户端请求 → 任意节点:80 → Routing Mesh → 某个运行web容器的节点

这意味着可以把任意节点IP挂到负载均衡器(如Nginx、LB)的后端,不必关心服务具体跑在哪——Swarm自己做了一层内部的四层负载均衡。

Stack 与 deploy 配置

Stack把Compose文件部署到Swarm集群。和单机docker compose up不同,docker stack deploy走的是Swarm调度,deploy字段(replicas、update_config、resources等)会完整生效。

1
2
3
4
5
6
7
8
9
10
11
# 部署(-c 指定 compose 文件,my_stack 是栈名)
docker stack deploy -c docker-compose.yml my_stack

# 查看栈里有哪些服务
docker stack services my_stack

# 查看栈里所有任务的状态
docker stack ps my_stack

# 删除整个栈
docker stack rm my_stack

Stack会自动为栈创建一个overlay网络(名为栈名_default),栈内服务默认都接在上面。如果Compose文件里声明了自定义网络(如net: driver: overlay),也会自动创建。

Stack的核心价值在于声明式 + 一键部署:所有服务的镜像、副本数、更新策略、网络、卷都写在一个YAML文件里,docker stack deploy一条命令搞定。更新时改YAML后再执行同一条命令就行,Swarm会自动做差异化的滚动更新。

下面是一个真实的 Stack 示例(样本溯源系统),由 12 个微服务组成,同一镜像通过环境变量 SUPERVISOR_CONF_NAME 切换为不同角色,各服务按业务负载设置不同副本数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
version: '3.7'

services:
relation-source-handle:
image: "harbor.qihoo.net/ybjcjdz-mobile-url-collection/server:20260603082135"
environment:
SUPERVISOR_CONF_NAME: relation_source_handle
deploy:
mode: replicated
replicas: 5
relation-specimen-sort:
image: "harbor.qihoo.net/ybjcjdz-mobile-url-collection/server:20260603082135"
environment:
SUPERVISOR_CONF_NAME: relation_specimen_sorter
deploy:
mode: replicated
replicas: 4
relation-specimen-apk:
image: "harbor.qihoo.net/ybjcjdz-mobile-url-collection/server:20260603082135"
environment:
SUPERVISOR_CONF_NAME: relation_specimen_apk_handler
deploy:
mode: replicated
replicas: 20
relation-specimen-pe:
image: "harbor.qihoo.net/ybjcjdz-mobile-url-collection/server:20260603082135"
environment:
SUPERVISOR_CONF_NAME: relation_specimen_pe_handler
deploy:
mode: replicated
replicas: 4
relation-es-store:
image: "harbor.qihoo.net/ybjcjdz-mobile-url-collection/server:20260603082135"
environment:
SUPERVISOR_CONF_NAME: relation_es_store_handler
deploy:
mode: replicated
replicas: 20
relation-cascade:
image: "harbor.qihoo.net/ybjcjdz-mobile-url-collection/server:20260603082135"
environment:
SUPERVISOR_CONF_NAME: relation_cascade_handler_v2
deploy:
mode: replicated
replicas: 30
relation-apk-label:
image: "harbor.qihoo.net/ybjcjdz-mobile-url-collection/server:20260603082135"
environment:
SUPERVISOR_CONF_NAME: relation_apk_label_handler
deploy:
mode: replicated
replicas: 10
relation-specimen-modification:
image: "harbor.qihoo.net/ybjcjdz-mobile-url-collection/server:20260603082135"
environment:
SUPERVISOR_CONF_NAME: relation_specimen_modification
deploy:
mode: replicated
replicas: 4
network-apk-handler:
image: "harbor.qihoo.net/ybjcjdz-mobile-url-collection/server:20260603082135"
environment:
SUPERVISOR_CONF_NAME: network_apk_handler
deploy:
mode: replicated
replicas: 4
network-wd-sandbox:
image: "harbor.qihoo.net/ybjcjdz-mobile-url-collection/server:20260603082135"
environment:
SUPERVISOR_CONF_NAME: network_wd_sandbox_handler
deploy:
mode: replicated
replicas: 2
android-apt:
image: "harbor.qihoo.net/ybjcjdz-mobile-url-collection/server:20260603082135"
environment:
SUPERVISOR_CONF_NAME: android_apt
deploy:
mode: replicated
replicas: 5
vt-handler:
image: "harbor.qihoo.net/ybjcjdz-mobile-url-collection/server:20260603082135"
environment:
SUPERVISOR_CONF_NAME: vt_handler
deploy:
mode: replicated
replicas: 10

这个 Stack 体现了几个实践要点:

  • 同一镜像、多角色:所有服务用同一个镜像,通过 SUPERVISOR_CONF_NAME 环境变量让容器内的 Supervisor 加载不同的进程配置,实现”一个镜像跑多种服务”。升级时只需更新一个镜像 tag,所有服务统一升级。
  • 按负载定副本数:高吞吐的服务(如 relation-cascade: 30relation-specimen-apk: 20)给更多副本,低负载的(如 network-wd-sandbox: 2)只给少量副本,精细控制资源。
  • 一键部署docker stack deploy -c relation.yml relation 一条命令把 12 个服务全部拉起来,扩缩容只需改 replicas 再重新 deploy。

样本溯源服务部署情况
样本溯源服务部署情况

stack 常用命令

命令 作用
docker stack deploy -c xxx.yml 栈名 部署或更新栈
docker stack ls 列出所有栈
docker stack services 栈名 查看栈内服务
docker stack ps 栈名 查看栈内所有任务
docker stack rm 栈名 删除栈(连同服务、网络,卷保留)

Compose 中 deploy 配置项详解

Compose文件里的deploy字段是Swarm专属的——docker compose up会忽略它,只有docker stack deploy才完整生效。下面列全deploy下的所有配置项:

配置项 作用 示例值
mode 部署模式 replicated(默认)/ global
replicas 副本数(仅replicated模式) 5
endpoint_mode 负载均衡模式 vip(默认,虚拟IP)/ dnsrr(DNS轮询)
labels 服务级别的元数据标签 com.example.env: prod
placement 调度约束与偏好 见下方
resources 资源限制与预留 见下方
update_config 滚动更新策略 见下方
rollback_config 回滚策略(参数同update_config) 见下方
restart_policy 容器重启策略 见下方

placement(调度约束)

1
2
3
4
5
6
7
8
deploy:
placement:
constraints:
- node.role == worker
- node.labels.mem == high
preferences:
- spread: node.labels.zone # 按zone均匀分布
max_replicas_per_node: 2 # 每个节点最多放2个副本

max_replicas_per_node限制单节点的副本密度,防止一台机器堆太多副本。

resources(资源限制与预留)

1
2
3
4
5
6
7
8
deploy:
resources:
limits: # 硬上限,超了就被限制/OOM
cpus: '4'
memory: 8G
reservations: # 预留,调度时节点至少要有这么多空闲资源
cpus: '2'
memory: 2G

limits是天花板——容器不能用超;reservations是地板——节点资源不够这个数就不往上调度。两者配合用:reservations保证调度合理,limits防止单个容器吃光节点资源。

update_config(滚动更新策略)

1
2
3
4
5
6
7
8
deploy:
update_config:
parallelism: 8 # 每批更新几个
delay: 3s # 每批间隔
failure_action: pause # 失败时:pause / continue / rollback
monitor: 10s # 更新后监控多久,在此期间失败算更新失败
max_failure_ratio: 0.1 # 允许的最大失败比例(10%)
order: stop-first # stop-first(先停后起)/ start-first(先起后停)

下面是一个生产环境的大规模下载服务栈,重点演示update_config512 副本场景下的作用——一次性替换全部副本会瞬间重建几百条网络规则,把节点的iptables压垮,所以用parallelism + delay分批慢放:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
version: '3.7'

services:
transfer:
image: "harbor.qihoo.net/ybjcjdz-downloader/mobile-url-downloader:20260318100535"
command: [ "downloadTransfer" ]
deploy:
mode: replicated
replicas: 5
networks:
- net
mobile_url_collection:
image: "harbor.qihoo.net/ybjcjdz-downloader/mobile-url-downloader:20260318100535"
command: [ "mobileUrlCollectionDownloader" ]
deploy:
mode: replicated
replicas: 512
resources:
reservations:
memory: 2G # 每个副本预留 2G,节点空闲内存不足就不往上调度
update_config:
parallelism: 8 # 每次只同时启动/更新 8 个容器
delay: 3s # 每批次间隔 3 秒,给 iptables 喘息的时间
failure_action: pause
order: stop-first
networks:
- net
cooperator:
image: "harbor.qihoo.net/ybjcjdz-downloader/mobile-url-downloader:20260318100535"
command: [ "cooperatorDownloader" ]
deploy:
mode: replicated
replicas: 0 # 副本数置 0:服务定义保留,但暂不实际运行,需要时 scale 拉起
networks:
- net
spider:
image: "harbor.qihoo.net/ybjcjdz-downloader/mobile-url-downloader:20260318100535"
command: [ "spiderDownloader" ]
deploy:
mode: replicated
replicas: 0
networks:
- net
networks:
net:
driver: overlay # 自建 overlay 网络,四个服务跨主机用服务名互通
ipam:
driver: default
config:
- subnet: "10.1.0.0/16"

几个值得注意的点:

  • parallelism: 8 + delay: 3s:512 个副本如果一次性全换,瞬间重建的网络规则会把节点iptables打满。分成每批8个、间隔3秒慢慢滚,是大副本数服务更新时的关键保护。
  • replicas: 0cooperatorspider把副本数设为0——服务定义保留在栈里,但不实际起容器。需要时docker service scale 栈名_cooperator=10即可秒级拉起,省去重新部署。
  • reservations.memory: 2G:配合前面「异构节点」讲的资源预留,保证每个副本被调度到至少有2G空闲内存的节点,避免OOM。
  • 自建overlay网络net:四个服务接在同一个overlay上,跨主机直接用服务名通信,对应前面「overlay 网络」一节。

下载服务部署情况
下载服务部署情况

rollback_config(回滚策略)

参数和update_config完全一致,控制的是docker service rollback或自动回滚时的行为。

restart_policy(重启策略)

1
2
3
4
5
6
deploy:
restart_policy:
condition: on-failure # none / on-failure / any(默认)
delay: 5s # 重启前等待
max_attempts: 3 # 最大重试次数(默认无限)
window: 120s # 判定重启是否成功的时间窗口

注意deploy.restart_policy和顶层的restart不是一回事——restartdocker compose up用的,restart_policy是Swarm用的。

Swarm vs Kubernetes

Swarm和K8s都是容器编排工具,解决的是同一类问题——把容器调度到集群里、管理副本、滚动更新、服务发现。但定位和复杂度差别很大。

对比项 Docker Swarm Kubernetes(K8s)
定位 Docker原生,轻量编排 生产级、工业标准编排平台
安装复杂度 docker swarm init一条命令 需要单独部署控制面(etcd、apiserver、scheduler等)
学习曲线 低,会Docker就会用 高,概念多、配置复杂
调度单位 Task(一个容器) Pod(一个或多个容器)
服务定义 docker service create或Compose文件 YAML资源清单(Deployment、Service等)
滚动更新 内置,参数简单 内置,策略更丰富(蓝绿、金丝雀可扩展)
自愈能力 有,容器挂了会重新调度 有,且更精细(健康检查、就绪探针等)
扩展性 适合中小规模(几十到上百节点) 支持数千节点级别
生态 相对封闭,社区萎缩 极其丰富(Helm、Istio、Prometheus等)
适用场景 团队小、集群不大、快速上手 大规模生产、微服务治理、多租户

一句话:Swarm胜在简单,K8s胜在强大。小团队、中等规模、不想引入太多复杂度时Swarm够用;一旦规模上去、需要精细的调度策略和丰富的生态,K8s基本是唯一选择。目前行业趋势是K8s已经成为事实标准,Swarm的使用在逐年减少。

K8s 核心概念速览

K8s的完整体系需要独立成篇,这里只列最核心的几个概念,建立一个基本的认知框架,方便后续深入。

概念 作用 和Swarm的对应关系
Pod K8s最小调度单位,一个Pod里可以有1~N个容器,共享网络和存储 对应Swarm的Task(但Task只有一个容器)
Deployment 管理Pod的副本数、滚动更新、回滚 对应Swarm的Service
Service 为一组Pod提供稳定的访问入口(虚拟IP + DNS),做负载均衡 对应Swarm的Routing Mesh + 服务名DNS
Namespace 逻辑隔离,同一集群内划分多个虚拟空间(如dev/staging/prod) Swarm无对应,Stack只是分组不隔离
Ingress 七层(HTTP)路由入口,把外部域名/路径映射到集群内的Service Swarm只有四层负载均衡(Routing Mesh)
ConfigMap / Secret 配置和敏感信息管理,与容器解耦 对应Swarm的configs/secrets
Node 集群中的工作机器 和Swarm Node一致

K8s的架构也是Master(控制面)+ Worker(数据面),控制面组件包括etcd(存储)、kube-apiserver(API入口)、kube-scheduler(调度器)、kube-controller-manager(控制器),Worker上跑kubelet和kube-proxy。比Swarm的Manager/Worker拆得更细、各司其职。

K8s的所有操作都是声明式的:写YAML描述”期望状态”,kubectl apply提交给apiserver,控制器持续驱动”当前状态”向”期望状态”收敛。和Swarm的docker stack deploy思路一致,但K8s的资源类型(CRD可自定义扩展)远比Swarm丰富。

K8s的安装、部署和实操内容较多,留给独立的篇章记录。