Repository navigation
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #9423 +/- ##
==========================================
- Coverage 87.79% 87.70% -0.10%
==========================================
Files 437 437
Lines 31442 31387 -55
==========================================
- Hits 27604 27527 -77
- Misses 3838 3860 +22
🚀 New features to boost your workflow:
|
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request refactors the CDS balancer configuration to align with gRFC A75, specifically updating the aggregate cluster configuration to wrap leaf clusters in outlier_detection and cluster_impl policies. It also cleans up test utilities and simplifies configuration building logic. A potential nil pointer dereference issue was identified in the EDS update logic, for which a defensive check has been suggested.
| priorities := [][]xdsresource.Locality{{}} | ||
| edsUpdate := leaf.clusterConfig.EndpointConfig.EDSUpdate | ||
| // Localities of length 0 is triggered by an NACK or resource-not-found | ||
| // error before update, or an empty localities list in an update. In either | ||
| // case want to create a priority, and send down empty address list, causing | ||
| // TF for that priority. "If any discovery mechanism instance experiences an | ||
| // error retrieving data, and it has not previously reported any results, it | ||
| // should report a result that is a single priority with no endpoints." - | ||
| // A37 | ||
| if len(edsUpdate.Localities) != 0 { | ||
| priorities = groupLocalitiesByPriority(edsUpdate.Localities) | ||
| } |
There was a problem hiding this comment.
To prevent a potential nil pointer dereference, we should add a defensive check to ensure leaf.clusterConfig.EndpointConfig is not nil before accessing EDSUpdate. In xDS, the endpoint configuration might not be populated yet if the endpoints are not resolved or if there was an error resolving them.
| priorities := [][]xdsresource.Locality{{}} | |
| edsUpdate := leaf.clusterConfig.EndpointConfig.EDSUpdate | |
| // Localities of length 0 is triggered by an NACK or resource-not-found | |
| // error before update, or an empty localities list in an update. In either | |
| // case want to create a priority, and send down empty address list, causing | |
| // TF for that priority. "If any discovery mechanism instance experiences an | |
| // error retrieving data, and it has not previously reported any results, it | |
| // should report a result that is a single priority with no endpoints." - | |
| // A37 | |
| if len(edsUpdate.Localities) != 0 { | |
| priorities = groupLocalitiesByPriority(edsUpdate.Localities) | |
| } | |
| priorities := [][]xdsresource.Locality{{}} | |
| var edsUpdate *xdsresource.EndpointsUpdate | |
| if leaf.clusterConfig.EndpointConfig != nil { | |
| edsUpdate = leaf.clusterConfig.EndpointConfig.EDSUpdate | |
| } | |
| // Localities of length 0 is triggered by an NACK or resource-not-found | |
| // error before update, or an empty localities list in an update. In either | |
| // case want to create a priority, and send down empty address list, causing | |
| // TF for that priority. "If any discovery mechanism instance experiences an | |
| // error retrieving data, and it has not previously reported any results, it | |
| // should report a result that is a single priority with no endpoints." - | |
| // A37 | |
| if edsUpdate != nil && len(edsUpdate.Localities) != 0 { | |
| priorities = groupLocalitiesByPriority(edsUpdate.Localities) | |
| } |
There was a problem hiding this comment.
I did some analysis and a nil EndpointConfig may actually happen. When one of the leaf clusters has not resolved its endpoints yet, but another one raises an error. However, instead of adding a simple nil check here, I fixed that a nil is not passed.
This is the commit that fixes it: 2e99573
@easwars @Pranjali-2501 please, let me know if it makes sense to deliver it with this PR or should I issue a new one?
There was a problem hiding this comment.
Thanks for digging into this. It will be better to fix this bug and a test for this in a separate PR. It's a pre-existing bug and independent of the tree refactoring done as part of gRFC A75.
| continue | ||
| default: | ||
| return nil, nil, fmt.Errorf("unsupported cluster type %v for leaf cluster %q", clusterUpdate.ClusterType, clusterUpdate.ClusterName) | ||
| odCfg, endpoints, err := buildLeafClusterConfig(leaf, xdsLBPolicy) |
There was a problem hiding this comment.
https://screenshot-v2.corp.google.com/07p4t433u6dag
As per gRFC A75, for aggregate clusters we should use the LB policy configured in each underlying (leaf) cluster and ignore the one in the aggregate cluster.
A75 also asks for a temporary GRPC_XDS_AGGREGATE_CLUSTER_BACKWARD_COMPAT env var. When it's set to true, the leaves use the aggregate cluster's LB policy, i.e. the current behavior.
But we're still unmarshaling the LB policy of the root cluster and passing the same policy to every leaf here:
grpc-go/internal/xds/balancer/cdsbalancer/cdsbalancer.go
Lines 239 to 242 in 3d69670
So if the aggregate cluster uses the default
round_robin and a leaf is configured with ring_hash, the leaf ends up using round_robin. None of the existing tests catch this because they all use the default policy for every cluster.
There was a problem hiding this comment.
thank you for spotting that, I added the missing switch and using a leaf LB policy
There was a problem hiding this comment.
I have also updated the RELEASE NOTES of this PR
There was a problem hiding this comment.
I think we have decided to remove the outlierDetection config parsing from cdsbalancer.go and build it inside buildLeafClusterConfig instead of updating it for all priorities.
See this: #9234 (comment)
We have also decided to remove the outlierDetection field from leafClusterConfig.
There was a problem hiding this comment.
this was fixed with a CDS on top of the leaf policy tree
| // ┌──────▼─────┐ ┌─────▼──────┐ | ||
| // │xDSLBPolicy │ │xDSLBPolicy │ (Locality and Endpoint picking layer) | ||
| // └────────────┘ └────────────┘ | ||
| // ┌────────┐ |
There was a problem hiding this comment.
https://github.com/grpc/proposal/blob/master/A75_graphics/grpc_client_architecture_aggregate.png
According to the gRFC, for aggregate clusters, priority lb for each cluster should have a CDS child and than follows the same leaf cluster config.
Currently this PR creates outlier_detection as child of priority LB for each cluster.
Is this the decision taken, if so why?
There was a problem hiding this comment.
The first implementation was doing an eager config building, which was rebuilding configs for all the leaves on each update, so CDS was not necessary.
I have reconsidered and decided to stick with A75 and C-Core implementation and I added CDS on the top of the leaf config tree.
|
Please resolve the merge conflicts in this PR. |
…licy-tree-refactoring
This reverts commit 2e99573.
resolved |
…licy-tree-refactoring
…licy-tree-refactoring
Implements A75 for the aggregate cluster.
Follow-up to #9234. This change implements the new LB policy topology (
priority -> outlier_detection -> cluster_impl -> priority -> xds_wrr_locality -> endpoint picking policy) for the aggregate cluster case by delegating leaf cluster configuration tobuildLeafClusterConfig, and removes the legacy aggregate cluster configuration helpers.RELEASE NOTES:
cluster of an aggregate cluster now uses the LB policy configured in that
cluster, and the LB policy configured in the aggregate cluster is ignored.
Outlier detection and other per-cluster settings now apply across all
priorities of the underlying cluster. The previous LB policy behavior can be
temporarily restored by setting the
GRPC_XDS_AGGREGATE_CLUSTER_BACKWARD_COMPATenvironment variable to
true; this mechanism will be removed in a futurerelease.