Skip to content

Commit dd6bca0

Browse files
committed
consul/connect: enable configuring custom gateway task
Add the ability to configure the Task used for Connect gateways, similar to how sidecar Task can be configured. The implementation here simply re-uses the sidecar_task stanza, and now gets applied whether connect.sidecar_service or connect.gateway is the thing being defined. In retrospect, connect.sidecar_task could have been more generically named like connect.task to make it a little more re-usable. Closes #9474
1 parent 0993d5c commit dd6bca0

File tree

4 files changed

+123
-22
lines changed

4 files changed

+123
-22
lines changed

nomad/job_endpoint_hook_connect.go

+6-1
Original file line numberDiff line numberDiff line change
@@ -263,11 +263,16 @@ func groupConnectHook(job *structs.Job, g *structs.TaskGroup) error {
263263

264264
// inject the gateway task only if it does not yet already exist
265265
if !hasGatewayTaskForService(g, service.Name) {
266-
// use the default envoy image, for now there is no support for a custom task
267266
task := newConnectGatewayTask(service.Name, netHost)
268267

269268
g.Tasks = append(g.Tasks, task)
270269

270+
// the connect.sidecar_task stanza can also be used to configure
271+
// a custom task to use as a gateway proxy
272+
if service.Connect.SidecarTask != nil {
273+
service.Connect.SidecarTask.MergeIntoTask(task)
274+
}
275+
271276
task.Canonicalize(job, g)
272277
}
273278
}

nomad/job_endpoint_hook_connect_test.go

