istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/xds/cds.go (about) 1 // Copyright Istio Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package xds 16 17 import ( 18 "istio.io/istio/pilot/pkg/features" 19 "istio.io/istio/pilot/pkg/model" 20 "istio.io/istio/pilot/pkg/networking/core" 21 "istio.io/istio/pkg/config/schema/kind" 22 "istio.io/istio/pkg/jwt" 23 "istio.io/istio/pkg/util/sets" 24 ) 25 26 type CdsGenerator struct { 27 ConfigGenerator core.ConfigGenerator 28 } 29 30 var _ model.XdsDeltaResourceGenerator = &CdsGenerator{} 31 32 // Map of all configs that do not impact CDS 33 var skippedCdsConfigs = sets.New( 34 kind.Gateway, 35 kind.WorkloadEntry, 36 kind.WorkloadGroup, 37 kind.AuthorizationPolicy, 38 kind.RequestAuthentication, 39 kind.Secret, 40 kind.Telemetry, 41 kind.WasmPlugin, 42 kind.ProxyConfig, 43 kind.DNSName, 44 45 kind.KubernetesGateway, 46 ) 47 48 // Map all configs that impact CDS for gateways when `PILOT_FILTER_GATEWAY_CLUSTER_CONFIG = true`. 49 var pushCdsGatewayConfig = func() sets.Set[kind.Kind] { 50 s := sets.New( 51 kind.VirtualService, 52 kind.Gateway, 53 54 kind.KubernetesGateway, 55 kind.HTTPRoute, 56 kind.TCPRoute, 57 kind.TLSRoute, 58 kind.GRPCRoute, 59 ) 60 if features.JwksFetchMode != jwt.Istiod { 61 s.Insert(kind.RequestAuthentication) 62 } 63 return s 64 }() 65 66 func cdsNeedsPush(req *model.PushRequest, proxy *model.Proxy) bool { 67 if req == nil { 68 return true 69 } 70 switch proxy.Type { 71 case model.Waypoint: 72 if model.HasConfigsOfKind(req.ConfigsUpdated, kind.Address) { 73 // TODO: this logic is identical to that used in LDS, consider refactor into a common function 74 // taken directly from LDS... waypoints need CDS updates on kind.Address changes 75 // after implementing use-waypoint which decouples waypoint creation, wl pod creation 76 // user specifying waypoint use. Without this we're not getting correct waypoint config 77 // in a timely manner 78 return true 79 } 80 // Otherwise, only handle full pushes (skip endpoint-only updates) 81 if !req.Full { 82 return false 83 } 84 default: 85 if !req.Full { 86 // CDS only handles full push 87 return false 88 } 89 } 90 // If none set, we will always push 91 if len(req.ConfigsUpdated) == 0 { 92 return true 93 } 94 95 checkGateway := false 96 for config := range req.ConfigsUpdated { 97 if proxy.Type == model.Router { 98 if features.FilterGatewayClusterConfig { 99 if _, f := pushCdsGatewayConfig[config.Kind]; f { 100 return true 101 } 102 } 103 if config.Kind == kind.Gateway { 104 // Do the check outside of the loop since its slow; just trigger we need it 105 checkGateway = true 106 } 107 } 108 109 if _, f := skippedCdsConfigs[config.Kind]; !f { 110 return true 111 } 112 } 113 if checkGateway { 114 autoPassthroughModeChanged := proxy.MergedGateway.HasAutoPassthroughGateways() != proxy.PrevMergedGateway.HasAutoPassthroughGateway() 115 autoPassthroughHostsChanged := !proxy.MergedGateway.GetAutoPassthrughGatewaySNIHosts().Equals(proxy.PrevMergedGateway.GetAutoPassthroughSNIHosts()) 116 if autoPassthroughModeChanged || autoPassthroughHostsChanged { 117 return true 118 } 119 } 120 return false 121 } 122 123 func (c CdsGenerator) Generate(proxy *model.Proxy, w *model.WatchedResource, req *model.PushRequest) (model.Resources, model.XdsLogDetails, error) { 124 if !cdsNeedsPush(req, proxy) { 125 return nil, model.DefaultXdsLogDetails, nil 126 } 127 clusters, logs := c.ConfigGenerator.BuildClusters(proxy, req) 128 return clusters, logs, nil 129 } 130 131 // GenerateDeltas for CDS currently only builds deltas when services change. todo implement changes for DestinationRule, etc 132 func (c CdsGenerator) GenerateDeltas(proxy *model.Proxy, req *model.PushRequest, 133 w *model.WatchedResource, 134 ) (model.Resources, model.DeletedResources, model.XdsLogDetails, bool, error) { 135 if !cdsNeedsPush(req, proxy) { 136 return nil, nil, model.DefaultXdsLogDetails, false, nil 137 } 138 updatedClusters, removedClusters, logs, usedDelta := c.ConfigGenerator.BuildDeltaClusters(proxy, req, w) 139 return updatedClusters, removedClusters, logs, usedDelta, nil 140 }