Repository navigation
Conversation
The port PR for the standard MCS implementation is now open as ai-dynamo/dynamo#17615. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Eric Stroczynski <estroczynski@nvidia.com>
e00f257 to
0fd4c96
Compare
❌ Dynamo PR CI failed — run 41121078903 (attempt 1) on
|
| Framework | Build |
|---|---|
| vLLM | ❌ 1 |
| SGLang | ❌ 1 |
| Other | Jobs |
|---|---|
| dynamo-runtime | ❌ 1 |
| frontend | ❌ 1 |
| Global Discovery MCS | ❌ 1 |
| Operator | ❌ 1 |
| planner | ❌ 1 |
| Power Agent | ❌ 1 |
| triton-runtime | ❌ 1 |
Failure details
All 9 failed jobs are image builds that fail at the push step with the same infrastructure error: the CI ECR repository ai-dynamo/dynamo has hit its 100,000-image limit, so every push is denied. No code or test failure appears in the logs; rerunning failed jobs should be enough once registry space is freed (a rerun before cleanup will likely fail the same way).
❌ Power Agent: ECR push denied: repository image limit (100000) reached
Job: Power Agent · Failed step: Build and push power agent · Logs: gh run view --job 124287457639 -R ai-dynamo/dynamo --log-failed
ERROR: failed to build: failed to solve: failed to push ***.dkr.ecr.us-west-2.amazonaws.com/ai-dynamo/dynamo: denied: The repository with name 'ai-dynamo/dynamo' in registry with id '***' already has the maximum allowed number of images which is '100000'
##[error]Process completed with exit code 1.
The image build completed but pushing to ECR was denied because the repository is at its maximum image count (infrastructure, not caused by the PR). Rerun failed jobs after the registry is cleaned up.
❌ Global Discovery MCS: ECR push denied: repository image limit (100000) reached
Job: Global Discovery MCS · Failed step: Build and push the MCS registry image · Logs: gh run view --job 124287457672 -R ai-dynamo/dynamo --log-failed
ERROR: failed to build: failed to solve: failed to push ***.dkr.ecr.us-west-2.amazonaws.com/ai-dynamo/dynamo: denied: The repository with name 'ai-dynamo/dynamo' in registry with id '***' already has the maximum allowed number of images which is '100000'
##[error]Process completed with exit code 1.
The image build completed but pushing to ECR was denied because the repository is at its maximum image count (infrastructure, not caused by the PR). Rerun failed jobs after the registry is cleaned up.
❌ Operator: ECR push denied: repository image limit (100000) reached
Job: Operator · Failed step: Build and push operator · Logs: gh run view --job 124287457745 -R ai-dynamo/dynamo --log-failed
ERROR: failed to build: failed to solve: failed to push ***.dkr.ecr.us-west-2.amazonaws.com/ai-dynamo/dynamo: denied: The repository with name 'ai-dynamo/dynamo' in registry with id '***' already has the maximum allowed number of images which is '100000'
##[error]Process completed with exit code 1.
The image build completed but pushing to ECR was denied because the repository is at its maximum image count (infrastructure, not caused by the PR). Rerun failed jobs after the registry is cleaned up.
❌ vllm-runtime / Build multi-arch cuda13.0: ECR push denied: repository image limit (100000) reached
Job: vllm-runtime / Build multi-arch cuda13.0 · Failed step: Build and Push Image · Logs: gh run view --job 124287457995 -R ai-dynamo/dynamo --log-failed
ERROR: failed to build: failed to solve: failed to push ***.dkr.ecr.us-west-2.amazonaws.com/ai-dynamo/dynamo: denied: The repository with name 'ai-dynamo/dynamo' in registry with id '***' already has the maximum allowed number of images which is '100000'
##[error]Process completed with exit code 1.
The image build completed but pushing to ECR was denied because the repository is at its maximum image count (infrastructure, not caused by the PR). Rerun failed jobs after the registry is cleaned up.
❌ sglang-runtime / Build multi-arch cuda13.0: ECR push denied: repository image limit (100000) reached
Job: sglang-runtime / Build multi-arch cuda13.0 · Failed step: Build and Push Image · Logs: gh run view --job 124287458149 -R ai-dynamo/dynamo --log-failed
ERROR: failed to build: failed to solve: failed to push ***.dkr.ecr.us-west-2.amazonaws.com/ai-dynamo/dynamo: denied: The repository with name 'ai-dynamo/dynamo' in registry with id '***' already has the maximum allowed number of images which is '100000'
##[error]Process completed with exit code 1.
The image build completed but pushing to ECR was denied because the repository is at its maximum image count (infrastructure, not caused by the PR). Rerun failed jobs after the registry is cleaned up.
❌ planner / Build multi-arch cpu: ECR push denied: repository image limit (100000) reached
Job: planner / Build multi-arch cpu · Failed step: Build and Push Image · Logs: gh run view --job 124287458163 -R ai-dynamo/dynamo --log-failed
ERROR: failed to build: failed to solve: failed to push ***.dkr.ecr.us-west-2.amazonaws.com/ai-dynamo/dynamo: denied: The repository with name 'ai-dynamo/dynamo' in registry with id '***' already has the maximum allowed number of images which is '100000'
##[error]Process completed with exit code 1.
The image build completed but pushing to ECR was denied because the repository is at its maximum image count (infrastructure, not caused by the PR). Rerun failed jobs after the registry is cleaned up.
❌ triton-runtime / Build multi-arch cpu: ECR push denied: repository image limit (100000) reached
Job: triton-runtime / Build multi-arch cpu · Failed step: Build and Push Image · Logs: gh run view --job 124287458166 -R ai-dynamo/dynamo --log-failed
ERROR: failed to build: failed to solve: failed to push ***.dkr.ecr.us-west-2.amazonaws.com/ai-dynamo/dynamo: denied: The repository with name 'ai-dynamo/dynamo' in registry with id '***' already has the maximum allowed number of images which is '100000'
##[error]Process completed with exit code 1.
The image build completed but pushing to ECR was denied because the repository is at its maximum image count (infrastructure, not caused by the PR). Rerun failed jobs after the registry is cleaned up.
❌ frontend / Build multi-arch cpu: ECR push denied: repository image limit (100000) reached
Job: frontend / Build multi-arch cpu · Failed step: Build and Push Image · Logs: gh run view --job 124287458320 -R ai-dynamo/dynamo --log-failed
denied: The repository with name 'ai-dynamo/dynamo' in registry with id '***' already has the maximum allowed number of images which is '100000'
ERROR: failed to build: failed commit on ref "index-sha256:8c0e6eeb...": unexpected status from PUT request to https://***.dkr.ecr.us-west-2.amazonaws.com/v2/ai-dynamo/dynamo/manifests/1a07d2f1be90d8fd87c5b9ec0e99cf3253f7f730-dynamo-frontend: 403 Forbidden
##[error]Process completed with exit code 1.
Layers built, but the manifest PUT to ECR returned 403 because the repository is at its maximum image count (infrastructure, not caused by the PR). Rerun failed jobs after the registry is cleaned up.
❌ dynamo-runtime / image / Build multi-arch cuda13.0: ECR push denied: repository image limit (100000) reached
Job: dynamo-runtime / image / Build multi-arch cuda13.0 · Failed step: Build and Push Image · Logs: gh run view --job 124287458428 -R ai-dynamo/dynamo --log-failed
ERROR: failed to build: failed to solve: failed to push ***.dkr.ecr.us-west-2.amazonaws.com/ai-dynamo/dynamo: denied: The repository with name 'ai-dynamo/dynamo' in registry with id '***' already has the maximum allowed number of images which is '100000'
##[error]Process completed with exit code 1.
The image build completed but pushing to ECR was denied because the repository is at its maximum image count (infrastructure, not caused by the PR). Rerun failed jobs after the registry is cleaned up.
For agents
{"pr": 17615, "run_id": 41121078903, "run_attempt": 1, "head_sha": "1a07d2f1be90d8fd87c5b9ec0e99cf3253f7f730", "failures": [{"job": "Power Agent", "job_id": 124287457639, "failed_step": "Build and push power agent", "signature": "ECR push denied: repository image limit (100000) reached", "tests": [], "log_cmd": "gh run view --job 124287457639 -R ai-dynamo/dynamo --log-failed"}, {"job": "Global Discovery MCS", "job_id": 124287457672, "failed_step": "Build and push the MCS registry image", "signature": "ECR push denied: repository image limit (100000) reached", "tests": [], "log_cmd": "gh run view --job 124287457672 -R ai-dynamo/dynamo --log-failed"}, {"job": "Operator", "job_id": 124287457745, "failed_step": "Build and push operator", "signature": "ECR push denied: repository image limit (100000) reached", "tests": [], "log_cmd": "gh run view --job 124287457745 -R ai-dynamo/dynamo --log-failed"}, {"job": "vllm-runtime / Build multi-arch cuda13.0", "job_id": 124287457995, "failed_step": "Build and Push Image", "signature": "ECR push denied: repository image limit (100000) reached", "tests": [], "log_cmd": "gh run view --job 124287457995 -R ai-dynamo/dynamo --log-failed"}, {"job": "sglang-runtime / Build multi-arch cuda13.0", "job_id": 124287458149, "failed_step": "Build and Push Image", "signature": "ECR push denied: repository image limit (100000) reached", "tests": [], "log_cmd": "gh run view --job 124287458149 -R ai-dynamo/dynamo --log-failed"}, {"job": "planner / Build multi-arch cpu", "job_id": 124287458163, "failed_step": "Build and Push Image", "signature": "ECR push denied: repository image limit (100000) reached", "tests": [], "log_cmd": "gh run view --job 124287458163 -R ai-dynamo/dynamo --log-failed"}, {"job": "triton-runtime / Build multi-arch cpu", "job_id": 124287458166, "failed_step": "Build and Push Image", "signature": "ECR push denied: repository image limit (100000) reached", "tests": [], "log_cmd": "gh run view --job 124287458166 -R ai-dynamo/dynamo --log-failed"}, {"job": "frontend / Build multi-arch cpu", "job_id": 124287458320, "failed_step": "Build and Push Image", "signature": "ECR push denied: repository image limit (100000) reached", "tests": [], "log_cmd": "gh run view --job 124287458320 -R ai-dynamo/dynamo --log-failed"}, {"job": "dynamo-runtime / image / Build multi-arch cuda13.0", "job_id": 124287458428, "failed_step": "Build and Push Image", "signature": "ECR push denied: repository image limit (100000) reached", "tests": [], "log_cmd": "gh run view --job 124287458428 -R ai-dynamo/dynamo --log-failed"}]}Posted automatically by Devin for run 41121078903. Updated on every full-CI run of this PR.
…roller Add a standard implementation of the Kubernetes Multi-Cluster Services API (KEP-1645) for the Global Router as the Go module deploy/global-discovery-mcs, with its Helm chart, CI wiring, docs-site pages and a kind end-to-end test. It replaces Karmada under the Global Discovery Service's --pool-discovery mcs mode: the controller writes the EndpointSlice labels, region label and per-endpoint targetRef that the service's mcs backend reads, so no Rust change is needed. Module (ported from an internal codebase without its pool layer): - mcs-registry: stateless registry with memory and DynamoDB stores, cluster leases, ServiceImport merge with the KEP-1645 conflict rules, watches with revisions, gRPC, grpc-gateway REST and OpenAPI. - mcs-controller: cluster registration, ServiceExport reconciler, label-driven auto-export, importer writing ServiceImports, derived-<hash> Services and EndpointSlices. - mcs-admin: create-table, describe, delete-cluster. - api/proto/dynamo/mcs/v1 contract, pkg/client and pkg/fakeregistry. - Labels dynamo.nvidia.com/mcs-*, metrics dynamo_mcs_*, image global-discovery-mcs, Makefile, Dockerfile, golangci config, docs. Chart deploy/helm/charts/global-discovery-mcs: registry and controller toggles, CRDs kept on uninstall and skippable, ClusterRole from the generated role file, schema, helm-docs README, unittest suites. CI: global_discovery_mcs filter, pre-merge module and chart jobs, image builds for amd64 and arm64, code ownership under global-router. Docs site: user guide, component reference and design page. Test: deploy/global-discovery-mcs/test/e2e runs three kind clusters and the Global Discovery Service in --pool-discovery mcs against the imports. Closes #17601 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Eric Stroczynski <estroczynski@nvidia.com>
0fd4c96 to
1a07d2f
Compare
Slice 1 of 8 of #17615, the port of the Multi-Cluster Services layer of the Global Router. Go module, Makefile, Dockerfile, lint configuration, README and AGENTS.md of deploy/global-discovery-mcs, with the CI filter, pre-merge check and image build jobs and the CODEOWNERS area. Relates to #17601 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Eric Stroczynski <estroczynski@nvidia.com>
Slice 1 of 8 of #17615, the port of the Multi-Cluster Services layer of the Global Router. Go module, Makefile, Dockerfile, lint configuration, README and AGENTS.md of deploy/global-discovery-mcs, with the CI filter, pre-merge check and image build jobs and the CODEOWNERS area. Relates to #17601 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Eric Stroczynski <estroczynski@nvidia.com>
Slice 5 of 8 of #17615, the port of the Multi-Cluster Services layer of the Global Router. The per-cluster controller: registration and lease, ServiceExport reconciler, autoexport, importer, the embedded CRDs and generated RBAC, and docs/mcs-controller.md. Relates to #17601 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Eric Stroczynski <estroczynski@nvidia.com>
Slice 1 of 8 of #17615, the port of the Multi-Cluster Services layer of the Global Router. Go module, Makefile, Dockerfile, lint configuration, README and AGENTS.md of deploy/global-discovery-mcs, with the CI filter, pre-merge check and image build jobs and the CODEOWNERS area. Relates to #17601 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Eric Stroczynski <estroczynski@nvidia.com>
…ract Slice 2 of 8 of #17615, the port of the Multi-Cluster Services layer of the Global Router. The dynamo.mcs.v1 proto package with its generated Go, gRPC, grpc-gateway and OpenAPI code, the KEP-1645 label, finalizer and condition constants, and docs/api.md. Relates to #17601 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Eric Stroczynski <estroczynski@nvidia.com>
Slice 3 of 8 of #17615, the port of the Multi-Cluster Services layer of the Global Router. The registry view, merge rules, store interface with the memory and DynamoDB stores, request handlers, gRPC and REST server, the mcs-registry binary and the mcs-admin table tool, with the consistency, storage and IAM docs. Relates to #17601 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Eric Stroczynski <estroczynski@nvidia.com>
Slice 4 of 8 of #17615, the port of the Multi-Cluster Services layer of the Global Router. The public pkg/client used by mcs-controller to talk to the registry, and pkg/fakeregistry, the in-process registry for tests. Relates to #17601 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Eric Stroczynski <estroczynski@nvidia.com>
Slice 6 of 8 of #17615, the port of the Multi-Cluster Services layer of the Global Router. The chart that installs mcs-registry, mcs-controller and the CRDs, with helm-unittest cases and the pre-commit exclusion for its templates. Relates to #17601 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Eric Stroczynski <estroczynski@nvidia.com>
…outer Slice 7 of 8 of #17615, the port of the Multi-Cluster Services layer of the Global Router. Docs-site pages: the Multi-Cluster Services deployment guide, the global-discovery-mcs configuration reference and the registry design page. Relates to #17601 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Eric Stroczynski <estroczynski@nvidia.com>
…y-mcs Slice 8 of 8 of #17615, the port of the Multi-Cluster Services layer of the Global Router. Three-cluster kind test for the module: phase 1 registry, phase 2 controller exports and imports, phase 3 the Global Discovery Service reading the imports. Relates to #17601 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Eric Stroczynski <estroczynski@nvidia.com>
Slice 1 of 8 of #17615, the port of the Multi-Cluster Services layer of the Global Router. Go module, Makefile, Dockerfile, lint configuration, README and AGENTS.md of deploy/global-discovery-mcs, with the CI filter, pre-merge check and image build jobs and the CODEOWNERS area. Relates to #17601 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Eric Stroczynski <estroczynski@nvidia.com>
Overview
Adds a standard implementation of the Kubernetes Multi-Cluster Services API (KEP-1645) for the Global Router as a new Go module,
deploy/global-discovery-mcs, with its Helm chart, CI wiring and docs-site pages. It replaces Karmada under the Global Discovery Service's--pool-discovery mcsmode: the service already selects EndpointSlices bymulticluster.kubernetes.io/service-nameandmulticluster.kubernetes.io/source-clusterand reads each endpoint'stargetRefname, and the controller here writes exactly those, so no Rust change is needed. With #17604 the service also reads thetopology.kubernetes.io/regionlabel the controller stamps on imported slices.Pool discovery stays with the Global Discovery Service's HTTP contract; this module only moves Services and endpoints between clusters.
Three binaries ship in one image (
global-discovery-mcs):mcs-registry: stateless registry server. Keeps clusters (with leases), ServiceExports and endpoint sets in memory or one DynamoDB table (Global Table across regions), merges the exports of a Service from every cluster into one ServiceImport using the KEP-1645 conflict rules (oldest export wins), and serves thedynamo.mcs.v1API over gRPC (:9090) and REST through grpc-gateway (:8080), including watches with opaque revisions.mcs-controller: runs in every member cluster. Registers the cluster with a lease, exports Services labelleddynamo.nvidia.com/mcs-export: "true"(or with a ServiceExport) with their endpoints, and materialises ServiceImports,derived-<hash>Services and EndpointSlices with the KEP labels, the source cluster's region and per-endpointtargetRef.mcs-admin: creates the DynamoDB table, describes a store, deletes a cluster.Key Changes
deploy/global-discovery-mcs(github.com/ai-dynamo/dynamo/deploy/global-discovery-mcs, Go 1.27.3, k8s.io v0.36.3, controller-runtime v0.24.1, mcs-api v0.5.2, no replace directives).cmd/mcs-registry: registry server with memory and DynamoDB stores, ServiceImport merge with the KEP-1645 conflict rules, watches with revisions, leases evaluated at read time, gRPC plus grpc-gateway REST plus OpenAPI.cmd/mcs-controller: cluster registration and lease, ServiceExport reconciler, label-driven auto-export, importer writing ServiceImports,derived-<hash>Services and EndpointSlices.cmd/mcs-admin:create-table,describe,delete-cluster; takes the store flags andMCS_env fallbacks.api/proto/dynamo/mcs/v1contract (cluster,common,mcs,server) and generated Go, gateway and OpenAPI underapi/gen.pkg/client(failover Go client with watch loop and metrics) andpkg/fakeregistry(in-memory server for consumer tests).topology.kubernetes.io/regionof the source cluster and a per-endpointtargetRefnaming the exported pod, which is what the Global Discovery Service'smcsbackend reads.dynamo.nvidia.com/mcs-export,mcs-managed-by,mcs-clusterset; finalizerdynamo.nvidia.com/mcs-service-export; leader Lease and EndpointSlice managed-bymcs-controller.dynamo.nvidia.com; metricsdynamo_mcs_registry_*,dynamo_mcs_controller_*,dynamo_mcs_client_*. KEP-1645 and ClusterProperty keys unchanged.build lint test envtest test-integration manifests proto proto-check sync-crds tidy-check check docker-build), Dockerfile withlinter,tester,builderand distroless runtime stages (USER 65532, entrypoint/mcs-registry, imageglobal-discovery-mcs),.golangci.ymlfromdeploy/operatorplusgoheader.README.md,AGENTS.mdwithCLAUDE.md,docs/(api, mcs-controller, consistency, consistency-dynamodb, storage, iam),pkg/client/README.md. The module.gitignorere-includesinternal/server/, which the rootserver/pattern would otherwise drop.deploy/helm/charts/global-discovery-mcs:registry.enabledandcontroller.enabled, one image block, ClusterRole rendered from the generatedfiles/controller-role.yaml, leader-election Role, CRDs undercrds.installwithhelm.sh/resource-policy: keep(setcrds.install=falsewhere Karmada or another implementation already owns them),values.schema.json, helm-docs README, 57 helm-unittest cases. Resource names are fixed (mcs-registry,mcs-controller), so one release per namespace.kubernetes/kv-aware-routing/multi-cluster-services.md, referencereference/components/global-discovery-mcs-configuration.md, design pagedeveloper-guide/knowledge-base/modular-components/router/multi-cluster-services-registry.md, nav entries, one cross-link from the pool relay page.global_discovery_mcsin.github/filters.yamlandFILTERS.md; pre-merge jobs for the module (check-deploy-componentplusmake proto-check checkandmake test-integration) and the chart (helm lint, unittest);pr.yamlandpost-merge-ci.ymlimage builds viabuild-deploy-componentfor amd64 and arm64;check-deploy-componentandbuild-deploy-componentaccept the new component.global-routerin.github/codeowners/areas.yaml;CODEOWNERSregenerated.make e2e).Validation
From a fresh checkout, in
deploy/global-discovery-mcs:make lint: 0 issues.make test(unit plus envtest,-race, coverage gate 85 on./internal/...): 95.7 percent.make test-integrationagainstamazon/dynamodb-local: all pass, none skipped.make proto-checkandmake check(tidy, manifests, proto, CRD copies): no drift.docker buildx build --target linterand--target testerexit 0; the runtime image builds and--helpworks for all three binaries.make -C deploy/helm/charts/global-discovery-mcs lint testunder Helm 3.17.3 and 3.21: lint strict clean, 57 unittest cases pass; server-side dry run of every object against a kube-apiserver 1.30 with CRDs on and off; a real install, upgrade withcrds.install=falseand uninstall keeps the CRDs. The controller ran with the chart's rendered args as the chart's ServiceAccount (RBAC enforced), took the leader Lease, registered the cluster and exported a labelled Service withValid=True,Ready=True,Conflict=False.build_codeowners.py --strict7514/7514 owned,emit_codeowners.pyno diff,test-filters.js87/87,actionlintadds no finding beyond the existing runner-label warning.docs_lint.py0 errors,fern check0 errors,fern docs broken-links --strictpasses.Not run here: the GitHub workflow jobs themselves (CI on this branch needs a maintainer's
/ok to test <sha>) and the PowerShell copyright check (pwshunavailable; headers verified with a script).End-to-end (
make -C deploy/global-discovery-mcs e2e E2E_PHASES="1 2 3", three kind clusters with routed pod subnets, the registry in the hub, a controller per cluster, and the Global Discovery Service built fromcontainer/Dockerfile.global-discovery-servicerunning in the hub with--pool-discovery mcs): 99 passed, 0 failed, 1 known gap. Phase 1 (23): registration, label-driven export, imports with derived Services, EndpointSlices with KEP labels, region and targetRef pod names in every cluster, a pod in each importing cluster reaching the exporter through its derived ClusterIP. Phase 2 (57): endpoint updates, a v1alpha1 ServiceExport, conflicting exports (oldest wins,Conflict=Trueon the loser), lease expiry, export deletion. Phase 3 (19):GET /poolslists the pool from cluster a with its relay identity,GET /routerslists the hub's two router pods, scaling the relay to zero removes the pool, deleting the export removes it. The known gap: the service reports the pool region as the cluster id because the branch predates #17604, which adds the label read;E2E_STRICT=1turns the gap into a failure.Review slices
This PR is kept open as the complete, validated source of truth. For review it is split into eight independent PRs against the same base branch; each carries one part and links back here for the pieces it depends on. Merge conflicts between them are expected only in
areas.yamlandCODEOWNERS.dynamo.mcs.v1proto contract, generated code and the label and condition constantsmcs-registry(view, merge rules, memory and DynamoDB stores, handlers, server) andmcs-adminpkg/clientandpkg/fakeregistrymcs-controller(registration and lease, export reconciler, auto-export, importer, CRDs, RBAC)Issues and Ongoing Work
--pool-discovery mcs. Companion gap PRs: feat(global-router): take a pool's region from its EndpointSlice label in the mcs backend #17604 (region label from the slice), fix(global-router): install mcs-api CRDs that serve v1alpha1 and v1beta1 in the CDK example #17605 (mcs-api v0.5.2 CRDs in the CDK), fix(operator): accept any served ServiceExport version for multi-cluster export #17606 (operator accepts either served ServiceExport version), docs(dep): add the standard Multi-Cluster Services implementation to DEP 103 enhancements#104 (DEP 103 wording).targetRef.namespace; the image build passes no version ldflags so binaries reportdev; a memory-store registry restart makes importers garbage-collect imports until controllers re-register (deferring GC on an empty snapshot from a new view epoch would avoid the gap).Pull Request Checklist
/pr-checklistskill.🤖 Generated with Claude Code