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.
背后发生的事:
- CLI 通过 SSH 登录机器,安装 Docker 和由 systemd 管理的
unclouddmachine daemon。 - 生成一对唯一的 WireGuard 密钥,为该机器及其容器分配专属子网
10.210.0.0/24,配置uncloudd。之后所有通信都通过 SSH 之上的 gRPC API 与uncloudd交互。 - 配置并启动 corrosion——一个基于 CRDT 的分布式 SQLite 数据库,把它作为 Docker 容器、由
uncloudd管理,用来在多机之间共享集群状态。 - 创建一个连接到 WireGuard 接口的 Docker bridge 网络。
- 这台机器成为集群的接入点,记录在
~/.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。
背后发生的事:
- 第二台机器按与第一台相同的方式初始化;如果 SSH 用户不是 root,需要 sudo 权限。
- 分配子网
10.210.1.0/24。 - 在集群状态中注册,并交换 WireGuard 密钥。
- 两台机器建立 WireGuard 隧道,bridge 网络上的容器可以跨机通信。
- 在第二台机器上启动
uncloud-corrosion容器以同步状态。 - 该机器成为备选接入点。
- 若其中一台离线,仍可通过另一台使用
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
背后发生的事:
- CLI 挑选一台机器。
uncloudd用 grpc-proxy 把请求转发到目标机器。- 目标机器上的
uncloudd在 bridge 网络中启动 Docker 容器,并把信息写入分布式状态。 - 容器获得集群内唯一的 IP,范围是
10.210.X.2-254。 - 每台机器上都以 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。
链接
- Uncloud:github.com/psviderski/uncloud
- 文档:uncloud.run/docs
- Unregistry:github.com/psviderski/unregistry
- Corrosion:github.com/superfly/corrosion
- Recipes:github.com/psviderski/uncloud-recipes