github.com/polarismesh/polaris@v1.17.8/apiserver/xdsserverv3/eds.go (about)

     1  /**
     2   * Tencent is pleased to support the open source community by making Polaris available.
     3   *
     4   * Copyright (C) 2019 THL A29 Limited, a Tencent company. All rights reserved.
     5   *
     6   * Licensed under the BSD 3-Clause License (the "License");
     7   * you may not use this file except in compliance with the License.
     8   * You may obtain a copy of the License at
     9   *
    10   * https://opensource.org/licenses/BSD-3-Clause
    11   *
    12   * Unless required by applicable law or agreed to in writing, software distributed
    13   * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
    14   * CONDITIONS OF ANY KIND, either express or implied. See the License for the
    15   * specific language governing permissions and limitations under the License.
    16   */
    17  
    18  package xdsserverv3
    19  
    20  import (
    21  	"strconv"
    22  	"strings"
    23  
    24  	core "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
    25  	corev3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
    26  	endpoint "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3"
    27  	"github.com/envoyproxy/go-control-plane/pkg/cache/types"
    28  	"google.golang.org/protobuf/types/known/wrapperspb"
    29  
    30  	"github.com/polarismesh/polaris/apiserver/xdsserverv3/resource"
    31  	"github.com/polarismesh/polaris/common/model"
    32  	"github.com/polarismesh/polaris/common/utils"
    33  	"github.com/polarismesh/polaris/service"
    34  )
    35  
    36  // EDSBuilder .
    37  type EDSBuilder struct {
    38  	client *resource.XDSClient
    39  	svr    service.DiscoverServer
    40  }
    41  
    42  func (eds *EDSBuilder) Init(client *resource.XDSClient, svr service.DiscoverServer) {
    43  	eds.client = client
    44  	eds.svr = svr
    45  }
    46  
    47  func (eds *EDSBuilder) Generate(option *resource.BuildOption) (interface{}, error) {
    48  	var resources []types.Resource
    49  	switch eds.client.RunType {
    50  	case resource.RunTypeGateway:
    51  		resources = append(resources, eds.makeBoundEndpoints(option, core.TrafficDirection_OUTBOUND)...)
    52  	case resource.RunTypeSidecar:
    53  		// sidecar 场景,如果流量方向是 envoy -> 业务 POD,那么 endpoint 只能是 本地 127.0.0.1
    54  		inBoundEndpoints := eds.makeSelfEndpoint(option)
    55  		outBoundEndpoints := eds.makeBoundEndpoints(option, core.TrafficDirection_OUTBOUND)
    56  		resources = append(resources, inBoundEndpoints...)
    57  		resources = append(resources, outBoundEndpoints...)
    58  	}
    59  	return resources, nil
    60  }
    61  
    62  func (eds *EDSBuilder) makeBoundEndpoints(option *resource.BuildOption,
    63  	direction corev3.TrafficDirection) []types.Resource {
    64  
    65  	services := option.Services
    66  	selfServiceKey := model.ServiceKey{
    67  		Namespace: eds.client.GetSelfNamespace(),
    68  		Name:      eds.client.GetSelfService(),
    69  	}
    70  
    71  	var clusterLoads []types.Resource
    72  	for svcKey, serviceInfo := range services {
    73  		if eds.client.IsGateway() && selfServiceKey.Equal(&svcKey) {
    74  			continue
    75  		}
    76  
    77  		var lbEndpoints []*endpoint.LbEndpoint
    78  		for _, instance := range serviceInfo.Instances {
    79  			// 处于隔离状态或者权重为0的实例不进行下发
    80  			if !resource.IsNormalEndpoint(instance) {
    81  				continue
    82  			}
    83  			ep := &endpoint.LbEndpoint{
    84  				HostIdentifier: &endpoint.LbEndpoint_Endpoint{
    85  					Endpoint: &endpoint.Endpoint{
    86  						Address: &core.Address{
    87  							Address: &core.Address_SocketAddress{
    88  								SocketAddress: &core.SocketAddress{
    89  									Protocol: core.SocketAddress_TCP,
    90  									Address:  instance.Host.Value,
    91  									PortSpecifier: &core.SocketAddress_PortValue{
    92  										PortValue: instance.Port.Value,
    93  									},
    94  								},
    95  							},
    96  						},
    97  					},
    98  				},
    99  				HealthStatus:        resource.FormatEndpointHealth(instance),
   100  				LoadBalancingWeight: utils.NewUInt32Value(instance.GetWeight().GetValue()),
   101  				Metadata:            resource.GenEndpointMetaFromPolarisIns(instance),
   102  			}
   103  			lbEndpoints = append(lbEndpoints, ep)
   104  		}
   105  
   106  		cla := &endpoint.ClusterLoadAssignment{
   107  			ClusterName: resource.MakeServiceName(svcKey, direction),
   108  			Endpoints: []*endpoint.LocalityLbEndpoints{
   109  				{
   110  					LbEndpoints: lbEndpoints,
   111  				},
   112  			},
   113  		}
   114  		clusterLoads = append(clusterLoads, cla)
   115  	}
   116  	return clusterLoads
   117  }
   118  
   119  func (eds *EDSBuilder) makeSelfEndpoint(option *resource.BuildOption) []types.Resource {
   120  	var clusterLoads []types.Resource
   121  	var lbEndpoints []*endpoint.LbEndpoint
   122  
   123  	selfServiceKey := model.ServiceKey{
   124  		Namespace: eds.client.GetSelfNamespace(),
   125  		Name:      eds.client.GetSelfService(),
   126  	}
   127  
   128  	var servicePorts []*model.ServicePort
   129  	selfServiceInfo, ok := option.Services[selfServiceKey]
   130  	if ok {
   131  		servicePorts = selfServiceInfo.Ports
   132  	} else {
   133  		// sidecar 的服务没有注册,那就看下 envoy metadata 上有没有设置 sidecar_bindports 标签
   134  		portsSlice := strings.Split(eds.client.Metadata[resource.SidecarBindPort], ",")
   135  		if len(portsSlice) > 0 {
   136  			for i := range portsSlice {
   137  				ret, err := strconv.ParseUint(portsSlice[i], 10, 64)
   138  				if err != nil {
   139  					continue
   140  				}
   141  				if ret <= 65535 {
   142  					servicePorts = append(servicePorts, &model.ServicePort{
   143  						Port:     uint32(ret),
   144  						Protocol: "TCP",
   145  					})
   146  				}
   147  			}
   148  		}
   149  	}
   150  
   151  	for _, port := range servicePorts {
   152  		ep := &endpoint.LbEndpoint{
   153  			HostIdentifier: &endpoint.LbEndpoint_Endpoint{
   154  				Endpoint: &endpoint.Endpoint{
   155  					Address: &core.Address{
   156  						Address: &core.Address_SocketAddress{
   157  							SocketAddress: &core.SocketAddress{
   158  								Protocol: core.SocketAddress_TCP,
   159  								Address:  "127.0.0.1",
   160  								PortSpecifier: &core.SocketAddress_PortValue{
   161  									PortValue: port.Port,
   162  								},
   163  							},
   164  						},
   165  					},
   166  				},
   167  			},
   168  			LoadBalancingWeight: wrapperspb.UInt32(100),
   169  			HealthStatus:        core.HealthStatus_HEALTHY,
   170  		}
   171  		lbEndpoints = append(lbEndpoints, ep)
   172  	}
   173  	cla := &endpoint.ClusterLoadAssignment{
   174  		ClusterName: resource.MakeServiceName(selfServiceKey, core.TrafficDirection_INBOUND),
   175  		Endpoints: []*endpoint.LocalityLbEndpoints{
   176  			{
   177  				LbEndpoints: lbEndpoints,
   178  			},
   179  		},
   180  	}
   181  	clusterLoads = append(clusterLoads, cla)
   182  	return clusterLoads
   183  }