diff --git a/README.md b/README.md index 3b1bb97..7897819 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ export NAMESPACE=prod 改 JSON → push `master` / `test` → workflow 按分支写入对应 Consul 并 `rollout restart`。 -手动: +手动(在 runner 机上;跨集群会自动 port-forward): ```bash # prod diff --git a/scripts/export-from-consul.sh b/scripts/export-from-consul.sh index d74d871..9430fa4 100644 --- a/scripts/export-from-consul.sh +++ b/scripts/export-from-consul.sh @@ -35,10 +35,34 @@ json_ok_str() { jq empty <<<"$raw" fi } +# Consul:跨集群时 ClusterIP 不可达 → port-forward +CONSUL_PF_PID="" +cleanup_pf() { + if [[ -n "${CONSUL_PF_PID:-}" ]]; then + kill "$CONSUL_PF_PID" 2>/dev/null || true + wait "$CONSUL_PF_PID" 2>/dev/null || true + CONSUL_PF_PID="" + fi +} +trap cleanup_pf EXIT + if [[ -z "${CONSUL_HTTP_ADDR:-}" ]]; then - CIP="$(kubectl -n "$NS" get svc consul -o jsonpath='{.spec.clusterIP}')" - CONSUL_HTTP_ADDR="http://${CIP}:8500" + LOCAL_PORT=18510 + echo "==> port-forward svc/consul → 127.0.0.1:${LOCAL_PORT} (ns=${NS})" + kubectl -n "$NS" port-forward svc/consul "${LOCAL_PORT}:8500" >/tmp/consul-pf-export-${NS}.log 2>&1 & + CONSUL_PF_PID=$! + ok=0 + for _ in $(seq 1 40); do + if curl -sf --connect-timeout 1 "http://127.0.0.1:${LOCAL_PORT}/v1/status/leader" >/dev/null 2>&1; then + ok=1 + break + fi + sleep 0.5 + done + [[ "$ok" == "1" ]] || { echo "FAIL: Consul port-forward 未就绪"; cat /tmp/consul-pf-export-${NS}.log 2>/dev/null || true; exit 1; } + CONSUL_HTTP_ADDR="http://127.0.0.1:${LOCAL_PORT}" fi +echo "==> Consul ${CONSUL_HTTP_ADDR}" if [[ -z "${CONSUL_HTTP_TOKEN:-}" ]]; then raw="$(kubectl -n "$NS" get secret consul-acl -o jsonpath='{.data.CONSUL_HTTP_TOKEN}' 2>/dev/null || true)" diff --git a/scripts/sync-to-consul.sh b/scripts/sync-to-consul.sh index 841f27b..b5d39eb 100644 --- a/scripts/sync-to-consul.sh +++ b/scripts/sync-to-consul.sh @@ -147,9 +147,54 @@ load_secret JWT_SECRET_KEY prod-credentials JWT_SECRET_KEY : "${ELASTIC_PASSWORD:?缺少 ELASTIC_PASSWORD}" : "${JWT_SECRET_KEY:?缺少 JWT_SECRET_KEY(请创建 secret/jwt-secret 或写入 prod-credentials)}" +# Consul:runner 可能在另一集群节点上,ClusterIP 不可达 → 一律 port-forward 到本机 +CONSUL_PF_PID="" +cleanup() { + if [[ -n "${CONSUL_PF_PID:-}" ]]; then + kill "$CONSUL_PF_PID" 2>/dev/null || true + wait "$CONSUL_PF_PID" 2>/dev/null || true + CONSUL_PF_PID="" + fi + [[ -n "${TMP:-}" && -d "${TMP:-}" ]] && rm -rf "$TMP" +} +trap cleanup EXIT + if [[ -z "$CONSUL_HTTP_ADDR" ]]; then - CIP="$(kubectl -n "$NS" get svc consul -o jsonpath='{.spec.clusterIP}')" - CONSUL_HTTP_ADDR="http://${CIP}:8500" + if ! kubectl -n "$NS" get svc consul >/dev/null 2>&1; then + echo "FAIL: 无 svc/${NS}/consul(KUBECONFIG=${KUBECONFIG})" + exit 1 + fi + # 避开常用端口;失败则换一个 + LOCAL_PORT="" + for p in 18500 18501 18502 18503 18504; do + if ! ss -ltn 2>/dev/null | grep -q ":${p} " && ! netstat -ltn 2>/dev/null | grep -q ":${p} "; then + LOCAL_PORT=$p + break + fi + done + LOCAL_PORT="${LOCAL_PORT:-18500}" + echo "==> port-forward svc/consul → 127.0.0.1:${LOCAL_PORT} (ns=${NS})" + kubectl -n "$NS" port-forward svc/consul "${LOCAL_PORT}:8500" >/tmp/consul-pf-${NS}.log 2>&1 & + CONSUL_PF_PID=$! + ok=0 + for _ in $(seq 1 40); do + if ! kill -0 "$CONSUL_PF_PID" 2>/dev/null; then + echo "FAIL: port-forward 已退出,见 /tmp/consul-pf-${NS}.log" + cat /tmp/consul-pf-${NS}.log 2>/dev/null || true + exit 1 + fi + if curl -sf --connect-timeout 1 "http://127.0.0.1:${LOCAL_PORT}/v1/status/leader" >/dev/null 2>&1; then + ok=1 + break + fi + sleep 0.5 + done + if [[ "$ok" != "1" ]]; then + echo "FAIL: Consul port-forward 未就绪,见 /tmp/consul-pf-${NS}.log" + cat /tmp/consul-pf-${NS}.log 2>/dev/null || true + exit 1 + fi + CONSUL_HTTP_ADDR="http://127.0.0.1:${LOCAL_PORT}" fi echo "==> Consul ${CONSUL_HTTP_ADDR}" @@ -179,7 +224,6 @@ fi [[ ${#TARGETS[@]} -gt 0 ]] || { echo "FAIL: 无同步目标"; exit 1; } TMP="$(mktemp -d)" -trap 'rm -rf "$TMP"' EXIT put_kv() { local key="$1" file="$2"