-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
feat(zrpc): migrate kube resolver from Endpoints to EndpointSlice API #4987
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
feat(zrpc): migrate kube resolver from Endpoints to EndpointSlice API #4987
Conversation
Codecov ReportAttention: Patch coverage is
📢 Thoughts on this report? Let us know! |
dc48d57
to
ca7e131
Compare
Thanks for your contribution! This PR will be merged in v1.9.0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR migrates the zrpc Kubernetes resolver from using the legacy core/v1 Endpoints
API to the newer discovery/v1 EndpointSlice
API, updating event handling, informer setup, initial synchronization, and port resolution.
- Swap informer and event-handler logic to work with
EndpointSlice
and itsEndpoints[].Addresses[]
. - Implement initial listing of
EndpointSlice
objects and derive service port from the first available slice. - Rename selector constant and add explicit error when no slices are found.
Reviewed Changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
File | Description |
---|---|
zrpc/resolver/internal/kubebuilder.go | Replace Endpoints informer with EndpointSlices, update port resolution and initial sync |
zrpc/resolver/internal/kube/eventhandler.go | Update event handler and update logic to handle discovery/v1.EndpointSlice |
zrpc/resolver/internal/kube/eventhandler_test.go | Update tests to use EndpointSlice types and verify address-change handling |
Comments suppressed due to low confidence (1)
zrpc/resolver/internal/kubebuilder.go:62
- The logic that lists EndpointSlices and assigns svc.Port from the first slice isn't covered by existing tests. Consider adding unit tests for port resolution and the error path when no slices or ports are available.
if svc.Port == 0 {
svc.Port = int(endpoints.Subsets[0].Ports[0].Port) | ||
// Since this resolver is used for in-cluster service discovery, | ||
// there should be at least one port available. | ||
svc.Port = int(*endpointSlices.Items[0].Ports[0].Port) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code assumes that each EndpointSlice has a non-empty Ports slice and will panic if Ports is empty. Add a check for len(endpointSlices.Items[0].Ports) > 0 (and a nil-Port pointer) before dereferencing, and return a clear error if missing.
Copilot uses AI. Check for mistakes.
for _, endpointSlice := range endpointSlices.Items { | ||
handler.Update(&endpointSlice) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling Update for each EndpointSlice resets the resolver state per slice, so after processing multiple slices only the last slice’s endpoints remain. Instead, merge addresses across all slices into one update or call OnAdd per slice to accumulate state.
for _, endpointSlice := range endpointSlices.Items { | |
handler.Update(&endpointSlice) | |
} | |
var allEndpoints []string | |
for _, endpointSlice := range endpointSlices.Items { | |
for _, endpoint := range endpointSlice.Endpoints { | |
for _, address := range endpoint.Addresses { | |
allEndpoints = append(allEndpoints, address) | |
} | |
} | |
} | |
allEndpoints = subset(allEndpoints, subsetSize) | |
addrs := make([]resolver.Address, 0, len(allEndpoints)) | |
for _, val := range allEndpoints { | |
addrs = append(addrs, resolver.Address{ | |
Addr: fmt.Sprintf("%s:%d", val, svc.Port), | |
}) | |
} | |
if err := cc.UpdateState(resolver.State{ | |
Addresses: addrs, | |
}); err != nil { | |
logx.Error(err) | |
} |
Copilot uses AI. Check for mistakes.
ca7e131
to
45868b0
Compare
* Replace core/v1 Endpoints with discovery/v1 EndpointSlice in event handler * Update handler logic to iterate over EndpointSlice.Endpoints[].Addresses[] * Switch informer to watch EndpointSlices using label selector "kubernetes.io/service-name" * Retrieve service port from the first EndpointSlice port when not specified * Rename constant `nameSelector` → `serviceSelector` for clarity * Improve error handling for missing EndpointSlices Signed-off-by: soasurs <soasurs@gmail.com>
Signed-off-by: soasurs <soasurs@gmail.com>
…v1 EndpointSlice * Replace legacy core/v1 Endpoints fixtures with discovery/v1 EndpointSlice * Adapt test data: switch Subsets/Addresses to Endpoints[].Addresses[] * Preserve existing test scenarios for add, delete, and update event flows Signed-off-by: soasurs <soasurs@gmail.com>
45868b0
to
d69d042
Compare
When there’s a pod change, the EndpointSlice returned isn’t the full set, but only the changed slice, right? We need to carefully analyze the notification mechanism. For example, if it’s split into 10 slices and a new pod is added, only one slice is returned — then traffic might become skewed toward that part.
Motivation
Kubernetes is gradually deprecating the legacy
core/v1 Endpoints
API in favor of the newerdiscovery/v1 EndpointSlice
API.Compared with
Endpoints
,EndpointSlice
objects:To keep go-zero up-to-date with upstream best practices and to prevent future breakage as clusters disable the old API, we need to adopt
EndpointSlice
.What this PR does
Event Path Migration
core/v1 Endpoints
types withdiscovery/v1 EndpointSlice
in the kube resolver.EndpointSlice.Endpoints[].Addresses[]
.Informer Updates
Core().V1().Endpoints()
toDiscovery().V1().EndpointSlices()
.kubernetes.io/service-name=<svc>
.Initial Sync & Port Resolution
EndpointSlice
objects for the target service at startup.svc.Port
from the first available slice port when the user omits it.Constants & Clean-ups
nameSelector
→serviceSelector
for clarity.Impact
zrpc
resolver API remains unchanged.Endpoints
API.get, list, watch
onEndpointSlices
(discovery.k8s.io
group).No other functional regressions are expected. All unit tests pass against Kubernetes ≥1.21 (the minimum version that GA-supports
EndpointSlice
).