From 773d3102144c8b00dac3262fc3c7403408e5c868 Mon Sep 17 00:00:00 2001 From: wangbo Date: Sat, 1 Aug 2026 12:33:19 +0800 Subject: [PATCH] =?UTF-8?q?fix(cluster):=20=E5=BC=BA=E5=88=B6=E5=85=B3?= =?UTF-8?q?=E9=94=AE=E5=89=AF=E6=9C=AC=E8=B7=A8=E8=8A=82=E7=82=B9=E5=88=86?= =?UTF-8?q?=E6=95=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 避免同站点 Worker 与容量控制器在滚动发布时集中到同一节点,并让 Kubernetes 运行态清单变更进入可追溯的 API release。\n\n验证:bash -n、ShellCheck、manual-release-test、生产集群 server-side dry-run。 --- deploy/kubernetes/production/application.yaml | 23 +++++++++++++++++++ scripts/release-components.mjs | 1 + tests/release/manual-release-test.sh | 11 ++++++++- 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/deploy/kubernetes/production/application.yaml b/deploy/kubernetes/production/application.yaml index 04b8bb2..49a1261 100644 --- a/deploy/kubernetes/production/application.yaml +++ b/deploy/kubernetes/production/application.yaml @@ -174,6 +174,13 @@ spec: spec: serviceAccountName: easyai-capacity-controller terminationGracePeriodSeconds: 30 + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: easyai.io/site + labelSelector: + matchLabels: + app.kubernetes.io/name: easyai-capacity-controller nodeSelector: easyai.io/workload: "true" topologySpreadConstraints: @@ -447,6 +454,14 @@ spec: spec: serviceAccountName: easyai-ai-gateway terminationGracePeriodSeconds: 90 + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: kubernetes.io/hostname + labelSelector: + matchLabels: + app.kubernetes.io/name: easyai-worker + easyai.io/site: ningbo topologySpreadConstraints: - maxSkew: 1 topologyKey: kubernetes.io/hostname @@ -612,6 +627,14 @@ spec: spec: serviceAccountName: easyai-ai-gateway terminationGracePeriodSeconds: 90 + affinity: + podAntiAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + - topologyKey: kubernetes.io/hostname + labelSelector: + matchLabels: + app.kubernetes.io/name: easyai-worker + easyai.io/site: hongkong topologySpreadConstraints: - maxSkew: 1 topologyKey: kubernetes.io/hostname diff --git a/scripts/release-components.mjs b/scripts/release-components.mjs index 6c80cf5..c79cdbb 100755 --- a/scripts/release-components.mjs +++ b/scripts/release-components.mjs @@ -49,6 +49,7 @@ const changed = git([ const apiPatterns = [ /^apps\/api\//, /^go\.work(?:\.sum)?$/, + /^deploy\/kubernetes\//, ] const webPatterns = [ /^apps\/web\//, diff --git a/tests/release/manual-release-test.sh b/tests/release/manual-release-test.sh index 4b80b67..eeb3e85 100755 --- a/tests/release/manual-release-test.sh +++ b/tests/release/manual-release-test.sh @@ -8,7 +8,8 @@ trap 'rm -rf "$tmp"' EXIT new_repo() { local name=$1 local repo=$tmp/$name - mkdir -p "$repo/apps/api/migrations" "$repo/apps/web/src" "$repo/packages/contracts/src" "$repo/docs" + mkdir -p "$repo/apps/api/migrations" "$repo/apps/web/src" "$repo/packages/contracts/src" \ + "$repo/deploy/kubernetes/production" "$repo/docs" git -C "$repo" init -q git -C "$repo" config user.name 'Manual Release Test' git -C "$repo" config user.email 'manual-release-test@example.invalid' @@ -16,6 +17,7 @@ new_repo() { printf 'SELECT 1;\n' >"$repo/apps/api/migrations/0001_init.sql" printf 'web\n' >"$repo/apps/web/src/app.ts" printf 'contracts\n' >"$repo/packages/contracts/src/index.ts" + printf 'kind: Deployment\n' >"$repo/deploy/kubernetes/production/application.yaml" # shellcheck disable=SC2016 printf 'ARG API_RUNTIME_IMAGE=scratch\nARG WEB_RUNTIME_IMAGE=scratch\nFROM ${API_RUNTIME_IMAGE} AS api\nCOPY apps/api /app\nFROM ${WEB_RUNTIME_IMAGE} AS web\nCOPY apps/web /web\n' >"$repo/Dockerfile" printf 'docs\n' >"$repo/docs/readme.md" @@ -80,6 +82,13 @@ git -C "$repo" add -A && git -C "$repo" commit -qm docs result=$(classify "$repo" "$base") node -e 'const value=JSON.parse(process.argv[1]); if(value.components!=="none")process.exit(1)' "$result" +repo=$(new_repo kubernetes-runtime) +base=$(git -C "$repo" rev-parse HEAD) +printf 'kind: Deployment\n# scheduling changed\n' >"$repo/deploy/kubernetes/production/application.yaml" +git -C "$repo" add -A && git -C "$repo" commit -qm kubernetes-runtime +result=$(classify "$repo" "$base") +node -e 'const value=JSON.parse(process.argv[1]); if(value.components!=="api"||value.migrationsChanged)process.exit(1)' "$result" + bare=$tmp/origin.git git init -q --bare "$bare" repo=$(new_repo preflight)