+75-6
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ func TestJobEndpointConnect_groupConnectHook(t *testing.T) {
9292
tgExp.Services[0].Name = "backend"
9393
tgExp.Services[1].Name = "admin"
9494

95-
// Expect sidecar tasks to be properly canonicalized
95+
// Expect sidecar tasks to be in canonical form.
9696
tgExp.Tasks[0].Canonicalize(job, tgExp)
9797
tgExp.Tasks[1].Canonicalize(job, tgExp)
9898
tgExp.Networks[0].DynamicPorts = []structs.Port{{
@@ -146,6 +146,75 @@ func TestJobEndpointConnect_groupConnectHook_IngressGateway(t *testing.T) {
146146
require.Exactly(t, expTG, job.TaskGroups[0])
147147
}
148148

149+
func TestJobEndpointConnect_groupConnectHook_IngressGateway_CustomTask(t *testing.T) {
150+
t.Parallel()
151+
152+
// Test that the connect gateway task is inserted if a gateway service exists
153+
// and since this is a bridge network, will rewrite the default gateway proxy
154+
// block with correct configuration.
155+
job := mock.ConnectIngressGatewayJob("bridge", false)
156+
157+
job.Meta = map[string]string{
158+
"gateway_name": "my-gateway",
159+
}
160+
161+
job.TaskGroups[0].Services[0].Name = "${NOMAD_META_gateway_name}"
162+
job.TaskGroups[0].Services[0].Connect.SidecarTask = &structs.SidecarTask{
163+
Driver: "raw_exec",
164+
User: "sidecars",
165+
Config: map[string]interface{}{
166+
"command": "/bin/sidecar",
167+
"args": []string{"a", "b"},
168+
},
169+
Resources: &structs.Resources{
170+
CPU: 400,
171+
// Memory: inherit 128
172+
},
173+
KillSignal: "SIGHUP",
174+
}
175+
176+
expTG := job.TaskGroups[0].Copy()
177+
expTG.Tasks = []*structs.Task{
178+
// inject merged gateway task
179+
{
180+
Name: "connect-ingress-my-gateway",
181+
Kind: structs.NewTaskKind(structs.ConnectIngressPrefix, "my-gateway"),
182+
Driver: "raw_exec",
183+
User: "sidecars",
184+
Config: map[string]interface{}{
185+
"command": "/bin/sidecar",
186+
"args": []string{"a", "b"},
187+
},
188+
Resources: &structs.Resources{
189+
CPU: 400,
190+
MemoryMB: 128,
191+
},
192+
LogConfig: &structs.LogConfig{
193+
MaxFiles: 2,
194+
MaxFileSizeMB: 2,
195+
},
196+
ShutdownDelay: 5 * time.Second,
197+
KillSignal: "SIGHUP",
198+
Constraints: structs.Constraints{
199+
connectGatewayVersionConstraint(),
200+
},
201+
},
202+
}
203+
expTG.Services[0].Name = "my-gateway"
204+
expTG.Tasks[0].Canonicalize(job, expTG)
205+
expTG.Networks[0].Canonicalize()
206+
207+
// rewrite the service gateway proxy configuration
208+
expTG.Services[0].Connect.Gateway.Proxy = gatewayProxyForBridge(expTG.Services[0].Connect.Gateway)
209+
210+
require.NoError(t, groupConnectHook(job, job.TaskGroups[0]))
211+
require.Exactly(t, expTG, job.TaskGroups[0])
212+
213+
// Test that the hook is idempotent
214+
require.NoError(t, groupConnectHook(job, job.TaskGroups[0]))
215+
require.Exactly(t, expTG, job.TaskGroups[0])
216+
}
217+
149218
// TestJobEndpoint_ConnectInterpolation asserts that when a Connect sidecar
150219
// proxy task is being created for a group service with an interpolated name,
151220
// the service name is interpolated *before the task is created.
@@ -330,7 +399,7 @@ func TestJobEndpointConnect_gatewayProxyIsDefault(t *testing.T) {
330399
t.Run("bind-addresses set", func(t *testing.T) {
331400
result := gatewayProxyIsDefault(&structs.ConsulGatewayProxy{
332401
EnvoyGatewayBindAddresses: map[string]*structs.ConsulGatewayBindAddress{
333-
"listener1": &structs.ConsulGatewayBindAddress{
402+
"listener1": {
334403
Address: "1.1.1.1",
335404
Port: 9000,
336405
},
@@ -362,7 +431,7 @@ func TestJobEndpointConnect_gatewayBindAddresses(t *testing.T) {
362431
}},
363432
})
364433
require.Equal(t, map[string]*structs.ConsulGatewayBindAddress{
365-
"service1": &structs.ConsulGatewayBindAddress{
434+
"service1": {
366435
Address: "0.0.0.0",
367436
Port: 3000,
368437
},
@@ -388,15 +457,15 @@ func TestJobEndpointConnect_gatewayBindAddresses(t *testing.T) {
388457
}},
389458
})
390459
require.Equal(t, map[string]*structs.ConsulGatewayBindAddress{
391-
"service1": &structs.ConsulGatewayBindAddress{
460+
"service1": {
392461
Address: "0.0.0.0",
393462
Port: 3000,
394463
},
395-
"service2": &structs.ConsulGatewayBindAddress{
464+
"service2": {
396465
Address: "0.0.0.0",
397466
Port: 3000,
398467
},
399-
"service3": &structs.ConsulGatewayBindAddress{
468+
"service3": {
400469
Address: "0.0.0.0",
401470
Port: 3001,
402471
},

website/pages/docs/job-specification/gateway.mdx

+18
Original file line numberDiff line numberDiff line change
@@ -199,12 +199,30 @@ make use of the envoy version interpolation, e.g.
199199
meta.connect.gateway_image = custom/envoy-${NOMAD_envoy_version}:latest
200200
```
201201

202+
### Custom gateway task
203+
204+
The task created for the gateway can be configured manually using the
205+
[`sidecar_task`][sidecar_task] stanza.
206+
207+
```
208+
connect {
209+
gateway {
210+
# ...
211+
}
212+
213+
sidecar_task {
214+
# ...
215+
}
216+
}
217+
```
218+
202219
[proxy]: /docs/job-specification/gateway#proxy-parameters
203220
[ingress]: /docs/job-specification/gateway#ingress-parameters
204221
[tls]: /docs/job-specification/gateway#tls-parameters
205222
[listener]: /docs/job-specification/gateway#listener-parameters
206223
[service]: /docs/job-specification/gateway#service-parameters
207224
[service-default]: https://www.consul.io/docs/agent/config-entries/service-defaults
225+
[sidecar_task]: /docs/job-specification/sidecar_task
208226
[connect_timeout_ms]: https://www.consul.io/docs/agent/config-entries/service-resolver#connecttimeout
209227
[address]: /docs/job-specification/gateway#address-parameters
210228
[Advanced Configuration]: https://www.consul.io/docs/connect/proxies/envoy#advanced-configuration

website/pages/docs/job-specification/sidecar_task.mdx

+24-15
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ description: |-
1212
<Placement groups={['job', 'group', 'service', 'connect', 'sidecar_task']} />
1313

1414
The `sidecar_task` stanza allows configuring various options for the proxy
15-
sidecar managed by Nomad for [Consul
15+
sidecar or connect gateway managed by Nomad for the [Consul
1616
Connect](/docs/integrations/consul-connect) integration such as
1717
resource requirements, kill timeouts and more as defined below. It is valid
1818
only within the context of a [`connect`][connect] stanza.
@@ -53,25 +53,30 @@ job "countdash" {
5353
}
5454
```
5555

56-
## Default Envoy proxy sidecar
56+
## Default Envoy configuration
5757

58-
Nomad automatically includes a default Envoy proxy sidecar task whenever a
59-
group service has a [`sidecar_service`][sidecar_service] stanza.
58+
Nomad automatically launches and manages an Envoy task for use as a proxy sidecar
59+
or connect gateway, when [`sidecar_service`][sidecar_service] or [`gateway`][gateway]
60+
are configured.
6061

61-
The default sidecar task is equivalent to:
62+
The default envoy task is equivalent to:
6263

6364
```hcl
6465
sidecar_task {
6566
name = "connect-proxy-<service>"
67+
# "connect-gateway-<service>" when used as a gateway
6668
67-
lifecycle {
69+
lifecycle { # absent when used as a gateway
6870
hook = "prestart"
6971
sidecar = true
7072
}
7173
7274
driver = "docker"
75+
7376
config {
7477
image = "${meta.connect.sidecar_image}"
78+
# "${meta.connect.gateway_image}" when used as a gateway
79+
7580
args = [
7681
"-c",
7782
"${NOMAD_SECRETS_DIR}/envoy_bootstrap.json",
@@ -97,13 +102,16 @@ sidecar_task {
97102
}
98103
```
99104

100-
The `meta.connect.sidecar_image`, `meta.connect.log_level`, and
101-
`meta.connect.proxy_concurrency` variables are [_client_
102-
configurable][nodemeta] variables with the following defaults:
105+
The `meta.connect.sidecar_image`, `meta.connect.gateway_image`, `meta.connect.log_level`,
106+
and `meta.connect.proxy_concurrency` variables are [client configurable][nodemeta]
107+
variables with the following defaults:
103108

104109
- `sidecar_image` - `(string: "envoyproxy/envoy:v${NOMAD_envoy_version}")` - The official
105110
upstream Envoy Docker image, where `${NOMAD_envoy_version}` is resolved automatically
106111
by a query to Consul.
112+
- `gateway_image` - `(string: "envoyproxy/envoy:v${NOMAD_envoy_version}")` - The official
113+
upstream Envoy Docker image, where `${NOMAD_envoy_version}` is resolved automatically
114+
by a query to Consul.
107115
- `log_level` - `(string: "info")` - Envoy sidecar log level. "`debug`" is useful for
108116
debugging Connect related issues.
109117
- `proxy_concurrency` - `(string: "1")` - The number of [worker threads][worker_threads] the Envoy
@@ -118,8 +126,8 @@ meta.connect.sidecar_image = custom/envoy-${NOMAD_envoy_version}:latest
118126

119127
## `sidecar_task` Parameters
120128

121-
- `name` `(string: "connect-proxy-<service>")` - Name of the task. Defaults to
122-
including the name of the service it is a proxy for.
129+
- `name` `(string: "connect-[proxy|gateway]-<service>")` - Name of the task. Defaults to
130+
including the name of the service the proxy or gateway is providing.
123131

124132
- `driver` `(string: "docker")` - Driver used for the sidecar task.
125133

@@ -166,12 +174,13 @@ The following example configures resources for the sidecar task and other config
166174
```
167175

168176
[connect]: /docs/job-specification/connect 'Nomad connect Job Specification'
169-
[job]: /docs/job-specification/job 'Nomad job Job Specification'
177+
[gateway]: /docs/job-specification/gateway
170178
[group]: /docs/job-specification/group 'Nomad group Job Specification'
171-
[task]: /docs/job-specification/task 'Nomad task Job Specification'
172179
[interpolation]: /docs/runtime/interpolation 'Nomad interpolation'
173-
[sidecar_service]: /docs/job-specification/sidecar_service 'Nomad sidecar service Specification'
174-
[resources]: /docs/job-specification/resources 'Nomad resources Job Specification'
180+
[job]: /docs/job-specification/job 'Nomad job Job Specification'
175181
[logs]: /docs/job-specification/logs 'Nomad logs Job Specification'
182+
[resources]: /docs/job-specification/resources 'Nomad resources Job Specification'
183+
[sidecar_service]: /docs/job-specification/sidecar_service 'Nomad sidecar service Specification'
184+
[task]: /docs/job-specification/task 'Nomad task Job Specification'
176185
[nodemeta]: /docs/configuration/client#meta
177186
[worker_threads]: https://www.envoyproxy.io/docs/envoy/latest/operations/cli#cmdoption-concurrency

0 commit comments

Comments
 (0)