跨三大洲的 Docker Swarm:以 100% 正常运行时间为设计目标的高可用架构
单个数据中心就是一个单点故障。本文搭建一个横跨三大洲的 Docker Swarm,即使整个机房宕机也无妨:内容涵盖 Manager Quorum、WireGuard、每个区域的入口、Geo-DNS 故障转移、数据库复制以及日常运维。
一台位于单个数据中心的服务器,无论硬件和网络多么出色,都是一个单点故障。一旦这个机房出现故障,例如供电或网络中断,或者仅仅是维护时的一次失误,应用就会随之下线。跨多个数据中心的 Docker Swarm 正好解决了这个问题:容器运行在三个相互独立的机房中,理想情况下分布在三个大洲;即使其中一个机房完全宕机,另外两个也会接管服务,用户对此毫无察觉。
本文将一步步介绍如何搭建一个以 100% 正常运行时间为设计目标的 Docker Swarm 集群:在北美、欧洲和亚洲各部署一台服务器,节点之间通过加密的 WireGuard 网络互联,由 Manager 组成的 Quorum 即使整个大洲宕机也能维持,每个区域设有一个入口,DNS 故障转移会自动把用户引导到最近的健康机房。我们还会坦诚地说明,即使采用这种架构,哪些环节仍可能出现故障,以及如何把这些风险也一并化解。
Docker Swarm 能实现 100% 正常运行时间吗?
跨三大洲的 Docker Swarm 以 100% 正常运行时间为设计目标:任何单台服务器、任何单个数据中心、任何单个大洲,都无法单独让应用停止运行。尽管如此,没有人能够保证绝对的可用性,即使是大型云服务商也做不到,它们承诺的最高可用性在 99.99% 到 99.999% 之间。原因不在于数据中心本身,而在于所有机房共有的那些环节。本文也会专门讨论这些环节,帮助您在技术允许的范围内尽可能接近 100%。
用数字看可用性
| 可用性 | 每年停机时间 | 每月停机时间 |
| 99% | 87.6 小时 | 7.3 小时 |
| 99.9% | 8.76 小时 | 43.8 分钟 |
| 99.99% | 52.6 分钟 | 4.4 分钟 |
| 99.999% | 5.3 分钟 | 26 秒 |
以上数据按每年 8,760 小时、每月 730 小时计算。每多一个 9,允许的停机时间就缩短到原来的十分之一,而单台服务器力所不及的工作,正是从这里开始的。
为什么分布在三大洲效果如此显著
三个相互独立、可用性各为 99.9% 的机房,按计算只有在三者同时出现故障时才会一起宕机:0.1% 乘以 0.1% 再乘以 0.1%,结果是 0.0000001%。机房之间相距越远,实际上就越相互独立:各自的电网、各自的网络接入、各自的天气状况、各自的维护窗口。因此,把集群分布在北美、欧洲和亚洲,是用服务器所能构建的最强的容灾形式。
即使跨三大洲,仍可能出故障的环节
剩下的风险在于所有机房共同的依赖,而每一项都有对应的应对措施:
- 有缺陷的更新会被集群像正常更新一样可靠地分发到所有机房。应对措施:健康检查和自动回滚,再加上逐个区域更新。
- DNS 是所有用户都必经的唯一环节。应对措施:选用具备全球分布式网络和故障转移能力的 DNS 服务商,并设置较短的 TTL。
- 数据库必须在所有机房保存相同的数据。应对措施:带自动切换的复制,详见关于数据的章节。
- 证书和域名过期会同时波及所有机房。应对措施:自动续期,并监控到期日期。
- 切换本身需要等健康检查和 DNS 做出反应,通常要一到两分钟,其间个别请求可能会失败。应对措施:缩短检查间隔、使用较短的 TTL,并让客户端重试失败的请求。
架构概览
跨多个大洲的 Docker Swarm 由六个部分组成,每个部分都消除一个特定的故障点:
| 组成部分 | 作用 | 可防范的故障 |
| 分布在三个大洲的三个 Manager 节点 | 通过 Raft 共识维护集群状态 | 整个机房或整个大洲宕机 |
| 每个区域的 Worker 容量 | 在靠近用户的地方运行容器 | 单台服务器故障 |
| 所有节点之间的 WireGuard 网络 | 对经由互联网传输的全部集群流量进行加密 | 数据中心之间的窃听和篡改 |
| 每个区域的入口(反向代理) | 接收用户请求并在本地响应 | 某个区域的入口故障 |
| 带健康检查的 Geo-DNS | 将用户引导到最近的健康机房 | 无法访问的机房 |
| 多副本数据存储与备份 | 在多个地点保存数据库和文件 | 机房故障导致的数据丢失 |
需要多少个 Manager,部署在哪里?
Swarm 的 Manager 节点使用 Raft 共识算法管理集群状态。每一项变更都需要获得多数 Manager 的同意,这个多数就是所谓的 Quorum(法定多数)。一旦失去多数,现有容器虽然会继续运行,但集群既无法重新调度,也无法弥补故障,更无法分发更新。
| Manager 数量 | 多数 | 可容忍的故障数 |
| 3 | 2 | 1 |
| 5 | 3 | 2 |
| 7 | 4 | 3 |
Docker 建议使用奇数个 Manager,并将它们分布在至少三个可用区中:三个 Manager 按 1-1-1 分布,五个按 2-2-1 分布。由此得出本文最重要的一条规则:两个机房不够。只有两个机房时,必然有一个机房的 Manager 更多,而一旦恰好是这个机房宕机,多数就不复存在。只有三个机房,Quorum 才能在任意一个数据中心宕机后依然保持;如果分布在三个大洲,就意味着能够承受整个大洲的故障。
三大洲还是一个大洲:如何权衡
对集群的每一项变更、每一次部署、每一次容器的重新调度,都要等待多数 Manager 的确认。在欧洲、北美和亚洲之间,每一次确认都要经历约 80 到 250 毫秒的数据包传输时延。这对用户没有影响,因为他们的请求都在本地得到响应;但部署和重新调度所需的时间,会明显长于网络路径较短的集群。
| 方案 | 优势 | 代价 |
| 三大洲(美国、欧洲、亚洲) | 独立性最高,全球用户都能就近访问服务器,允许整个大洲宕机 | 集群管理较慢,数据库需要跨远距离复制,请求必须留在本地 |
| 同一大洲的三个机房(例如法兰克福、斯特拉斯堡、华沙) | 集群管理快速,同步复制简单 | 大洲范围内的大规模事件会波及所有机房,距离较远的用户访问路径更长 |
如果应用的用户分布在多个大洲,目标又是尽可能高的可用性,那么三大洲方案就是正确的选择,本文教程搭建的也正是这种方案。其中有一条贯穿所有步骤的重要规则:每个请求都在其所在区域内得到响应,绝不在大洲之间来回传输。
哪些 KernelHost 机房适合
KernelHost 在美因河畔法兰克福的 maincubes 数据中心运营服务器,并在欧洲、北美和亚太地区的更多机房提供虚拟服务器,其中包括美国的三个机房,以及加拿大、伦敦、斯特拉斯堡、华沙、赫尔辛基、新加坡、日本、悉尼和孟买。带地图的完整列表见服务器机房位置页面。本文示例中,欧洲选用美因河畔法兰克福,北美选用美国东海岸,亚洲选用新加坡。
教程:搭建跨三大洲的 Docker Swarm
示例使用三台服务器:位于美因河畔法兰克福的 swarm-eu、位于美国东海岸的 swarm-us,以及位于新加坡的 swarm-asia。公网地址取自文档专用网段 203.0.113.0/24,WireGuard 网络使用 10.10.0.0/24。请将两者替换为您自己的值。三个节点同时担任 Manager 和 Worker;如需更多性能,以后可以在每个区域再添加纯 Worker 节点。
第 1 步:在三个大洲开通服务器
在三个区域各订购一台运行 Debian 12 或 13 的服务器,并完成基础加固:SSH 只允许密钥登录、自动安装安全更新、使用独立的用户账户。新 Root 服务器检查清单涵盖了这些内容。请设置含义明确的主机名,这样在 docker node ls 中就能一眼看出每个节点位于何处。
hostnamectl set-hostname swarm-eu
第 2 步:在所有节点上安装 Docker
在全部三台服务器上从 Docker 官方软件源安装 Docker Engine,具体方法见在 Debian 和 Ubuntu 上安装 Docker一文。随后在每个节点上检查版本,三个节点应当使用相同的主版本:
docker version --format '{{.Server.Version}}'
第 3 步:在各大洲之间搭建 WireGuard 网络
各节点之间通过公共互联网通信。为了让全部集群流量都经过加密,并确保 Swarm 端口永远不会暴露在公网上,我们用一个 WireGuard 网络把三台服务器连接起来。首先在每个节点上生成一对密钥:
apt-get install -y wireguard
umask 077
wg genkey | tee /etc/wireguard/private.key | wg pubkey > /etc/wireguard/public.key
然后为每个节点创建文件 /etc/wireguard/wg0.conf。下面是它在 swarm-eu 上的内容,另外两个节点按对称方式配置:
[Interface]
Address = 10.10.0.1/24
ListenPort = 51820
PrivateKey = SWARM_EU_私钥
MTU = 1420
[Peer]
PublicKey = SWARM_US_公钥
Endpoint = 203.0.113.12:51820
AllowedIPs = 10.10.0.2/32
PersistentKeepalive = 25
[Peer]
PublicKey = SWARM_ASIA_公钥
Endpoint = 203.0.113.13:51820
AllowedIPs = 10.10.0.3/32
PersistentKeepalive = 25
systemctl enable --now wg-quick@wg0
ping -c 3 10.10.0.2
只要所有节点都能通过各自的 10.10.0.x 地址响应,网络就搭建好了。PersistentKeepalive 可以让连接在有状态防火墙之后也保持畅通。ping 现在显示的大洲之间的时延,正是集群每一次变更都要付出的等待时间。
第 4 步:配置防火墙,只允许 Swarm 节点访问
Docker Swarm 在节点之间需要以下端口:2377/TCP 用于集群管理,7946/TCP 和 UDP 用于节点之间的通信,4789/UDP 用于 Overlay 网络。这些端口只在 WireGuard 接口上放行;对公网只开放 WireGuard 本身,而且仅限其他节点访问。使用 ufw 时,swarm-eu 上的配置如下:
ufw allow from 203.0.113.12 to any port 51820 proto udp
ufw allow from 203.0.113.13 to any port 51820 proto udp
ufw allow in on wg0 to any port 2377 proto tcp
ufw allow in on wg0 to any port 7946
ufw allow in on wg0 to any port 4789 proto udp
重要提示:Docker 为容器发布的端口会绕过 ufw,因为 Docker 会设置自己的 iptables 规则。因此,只发布入口的端口(80 和 443),绝不要发布数据库端口或管理端口。
第 5 步:初始化 Swarm 并添加 Manager
在 swarm-eu 上初始化 Swarm,并确保管理流量和数据流量都经由 WireGuard 传输:
docker swarm init --advertise-addr 10.10.0.1 --data-path-addr 10.10.0.1
docker swarm join-token manager
第二条命令会输出供其他 Manager 加入集群的命令。在 swarm-us 和 swarm-asia 上分别使用各自的 WireGuard 地址执行该命令,下面以 swarm-us 为例:
docker swarm join --token SWMTKN-1-... --advertise-addr 10.10.0.2 --data-path-addr 10.10.0.2 10.10.0.1:2377
docker node ls
之后,docker node ls 会显示三个节点,其中一个的状态为 Leader,另外两个为 Reachable。加入令牌属于机密:任何知道它的人,都能把自己的 Manager 偷偷加入您的集群。搭建完成后,请用 docker swarm join-token --rotate manager 轮换令牌。
第 6 步:启用 Autolock
Manager 将集群状态连同用于加密 Raft 日志的密钥一起保存在 /var/lib/docker/swarm/ 下。启用 Autolock(自动锁定)后,这些密钥本身也会被加密;Manager 重启后,必须输入解锁密钥才能重新加入集群:
docker swarm update --autolock=true
docker swarm unlock
第一条命令会输出解锁密钥,请把它保存在密码管理器中。第二条命令在每次重启 Manager 后都要用到。没有这个密钥,即使有备份也无法恢复 Swarm,因此请将它与服务器分开保管。
第 7 步:按区域为节点打标签
标签告诉调度器每个节点位于何处,后续步骤中的放置约束都以此为基础:
docker node update --label-add region=eu swarm-eu
docker node update --label-add region=us swarm-us
docker node update --label-add region=asia swarm-asia
第 8 步:创建 MTU 合适的 Overlay 网络
位于不同机房的容器通过 Overlay 网络相互通信。由于 Overlay 网络要经过 WireGuard 隧道,它的 MTU 必须更小:WireGuard 使用 1420 字节,Overlay 网络(VXLAN)要从中占用 50 字节存放自己的报头,剩下 1370 字节:
docker network create --driver overlay --attachable --opt com.docker.network.driver.mtu=1370 appnet
MTU 过大时,症状很隐蔽:小请求一切正常,大响应却会卡住。如果不使用 WireGuard,也可以改用 --opt encrypted 为 Overlay 网络加密;这时节点之间还必须额外放行 IP 协议 50(ESP),而且 Docker 明确指出这会带来明显的性能损失。我们推荐 WireGuard,因为它覆盖包括管理流量在内的全部流量。
第 9 步:在每个区域运行应用
普通的 Swarm 服务会通过自己的服务地址,把请求分发给集群中的所有副本,其中也包括位于其他大洲的副本。在三大洲部署中,这意味着每两三个请求中就会有一个绕行半个地球。因此,每个区域都有一个独立的服务,并通过放置约束将其限定在本区域内。更新参数则确保新版本逐个容器地发布,并在出错时自动回滚:
for r in eu us asia; do
docker service create --name web-$r --replicas 2 --network appnet \
--constraint node.labels.region==$r \
--update-parallelism 1 --update-delay 30s \
--update-failure-action rollback \
registry.example.com/web:1.0
done
为了让 Swarm 能够判断容器是真的在正常工作,而不只是处于运行状态,镜像中应当包含健康检查,例如在应用的 Dockerfile 中加入这一行:
HEALTHCHECK --interval=10s --timeout=3s --retries=3 CMD wget -qO- http://127.0.0.1:8080/health || exit 1
如果某个容器的健康检查连续三次失败,它就会被替换;在更新过程中,健康检查失败会中止发布。
第 10 步:每个区域一个入口
入口由 Caddy、Traefik 或 nginx 之类的反向代理承担。它同样在每个区域作为独立服务运行,只把请求转发给本区域的应用。在 host 模式下,它会直接在本区域的服务器上发布 80 和 443 端口。由于 Caddy 从环境变量中读取转发目标,一份共用的配置就足够了:
example.com {
reverse_proxy {$UPSTREAM}:80
}
docker config create caddyfile ./Caddyfile
for r in eu us asia; do
docker service create --name edge-$r --network appnet \
--constraint node.labels.region==$r \
--env UPSTREAM=web-$r \
--config source=caddyfile,target=/etc/caddy/Caddyfile \
--publish mode=host,target=80,published=80 \
--publish mode=host,target=443,published=443 \
caddy:2
done
所有区域都需要同一个域名的 TLS 证书。因此,请通过 DNS 验证(DNS Challenge)申请证书,这种方式不受 DNS 记录当前指向哪个区域的影响;为此,Caddy 需要安装与您的 DNS 服务商对应的模块。反向代理的基础知识,请参阅将 nginx 配置为反向代理一文。
第 11 步:配置带故障转移的 Geo-DNS
最后一个组成部分负责把用户引导到正确的区域。支持地理位置路由和健康检查的 DNS 服务会把欧洲用户引导到美因河畔法兰克福,把美洲用户引导到美国东海岸,把亚洲用户引导到新加坡。某个区域宕机时,健康检查会在 30 到 60 秒内发现,并把该区域的用户引导到最近的健康区域。请将记录的生存时间(TTL)设为 60 秒,以便解析器迅速采用切换后的结果。没有健康检查的多条 A 记录只是权宜之计:浏览器虽然经常会尝试下一个地址,但并非所有客户端都会这样做,而且宕机区域的地址仍会留在应答中。
请实事求是地估算:从宕机到切换完成,需要经过检查间隔加上 TTL 的时间,在本例中约为一到两分钟;在此期间,受影响区域的一部分用户仍会访问到已宕机的机房。如果应用程序和 App 会在短暂等待后重试失败的请求,就能在用户几乎察觉不到的情况下度过这段时间。
第 12 步:测试区域故障
从未演练过的故障转移,在真正出事时很少能正常工作。请将某个区域的节点撤出运行,以此模拟该区域宕机,并观察集群和 DNS 的反应:
docker node update --availability drain swarm-asia
docker node ls
docker service ls
docker node update --availability active swarm-asia
由于该区域的服务通过放置约束绑定在自己的节点上,它们不会迁移,而是暂停运行;该区域的用户由 DNS 故障转移接管。因此,这项测试主要检查两点:健康检查是否把该区域从应答中移除,以及相邻区域能否承担额外的负载。如需更严格的测试,可以把节点完全断网,例如停止 WireGuard。每次较大的变更之后都要重复这项测试,并且至少每季度进行一次。
数据:高可用中最难的部分
Docker Swarm 复制的是容器,而不是数据。数据卷(Volume)始终位于运行该容器的节点上。因此,Web 前端和 API 之类的无状态服务可以毫无障碍地在每个区域运行,而凡是涉及数据的部分,都需要单独的复制机制。
跨大洲复制数据库
数据库自带复制功能,它始终优于跨数据中心的共享存储。在跨大洲的场景中,行之有效的做法是:在一个区域运行主实例,在另外两个区域运行异步副本。例如,PostgreSQL 可以使用流复制(Streaming Replication),并借助 Patroni 之类的工具实现自动切换;MariaDB 和 MySQL 则使用内置的复制功能。这样,每个区域都在本地响应读请求,写操作则发往主实例。坦白地说,异步也意味着:一旦主区域宕机,最后几秒的写入可能会丢失。如果要在全球范围内写入且不丢失任何数据,就应选用专为多区域设计的数据库,例如 CockroachDB 或 YugabyteDB。请通过放置约束把数据库节点固定在各自的区域,以免 Swarm 将它们迁移到没有其数据的节点上:
docker service create --name db-asia --constraint node.labels.region==asia ...
文件与上传内容
用户上传的文件不应放在本地数据卷中,而应存放在兼容 S3、并复制到第二个区域的对象存储中,或者存放在自建的多副本存储系统中。跨大洲使用 NFS 之类的网络文件系统不仅速度慢,其本身也是一个单点故障。
会话与缓存
如果应用把会话保存在容器的内存中,用户会在切换时丢失登录状态。请把会话存放在经过复制的数据库或经过复制的缓存(例如 Redis)中,或者使用每个区域都能自行验证的签名 Token。
备份依然必不可少
复制能防范机房故障,却防不住错误操作:一条被误删的记录,几秒钟后就会在所有区域被删除。因此,每一套高可用架构都应包含定期进行、经过测试并存放在独立地点的备份,具体见服务器备份策略一文。
运维:更新、维护与监控
逐个区域更新
不要在所有区域同时发布新版本,而应依次发布,并在进入下一个区域之前先观察当前区域一小段时间。这样,即使出现健康检查发现不了的缺陷,也最多只影响一个区域,另外两个区域会继续为该区域的用户提供服务:
for r in asia us eu; do
docker service update --image registry.example.com/web:1.1 web-$r || break
sleep 300
done
如果更新失败,得益于第 9 步中的设置,Swarm 会自动回滚;一旦命令报错,|| break 就会终止循环。对于事后才暴露问题的更新,请用 docker service rollback web-asia 手动回滚。
维护单个区域
如果某台服务器需要重启或更新,请用 docker node update --availability drain 将其撤出运行,并事先让 DNS 故障转移把它的用户引导到相邻区域。维护结束后,用 --availability active 让它重新投入运行。在处理下一个 Manager 之前,请等到 docker node ls 再次显示三个节点均可访问,以确保永远不会同时缺少两个 Manager。
从外部监控
请从集群外部对每个区域分别进行监控:入口的可达性、服务的健康检查、Manager 的状态、数据库的复制延迟,以及证书和域名的到期日期。即使整个区域都没有了响应,告警也必须能够送达。如何为单台服务器搭建这样的监控,请参阅搭建服务器监控一文。
安全地分发机密
密码和密钥不应放在环境变量或 Compose 文件中,而应交给 Docker Secrets 管理。它们以加密形式存储在 Raft 日志中,只会分发给您明确指定的服务:
printf '%s' '您的_数据库密码' | docker secret create db_password -
docker service update --secret-add db_password web-eu
为什么选择 KernelHost 部署跨大洲的 Swarm
与单台服务器相比,跨多个大洲的集群对服务商有着不同的要求。在实践中,以下几点起决定作用:
| 要求 | 为什么重要 | KernelHost 的方案 |
| 多个大洲的机房 | Quorum 需要三个相互独立的机房,用户希望访问路径短 | 美因河畔法兰克福,另有欧洲、北美和亚太地区的机房,全部由一家服务商提供 |
| 无限流量 | WireGuard、Overlay 网络和数据库复制会在大洲之间持续产生流量 | 无限流量 VPS,不设流量上限 |
| DDoS 防护 | 每个入口都可以从公网访问,因此都是攻击目标 | 每个机房均已包含,核心机房美因河畔法兰克福采用 3.2 Tbps Arbor 实时过滤,不做黑洞路由 |
| 完整的 Root 权限 | WireGuard、防火墙和 Docker Engine 都需要完全的控制权 | 每台 KVM Root 服务器和独立服务器均提供 |
| 快速开通 | 替换节点和测试区域应在几分钟内就绪 | 美因河畔法兰克福约 30 秒,其他机房通常只需几分钟 |
| 每个节点均无合约绑定 | 节点随需求增减 | PrePaid 预付费,无最低合约期,无开通费 |
| 自动化 | 新节点应能通过脚本创建 | 通过 KernelHost API 订购和控制 |
所有云服务器套餐的价格概览,以及与大型云服务商的成本对比,请见云服务器租用页面。
常见错误及避免方法
- Manager 只分布在两个机房。拥有多数 Manager 的机房一旦宕机,集群就会停摆。解决方法:使用三个机房,按 1-1-1 或 2-2-1 分布。
- Manager 数量为偶数。四个 Manager 能容忍的故障数并不比三个多,却会增加协调开销。解决方法:3 个、5 个或 7 个。
- 请求在大洲之间来回传输。在所有区域共用一个服务地址,会让用户的请求绕行半个地球。解决方法:每个区域一个服务、一个入口。
- Swarm 端口可从公网访问。2377 端口和 Overlay 网络绝不能暴露在开放的互联网上。解决方法:只经由 WireGuard 通信,对公网只开放 80、443 以及供其他节点使用的 WireGuard。
- 忘记调整 MTU。大响应卡住,小响应正常。解决方法:WireGuard 使用 1420 时,Overlay MTU 设为 1370。
- 依赖 ufw 保护容器端口。对于已发布的端口,Docker 会绕过 ufw。解决方法:只发布入口。
- 数据库放在没有复制的数据卷中。区域一旦宕机,数据就无法访问。解决方法:为数据库配置复制,并将其放置位置固定在所属区域。
- 在所有区域同时更新。一旦出错,全球所有用户都会受到影响。解决方法:逐个区域发布。
- DNS TTL 过长。如果 TTL 为一天,故障转移要到第二天才会生效。解决方法:60 秒。
- 用复制代替备份。错误会像正常数据一样被复制出去。解决方法:另外在独立地点保存经过测试的备份。
要点总结
- 跨三大洲的 Docker Swarm 以 100% 正常运行时间为设计目标:即使整个机房或整个大洲宕机,应用也不会停止运行。
- 没有人能够绝对保证可用性;剩下的风险来自 DNS、有缺陷的更新、数据库和证书,而每一项都有对应的应对措施。
- 三个机房各部署一个 Manager 是最低要求,两个机房不足以构成具备容错能力的 Quorum。
- 每个请求都留在其所在区域:每个区域一个服务、一个入口,再加上带健康检查和较短 TTL 的 Geo-DNS。
- WireGuard 加密集群流量,Swarm 端口对外不可见,Overlay MTU 降至 1370。
- Swarm 复制的是容器,而不是数据:数据库需要自己的复制机制,备份依然必不可少。
- KernelHost 提供欧洲、北美和亚太地区的机房、无限流量、覆盖每个机房的 DDoS 防护,以及无最低合约期的 PrePaid 预付费计费方式。
常见问题
Docker Swarm 能保证 100% 正常运行时间吗?
高可用的 Docker Swarm 需要多少个 Manager 节点?
为什么两个数据中心不足以支撑 Docker Swarm?
Swarm 的 Manager 可以分布在不同大洲吗?
Docker Swarm 需要哪些端口?
需要 WireGuard 吗,还是加密的 Overlay 网络就足够了?
大洲之间的故障转移是如何实现的?
机房宕机时,数据库如何保持可用?
多机房部署该选 Docker Swarm 还是 Kubernetes?
哪些 KernelHost 机房适合部署跨三大洲的 Swarm?
跨三大洲的 Docker Swarm 需要多少费用?
2026 KernelHost GmbH。保留所有权利。本教程受著作权法保护,未经我们书面同意,不得在其他网站上转载,节选转载或改写后转载同样不被允许。欢迎在注明出处并附上链接的前提下引用。

