Files
easyai-ai-gateway/scripts/cluster/common.sh
T
wangbo ed3b970178 refactor(cluster): 通用化第四个 Worker 节点接入
将原宁波专用接入脚本改为由环境变量控制节点名称、站点和 WireGuard 端口,支持香港双物理节点 Worker 池。增加候选节点启用开关和服务商网络许可门禁,未明确批准时禁止任何 WireGuard 或 K3s 写操作。同步调整生产验收、巡检、拓扑校验和运行手册。\n\n验证:\n- scripts/cluster 全部 Shell 脚本 bash -n\n- scripts/cluster 全部 ShellCheck\n- git diff --check\n- 本地凭据值扫描\n- 当前三节点 WireGuard/K3s/PostgreSQL 只读基线检查
2026-08-01 11:23:19 +08:00

138 lines
4.5 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
cluster_root=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)
cluster_env_file=${AI_GATEWAY_CLUSTER_ENV_FILE:-"$cluster_root/.env.local"}
cluster_ssh_key=${AI_GATEWAY_CLUSTER_SSH_KEY:-"$HOME/.ssh/id_ed25519_easyai_gateway_cluster"}
load_cluster_env() {
[[ -f $cluster_env_file && ! -L $cluster_env_file ]] || {
echo "missing local cluster environment file: $cluster_env_file" >&2
return 1
}
set -a
# shellcheck source=/dev/null
source "$cluster_env_file"
set +a
cluster_ssh_key=${AI_GATEWAY_CLUSTER_SSH_KEY:-$cluster_ssh_key}
: "${AI_GATEWAY_DEPLOY_HOST:?}"
: "${AI_GATEWAY_DEPLOY_HOST_2:?}"
: "${AI_GATEWAY_DEPLOY_HOST_3:?}"
: "${ALI_KEY:?}"
: "${ALI_SECRET:?}"
: "${ALI_REGION:?}"
: "${ALI_BUCKET:?}"
CLUSTER_NINGBO_HOST=${AI_GATEWAY_NINGBO_HOST:-$AI_GATEWAY_DEPLOY_HOST}
CLUSTER_LOS_ANGELES_HOST=${AI_GATEWAY_LOS_ANGELES_HOST:-$AI_GATEWAY_DEPLOY_HOST_2}
CLUSTER_HONGKONG_HOST=${AI_GATEWAY_HONGKONG_HOST:-$AI_GATEWAY_DEPLOY_HOST_3}
CLUSTER_WORKER_NODE_4_HOST=${AI_GATEWAY_WORKER_NODE_4_HOST:-}
CLUSTER_WORKER_NODE_4_NAME=${AI_GATEWAY_WORKER_NODE_4_NAME:-}
CLUSTER_WORKER_NODE_4_SITE=${AI_GATEWAY_WORKER_NODE_4_SITE:-}
CLUSTER_WORKER_NODE_4_WIREGUARD_PORT=${AI_GATEWAY_WORKER_NODE_4_WIREGUARD_PORT:-51820}
CLUSTER_WORKER_NODE_4_NETWORK_APPROVED=${AI_GATEWAY_WORKER_NODE_4_NETWORK_APPROVED:-false}
CLUSTER_WORKER_NODE_4_ENABLED=${AI_GATEWAY_WORKER_NODE_4_ENABLED:-false}
export CLUSTER_NINGBO_HOST CLUSTER_LOS_ANGELES_HOST CLUSTER_HONGKONG_HOST
export CLUSTER_WORKER_NODE_4_HOST CLUSTER_WORKER_NODE_4_NAME CLUSTER_WORKER_NODE_4_SITE
export CLUSTER_WORKER_NODE_4_WIREGUARD_PORT CLUSTER_WORKER_NODE_4_NETWORK_APPROVED
export CLUSTER_WORKER_NODE_4_ENABLED
for host in "$CLUSTER_NINGBO_HOST" "$CLUSTER_HONGKONG_HOST" "$CLUSTER_LOS_ANGELES_HOST"; do
[[ $host =~ ^root@[A-Za-z0-9.-]+$ ]] || {
echo "cluster hosts must use root@host syntax" >&2
return 1
}
done
if [[ -n $CLUSTER_WORKER_NODE_4_HOST ]]; then
[[ $CLUSTER_WORKER_NODE_4_HOST =~ ^root@[A-Za-z0-9.-]+$ ]] || {
echo "dedicated Worker node 4 host must use root@host syntax" >&2
return 1
}
[[ ${#CLUSTER_WORKER_NODE_4_NAME} -le 63 &&
$CLUSTER_WORKER_NODE_4_NAME =~ ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$ ]] || {
echo "dedicated Worker node 4 name must be a Kubernetes DNS label" >&2
return 1
}
[[ $CLUSTER_WORKER_NODE_4_SITE == ningbo || $CLUSTER_WORKER_NODE_4_SITE == hongkong ]] || {
echo "dedicated Worker node 4 site must be ningbo or hongkong" >&2
return 1
}
[[ $CLUSTER_WORKER_NODE_4_WIREGUARD_PORT =~ ^[0-9]+$ &&
$CLUSTER_WORKER_NODE_4_WIREGUARD_PORT -ge 1 &&
$CLUSTER_WORKER_NODE_4_WIREGUARD_PORT -le 65535 ]] || {
echo "dedicated Worker node 4 WireGuard port is invalid" >&2
return 1
}
[[ $CLUSTER_WORKER_NODE_4_NETWORK_APPROVED == true ||
$CLUSTER_WORKER_NODE_4_NETWORK_APPROVED == false ]] || {
echo "dedicated Worker node 4 network approval must be true or false" >&2
return 1
}
[[ $CLUSTER_WORKER_NODE_4_ENABLED == true || $CLUSTER_WORKER_NODE_4_ENABLED == false ]] || {
echo "dedicated Worker node 4 enabled flag must be true or false" >&2
return 1
}
elif [[ -n $CLUSTER_WORKER_NODE_4_NAME || -n $CLUSTER_WORKER_NODE_4_SITE ]]; then
echo "dedicated Worker node 4 metadata requires AI_GATEWAY_WORKER_NODE_4_HOST" >&2
return 1
fi
[[ $ALI_REGION =~ ^[a-z0-9-]+$ && $ALI_BUCKET =~ ^[A-Za-z0-9.-]+$ ]] || {
echo 'invalid OSS region or bucket' >&2
return 1
}
[[ -f $cluster_ssh_key && ! -L $cluster_ssh_key ]] || {
echo "missing cluster SSH key: $cluster_ssh_key" >&2
return 1
}
}
cluster_ssh() {
local host=$1
shift
ssh \
-i "$cluster_ssh_key" \
-o BatchMode=yes \
-o ConnectTimeout=10 \
-o ServerAliveInterval=15 \
-o ServerAliveCountMax=3 \
"$host" "$@"
}
cluster_scp() {
scp \
-i "$cluster_ssh_key" \
-o BatchMode=yes \
-o ConnectTimeout=10 \
"$@"
}
require_commands() {
local command
for command in "$@"; do
command -v "$command" >/dev/null 2>&1 || {
echo "$command is required" >&2
return 1
}
done
}
assert_private_file() {
local path=$1
local mode
[[ -f $path && ! -L $path ]] || {
echo "missing private file: $path" >&2
return 1
}
if [[ $(uname -s) == Darwin ]]; then
mode=$(stat -f '%Lp' "$path")
else
mode=$(stat -c '%a' "$path")
fi
[[ $mode == 600 ]] || {
echo "private file must have mode 0600: $path" >&2
return 1
}
}