Skip to content

Gateway XDS Server resilience #309

@aojea

Description

@aojea

Envoys for Gateway uses the XDS protocol and cloud-provider-kinds acts as an XDS server.

Currently cloud provider kind tries to figure out its IP address and Port

func GetControlPlaneAddress() (string, error) {
interfaces, err := net.Interfaces()
if err != nil {
return "", err
}
sort.Slice(interfaces, func(i, j int) bool {
nameI := interfaces[i].Name
nameJ := interfaces[j].Name
if nameI == "docker0" {
return true
}
if nameJ == "docker0" {
return false
}
if nameI == "eth0" {
return nameJ != "docker0"
}
if nameJ == "eth0" {
return false
}
return nameI < nameJ
})
for _, iface := range interfaces {
if iface.Flags&net.FlagUp == 0 || iface.Flags&net.FlagLoopback != 0 {
continue
}
addrs, err := iface.Addrs()
if err != nil {
continue
}
for _, addr := range addrs {
ipNet, ok := addr.(*net.IPNet)
if ok && ipNet.IP.To4() != nil && !ipNet.IP.IsLinkLocalUnicast() && !ipNet.IP.IsLoopback() {
return ipNet.IP.String(), nil
}
}
}
return "", fmt.Errorf("no suitable global unicast IPv4 address found on any active non-loopback interface")
}

and configures envoy to use them, together with the well known lima and docker ips to reach the host, in case of platforms like Windows or Mac where containers run inside a VM and cloud provider kind in the host

const dynamicControlPlaneConfig = `node:
cluster: {{ .Cluster }}
id: {{ .ID }}
dynamic_resources:
ads_config:
api_type: GRPC
grpc_services:
- envoy_grpc:
cluster_name: xds_cluster
cds_config:
ads: {}
lds_config:
ads: {}
static_resources:
clusters:
- type: STRICT_DNS
typed_extension_protocol_options:
envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
"@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
explicit_http_config:
http2_protocol_options: {}
name: xds_cluster
load_assignment:
cluster_name: xds_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: {{ .ControlPlaneAddress }}
port_value: {{ .ControlPlanePort }}
- endpoint:
address:
socket_address:
address: host.docker.internal
port_value: {{ .ControlPlanePort }}
- endpoint:
address:
socket_address:
address: host.lima.internal
port_value: {{ .ControlPlanePort }}
admin:
access_log_path: /dev/stdout
address:
socket_address:
address: 0.0.0.0
port_value: {{ .AdminPort }}
`

Ideally, to be more resilient, we can export an additional Port in the envoy container, and be able to create a reverse tunnel connecting to that exposed port, so we do not need to worry about the dynamic XDS server IP:Port, it will be fixed.

It seems that envoy has recently added some reverse tunnel functionality envoyproxy/envoy#33320 so it will be good to understand if that can be used and implement it, and drop all the existing brittle heuristics

Metadata

Metadata

Labels

kind/featureCategorizes issue or PR as related to a new feature.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions