istio.io/istio@v0.0.0-20240520182934-d79c90f27776/pilot/pkg/serviceregistry/kube/controller/endpoint_builder.go (about) 1 // Copyright Istio Authors. All Rights Reserved. 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 controller 16 17 import ( 18 v1 "k8s.io/api/core/v1" 19 20 "istio.io/api/label" 21 "istio.io/istio/pilot/pkg/model" 22 "istio.io/istio/pilot/pkg/networking/util" 23 "istio.io/istio/pilot/pkg/serviceregistry/kube" 24 labelutil "istio.io/istio/pilot/pkg/serviceregistry/util/label" 25 "istio.io/istio/pkg/config/labels" 26 kubeUtil "istio.io/istio/pkg/kube" 27 "istio.io/istio/pkg/network" 28 ) 29 30 // EndpointBuilder is a stateful IstioEndpoint builder with metadata used to build IstioEndpoint 31 type EndpointBuilder struct { 32 controller controllerInterface 33 34 labels labels.Instance 35 metaNetwork network.ID 36 serviceAccount string 37 locality model.Locality 38 tlsMode string 39 workloadName string 40 namespace string 41 42 // Values used to build dns name tables per pod. 43 // The hostname of the Pod, by default equals to pod name. 44 hostname string 45 // If specified, the fully qualified Pod hostname will be "<hostname>.<subdomain>.<pod namespace>.svc.<cluster domain>". 46 subDomain string 47 // If in k8s, the node where the pod resides 48 nodeName string 49 } 50 51 func NewEndpointBuilder(c controllerInterface, pod *v1.Pod) *EndpointBuilder { 52 var locality, sa, namespace, hostname, subdomain, ip, node string 53 var podLabels labels.Instance 54 if pod != nil { 55 locality = c.getPodLocality(pod) 56 sa = kube.SecureNamingSAN(pod) 57 podLabels = pod.Labels 58 namespace = pod.Namespace 59 subdomain = pod.Spec.Subdomain 60 if subdomain != "" { 61 hostname = pod.Spec.Hostname 62 if hostname == "" { 63 hostname = pod.Name 64 } 65 } 66 ip = pod.Status.PodIP 67 node = pod.Spec.NodeName 68 } 69 dm, _ := kubeUtil.GetDeployMetaFromPod(pod) 70 out := &EndpointBuilder{ 71 controller: c, 72 serviceAccount: sa, 73 locality: model.Locality{ 74 Label: locality, 75 ClusterID: c.Cluster(), 76 }, 77 tlsMode: kube.PodTLSMode(pod), 78 workloadName: dm.Name, 79 namespace: namespace, 80 hostname: hostname, 81 subDomain: subdomain, 82 labels: podLabels, 83 nodeName: node, 84 } 85 networkID := out.endpointNetwork(ip) 86 out.labels = labelutil.AugmentLabels(podLabels, c.Cluster(), locality, node, networkID) 87 return out 88 } 89 90 func NewEndpointBuilderFromMetadata(c controllerInterface, proxy *model.Proxy) *EndpointBuilder { 91 locality := util.LocalityToString(proxy.Locality) 92 out := &EndpointBuilder{ 93 controller: c, 94 metaNetwork: proxy.Metadata.Network, 95 serviceAccount: proxy.Metadata.ServiceAccount, 96 locality: model.Locality{ 97 Label: locality, 98 ClusterID: c.Cluster(), 99 }, 100 tlsMode: model.GetTLSModeFromEndpointLabels(proxy.Labels), 101 nodeName: proxy.GetNodeName(), 102 } 103 var networkID network.ID 104 if len(proxy.IPAddresses) > 0 { 105 networkID = out.endpointNetwork(proxy.IPAddresses[0]) 106 } 107 out.labels = labelutil.AugmentLabels(proxy.Labels, c.Cluster(), locality, out.nodeName, networkID) 108 return out 109 } 110 111 func (b *EndpointBuilder) buildIstioEndpoint( 112 endpointAddress string, 113 endpointPort int32, 114 svcPortName string, 115 discoverabilityPolicy model.EndpointDiscoverabilityPolicy, 116 healthStatus model.HealthStatus, 117 ) *model.IstioEndpoint { 118 if b == nil { 119 return nil 120 } 121 122 // in case pod is not found when init EndpointBuilder. 123 networkID := network.ID(b.labels[label.TopologyNetwork.Name]) 124 if networkID == "" { 125 networkID = b.endpointNetwork(endpointAddress) 126 b.labels[label.TopologyNetwork.Name] = string(networkID) 127 } 128 129 return &model.IstioEndpoint{ 130 Labels: b.labels, 131 ServiceAccount: b.serviceAccount, 132 Locality: b.locality, 133 TLSMode: b.tlsMode, 134 Address: endpointAddress, 135 EndpointPort: uint32(endpointPort), 136 ServicePortName: svcPortName, 137 Network: networkID, 138 WorkloadName: b.workloadName, 139 Namespace: b.namespace, 140 HostName: b.hostname, 141 SubDomain: b.subDomain, 142 DiscoverabilityPolicy: discoverabilityPolicy, 143 HealthStatus: healthStatus, 144 NodeName: b.nodeName, 145 } 146 } 147 148 // return the mesh network for the endpoint IP. Empty string if not found. 149 func (b *EndpointBuilder) endpointNetwork(endpointIP string) network.ID { 150 // If we're building the endpoint based on proxy meta, prefer the injected ISTIO_META_NETWORK value. 151 if b.metaNetwork != "" { 152 return b.metaNetwork 153 } 154 155 return b.controller.Network(endpointIP, b.labels) 156 }