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

Consul Connect over IPv6 (except tproxy) #24203

Merged
merged 3 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions command/agent/consul/connect.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ func connectSidecarProxy(info structs.AllocInfo, proxy *structs.ConsulProxy, cPo
Mode: mode,
LocalServiceAddress: proxy.LocalServiceAddress,
LocalServicePort: proxy.LocalServicePort,
Config: connectProxyConfig(proxy.Config, cPort, info),
Config: connectProxyConfig(proxy.Config, cPort, info, networks),
Upstreams: connectUpstreams(proxy.Upstreams),
Expose: expose,
}, nil
Expand Down Expand Up @@ -243,11 +243,13 @@ func connectMeshGateway(in structs.ConsulMeshGateway) api.MeshGatewayConfig {
return gw
}

func connectProxyConfig(cfg map[string]interface{}, port int, info structs.AllocInfo) map[string]interface{} {
func connectProxyConfig(cfg map[string]interface{}, port int, info structs.AllocInfo, networks structs.Networks) map[string]interface{} {
if cfg == nil {
cfg = make(map[string]interface{})
}
cfg["bind_address"] = "0.0.0.0"
if _, ok := cfg["bind_address"]; !ok {
cfg["bind_address"] = connectProxyBindAddress(networks)
}
cfg["bind_port"] = port

tags := map[string]string{
Expand All @@ -260,6 +262,15 @@ func connectProxyConfig(cfg map[string]interface{}, port int, info structs.Alloc
return cfg
}

func connectProxyBindAddress(networks structs.Networks) string {
for _, n := range networks {
if n.Mode == "bridge" && n.IsIPv6() {
return "::"
}
}
return "0.0.0.0"
}

// injectNomadInfo merges nomad information into cfg=>envoy_stats_tags
//
// cfg must not be nil
Expand Down
32 changes: 27 additions & 5 deletions command/agent/consul/connect_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -409,22 +409,44 @@ func TestConnect_connectProxyConfig(t *testing.T) {
ci.Parallel(t)

t.Run("nil map", func(t *testing.T) {
require.Equal(t, map[string]interface{}{
must.Eq(t, map[string]any{
"bind_address": "0.0.0.0",
"bind_port": 42,
"envoy_stats_tags": []string{"nomad.alloc_id=test_alloc1"},
}, connectProxyConfig(nil, 42, structs.AllocInfo{AllocID: "test_alloc1"}))
}, connectProxyConfig(nil, 42, structs.AllocInfo{AllocID: "test_alloc1"}, nil))
})

t.Run("pre-existing map", func(t *testing.T) {
require.Equal(t, map[string]interface{}{
must.Eq(t, map[string]any{
"bind_address": "0.0.0.0",
"bind_port": 42,
"foo": "bar",
"envoy_stats_tags": []string{"nomad.alloc_id=test_alloc2"},
}, connectProxyConfig(map[string]interface{}{
}, connectProxyConfig(map[string]any{
"foo": "bar",
}, 42, structs.AllocInfo{AllocID: "test_alloc2"}))
}, 42, structs.AllocInfo{AllocID: "test_alloc2"}, nil))
})

t.Run("bind_address override", func(t *testing.T) {
must.Eq(t, map[string]any{
"bind_address": "anything",
"bind_port": 42,
"envoy_stats_tags": []string{"nomad.alloc_id=custom_bind_alloc"},
}, connectProxyConfig(map[string]any{
"bind_address": "anything",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This kind of invalid input just blows up downstream, right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, with this "anything" for example, the sidecar logs will show envoy squawking like

[2024-10-14 20:36:19.901][1][warning][config] [source/extensions/config_subscription/grpc/delta_subscription_state.cc:269] delta config for type.googleapis.com/envoy.config.listener.v3.Listener rejected: Error adding/updating listener(s) public_listener:anything:28417: malformed IP address: anything
[2024-10-14 20:36:19.901][1][warning][config] [source/extensions/config_subscription/grpc/grpc_subscription_impl.cc:138] gRPC config for type.googleapis.com/envoy.config.listener.v3.Listener rejected: Error adding/updating listener(s) public_listener:anything:28417: malformed IP address: anything

It will continue running, but the "Connect Sidecar Listening" health check fails.

So maybe it doesn't quite "blow up" but it's not too hard to track down.

}, 42, structs.AllocInfo{AllocID: "custom_bind_alloc"}, nil))
})

t.Run("bind_address ipv6", func(t *testing.T) {
must.Eq(t, map[string]any{
"bind_address": "::",
"bind_port": 42,
"envoy_stats_tags": []string{"nomad.alloc_id=ipv6_alloc"},
}, connectProxyConfig(map[string]any{
"bind_address": "::",
}, 42, structs.AllocInfo{AllocID: "ipv6_alloc"}, []*structs.NetworkResource{
{Mode: "bridge", IP: "fd00:a110:c8::1"},
}))
})
}

Expand Down
5 changes: 5 additions & 0 deletions nomad/structs/structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -3037,6 +3037,11 @@ func (n *NetworkResource) PortLabels() map[string]int {
return labelValues
}

func (n *NetworkResource) IsIPv6() bool {
ip := net.ParseIP(n.IP)
return ip != nil && ip.To4() == nil
}

// Networks defined for a task on the Resources struct.
type Networks []*NetworkResource

Expand Down