Skip to content

Commit

Permalink
connect: use heuristic to detect sidecar task driver
Browse files Browse the repository at this point in the history
This PR adds a heuristic to detect whether to use the podman task driver
for the connect sidecar proxy. The podman driver will be selected if there
is at least one task in the task group configured to use podman, and there
are zero tasks in the group configured to use docker. In all other cases
the task driver defaults to docker.

After this change, we should be able to run typical Connect jobspecs
(e.g. nomad job init [-short] -connect) on Clusters configured with the
podman task driver, without modification to the job files.

Closes #17042
  • Loading branch information
shoenig committed May 2, 2023
1 parent d5dd0c2 commit 289b29e
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 5 deletions.
3 changes: 3 additions & 0 deletions .changelog/17065.txt
@@ -0,0 +1,3 @@
```release-note:improvement
connect: Auto detect when to use podman for connect sidecar proxies
```
30 changes: 27 additions & 3 deletions nomad/job_endpoint_hook_connect.go
Expand Up @@ -230,6 +230,29 @@ func injectPort(group *structs.TaskGroup, label string) {
})
}

// groupConnectGuessTaskDriver will scan the tasks in g and try to decide which
// task driver to use for the default sidecar proxy task definition.
//
// If there is at least one podman task and zero docker tasks, use podman.
// Otherwise default to docker.
//
// If the sidecar_task block is set, that takes precedence and this does not apply.
func groupConnectGuessTaskDriver(g *structs.TaskGroup) string {
foundPodman := false
for _, task := range g.Tasks {
switch task.Driver {
case "docker":
return "docker"
case "podman":
foundPodman = true
}
}
if foundPodman {
return "podman"
}
return "docker"
}

func groupConnectHook(job *structs.Job, g *structs.TaskGroup) error {
// Create an environment interpolator with what we have at submission time.
// This should only be used to interpolate connect service names which are
Expand All @@ -254,7 +277,8 @@ func groupConnectHook(job *structs.Job, g *structs.TaskGroup) error {

// If the task doesn't already exist, create a new one and add it to the job
if task == nil {
task = newConnectSidecarTask(service.Name)
driver := groupConnectGuessTaskDriver(g)
task = newConnectSidecarTask(service.Name, driver)

// If there happens to be a task defined with the same name
// append an UUID fragment to the task name
Expand Down Expand Up @@ -477,12 +501,12 @@ func newConnectGatewayTask(prefix, service string, netHost, customizedTls bool)
}
}

func newConnectSidecarTask(service string) *structs.Task {
func newConnectSidecarTask(service, driver string) *structs.Task {
return &structs.Task{
// Name is used in container name so must start with '[A-Za-z0-9]'
Name: fmt.Sprintf("%s-%s", structs.ConnectProxyPrefix, service),
Kind: structs.NewTaskKind(structs.ConnectProxyPrefix, service),
Driver: "docker",
Driver: driver,
Config: connectSidecarDriverConfig(),
ShutdownDelay: 5 * time.Second,
LogConfig: &structs.LogConfig{
Expand Down
63 changes: 61 additions & 2 deletions nomad/job_endpoint_hook_connect_test.go
Expand Up @@ -9,10 +9,12 @@ import (
"time"

"github.com/hashicorp/nomad/ci"
"github.com/hashicorp/nomad/helper"
"github.com/hashicorp/nomad/helper/pointer"
"github.com/hashicorp/nomad/helper/testlog"
"github.com/hashicorp/nomad/nomad/mock"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/shoenig/test/must"
"github.com/stretchr/testify/require"
)

Expand Down Expand Up @@ -57,6 +59,63 @@ func TestJobEndpointConnect_isSidecarForService(t *testing.T) {
}
}

func TestJobEndpointConnect_groupConnectGuessTaskDriver(t *testing.T) {
ci.Parallel(t)

cases := []struct {
name string
drivers []string
exp string
}{
{
name: "none",
drivers: nil,
exp: "docker",
},
{
name: "neither",
drivers: []string{"exec", "raw_exec", "rkt"},
exp: "docker",
},
{
name: "docker only",
drivers: []string{"docker"},
exp: "docker",
},
{
name: "podman only",
drivers: []string{"podman"},
exp: "podman",
},
{
name: "mix",
drivers: []string{"podman", "docker", "exec"},
exp: "docker",
},
}

for _, tc := range cases {
tasks := helper.ConvertSlice(tc.drivers, func(driver string) *structs.Task {
return &structs.Task{Driver: driver}
})
tg := &structs.TaskGroup{Tasks: tasks}
result := groupConnectGuessTaskDriver(tg)
must.Eq(t, tc.exp, result)
}
}

func TestJobEndpointConnect_newConnectSidecarTask(t *testing.T) {
ci.Parallel(t)

task := newConnectSidecarTask("redis", "podman")
must.Eq(t, "connect-proxy-redis", task.Name)
must.Eq(t, "podman", task.Driver)

task2 := newConnectSidecarTask("db", "docker")
must.Eq(t, "connect-proxy-db", task2.Name)
must.Eq(t, "docker", task2.Driver)
}

func TestJobEndpointConnect_groupConnectHook(t *testing.T) {
ci.Parallel(t)

Expand Down Expand Up @@ -90,8 +149,8 @@ func TestJobEndpointConnect_groupConnectHook(t *testing.T) {
// Expected tasks
tgExp := job.TaskGroups[0].Copy()
tgExp.Tasks = []*structs.Task{
newConnectSidecarTask("backend"),
newConnectSidecarTask("admin"),
newConnectSidecarTask("backend", "docker"),
newConnectSidecarTask("admin", "docker"),
}
tgExp.Services[0].Name = "backend"
tgExp.Services[1].Name = "admin"
Expand Down

0 comments on commit 289b29e

Please sign in to comment.