Skip to content

Support distinct endpoints and Pod/Node metadata mapping for xDS K8s endpoints - #1326

Merged
ikhoon merged 1 commit into
line:mainfrom
ikhoon:enhance-k8s-endpoints
Jul 3, 2026
Merged

Support distinct endpoints and Pod/Node metadata mapping for xDS K8s endpoints#1326
ikhoon merged 1 commit into
line:mainfrom
ikhoon:enhance-k8s-endpoints

Conversation

@ikhoon

@ikhoon ikhoon commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Motivation:

The xDS control plane converts Kubernetes service endpoints into Envoy ClusterLoadAssignment resources, but had two gaps: in NODE_PORT mode multiple Pods on the same node produce duplicate LbEndpoints, and LbEndpoint.metadata was never populated, so users could not drive Envoy subset load balancing from Kubernetes Pod/Node labels or annotations.

Modifications:

  • Add distinct_endpoint to ServiceEndpointWatcher; when true, endpoints that share the same host:port are collapsed into a single LbEndpoint.
  • Add metadata_mapping (repeated MetadataMapping) to ServiceEndpointWatcher. Each rule copies a Pod/Node label or annotation into LbEndpoint.metadata, selecting an exact source_key or a source_key_prefix (original keys kept), under a configurable metadata_namespace (default envoy.lb) and metadata_key.
  • Add KubernetesEndpointConverter centralizing endpoint-to-LbEndpoint conversion (dedup + metadata) via Armeria KubernetesResourceAccess.
  • Route both build sites (background fetching service and preview) through the converter, removing duplicated conversion code.
  • Validate metadata mappings on create/update, rejecting malformed rules with INVALID_ARGUMENT.
  • Add tests for exact/prefix metadata copy, custom namespace, annotations, endpoint dedup, and validation errors.

Result:

Users can deduplicate Kubernetes endpoints and carry Pod/Node labels and annotations as Envoy endpoint metadata by configuring the watcher. Both fields are optional; existing configurations are unaffected.

…endpoints

Motivation:

The xDS control plane converts Kubernetes service endpoints into Envoy
ClusterLoadAssignment resources, but had two gaps: in NODE_PORT mode multiple
Pods on the same node produce duplicate LbEndpoints, and LbEndpoint.metadata was
never populated, so users could not drive Envoy subset load balancing from
Kubernetes Pod/Node labels or annotations.

Modifications:

- Add `distinct_endpoint` to `ServiceEndpointWatcher`; when true, endpoints that
  share the same host:port are collapsed into a single LbEndpoint.
- Add `metadata_mapping` (repeated `MetadataMapping`) to `ServiceEndpointWatcher`.
  Each rule copies a Pod/Node label or annotation into `LbEndpoint.metadata`,
  selecting an exact `source_key` or a `source_key_prefix` (original keys kept),
  under a configurable `metadata_namespace` (default `envoy.lb`) and `metadata_key`.
- Add `KubernetesEndpointConverter` centralizing endpoint-to-LbEndpoint
  conversion (dedup + metadata) via Armeria `KubernetesResourceAccess`.
- Route both build sites (background fetching service and preview) through the
  converter, removing duplicated conversion code.
- Validate metadata mappings on create/update, rejecting malformed rules with
  INVALID_ARGUMENT.
- Add tests for exact/prefix metadata copy, custom namespace, annotations,
  endpoint dedup, and validation errors.

Result:

Users can deduplicate Kubernetes endpoints and carry Pod/Node labels and
annotations as Envoy endpoint metadata by configuring the watcher. Both fields
are optional; existing configurations are unaffected.
@ikhoon
ikhoon force-pushed the enhance-k8s-endpoints branch from 71667a3 to a8f1ed0 Compare July 2, 2026 02:58
@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds Kubernetes endpoint metadata mapping support: new distinct_endpoint and metadata_mapping proto fields with a MetadataMapping message, a new KubernetesEndpointConverter to build Envoy LbEndpoints with deduplication and metadata copied from Pod/Node labels or annotations, service wiring with validation, and a new test suite.

Changes

Kubernetes endpoint metadata mapping

