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

Agent-wide node selector #3608

Merged
merged 7 commits into from
Jun 3, 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
9 changes: 8 additions & 1 deletion docs/docs/30-administration/22-backends/40-kubernetes.md
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@ And then overwrite the `nodeSelector` in the `backend_options` section of the st
kubernetes.io/arch: "${ARCH}"
```

You can use [PodNodeSelector](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#podnodeselector) admission controller if you want to set the node selector by per-namespace basis.
You can use [WOODPECKER_BACKEND_K8S_POD_NODE_SELECTOR](#woodpecker_backend_k8s_pod_node_selector) if you want to set the node selector per Agent
or [PodNodeSelector](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#podnodeselector) admission controller if you want to set the node selector by per-namespace basis.

### Tolerations

Expand Down Expand Up @@ -279,6 +280,12 @@ Additional annotations to apply to worker Pods. Must be a YAML object, e.g. `{"e

Determines if Pod annotations can be defined from a step's backend options.

### `WOODPECKER_BACKEND_K8S_POD_NODE_SELECTOR`

> Default: empty

Additional node selector to apply to worker pods. Must be a YAML object, e.g. `{"topology.kubernetes.io/region":"eu-central-1"}`.

### `WOODPECKER_BACKEND_K8S_SECCTX_NONROOT`

> Default: `false`
Expand Down
6 changes: 6 additions & 0 deletions pipeline/backend/kubernetes/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ var Flags = []cli.Flag{
Usage: "backend k8s additional Agent-wide worker pod annotations",
Value: "",
},
&cli.StringFlag{
EnvVars: []string{"WOODPECKER_BACKEND_K8S_POD_NODE_SELECTOR"},
Name: "backend-k8s-pod-node-selector",
Usage: "backend k8s Agent-wide worker pod node selector",
Value: "",
},
&cli.BoolFlag{
EnvVars: []string{"WOODPECKER_BACKEND_K8S_POD_ANNOTATIONS_ALLOW_FROM_STEP"},
Name: "backend-k8s-pod-annotations-allow-from-step",
Expand Down
9 changes: 9 additions & 0 deletions pipeline/backend/kubernetes/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
PodLabelsAllowFromStep bool
PodAnnotations map[string]string
PodAnnotationsAllowFromStep bool
PodNodeSelector map[string]string
ImagePullSecretNames []string
SecurityContext SecurityContextConfig
}
Expand Down Expand Up @@ -91,6 +92,7 @@
PodLabelsAllowFromStep: c.Bool("backend-k8s-pod-labels-allow-from-step"),
PodAnnotations: make(map[string]string), // just init empty map to prevent nil panic
PodAnnotationsAllowFromStep: c.Bool("backend-k8s-pod-annotations-allow-from-step"),
PodNodeSelector: make(map[string]string), // just init empty map to prevent nil panic

Check warning on line 95 in pipeline/backend/kubernetes/kubernetes.go

View check run for this annotation

Codecov / codecov/patch

pipeline/backend/kubernetes/kubernetes.go#L95

Added line #L95 was not covered by tests
ImagePullSecretNames: c.StringSlice("backend-k8s-pod-image-pull-secret-names"),
SecurityContext: SecurityContextConfig{
RunAsNonRoot: c.Bool("backend-k8s-secctx-nonroot"), // cspell:words secctx nonroot
Expand All @@ -113,6 +115,12 @@
return nil, err
}
}
if nodeSelector := c.String("backend-k8s-pod-node-selector"); nodeSelector != "" {
if err := yaml.Unmarshal([]byte(nodeSelector), &config.PodNodeSelector); err != nil {
log.Error().Err(err).Msgf("could not unmarshal pod node selector '%s'", nodeSelector)
return nil, err
}

Check warning on line 122 in pipeline/backend/kubernetes/kubernetes.go

View check run for this annotation

Codecov / codecov/patch

pipeline/backend/kubernetes/kubernetes.go#L118-L122

Added lines #L118 - L122 were not covered by tests
}
return &config, nil
}
}
Expand Down Expand Up @@ -173,6 +181,7 @@
c := *e.config
c.PodLabels = maps.Clone(e.config.PodLabels)
c.PodAnnotations = maps.Clone(e.config.PodAnnotations)
c.PodNodeSelector = maps.Clone(e.config.PodNodeSelector)
c.ImagePullSecretNames = slices.Clone(e.config.ImagePullSecretNames)
return &c
}
Expand Down
9 changes: 7 additions & 2 deletions pipeline/backend/kubernetes/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ func podSpec(step *types.Step, config *config, options BackendOptions) (v1.PodSp
ServiceAccountName: options.ServiceAccountName,
ImagePullSecrets: imagePullSecretsReferences(config.ImagePullSecretNames),
HostAliases: hostAliases(step.ExtraHosts),
NodeSelector: nodeSelector(options.NodeSelector, step.Environment["CI_SYSTEM_PLATFORM"]),
NodeSelector: nodeSelector(options.NodeSelector, config.PodNodeSelector, step.Environment["CI_SYSTEM_PLATFORM"]),
Tolerations: tolerations(options.Tolerations),
SecurityContext: podSecurityContext(options.SecurityContext, config.SecurityContext, step.Privileged),
}
Expand Down Expand Up @@ -331,7 +331,7 @@ func resourceList(resources map[string]string) (v1.ResourceList, error) {
return requestResources, nil
}

func nodeSelector(backendNodeSelector map[string]string, platform string) map[string]string {
func nodeSelector(backendNodeSelector, configNodeSelector map[string]string, platform string) map[string]string {
nodeSelector := make(map[string]string)

if platform != "" {
Expand All @@ -340,6 +340,11 @@ func nodeSelector(backendNodeSelector map[string]string, platform string) map[st
log.Trace().Msgf("using the node selector from the Agent's platform: %v", nodeSelector)
}

if len(configNodeSelector) > 0 {
log.Trace().Msgf("appending labels to the node selector from the configuration: %v", configNodeSelector)
maps.Copy(nodeSelector, configNodeSelector)
}

if len(backendNodeSelector) > 0 {
log.Trace().Msgf("appending labels to the node selector from the backend options: %v", backendNodeSelector)
maps.Copy(nodeSelector, backendNodeSelector)
Expand Down
4 changes: 3 additions & 1 deletion pipeline/backend/kubernetes/pod_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,8 @@ func TestFullPod(t *testing.T) {
],
"restartPolicy": "Never",
"nodeSelector": {
"storage": "ssd"
"storage": "ssd",
"topology.kubernetes.io/region": "eu-central-1"
},
"runtimeClassName": "runc",
"serviceAccountName": "wp-svc-acc",
Expand Down Expand Up @@ -331,6 +332,7 @@ func TestFullPod(t *testing.T) {
PodLabelsAllowFromStep: true,
PodAnnotations: map[string]string{"apps.kubernetes.io/pod-index": "0"},
PodAnnotationsAllowFromStep: true,
PodNodeSelector: map[string]string{"topology.kubernetes.io/region": "eu-central-1"},
SecurityContext: SecurityContextConfig{RunAsNonRoot: false},
}, "wp-01he8bebctabr3kgk0qj36d2me-0", "linux/amd64", BackendOptions{
Labels: map[string]string{"part-of": "woodpecker-ci"},
Expand Down