This is an automated email from the ASF dual-hosted git repository.
zhongxjian pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/dubbo-kubernetes.git
The following commit(s) were added to refs/heads/master by this push:
new 94a17013 Fix networking api (#839)
94a17013 is described below
commit 94a1701345e332081b0350979cbd219ee7efb91d
Author: mfordjody <[email protected]>
AuthorDate: Mon Jan 5 00:38:31 2026 +0800
Fix networking api (#839)
---
dubbod/planet/pkg/model/destinationrule.go | 22 +-
dubbod/planet/pkg/model/push_context.go | 42 +---
dubbod/planet/pkg/model/virtualservice.go | 309 ----------------------------
dubbod/planet/pkg/networking/grpcgen/cds.go | 9 +-
dubbod/planet/pkg/networking/grpcgen/rds.go | 7 +-
5 files changed, 15 insertions(+), 374 deletions(-)
diff --git a/dubbod/planet/pkg/model/destinationrule.go
b/dubbod/planet/pkg/model/destinationrule.go
index 8d71f78e..a14ec318 100644
--- a/dubbod/planet/pkg/model/destinationrule.go
+++ b/dubbod/planet/pkg/model/destinationrule.go
@@ -21,7 +21,6 @@ import (
"github.com/apache/dubbo-kubernetes/dubbod/planet/pkg/features"
"github.com/apache/dubbo-kubernetes/pkg/config"
"github.com/apache/dubbo-kubernetes/pkg/config/host"
- "github.com/apache/dubbo-kubernetes/pkg/config/labels"
"github.com/apache/dubbo-kubernetes/pkg/config/visibility"
"github.com/apache/dubbo-kubernetes/pkg/util/sets"
"k8s.io/apimachinery/pkg/types"
@@ -57,24 +56,9 @@ func (ps *PushContext) mergeDestinationRule(p
*consolidatedSubRules, subRuleConf
}
}
- existingRule :=
mdr.rule.Spec.(*networking.DestinationRule)
- bothWithoutSelector := rule.GetWorkloadSelector() ==
nil && existingRule.GetWorkloadSelector() == nil
- bothWithSelector := existingRule.GetWorkloadSelector()
!= nil && rule.GetWorkloadSelector() != nil
- selectorsMatch :=
labels.Instance(existingRule.GetWorkloadSelector().GetMatchLabels()).Equals(rule.GetWorkloadSelector().GetMatchLabels())
- if bothWithSelector && !selectorsMatch {
- // If the new destination rule and the existing
one has workload selectors associated with them, skip merging
- // if the selectors do not match
- appendSeparately = true
- continue
- }
- // If both the destination rules are without a workload
selector or with matching workload selectors, simply merge them.
- // If the incoming rule has a workload selector, it has
to be merged with the existing rules with workload selector, and
- // at the same time added as a unique entry in the
processedDestRules.
- if bothWithoutSelector || (bothWithSelector &&
selectorsMatch) {
- appendSeparately = false
- log.Debugf("mergeDestinationRule: will merge
rules for host %s (bothWithoutSelector: %v, bothWithSelector: %v,
selectorsMatch: %v)",
- resolvedHost, bothWithoutSelector,
bothWithSelector, selectorsMatch)
- }
+ // Merge destination rules for the same host
+ appendSeparately = false
+ log.Debugf("mergeDestinationRule: will merge rules for
host %s", resolvedHost)
// Deep copy destination rule, to prevent mutate it
later when merge with a new one.
// This can happen when there are more than one
destination rule of same host in one namespace.
diff --git a/dubbod/planet/pkg/model/push_context.go
b/dubbod/planet/pkg/model/push_context.go
index 5a2c701d..845f411e 100644
--- a/dubbod/planet/pkg/model/push_context.go
+++ b/dubbod/planet/pkg/model/push_context.go
@@ -145,9 +145,6 @@ type exportToDefaults struct {
}
type virtualServiceIndex struct {
- // root vs namespace/name ->delegate vs virtualservice
gvk/namespace/name
- delegates map[ConfigKey][]ConfigKey
-
// Map of VS hostname -> referenced hostnames
referencedDestinations map[string]sets.String
@@ -192,7 +189,6 @@ func newServiceIndex() serviceIndex {
func newVirtualServiceIndex() virtualServiceIndex {
out := virtualServiceIndex{
- delegates: map[ConfigKey][]ConfigKey{},
referencedDestinations: map[string]sets.String{},
hostToRoutes: map[host.Name][]config.Config{},
}
@@ -753,7 +749,6 @@ func (ps *PushContext) initVirtualServices(env
*Environment) {
r.Namespace, r.Name, vs.Hosts, len(vs.Http))
}
}
- vsroutes, ps.virtualServiceIndex.delegates =
mergeVirtualServicesIfNeeded(vsroutes, ps.exportToDefaults.virtualService)
hostToRoutes := make(map[host.Name][]config.Config)
for i := range vsroutes {
@@ -867,20 +862,10 @@ func (ps *PushContext) HTTPRouteForHost(hostname
host.Name) []config.Config {
return routes
}
-// sortConfigBySelectorAndCreationTime sorts the list of config objects based
on priority and creation time.
+// sortConfigBySelectorAndCreationTime sorts the list of config objects based
on creation time.
func sortConfigBySelectorAndCreationTime(configs []config.Config)
[]config.Config {
sort.Slice(configs, func(i, j int) bool {
- // check if one of the configs has priority
- idr := configs[i].Spec.(*networking.DestinationRule)
- jdr := configs[j].Spec.(*networking.DestinationRule)
- if idr.GetWorkloadSelector() != nil &&
jdr.GetWorkloadSelector() == nil {
- return true
- }
- if idr.GetWorkloadSelector() == nil &&
jdr.GetWorkloadSelector() != nil {
- return false
- }
-
- // If priority is the same or neither has priority, fallback to
creation time ordering
+ // Sort by creation time ordering
if r :=
configs[i].CreationTimestamp.Compare(configs[j].CreationTimestamp); r != 0 {
return r == -1 // -1 means i is less than j, so return
true.
}
@@ -905,14 +890,9 @@ func (ps *PushContext) setDestinationRules(configs
[]config.Config) {
rule.Host = string(ResolveShortnameToFQDN(rule.Host,
configs[i].Meta))
var exportToSet sets.Set[visibility.Instance]
- // destination rules with workloadSelector should not be
exported to other namespaces
- if rule.GetWorkloadSelector() == nil {
- exportToSet =
sets.NewWithLength[visibility.Instance](len(rule.ExportTo))
- for _, e := range rule.ExportTo {
- exportToSet.Insert(visibility.Instance(e))
- }
- } else {
- exportToSet =
sets.New[visibility.Instance](visibility.Private)
+ exportToSet =
sets.NewWithLength[visibility.Instance](len(rule.ExportTo))
+ for _, e := range rule.ExportTo {
+ exportToSet.Insert(visibility.Instance(e))
}
// add only if the dest rule is exported with . or * or
explicit exportTo containing this namespace
@@ -1138,9 +1118,8 @@ func firstDestinationRule(csr *consolidatedSubRules,
hostname host.Name) *networ
if dr, ok :=
rule.rule.Spec.(*networking.DestinationRule); ok {
hasTLS := dr.TrafficPolicy != nil &&
dr.TrafficPolicy.Tls != nil
if hasTLS {
- tlsMode := dr.TrafficPolicy.Tls.Mode
tlsModeStr :=
dr.TrafficPolicy.Tls.Mode.String()
- hasTLS = (tlsMode ==
networking.ClientTLSSettings_ISTIO_MUTUAL || tlsModeStr == "DUBBO_MUTUAL")
+ hasTLS = (tlsModeStr == "DUBBO_MUTUAL")
}
if i == 0 {
// Always use first rule as fallback
@@ -1178,15 +1157,6 @@ func firstDestinationRule(csr *consolidatedSubRules,
hostname host.Name) *networ
return nil
}
-func (ps *PushContext) DelegateVirtualServices(vses []config.Config)
[]ConfigHash {
- var out []ConfigHash
- for _, vs := range vses {
- for _, delegate := range
ps.virtualServiceIndex.delegates[ConfigKey{Kind: kind.VirtualService,
Namespace: vs.Namespace, Name: vs.Name}] {
- out = append(out, delegate.HashCode())
- }
- }
- return out
-}
func ConfigNamesOfKind(configs sets.Set[ConfigKey], k kind.Kind) sets.String {
ret := sets.New[string]()
diff --git a/dubbod/planet/pkg/model/virtualservice.go
b/dubbod/planet/pkg/model/virtualservice.go
index 4c721bce..fa9237ff 100644
--- a/dubbod/planet/pkg/model/virtualservice.go
+++ b/dubbod/planet/pkg/model/virtualservice.go
@@ -17,15 +17,8 @@
package model
import (
- "strings"
-
networking "github.com/apache/dubbo-kubernetes/api/networking/v1alpha3"
"github.com/apache/dubbo-kubernetes/pkg/config"
- "github.com/apache/dubbo-kubernetes/pkg/config/schema/kind"
- "github.com/apache/dubbo-kubernetes/pkg/config/visibility"
- "github.com/apache/dubbo-kubernetes/pkg/util/sets"
- "google.golang.org/protobuf/proto"
- "k8s.io/apimachinery/pkg/types"
)
func resolveVirtualServiceShortnames(config config.Config) config.Config {
@@ -51,305 +44,3 @@ func resolveVirtualServiceShortnames(config config.Config)
config.Config {
return r
}
-
-// Return merged virtual services and the root->delegate vs map
-func mergeVirtualServicesIfNeeded(sRoutes []config.Config, defaultExportTo
sets.Set[visibility.Instance]) ([]config.Config, map[ConfigKey][]ConfigKey) {
- out := make([]config.Config, 0, len(sRoutes))
- delegatesMap := map[types.NamespacedName]config.Config{}
- delegatesExportToMap :=
make(map[types.NamespacedName]sets.Set[visibility.Instance])
- // root service routes with delegate
- var rootVses []config.Config
-
- // 1. classify virtualservices
- for _, sr := range sRoutes {
- rule := sr.Spec.(*networking.VirtualService)
- // it is delegate, add it to the indexer cache along with the
exportTo for the delegate
- if len(rule.Hosts) == 0 {
- delegatesMap[sr.NamespacedName()] = sr
- var exportToSet sets.Set[visibility.Instance]
- if len(rule.ExportTo) == 0 {
- // No exportTo in virtualService. Use the
global default
- exportToSet =
sets.NewWithLength[visibility.Instance](defaultExportTo.Len())
- for v := range defaultExportTo {
- if v == visibility.Private {
-
exportToSet.Insert(visibility.Instance(sr.Namespace))
- } else {
- exportToSet.Insert(v)
- }
- }
- } else {
- exportToSet =
sets.NewWithLength[visibility.Instance](len(rule.ExportTo))
- for _, e := range rule.ExportTo {
- if e == string(visibility.Private) {
-
exportToSet.Insert(visibility.Instance(sr.Namespace))
- } else {
-
exportToSet.Insert(visibility.Instance(e))
- }
- }
- }
- delegatesExportToMap[sr.NamespacedName()] = exportToSet
-
- continue
- }
-
- // root sr
- if isRootSr(rule) {
- rootVses = append(rootVses, sr)
- continue
- }
-
- // the others are normal sr without delegate
- out = append(out, sr)
- }
-
- delegatesByRoot := make(map[ConfigKey][]ConfigKey, len(rootVses))
-
- // 2. merge delegates and root
- for _, root := range rootVses {
- rootConfigKey := ConfigKey{Kind: kind.VirtualService, Name:
root.Name, Namespace: root.Namespace}
- rootVs := root.Spec.(*networking.VirtualService)
- mergedRoutes := []*networking.HTTPRoute{}
- for _, route := range rootVs.Http {
- // it is root sr with delegate
- if delegate := route.Delegate; delegate != nil {
- delegateNamespace := delegate.Namespace
- if delegateNamespace == "" {
- delegateNamespace = root.Namespace
- }
- delegateConfigKey := ConfigKey{Kind:
kind.VirtualService, Name: delegate.Name, Namespace: delegateNamespace}
- delegatesByRoot[rootConfigKey] =
append(delegatesByRoot[rootConfigKey], delegateConfigKey)
- delegateVS, ok :=
delegatesMap[types.NamespacedName{Namespace: delegateNamespace, Name:
delegate.Name}]
- if !ok {
- log.Warnf("delegate virtual service
%s/%s of %s/%s not found",
- delegateNamespace,
delegate.Name, root.Namespace, root.Name)
- // delegate not found, ignore only the
current HTTP route
- continue
- }
- // make sure that the delegate is visible to
root virtual service's namespace
- exportTo :=
delegatesExportToMap[types.NamespacedName{Namespace: delegateNamespace, Name:
delegate.Name}]
- if !exportTo.Contains(visibility.Public) &&
!exportTo.Contains(visibility.Instance(root.Namespace)) {
- log.Warnf("delegate virtual service
%s/%s of %s/%s is not exported to %s",
- delegateNamespace,
delegate.Name, root.Namespace, root.Name, root.Namespace)
- continue
- }
- // DeepCopy to prevent mutate the original
delegate, it can conflict
- // when multiple routes delegate to one single
VS.
- copiedDelegate :=
config.DeepCopy(delegateVS.Spec)
- vs :=
copiedDelegate.(*networking.VirtualService)
- merged := mergeHTTPRoutes(route, vs.Http)
- mergedRoutes = append(mergedRoutes, merged...)
- } else {
- mergedRoutes = append(mergedRoutes, route)
- }
- }
- rootVs.Http = mergedRoutes
-
- out = append(out, root)
- }
-
- sortConfigByCreationTime(out)
-
- return out, delegatesByRoot
-}
-
-func isRootSr(vs *networking.VirtualService) bool {
- for _, route := range vs.Http {
- // it is root vs with delegate
- if route.Delegate != nil {
- return true
- }
- }
- return false
-}
-
-func mergeHTTPRoutes(root *networking.HTTPRoute, delegate
[]*networking.HTTPRoute) []*networking.HTTPRoute {
- root.Delegate = nil
-
- out := make([]*networking.HTTPRoute, 0, len(delegate))
- for _, subRoute := range delegate {
- merged := mergeHTTPRoute(root, subRoute)
- if merged != nil {
- out = append(out, merged)
- }
- }
- return out
-}
-
-func mergeHTTPRoute(root *networking.HTTPRoute, delegate
*networking.HTTPRoute) *networking.HTTPRoute {
- // suppose there are N1 match conditions in root, N2 match conditions
in delegate
- // if match condition of N2 is a subset of anyone in N1, this is a
valid matching conditions
- merged, conflict := mergeHTTPMatchRequests(root.Match, delegate.Match)
- if conflict {
- log.Warnf("HTTPMatchRequests conflict: root route %s, delegate
route %s", root.Name, delegate.Name)
- return nil
- }
- delegate.Match = merged
-
- if delegate.Name == "" {
- delegate.Name = root.Name
- } else if root.Name != "" {
- delegate.Name = root.Name + "-" + delegate.Name
- }
-
- return delegate
-}
-
-func mergeHTTPMatchRequests(root, delegate []*networking.HTTPMatchRequest)
(out []*networking.HTTPMatchRequest, conflict bool) {
- if len(root) == 0 {
- return delegate, false
- }
-
- if len(delegate) == 0 {
- return root, false
- }
-
- // each HTTPMatchRequest of delegate must find a superset in root.
- // otherwise it conflicts
- for _, subMatch := range delegate {
- foundMatch := false
- for _, rootMatch := range root {
- if hasConflict(rootMatch, subMatch) {
- log.Warnf("HTTPMatchRequests conflict: root %v,
delegate %v", rootMatch, subMatch)
- continue
- }
- // merge HTTPMatchRequest
- out = append(out, mergeHTTPMatchRequest(rootMatch,
subMatch))
- foundMatch = true
- }
- if !foundMatch {
- return nil, true
- }
- }
- if len(out) == 0 {
- conflict = true
- }
- return
-}
-
-func mergeHTTPMatchRequest(root, delegate *networking.HTTPMatchRequest)
*networking.HTTPMatchRequest {
- cloned := proto.Clone(delegate)
- out, ok := cloned.(*networking.HTTPMatchRequest)
- if !ok {
- log.Warnf("mergeHTTPMatchRequest: failed to clone
HTTPMatchRequest for delegate %s", delegate.GetName())
- return nil
- }
- if out == nil {
- return nil
- }
- if out.Name == "" {
- out.Name = root.Name
- } else if root.Name != "" {
- out.Name = root.Name + "-" + out.Name
- }
- return out
-}
-
-func hasConflict(root, leaf *networking.HTTPMatchRequest) bool {
- roots := []*networking.StringMatch{root.Uri, root.Scheme, root.Method,
root.Authority}
- leaves := []*networking.StringMatch{leaf.Uri, leaf.Scheme, leaf.Method,
leaf.Authority}
- for i := range roots {
- if stringMatchConflict(roots[i], leaves[i]) {
- return true
- }
- }
- // header conflicts
- for key, leafHeader := range leaf.Headers {
- if stringMatchConflict(root.Headers[key], leafHeader) {
- return true
- }
- }
-
- // without headers
- for key, leafValue := range leaf.WithoutHeaders {
- if stringMatchConflict(root.WithoutHeaders[key], leafValue) {
- return true
- }
- }
-
- // query params conflict
- for key, value := range leaf.QueryParams {
- if stringMatchConflict(root.QueryParams[key], value) {
- return true
- }
- }
-
- if root.IgnoreUriCase != leaf.IgnoreUriCase {
- return true
- }
- if root.Port > 0 && leaf.Port > 0 && root.Port != leaf.Port {
- return true
- }
-
- // sourceNamespace
- if root.SourceNamespace != "" && leaf.SourceNamespace !=
root.SourceNamespace {
- return true
- }
-
- // sourceLabels should not conflict, root should have superset of
sourceLabels.
- for key, leafValue := range leaf.SourceLabels {
- if v, ok := root.SourceLabels[key]; ok && v != leafValue {
- return true
- }
- }
-
- // gateways should not conflict, root should have superset of gateways.
- if len(root.Gateways) > 0 && len(leaf.Gateways) > 0 {
- if len(root.Gateways) < len(leaf.Gateways) {
- return true
- }
- rootGateway := sets.New(root.Gateways...)
- for _, gw := range leaf.Gateways {
- if !rootGateway.Contains(gw) {
- return true
- }
- }
- }
-
- return false
-}
-
-func stringMatchConflict(root, leaf *networking.StringMatch) bool {
- // no conflict when root or leaf is not specified
- if root == nil || leaf == nil {
- return false
- }
- // If root regex match is specified, delegate should not have other
matches.
- if root.GetRegex() != "" {
- if leaf.GetRegex() != "" || leaf.GetPrefix() != "" ||
leaf.GetExact() != "" {
- return true
- }
- }
- // If delegate regex match is specified, root should not have other
matches.
- if leaf.GetRegex() != "" {
- if root.GetRegex() != "" || root.GetPrefix() != "" ||
root.GetExact() != "" {
- return true
- }
- }
- // root is exact match
- if exact := root.GetExact(); exact != "" {
- // leaf is prefix match, conflict
- if leaf.GetPrefix() != "" {
- return true
- }
- // both exact, but not equal
- if leaf.GetExact() != exact {
- return true
- }
- return false
- }
- // root is prefix match
- if prefix := root.GetPrefix(); prefix != "" {
- // leaf is prefix match
- if leaf.GetPrefix() != "" {
- // leaf(`/a`) is not subset of root(`/a/b`)
- return !strings.HasPrefix(leaf.GetPrefix(), prefix)
- }
- // leaf is exact match
- if leaf.GetExact() != "" {
- // leaf(`/a`) is not subset of root(`/a/b`)
- return !strings.HasPrefix(leaf.GetExact(), prefix)
- }
- }
-
- return true
-}
diff --git a/dubbod/planet/pkg/networking/grpcgen/cds.go
b/dubbod/planet/pkg/networking/grpcgen/cds.go
index 31c55b38..44b394e5 100644
--- a/dubbod/planet/pkg/networking/grpcgen/cds.go
+++ b/dubbod/planet/pkg/networking/grpcgen/cds.go
@@ -134,7 +134,7 @@ func (b *clusterBuilder) build() []*cluster.Cluster {
if hasTLSInDR {
tlsMode := dr.TrafficPolicy.Tls.Mode
tlsModeStr := dr.TrafficPolicy.Tls.Mode.String()
- hasTLSInDR = (tlsMode ==
networking.ClientTLSSettings_ISTIO_MUTUAL || tlsModeStr == "DUBBO_MUTUAL")
+ hasTLSInDR = (tlsMode ==
networking.ClientTLSSettings_DUBBO_MUTUAL || tlsModeStr == "DUBBO_MUTUAL")
}
// Generate default cluster if requested OR if DestinationRule has
ISTIO_MUTUAL TLS
@@ -225,7 +225,7 @@ func (b *clusterBuilder)
applyDestinationRule(defaultCluster *cluster.Cluster) (
if hasTLS {
tlsMode := dr.TrafficPolicy.Tls.Mode
tlsModeStr := dr.TrafficPolicy.Tls.Mode.String()
- hasTLS = (tlsMode == networking.ClientTLSSettings_ISTIO_MUTUAL
|| tlsModeStr == "DUBBO_MUTUAL")
+ hasTLS = (tlsMode == networking.ClientTLSSettings_DUBBO_MUTUAL
|| tlsModeStr == "DUBBO_MUTUAL")
}
// If no subsets and no TLS, there's nothing to do
@@ -248,7 +248,7 @@ func (b *clusterBuilder)
applyDestinationRule(defaultCluster *cluster.Cluster) (
if recheckTLS {
tlsMode := dr.TrafficPolicy.Tls.Mode
tlsModeStr := dr.TrafficPolicy.Tls.Mode.String()
- recheckTLS = (tlsMode ==
networking.ClientTLSSettings_ISTIO_MUTUAL || tlsModeStr == "DUBBO_MUTUAL")
+ recheckTLS = (tlsMode ==
networking.ClientTLSSettings_DUBBO_MUTUAL || tlsModeStr == "DUBBO_MUTUAL")
}
if hasTLS || recheckTLS {
log.Infof("applyDestinationRule: applying TLS to
default cluster %s (DestinationRule has ISTIO_MUTUAL)", b.defaultClusterName)
@@ -371,7 +371,7 @@ func (b *clusterBuilder) applyTLSForCluster(c
*cluster.Cluster, subset *networki
mode := policy.Tls.Mode
modeStr := policy.Tls.Mode.String()
- if mode != networking.ClientTLSSettings_ISTIO_MUTUAL && modeStr !=
"DUBBO_MUTUAL" {
+ if mode != networking.ClientTLSSettings_DUBBO_MUTUAL && modeStr !=
"DUBBO_MUTUAL" {
log.Debugf("applyTLSForCluster: TLS mode %v (%s) not supported
for gRPC proxyless, skipping", mode, modeStr)
return
}
@@ -406,7 +406,6 @@ func (b *clusterBuilder) buildUpstreamTLSContext(c
*cluster.Cluster, tlsSettings
tlsContext := &tlsv3.UpstreamTlsContext{
CommonTlsContext: common,
- Sni: tlsSettings.GetSni(),
}
// SNI must be the service hostname, not the cluster name
// Cluster name format: outbound|port|subset|hostname
diff --git a/dubbod/planet/pkg/networking/grpcgen/rds.go
b/dubbod/planet/pkg/networking/grpcgen/rds.go
index d88800ec..1109b227 100644
--- a/dubbod/planet/pkg/networking/grpcgen/rds.go
+++ b/dubbod/planet/pkg/networking/grpcgen/rds.go
@@ -368,17 +368,14 @@ func buildRouteFromHTTPRoute(httpRoute
*networking.HTTPRoute, hostName host.Name
Host: string(hostName),
}
} else {
- log.Debugf("buildRouteFromHTTPRoute: route[%d]
Destination: host=%s, subset=%s, port=%v, weight=%d",
- i, destination.Host, destination.Subset,
destination.Port, dest.Weight)
+ log.Debugf("buildRouteFromHTTPRoute: route[%d]
Destination: host=%s, subset=%s, weight=%d",
+ i, destination.Host, destination.Subset,
dest.Weight)
}
targetHost := destination.Host
if targetHost == "" {
targetHost = string(hostName)
}
targetPort := defaultPort
- if destination.Port != nil && destination.Port.Number != 0 {
- targetPort = int(destination.Port.Number)
- }
subsetName := destination.Subset
clusterName :=
model.BuildSubsetKey(model.TrafficDirectionOutbound, subsetName,
host.Name(targetHost), targetPort)
weight := dest.Weight