Layer / File(s) Summary
Proto schema for metadata mapping
xds/src/main/proto/.../xds_kubernetes.proto
Adds distinct_endpoint and metadata_mapping fields to ServiceEndpointWatcher, and introduces MetadataMapping with source oneof and ResourceType/EntryType enums.
KubernetesEndpointConverter implementation
xds/.../KubernetesEndpointConverter.java
New utility that builds LbEndpoints from Kubernetes endpoints, optionally deduplicates by host:port, and attaches Envoy Metadata derived from Pod/Node labels or annotations via KubernetesResourceAccess.
Service integration and validation
xds/.../XdsKubernetesEndpointFetchingService.java, xds/.../XdsKubernetesService.java
Both services delegate endpoint-to-LbEndpoint conversion to KubernetesEndpointConverter; XdsKubernetesService adds validateMetadataMappings to reject invalid mappings with INVALID_ARGUMENT before creating endpoint groups.
Metadata mapping test suite
xds/src/test/.../KubernetesEndpointMetadataTest.java
New tests cover label/annotation mapping (exact and prefix), custom namespace, endpoint deduplication, and rejection of invalid mappings, with mock Kubernetes fixture helpers.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant XdsKubernetesService
  participant KubernetesEndpointConverter
  participant KubernetesResourceAccess
  participant EnvoyLbEndpoint

  XdsKubernetesService->>XdsKubernetesService: validateMetadataMappings(watcher)
  XdsKubernetesService->>KubernetesEndpointConverter: addLbEndpoints(builder, endpoints, watcher)
  loop each Kubernetes endpoint
    KubernetesEndpointConverter->>KubernetesEndpointConverter: skip if no ports / dedupe by host:port
    KubernetesEndpointConverter->>KubernetesResourceAccess: objectMeta(endpoint, resourceType)
    KubernetesResourceAccess-->>KubernetesEndpointConverter: Pod/Node ObjectMeta
    KubernetesEndpointConverter->>KubernetesEndpointConverter: buildMetadata(metadataMappingList, objectMeta)
    KubernetesEndpointConverter->>EnvoyLbEndpoint: build LbEndpoint(address, metadata)
  end
  KubernetesEndpointConverter-->>XdsKubernetesService: populated LocalityLbEndpoints
Loading

Suggested reviewers: jrhee17, minwoox

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the two main changes: distinct endpoints and Pod/Node metadata mapping for xDS Kubernetes endpoints.
Description check ✅ Passed The description directly matches the implemented changes, including deduplication, metadata mapping, validation, tests, and converter refactor.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (3)
xds/src/main/java/com/linecorp/centraldogma/xds/k8s/v1/KubernetesEndpointConverter.java (1)

86-136: 🚀 Performance & Scalability | 🔵 Trivial

Minor: repeated Pod/Node lookups when multiple mappings target the same resource.

objectMeta(endpoint, mapping.getResourceType()) is invoked once per MetadataMapping; if several mappings target the same resource_type, the same Pod/Node lookup is repeated. Caching per resource type per endpoint (e.g. a small EnumMap) would avoid the redundant calls.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@xds/src/main/java/com/linecorp/centraldogma/xds/k8s/v1/KubernetesEndpointConverter.java`
around lines 86 - 136, buildMetadata repeatedly calls objectMeta(endpoint,
mapping.getResourceType()) for every MetadataMapping, causing redundant Pod/Node
lookups when multiple mappings share the same resource type. Cache the
ObjectMeta per resource type within buildMetadata, using a small per-endpoint
map keyed by mapping.getResourceType(), and reuse the cached value inside the
loop while preserving the current metadata assembly logic.
xds/src/main/proto/centraldogma/xds/k8s/v1/xds_kubernetes.proto (1)

129-139: 📐 Maintainability & Code Quality | 🔵 Trivial

Optional: prefix enum values with the enum name.

POD/NODE and LABEL/ANNOTATION share C++/Python scope with sibling enums in the same message per protobuf style guide; prefixing (e.g. RESOURCE_TYPE_POD) avoids future name collisions if more enums are added to MetadataMapping.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@xds/src/main/proto/centraldogma/xds/k8s/v1/xds_kubernetes.proto` around lines
129 - 139, Prefix the enum values in MetadataMapping’s ResourceType and
EntryType to avoid shared C++/Python scope collisions with sibling enums; update
the definitions of ResourceType and EntryType so POD/NODE and LABEL/ANNOTATION
use enum-name-prefixed identifiers consistently. Keep the zero-value unspecified
members aligned with the same naming pattern, and make sure any generated
references in xds_kubernetes.proto are updated to the new enum symbols.
xds/src/test/java/com/linecorp/centraldogma/xds/k8s/v1/KubernetesEndpointMetadataTest.java (1)

