From d5656c3395f7f431bb2d260840787de6606c87ab Mon Sep 17 00:00:00 2001 From: Cybwan Date: Wed, 10 Apr 2024 08:58:56 +0800 Subject: [PATCH] feat: support forward mode. (#221) * fix dns searches. * support forward mode. fix: make codegen Signed-off-by: Lin Yang --- charts/fsm/README.md | 2 +- charts/fsm/values.schema.json | 20 +++ charts/fsm/values.yaml | 2 + .../crds/config.flomesh.io_meshconfigs.yaml | 6 + ...connector.flomesh.io_consulconnectors.yaml | 6 + ...connector.flomesh.io_eurekaconnectors.yaml | 6 + .../connector.flomesh.io_nacosconnectors.yaml | 6 + pkg/apis/config/v1alpha3/mesh_config.go | 8 + pkg/apis/connector/v1alpha1/consul.go | 4 + pkg/apis/connector/v1alpha1/eureka.go | 4 + pkg/apis/connector/v1alpha1/nacos.go | 4 + pkg/apis/connector/v1alpha1/types.go | 8 + pkg/configurator/methods.go | 10 ++ pkg/configurator/mock_client_generated.go | 28 ++++ pkg/configurator/types.go | 6 + pkg/connector/annotation.go | 7 + pkg/connector/cli/config.go | 11 ++ pkg/connector/controller.go | 1 + pkg/connector/ctok/endpoint.go | 46 +++++- pkg/connector/ctok/source.go | 15 ++ pkg/connector/ctok/syncer.go | 7 + pkg/connector/ctok/types.go | 2 + pkg/connector/discovery.go | 2 + pkg/connector/ktoc/source.go | 33 +++- pkg/connector/provider/consul.go | 1 + pkg/gateway/cache/config.go | 141 ++++++------------ pkg/gateway/cache/types.go | 8 +- pkg/gateway/cache/utils.go | 23 +-- .../config/v1alpha3/localdnsproxy.go | 18 +++ .../v1alpha1/consulsyncfromk8sspec.go | 9 ++ .../v1alpha1/eurekasyncfromk8sspec.go | 9 ++ .../v1alpha1/nacossyncfromk8sspec.go | 9 ++ pkg/manager/listeners/client.go | 11 ++ .../providers/pipy/driver/pipy_container.go | 28 +++- 34 files changed, 361 insertions(+), 140 deletions(-) diff --git a/charts/fsm/README.md b/charts/fsm/README.md index 8cd12537f..3f13b5b96 100644 --- a/charts/fsm/README.md +++ b/charts/fsm/README.md @@ -346,7 +346,7 @@ The following table lists the configurable parameters of the fsm chart and their | fsm.injector.resource | object | `{"limits":{"cpu":"1","memory":"512M"},"requests":{"cpu":"0.5","memory":"128M"}}` | Sidecar injector's container resource parameters | | fsm.injector.tolerations | list | `[]` | Node tolerations applied to control plane pods. The specified tolerations allow pods to schedule onto nodes with matching taints. | | fsm.injector.webhookTimeoutSeconds | int | `20` | Mutating webhook timeout | -| fsm.localDNSProxy | object | `{"enable":false,"wildcard":{"enable":false,"ipv4":["127.0.0.2"]}}` | Local DNS Proxy improves the performance of your computer by caching the responses coming from your DNS servers | +| fsm.localDNSProxy | object | `{"enable":false,"searchesWithNamespace":true,"searchesWithTrustDomain":true,"wildcard":{"enable":false,"ipv4":["127.0.0.2"]}}` | Local DNS Proxy improves the performance of your computer by caching the responses coming from your DNS servers | | fsm.localProxyMode | string | `"Localhost"` | Proxy mode for the proxy sidecar. Acceptable values are ['Localhost', 'PodIP'] | | fsm.maxDataPlaneConnections | int | `0` | Sets the max data plane connections allowed for an instance of fsm-controller, set to 0 to not enforce limits | | fsm.meshName | string | `"fsm"` | Identifier for the instance of a service mesh within a cluster | diff --git a/charts/fsm/values.schema.json b/charts/fsm/values.schema.json index c850bc879..76122a36b 100644 --- a/charts/fsm/values.schema.json +++ b/charts/fsm/values.schema.json @@ -1180,6 +1180,8 @@ "description": "Local DNS Proxy improves the performance of your computer by caching the responses coming from your DNS servers.", "required": [ "enable", + "searchesWithNamespace", + "searchesWithTrustDomain", "wildcard" ], "properties": { @@ -1192,6 +1194,24 @@ true ] }, + "searchesWithNamespace": { + "$id": "#/properties/fsm/properties/localDNSProxy/properties/searchesWithNamespace", + "type": "boolean", + "title": "The enable schema for searches with Namespace", + "description": "Indicates whether dns searches contains namespace or not", + "examples": [ + true + ] + }, + "searchesWithTrustDomain": { + "$id": "#/properties/fsm/properties/localDNSProxy/properties/searchesWithTrustDomain", + "type": "boolean", + "title": "The enable schema for searches with trust domain", + "description": "Indicates whether dns searches contains trust domain or not", + "examples": [ + true + ] + }, "primaryUpstreamDNSServerIPAddr": { "$id": "#/properties/fsm/properties/localDNSProxy/properties/primaryUpstreamDNSServerIPAddr", "type": "string", diff --git a/charts/fsm/values.yaml b/charts/fsm/values.yaml index 486ab301e..017cb7b37 100644 --- a/charts/fsm/values.yaml +++ b/charts/fsm/values.yaml @@ -497,6 +497,8 @@ fsm: # -- Local DNS Proxy improves the performance of your computer by caching the responses coming from your DNS servers localDNSProxy: enable: false + searchesWithNamespace: true + searchesWithTrustDomain: true wildcard: enable: false ipv4: diff --git a/cmd/fsm-bootstrap/crds/config.flomesh.io_meshconfigs.yaml b/cmd/fsm-bootstrap/crds/config.flomesh.io_meshconfigs.yaml index c40df00be..0fe3a0ac4 100644 --- a/cmd/fsm-bootstrap/crds/config.flomesh.io_meshconfigs.yaml +++ b/cmd/fsm-bootstrap/crds/config.flomesh.io_meshconfigs.yaml @@ -2061,6 +2061,12 @@ spec: description: PrimaryUpstreamDNSServerIPAddr defines a primary upstream DNS server for local DNS Proxy. type: string + searchesWithNamespace: + default: true + type: boolean + searchesWithTrustDomain: + default: true + type: boolean secondaryUpstreamDNSServerIPAddr: description: SecondaryUpstreamDNSServerIPAddr defines a secondary upstream DNS server for local DNS Proxy. diff --git a/cmd/fsm-bootstrap/crds/connector.flomesh.io_consulconnectors.yaml b/cmd/fsm-bootstrap/crds/connector.flomesh.io_consulconnectors.yaml index 3dae9fbb9..1fc6a0bbb 100644 --- a/cmd/fsm-bootstrap/crds/connector.flomesh.io_consulconnectors.yaml +++ b/cmd/fsm-bootstrap/crds/connector.flomesh.io_consulconnectors.yaml @@ -247,6 +247,12 @@ spec: withGateway: default: false type: boolean + withGatewayMode: + default: forward + enum: + - proxy + - forward + type: string required: - enable type: object diff --git a/cmd/fsm-bootstrap/crds/connector.flomesh.io_eurekaconnectors.yaml b/cmd/fsm-bootstrap/crds/connector.flomesh.io_eurekaconnectors.yaml index 8bb737ee8..f40edafa1 100644 --- a/cmd/fsm-bootstrap/crds/connector.flomesh.io_eurekaconnectors.yaml +++ b/cmd/fsm-bootstrap/crds/connector.flomesh.io_eurekaconnectors.yaml @@ -205,6 +205,12 @@ spec: withGateway: default: false type: boolean + withGatewayMode: + default: forward + enum: + - proxy + - forward + type: string required: - enable type: object diff --git a/cmd/fsm-bootstrap/crds/connector.flomesh.io_nacosconnectors.yaml b/cmd/fsm-bootstrap/crds/connector.flomesh.io_nacosconnectors.yaml index 451cb1f32..32c11627d 100644 --- a/cmd/fsm-bootstrap/crds/connector.flomesh.io_nacosconnectors.yaml +++ b/cmd/fsm-bootstrap/crds/connector.flomesh.io_nacosconnectors.yaml @@ -232,6 +232,12 @@ spec: withGateway: default: false type: boolean + withGatewayMode: + default: forward + enum: + - proxy + - forward + type: string required: - enable type: object diff --git a/pkg/apis/config/v1alpha3/mesh_config.go b/pkg/apis/config/v1alpha3/mesh_config.go index 26ec322fd..dc1d36610 100644 --- a/pkg/apis/config/v1alpha3/mesh_config.go +++ b/pkg/apis/config/v1alpha3/mesh_config.go @@ -109,6 +109,14 @@ type LocalDNSProxy struct { // Enable defines a boolean indicating if the sidecars are enabled for local DNS Proxy. Enable bool `json:"enable"` + // +kubebuilder:default=true + // +optional + SearchesWithNamespace bool `json:"searchesWithNamespace,omitempty"` + + // +kubebuilder:default=true + // +optional + SearchesWithTrustDomain bool `json:"searchesWithTrustDomain,omitempty"` + // PrimaryUpstreamDNSServerIPAddr defines a primary upstream DNS server for local DNS Proxy. // +optional PrimaryUpstreamDNSServerIPAddr string `json:"primaryUpstreamDNSServerIPAddr,omitempty"` diff --git a/pkg/apis/connector/v1alpha1/consul.go b/pkg/apis/connector/v1alpha1/consul.go index b79702151..912fe8d04 100644 --- a/pkg/apis/connector/v1alpha1/consul.go +++ b/pkg/apis/connector/v1alpha1/consul.go @@ -139,6 +139,10 @@ type ConsulSyncFromK8SSpec struct { // +optional WithGateway bool `json:"withGateway,omitempty"` + // +kubebuilder:default=forward + // +optional + WithGatewayMode WithGatewayMode `json:"withGatewayMode,omitempty"` + // +optional ConsulNodeName string `json:"consulNodeName,omitempty"` diff --git a/pkg/apis/connector/v1alpha1/eureka.go b/pkg/apis/connector/v1alpha1/eureka.go index dfdc05441..c89355607 100644 --- a/pkg/apis/connector/v1alpha1/eureka.go +++ b/pkg/apis/connector/v1alpha1/eureka.go @@ -122,6 +122,10 @@ type EurekaSyncFromK8SSpec struct { // +kubebuilder:default=false // +optional WithGateway bool `json:"withGateway,omitempty"` + + // +kubebuilder:default=forward + // +optional + WithGatewayMode WithGatewayMode `json:"withGatewayMode,omitempty"` } // EurekaSpec is the type used to represent the Eureka Connector specification. diff --git a/pkg/apis/connector/v1alpha1/nacos.go b/pkg/apis/connector/v1alpha1/nacos.go index cac080ee0..e4caee9ff 100644 --- a/pkg/apis/connector/v1alpha1/nacos.go +++ b/pkg/apis/connector/v1alpha1/nacos.go @@ -144,6 +144,10 @@ type NacosSyncFromK8SSpec struct { // +kubebuilder:default=false // +optional WithGateway bool `json:"withGateway,omitempty"` + + // +kubebuilder:default=forward + // +optional + WithGatewayMode WithGatewayMode `json:"withGatewayMode,omitempty"` } // NacosSpec is the type used to represent the Nacos Connector specification. diff --git a/pkg/apis/connector/v1alpha1/types.go b/pkg/apis/connector/v1alpha1/types.go index ed9340c14..4958d9185 100644 --- a/pkg/apis/connector/v1alpha1/types.go +++ b/pkg/apis/connector/v1alpha1/types.go @@ -30,6 +30,14 @@ const ( ClusterIP AddrSelector = "ClusterIP" ) +// +kubebuilder:validation:Enum=proxy;forward +type WithGatewayMode string + +const ( + Proxy WithGatewayMode = "proxy" + Forward WithGatewayMode = "forward" +) + type Connector interface { runtime.Object metav1.Object diff --git a/pkg/configurator/methods.go b/pkg/configurator/methods.go index ba12267ac..9ede25f04 100644 --- a/pkg/configurator/methods.go +++ b/pkg/configurator/methods.go @@ -103,6 +103,16 @@ func (c *Client) IsLocalDNSProxyEnabled() bool { return c.getMeshConfig().Spec.Sidecar.LocalDNSProxy.Enable } +// IsSearchesWithNamespace returns whether dns searches contains namespace +func (c *Client) IsSearchesWithNamespace() bool { + return c.getMeshConfig().Spec.Sidecar.LocalDNSProxy.SearchesWithNamespace +} + +// IsSearchesWithTrustDomain returns whether dns searches contains trust domain +func (c *Client) IsSearchesWithTrustDomain() bool { + return c.getMeshConfig().Spec.Sidecar.LocalDNSProxy.SearchesWithTrustDomain +} + // IsWildcardDNSProxyEnabled returns whether wildcard DNS proxy is enabled func (c *Client) IsWildcardDNSProxyEnabled() bool { return c.getMeshConfig().Spec.Sidecar.LocalDNSProxy.Wildcard.Enable diff --git a/pkg/configurator/mock_client_generated.go b/pkg/configurator/mock_client_generated.go index 2372268a3..afd69485c 100644 --- a/pkg/configurator/mock_client_generated.go +++ b/pkg/configurator/mock_client_generated.go @@ -1075,6 +1075,34 @@ func (mr *MockConfiguratorMockRecorder) IsRemoteLoggingEnabled() *gomock.Call { return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsRemoteLoggingEnabled", reflect.TypeOf((*MockConfigurator)(nil).IsRemoteLoggingEnabled)) } +// IsSearchesWithNamespace mocks base method. +func (m *MockConfigurator) IsSearchesWithNamespace() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsSearchesWithNamespace") + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsSearchesWithNamespace indicates an expected call of IsSearchesWithNamespace. +func (mr *MockConfiguratorMockRecorder) IsSearchesWithNamespace() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSearchesWithNamespace", reflect.TypeOf((*MockConfigurator)(nil).IsSearchesWithNamespace)) +} + +// IsSearchesWithTrustDomain mocks base method. +func (m *MockConfigurator) IsSearchesWithTrustDomain() bool { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "IsSearchesWithTrustDomain") + ret0, _ := ret[0].(bool) + return ret0 +} + +// IsSearchesWithTrustDomain indicates an expected call of IsSearchesWithTrustDomain. +func (mr *MockConfiguratorMockRecorder) IsSearchesWithTrustDomain() *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsSearchesWithTrustDomain", reflect.TypeOf((*MockConfigurator)(nil).IsSearchesWithTrustDomain)) +} + // IsServiceLBEnabled mocks base method. func (m *MockConfigurator) IsServiceLBEnabled() bool { m.ctrl.T.Helper() diff --git a/pkg/configurator/types.go b/pkg/configurator/types.go index 789a3fd93..d558c565d 100644 --- a/pkg/configurator/types.go +++ b/pkg/configurator/types.go @@ -57,6 +57,12 @@ type Configurator interface { // IsLocalDNSProxyEnabled returns whether local DNS proxy is enabled IsLocalDNSProxyEnabled() bool + // IsSearchesWithNamespace returns whether dns searches contains namespace + IsSearchesWithNamespace() bool + + // IsSearchesWithTrustDomain returns whether dns searches contains trust domain + IsSearchesWithTrustDomain() bool + // IsWildcardDNSProxyEnabled returns whether wildcard DNS proxy is enabled IsWildcardDNSProxyEnabled() bool diff --git a/pkg/connector/annotation.go b/pkg/connector/annotation.go index 5635ba8eb..92f14dbe2 100644 --- a/pkg/connector/annotation.go +++ b/pkg/connector/annotation.go @@ -14,6 +14,7 @@ var ( CloudK8SRefValue = "fsm.connector.service.k8s.ref.name" CloudK8SNodeName = "fsm.connector.service.k8s.node.name" CloudK8SPort = "fsm.connector.service.k8s.port" + CloudK8SVia = "fsm.connector.service.via.gateway" ) const ( @@ -29,6 +30,12 @@ const ( // AnnotationCloudServiceInheritedClusterID defines cloud service cluster id annotation AnnotationCloudServiceInheritedClusterID = "flomesh.io/cloud-service-inherited-cluster-id" + // AnnotationCloudServiceViaGateway defines cloud service via gateway annotation + AnnotationCloudServiceViaGateway = "flomesh.io/cloud-service-via-gateway" + + // AnnotationCloudServiceClusterSet defines cloud service cluster set annotation + AnnotationCloudServiceClusterSet = "flomesh.io/cloud-service-cluster-set" + // AnnotationMeshEndpointAddr defines mesh endpoint addr annotation AnnotationMeshEndpointAddr = "flomesh.io/cloud-endpoint-addr" ) diff --git a/pkg/connector/cli/config.go b/pkg/connector/cli/config.go index 246a4d926..a8cfbe7c5 100644 --- a/pkg/connector/cli/config.go +++ b/pkg/connector/cli/config.go @@ -122,6 +122,8 @@ type config struct { withGateway bool + withGatewayMode ctv1.WithGatewayMode + consulCfg struct { // The Consul node name to register services with. consulNodeName string @@ -373,6 +375,12 @@ func (c *config) GetK2CWithGateway() bool { return c.k2cCfg.withGateway } +func (c *config) GetK2CWithGatewayMode() ctv1.WithGatewayMode { + c.flock.RLock() + defer c.flock.RUnlock() + return c.k2cCfg.withGatewayMode +} + func (c *config) GetConsulNodeName() string { c.flock.RLock() defer c.flock.RUnlock() @@ -664,6 +672,7 @@ func (c *client) initNacosConnectorConfig(spec ctv1.NacosSpec) { c.k2cCfg.allowK8sNamespacesSet = ToSet(spec.SyncFromK8S.AllowK8sNamespaces) c.k2cCfg.denyK8sNamespacesSet = ToSet(spec.SyncFromK8S.DenyK8sNamespaces) c.k2cCfg.withGateway = spec.SyncFromK8S.WithGateway + c.k2cCfg.withGatewayMode = spec.SyncFromK8S.WithGatewayMode c.k2cCfg.nacosCfg.clusterId = spec.SyncFromK8S.ClusterId c.k2cCfg.nacosCfg.groupId = spec.SyncFromK8S.GroupId @@ -704,6 +713,7 @@ func (c *client) initEurekaConnectorConfig(spec ctv1.EurekaSpec) { c.k2cCfg.allowK8sNamespacesSet = ToSet(spec.SyncFromK8S.AllowK8sNamespaces) c.k2cCfg.denyK8sNamespacesSet = ToSet(spec.SyncFromK8S.DenyK8sNamespaces) c.k2cCfg.withGateway = spec.SyncFromK8S.WithGateway + c.k2cCfg.withGatewayMode = spec.SyncFromK8S.WithGatewayMode c.limiter.SetLimit(rate.Limit(spec.Limiter.Limit)) c.limiter.SetBurst(int(spec.Limiter.Limit)) @@ -746,6 +756,7 @@ func (c *client) initConsulConnectorConfig(spec ctv1.ConsulSpec) { c.k2cCfg.allowK8sNamespacesSet = ToSet(spec.SyncFromK8S.AllowK8sNamespaces) c.k2cCfg.denyK8sNamespacesSet = ToSet(spec.SyncFromK8S.DenyK8sNamespaces) c.k2cCfg.withGateway = spec.SyncFromK8S.WithGateway + c.k2cCfg.withGatewayMode = spec.SyncFromK8S.WithGatewayMode c.k2cCfg.consulCfg.consulNodeName = spec.SyncFromK8S.ConsulNodeName c.k2cCfg.consulCfg.consulEnableNamespaces = spec.SyncFromK8S.ConsulEnableNamespaces diff --git a/pkg/connector/controller.go b/pkg/connector/controller.go index 6d0de0bb9..471ecd95a 100644 --- a/pkg/connector/controller.go +++ b/pkg/connector/controller.go @@ -74,6 +74,7 @@ type ConnectController interface { GetDenyK8SNamespaceSet() mapset.Set GetK2CWithGateway() bool + GetK2CWithGatewayMode() ctv1.WithGatewayMode GetConsulNodeName() string GetConsulEnableNamespaces() bool diff --git a/pkg/connector/ctok/endpoint.go b/pkg/connector/ctok/endpoint.go index bb05ff94c..04492dab4 100644 --- a/pkg/connector/ctok/endpoint.go +++ b/pkg/connector/ctok/endpoint.go @@ -78,6 +78,12 @@ func (t *endpointsResource) Upsert(key string, raw interface{}) error { if clusterId, clusterIDExists := service.Annotations[connector.AnnotationCloudServiceInheritedClusterID]; clusterIDExists { endpoints.Annotations[connector.AnnotationCloudServiceInheritedClusterID] = clusterId } + if clusterSet, clusterSetyExists := service.Annotations[connector.AnnotationCloudServiceClusterSet]; clusterSetyExists { + endpoints.Annotations[connector.AnnotationCloudServiceClusterSet] = clusterSet + } + if viaGateway, viaGatewayExists := service.Annotations[connector.AnnotationCloudServiceViaGateway]; viaGatewayExists { + endpoints.Annotations[connector.AnnotationCloudServiceViaGateway] = viaGateway + } if t.controller.GetC2KWithGateway() { if syncer.discClient.IsInternalServices() { endpoints.Annotations[connector.AnnotationMeshServiceInternalSync] = True @@ -164,15 +170,34 @@ func (t *endpointsResource) updateGatewayEndpointSlice(ctx context.Context, endp } var ports []discoveryv1.EndpointPort var epts []discoveryv1.Endpoint + var viaAddr string + var viaPort int32 + if viaGateway, viaGatewayExists := endpointsDup.Annotations[connector.AnnotationCloudServiceViaGateway]; viaGatewayExists { + if segs := strings.Split(viaGateway, ":"); len(segs) == 2 { + if port, convErr := strconv.Atoi(segs[1]); convErr == nil { + viaPort = int32(port & 0xFFFF) + viaAddr = segs[0] + } + } + } for _, subsets := range endpointsDup.Subsets { for _, port := range subsets.Ports { shadow := port - ports = append(ports, discoveryv1.EndpointPort{ - Name: &shadow.Name, - Protocol: &shadow.Protocol, - Port: &shadow.Port, - AppProtocol: shadow.AppProtocol, - }) + if viaPort > 0 { + ports = append(ports, discoveryv1.EndpointPort{ + Name: &shadow.Name, + Protocol: &shadow.Protocol, + Port: &viaPort, + AppProtocol: shadow.AppProtocol, + }) + } else { + ports = append(ports, discoveryv1.EndpointPort{ + Name: &shadow.Name, + Protocol: &shadow.Protocol, + Port: &shadow.Port, + AppProtocol: shadow.AppProtocol, + }) + } } if len(subsets.Addresses) > 0 { var ready = true @@ -182,9 +207,14 @@ func (t *endpointsResource) updateGatewayEndpointSlice(ctx context.Context, endp Ready: &ready, }, } - for _, addr := range subsets.Addresses { - addrs = append(addrs, addr.IP) + if len(viaAddr) > 0 { + addrs = append(addrs, viaAddr) + } else { + for _, addr := range subsets.Addresses { + addrs = append(addrs, addr.IP) + } } + ept.Addresses = addrs epts = append(epts, ept) } diff --git a/pkg/connector/ctok/source.go b/pkg/connector/ctok/source.go index 63ed542a1..afe24af00 100644 --- a/pkg/connector/ctok/source.go +++ b/pkg/connector/ctok/source.go @@ -130,6 +130,21 @@ func (s *CtoKSource) Aggregate(ctx context.Context, svcName MicroSvcName) map[Mi svcMeta.Addresses[MicroEndpointAddr(instance.Address)] = 1 svcMeta.ClusterId = instance.ClusterId svcMeta.HealthCheck = instance.HealthCheck + if viaGateway, ok := instance.Meta[connector.CloudK8SVia]; ok { + if viaGateway, str := viaGateway.(string); str { + if len(viaGateway) > 0 { + svcMeta.ViaGateway = viaGateway + } + } + } + if clusterSet, ok := instance.Meta[connector.ClusterSetKey]; ok { + if clusterSet, str := clusterSet.(string); str { + if len(clusterSet) > 0 { + svcMeta.ClusterSet = clusterSet + svcMeta.ClusterId = clusterSet + } + } + } } } return svcMetaMap diff --git a/pkg/connector/ctok/syncer.go b/pkg/connector/ctok/syncer.go index f0f8ee9c9..fef35be4a 100644 --- a/pkg/connector/ctok/syncer.go +++ b/pkg/connector/ctok/syncer.go @@ -368,6 +368,13 @@ func (s *CtoKSyncer) fillService(svcMeta *MicroSvcMeta, createSvc *apiv1.Service } sort.Ints(ports) createSvc.ObjectMeta.Annotations[connector.AnnotationCloudServiceInheritedClusterID] = svcMeta.ClusterId + if len(svcMeta.ViaGateway) > 0 { + createSvc.ObjectMeta.Annotations[connector.AnnotationCloudServiceViaGateway] = svcMeta.ViaGateway + } + if len(svcMeta.ViaGateway) > 0 && !strings.EqualFold(svcMeta.ClusterSet, s.controller.GetClusterSet()) { + createSvc.ObjectMeta.Annotations[connector.AnnotationCloudServiceClusterSet] = svcMeta.ClusterSet + delete(createSvc.ObjectMeta.Annotations, connector.AnnotationMeshServiceInternalSync) + } for addr := range svcMeta.Addresses { createSvc.ObjectMeta.Annotations[fmt.Sprintf("%s-%d", connector.AnnotationMeshEndpointAddr, utils.IP2Int(addr.To4()))] = fmt.Sprintf("%v", ports) } diff --git a/pkg/connector/ctok/types.go b/pkg/connector/ctok/types.go index 411446e56..38137ef36 100644 --- a/pkg/connector/ctok/types.go +++ b/pkg/connector/ctok/types.go @@ -31,6 +31,8 @@ type MicroSvcMeta struct { Ports map[MicroSvcPort]MicroSvcAppProtocol Addresses map[MicroEndpointAddr]int ClusterId string + ViaGateway string + ClusterSet string HealthCheck bool } diff --git a/pkg/connector/discovery.go b/pkg/connector/discovery.go index 00fbe00ba..4aa3bc408 100644 --- a/pkg/connector/discovery.go +++ b/pkg/connector/discovery.go @@ -91,6 +91,8 @@ type AgentService struct { Address string HTTPPort int GRPCPort int + ViaAddress string + ViaPort int Weights AgentWeights Tags []string Meta map[string]interface{} diff --git a/pkg/connector/ktoc/source.go b/pkg/connector/ktoc/source.go index 41aa5e281..374c55ce9 100644 --- a/pkg/connector/ktoc/source.go +++ b/pkg/connector/ktoc/source.go @@ -219,6 +219,12 @@ func (t *KtoCSource) shouldSync(svc *corev1.Service) bool { return false } + if clusterSet, ok := svc.Annotations[connector.AnnotationCloudServiceClusterSet]; ok { + if len(clusterSet) > 0 && !strings.EqualFold(clusterSet, t.controller.GetClusterSet()) { + return false + } + } + raw, ok := svc.Annotations[connector.AnnotationServiceSyncK8sToCloud] if !ok { // If there is no explicit value, then set it to our current default. @@ -659,13 +665,13 @@ func (t *KtoCSource) registerServiceInstance( if httpPort == 0 && strings.EqualFold(string(p.Protocol), strings.ToUpper(constants.ProtocolTCP)) && p.AppProtocol != nil && - strings.EqualFold(string(*p.AppProtocol), strings.ToUpper(constants.ProtocolHTTP)) { + strings.EqualFold(*p.AppProtocol, strings.ToUpper(constants.ProtocolHTTP)) { httpPort = int(p.Port) } if grpcPort == 0 && strings.EqualFold(string(p.Protocol), strings.ToUpper(constants.ProtocolTCP)) && p.AppProtocol != nil && - strings.EqualFold(string(*p.AppProtocol), strings.ToUpper(constants.ProtocolGRPC)) { + strings.EqualFold(*p.AppProtocol, strings.ToUpper(constants.ProtocolGRPC)) { grpcPort = int(p.Port) } if httpPort > 0 && grpcPort > 0 { @@ -675,14 +681,22 @@ func (t *KtoCSource) registerServiceInstance( } for _, subsetAddr := range subset.Addresses { var addr string + var viaAddr string + var viaPort int addr, httpPort = t.chooseServiceAddrPort(key, httpPort, subsetAddr, useHostname) if len(addr) == 0 { continue } if t.controller.GetK2CWithGateway() { - addr = t.controller.GetViaIngressAddr() - httpPort = int(t.controller.GetViaIngressHTTPPort()) + if t.controller.GetK2CWithGatewayMode() == ctv1.Forward { + viaAddr = t.controller.GetViaIngressAddr() + viaPort = int(t.controller.GetViaIngressHTTPPort()) + } + if t.controller.GetK2CWithGatewayMode() == ctv1.Proxy { + addr = t.controller.GetViaIngressAddr() + httpPort = int(t.controller.GetViaIngressHTTPPort()) + } } // Its not clear whether K8S guarantees ready addresses to @@ -694,7 +708,7 @@ func (t *KtoCSource) registerServiceInstance( seen[addr] = struct{}{} r := baseNode - r.Service = t.bindService(baseService, baseService.Service, addr, httpPort, grpcPort) + r.Service = t.bindService(baseService, baseService.Service, addr, httpPort, grpcPort, viaAddr, viaPort) // Deepcopy baseService.Meta into r.RegisteredInstances.Meta as baseService is shared // between all nodes of a service for k, v := range baseService.Meta { @@ -745,13 +759,20 @@ func (t *KtoCSource) chooseServiceAddrPort(key string, port int, subsetAddr core return addr, httpPort } -func (t *KtoCSource) bindService(baseService connector.AgentService, service, addr string, httpPort, grpcPort int) *connector.AgentService { +func (t *KtoCSource) bindService(baseService connector.AgentService, + service, addr string, httpPort, grpcPort int, + viaAddr string, viaPort int) *connector.AgentService { rs := baseService rs.ID = t.controller.GetServiceInstanceID(service, addr, httpPort, grpcPort) rs.Address = addr rs.HTTPPort = httpPort rs.GRPCPort = grpcPort + rs.ViaAddress = viaAddr + rs.ViaPort = viaPort rs.Meta = make(map[string]interface{}) + if len(viaAddr) > 0 && viaPort > 0 { + rs.Meta[connector.CloudK8SVia] = fmt.Sprintf("%s:%d", viaAddr, viaPort) + } return &rs } diff --git a/pkg/connector/provider/consul.go b/pkg/connector/provider/consul.go index 9f140634e..878f161da 100644 --- a/pkg/connector/provider/consul.go +++ b/pkg/connector/provider/consul.go @@ -329,6 +329,7 @@ func GetConsulDiscoveryClient(connectController connector.ConnectController) (*C connector.CloudK8SRefValue = "fsm_connector_service_k8s_ref_name" connector.CloudK8SNodeName = "fsm_connector_service_k8s_node_name" connector.CloudK8SPort = "fsm_connector_service_k8s_port" + connector.CloudK8SVia = "fsm_connector_service_via_gateway" return consulDiscoveryClient, nil } diff --git a/pkg/gateway/cache/config.go b/pkg/gateway/cache/config.go index cb61d9d82..63ba6e2db 100644 --- a/pkg/gateway/cache/config.go +++ b/pkg/gateway/cache/config.go @@ -3,8 +3,6 @@ package cache import ( "fmt" - "k8s.io/apimachinery/pkg/util/sets" - gwv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" "k8s.io/utils/pointer" @@ -295,23 +293,60 @@ func (c *GatewayCache) serviceConfigs(services map[string]serviceInfo) map[strin continue } - if svc.Spec.Type == corev1.ServiceTypeExternalName { - log.Warn().Msgf("Type of Service %s is %s, will be ignored", svcKey, corev1.ServiceTypeExternalName) + selector, err := metav1.LabelSelectorAsSelector(&metav1.LabelSelector{ + MatchLabels: map[string]string{ + constants.KubernetesEndpointSliceServiceNameLabel: svc.Name, + }, + }) + if err != nil { + log.Error().Msgf("Failed to convert LabelSelector to Selector: %s", err) + continue + } + + endpointSliceList, err := c.informers.GetListers().EndpointSlice.EndpointSlices(svc.Namespace).List(selector) + if err != nil { + log.Error().Msgf("Failed to list EndpointSlice of Service %s: %s", svcKey, err) + continue + } + + if len(endpointSliceList) == 0 { continue } - upstreams := c.upstreams(svcInfo, svc) + svcPort, err := getServicePort(svc, svcInfo.svcPortName.Port) + if err != nil { + log.Error().Msgf("Failed to get ServicePort: %s", err) + continue + } - if len(upstreams) == 0 { + filteredSlices := filterEndpointSliceList(endpointSliceList, svcPort) + if len(filteredSlices) == 0 { + log.Error().Msgf("no valid endpoints found for Service %s and port %+v", svcKey, svcPort) continue } + endpointSet := make(map[endpointInfo]struct{}) + for _, eps := range filteredSlices { + for _, endpoint := range eps.Endpoints { + if !isEndpointReady(endpoint) { + continue + } + endpointPort := findPort(eps.Ports, svcPort) + + for _, address := range endpoint.Addresses { + ep := endpointInfo{address: address, port: endpointPort} + endpointSet[ep] = struct{}{} + } + } + } + svcCfg := &fgw.ServiceConfig{ - //Filters: referredSvcInfo.filters, + //Filters: svcInfo.filters, Endpoints: make(map[string]fgw.Endpoint), } - for _, hostport := range upstreams { + for ep := range endpointSet { + hostport := fmt.Sprintf("%s:%d", ep.address, ep.port) svcCfg.Endpoints[hostport] = fgw.Endpoint{ Weight: 1, } @@ -327,96 +362,6 @@ func (c *GatewayCache) serviceConfigs(services map[string]serviceInfo) map[strin return configs } -func (c *GatewayCache) upstreams(referredSvcInfo serviceInfo, svc *corev1.Service) []string { - if svc.Spec.ClusterIP == corev1.ClusterIPNone && len(svc.Spec.Selector) == 0 { - return c.getEndpointsOfHeadlessServiceWithoutSelector(referredSvcInfo, svc) - } - - return c.upstreamsBySelector(referredSvcInfo, svc) -} - -func (c *GatewayCache) getEndpointsOfHeadlessServiceWithoutSelector(referredSvcInfo serviceInfo, svc *corev1.Service) []string { - endpoints, err := c.informers.GetListers().Endpoints.Endpoints(svc.Namespace).Get(svc.Name) - if err != nil { - log.Error().Msgf("Failed to get Endpoints of Service %s: %s", svc.Name, err) - return nil - } - - if len(endpoints.Subsets) == 0 { - return nil - } - - svcPort, err := getServicePort(svc, referredSvcInfo.svcPortName.Port) - if err != nil { - log.Error().Msgf("Failed to get ServicePort: %s", err) - return nil - } - - endpointSet := sets.New[string]() - for _, subset := range endpoints.Subsets { - if endpointPort := findEndpointPort(subset.Ports, svcPort); endpointPort > 0 && endpointPort <= 65535 { - for _, address := range subset.Addresses { - endpointSet.Insert(fmt.Sprintf("%s:%d", address.IP, endpointPort)) - } - } - } - - return sets.List(endpointSet) -} - -func (c *GatewayCache) upstreamsBySelector(referredSvcInfo serviceInfo, svc *corev1.Service) []string { - svcKey := referredSvcInfo.svcPortName.NamespacedName - - selector, err := metav1.LabelSelectorAsSelector(&metav1.LabelSelector{ - MatchLabels: map[string]string{ - constants.KubernetesEndpointSliceServiceNameLabel: svc.Name, - }, - }) - if err != nil { - log.Error().Msgf("Failed to convert LabelSelector to Selector: %s", err) - return nil - } - - endpointSliceList, err := c.informers.GetListers().EndpointSlice.EndpointSlices(svc.Namespace).List(selector) - if err != nil { - log.Error().Msgf("Failed to list EndpointSlice of Service %s: %s", svcKey, err) - return nil - } - - if len(endpointSliceList) == 0 { - return nil - } - - svcPort, err := getServicePort(svc, referredSvcInfo.svcPortName.Port) - if err != nil { - log.Error().Msgf("Failed to get ServicePort: %s", err) - return nil - } - - filteredSlices := filterEndpointSliceList(endpointSliceList, svcPort) - if len(filteredSlices) == 0 { - log.Error().Msgf("no valid endpoints found for Service %s and port %+v", svcKey, svcPort) - return nil - } - - endpointSet := sets.New[string]() - for _, eps := range filteredSlices { - for _, endpoint := range eps.Endpoints { - if !isEndpointReady(endpoint) { - continue - } - - if endpointPort := findEndpointSlicePort(eps.Ports, svcPort); endpointPort > 0 && endpointPort <= 65535 { - for _, address := range endpoint.Addresses { - endpointSet.Insert(fmt.Sprintf("%s:%d", address, endpointPort)) - } - } - } - } - - return sets.List(endpointSet) -} - func (c *GatewayCache) chains() fgw.Chains { if c.cfg.GetFeatureFlags().EnableGatewayAgentService { return fgw.Chains{ diff --git a/pkg/gateway/cache/types.go b/pkg/gateway/cache/types.go index bc56654fe..f4277cd33 100644 --- a/pkg/gateway/cache/types.go +++ b/pkg/gateway/cache/types.go @@ -125,10 +125,10 @@ type serviceInfo struct { //filters []routecfg.Filter } -//type endpointInfo struct { -// address string -// port int32 -//} +type endpointInfo struct { + address string + port int32 +} type globalPolicyAttachments struct { rateLimits map[gwpkg.PolicyMatchType][]gwpav1alpha1.RateLimitPolicy diff --git a/pkg/gateway/cache/utils.go b/pkg/gateway/cache/utils.go index 86a07fcc1..42b55efd6 100644 --- a/pkg/gateway/cache/utils.go +++ b/pkg/gateway/cache/utils.go @@ -507,10 +507,10 @@ func ignoreEndpointSlice(endpointSlice *discoveryv1.EndpointSlice, port corev1.S } // ignore endpoint slices that don't have a matching port. - return findEndpointSlicePort(endpointSlice.Ports, port) == 0 + return findPort(endpointSlice.Ports, port) == 0 } -func findEndpointSlicePort(ports []discoveryv1.EndpointPort, svcPort corev1.ServicePort) int32 { +func findPort(ports []discoveryv1.EndpointPort, svcPort corev1.ServicePort) int32 { portName := svcPort.Name for _, p := range ports { if p.Port == nil { @@ -525,25 +525,6 @@ func findEndpointSlicePort(ports []discoveryv1.EndpointPort, svcPort corev1.Serv return 0 } -func findEndpointPort(ports []corev1.EndpointPort, svcPort corev1.ServicePort) int32 { - for i, epPort := range ports { - if svcPort.Name == "" { - // port.Name is optional if there is only one port - return epPort.Port - } - - if svcPort.Name == epPort.Name { - return epPort.Port - } - - if i == len(ports)-1 && svcPort.TargetPort.Type == intstr.Int { - return svcPort.TargetPort.IntVal - } - } - - return 0 -} - func getDefaultPort(svcPort corev1.ServicePort) int32 { switch svcPort.TargetPort.Type { case intstr.Int: diff --git a/pkg/gen/client/config/applyconfiguration/config/v1alpha3/localdnsproxy.go b/pkg/gen/client/config/applyconfiguration/config/v1alpha3/localdnsproxy.go index 57d47b798..50ac425ee 100644 --- a/pkg/gen/client/config/applyconfiguration/config/v1alpha3/localdnsproxy.go +++ b/pkg/gen/client/config/applyconfiguration/config/v1alpha3/localdnsproxy.go @@ -19,6 +19,8 @@ package v1alpha3 // with apply. type LocalDNSProxyApplyConfiguration struct { Enable *bool `json:"enable,omitempty"` + SearchesWithNamespace *bool `json:"searchesWithNamespace,omitempty"` + SearchesWithTrustDomain *bool `json:"searchesWithTrustDomain,omitempty"` PrimaryUpstreamDNSServerIPAddr *string `json:"primaryUpstreamDNSServerIPAddr,omitempty"` SecondaryUpstreamDNSServerIPAddr *string `json:"secondaryUpstreamDNSServerIPAddr,omitempty"` Wildcard *WildcardDNApplyConfiguration `json:"wildcard,omitempty"` @@ -39,6 +41,22 @@ func (b *LocalDNSProxyApplyConfiguration) WithEnable(value bool) *LocalDNSProxyA return b } +// WithSearchesWithNamespace sets the SearchesWithNamespace field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the SearchesWithNamespace field is set to the value of the last call. +func (b *LocalDNSProxyApplyConfiguration) WithSearchesWithNamespace(value bool) *LocalDNSProxyApplyConfiguration { + b.SearchesWithNamespace = &value + return b +} + +// WithSearchesWithTrustDomain sets the SearchesWithTrustDomain field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the SearchesWithTrustDomain field is set to the value of the last call. +func (b *LocalDNSProxyApplyConfiguration) WithSearchesWithTrustDomain(value bool) *LocalDNSProxyApplyConfiguration { + b.SearchesWithTrustDomain = &value + return b +} + // WithPrimaryUpstreamDNSServerIPAddr sets the PrimaryUpstreamDNSServerIPAddr field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the PrimaryUpstreamDNSServerIPAddr field is set to the value of the last call. diff --git a/pkg/gen/client/connector/applyconfiguration/connector/v1alpha1/consulsyncfromk8sspec.go b/pkg/gen/client/connector/applyconfiguration/connector/v1alpha1/consulsyncfromk8sspec.go index a25b8acfd..2e926a982 100644 --- a/pkg/gen/client/connector/applyconfiguration/connector/v1alpha1/consulsyncfromk8sspec.go +++ b/pkg/gen/client/connector/applyconfiguration/connector/v1alpha1/consulsyncfromk8sspec.go @@ -36,6 +36,7 @@ type ConsulSyncFromK8SSpecApplyConfiguration struct { AllowK8sNamespaces []string `json:"allowK8sNamespaces,omitempty"` DenyK8sNamespaces []string `json:"denyK8sNamespaces,omitempty"` WithGateway *bool `json:"withGateway,omitempty"` + WithGatewayMode *v1alpha1.WithGatewayMode `json:"withGatewayMode,omitempty"` ConsulNodeName *string `json:"consulNodeName,omitempty"` ConsulEnableNamespaces *bool `json:"consulEnableNamespaces,omitempty"` ConsulDestinationNamespace *string `json:"consulDestinationNamespace,omitempty"` @@ -173,6 +174,14 @@ func (b *ConsulSyncFromK8SSpecApplyConfiguration) WithWithGateway(value bool) *C return b } +// WithWithGatewayMode sets the WithGatewayMode field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the WithGatewayMode field is set to the value of the last call. +func (b *ConsulSyncFromK8SSpecApplyConfiguration) WithWithGatewayMode(value v1alpha1.WithGatewayMode) *ConsulSyncFromK8SSpecApplyConfiguration { + b.WithGatewayMode = &value + return b +} + // WithConsulNodeName sets the ConsulNodeName field in the declarative configuration to the given value // and returns the receiver, so that objects can be built by chaining "With" function invocations. // If called multiple times, the ConsulNodeName field is set to the value of the last call. diff --git a/pkg/gen/client/connector/applyconfiguration/connector/v1alpha1/eurekasyncfromk8sspec.go b/pkg/gen/client/connector/applyconfiguration/connector/v1alpha1/eurekasyncfromk8sspec.go index 08df08fa0..a0afa1c53 100644 --- a/pkg/gen/client/connector/applyconfiguration/connector/v1alpha1/eurekasyncfromk8sspec.go +++ b/pkg/gen/client/connector/applyconfiguration/connector/v1alpha1/eurekasyncfromk8sspec.go @@ -35,6 +35,7 @@ type EurekaSyncFromK8SSpecApplyConfiguration struct { AllowK8sNamespaces []string `json:"allowK8sNamespaces,omitempty"` DenyK8sNamespaces []string `json:"denyK8sNamespaces,omitempty"` WithGateway *bool `json:"withGateway,omitempty"` + WithGatewayMode *v1alpha1.WithGatewayMode `json:"withGatewayMode,omitempty"` } // EurekaSyncFromK8SSpecApplyConfiguration constructs an declarative configuration of the EurekaSyncFromK8SSpec type for use with @@ -155,3 +156,11 @@ func (b *EurekaSyncFromK8SSpecApplyConfiguration) WithWithGateway(value bool) *E b.WithGateway = &value return b } + +// WithWithGatewayMode sets the WithGatewayMode field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the WithGatewayMode field is set to the value of the last call. +func (b *EurekaSyncFromK8SSpecApplyConfiguration) WithWithGatewayMode(value v1alpha1.WithGatewayMode) *EurekaSyncFromK8SSpecApplyConfiguration { + b.WithGatewayMode = &value + return b +} diff --git a/pkg/gen/client/connector/applyconfiguration/connector/v1alpha1/nacossyncfromk8sspec.go b/pkg/gen/client/connector/applyconfiguration/connector/v1alpha1/nacossyncfromk8sspec.go index 2b6531aa4..89e344521 100644 --- a/pkg/gen/client/connector/applyconfiguration/connector/v1alpha1/nacossyncfromk8sspec.go +++ b/pkg/gen/client/connector/applyconfiguration/connector/v1alpha1/nacossyncfromk8sspec.go @@ -37,6 +37,7 @@ type NacosSyncFromK8SSpecApplyConfiguration struct { AllowK8sNamespaces []string `json:"allowK8sNamespaces,omitempty"` DenyK8sNamespaces []string `json:"denyK8sNamespaces,omitempty"` WithGateway *bool `json:"withGateway,omitempty"` + WithGatewayMode *v1alpha1.WithGatewayMode `json:"withGatewayMode,omitempty"` } // NacosSyncFromK8SSpecApplyConfiguration constructs an declarative configuration of the NacosSyncFromK8SSpec type for use with @@ -173,3 +174,11 @@ func (b *NacosSyncFromK8SSpecApplyConfiguration) WithWithGateway(value bool) *Na b.WithGateway = &value return b } + +// WithWithGatewayMode sets the WithGatewayMode field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the WithGatewayMode field is set to the value of the last call. +func (b *NacosSyncFromK8SSpecApplyConfiguration) WithWithGatewayMode(value v1alpha1.WithGatewayMode) *NacosSyncFromK8SSpecApplyConfiguration { + b.WithGatewayMode = &value + return b +} diff --git a/pkg/manager/listeners/client.go b/pkg/manager/listeners/client.go index a506a50a2..1b31e66bc 100644 --- a/pkg/manager/listeners/client.go +++ b/pkg/manager/listeners/client.go @@ -136,6 +136,17 @@ func (c *client) IsLocalDNSProxyEnabled() bool { //TODO implement me panic("implement me") } + +func (c *client) IsSearchesWithNamespace() bool { + //TODO implement me + panic("implement me") +} + +func (c *client) IsSearchesWithTrustDomain() bool { + //TODO implement me + panic("implement me") +} + func (c *client) IsWildcardDNSProxyEnabled() bool { //TODO implement me panic("implement me") diff --git a/pkg/sidecar/providers/pipy/driver/pipy_container.go b/pkg/sidecar/providers/pipy/driver/pipy_container.go index 63302a619..c790c4cf6 100644 --- a/pkg/sidecar/providers/pipy/driver/pipy_container.go +++ b/pkg/sidecar/providers/pipy/driver/pipy_container.go @@ -153,10 +153,34 @@ func getPipySidecarContainerSpec(injCtx *driver.InjectorContext, pod *corev1.Pod pod.Spec.DNSPolicy = "None" trustDomain := injCtx.CertManager.GetTrustDomain() - ndots := "5" + ndots := "1" + searches := make([]string, 0) + if injCtx.Configurator.IsSearchesWithTrustDomain() { + ndots = "4" + if injCtx.Configurator.IsSearchesWithNamespace() { + if len(pod.Namespace) > 0 { + ndots = "5" + searches = append(searches, fmt.Sprintf("%s.svc.%s", pod.Namespace, trustDomain)) + } else if len(injCtx.PodNamespace) > 0 { + ndots = "5" + searches = append(searches, fmt.Sprintf("%s.svc.%s", injCtx.PodNamespace, trustDomain)) + } + } + searches = append(searches, fmt.Sprintf("svc.%s", trustDomain)) + searches = append(searches, trustDomain) + } else if injCtx.Configurator.IsSearchesWithNamespace() { + if len(pod.Namespace) > 0 { + ndots = "2" + searches = append(searches, pod.Namespace) + } else if len(injCtx.PodNamespace) > 0 { + ndots = "2" + searches = append(searches, injCtx.PodNamespace) + } + } + pod.Spec.DNSConfig = &corev1.PodDNSConfig{ Nameservers: []string{"127.0.0.153"}, - Searches: []string{fmt.Sprintf("%s.svc.%s", pod.Namespace, trustDomain), fmt.Sprintf("svc.%s", trustDomain), trustDomain}, + Searches: searches, Options: []corev1.PodDNSConfigOption{ {Name: "ndots", Value: &ndots}, },