fix: 在 proxy 前恢复 worker WireGuard

This commit is contained in:
pikastech
2026-07-20 04:58:21 +02:00
parent b666f9a884
commit 7302a08fd1
3 changed files with 50 additions and 1 deletions
+1
View File
@@ -91,6 +91,7 @@ description: UniDesk YAML-first 运维正规化技能。用户提到 ymal-first/
- 多主机 k3s 集群:
- 跨主机拓扑、WireGuard、agent token、worker host proxy 引用、集群内 artifact registry 映射、ServiceLB 节点和调度 smoke 归独立集群 owning YAML。
- worker host proxy 归 `config/platform-infra/host-proxy.yaml`;集群 apply 必须先确认 proxy client 连接声明的 `vpn-server` 并通过外网 probe,再启动 agent。
- worker proxy 前必须先收敛 WireGuard;配置一致时不重启,只有 unit 未运行或握手过期且隧道探针失败时才允许恢复 worker 接口。
- containerd 通过 host proxy 直接访问公共 registry,禁止为公共依赖新增 registry mirror;集群内 artifact registry 映射不属于公共镜像代理。
- 既有 control-plane 的 k3s renderer 通过 `clusterConfigRef` 消费集群网络参数,不得由集群 CLI 再写第二个 systemd drop-in。
- 无固定公网地址 worker 使用宿主内网 SSH 作为部署控制通道并主动连接 WireGuard endpoint,不使用 FRP 代替三层集群网络。
+1
View File
@@ -22,6 +22,7 @@
- `platform-infra k3s-cluster plan|apply|status|smoke --target <id>` 是部署和验收入口。
- 无固定公网地址的 worker 由宿主内网 SSH 控制,主动连接 control-plane WireGuard endpointworker provider route 只作为部署后补充验收入口。
- 集群 apply 先经宿主内网 SSH 分发零依赖 proxy client,确认它连接声明的 `vpn-server` 且外网 probe 成功,再启动或恢复 `k3s-agent`
- 集群 apply 在 proxy 前先收敛 worker WireGuard;内容一致时不强写,只有 unit 未运行或握手过期且隧道探针失败时才恢复 worker 接口。
- 大型 proxy 工件由 Windows 宿主按 YAML `upstreamUrl` 获取并校验 SHA-256Provider/trans 只承载控制命令,不作为大二进制数据面。
- WireGuard 已建立的 worker 应通过隧道地址连接 control-plane 上的 `vpn-server`,不要求为 proxy 单独开放公网端口。
- proxy client 协议实现版本由 host-proxy YAML 声明,并与所连接的 `vpn-server` 协议实现版本保持一致。
+48 -1
View File
@@ -103,11 +103,14 @@ function secretInit(target: K3sClusterTarget, confirm: boolean): Record<string,
}
function apply(target: K3sClusterTarget): Record<string, unknown> {
const secret = readSecrets(target);
const workerNetwork = runWorker(target, workerWireguardApplyScript(target, secret), false, 120_000);
requireSuccess(workerNetwork, "worker-wireguard-apply");
const hostProxy = prepareHostProxyGuestBundle(target.worker.hostProxyTargetId);
const workerHostProxy = runWorkerHostProxy(target, hostProxy, 240_000);
requireSuccess(workerHostProxy, "worker-host-proxy-apply");
const secret = readSecrets(target);
const controlWireguard = runControlPlane(target, controlPlaneApplyScript(target, secret), 180_000);
requireSuccess(controlWireguard, "control-plane-wireguard-apply");
@@ -133,6 +136,7 @@ function apply(target: K3sClusterTarget): Record<string, unknown> {
mutation: true,
targetId: target.id,
stages: {
workerWireguard: compact(workerNetwork),
workerHostProxy: {
...compact(workerHostProxy),
configRef: hostProxy.configRef,
@@ -223,6 +227,49 @@ function smoke(target: K3sClusterTarget, confirm: boolean): Record<string, unkno
};
}
function workerWireguardApplyScript(target: K3sClusterTarget, secret: SecretMaterial): string {
const wg = target.wireguard;
return `set -eu
if ! command -v wg >/dev/null 2>&1; then
DEBIAN_FRONTEND=noninteractive apt-get update -qq
DEBIAN_FRONTEND=noninteractive apt-get install -y -qq ${shellToken(wg.packageName)}
fi
install -d -m 700 /etc/wireguard
candidate="$(mktemp)"
trap 'rm -f "$candidate"' EXIT
cat >"$candidate" <<'EOF'
[Interface]
Address = ${wg.workerAddress}
PrivateKey = ${secret.workerPrivate}
MTU = ${wg.mtu}
[Peer]
PublicKey = ${secret.controlPublic}
AllowedIPs = ${address(wg.controlPlaneAddress)}/32
Endpoint = ${wg.endpoint}
PersistentKeepalive = ${wg.persistentKeepaliveSeconds}
EOF
changed=false
if ! cmp -s "$candidate" /etc/wireguard/${wg.interfaceName}.conf 2>/dev/null; then
install -m 0600 "$candidate" /etc/wireguard/${wg.interfaceName}.conf
changed=true
fi
systemctl enable wg-quick@${wg.interfaceName} >/dev/null 2>&1 || true
if [ "$changed" = true ]; then
systemctl restart wg-quick@${wg.interfaceName}
elif ! systemctl is-active --quiet wg-quick@${wg.interfaceName}; then
systemctl start wg-quick@${wg.interfaceName}
elif ! ping -c 1 -W 3 ${address(wg.controlPlaneAddress)} >/dev/null 2>&1; then
handshake="$(wg show ${wg.interfaceName} latest-handshakes 2>/dev/null | awk '{print $2}' | head -n1)"
now="$(date +%s)"
if [ -z "$handshake" ] || [ $((now - handshake)) -ge 180 ]; then
systemctl restart wg-quick@${wg.interfaceName}
fi
fi
ping -c 3 -W 5 ${address(wg.controlPlaneAddress)} >/dev/null
`;
}
function controlPlaneApplyScript(target: K3sClusterTarget, secret: SecretMaterial): string {
const wg = target.wireguard;
return `set -eu