fix: 在 proxy 前恢复 worker WireGuard
This commit is contained in:
@@ -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 代替三层集群网络。
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
- `platform-infra k3s-cluster plan|apply|status|smoke --target <id>` 是部署和验收入口。
|
||||
- 无固定公网地址的 worker 由宿主内网 SSH 控制,主动连接 control-plane WireGuard endpoint;worker provider route 只作为部署后补充验收入口。
|
||||
- 集群 apply 先经宿主内网 SSH 分发零依赖 proxy client,确认它连接声明的 `vpn-server` 且外网 probe 成功,再启动或恢复 `k3s-agent`。
|
||||
- 集群 apply 在 proxy 前先收敛 worker WireGuard;内容一致时不强写,只有 unit 未运行或握手过期且隧道探针失败时才恢复 worker 接口。
|
||||
- 大型 proxy 工件由 Windows 宿主按 YAML `upstreamUrl` 获取并校验 SHA-256,Provider/trans 只承载控制命令,不作为大二进制数据面。
|
||||
- WireGuard 已建立的 worker 应通过隧道地址连接 control-plane 上的 `vpn-server`,不要求为 proxy 单独开放公网端口。
|
||||
- proxy client 协议实现版本由 host-proxy YAML 声明,并与所连接的 `vpn-server` 协议实现版本保持一致。
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user