200-221: 📐 Maintainability & Code Quality | 🔵 Trivial

Consider covering update-path validation too.

rejectInvalidMetadataMapping only exercises createAggregator; updateKubernetesEndpointAggregator goes through the same validateKubernetesEndpointAndPush/validateMetadataMappings code path, so a corresponding update-rejection test would round out coverage, though the risk is low given shared implementation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@xds/src/test/java/com/linecorp/centraldogma/xds/k8s/v1/KubernetesEndpointMetadataTest.java`
around lines 200 - 221, Add update-path coverage for invalid metadata mapping
validation in KubernetesEndpointMetadataTest, since rejectInvalidMetadataMapping
only verifies createAggregator. Reuse the existing invalid MetadataMapping cases
and assert that updateKubernetesEndpointAggregator (through
ServiceEndpointWatcher / watcher setup and validateKubernetesEndpointAndPush)
also returns BAD_REQUEST with INVALID_ARGUMENT, so the shared
validateMetadataMappings path is exercised for updates too.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In
`@xds/src/main/java/com/linecorp/centraldogma/xds/k8s/v1/KubernetesEndpointConverter.java`:
- Around line 86-136: buildMetadata repeatedly calls objectMeta(endpoint,
mapping.getResourceType()) for every MetadataMapping, causing redundant Pod/Node
lookups when multiple mappings share the same resource type. Cache the
ObjectMeta per resource type within buildMetadata, using a small per-endpoint
map keyed by mapping.getResourceType(), and reuse the cached value inside the
loop while preserving the current metadata assembly logic.

In `@xds/src/main/proto/centraldogma/xds/k8s/v1/xds_kubernetes.proto`:
- Around line 129-139: Prefix the enum values in MetadataMapping’s ResourceType
and EntryType to avoid shared C++/Python scope collisions with sibling enums;
update the definitions of ResourceType and EntryType so POD/NODE and
LABEL/ANNOTATION use enum-name-prefixed identifiers consistently. Keep the
zero-value unspecified members aligned with the same naming pattern, and make
sure any generated references in xds_kubernetes.proto are updated to the new
enum symbols.

In
`@xds/src/test/java/com/linecorp/centraldogma/xds/k8s/v1/KubernetesEndpointMetadataTest.java`:
- Around line 200-221: Add update-path coverage for invalid metadata mapping
validation in KubernetesEndpointMetadataTest, since rejectInvalidMetadataMapping
only verifies createAggregator. Reuse the existing invalid MetadataMapping cases
and assert that updateKubernetesEndpointAggregator (through
ServiceEndpointWatcher / watcher setup and validateKubernetesEndpointAndPush)
also returns BAD_REQUEST with INVALID_ARGUMENT, so the shared
validateMetadataMappings path is exercised for updates too.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 10bdf480-5dad-4f2f-a88c-ffbc361d224f

📥 Commits

Reviewing files that changed from the base of the PR and between 0c40353 and a8f1ed0.

📒 Files selected for processing (5)
  • xds/src/main/java/com/linecorp/centraldogma/xds/k8s/v1/KubernetesEndpointConverter.java
  • xds/src/main/java/com/linecorp/centraldogma/xds/k8s/v1/XdsKubernetesEndpointFetchingService.java
  • xds/src/main/java/com/linecorp/centraldogma/xds/k8s/v1/XdsKubernetesService.java
  • xds/src/main/proto/centraldogma/xds/k8s/v1/xds_kubernetes.proto
  • xds/src/test/java/com/linecorp/centraldogma/xds/k8s/v1/KubernetesEndpointMetadataTest.java

@ikhoon
ikhoon marked this pull request as ready for review July 2, 2026 05:02

@minwoox minwoox left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 👍 👍

@jrhee17 jrhee17 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 👍

@ikhoon
ikhoon merged commit eea921b into line:main Jul 3, 2026
13 of 14 checks passed
@ikhoon
ikhoon deleted the enhance-k8s-endpoints branch July 3, 2026 08:52
@ikhoon ikhoon added this to the 0.85.0 milestone Jul 14, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants