编程 Uncloud:没有控制面的多机 Docker 编排,WireGuard 组网 + CRDT 同步状态

2026-10-09 21:30:48

Uncloud:没有控制面的多机 Docker 编排,WireGuard 组网 + CRDT 同步状态

项目地址:github.com/psviderski/uncloud
文档:uncloud.run/docs

Uncloud 是一个轻量集群与容器编排工具,用来把云主机、独立服务器、裸金属机器组成一个统一的计算环境,部署和管理 Web 应用。它会在你的 Docker 主机之间建立一条 WireGuard mesh 私有网络,并提供服务发现、负载均衡、带 HTTPS 的入口,以及一套简单 CLI。

和传统编排器不同,Uncloud 没有中心控制面,也没有需要维护的 quorum。每台机器通过点对点通信持有一份同步的集群状态副本,部分机器掉线时集群操作仍然可用。

定位上,它落在 Docker 和 Kubernetes 之间:比 Swarm 更去中心,比 K8s 少一整套运维负担。适合想要自托管基础设施的灵活性、但不想背上 Kubernetes 运维复杂度的开发者。

特性

  • 部署位置自由:云主机、独立服务器、裸金属可以混在同一套计算环境里。
  • Docker Compose:用熟悉的格式定义服务和卷。
  • 零停机部署:滚动更新不中断服务,失败自动回滚在计划中。
  • Unregistry 集成:直接构建并推送镜像到自己的机器上,不需要外部 registry,只传输缺失的镜像层。
  • 服务发现:内置 DNS 服务器把服务名解析成容器 IP。
  • 持久化存储:Docker 卷可跨机器管理。
  • 零配置私有网络:自动 WireGuard mesh,自带 peer 发现和 NAT 穿透,容器拥有唯一 IP。
  • 无控制面:完全去中心化,消除单点故障。
  • 命令式优先于声明式:用命令式操作代替状态协调,心智模型和排障都更简单。
  • 托管 DNS:通过 Uncloud DNS 服务自动创建 *.xxxxxx.uncld.dev 记录。
  • 自动 HTTPS:内置 Caddy 反向代理,用 Let's Encrypt 完成证书签发与续期。
  • TLS 证书的集群存储:Caddy 使用原生集群存储,在多台机器间共享证书和 ACME challenge token,并协调签发。
  • 类 Docker CLI:命令习惯与 Docker 接近。
  • 远程管理:SSH 到任意一台机器就能管整个基础设施。

快速开始

1)安装 Uncloud CLI:

brew install psviderski/tap/uncloud
# 或者用 curl(macOS/Linux)
curl -fsS https://get.uncloud.run/install.sh | sh

另有 nightly rolling release 可用。

2)初始化第一台机器:

uc machine init root@your-server-ip

3)从 Docker 镜像部署应用,把容器 8000 端口以 app.example.com 域名发布为 HTTPS:

uc run -p app.example.com:8000/https image/my-app

4)创建一条 DNS A 记录,把 app.example.com 指向你的服务器 IP。

5)清理:

uc ls
uc rm my-app-name
uncloud-uninstall

工作原理

一个跨多家云厂商、由 3 台机器组成的集群示意。

初始化第一台机器

$ uc machine init --name oracle-vm ubuntu@152.67.101.197

执行过程包括:运行安装脚本、安装 Docker、创建 uncloud 用户/组、安装 uncloudd 二进制、写入卸载脚本、安装 systemd unit(uncloud.socket / uncloud.service)、启动 uncloud machine daemon。

输出:

Cluster "default" initialised with machine "oracle-vm"
Reserved cluster domain: xuw3xd.cluster.uncloud.run
Deploying service caddy 1/1
Updating cluster domain records in Uncloud DNS...
DNS records updated.

背后发生的事:

  1. CLI 通过 SSH 登录机器,安装 Docker 和由 systemd 管理的 uncloudd machine daemon。
  2. 生成一对唯一的 WireGuard 密钥,为该机器及其容器分配专属子网 10.210.0.0/24,配置 uncloudd。之后所有通信都通过 SSH 之上的 gRPC API 与 uncloudd 交互。
  3. 配置并启动 corrosion——一个基于 CRDT 的分布式 SQLite 数据库,把它作为 Docker 容器、由 uncloudd 管理,用来在多机之间共享集群状态。
  4. 创建一个连接到 WireGuard 接口的 Docker bridge 网络。
  5. 这台机器成为集群的接入点,记录在 ~/.config/uncloud/config.yaml 的集群配置里。

添加第二台机器

$ uc machine add --name hetzner-server root@5.223.45.199

输出:

Machine "hetzner-server" added to cluster
Deploying service caddy 1/1 on hetzner-server
DNS records updated to use only the internet-reachable machines running caddy service:
  *.xuw3xd.cluster.uncloud.run  A -> 152.67.101.197, 5.223.45.199

查看机器列表:

$ uc machine ls

列包含:NAME、STATE、ADDRESS、PUBLIC IP、WIREGUARD ENDPOINTS。

背后发生的事:

  1. 第二台机器按与第一台相同的方式初始化;如果 SSH 用户不是 root,需要 sudo 权限。
  2. 分配子网 10.210.1.0/24。
  3. 在集群状态中注册,并交换 WireGuard 密钥。
  4. 两台机器建立 WireGuard 隧道,bridge 网络上的容器可以跨机通信。
  5. 在第二台机器上启动 uncloud-corrosion 容器以同步状态。
  6. 该机器成为备选接入点。
  7. 若其中一台离线,仍可通过另一台使用 uc。

运行服务

$ uc run -p app.example.com:8000/https image/my-app

输出:

my-app endpoints: https://app.example.com -> :8000 ; https://my-app-1b3b.xuw3xd.cluster.uncloud.run -> :8000

背后发生的事:

  1. CLI 挑选一台机器。
  2. uncloudd 用 grpc-proxy 把请求转发到目标机器。
  3. 目标机器上的 uncloudd 在 bridge 网络中启动 Docker 容器,并把信息写入分布式状态。
  4. 容器获得集群内唯一的 IP,范围是 10.210.X.2-254。
  5. 每台机器上都以 global 模式运行 Caddy 反向代理,它监听集群状态并更新配置来路由流量。

交互式教程

iximiuz Labs 上提供了三份动手教程:搭建新集群、部署 Django Web 应用、以及 playground。

项目状态

项目仍在活跃开发中,处于 pre-1.0 阶段,会有偶发的破坏性变更。核心的 build/push/deploy 流程已经稳定;运行时依赖 Docker、Caddy、WireGuard 和 Corrosion。

取舍

单机或几台机器跑几个 Web 服务、希望用 Docker Compose 语法、又不想维护控制面和 etcd 的场景,Uncloud 的复杂度明显更低:没有 quorum,一台挂了另一台仍能接受 uc 操作,入口和证书由 Caddy 自动处理。

但如果需要多租户、细粒度的 RBAC、丰富的调度约束、HPA 这类自动扩缩容、或者一整套成熟的 Operator 生态,K8s 仍然是更合适的选择——Uncloud 走的是命令式路线,不做状态协调,也就不会替你做声明式的收敛。

灵感来源

Kamal(命令式部署)、Fly.io、Tailscale、Talos Linux/KubeSpan、Docker Swarm Classic、Rancher 1.x。特别感谢 Fly.io 的 Corrosion。

链接

复制全文 生成海报 Docker 容器编排 WireGuard 运维部署

推荐文章

程序员茄子在线接单