Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: automatically detect dns lookup family for cp cluster #4275

5 changes: 5 additions & 0 deletions pkg/xds/bootstrap/export_template.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package bootstrap

var (
DnsLookupFamilyFromXdsHost = dnsLookupFamilyFromXdsHost
)
slonka marked this conversation as resolved.
Show resolved Hide resolved
30 changes: 30 additions & 0 deletions pkg/xds/bootstrap/template_v3.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package bootstrap

import (
"net"
"strconv"

"github.com/asaskevich/govalidator"
Expand Down Expand Up @@ -171,6 +172,7 @@ func genConfig(parameters configParameters) (*envoy_bootstrap_v3.Bootstrap, erro
},
},
ClusterDiscoveryType: &envoy_cluster_v3.Cluster_Type{Type: clusterTypeFromHost(parameters.XdsHost)},
DnsLookupFamily: dnsLookupFamilyFromXdsHost(parameters.XdsHost, net.LookupIP),
LoadAssignment: &envoy_config_endpoint_v3.ClusterLoadAssignment{
ClusterName: "ads_cluster",
Endpoints: []*envoy_config_endpoint_v3.LocalityLbEndpoints{
Expand Down Expand Up @@ -295,6 +297,34 @@ func genConfig(parameters configParameters) (*envoy_bootstrap_v3.Bootstrap, erro
return res, nil
}

func dnsLookupFamilyFromXdsHost(host string, lookupFn func(host string) ([]net.IP, error)) envoy_cluster_v3.Cluster_DnsLookupFamily {
if govalidator.IsHost(host) {
ips, err := lookupFn(host)
if err != nil {
log.Info("[WARNING] error looking up XDS host to determine DnsLookupFamily, falling back to AUTO", "hostname", host)
return envoy_cluster_v3.Cluster_AUTO
}
hasIPv6 := false
hasIPv4 := false

for _, ip := range ips {
if ip.To4() != nil {
hasIPv4 = true
} else {
hasIPv6 = true
}
}

if hasIPv6 {
return envoy_cluster_v3.Cluster_AUTO
} else if hasIPv4 {
return envoy_cluster_v3.Cluster_V4_ONLY
}
slonka marked this conversation as resolved.
Show resolved Hide resolved
}

return envoy_cluster_v3.Cluster_AUTO // default
}

func clusterTypeFromHost(host string) envoy_cluster_v3.Cluster_DiscoveryType {
if govalidator.IsIP(host) {
return envoy_cluster_v3.Cluster_STATIC
Expand Down
77 changes: 77 additions & 0 deletions pkg/xds/bootstrap/template_v3_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package bootstrap

import (
"errors"
"net"

envoy_cluster_v3 "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

var _ = Describe("DnsLookupFamilyFromXdsHost", func() {
It("should return AUTO when IPv6 found", func() {
// given
lookupFn := func(host string) ([]net.IP, error) {
return []net.IP{net.IPv6loopback}, nil
}

// when
result := DnsLookupFamilyFromXdsHost("example.com", lookupFn)

//
Expect(result).To(Equal(envoy_cluster_v3.Cluster_AUTO))
})

It("should return AUTO when both IPv6 and IPv4 found", func() {
// given
lookupFn := func(host string) ([]net.IP, error) {
return []net.IP{net.IPv6loopback, net.IPv4(127, 0, 0, 1)}, nil
}

// when
result := DnsLookupFamilyFromXdsHost("example.com", lookupFn)

//
Expect(result).To(Equal(envoy_cluster_v3.Cluster_AUTO))
})

It("should return IPV4 when only IPv4 found", func() {
// given
lookupFn := func(host string) ([]net.IP, error) {
return []net.IP{net.IPv4(127, 0, 0, 1)}, nil
}

// when
result := DnsLookupFamilyFromXdsHost("example.com", lookupFn)

//
Expect(result).To(Equal(envoy_cluster_v3.Cluster_V4_ONLY))
})

It("should return AUTO (default) when no ips returned", func() {
// given
lookupFn := func(host string) ([]net.IP, error) {
return []net.IP{}, nil
}

// when
result := DnsLookupFamilyFromXdsHost("example.com", lookupFn)

//
Expect(result).To(Equal(envoy_cluster_v3.Cluster_AUTO))
})

It("should return AUTO when error occurs", func() {
// given
lookupFn := func(host string) ([]net.IP, error) {
return nil, errors.New("could not resolve hostname")
}

// when
result := DnsLookupFamilyFromXdsHost("example.com", lookupFn)

//
Expect(result).To(Equal(envoy_cluster_v3.Cluster_AUTO))
})
})
1 change: 1 addition & 0 deletions pkg/xds/bootstrap/testdata/bootstrap.k8s.golden.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ staticResources:
keepaliveProbes: 3
keepaliveTime: 10
- connectTimeout: 1s
dnsLookupFamily: V4_ONLY
http2ProtocolOptions: {}
loadAssignment:
clusterName: ads_cluster
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ staticResources:
keepaliveProbes: 3
keepaliveTime: 10
- connectTimeout: 1s
dnsLookupFamily: V4_ONLY
http2ProtocolOptions: {}
loadAssignment:
clusterName: ads_cluster
Expand Down
1 change: 1 addition & 0 deletions pkg/xds/bootstrap/testdata/bootstrap.universal.golden.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ staticResources:
keepaliveProbes: 3
keepaliveTime: 10
- connectTimeout: 1s
dnsLookupFamily: V4_ONLY
http2ProtocolOptions: {}
loadAssignment:
clusterName: ads_cluster
Expand Down