github.com/polarismesh/polaris@v1.17.8/apiserver/xdsserverv3/cds.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  	"fmt"
    22  	"time"
    23  
    24  	cluster "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3"
    25  	core "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
    26  	corev3 "github.com/envoyproxy/go-control-plane/envoy/config/core/v3"
    27  	rawbuffer "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/raw_buffer/v3"
    28  	tlstrans "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3"
    29  	"github.com/envoyproxy/go-control-plane/pkg/cache/types"
    30  	resourcev3 "github.com/envoyproxy/go-control-plane/pkg/resource/v3"
    31  	"github.com/envoyproxy/go-control-plane/pkg/wellknown"
    32  	"github.com/golang/protobuf/ptypes"
    33  	"google.golang.org/protobuf/types/known/structpb"
    34  
    35  	"github.com/polarismesh/polaris/apiserver/xdsserverv3/resource"
    36  	"github.com/polarismesh/polaris/common/model"
    37  	"github.com/polarismesh/polaris/service"
    38  )
    39  
    40  // CDSBuilder .
    41  type CDSBuilder struct {
    42  	client *resource.XDSClient
    43  	svr    service.DiscoverServer
    44  }
    45  
    46  func (cds *CDSBuilder) Init(client *resource.XDSClient, svr service.DiscoverServer) {
    47  	cds.client = client
    48  	cds.svr = svr
    49  }
    50  
    51  const (
    52  	SniTemp = "outbound_.default_.%s.%s.svc.cluster.local"
    53  )
    54  
    55  func (cds *CDSBuilder) Generate(option *resource.BuildOption) (interface{}, error) {
    56  	var clusters []types.Resource
    57  
    58  	// 默认 passthrough cluster
    59  	clusters = append(clusters, resource.PassthroughCluster)
    60  
    61  	inBoundClusters, err := cds.GenerateByDirection(option, corev3.TrafficDirection_INBOUND)
    62  	if err != nil {
    63  		return nil, err
    64  	}
    65  	outBoundClusters, err := cds.GenerateByDirection(option, corev3.TrafficDirection_OUTBOUND)
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  
    70  	clusters = append(clusters, inBoundClusters...)
    71  	clusters = append(clusters, outBoundClusters...)
    72  	return clusters, nil
    73  }
    74  
    75  func (cds *CDSBuilder) GenerateByDirection(option *resource.BuildOption,
    76  	direction corev3.TrafficDirection) ([]types.Resource, error) {
    77  	var clusters []types.Resource
    78  
    79  	selfServiceKey := model.ServiceKey{
    80  		Namespace: cds.client.GetSelfNamespace(),
    81  		Name:      cds.client.GetSelfService(),
    82  	}
    83  
    84  	ignore := func(svcKey model.ServiceKey) bool {
    85  		// 如果是 INBOUND 场景,只需要下发 XDS Sidecar Node 所归属的服务 INBOUND Cluster 规则
    86  		if direction == core.TrafficDirection_INBOUND {
    87  			if cds.client.IsGateway() {
    88  				return true
    89  			}
    90  			if !cds.client.IsGateway() && !selfServiceKey.Equal(&svcKey) {
    91  				return true
    92  			}
    93  		}
    94  		// 如果是网关,则自己的数据不会下发
    95  		if cds.client.IsGateway() && selfServiceKey.Equal(&svcKey) {
    96  			return true
    97  		}
    98  		return false
    99  	}
   100  
   101  	services := option.Services
   102  	// 每一个 polaris service 对应一个 envoy cluster
   103  	for svcKey, svc := range services {
   104  		if ignore(svcKey) {
   105  			continue
   106  		}
   107  		c := cds.makeCluster(svc, direction)
   108  		switch option.TLSMode {
   109  		case resource.TLSModePermissive:
   110  			// In permissive mode, we should use `TLSTransportSocket` to connect to mtls enabled endpoints.
   111  			// Or we use rawbuffer transport for those endpoints which not enabled mtls.
   112  			c.TransportSocketMatches = []*cluster.Cluster_TransportSocketMatch{
   113  				{
   114  					Name:  "tls-mode",
   115  					Match: resource.MTLSTransportSocketMatch,
   116  					TransportSocket: resource.MakeTLSTransportSocket(&tlstrans.UpstreamTlsContext{
   117  						CommonTlsContext: resource.OutboundCommonTLSContext,
   118  						Sni:              fmt.Sprintf(SniTemp, svc.Name, svc.Namespace),
   119  					}),
   120  				},
   121  				{
   122  					Name:  "rawbuffer",
   123  					Match: &structpb.Struct{},
   124  					TransportSocket: &core.TransportSocket{
   125  						Name: wellknown.TransportSocketRawBuffer,
   126  						ConfigType: &core.TransportSocket_TypedConfig{
   127  							TypedConfig: resource.MustNewAny(&rawbuffer.RawBuffer{}),
   128  						},
   129  					},
   130  				},
   131  			}
   132  		case resource.TLSModeStrict:
   133  			// In strict mode, we should only use `TLSTransportSocket` to connect to mtls enabled endpoints.
   134  			c.TransportSocketMatches = []*cluster.Cluster_TransportSocketMatch{
   135  				{
   136  					Name: "tls-mode",
   137  					TransportSocket: resource.MakeTLSTransportSocket(&tlstrans.UpstreamTlsContext{
   138  						CommonTlsContext: resource.OutboundCommonTLSContext,
   139  						Sni:              fmt.Sprintf(SniTemp, svc.Name, svc.Namespace),
   140  					}),
   141  				},
   142  			}
   143  		}
   144  		clusters = append(clusters, c)
   145  	}
   146  	return clusters, nil
   147  }
   148  
   149  func (cds *CDSBuilder) makeCluster(svcInfo *resource.ServiceInfo,
   150  	trafficDirection corev3.TrafficDirection) *cluster.Cluster {
   151  
   152  	name := resource.MakeServiceName(svcInfo.ServiceKey, trafficDirection)
   153  
   154  	return &cluster.Cluster{
   155  		Name:                 name,
   156  		ConnectTimeout:       ptypes.DurationProto(5 * time.Second),
   157  		ClusterDiscoveryType: &cluster.Cluster_Type{Type: cluster.Cluster_EDS},
   158  		EdsClusterConfig: &cluster.Cluster_EdsClusterConfig{
   159  			ServiceName: name,
   160  			EdsConfig: &core.ConfigSource{
   161  				ResourceApiVersion: resourcev3.DefaultAPIVersion,
   162  				ConfigSourceSpecifier: &core.ConfigSource_Ads{
   163  					Ads: &core.AggregatedConfigSource{},
   164  				},
   165  			},
   166  		},
   167  		LbSubsetConfig:   resource.MakeLbSubsetConfig(svcInfo),
   168  		OutlierDetection: resource.MakeOutlierDetection(svcInfo),
   169  		HealthChecks:     resource.MakeHealthCheck(svcInfo),
   170  	}
   171  }