From 4756775ad469bd07820112fe0ba46fd742e5f891 Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Wed, 3 Jun 2026 19:18:43 -0700 Subject: [PATCH 01/30] feat(dind): multi-queue support and Docker mode fixes - Add `queues` list to values: when set, renders one Deployment + Service per queue instead of the single executor Deployment - Each queue merges with global executor.env (queue overrides global) and supports replicaCount and resources overrides - Add global executor.resources and per-queue resources override - Fix readiness probe path: /ready does not exist, use /healthz - Set EXECUTOR_USE_KUBERNETES=false to prevent the executor from auto-detecting Kubernetes mode via KUBERNETES_SERVICE_HOST/PORT (which are always injected into pods); dind chart runs in Docker mode using the dind sidecar - Set enableServiceLinks: false to reduce noise in pod env - Fix private docker registry image tag (registry:3) Co-Authored-By: Claude Sonnet 4.6 --- .../executor/executor.Deployment.yaml | 187 +++++++++++++++++- .../templates/executor/executor.Service.yaml | 33 +++- charts/sourcegraph-executor/dind/values.yaml | 36 +++- 3 files changed, 250 insertions(+), 6 deletions(-) diff --git a/charts/sourcegraph-executor/dind/templates/executor/executor.Deployment.yaml b/charts/sourcegraph-executor/dind/templates/executor/executor.Deployment.yaml index 06948149..4a66eeda 100644 --- a/charts/sourcegraph-executor/dind/templates/executor/executor.Deployment.yaml +++ b/charts/sourcegraph-executor/dind/templates/executor/executor.Deployment.yaml @@ -1,7 +1,179 @@ -{{- if .Values.executor.enabled -}} +{{- if .Values.queues }} +{{- range .Values.queues }} +{{- $queue := . }} +{{- $mergedEnv := mergeOverwrite (deepCopy $.Values.executor.env) ($queue.env | default dict) }} +{{- $replicaCount := ($queue.replicaCount | default $.Values.executor.replicaCount) }} +{{- $resources := ($queue.resources | default $.Values.executor.resources) }} +--- apiVersion: apps/v1 kind: Deployment metadata: + name: executor-{{ $queue.name }} + annotations: + description: Runs sourcegraph executors + kubectl.kubernetes.io/default-container: executor + labels: + {{- include "sourcegraph.labels" $ | nindent 4 }} + {{- if $.Values.executor.labels }} + {{- toYaml $.Values.executor.labels | nindent 4 }} + {{- end }} + app: executor-{{ $queue.name }} + deploy: sourcegraph + sourcegraph-resource-requires: no-cluster-admin + app.kubernetes.io/component: executor +spec: + selector: + matchLabels: + {{- include "sourcegraph.selectorLabels" $ | nindent 6 }} + app: executor-{{ $queue.name }} + minReadySeconds: 10 + replicas: {{ $replicaCount }} + revisionHistoryLimit: 10 + strategy: + rollingUpdate: + maxSurge: 1 + maxUnavailable: 1 + type: RollingUpdate + template: + metadata: + annotations: + kubectl.kubernetes.io/default-container: executor + {{- if $.Values.sourcegraph.podAnnotations }} + {{- toYaml $.Values.sourcegraph.podAnnotations | nindent 8 }} + {{- end }} + {{- if $.Values.executor.podAnnotations }} + {{- toYaml $.Values.executor.podAnnotations | nindent 8 }} + {{- end }} + labels: + {{- include "sourcegraph.selectorLabels" $ | nindent 8 }} + {{- if $.Values.sourcegraph.podLabels }} + {{- toYaml $.Values.sourcegraph.podLabels | nindent 8 }} + {{- end }} + {{- if $.Values.executor.podLabels }} + {{- toYaml $.Values.executor.podLabels | nindent 8 }} + {{- end }} + app: executor-{{ $queue.name }} + deploy: sourcegraph + sourcegraph-resource-requires: no-cluster-admin + app.kubernetes.io/component: executor + spec: + containers: + - name: executor + image: {{ include "sourcegraph.image" (list $ "executor") }} + imagePullPolicy: {{ $.Values.sourcegraph.image.pullPolicy }} + livenessProbe: + httpGet: + path: /healthz + port: http-debug + scheme: HTTP + initialDelaySeconds: 60 + timeoutSeconds: 5 + readinessProbe: + httpGet: + path: /healthz + port: http-debug + scheme: HTTP + periodSeconds: 5 + timeoutSeconds: 5 + ports: + - name: http-debug + containerPort: 8080 + terminationMessagePolicy: FallbackToLogsOnError + env: + {{- range $name, $item := $mergedEnv }} + - name: {{ $name }} + {{- $item | toYaml | nindent 14 }} + {{- end }} + - name: EXECUTOR_USE_FIRECRACKER + value: "false" + - name: EXECUTOR_HEALTH_SERVER_ADDR + value: ":8080" + - name: EXECUTOR_JOB_NUM_CPUS + value: "0" + - name: EXECUTOR_JOB_MEMORY + value: "0" + - name: DOCKER_HOST + value: tcp://localhost:2375 + - name: TMPDIR + value: /scratch + - name: EXECUTOR_USE_KUBERNETES + value: "false" + volumeMounts: + - mountPath: /scratch + name: executor-scratch + {{- with $resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + - name: dind + image: "{{ $.Values.dind.image.registry}}/{{ $.Values.dind.image.repository}}:{{ $.Values.dind.image.tag}}" + imagePullPolicy: {{ $.Values.sourcegraph.image.pullPolicy }} + securityContext: + privileged: true + command: + - 'dockerd' + - '--tls=false' + - '--mtu=1200' + - '--registry-mirror=http://executor:5000' + - '--host=tcp://0.0.0.0:2375' + livenessProbe: + tcpSocket: + port: 2375 + initialDelaySeconds: 5 + periodSeconds: 5 + failureThreshold: 5 + readinessProbe: + tcpSocket: + port: 2375 + initialDelaySeconds: 10 + periodSeconds: 5 + failureThreshold: 5 + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + ports: + - containerPort: 2375 + protocol: TCP + volumeMounts: + - mountPath: /scratch + name: executor-scratch + - mountPath: /etc/docker/daemon.json + subPath: daemon.json + name: docker-config + enableServiceLinks: false + {{- with $.Values.sourcegraph.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with $.Values.sourcegraph.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with include "sourcegraph.priorityClassName" (list $ "executor") | trim }}{{ . | nindent 6 }}{{- end }} + {{- with $.Values.sourcegraph.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with $.Values.sourcegraph.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: executor-scratch + emptyDir: {} + - name: docker-config + configMap: + defaultMode: 420 + name: docker-config +{{- end }} +{{- else if .Values.executor.enabled }} +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "executor.name" . }} annotations: description: Runs sourcegraph executors kubectl.kubernetes.io/default-container: executor @@ -57,14 +229,14 @@ spec: timeoutSeconds: 5 readinessProbe: httpGet: - path: /ready + path: /healthz port: http-debug scheme: HTTP periodSeconds: 5 timeoutSeconds: 5 ports: - name: http-debug - containerPort: 6060 + containerPort: 8080 terminationMessagePolicy: FallbackToLogsOnError env: {{- range $name, $item := .Values.executor.env }} @@ -73,6 +245,8 @@ spec: {{- end }} - name: EXECUTOR_USE_FIRECRACKER value: "false" + - name: EXECUTOR_HEALTH_SERVER_ADDR + value: ":8080" - name: EXECUTOR_JOB_NUM_CPUS value: "0" - name: EXECUTOR_JOB_MEMORY @@ -81,9 +255,15 @@ spec: value: tcp://localhost:2375 - name: TMPDIR value: /scratch + - name: EXECUTOR_USE_KUBERNETES + value: "false" volumeMounts: - mountPath: /scratch name: executor-scratch + {{- with .Values.executor.resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} - name: dind image: "{{ .Values.dind.image.registry}}/{{ .Values.dind.image.repository}}:{{ .Values.dind.image.tag}}" imagePullPolicy: {{ .Values.sourcegraph.image.pullPolicy }} @@ -122,6 +302,7 @@ spec: - mountPath: /etc/docker/daemon.json subPath: daemon.json name: docker-config + enableServiceLinks: false {{- with .Values.sourcegraph.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} diff --git a/charts/sourcegraph-executor/dind/templates/executor/executor.Service.yaml b/charts/sourcegraph-executor/dind/templates/executor/executor.Service.yaml index 970de1a9..beb6361c 100644 --- a/charts/sourcegraph-executor/dind/templates/executor/executor.Service.yaml +++ b/charts/sourcegraph-executor/dind/templates/executor/executor.Service.yaml @@ -1,4 +1,35 @@ -{{- if .Values.executor.enabled -}} +{{- if .Values.queues }} +{{- range .Values.queues }} +--- +apiVersion: v1 +kind: Service +metadata: + annotations: + prometheus.io/port: "6060" + sourcegraph.prometheus/scrape: "true" + {{- if $.Values.executor.serviceAnnotations }} + {{- toYaml $.Values.executor.serviceAnnotations | nindent 4 }} + {{- end }} + labels: + {{- if $.Values.executor.serviceLabels }} + {{- toYaml $.Values.executor.serviceLabels | nindent 4 }} + {{- end }} + app: executor-{{ .name }} + deploy: sourcegraph + sourcegraph-resource-requires: no-cluster-admin + app.kubernetes.io/component: executor + name: executor-{{ .name }} +spec: + ports: + - name: http-debug + port: 6060 + targetPort: http-debug + selector: + {{- include "sourcegraph.selectorLabels" $ | nindent 4 }} + app: executor-{{ .name }} + type: {{ $.Values.executor.serviceType | default "ClusterIP" }} +{{- end }} +{{- else if .Values.executor.enabled }} apiVersion: v1 kind: Service metadata: diff --git a/charts/sourcegraph-executor/dind/values.yaml b/charts/sourcegraph-executor/dind/values.yaml index eec0a03c..9b2d92fc 100644 --- a/charts/sourcegraph-executor/dind/values.yaml +++ b/charts/sourcegraph-executor/dind/values.yaml @@ -54,8 +54,40 @@ storageClass: # learn more from the [Kubernetes documentation](https://kubernetes.io/docs/concepts/storage/storage-classes/#allowed-topologies) allowedTopologies: {} +# -- Optional list of queues to deploy as standalone Deployments. +# When set, the single executor Deployment is not rendered. +# Each entry supports: name (required), replicaCount, resources, env (merged with executor.env, queue overrides). +queues: [] +# - name: codeintel +# replicaCount: 2 +# resources: +# requests: +# cpu: "2" +# memory: 4Gi +# limits: +# cpu: "4" +# memory: 8Gi +# env: +# EXECUTOR_QUEUE_NAME: +# value: codeintel +# - name: batches +# replicaCount: 1 +# resources: +# requests: +# cpu: "1" +# memory: 2Gi +# limits: +# cpu: "2" +# memory: 4Gi +# env: +# EXECUTOR_QUEUE_NAME: +# value: batches + executor: enabled: true + # -- Resource requests and limits for the executor container. + # Each queue can override this with its own resources field. + resources: {} image: defaultTag: 6.0.0@sha256:0be94a7c91f8273db10fdf46718c6596340ab2acc570e7b85353806e67a27508 name: "executor" @@ -86,6 +118,6 @@ privateDockerRegistry: enabled: true image: registry: index.docker.io - repository: docker/regisry - tag: 2 + repository: registry + tag: 3 storageSize: 10Gi From da473215559ee6600f87374f185a0a3cab48681c Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Wed, 3 Jun 2026 19:19:05 -0700 Subject: [PATCH 02/30] =?UTF-8?q?remove=20executor=20Service=20=E2=80=94?= =?UTF-8?q?=20executors=20are=20pull-based,=20no=20Service=20needed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- charts/sourcegraph-executor/dind/README.md | 6 +- .../templates/executor/executor.Service.yaml | 57 ------------------- 2 files changed, 4 insertions(+), 59 deletions(-) delete mode 100644 charts/sourcegraph-executor/dind/templates/executor/executor.Service.yaml diff --git a/charts/sourcegraph-executor/dind/README.md b/charts/sourcegraph-executor/dind/README.md index 8de11ecd..2ebf27c5 100644 --- a/charts/sourcegraph-executor/dind/README.md +++ b/charts/sourcegraph-executor/dind/README.md @@ -69,11 +69,13 @@ In addition to the documented values, the `executor` and `private-docker-registr | executor.image.defaultTag | string | `"6.0.0@sha256:0be94a7c91f8273db10fdf46718c6596340ab2acc570e7b85353806e67a27508"` | | | executor.image.name | string | `"executor"` | | | executor.replicaCount | int | `1` | | +| executor.resources | object | `{}` | Resource requests and limits for the executor container. Each queue can override this with its own resources field. | | privateDockerRegistry.enabled | bool | `true` | Whether to deploy the private registry. Only one registry is needed when deploying multiple executors. More information: https://docs.sourcegraph.com/admin/executors/deploy_executors#using-private-registries | | privateDockerRegistry.image.registry | string | `"index.docker.io"` | | -| privateDockerRegistry.image.repository | string | `"docker/regisry"` | | -| privateDockerRegistry.image.tag | int | `2` | | +| privateDockerRegistry.image.repository | string | `"registry"` | | +| privateDockerRegistry.image.tag | int | `3` | | | privateDockerRegistry.storageSize | string | `"10Gi"` | | +| queues | list | `[]` | Optional list of queues to deploy as standalone Deployments. When set, the single executor Deployment is not rendered. Each entry supports: name (required), replicaCount, resources, env (merged with executor.env, queue overrides). | | sourcegraph.affinity | object | `{}` | Affinity, learn more from the [Kubernetes documentation](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity) | | sourcegraph.image.defaultTag | string | `"{{ .Chart.AppVersion }}"` | Global docker image tag | | sourcegraph.image.pullPolicy | string | `"IfNotPresent"` | Global docker image pull policy | diff --git a/charts/sourcegraph-executor/dind/templates/executor/executor.Service.yaml b/charts/sourcegraph-executor/dind/templates/executor/executor.Service.yaml deleted file mode 100644 index beb6361c..00000000 --- a/charts/sourcegraph-executor/dind/templates/executor/executor.Service.yaml +++ /dev/null @@ -1,57 +0,0 @@ -{{- if .Values.queues }} -{{- range .Values.queues }} ---- -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/port: "6060" - sourcegraph.prometheus/scrape: "true" - {{- if $.Values.executor.serviceAnnotations }} - {{- toYaml $.Values.executor.serviceAnnotations | nindent 4 }} - {{- end }} - labels: - {{- if $.Values.executor.serviceLabels }} - {{- toYaml $.Values.executor.serviceLabels | nindent 4 }} - {{- end }} - app: executor-{{ .name }} - deploy: sourcegraph - sourcegraph-resource-requires: no-cluster-admin - app.kubernetes.io/component: executor - name: executor-{{ .name }} -spec: - ports: - - name: http-debug - port: 6060 - targetPort: http-debug - selector: - {{- include "sourcegraph.selectorLabels" $ | nindent 4 }} - app: executor-{{ .name }} - type: {{ $.Values.executor.serviceType | default "ClusterIP" }} -{{- end }} -{{- else if .Values.executor.enabled }} -apiVersion: v1 -kind: Service -metadata: - annotations: - prometheus.io/port: "6060" - sourcegraph.prometheus/scrape: "true" - {{- if .Values.executor.serviceAnnotations }} - {{- toYaml .Values.executor.serviceAnnotations | nindent 4 }} - {{- end }} - labels: - {{- include "executor.labels" . | nindent 4 }} - {{- if .Values.executor.serviceLabels }} - {{- toYaml .Values.executor.serviceLabels | nindent 4 }} - {{- end }} - name: executor -spec: - ports: - - name: http-debug - port: 6060 - targetPort: http-debug - selector: - {{- include "sourcegraph.selectorLabels" . | nindent 4 }} - app: {{include "executor.name" . }} - type: {{ .Values.executor.serviceType | default "ClusterIP" }} -{{- end }} From 415c67ceffcdbdfe2774654064a209a3babb2543 Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Wed, 3 Jun 2026 19:30:55 -0700 Subject: [PATCH 03/30] fix(dind): point registry mirror at correct service name --registry-mirror was pointing at http://executor:5000 which doesn't resolve; the private registry service is private-docker-registry:5000. Also fix ConfigMap condition to render in both single and multi-queue modes. Co-Authored-By: Claude Sonnet 4.6 --- .../dind/templates/executor/docker-daemon.ConfigMap.yaml | 2 +- .../dind/templates/executor/executor.Deployment.yaml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/charts/sourcegraph-executor/dind/templates/executor/docker-daemon.ConfigMap.yaml b/charts/sourcegraph-executor/dind/templates/executor/docker-daemon.ConfigMap.yaml index f927fcf8..b06f8110 100644 --- a/charts/sourcegraph-executor/dind/templates/executor/docker-daemon.ConfigMap.yaml +++ b/charts/sourcegraph-executor/dind/templates/executor/docker-daemon.ConfigMap.yaml @@ -1,4 +1,4 @@ -{{- if .Values.executor.enabled -}} +{{- if or .Values.queues .Values.executor.enabled -}} apiVersion: v1 data: daemon.json: | diff --git a/charts/sourcegraph-executor/dind/templates/executor/executor.Deployment.yaml b/charts/sourcegraph-executor/dind/templates/executor/executor.Deployment.yaml index 4a66eeda..6bbf75a1 100644 --- a/charts/sourcegraph-executor/dind/templates/executor/executor.Deployment.yaml +++ b/charts/sourcegraph-executor/dind/templates/executor/executor.Deployment.yaml @@ -114,7 +114,7 @@ spec: - 'dockerd' - '--tls=false' - '--mtu=1200' - - '--registry-mirror=http://executor:5000' + - '--registry-mirror=http://private-docker-registry:5000' - '--host=tcp://0.0.0.0:2375' livenessProbe: tcpSocket: @@ -273,7 +273,7 @@ spec: - 'dockerd' - '--tls=false' - '--mtu=1200' - - '--registry-mirror=http://executor:5000' + - '--registry-mirror=http://private-docker-registry:5000' - '--host=tcp://0.0.0.0:2375' livenessProbe: tcpSocket: From b3ad090255d2905d898ea4bfc6119b5c376228a8 Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Wed, 3 Jun 2026 23:39:23 -0700 Subject: [PATCH 04/30] feat(dind): convert private-docker-registry to StatefulSet StatefulSet gives stable pod identity and manages its own PVC via volumeClaimTemplates, replacing the separate PersistentVolumeClaim. Co-Authored-By: Claude Sonnet 4.6 --- .../private-docker-registry.Deployment.yaml | 26 +++++++++++++------ ...docker-registry.PersistentVolumeClaim.yaml | 19 -------------- 2 files changed, 18 insertions(+), 27 deletions(-) delete mode 100644 charts/sourcegraph-executor/dind/templates/private-docker-registry/private-docker-registry.PersistentVolumeClaim.yaml diff --git a/charts/sourcegraph-executor/dind/templates/private-docker-registry/private-docker-registry.Deployment.yaml b/charts/sourcegraph-executor/dind/templates/private-docker-registry/private-docker-registry.Deployment.yaml index 32554be6..fff6d337 100644 --- a/charts/sourcegraph-executor/dind/templates/private-docker-registry/private-docker-registry.Deployment.yaml +++ b/charts/sourcegraph-executor/dind/templates/private-docker-registry/private-docker-registry.Deployment.yaml @@ -1,6 +1,6 @@ {{- if .Values.privateDockerRegistry.enabled -}} apiVersion: apps/v1 -kind: Deployment +kind: StatefulSet metadata: name: private-docker-registry labels: @@ -11,13 +11,14 @@ metadata: deploy: sourcegraph app.kubernetes.io/component: private-docker-registry spec: - replicas: {{ .Values.privateDockerRegistry.replicaCount }} + replicas: 1 + serviceName: private-docker-registry selector: matchLabels: {{- include "sourcegraph.selectorLabels" . | nindent 6 }} app: private-docker-registry - strategy: - type: Recreate + updateStrategy: + type: RollingUpdate template: metadata: annotations: @@ -83,8 +84,17 @@ spec: imagePullSecrets: {{- toYaml . | nindent 8 }} {{- end }} - volumes: - - name: cache - persistentVolumeClaim: - claimName: private-docker-registry + volumeClaimTemplates: + - metadata: + name: cache + labels: + deploy: sourcegraph + app.kubernetes.io/component: private-docker-registry + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: {{ .Values.privateDockerRegistry.storageSize }} + storageClassName: {{ .Values.storageClass.name }} {{- end }} diff --git a/charts/sourcegraph-executor/dind/templates/private-docker-registry/private-docker-registry.PersistentVolumeClaim.yaml b/charts/sourcegraph-executor/dind/templates/private-docker-registry/private-docker-registry.PersistentVolumeClaim.yaml deleted file mode 100644 index 619d5af9..00000000 --- a/charts/sourcegraph-executor/dind/templates/private-docker-registry/private-docker-registry.PersistentVolumeClaim.yaml +++ /dev/null @@ -1,19 +0,0 @@ -{{- if .Values.privateDockerRegistry.enabled -}} -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - labels: - deploy: sourcegraph - app.kubernetes.io/component: private-docker-registry - name: private-docker-registry -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: {{ .Values.privateDockerRegistry.storageSize }} - storageClassName: {{ .Values.storageClass.name }} - {{- if .Values.privateDockerRegistry.volumeName }} - volumeName: {{ .Values.privateDockerRegistry.volumeName }} - {{- end }} -{{- end }} From 76d107079f7c6b8f1200053a69aa405d675beea0 Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Thu, 4 Jun 2026 09:34:57 -0700 Subject: [PATCH 05/30] feat(dind): structured executor options and env validation Add first-class values for options that map directly to executor env vars, mirroring the k8s chart interface: - executor.frontendUrl/frontendPassword/frontendExistingSecret - executor.queueName/queueNames (single-deployment mode) - executor.maximumNumJobs/maximumRuntimePerJob - executor.log.level/format - executor.dockerAddHostGateway - executor.debug.keepWorkspaces In multi-queue mode, each queue's EXECUTOR_QUEUE_NAME is set automatically from its name field. Add executor.validateEnv helper that fails at render time if executor.env or any queue.env contains a managed env var name. Co-Authored-By: Claude Sonnet 4.6 --- .../dind/templates/_helpers.tpl | 33 +++++++-- .../executor/executor.Deployment.yaml | 71 ++++++++++++++++--- charts/sourcegraph-executor/dind/values.yaml | 53 ++++++++------ dind.override.yaml | 21 ++++++ 4 files changed, 146 insertions(+), 32 deletions(-) create mode 100644 dind.override.yaml diff --git a/charts/sourcegraph-executor/dind/templates/_helpers.tpl b/charts/sourcegraph-executor/dind/templates/_helpers.tpl index d2797759..708f1a92 100644 --- a/charts/sourcegraph-executor/dind/templates/_helpers.tpl +++ b/charts/sourcegraph-executor/dind/templates/_helpers.tpl @@ -100,10 +100,10 @@ tolerations: {{- define "executor.name" -}} -{{- if .Values.executor.env.EXECUTOR_QUEUE_NAME.value -}} -executor-{{.Values.executor.env.EXECUTOR_QUEUE_NAME.value}} -{{- else if .Values.executor.env.EXECUTOR_QUEUE_NAMES.value -}} -executor-{{replace "," "-" .Values.executor.env.EXECUTOR_QUEUE_NAMES.value }} +{{- if .Values.executor.queueName -}} +executor-{{.Values.executor.queueName}} +{{- else if .Values.executor.queueNames -}} +executor-{{join "-" .Values.executor.queueNames }} {{- end }} {{- end }} @@ -113,3 +113,28 @@ deploy: sourcegraph sourcegraph-resource-requires: no-cluster-admin app.kubernetes.io/component: executor {{- end}} + +{{/* +Validate that an env dict does not contain managed environment variable names. +Usage: include "executor.validateEnv" (list $envDict "label") +*/}} +{{- define "executor.validateEnv" -}} +{{- $envDict := index . 0 }} +{{- $label := index . 1 }} +{{- $managed := list + "EXECUTOR_FRONTEND_URL" + "EXECUTOR_FRONTEND_PASSWORD" + "EXECUTOR_QUEUE_NAME" + "EXECUTOR_QUEUE_NAMES" + "SRC_LOG_LEVEL" + "SRC_LOG_FORMAT" + "EXECUTOR_MAXIMUM_NUM_JOBS" + "EXECUTOR_MAXIMUM_RUNTIME_PER_JOB" + "EXECUTOR_DOCKER_ADD_HOST_GATEWAY" + "EXECUTOR_KEEP_WORKSPACES" -}} +{{- range $managed -}} +{{- if hasKey $envDict . -}} +{{- fail (printf "%s: env must not contain managed variable %s; use the structured executor fields instead" $label .) -}} +{{- end -}} +{{- end -}} +{{- end -}} diff --git a/charts/sourcegraph-executor/dind/templates/executor/executor.Deployment.yaml b/charts/sourcegraph-executor/dind/templates/executor/executor.Deployment.yaml index 6bbf75a1..eb2ebd63 100644 --- a/charts/sourcegraph-executor/dind/templates/executor/executor.Deployment.yaml +++ b/charts/sourcegraph-executor/dind/templates/executor/executor.Deployment.yaml @@ -1,6 +1,8 @@ {{- if .Values.queues }} {{- range .Values.queues }} {{- $queue := . }} +{{- include "executor.validateEnv" (list $.Values.executor.env "executor.env") }} +{{- include "executor.validateEnv" (list ($queue.env | default dict) (printf "queues[%s].env" $queue.name)) }} {{- $mergedEnv := mergeOverwrite (deepCopy $.Values.executor.env) ($queue.env | default dict) }} {{- $replicaCount := ($queue.replicaCount | default $.Values.executor.replicaCount) }} {{- $resources := ($queue.resources | default $.Values.executor.resources) }} @@ -80,10 +82,31 @@ spec: containerPort: 8080 terminationMessagePolicy: FallbackToLogsOnError env: - {{- range $name, $item := $mergedEnv }} - - name: {{ $name }} - {{- $item | toYaml | nindent 14 }} - {{- end }} + - name: EXECUTOR_FRONTEND_URL + value: {{ $.Values.executor.frontendUrl | quote }} + - name: EXECUTOR_FRONTEND_PASSWORD + {{- if $.Values.executor.frontendExistingSecret }} + valueFrom: + secretKeyRef: + name: {{ $.Values.executor.frontendExistingSecret }} + key: EXECUTOR_FRONTEND_PASSWORD + {{- else }} + value: {{ $.Values.executor.frontendPassword | quote }} + {{- end }} + - name: EXECUTOR_QUEUE_NAME + value: {{ $queue.name | quote }} + - name: SRC_LOG_LEVEL + value: {{ $.Values.executor.log.level | quote }} + - name: SRC_LOG_FORMAT + value: {{ $.Values.executor.log.format | quote }} + - name: EXECUTOR_MAXIMUM_NUM_JOBS + value: {{ $.Values.executor.maximumNumJobs | quote }} + - name: EXECUTOR_MAXIMUM_RUNTIME_PER_JOB + value: {{ $.Values.executor.maximumRuntimePerJob | quote }} + - name: EXECUTOR_DOCKER_ADD_HOST_GATEWAY + value: {{ $.Values.executor.dockerAddHostGateway | quote }} + - name: EXECUTOR_KEEP_WORKSPACES + value: {{ $.Values.executor.debug.keepWorkspaces | quote }} - name: EXECUTOR_USE_FIRECRACKER value: "false" - name: EXECUTOR_HEALTH_SERVER_ADDR @@ -98,6 +121,10 @@ spec: value: /scratch - name: EXECUTOR_USE_KUBERNETES value: "false" + {{- range $name, $item := $mergedEnv }} + - name: {{ $name }} + {{- $item | toYaml | nindent 14 }} + {{- end }} volumeMounts: - mountPath: /scratch name: executor-scratch @@ -170,6 +197,7 @@ spec: name: docker-config {{- end }} {{- else if .Values.executor.enabled }} +{{- include "executor.validateEnv" (list .Values.executor.env "executor.env") }} apiVersion: apps/v1 kind: Deployment metadata: @@ -239,10 +267,33 @@ spec: containerPort: 8080 terminationMessagePolicy: FallbackToLogsOnError env: - {{- range $name, $item := .Values.executor.env }} - - name: {{ $name }} - {{- $item | toYaml | nindent 14 }} - {{- end }} + - name: EXECUTOR_FRONTEND_URL + value: {{ .Values.executor.frontendUrl | quote }} + - name: EXECUTOR_FRONTEND_PASSWORD + {{- if .Values.executor.frontendExistingSecret }} + valueFrom: + secretKeyRef: + name: {{ .Values.executor.frontendExistingSecret }} + key: EXECUTOR_FRONTEND_PASSWORD + {{- else }} + value: {{ .Values.executor.frontendPassword | quote }} + {{- end }} + - name: EXECUTOR_QUEUE_NAME + value: {{ .Values.executor.queueName | quote }} + - name: EXECUTOR_QUEUE_NAMES + value: {{ join "," .Values.executor.queueNames | quote }} + - name: SRC_LOG_LEVEL + value: {{ .Values.executor.log.level | quote }} + - name: SRC_LOG_FORMAT + value: {{ .Values.executor.log.format | quote }} + - name: EXECUTOR_MAXIMUM_NUM_JOBS + value: {{ .Values.executor.maximumNumJobs | quote }} + - name: EXECUTOR_MAXIMUM_RUNTIME_PER_JOB + value: {{ .Values.executor.maximumRuntimePerJob | quote }} + - name: EXECUTOR_DOCKER_ADD_HOST_GATEWAY + value: {{ .Values.executor.dockerAddHostGateway | quote }} + - name: EXECUTOR_KEEP_WORKSPACES + value: {{ .Values.executor.debug.keepWorkspaces | quote }} - name: EXECUTOR_USE_FIRECRACKER value: "false" - name: EXECUTOR_HEALTH_SERVER_ADDR @@ -257,6 +308,10 @@ spec: value: /scratch - name: EXECUTOR_USE_KUBERNETES value: "false" + {{- range $name, $item := .Values.executor.env }} + - name: {{ $name }} + {{- $item | toYaml | nindent 14 }} + {{- end }} volumeMounts: - mountPath: /scratch name: executor-scratch diff --git a/charts/sourcegraph-executor/dind/values.yaml b/charts/sourcegraph-executor/dind/values.yaml index 9b2d92fc..bb3ae6b3 100644 --- a/charts/sourcegraph-executor/dind/values.yaml +++ b/charts/sourcegraph-executor/dind/values.yaml @@ -56,7 +56,7 @@ storageClass: # -- Optional list of queues to deploy as standalone Deployments. # When set, the single executor Deployment is not rendered. -# Each entry supports: name (required), replicaCount, resources, env (merged with executor.env, queue overrides). +# Each entry supports: name (required, automatically used as EXECUTOR_QUEUE_NAME), replicaCount, resources, env (merged with executor.env, queue overrides). queues: [] # - name: codeintel # replicaCount: 2 @@ -67,9 +67,7 @@ queues: [] # limits: # cpu: "4" # memory: 8Gi -# env: -# EXECUTOR_QUEUE_NAME: -# value: codeintel +# env: {} # - name: batches # replicaCount: 1 # resources: @@ -79,12 +77,34 @@ queues: [] # limits: # cpu: "2" # memory: 4Gi -# env: -# EXECUTOR_QUEUE_NAME: -# value: batches +# env: {} executor: enabled: true + # -- The external URL of the Sourcegraph instance. Required. + frontendUrl: "" + # -- The shared secret configured in the Sourcegraph instance site config under executors.accessToken. Required if frontendExistingSecret is not configured. + frontendPassword: "" + # -- Name of existing k8s Secret to use for frontend password. + # The k8s Secret must contain the key EXECUTOR_FRONTEND_PASSWORD matching the site config executors.accessToken value. + # frontendPassword is ignored if this is set. + frontendExistingSecret: "" + # -- The name of the queue to pull jobs from. Possible values: batches and codeintel. Either this or queueNames is required (when not using queues). + queueName: "" + # -- The names of multiple queues to pull jobs from. Possible values: batches and codeintel. Either this or queueName is required (when not using queues). + queueNames: [] + # -- The maximum amount of jobs that can be executed concurrently. + maximumNumJobs: 10 + # -- The maximum wall time that can be spent on a single job. + maximumRuntimePerJob: "30m" + log: + # -- Possible values are dbug, info, warn, eror, crit. + level: "warn" + format: "condensed" + # -- For local deployments the host is 'host.docker.internal' and this needs to be true. + dockerAddHostGateway: "false" + debug: + keepWorkspaces: "false" # -- Resource requests and limits for the executor container. # Each queue can override this with its own resources field. resources: {} @@ -92,19 +112,12 @@ executor: defaultTag: 6.0.0@sha256:0be94a7c91f8273db10fdf46718c6596340ab2acc570e7b85353806e67a27508 name: "executor" replicaCount: 1 - env: - # -- The external URL of the Sourcegraph instance. Required. - EXECUTOR_FRONTEND_URL: - value: "" - # -- The shared secret configured in the Sourcegraph instance site config under executors.accessToken. Required. - EXECUTOR_FRONTEND_PASSWORD: - value: "" - # -- The name of the queue to pull jobs from to. Possible values: batches and codeintel. **Either this or EXECUTOR_QUEUE_NAMES is required.** - EXECUTOR_QUEUE_NAME: - value: "" - # -- The comma-separated list of names of multiple queues to pull jobs from to. Possible values: batches and codeintel. **Either this or EXECUTOR_QUEUE_NAME is required.** - EXECUTOR_QUEUE_NAMES: - value: "" + # -- Extra environment variables to set on the executor container. + # Must NOT contain managed env vars (EXECUTOR_FRONTEND_URL, EXECUTOR_FRONTEND_PASSWORD, + # EXECUTOR_QUEUE_NAME, EXECUTOR_QUEUE_NAMES, SRC_LOG_LEVEL, SRC_LOG_FORMAT, + # EXECUTOR_MAXIMUM_NUM_JOBS, EXECUTOR_MAXIMUM_RUNTIME_PER_JOB, + # EXECUTOR_DOCKER_ADD_HOST_GATEWAY, EXECUTOR_KEEP_WORKSPACES). + env: {} dind: image: diff --git a/dind.override.yaml b/dind.override.yaml new file mode 100644 index 00000000..4f4bddb7 --- /dev/null +++ b/dind.override.yaml @@ -0,0 +1,21 @@ +storageClass: + create: false + name: sourcegraph + +sourcegraph: + image: + repository: us-docker.pkg.dev/sourcegraph-images/external + defaultTag: docker-images-notest-06-03-fix_374565_2026-06-04_7.3-e87902b59ff0 + useGlobalTagAsDefault: true + +executor: + replicaCount: 4 + frontendUrl: "http://frontend.sourcegraph.internal" + frontendPassword: SrHY0aVe0keHeh9MBzcX097NBXXdpcQs + +queues: + - name: batches + replicaCount: 4 + - name: codeintel + replicaCount: 4 + From 00f3227f2ab74de75528961e74fbbdb0ce623bd4 Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Thu, 4 Jun 2026 10:05:19 -0700 Subject: [PATCH 06/30] remove dind.override.yaml from tracking Co-Authored-By: Claude Sonnet 4.6 --- dind.override.yaml | 21 --------------------- 1 file changed, 21 deletions(-) delete mode 100644 dind.override.yaml diff --git a/dind.override.yaml b/dind.override.yaml deleted file mode 100644 index 4f4bddb7..00000000 --- a/dind.override.yaml +++ /dev/null @@ -1,21 +0,0 @@ -storageClass: - create: false - name: sourcegraph - -sourcegraph: - image: - repository: us-docker.pkg.dev/sourcegraph-images/external - defaultTag: docker-images-notest-06-03-fix_374565_2026-06-04_7.3-e87902b59ff0 - useGlobalTagAsDefault: true - -executor: - replicaCount: 4 - frontendUrl: "http://frontend.sourcegraph.internal" - frontendPassword: SrHY0aVe0keHeh9MBzcX097NBXXdpcQs - -queues: - - name: batches - replicaCount: 4 - - name: codeintel - replicaCount: 4 - From d0d5ae3bedadf574453169e8a34f4f752d5a4965 Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Thu, 4 Jun 2026 10:05:19 -0700 Subject: [PATCH 07/30] chore: gitignore dind.override.yaml Co-Authored-By: Claude Sonnet 4.6 --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index a46e872c..4356b4a8 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ target/* # Jetbrains .idea/ +dind.override.yaml From 2c7574831092b4ecb33e74c784642e875fb917fd Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Thu, 4 Jun 2026 10:58:46 -0700 Subject: [PATCH 08/30] feat(dind): remove executor.enabled, make daemon.json configurable - executor.enabled had no meaningful use; the chart always deploys an executor, so the flag is removed - dind.daemonConfig is now a values map rendered as daemon.json, allowing arbitrary Docker daemon configuration via values overrides Co-Authored-By: Claude Sonnet 4.6 --- .../dind/templates/executor/docker-daemon.ConfigMap.yaml | 9 +++------ .../dind/templates/executor/executor.Deployment.yaml | 8 +------- ...ent.yaml => private-docker-registry.Statefulset.yaml} | 0 charts/sourcegraph-executor/dind/values.yaml | 5 ++++- 4 files changed, 8 insertions(+), 14 deletions(-) rename charts/sourcegraph-executor/dind/templates/private-docker-registry/{private-docker-registry.Deployment.yaml => private-docker-registry.Statefulset.yaml} (100%) diff --git a/charts/sourcegraph-executor/dind/templates/executor/docker-daemon.ConfigMap.yaml b/charts/sourcegraph-executor/dind/templates/executor/docker-daemon.ConfigMap.yaml index b06f8110..1a767bd5 100644 --- a/charts/sourcegraph-executor/dind/templates/executor/docker-daemon.ConfigMap.yaml +++ b/charts/sourcegraph-executor/dind/templates/executor/docker-daemon.ConfigMap.yaml @@ -1,9 +1,4 @@ -{{- if or .Values.queues .Values.executor.enabled -}} apiVersion: v1 -data: - daemon.json: | - { "insecure-registries":["private-docker-registry:5000"] } - kind: ConfigMap metadata: labels: @@ -11,4 +6,6 @@ metadata: deploy: sourcegraph app.kubernetes.io/component: executor name: docker-config -{{- end }} +data: + daemon.json: | + {{- .Values.dind.daemonConfig | toPrettyJson | nindent 4 }} diff --git a/charts/sourcegraph-executor/dind/templates/executor/executor.Deployment.yaml b/charts/sourcegraph-executor/dind/templates/executor/executor.Deployment.yaml index eb2ebd63..960c5ba6 100644 --- a/charts/sourcegraph-executor/dind/templates/executor/executor.Deployment.yaml +++ b/charts/sourcegraph-executor/dind/templates/executor/executor.Deployment.yaml @@ -196,7 +196,7 @@ spec: defaultMode: 420 name: docker-config {{- end }} -{{- else if .Values.executor.enabled }} +{{- else }} {{- include "executor.validateEnv" (list .Values.executor.env "executor.env") }} apiVersion: apps/v1 kind: Deployment @@ -286,14 +286,8 @@ spec: value: {{ .Values.executor.log.level | quote }} - name: SRC_LOG_FORMAT value: {{ .Values.executor.log.format | quote }} - - name: EXECUTOR_MAXIMUM_NUM_JOBS - value: {{ .Values.executor.maximumNumJobs | quote }} - name: EXECUTOR_MAXIMUM_RUNTIME_PER_JOB value: {{ .Values.executor.maximumRuntimePerJob | quote }} - - name: EXECUTOR_DOCKER_ADD_HOST_GATEWAY - value: {{ .Values.executor.dockerAddHostGateway | quote }} - - name: EXECUTOR_KEEP_WORKSPACES - value: {{ .Values.executor.debug.keepWorkspaces | quote }} - name: EXECUTOR_USE_FIRECRACKER value: "false" - name: EXECUTOR_HEALTH_SERVER_ADDR diff --git a/charts/sourcegraph-executor/dind/templates/private-docker-registry/private-docker-registry.Deployment.yaml b/charts/sourcegraph-executor/dind/templates/private-docker-registry/private-docker-registry.Statefulset.yaml similarity index 100% rename from charts/sourcegraph-executor/dind/templates/private-docker-registry/private-docker-registry.Deployment.yaml rename to charts/sourcegraph-executor/dind/templates/private-docker-registry/private-docker-registry.Statefulset.yaml diff --git a/charts/sourcegraph-executor/dind/values.yaml b/charts/sourcegraph-executor/dind/values.yaml index bb3ae6b3..4b026ce9 100644 --- a/charts/sourcegraph-executor/dind/values.yaml +++ b/charts/sourcegraph-executor/dind/values.yaml @@ -80,7 +80,6 @@ queues: [] # env: {} executor: - enabled: true # -- The external URL of the Sourcegraph instance. Required. frontendUrl: "" # -- The shared secret configured in the Sourcegraph instance site config under executors.accessToken. Required if frontendExistingSecret is not configured. @@ -124,6 +123,10 @@ dind: registry: index.docker.io repository: docker tag: 20.10.22-dind + # -- Docker daemon configuration passed as daemon.json to the dind sidecar. + daemonConfig: + insecure-registries: + - private-docker-registry:5000 privateDockerRegistry: # -- Whether to deploy the private registry. Only one registry is needed when deploying multiple executors. From 37a4c265dc50e16da74a38bbfb40802360d1fe8f Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Thu, 4 Jun 2026 14:02:02 -0700 Subject: [PATCH 09/30] refactor(dind): DRY executor Deployment via named template MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract the full Deployment body into executor.deployment in _helpers.tpl. executor.Deployment.yaml is now pure dispatch — resolves the per-queue vs single-deployment args and delegates to the shared template. Co-Authored-By: Claude Sonnet 4.6 --- .../dind/templates/_helpers.tpl | 195 +++++++++ .../executor/executor.Deployment.yaml | 391 +----------------- charts/sourcegraph-executor/dind/values.yaml | 7 +- 3 files changed, 216 insertions(+), 377 deletions(-) diff --git a/charts/sourcegraph-executor/dind/templates/_helpers.tpl b/charts/sourcegraph-executor/dind/templates/_helpers.tpl index 708f1a92..eaea512c 100644 --- a/charts/sourcegraph-executor/dind/templates/_helpers.tpl +++ b/charts/sourcegraph-executor/dind/templates/_helpers.tpl @@ -114,6 +114,201 @@ sourcegraph-resource-requires: no-cluster-admin app.kubernetes.io/component: executor {{- end}} +{{/* +Render a single executor Deployment. +Usage: include "executor.deployment" (dict "root" $ "name" "executor-foo" "queueName" "foo" "queueNames" (list) "replicaCount" 1 "resources" $res "env" $env) +*/}} +{{- define "executor.deployment" -}} +{{- $r := .root -}} +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ .name }} + annotations: + description: Runs sourcegraph executors + kubectl.kubernetes.io/default-container: executor + labels: + {{- include "sourcegraph.labels" $r | nindent 4 }} + {{- if $r.Values.executor.labels }} + {{- toYaml $r.Values.executor.labels | nindent 4 }} + {{- end }} + app: {{ .name }} + deploy: sourcegraph + sourcegraph-resource-requires: no-cluster-admin + app.kubernetes.io/component: executor +spec: + selector: + matchLabels: + {{- include "sourcegraph.selectorLabels" $r | nindent 6 }} + app: {{ .name }} + minReadySeconds: 10 + replicas: {{ .replicaCount }} + revisionHistoryLimit: 10 + strategy: + rollingUpdate: + maxSurge: 1 + maxUnavailable: 1 + type: RollingUpdate + template: + metadata: + annotations: + kubectl.kubernetes.io/default-container: executor + {{- if $r.Values.sourcegraph.podAnnotations }} + {{- toYaml $r.Values.sourcegraph.podAnnotations | nindent 8 }} + {{- end }} + {{- if $r.Values.executor.podAnnotations }} + {{- toYaml $r.Values.executor.podAnnotations | nindent 8 }} + {{- end }} + labels: + {{- include "sourcegraph.selectorLabels" $r | nindent 8 }} + {{- if $r.Values.sourcegraph.podLabels }} + {{- toYaml $r.Values.sourcegraph.podLabels | nindent 8 }} + {{- end }} + {{- if $r.Values.executor.podLabels }} + {{- toYaml $r.Values.executor.podLabels | nindent 8 }} + {{- end }} + app: {{ .name }} + deploy: sourcegraph + sourcegraph-resource-requires: no-cluster-admin + app.kubernetes.io/component: executor + spec: + containers: + - name: executor + image: {{ include "sourcegraph.image" (list $r "executor") }} + imagePullPolicy: {{ $r.Values.sourcegraph.image.pullPolicy }} + livenessProbe: + httpGet: + path: /healthz + port: http-debug + scheme: HTTP + initialDelaySeconds: 60 + timeoutSeconds: 5 + readinessProbe: + httpGet: + path: /healthz + port: http-debug + scheme: HTTP + periodSeconds: 5 + timeoutSeconds: 5 + ports: + - name: http-debug + containerPort: 8080 + terminationMessagePolicy: FallbackToLogsOnError + env: + - name: EXECUTOR_FRONTEND_URL + value: {{ $r.Values.executor.frontendUrl | quote }} + - name: EXECUTOR_FRONTEND_PASSWORD + {{- if $r.Values.executor.frontendExistingSecret }} + valueFrom: + secretKeyRef: + name: {{ $r.Values.executor.frontendExistingSecret }} + key: EXECUTOR_FRONTEND_PASSWORD + {{- else }} + value: {{ $r.Values.executor.frontendPassword | quote }} + {{- end }} + - name: EXECUTOR_QUEUE_NAME + value: {{ .queueName | quote }} + {{- if .queueNames }} + - name: EXECUTOR_QUEUE_NAMES + value: {{ join "," .queueNames | quote }} + {{- end }} + - name: SRC_LOG_LEVEL + value: {{ $r.Values.executor.log.level | quote }} + - name: SRC_LOG_FORMAT + value: {{ $r.Values.executor.log.format | quote }} + - name: EXECUTOR_MAXIMUM_RUNTIME_PER_JOB + value: {{ $r.Values.executor.maximumRuntimePerJob | quote }} + - name: EXECUTOR_USE_FIRECRACKER + value: "false" + - name: EXECUTOR_USE_KUBERNETES + value: "false" + - name: EXECUTOR_HEALTH_SERVER_ADDR + value: ":8080" + - name: EXECUTOR_JOB_NUM_CPUS + value: "0" + - name: EXECUTOR_JOB_MEMORY + value: "0" + - name: DOCKER_HOST + value: tcp://localhost:2375 + - name: TMPDIR + value: /scratch + {{- range $name, $item := .env }} + - name: {{ $name }} + {{- $item | toYaml | nindent 14 }} + {{- end }} + volumeMounts: + - mountPath: /scratch + name: executor-scratch + {{- with .resources }} + resources: + {{- toYaml . | nindent 12 }} + {{- end }} + - name: dind + image: "{{ $r.Values.dind.image.registry }}/{{ $r.Values.dind.image.repository }}:{{ $r.Values.dind.image.tag }}" + imagePullPolicy: {{ $r.Values.sourcegraph.image.pullPolicy }} + securityContext: + privileged: true + command: + - dockerd + - --tls=false + - --mtu=1200 + - --registry-mirror=http://private-docker-registry:5000 + - --host=tcp://0.0.0.0:2375 + livenessProbe: + tcpSocket: + port: 2375 + initialDelaySeconds: 5 + periodSeconds: 5 + failureThreshold: 5 + readinessProbe: + tcpSocket: + port: 2375 + initialDelaySeconds: 10 + periodSeconds: 5 + failureThreshold: 5 + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + ports: + - containerPort: 2375 + protocol: TCP + volumeMounts: + - mountPath: /scratch + name: executor-scratch + - mountPath: /etc/docker/daemon.json + subPath: daemon.json + name: docker-config + enableServiceLinks: false + {{- with $r.Values.sourcegraph.nodeSelector }} + nodeSelector: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with $r.Values.sourcegraph.affinity }} + affinity: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with include "sourcegraph.priorityClassName" (list $r "executor") | trim }}{{ . | nindent 6 }}{{- end }} + {{- with $r.Values.sourcegraph.tolerations }} + tolerations: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- with $r.Values.sourcegraph.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + volumes: + - name: executor-scratch + emptyDir: {} + - name: docker-config + configMap: + defaultMode: 420 + name: docker-config +{{- end }} + {{/* Validate that an env dict does not contain managed environment variable names. Usage: include "executor.validateEnv" (list $envDict "label") diff --git a/charts/sourcegraph-executor/dind/templates/executor/executor.Deployment.yaml b/charts/sourcegraph-executor/dind/templates/executor/executor.Deployment.yaml index 960c5ba6..96bf5369 100644 --- a/charts/sourcegraph-executor/dind/templates/executor/executor.Deployment.yaml +++ b/charts/sourcegraph-executor/dind/templates/executor/executor.Deployment.yaml @@ -1,379 +1,26 @@ {{- if .Values.queues }} {{- range .Values.queues }} -{{- $queue := . }} {{- include "executor.validateEnv" (list $.Values.executor.env "executor.env") }} -{{- include "executor.validateEnv" (list ($queue.env | default dict) (printf "queues[%s].env" $queue.name)) }} -{{- $mergedEnv := mergeOverwrite (deepCopy $.Values.executor.env) ($queue.env | default dict) }} -{{- $replicaCount := ($queue.replicaCount | default $.Values.executor.replicaCount) }} -{{- $resources := ($queue.resources | default $.Values.executor.resources) }} ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: executor-{{ $queue.name }} - annotations: - description: Runs sourcegraph executors - kubectl.kubernetes.io/default-container: executor - labels: - {{- include "sourcegraph.labels" $ | nindent 4 }} - {{- if $.Values.executor.labels }} - {{- toYaml $.Values.executor.labels | nindent 4 }} - {{- end }} - app: executor-{{ $queue.name }} - deploy: sourcegraph - sourcegraph-resource-requires: no-cluster-admin - app.kubernetes.io/component: executor -spec: - selector: - matchLabels: - {{- include "sourcegraph.selectorLabels" $ | nindent 6 }} - app: executor-{{ $queue.name }} - minReadySeconds: 10 - replicas: {{ $replicaCount }} - revisionHistoryLimit: 10 - strategy: - rollingUpdate: - maxSurge: 1 - maxUnavailable: 1 - type: RollingUpdate - template: - metadata: - annotations: - kubectl.kubernetes.io/default-container: executor - {{- if $.Values.sourcegraph.podAnnotations }} - {{- toYaml $.Values.sourcegraph.podAnnotations | nindent 8 }} - {{- end }} - {{- if $.Values.executor.podAnnotations }} - {{- toYaml $.Values.executor.podAnnotations | nindent 8 }} - {{- end }} - labels: - {{- include "sourcegraph.selectorLabels" $ | nindent 8 }} - {{- if $.Values.sourcegraph.podLabels }} - {{- toYaml $.Values.sourcegraph.podLabels | nindent 8 }} - {{- end }} - {{- if $.Values.executor.podLabels }} - {{- toYaml $.Values.executor.podLabels | nindent 8 }} - {{- end }} - app: executor-{{ $queue.name }} - deploy: sourcegraph - sourcegraph-resource-requires: no-cluster-admin - app.kubernetes.io/component: executor - spec: - containers: - - name: executor - image: {{ include "sourcegraph.image" (list $ "executor") }} - imagePullPolicy: {{ $.Values.sourcegraph.image.pullPolicy }} - livenessProbe: - httpGet: - path: /healthz - port: http-debug - scheme: HTTP - initialDelaySeconds: 60 - timeoutSeconds: 5 - readinessProbe: - httpGet: - path: /healthz - port: http-debug - scheme: HTTP - periodSeconds: 5 - timeoutSeconds: 5 - ports: - - name: http-debug - containerPort: 8080 - terminationMessagePolicy: FallbackToLogsOnError - env: - - name: EXECUTOR_FRONTEND_URL - value: {{ $.Values.executor.frontendUrl | quote }} - - name: EXECUTOR_FRONTEND_PASSWORD - {{- if $.Values.executor.frontendExistingSecret }} - valueFrom: - secretKeyRef: - name: {{ $.Values.executor.frontendExistingSecret }} - key: EXECUTOR_FRONTEND_PASSWORD - {{- else }} - value: {{ $.Values.executor.frontendPassword | quote }} - {{- end }} - - name: EXECUTOR_QUEUE_NAME - value: {{ $queue.name | quote }} - - name: SRC_LOG_LEVEL - value: {{ $.Values.executor.log.level | quote }} - - name: SRC_LOG_FORMAT - value: {{ $.Values.executor.log.format | quote }} - - name: EXECUTOR_MAXIMUM_NUM_JOBS - value: {{ $.Values.executor.maximumNumJobs | quote }} - - name: EXECUTOR_MAXIMUM_RUNTIME_PER_JOB - value: {{ $.Values.executor.maximumRuntimePerJob | quote }} - - name: EXECUTOR_DOCKER_ADD_HOST_GATEWAY - value: {{ $.Values.executor.dockerAddHostGateway | quote }} - - name: EXECUTOR_KEEP_WORKSPACES - value: {{ $.Values.executor.debug.keepWorkspaces | quote }} - - name: EXECUTOR_USE_FIRECRACKER - value: "false" - - name: EXECUTOR_HEALTH_SERVER_ADDR - value: ":8080" - - name: EXECUTOR_JOB_NUM_CPUS - value: "0" - - name: EXECUTOR_JOB_MEMORY - value: "0" - - name: DOCKER_HOST - value: tcp://localhost:2375 - - name: TMPDIR - value: /scratch - - name: EXECUTOR_USE_KUBERNETES - value: "false" - {{- range $name, $item := $mergedEnv }} - - name: {{ $name }} - {{- $item | toYaml | nindent 14 }} - {{- end }} - volumeMounts: - - mountPath: /scratch - name: executor-scratch - {{- with $resources }} - resources: - {{- toYaml . | nindent 12 }} - {{- end }} - - name: dind - image: "{{ $.Values.dind.image.registry}}/{{ $.Values.dind.image.repository}}:{{ $.Values.dind.image.tag}}" - imagePullPolicy: {{ $.Values.sourcegraph.image.pullPolicy }} - securityContext: - privileged: true - command: - - 'dockerd' - - '--tls=false' - - '--mtu=1200' - - '--registry-mirror=http://private-docker-registry:5000' - - '--host=tcp://0.0.0.0:2375' - livenessProbe: - tcpSocket: - port: 2375 - initialDelaySeconds: 5 - periodSeconds: 5 - failureThreshold: 5 - readinessProbe: - tcpSocket: - port: 2375 - initialDelaySeconds: 10 - periodSeconds: 5 - failureThreshold: 5 - env: - - name: POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - ports: - - containerPort: 2375 - protocol: TCP - volumeMounts: - - mountPath: /scratch - name: executor-scratch - - mountPath: /etc/docker/daemon.json - subPath: daemon.json - name: docker-config - enableServiceLinks: false - {{- with $.Values.sourcegraph.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with $.Values.sourcegraph.affinity }} - affinity: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with include "sourcegraph.priorityClassName" (list $ "executor") | trim }}{{ . | nindent 6 }}{{- end }} - {{- with $.Values.sourcegraph.tolerations }} - tolerations: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with $.Values.sourcegraph.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - volumes: - - name: executor-scratch - emptyDir: {} - - name: docker-config - configMap: - defaultMode: 420 - name: docker-config +{{- include "executor.validateEnv" (list (.env | default dict) (printf "queues[%s].env" .name)) }} +{{- include "executor.deployment" (dict + "root" $ + "name" (printf "executor-%s" .name) + "queueName" .name + "queueNames" (list) + "replicaCount" (.replicaCount | default $.Values.executor.replicaCount) + "resources" (.resources | default $.Values.executor.resources) + "env" (mergeOverwrite (deepCopy $.Values.executor.env) (.env | default dict)) +) }} {{- end }} {{- else }} {{- include "executor.validateEnv" (list .Values.executor.env "executor.env") }} -apiVersion: apps/v1 -kind: Deployment -metadata: - name: {{ include "executor.name" . }} - annotations: - description: Runs sourcegraph executors - kubectl.kubernetes.io/default-container: executor - labels: - {{- include "sourcegraph.labels" . | nindent 4 }} - {{- if .Values.executor.labels }} - {{- toYaml .Values.executor.labels | nindent 4 }} - {{- end }} - {{- include "executor.labels" . | nindent 4 }} -spec: - selector: - matchLabels: - {{- include "sourcegraph.selectorLabels" . | nindent 6 }} - app: {{ include "executor.name" . }} - minReadySeconds: 10 - replicas: {{ .Values.executor.replicaCount }} - revisionHistoryLimit: 10 - strategy: - rollingUpdate: - maxSurge: 1 - maxUnavailable: 1 - type: RollingUpdate - template: - metadata: - annotations: - kubectl.kubernetes.io/default-container: executor - {{- if .Values.sourcegraph.podAnnotations }} - {{- toYaml .Values.sourcegraph.podAnnotations | nindent 8 }} - {{- end }} - {{- if .Values.executor.podAnnotations }} - {{- toYaml .Values.executor.podAnnotations | nindent 8 }} - {{- end }} - labels: - {{- include "sourcegraph.selectorLabels" . | nindent 8 }} - {{- if .Values.sourcegraph.podLabels }} - {{- toYaml .Values.sourcegraph.podLabels | nindent 8 }} - {{- end }} - {{- if .Values.executor.podLabels }} - {{- toYaml .Values.executor.podLabels | nindent 8 }} - {{- end }} - {{- include "executor.labels" . | nindent 8 }} - spec: - containers: - - name: executor - image: {{ include "sourcegraph.image" (list . "executor") }} - imagePullPolicy: {{ .Values.sourcegraph.image.pullPolicy }} - livenessProbe: - httpGet: - path: /healthz - port: http-debug - scheme: HTTP - initialDelaySeconds: 60 - timeoutSeconds: 5 - readinessProbe: - httpGet: - path: /healthz - port: http-debug - scheme: HTTP - periodSeconds: 5 - timeoutSeconds: 5 - ports: - - name: http-debug - containerPort: 8080 - terminationMessagePolicy: FallbackToLogsOnError - env: - - name: EXECUTOR_FRONTEND_URL - value: {{ .Values.executor.frontendUrl | quote }} - - name: EXECUTOR_FRONTEND_PASSWORD - {{- if .Values.executor.frontendExistingSecret }} - valueFrom: - secretKeyRef: - name: {{ .Values.executor.frontendExistingSecret }} - key: EXECUTOR_FRONTEND_PASSWORD - {{- else }} - value: {{ .Values.executor.frontendPassword | quote }} - {{- end }} - - name: EXECUTOR_QUEUE_NAME - value: {{ .Values.executor.queueName | quote }} - - name: EXECUTOR_QUEUE_NAMES - value: {{ join "," .Values.executor.queueNames | quote }} - - name: SRC_LOG_LEVEL - value: {{ .Values.executor.log.level | quote }} - - name: SRC_LOG_FORMAT - value: {{ .Values.executor.log.format | quote }} - - name: EXECUTOR_MAXIMUM_RUNTIME_PER_JOB - value: {{ .Values.executor.maximumRuntimePerJob | quote }} - - name: EXECUTOR_USE_FIRECRACKER - value: "false" - - name: EXECUTOR_HEALTH_SERVER_ADDR - value: ":8080" - - name: EXECUTOR_JOB_NUM_CPUS - value: "0" - - name: EXECUTOR_JOB_MEMORY - value: "0" - - name: DOCKER_HOST - value: tcp://localhost:2375 - - name: TMPDIR - value: /scratch - - name: EXECUTOR_USE_KUBERNETES - value: "false" - {{- range $name, $item := .Values.executor.env }} - - name: {{ $name }} - {{- $item | toYaml | nindent 14 }} - {{- end }} - volumeMounts: - - mountPath: /scratch - name: executor-scratch - {{- with .Values.executor.resources }} - resources: - {{- toYaml . | nindent 12 }} - {{- end }} - - name: dind - image: "{{ .Values.dind.image.registry}}/{{ .Values.dind.image.repository}}:{{ .Values.dind.image.tag}}" - imagePullPolicy: {{ .Values.sourcegraph.image.pullPolicy }} - securityContext: - privileged: true - command: - - 'dockerd' - - '--tls=false' - - '--mtu=1200' - - '--registry-mirror=http://private-docker-registry:5000' - - '--host=tcp://0.0.0.0:2375' - livenessProbe: - tcpSocket: - port: 2375 - initialDelaySeconds: 5 - periodSeconds: 5 - failureThreshold: 5 - readinessProbe: - tcpSocket: - port: 2375 - initialDelaySeconds: 10 - periodSeconds: 5 - failureThreshold: 5 - env: - - name: POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - ports: - - containerPort: 2375 - protocol: TCP - volumeMounts: - - mountPath: /scratch - name: executor-scratch - - mountPath: /etc/docker/daemon.json - subPath: daemon.json - name: docker-config - enableServiceLinks: false - {{- with .Values.sourcegraph.nodeSelector }} - nodeSelector: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.sourcegraph.affinity }} - affinity: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with include "sourcegraph.priorityClassName" (list . "executor") | trim }}{{ . | nindent 6 }}{{- end }} - {{- with .Values.sourcegraph.tolerations }} - tolerations: - {{- toYaml . | nindent 8 }} - {{- end }} - {{- with .Values.sourcegraph.imagePullSecrets }} - imagePullSecrets: - {{- toYaml . | nindent 8 }} - {{- end }} - volumes: - - name: executor-scratch - emptyDir: {} - - name: docker-config - configMap: - defaultMode: 420 - name: docker-config +{{- include "executor.deployment" (dict + "root" . + "name" (include "executor.name" .) + "queueName" .Values.executor.queueName + "queueNames" .Values.executor.queueNames + "replicaCount" .Values.executor.replicaCount + "resources" .Values.executor.resources + "env" .Values.executor.env +) }} {{- end }} diff --git a/charts/sourcegraph-executor/dind/values.yaml b/charts/sourcegraph-executor/dind/values.yaml index 4b026ce9..5527a65b 100644 --- a/charts/sourcegraph-executor/dind/values.yaml +++ b/charts/sourcegraph-executor/dind/values.yaml @@ -99,11 +99,7 @@ executor: log: # -- Possible values are dbug, info, warn, eror, crit. level: "warn" - format: "condensed" - # -- For local deployments the host is 'host.docker.internal' and this needs to be true. - dockerAddHostGateway: "false" - debug: - keepWorkspaces: "false" + format: "json" # -- Resource requests and limits for the executor container. # Each queue can override this with its own resources field. resources: {} @@ -124,6 +120,7 @@ dind: repository: docker tag: 20.10.22-dind # -- Docker daemon configuration passed as daemon.json to the dind sidecar. + # Learn more from: https://docs.docker.com/reference/cli/dockerd/#on-linux daemonConfig: insecure-registries: - private-docker-registry:5000 From 9a4056b8dbfd78508e20ac3e8a4887fd48bfbdc7 Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Thu, 4 Jun 2026 19:04:51 -0700 Subject: [PATCH 10/30] fix(dind): emit --- at call site, not inside named template Helm trims whitespace between range iterations, causing the --- inside executor.deployment to land on the same line as the prior document's last character. Both deployments ended up in a single YAML document, making helm track them incorrectly. Move the separator to the call site. Co-Authored-By: Claude Sonnet 4.6 --- charts/sourcegraph-executor/dind/templates/_helpers.tpl | 1 - .../dind/templates/executor/executor.Deployment.yaml | 6 ++++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/charts/sourcegraph-executor/dind/templates/_helpers.tpl b/charts/sourcegraph-executor/dind/templates/_helpers.tpl index eaea512c..bbd86143 100644 --- a/charts/sourcegraph-executor/dind/templates/_helpers.tpl +++ b/charts/sourcegraph-executor/dind/templates/_helpers.tpl @@ -120,7 +120,6 @@ Usage: include "executor.deployment" (dict "root" $ "name" "executor-foo" "queue */}} {{- define "executor.deployment" -}} {{- $r := .root -}} ---- apiVersion: apps/v1 kind: Deployment metadata: diff --git a/charts/sourcegraph-executor/dind/templates/executor/executor.Deployment.yaml b/charts/sourcegraph-executor/dind/templates/executor/executor.Deployment.yaml index 96bf5369..3eb63173 100644 --- a/charts/sourcegraph-executor/dind/templates/executor/executor.Deployment.yaml +++ b/charts/sourcegraph-executor/dind/templates/executor/executor.Deployment.yaml @@ -2,7 +2,8 @@ {{- range .Values.queues }} {{- include "executor.validateEnv" (list $.Values.executor.env "executor.env") }} {{- include "executor.validateEnv" (list (.env | default dict) (printf "queues[%s].env" .name)) }} -{{- include "executor.deployment" (dict +--- +{{ include "executor.deployment" (dict "root" $ "name" (printf "executor-%s" .name) "queueName" .name @@ -14,7 +15,8 @@ {{- end }} {{- else }} {{- include "executor.validateEnv" (list .Values.executor.env "executor.env") }} -{{- include "executor.deployment" (dict +--- +{{ include "executor.deployment" (dict "root" . "name" (include "executor.name" .) "queueName" .Values.executor.queueName From 36a2b684e2899d7cb356d15c3a04a8c9a4881b54 Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Thu, 4 Jun 2026 19:21:53 -0700 Subject: [PATCH 11/30] feat(dind): add queueName/queueNames per queue entry Each queue now supports explicit queueName (EXECUTOR_QUEUE_NAME) and queueNames (EXECUTOR_QUEUE_NAMES) fields, mirroring the global executor.queueName/queueNames. The deployment name still comes from queue.name; queueName defaults to name when omitted. The two env vars are mutually exclusive: queueNames takes precedence. Co-Authored-By: Claude Sonnet 4.6 --- charts/sourcegraph-executor/dind/templates/_helpers.tpl | 5 +++-- .../dind/templates/executor/executor.Deployment.yaml | 4 ++-- charts/sourcegraph-executor/dind/values.yaml | 8 +++++++- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/charts/sourcegraph-executor/dind/templates/_helpers.tpl b/charts/sourcegraph-executor/dind/templates/_helpers.tpl index bbd86143..579294eb 100644 --- a/charts/sourcegraph-executor/dind/templates/_helpers.tpl +++ b/charts/sourcegraph-executor/dind/templates/_helpers.tpl @@ -206,11 +206,12 @@ spec: {{- else }} value: {{ $r.Values.executor.frontendPassword | quote }} {{- end }} - - name: EXECUTOR_QUEUE_NAME - value: {{ .queueName | quote }} {{- if .queueNames }} - name: EXECUTOR_QUEUE_NAMES value: {{ join "," .queueNames | quote }} + {{- else }} + - name: EXECUTOR_QUEUE_NAME + value: {{ .queueName | quote }} {{- end }} - name: SRC_LOG_LEVEL value: {{ $r.Values.executor.log.level | quote }} diff --git a/charts/sourcegraph-executor/dind/templates/executor/executor.Deployment.yaml b/charts/sourcegraph-executor/dind/templates/executor/executor.Deployment.yaml index 3eb63173..e251e60b 100644 --- a/charts/sourcegraph-executor/dind/templates/executor/executor.Deployment.yaml +++ b/charts/sourcegraph-executor/dind/templates/executor/executor.Deployment.yaml @@ -6,8 +6,8 @@ {{ include "executor.deployment" (dict "root" $ "name" (printf "executor-%s" .name) - "queueName" .name - "queueNames" (list) + "queueName" (.queueName | default .name) + "queueNames" (.queueNames | default (list)) "replicaCount" (.replicaCount | default $.Values.executor.replicaCount) "resources" (.resources | default $.Values.executor.resources) "env" (mergeOverwrite (deepCopy $.Values.executor.env) (.env | default dict)) diff --git a/charts/sourcegraph-executor/dind/values.yaml b/charts/sourcegraph-executor/dind/values.yaml index 5527a65b..276a624e 100644 --- a/charts/sourcegraph-executor/dind/values.yaml +++ b/charts/sourcegraph-executor/dind/values.yaml @@ -56,9 +56,14 @@ storageClass: # -- Optional list of queues to deploy as standalone Deployments. # When set, the single executor Deployment is not rendered. -# Each entry supports: name (required, automatically used as EXECUTOR_QUEUE_NAME), replicaCount, resources, env (merged with executor.env, queue overrides). +# Each entry supports: +# name (required) — used as the deployment name suffix (executor-) +# queueName — sets EXECUTOR_QUEUE_NAME; defaults to name if omitted +# queueNames — sets EXECUTOR_QUEUE_NAMES (comma-joined); takes precedence over queueName when set +# replicaCount, resources, env (merged with executor.env, queue overrides) queues: [] # - name: codeintel +# queueName: codeintel # replicaCount: 2 # resources: # requests: @@ -69,6 +74,7 @@ queues: [] # memory: 8Gi # env: {} # - name: batches +# queueName: batches # replicaCount: 1 # resources: # requests: From ecc6ea6d5976c859b30497ac1ddef0f69f7d5eab Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Thu, 4 Jun 2026 19:30:24 -0700 Subject: [PATCH 12/30] fix up --- charts/sourcegraph-executor/dind/README.md | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/charts/sourcegraph-executor/dind/README.md b/charts/sourcegraph-executor/dind/README.md index 2ebf27c5..140432cf 100644 --- a/charts/sourcegraph-executor/dind/README.md +++ b/charts/sourcegraph-executor/dind/README.md @@ -58,16 +58,22 @@ In addition to the documented values, the `executor` and `private-docker-registr | Key | Type | Default | Description | |-----|------|---------|-------------| +| dind.daemonConfig | object | `{"insecure-registries":["private-docker-registry:5000"]}` | Docker daemon configuration passed as daemon.json to the dind sidecar. Learn more from: https://docs.docker.com/reference/cli/dockerd/#on-linux | | dind.image.registry | string | `"index.docker.io"` | | | dind.image.repository | string | `"docker"` | | | dind.image.tag | string | `"20.10.22-dind"` | | -| executor.enabled | bool | `true` | | -| executor.env.EXECUTOR_FRONTEND_PASSWORD | object | `{"value":""}` | The shared secret configured in the Sourcegraph instance site config under executors.accessToken. Required. | -| executor.env.EXECUTOR_FRONTEND_URL | object | `{"value":""}` | The external URL of the Sourcegraph instance. Required. | -| executor.env.EXECUTOR_QUEUE_NAME | object | `{"value":""}` | The name of the queue to pull jobs from to. Possible values: batches and codeintel. **Either this or EXECUTOR_QUEUE_NAMES is required.** | -| executor.env.EXECUTOR_QUEUE_NAMES | object | `{"value":""}` | The comma-separated list of names of multiple queues to pull jobs from to. Possible values: batches and codeintel. **Either this or EXECUTOR_QUEUE_NAME is required.** | +| executor.env | object | `{}` | Extra environment variables to set on the executor container. Must NOT contain managed env vars (EXECUTOR_FRONTEND_URL, EXECUTOR_FRONTEND_PASSWORD, EXECUTOR_QUEUE_NAME, EXECUTOR_QUEUE_NAMES, SRC_LOG_LEVEL, SRC_LOG_FORMAT, EXECUTOR_MAXIMUM_NUM_JOBS, EXECUTOR_MAXIMUM_RUNTIME_PER_JOB, EXECUTOR_DOCKER_ADD_HOST_GATEWAY, EXECUTOR_KEEP_WORKSPACES). | +| executor.frontendExistingSecret | string | `""` | Name of existing k8s Secret to use for frontend password. The k8s Secret must contain the key EXECUTOR_FRONTEND_PASSWORD matching the site config executors.accessToken value. frontendPassword is ignored if this is set. | +| executor.frontendPassword | string | `""` | The shared secret configured in the Sourcegraph instance site config under executors.accessToken. Required if frontendExistingSecret is not configured. | +| executor.frontendUrl | string | `""` | The external URL of the Sourcegraph instance. Required. | | executor.image.defaultTag | string | `"6.0.0@sha256:0be94a7c91f8273db10fdf46718c6596340ab2acc570e7b85353806e67a27508"` | | | executor.image.name | string | `"executor"` | | +| executor.log.format | string | `"json"` | | +| executor.log.level | string | `"warn"` | Possible values are dbug, info, warn, eror, crit. | +| executor.maximumNumJobs | int | `10` | The maximum amount of jobs that can be executed concurrently. | +| executor.maximumRuntimePerJob | string | `"30m"` | The maximum wall time that can be spent on a single job. | +| executor.queueName | string | `""` | The name of the queue to pull jobs from. Possible values: batches and codeintel. Either this or queueNames is required (when not using queues). | +| executor.queueNames | list | `[]` | The names of multiple queues to pull jobs from. Possible values: batches and codeintel. Either this or queueName is required (when not using queues). | | executor.replicaCount | int | `1` | | | executor.resources | object | `{}` | Resource requests and limits for the executor container. Each queue can override this with its own resources field. | | privateDockerRegistry.enabled | bool | `true` | Whether to deploy the private registry. Only one registry is needed when deploying multiple executors. More information: https://docs.sourcegraph.com/admin/executors/deploy_executors#using-private-registries | @@ -75,7 +81,7 @@ In addition to the documented values, the `executor` and `private-docker-registr | privateDockerRegistry.image.repository | string | `"registry"` | | | privateDockerRegistry.image.tag | int | `3` | | | privateDockerRegistry.storageSize | string | `"10Gi"` | | -| queues | list | `[]` | Optional list of queues to deploy as standalone Deployments. When set, the single executor Deployment is not rendered. Each entry supports: name (required), replicaCount, resources, env (merged with executor.env, queue overrides). | +| queues | list | `[]` | Optional list of queues to deploy as standalone Deployments. When set, the single executor Deployment is not rendered. Each entry supports: name (required) — used as the deployment name suffix (executor-) queueName — sets EXECUTOR_QUEUE_NAME; defaults to name if omitted queueNames — sets EXECUTOR_QUEUE_NAMES (comma-joined); takes precedence over queueName when set replicaCount, resources, env (merged with executor.env, queue overrides) | | sourcegraph.affinity | object | `{}` | Affinity, learn more from the [Kubernetes documentation](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#affinity-and-anti-affinity) | | sourcegraph.image.defaultTag | string | `"{{ .Chart.AppVersion }}"` | Global docker image tag | | sourcegraph.image.pullPolicy | string | `"IfNotPresent"` | Global docker image pull policy | From 24a61759c64d5d973678a20ffce674c69e502417 Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Thu, 4 Jun 2026 19:47:56 -0700 Subject: [PATCH 13/30] fix(dind): bind dockerd to 127.0.0.1 and add gVisor support - Change --host=tcp://0.0.0.0:2375 to 127.0.0.1:2375 so the unauthenticated Docker API is not reachable from other cluster pods - Add dind.gVisor.enabled (default false): sets runtimeClassName: gvisor and replaces privileged: true with explicit capabilities per https://gvisor.dev/docs/tutorials/docker-in-gke-sandbox/ gVisor intercepts these capabilities in-sandbox; no host privileges are granted regardless of the capability list Co-Authored-By: Claude Sonnet 4.6 --- .../dind/templates/_helpers.tpl | 27 ++++++++++++++++++- charts/sourcegraph-executor/dind/values.yaml | 6 +++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/charts/sourcegraph-executor/dind/templates/_helpers.tpl b/charts/sourcegraph-executor/dind/templates/_helpers.tpl index 579294eb..0eb39881 100644 --- a/charts/sourcegraph-executor/dind/templates/_helpers.tpl +++ b/charts/sourcegraph-executor/dind/templates/_helpers.tpl @@ -248,13 +248,35 @@ spec: image: "{{ $r.Values.dind.image.registry }}/{{ $r.Values.dind.image.repository }}:{{ $r.Values.dind.image.tag }}" imagePullPolicy: {{ $r.Values.sourcegraph.image.pullPolicy }} securityContext: + {{- if $r.Values.dind.gVisor.enabled }} + capabilities: + add: + - NET_ADMIN + - SYS_ADMIN + - AUDIT_WRITE + - CHOWN + - DAC_OVERRIDE + - FOWNER + - FSETID + - KILL + - MKNOD + - NET_BIND_SERVICE + - NET_RAW + - SETFCAP + - SETGID + - SETPCAP + - SETUID + - SYS_CHROOT + - SYS_PTRACE + {{- else }} privileged: true + {{- end }} command: - dockerd - --tls=false - --mtu=1200 - --registry-mirror=http://private-docker-registry:5000 - - --host=tcp://0.0.0.0:2375 + - --host=tcp://127.0.0.1:2375 livenessProbe: tcpSocket: port: 2375 @@ -283,6 +305,9 @@ spec: subPath: daemon.json name: docker-config enableServiceLinks: false + {{- if $r.Values.dind.gVisor.enabled }} + runtimeClassName: gvisor + {{- end }} {{- with $r.Values.sourcegraph.nodeSelector }} nodeSelector: {{- toYaml . | nindent 8 }} diff --git a/charts/sourcegraph-executor/dind/values.yaml b/charts/sourcegraph-executor/dind/values.yaml index 276a624e..743af04f 100644 --- a/charts/sourcegraph-executor/dind/values.yaml +++ b/charts/sourcegraph-executor/dind/values.yaml @@ -130,6 +130,12 @@ dind: daemonConfig: insecure-registries: - private-docker-registry:5000 + gVisor: + # -- Enable gVisor sandbox (GKE only). Requires the GKE node pool to have sandbox type set to gvisor. + # When enabled, sets runtimeClassName: gvisor on executor pods and replaces privileged: true with + # explicit capabilities — these are intercepted in-sandbox and never granted to the host kernel. + # See: https://gvisor.dev/docs/tutorials/docker-in-gke-sandbox/ + enabled: false privateDockerRegistry: # -- Whether to deploy the private registry. Only one registry is needed when deploying multiple executors. From 6d6f462846652c2cc2e0d5ef6ffdd79dabe8ab57 Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Thu, 4 Jun 2026 19:54:16 -0700 Subject: [PATCH 14/30] fix(dind): add --storage-driver=vfs when gVisor is enabled MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gVisor's kernel does not implement the ioctls required by overlay2, aufs, or devicemapper — all three fail with "invalid argument" or "not found". vfs is the only storage driver that works inside the gVisor sandbox. Add --storage-driver=vfs to the dockerd command when dind.gVisor.enabled is true so the daemon starts successfully on gVisor nodes. Co-Authored-By: Claude Sonnet 4.6 --- charts/sourcegraph-executor/dind/templates/_helpers.tpl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/charts/sourcegraph-executor/dind/templates/_helpers.tpl b/charts/sourcegraph-executor/dind/templates/_helpers.tpl index 0eb39881..25dda4f8 100644 --- a/charts/sourcegraph-executor/dind/templates/_helpers.tpl +++ b/charts/sourcegraph-executor/dind/templates/_helpers.tpl @@ -277,6 +277,9 @@ spec: - --mtu=1200 - --registry-mirror=http://private-docker-registry:5000 - --host=tcp://127.0.0.1:2375 + {{- if $r.Values.dind.gVisor.enabled }} + - --storage-driver=vfs + {{- end }} livenessProbe: tcpSocket: port: 2375 From d527de7fa599c3b13f36b66d4df2032589212bad Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Thu, 4 Jun 2026 19:55:28 -0700 Subject: [PATCH 15/30] fix(dind): add --iptables=false for gVisor gVisor's virtual network layer exposes docker0 as a plain interface, not a bridge, causing dockerd to fail at network controller initialization. --iptables=false bypasses the bridge/netfilter setup path that requires kernel modules (bridge, br_netfilter, nf_conntrack) unavailable in gVisor. Co-Authored-By: Claude Sonnet 4.6 --- charts/sourcegraph-executor/dind/templates/_helpers.tpl | 1 + 1 file changed, 1 insertion(+) diff --git a/charts/sourcegraph-executor/dind/templates/_helpers.tpl b/charts/sourcegraph-executor/dind/templates/_helpers.tpl index 25dda4f8..fc4f2c0a 100644 --- a/charts/sourcegraph-executor/dind/templates/_helpers.tpl +++ b/charts/sourcegraph-executor/dind/templates/_helpers.tpl @@ -279,6 +279,7 @@ spec: - --host=tcp://127.0.0.1:2375 {{- if $r.Values.dind.gVisor.enabled }} - --storage-driver=vfs + - --iptables=false {{- end }} livenessProbe: tcpSocket: From ae9dd5c3ef78edfada3b0fba04963c41d2bf207a Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Thu, 4 Jun 2026 20:03:05 -0700 Subject: [PATCH 16/30] fix(dind): implement gVisor-compatible dockerd startup sequence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Docker 29 + gVisor requires specific setup before dockerd can start: - ip_forward must be enabled manually (gVisor doesn't auto-enable it) - iptables-legacy NAT POSTROUTING rules must be set up before dockerd since --iptables=false prevents dockerd from managing them - docker0 must be deleted before restart to avoid "existing interface docker0 is not a bridge" crash on CrashLoopBackOff recovery - --feature containerd-snapshotter=false is required for Docker 29+ on gVisor since the containerd image store needs tmpfs as upper layer - --ip6tables=false required alongside --iptables=false per gVisor docs Also bumps dind liveness/readiness initialDelaySeconds (5/10 → 15/20) to give the setup script time to run before the probe fires. References: https://gvisor.dev/docs/tutorials/docker-in-gvisor/ Co-Authored-By: Claude Sonnet 4.6 --- .../dind/templates/_helpers.tpl | 30 +++++++++++++++---- charts/sourcegraph-executor/dind/values.yaml | 2 +- 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/charts/sourcegraph-executor/dind/templates/_helpers.tpl b/charts/sourcegraph-executor/dind/templates/_helpers.tpl index fc4f2c0a..2fb96c11 100644 --- a/charts/sourcegraph-executor/dind/templates/_helpers.tpl +++ b/charts/sourcegraph-executor/dind/templates/_helpers.tpl @@ -271,26 +271,36 @@ spec: {{- else }} privileged: true {{- end }} + {{- if $r.Values.dind.gVisor.enabled }} + command: + - /bin/sh + - -c + - | + ip link del docker0 2>/dev/null || true + echo 1 > /proc/sys/net/ipv4/ip_forward + dev=$(ip route show default | sed 's/.*\sdev\s\(\S*\)\s.*$/\1/') + addr=$(ip addr show dev "$dev" | grep -w inet | sed 's/^\s*inet\s\(\S*\)\/.*$/\1/') + iptables-legacy -t nat -A POSTROUTING -o "$dev" -j SNAT --to-source "$addr" -p tcp || true + iptables-legacy -t nat -A POSTROUTING -o "$dev" -j SNAT --to-source "$addr" -p udp || true + exec dockerd --tls=false --mtu=1200 --registry-mirror=http://private-docker-registry:5000 --host=tcp://127.0.0.1:2375 --storage-driver=vfs --feature containerd-snapshotter=false --iptables=false --ip6tables=false + {{- else }} command: - dockerd - --tls=false - --mtu=1200 - --registry-mirror=http://private-docker-registry:5000 - --host=tcp://127.0.0.1:2375 - {{- if $r.Values.dind.gVisor.enabled }} - - --storage-driver=vfs - - --iptables=false - {{- end }} + {{- end }} livenessProbe: tcpSocket: port: 2375 - initialDelaySeconds: 5 + initialDelaySeconds: 15 periodSeconds: 5 failureThreshold: 5 readinessProbe: tcpSocket: port: 2375 - initialDelaySeconds: 10 + initialDelaySeconds: 20 periodSeconds: 5 failureThreshold: 5 env: @@ -308,6 +318,10 @@ spec: - mountPath: /etc/docker/daemon.json subPath: daemon.json name: docker-config + {{- if $r.Values.dind.gVisor.enabled }} + - mountPath: /var/lib/docker + name: docker + {{- end }} enableServiceLinks: false {{- if $r.Values.dind.gVisor.enabled }} runtimeClassName: gvisor @@ -336,6 +350,10 @@ spec: configMap: defaultMode: 420 name: docker-config + {{- if $r.Values.dind.gVisor.enabled }} + - name: docker + emptyDir: {} + {{- end }} {{- end }} {{/* diff --git a/charts/sourcegraph-executor/dind/values.yaml b/charts/sourcegraph-executor/dind/values.yaml index 743af04f..bca52b95 100644 --- a/charts/sourcegraph-executor/dind/values.yaml +++ b/charts/sourcegraph-executor/dind/values.yaml @@ -124,7 +124,7 @@ dind: image: registry: index.docker.io repository: docker - tag: 20.10.22-dind + tag: 29.5.3-dind # -- Docker daemon configuration passed as daemon.json to the dind sidecar. # Learn more from: https://docs.docker.com/reference/cli/dockerd/#on-linux daemonConfig: From 23a1adb752f7b0a2713ce59d6c0391e206d79953 Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Thu, 4 Jun 2026 20:08:24 -0700 Subject: [PATCH 17/30] fix(dind/gvisor): pre-create docker0 bridge and fix device parsing MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two bugs: 1. `ip link del docker0` in gVisor silently fails (or docker0 is pre-existing and can't be deleted), leaving a non-bridge docker0 when dockerd starts. Fix: explicitly create docker0 as a bridge (del, add type bridge, assign 172.17.0.1/16, bring up) before starting dockerd so Docker finds a proper bridge interface. 2. `sed '\s'` is not portable on Alpine's busybox sed — the \s escape is not recognized, causing the device-name variable to capture all ip-route output lines. Fix: use awk to extract the first 'dev' token from the default route. Co-Authored-By: Claude Sonnet 4.6 --- charts/sourcegraph-executor/dind/templates/_helpers.tpl | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/charts/sourcegraph-executor/dind/templates/_helpers.tpl b/charts/sourcegraph-executor/dind/templates/_helpers.tpl index 2fb96c11..466b3fc9 100644 --- a/charts/sourcegraph-executor/dind/templates/_helpers.tpl +++ b/charts/sourcegraph-executor/dind/templates/_helpers.tpl @@ -277,9 +277,12 @@ spec: - -c - | ip link del docker0 2>/dev/null || true + ip link add name docker0 type bridge 2>/dev/null || true + ip addr add 172.17.0.1/16 dev docker0 2>/dev/null || true + ip link set docker0 up 2>/dev/null || true echo 1 > /proc/sys/net/ipv4/ip_forward - dev=$(ip route show default | sed 's/.*\sdev\s\(\S*\)\s.*$/\1/') - addr=$(ip addr show dev "$dev" | grep -w inet | sed 's/^\s*inet\s\(\S*\)\/.*$/\1/') + dev=$(ip route show default | awk '{for(i=1;i<=NF;i++) if($i=="dev"){print $(i+1); exit}}') + addr=$(ip addr show dev "$dev" | awk '/inet /{gsub(/\/.*/, "", $2); print $2; exit}') iptables-legacy -t nat -A POSTROUTING -o "$dev" -j SNAT --to-source "$addr" -p tcp || true iptables-legacy -t nat -A POSTROUTING -o "$dev" -j SNAT --to-source "$addr" -p udp || true exec dockerd --tls=false --mtu=1200 --registry-mirror=http://private-docker-registry:5000 --host=tcp://127.0.0.1:2375 --storage-driver=vfs --feature containerd-snapshotter=false --iptables=false --ip6tables=false From 5d37aaed830d5366cd566844aac8da96b5eb790a Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Thu, 4 Jun 2026 20:12:23 -0700 Subject: [PATCH 18/30] debug: add set -x to gVisor dind startup script --- .../dind/templates/_helpers.tpl | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/charts/sourcegraph-executor/dind/templates/_helpers.tpl b/charts/sourcegraph-executor/dind/templates/_helpers.tpl index 466b3fc9..b1a5d6a0 100644 --- a/charts/sourcegraph-executor/dind/templates/_helpers.tpl +++ b/charts/sourcegraph-executor/dind/templates/_helpers.tpl @@ -276,13 +276,18 @@ spec: - /bin/sh - -c - | - ip link del docker0 2>/dev/null || true - ip link add name docker0 type bridge 2>/dev/null || true - ip addr add 172.17.0.1/16 dev docker0 2>/dev/null || true - ip link set docker0 up 2>/dev/null || true + set -x + ip link del docker0 || true + ip link show 2>&1 + ip link add name docker0 type bridge || true + ip link show docker0 2>&1 + ip addr add 172.17.0.1/16 dev docker0 || true + ip link set docker0 up || true echo 1 > /proc/sys/net/ipv4/ip_forward dev=$(ip route show default | awk '{for(i=1;i<=NF;i++) if($i=="dev"){print $(i+1); exit}}') + echo "dev=$dev" addr=$(ip addr show dev "$dev" | awk '/inet /{gsub(/\/.*/, "", $2); print $2; exit}') + echo "addr=$addr" iptables-legacy -t nat -A POSTROUTING -o "$dev" -j SNAT --to-source "$addr" -p tcp || true iptables-legacy -t nat -A POSTROUTING -o "$dev" -j SNAT --to-source "$addr" -p udp || true exec dockerd --tls=false --mtu=1200 --registry-mirror=http://private-docker-registry:5000 --host=tcp://127.0.0.1:2375 --storage-driver=vfs --feature containerd-snapshotter=false --iptables=false --ip6tables=false From f2ec606c059365df7c62fd9896b20424dc5127fe Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Thu, 4 Jun 2026 20:14:13 -0700 Subject: [PATCH 19/30] fix(dind/gvisor): let Docker create docker0 itself instead of pre-creating MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit gVisor's netlink implementation does not report IFLA_INFO_KIND="bridge" when querying an interface created with `ip link add type bridge`. This causes Docker's bridge driver to fail the pre-existing interface type check (link.Type() != "bridge"). The fix: don't pre-create docker0. When Docker creates it via Go's netlink library (bridgeAlreadyExists=false), the type check is skipped entirely. Keep `ip link del docker0` for restart resilience — on CrashLoopBackOff restarts, docker0 from the previous run is deleted before dockerd starts, so Docker always sees it as a fresh create. Co-Authored-By: Claude Sonnet 4.6 --- .../sourcegraph-executor/dind/templates/_helpers.tpl | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/charts/sourcegraph-executor/dind/templates/_helpers.tpl b/charts/sourcegraph-executor/dind/templates/_helpers.tpl index b1a5d6a0..ac52818a 100644 --- a/charts/sourcegraph-executor/dind/templates/_helpers.tpl +++ b/charts/sourcegraph-executor/dind/templates/_helpers.tpl @@ -276,18 +276,10 @@ spec: - /bin/sh - -c - | - set -x - ip link del docker0 || true - ip link show 2>&1 - ip link add name docker0 type bridge || true - ip link show docker0 2>&1 - ip addr add 172.17.0.1/16 dev docker0 || true - ip link set docker0 up || true + ip link del docker0 2>/dev/null || true echo 1 > /proc/sys/net/ipv4/ip_forward dev=$(ip route show default | awk '{for(i=1;i<=NF;i++) if($i=="dev"){print $(i+1); exit}}') - echo "dev=$dev" addr=$(ip addr show dev "$dev" | awk '/inet /{gsub(/\/.*/, "", $2); print $2; exit}') - echo "addr=$addr" iptables-legacy -t nat -A POSTROUTING -o "$dev" -j SNAT --to-source "$addr" -p tcp || true iptables-legacy -t nat -A POSTROUTING -o "$dev" -j SNAT --to-source "$addr" -p udp || true exec dockerd --tls=false --mtu=1200 --registry-mirror=http://private-docker-registry:5000 --host=tcp://127.0.0.1:2375 --storage-driver=vfs --feature containerd-snapshotter=false --iptables=false --ip6tables=false From 31bb5681d33b33d13d554e6769885f462674d878 Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Thu, 4 Jun 2026 20:18:26 -0700 Subject: [PATCH 20/30] fix(dind): change probe from tcpSocket to exec for 127.0.0.1 bind MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit tcpSocket probes connect from the kubelet using the pod IP, not 127.0.0.1, so they always fail when dockerd is bound to localhost only. After failureThreshold (5 × 5s = 25s past initialDelay), kubelet kills dind — leaving docker0 in the network namespace and causing the "existing interface docker0 is not a bridge" error on the next restart. Switch to exec probe using `docker -H tcp://127.0.0.1:2375 version`, which runs inside the container and can reach the loopback address. Co-Authored-By: Claude Sonnet 4.6 --- .../dind/templates/_helpers.tpl | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/charts/sourcegraph-executor/dind/templates/_helpers.tpl b/charts/sourcegraph-executor/dind/templates/_helpers.tpl index ac52818a..12bc795b 100644 --- a/charts/sourcegraph-executor/dind/templates/_helpers.tpl +++ b/charts/sourcegraph-executor/dind/templates/_helpers.tpl @@ -292,14 +292,22 @@ spec: - --host=tcp://127.0.0.1:2375 {{- end }} livenessProbe: - tcpSocket: - port: 2375 + exec: + command: + - docker + - -H + - tcp://127.0.0.1:2375 + - version initialDelaySeconds: 15 periodSeconds: 5 failureThreshold: 5 readinessProbe: - tcpSocket: - port: 2375 + exec: + command: + - docker + - -H + - tcp://127.0.0.1:2375 + - version initialDelaySeconds: 20 periodSeconds: 5 failureThreshold: 5 From dad12426f9b86680af77214f9c0de7de66ebb51e Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Thu, 4 Jun 2026 21:15:11 -0700 Subject: [PATCH 21/30] refactor(dind): move gVisor daemon flags into daemon.json via mergeOverwrite Instead of appending gVisor-specific flags to the dockerd command, merge them into daemon.json via the ConfigMap template using mergeOverwrite. - Add dind.gVisor.daemonConfig with the gVisor defaults: storage-driver, iptables, ip6tables, features.containerd-snapshotter - ConfigMap deep-merges gVisor.daemonConfig into dind.daemonConfig when gVisor is enabled, so users can override individual keys if needed - Exec line is now identical for both gVisor and non-gVisor paths Co-Authored-By: Claude Sonnet 4.6 --- .../sourcegraph-executor/dind/templates/_helpers.tpl | 2 +- .../templates/executor/docker-daemon.ConfigMap.yaml | 6 +++++- charts/sourcegraph-executor/dind/values.yaml | 10 +++++++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/charts/sourcegraph-executor/dind/templates/_helpers.tpl b/charts/sourcegraph-executor/dind/templates/_helpers.tpl index 12bc795b..1f3d1d02 100644 --- a/charts/sourcegraph-executor/dind/templates/_helpers.tpl +++ b/charts/sourcegraph-executor/dind/templates/_helpers.tpl @@ -282,7 +282,7 @@ spec: addr=$(ip addr show dev "$dev" | awk '/inet /{gsub(/\/.*/, "", $2); print $2; exit}') iptables-legacy -t nat -A POSTROUTING -o "$dev" -j SNAT --to-source "$addr" -p tcp || true iptables-legacy -t nat -A POSTROUTING -o "$dev" -j SNAT --to-source "$addr" -p udp || true - exec dockerd --tls=false --mtu=1200 --registry-mirror=http://private-docker-registry:5000 --host=tcp://127.0.0.1:2375 --storage-driver=vfs --feature containerd-snapshotter=false --iptables=false --ip6tables=false + exec dockerd --tls=false --mtu=1200 --registry-mirror=http://private-docker-registry:5000 --host=tcp://127.0.0.1:2375 {{- else }} command: - dockerd diff --git a/charts/sourcegraph-executor/dind/templates/executor/docker-daemon.ConfigMap.yaml b/charts/sourcegraph-executor/dind/templates/executor/docker-daemon.ConfigMap.yaml index 1a767bd5..5d244e42 100644 --- a/charts/sourcegraph-executor/dind/templates/executor/docker-daemon.ConfigMap.yaml +++ b/charts/sourcegraph-executor/dind/templates/executor/docker-daemon.ConfigMap.yaml @@ -8,4 +8,8 @@ metadata: name: docker-config data: daemon.json: | - {{- .Values.dind.daemonConfig | toPrettyJson | nindent 4 }} + {{- $config := .Values.dind.daemonConfig | deepCopy }} + {{- if .Values.dind.gVisor.enabled }} + {{- $config = mergeOverwrite $config .Values.dind.gVisor.daemonConfig }} + {{- end }} + {{- $config | toPrettyJson | nindent 4 }} diff --git a/charts/sourcegraph-executor/dind/values.yaml b/charts/sourcegraph-executor/dind/values.yaml index bca52b95..64288a0e 100644 --- a/charts/sourcegraph-executor/dind/values.yaml +++ b/charts/sourcegraph-executor/dind/values.yaml @@ -134,8 +134,16 @@ dind: # -- Enable gVisor sandbox (GKE only). Requires the GKE node pool to have sandbox type set to gvisor. # When enabled, sets runtimeClassName: gvisor on executor pods and replaces privileged: true with # explicit capabilities — these are intercepted in-sandbox and never granted to the host kernel. - # See: https://gvisor.dev/docs/tutorials/docker-in-gke-sandbox/ + # See: https://gvisor.dev/docs/tutorials/docker-in-gvisor/ enabled: false + # -- Extra daemon.json settings merged into dind.daemonConfig when gVisor is enabled. + # These defaults configure Docker to work within gVisor's kernel constraints. + daemonConfig: + storage-driver: vfs + iptables: false + ip6tables: false + features: + containerd-snapshotter: false privateDockerRegistry: # -- Whether to deploy the private registry. Only one registry is needed when deploying multiple executors. From ecefa7387a853e92b354e55f397561fe19264885 Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Thu, 4 Jun 2026 21:19:03 -0700 Subject: [PATCH 22/30] =?UTF-8?q?refactor(dind):=20unify=20command=20block?= =?UTF-8?q?=20=E2=80=94=20single=20declaration,=20conditional=20body?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move the {{- if gVisor }} inside the command: block instead of duplicating the whole block, eliminating the repeated dockerd arguments. Co-Authored-By: Claude Sonnet 4.6 --- charts/sourcegraph-executor/dind/templates/_helpers.tpl | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/charts/sourcegraph-executor/dind/templates/_helpers.tpl b/charts/sourcegraph-executor/dind/templates/_helpers.tpl index 1f3d1d02..dd1a8a2a 100644 --- a/charts/sourcegraph-executor/dind/templates/_helpers.tpl +++ b/charts/sourcegraph-executor/dind/templates/_helpers.tpl @@ -271,8 +271,8 @@ spec: {{- else }} privileged: true {{- end }} - {{- if $r.Values.dind.gVisor.enabled }} command: + {{- if $r.Values.dind.gVisor.enabled }} - /bin/sh - -c - | @@ -283,14 +283,13 @@ spec: iptables-legacy -t nat -A POSTROUTING -o "$dev" -j SNAT --to-source "$addr" -p tcp || true iptables-legacy -t nat -A POSTROUTING -o "$dev" -j SNAT --to-source "$addr" -p udp || true exec dockerd --tls=false --mtu=1200 --registry-mirror=http://private-docker-registry:5000 --host=tcp://127.0.0.1:2375 - {{- else }} - command: + {{- else }} - dockerd - --tls=false - --mtu=1200 - --registry-mirror=http://private-docker-registry:5000 - --host=tcp://127.0.0.1:2375 - {{- end }} + {{- end }} livenessProbe: exec: command: From b88764847f5b6e7cf80298af793abc89cd9de160 Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Thu, 4 Jun 2026 21:21:52 -0700 Subject: [PATCH 23/30] refactor(dind): move all dockerd flags into daemon.json tls, mtu, hosts, registry-mirrors are now in dind.daemonConfig so the command is just [dockerd] (non-gVisor) or [/bin/sh, -c, setup+exec dockerd] (gVisor). No flags passed on the command line. Co-Authored-By: Claude Sonnet 4.6 --- charts/sourcegraph-executor/dind/templates/_helpers.tpl | 6 +----- charts/sourcegraph-executor/dind/values.yaml | 6 ++++++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/charts/sourcegraph-executor/dind/templates/_helpers.tpl b/charts/sourcegraph-executor/dind/templates/_helpers.tpl index dd1a8a2a..1ab16985 100644 --- a/charts/sourcegraph-executor/dind/templates/_helpers.tpl +++ b/charts/sourcegraph-executor/dind/templates/_helpers.tpl @@ -282,13 +282,9 @@ spec: addr=$(ip addr show dev "$dev" | awk '/inet /{gsub(/\/.*/, "", $2); print $2; exit}') iptables-legacy -t nat -A POSTROUTING -o "$dev" -j SNAT --to-source "$addr" -p tcp || true iptables-legacy -t nat -A POSTROUTING -o "$dev" -j SNAT --to-source "$addr" -p udp || true - exec dockerd --tls=false --mtu=1200 --registry-mirror=http://private-docker-registry:5000 --host=tcp://127.0.0.1:2375 + exec dockerd {{- else }} - dockerd - - --tls=false - - --mtu=1200 - - --registry-mirror=http://private-docker-registry:5000 - - --host=tcp://127.0.0.1:2375 {{- end }} livenessProbe: exec: diff --git a/charts/sourcegraph-executor/dind/values.yaml b/charts/sourcegraph-executor/dind/values.yaml index 64288a0e..6bf40c2e 100644 --- a/charts/sourcegraph-executor/dind/values.yaml +++ b/charts/sourcegraph-executor/dind/values.yaml @@ -128,6 +128,12 @@ dind: # -- Docker daemon configuration passed as daemon.json to the dind sidecar. # Learn more from: https://docs.docker.com/reference/cli/dockerd/#on-linux daemonConfig: + tls: false + mtu: 1200 + hosts: + - tcp://127.0.0.1:2375 + registry-mirrors: + - http://private-docker-registry:5000 insecure-registries: - private-docker-registry:5000 gVisor: From 2396cf9d5dad541e9bfd0e46e3cc3b792b5fd596 Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Thu, 4 Jun 2026 21:24:54 -0700 Subject: [PATCH 24/30] fix up --- charts/sourcegraph-executor/dind/README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/charts/sourcegraph-executor/dind/README.md b/charts/sourcegraph-executor/dind/README.md index 140432cf..8d2e0445 100644 --- a/charts/sourcegraph-executor/dind/README.md +++ b/charts/sourcegraph-executor/dind/README.md @@ -58,10 +58,12 @@ In addition to the documented values, the `executor` and `private-docker-registr | Key | Type | Default | Description | |-----|------|---------|-------------| -| dind.daemonConfig | object | `{"insecure-registries":["private-docker-registry:5000"]}` | Docker daemon configuration passed as daemon.json to the dind sidecar. Learn more from: https://docs.docker.com/reference/cli/dockerd/#on-linux | +| dind.daemonConfig | object | `{"hosts":["tcp://127.0.0.1:2375"],"insecure-registries":["private-docker-registry:5000"],"mtu":1200,"registry-mirrors":["http://private-docker-registry:5000"],"tls":false}` | Docker daemon configuration passed as daemon.json to the dind sidecar. Learn more from: https://docs.docker.com/reference/cli/dockerd/#on-linux | +| dind.gVisor.daemonConfig | object | `{"features":{"containerd-snapshotter":false},"ip6tables":false,"iptables":false,"storage-driver":"vfs"}` | Extra daemon.json settings merged into dind.daemonConfig when gVisor is enabled. These defaults configure Docker to work within gVisor's kernel constraints. | +| dind.gVisor.enabled | bool | `false` | Enable gVisor sandbox (GKE only). Requires the GKE node pool to have sandbox type set to gvisor. When enabled, sets runtimeClassName: gvisor on executor pods and replaces privileged: true with explicit capabilities — these are intercepted in-sandbox and never granted to the host kernel. See: https://gvisor.dev/docs/tutorials/docker-in-gvisor/ | | dind.image.registry | string | `"index.docker.io"` | | | dind.image.repository | string | `"docker"` | | -| dind.image.tag | string | `"20.10.22-dind"` | | +| dind.image.tag | string | `"29.5.3-dind"` | | | executor.env | object | `{}` | Extra environment variables to set on the executor container. Must NOT contain managed env vars (EXECUTOR_FRONTEND_URL, EXECUTOR_FRONTEND_PASSWORD, EXECUTOR_QUEUE_NAME, EXECUTOR_QUEUE_NAMES, SRC_LOG_LEVEL, SRC_LOG_FORMAT, EXECUTOR_MAXIMUM_NUM_JOBS, EXECUTOR_MAXIMUM_RUNTIME_PER_JOB, EXECUTOR_DOCKER_ADD_HOST_GATEWAY, EXECUTOR_KEEP_WORKSPACES). | | executor.frontendExistingSecret | string | `""` | Name of existing k8s Secret to use for frontend password. The k8s Secret must contain the key EXECUTOR_FRONTEND_PASSWORD matching the site config executors.accessToken value. frontendPassword is ignored if this is set. | | executor.frontendPassword | string | `""` | The shared secret configured in the Sourcegraph instance site config under executors.accessToken. Required if frontendExistingSecret is not configured. | From 365f89a32c79a81300203ddd50416d7a4133c43b Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Thu, 4 Jun 2026 22:51:29 -0700 Subject: [PATCH 25/30] fix up --- .../dind/examples/gcp/values.yaml | 17 +++++++++++++++++ .../dind/templates/_helpers.tpl | 9 +++++++++ .../executor/docker-daemon.ConfigMap.yaml | 6 +----- 3 files changed, 27 insertions(+), 5 deletions(-) create mode 100644 charts/sourcegraph-executor/dind/examples/gcp/values.yaml diff --git a/charts/sourcegraph-executor/dind/examples/gcp/values.yaml b/charts/sourcegraph-executor/dind/examples/gcp/values.yaml new file mode 100644 index 00000000..465d6029 --- /dev/null +++ b/charts/sourcegraph-executor/dind/examples/gcp/values.yaml @@ -0,0 +1,17 @@ +storageClass: + create: false + name: standard-rwo + +executor: + replicaCount: 4 + frontendUrl: "http://" + frontendPassword: "" + queueNames: ["batches", "codeintel"] + log: + format: "json_gcp" + +dind: + # enable gVisor to run executor instances on GKE Sandbox + # for security hardening. + gVisor: + enabled: true diff --git a/charts/sourcegraph-executor/dind/templates/_helpers.tpl b/charts/sourcegraph-executor/dind/templates/_helpers.tpl index 1ab16985..eb00d73e 100644 --- a/charts/sourcegraph-executor/dind/templates/_helpers.tpl +++ b/charts/sourcegraph-executor/dind/templates/_helpers.tpl @@ -114,6 +114,14 @@ sourcegraph-resource-requires: no-cluster-admin app.kubernetes.io/component: executor {{- end}} +{{- define "dind.daemonConfig" -}} +{{- $config := .Values.dind.daemonConfig | deepCopy }} +{{- if .Values.dind.gVisor.enabled }} +{{- $config = mergeOverwrite $config .Values.dind.gVisor.daemonConfig }} +{{- end }} +{{- $config | toPrettyJson }} +{{- end }} + {{/* Render a single executor Deployment. Usage: include "executor.deployment" (dict "root" $ "name" "executor-foo" "queueName" "foo" "queueNames" (list) "replicaCount" 1 "resources" $res "env" $env) @@ -153,6 +161,7 @@ spec: metadata: annotations: kubectl.kubernetes.io/default-container: executor + checksum/docker-config: {{ include "dind.daemonConfig" $r | sha256sum }} {{- if $r.Values.sourcegraph.podAnnotations }} {{- toYaml $r.Values.sourcegraph.podAnnotations | nindent 8 }} {{- end }} diff --git a/charts/sourcegraph-executor/dind/templates/executor/docker-daemon.ConfigMap.yaml b/charts/sourcegraph-executor/dind/templates/executor/docker-daemon.ConfigMap.yaml index 5d244e42..ecd96f99 100644 --- a/charts/sourcegraph-executor/dind/templates/executor/docker-daemon.ConfigMap.yaml +++ b/charts/sourcegraph-executor/dind/templates/executor/docker-daemon.ConfigMap.yaml @@ -8,8 +8,4 @@ metadata: name: docker-config data: daemon.json: | - {{- $config := .Values.dind.daemonConfig | deepCopy }} - {{- if .Values.dind.gVisor.enabled }} - {{- $config = mergeOverwrite $config .Values.dind.gVisor.daemonConfig }} - {{- end }} - {{- $config | toPrettyJson | nindent 4 }} + {{- include "dind.daemonConfig" . | nindent 4 }} From a815cbf0c8e95350aa5beda65172d23496525046 Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Fri, 5 Jun 2026 09:12:16 -0700 Subject: [PATCH 26/30] refactor(dind): move gVisor securityContext and setupScript into values Extract the hardcoded capabilities list and shell setup script out of the template and into dind.gVisor.securityContext and dind.gVisor.setupScript, following the same pattern as daemonConfig. Both fields are fully overridable in user values files. Co-Authored-By: Claude Sonnet 4.6 --- .../dind/templates/_helpers.tpl | 27 ++-------------- charts/sourcegraph-executor/dind/values.yaml | 32 +++++++++++++++++++ 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/charts/sourcegraph-executor/dind/templates/_helpers.tpl b/charts/sourcegraph-executor/dind/templates/_helpers.tpl index eb00d73e..48697806 100644 --- a/charts/sourcegraph-executor/dind/templates/_helpers.tpl +++ b/charts/sourcegraph-executor/dind/templates/_helpers.tpl @@ -258,25 +258,7 @@ spec: imagePullPolicy: {{ $r.Values.sourcegraph.image.pullPolicy }} securityContext: {{- if $r.Values.dind.gVisor.enabled }} - capabilities: - add: - - NET_ADMIN - - SYS_ADMIN - - AUDIT_WRITE - - CHOWN - - DAC_OVERRIDE - - FOWNER - - FSETID - - KILL - - MKNOD - - NET_BIND_SERVICE - - NET_RAW - - SETFCAP - - SETGID - - SETPCAP - - SETUID - - SYS_CHROOT - - SYS_PTRACE + {{- toYaml $r.Values.dind.gVisor.securityContext | nindent 12 }} {{- else }} privileged: true {{- end }} @@ -285,12 +267,7 @@ spec: - /bin/sh - -c - | - ip link del docker0 2>/dev/null || true - echo 1 > /proc/sys/net/ipv4/ip_forward - dev=$(ip route show default | awk '{for(i=1;i<=NF;i++) if($i=="dev"){print $(i+1); exit}}') - addr=$(ip addr show dev "$dev" | awk '/inet /{gsub(/\/.*/, "", $2); print $2; exit}') - iptables-legacy -t nat -A POSTROUTING -o "$dev" -j SNAT --to-source "$addr" -p tcp || true - iptables-legacy -t nat -A POSTROUTING -o "$dev" -j SNAT --to-source "$addr" -p udp || true + {{- $r.Values.dind.gVisor.setupScript | trim | nindent 14 }} exec dockerd {{- else }} - dockerd diff --git a/charts/sourcegraph-executor/dind/values.yaml b/charts/sourcegraph-executor/dind/values.yaml index 6bf40c2e..ff2c597a 100644 --- a/charts/sourcegraph-executor/dind/values.yaml +++ b/charts/sourcegraph-executor/dind/values.yaml @@ -150,6 +150,38 @@ dind: ip6tables: false features: containerd-snapshotter: false + # -- securityContext for the dind container when gVisor is enabled. + # Replaces privileged: true — gVisor intercepts these capabilities in-sandbox and never + # grants them to the host kernel. + securityContext: + capabilities: + add: + - NET_ADMIN + - SYS_ADMIN + - AUDIT_WRITE + - CHOWN + - DAC_OVERRIDE + - FOWNER + - FSETID + - KILL + - MKNOD + - NET_BIND_SERVICE + - NET_RAW + - SETFCAP + - SETGID + - SETPCAP + - SETUID + - SYS_CHROOT + - SYS_PTRACE + # -- Shell script run before dockerd on gVisor nodes. + # Prepares the network environment that gVisor does not initialise automatically. + setupScript: | + ip link del docker0 2>/dev/null || true + echo 1 > /proc/sys/net/ipv4/ip_forward + dev=$(ip route show default | awk '{for(i=1;i<=NF;i++) if($i=="dev"){print $(i+1); exit}}') + addr=$(ip addr show dev "$dev" | awk '/inet /{gsub(/\/.*/, "", $2); print $2; exit}') + iptables-legacy -t nat -A POSTROUTING -o "$dev" -j SNAT --to-source "$addr" -p tcp || true + iptables-legacy -t nat -A POSTROUTING -o "$dev" -j SNAT --to-source "$addr" -p udp || true privateDockerRegistry: # -- Whether to deploy the private registry. Only one registry is needed when deploying multiple executors. From e637b80a6227248a0403d0abbd5ad46ebd5afa85 Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Fri, 5 Jun 2026 09:20:37 -0700 Subject: [PATCH 27/30] refactor(dind): replace setupScript with dind.command / dind.gVisor.command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add dind.command (default: [dockerd]) and dind.gVisor.command (the gVisor shell wrapper) as plain YAML arrays in values. Template renders whichever is active via toYaml — no string interpolation needed. Removes the setupScript field. Co-Authored-By: Claude Sonnet 4.6 --- .../dind/templates/_helpers.tpl | 8 ++---- charts/sourcegraph-executor/dind/values.yaml | 26 ++++++++++++------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/charts/sourcegraph-executor/dind/templates/_helpers.tpl b/charts/sourcegraph-executor/dind/templates/_helpers.tpl index 48697806..9e6be840 100644 --- a/charts/sourcegraph-executor/dind/templates/_helpers.tpl +++ b/charts/sourcegraph-executor/dind/templates/_helpers.tpl @@ -264,13 +264,9 @@ spec: {{- end }} command: {{- if $r.Values.dind.gVisor.enabled }} - - /bin/sh - - -c - - | - {{- $r.Values.dind.gVisor.setupScript | trim | nindent 14 }} - exec dockerd + {{- toYaml $r.Values.dind.gVisor.command | nindent 12 }} {{- else }} - - dockerd + {{- toYaml $r.Values.dind.command | nindent 12 }} {{- end }} livenessProbe: exec: diff --git a/charts/sourcegraph-executor/dind/values.yaml b/charts/sourcegraph-executor/dind/values.yaml index ff2c597a..0ba60572 100644 --- a/charts/sourcegraph-executor/dind/values.yaml +++ b/charts/sourcegraph-executor/dind/values.yaml @@ -125,6 +125,9 @@ dind: registry: index.docker.io repository: docker tag: 29.5.3-dind + # -- Command for the dind container. + command: + - dockerd # -- Docker daemon configuration passed as daemon.json to the dind sidecar. # Learn more from: https://docs.docker.com/reference/cli/dockerd/#on-linux daemonConfig: @@ -173,15 +176,20 @@ dind: - SETUID - SYS_CHROOT - SYS_PTRACE - # -- Shell script run before dockerd on gVisor nodes. - # Prepares the network environment that gVisor does not initialise automatically. - setupScript: | - ip link del docker0 2>/dev/null || true - echo 1 > /proc/sys/net/ipv4/ip_forward - dev=$(ip route show default | awk '{for(i=1;i<=NF;i++) if($i=="dev"){print $(i+1); exit}}') - addr=$(ip addr show dev "$dev" | awk '/inet /{gsub(/\/.*/, "", $2); print $2; exit}') - iptables-legacy -t nat -A POSTROUTING -o "$dev" -j SNAT --to-source "$addr" -p tcp || true - iptables-legacy -t nat -A POSTROUTING -o "$dev" -j SNAT --to-source "$addr" -p udp || true + # -- Command for the dind container when gVisor is enabled. + # Overrides dind.command. Prepares the network environment that gVisor does not + # initialise automatically before handing off to dockerd. + command: + - /bin/sh + - -c + - | + ip link del docker0 2>/dev/null || true + echo 1 > /proc/sys/net/ipv4/ip_forward + dev=$(ip route show default | awk '{for(i=1;i<=NF;i++) if($i=="dev"){print $(i+1); exit}}') + addr=$(ip addr show dev "$dev" | awk '/inet /{gsub(/\/.*/, "", $2); print $2; exit}') + iptables-legacy -t nat -A POSTROUTING -o "$dev" -j SNAT --to-source "$addr" -p tcp || true + iptables-legacy -t nat -A POSTROUTING -o "$dev" -j SNAT --to-source "$addr" -p udp || true + exec dockerd privateDockerRegistry: # -- Whether to deploy the private registry. Only one registry is needed when deploying multiple executors. From 5fff99003e63fb2b0a2ec9ed657aa5592bbe3414 Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Fri, 5 Jun 2026 12:55:45 -0700 Subject: [PATCH 28/30] fix up --- charts/sourcegraph-executor/dind/README.md | 6 ++++++ .../dind/examples/gcp/values.yaml | 4 ++++ .../dind/templates/_helpers.tpl | 18 +++++++++++++++++- charts/sourcegraph-executor/dind/values.yaml | 12 ++++++++++++ 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/charts/sourcegraph-executor/dind/README.md b/charts/sourcegraph-executor/dind/README.md index 8d2e0445..3a1e7f76 100644 --- a/charts/sourcegraph-executor/dind/README.md +++ b/charts/sourcegraph-executor/dind/README.md @@ -58,9 +58,12 @@ In addition to the documented values, the `executor` and `private-docker-registr | Key | Type | Default | Description | |-----|------|---------|-------------| +| dind.command | list | `["dockerd"]` | Command for the dind container. | | dind.daemonConfig | object | `{"hosts":["tcp://127.0.0.1:2375"],"insecure-registries":["private-docker-registry:5000"],"mtu":1200,"registry-mirrors":["http://private-docker-registry:5000"],"tls":false}` | Docker daemon configuration passed as daemon.json to the dind sidecar. Learn more from: https://docs.docker.com/reference/cli/dockerd/#on-linux | +| dind.gVisor.command | list | `["/bin/sh","-c","ip link del docker0 2>/dev/null || true\necho 1 > /proc/sys/net/ipv4/ip_forward\ndev=$(ip route show default | awk '{for(i=1;i<=NF;i++) if($i==\"dev\"){print $(i+1); exit}}')\naddr=$(ip addr show dev \"$dev\" | awk '/inet /{gsub(/\\/.*/, \"\", $2); print $2; exit}')\niptables-legacy -t nat -A POSTROUTING -o \"$dev\" -j SNAT --to-source \"$addr\" -p tcp || true\niptables-legacy -t nat -A POSTROUTING -o \"$dev\" -j SNAT --to-source \"$addr\" -p udp || true\nexec dockerd\n"]` | Command for the dind container when gVisor is enabled. Overrides dind.command. Prepares the network environment that gVisor does not initialise automatically before handing off to dockerd. | | dind.gVisor.daemonConfig | object | `{"features":{"containerd-snapshotter":false},"ip6tables":false,"iptables":false,"storage-driver":"vfs"}` | Extra daemon.json settings merged into dind.daemonConfig when gVisor is enabled. These defaults configure Docker to work within gVisor's kernel constraints. | | dind.gVisor.enabled | bool | `false` | Enable gVisor sandbox (GKE only). Requires the GKE node pool to have sandbox type set to gvisor. When enabled, sets runtimeClassName: gvisor on executor pods and replaces privileged: true with explicit capabilities — these are intercepted in-sandbox and never granted to the host kernel. See: https://gvisor.dev/docs/tutorials/docker-in-gvisor/ | +| dind.gVisor.securityContext | object | `{"capabilities":{"add":["NET_ADMIN","SYS_ADMIN","AUDIT_WRITE","CHOWN","DAC_OVERRIDE","FOWNER","FSETID","KILL","MKNOD","NET_BIND_SERVICE","NET_RAW","SETFCAP","SETGID","SETPCAP","SETUID","SYS_CHROOT","SYS_PTRACE"]}}` | securityContext for the dind container when gVisor is enabled. Replaces privileged: true — gVisor intercepts these capabilities in-sandbox and never grants them to the host kernel. | | dind.image.registry | string | `"index.docker.io"` | | | dind.image.repository | string | `"docker"` | | | dind.image.tag | string | `"29.5.3-dind"` | | @@ -78,6 +81,9 @@ In addition to the documented values, the `executor` and `private-docker-registr | executor.queueNames | list | `[]` | The names of multiple queues to pull jobs from. Possible values: batches and codeintel. Either this or queueName is required (when not using queues). | | executor.replicaCount | int | `1` | | | executor.resources | object | `{}` | Resource requests and limits for the executor container. Each queue can override this with its own resources field. | +| executor.storage.class | string | `""` | StorageClass for the ephemeral volume. Only used when type is ephemeral. Defaults to the cluster default StorageClass when empty. | +| executor.storage.size | string | `""` | Size of the scratch volume. emptyDir: sets sizeLimit (optional, leave empty for unlimited). ephemeral: sets the PVC storage request (required). | +| executor.storage.type | string | `"emptyDir"` | Type of scratch volume for job workspaces. One of: emptyDir, ephemeral. emptyDir: plain emptyDir, no storage class required. ephemeral: per-pod PVC via the cluster default storage class; size is required. | | privateDockerRegistry.enabled | bool | `true` | Whether to deploy the private registry. Only one registry is needed when deploying multiple executors. More information: https://docs.sourcegraph.com/admin/executors/deploy_executors#using-private-registries | | privateDockerRegistry.image.registry | string | `"index.docker.io"` | | | privateDockerRegistry.image.repository | string | `"registry"` | | diff --git a/charts/sourcegraph-executor/dind/examples/gcp/values.yaml b/charts/sourcegraph-executor/dind/examples/gcp/values.yaml index 465d6029..feee1a29 100644 --- a/charts/sourcegraph-executor/dind/examples/gcp/values.yaml +++ b/charts/sourcegraph-executor/dind/examples/gcp/values.yaml @@ -9,6 +9,10 @@ executor: queueNames: ["batches", "codeintel"] log: format: "json_gcp" + storage: + type: ephemeral + size: 50Gi + class: premium-rwo dind: # enable gVisor to run executor instances on GKE Sandbox diff --git a/charts/sourcegraph-executor/dind/templates/_helpers.tpl b/charts/sourcegraph-executor/dind/templates/_helpers.tpl index 9e6be840..091512ad 100644 --- a/charts/sourcegraph-executor/dind/templates/_helpers.tpl +++ b/charts/sourcegraph-executor/dind/templates/_helpers.tpl @@ -330,7 +330,23 @@ spec: {{- end }} volumes: - name: executor-scratch - emptyDir: {} + {{- if eq $r.Values.executor.storage.type "ephemeral" }} + ephemeral: + volumeClaimTemplate: + spec: + accessModes: ["ReadWriteOnce"] + {{- if $r.Values.executor.storage.class }} + storageClassName: {{ $r.Values.executor.storage.class }} + {{- end }} + resources: + requests: + storage: {{ required "executor.storage.size is required when storage.type is ephemeral" $r.Values.executor.storage.size }} + {{- else }} + emptyDir: + {{- if $r.Values.executor.storage.size }} + sizeLimit: {{ $r.Values.executor.storage.size }} + {{- end }} + {{- end }} - name: docker-config configMap: defaultMode: 420 diff --git a/charts/sourcegraph-executor/dind/values.yaml b/charts/sourcegraph-executor/dind/values.yaml index 0ba60572..48859e9c 100644 --- a/charts/sourcegraph-executor/dind/values.yaml +++ b/charts/sourcegraph-executor/dind/values.yaml @@ -119,6 +119,18 @@ executor: # EXECUTOR_MAXIMUM_NUM_JOBS, EXECUTOR_MAXIMUM_RUNTIME_PER_JOB, # EXECUTOR_DOCKER_ADD_HOST_GATEWAY, EXECUTOR_KEEP_WORKSPACES). env: {} + storage: + # -- Type of scratch volume for job workspaces. One of: emptyDir, ephemeral. + # emptyDir: plain emptyDir, no storage class required. + # ephemeral: per-pod PVC via the cluster default storage class; size is required. + type: emptyDir + # -- Size of the scratch volume. + # emptyDir: sets sizeLimit (optional, leave empty for unlimited). + # ephemeral: sets the PVC storage request (required). + size: "" + # -- StorageClass for the ephemeral volume. Only used when type is ephemeral. + # Defaults to the cluster default StorageClass when empty. + class: "" dind: image: From 2530b2b7f57d1e12be3385bc7ac1464cddfd5de2 Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Fri, 5 Jun 2026 12:57:32 -0700 Subject: [PATCH 29/30] fix up --- charts/sourcegraph-executor/dind/README.md | 2 +- charts/sourcegraph-executor/dind/values.yaml | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/charts/sourcegraph-executor/dind/README.md b/charts/sourcegraph-executor/dind/README.md index 3a1e7f76..087e9184 100644 --- a/charts/sourcegraph-executor/dind/README.md +++ b/charts/sourcegraph-executor/dind/README.md @@ -67,7 +67,7 @@ In addition to the documented values, the `executor` and `private-docker-registr | dind.image.registry | string | `"index.docker.io"` | | | dind.image.repository | string | `"docker"` | | | dind.image.tag | string | `"29.5.3-dind"` | | -| executor.env | object | `{}` | Extra environment variables to set on the executor container. Must NOT contain managed env vars (EXECUTOR_FRONTEND_URL, EXECUTOR_FRONTEND_PASSWORD, EXECUTOR_QUEUE_NAME, EXECUTOR_QUEUE_NAMES, SRC_LOG_LEVEL, SRC_LOG_FORMAT, EXECUTOR_MAXIMUM_NUM_JOBS, EXECUTOR_MAXIMUM_RUNTIME_PER_JOB, EXECUTOR_DOCKER_ADD_HOST_GATEWAY, EXECUTOR_KEEP_WORKSPACES). | +| executor.env | object | `{}` | Extra environment variables to set on the executor container. | | executor.frontendExistingSecret | string | `""` | Name of existing k8s Secret to use for frontend password. The k8s Secret must contain the key EXECUTOR_FRONTEND_PASSWORD matching the site config executors.accessToken value. frontendPassword is ignored if this is set. | | executor.frontendPassword | string | `""` | The shared secret configured in the Sourcegraph instance site config under executors.accessToken. Required if frontendExistingSecret is not configured. | | executor.frontendUrl | string | `""` | The external URL of the Sourcegraph instance. Required. | diff --git a/charts/sourcegraph-executor/dind/values.yaml b/charts/sourcegraph-executor/dind/values.yaml index 48859e9c..e27885cf 100644 --- a/charts/sourcegraph-executor/dind/values.yaml +++ b/charts/sourcegraph-executor/dind/values.yaml @@ -114,10 +114,6 @@ executor: name: "executor" replicaCount: 1 # -- Extra environment variables to set on the executor container. - # Must NOT contain managed env vars (EXECUTOR_FRONTEND_URL, EXECUTOR_FRONTEND_PASSWORD, - # EXECUTOR_QUEUE_NAME, EXECUTOR_QUEUE_NAMES, SRC_LOG_LEVEL, SRC_LOG_FORMAT, - # EXECUTOR_MAXIMUM_NUM_JOBS, EXECUTOR_MAXIMUM_RUNTIME_PER_JOB, - # EXECUTOR_DOCKER_ADD_HOST_GATEWAY, EXECUTOR_KEEP_WORKSPACES). env: {} storage: # -- Type of scratch volume for job workspaces. One of: emptyDir, ephemeral. From ab01093b37471b2db4b5668d6e8a2119b5ac1333 Mon Sep 17 00:00:00 2001 From: Michael Lin Date: Fri, 5 Jun 2026 13:13:07 -0700 Subject: [PATCH 30/30] fix(dind): use wget /_ping for liveness/readiness probes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace `docker version` with `wget -qO- http://127.0.0.1:2375/_ping` — lighter check against Docker's purpose-built ping endpoint, using busybox wget which is always present in the Alpine-based dind image. Co-Authored-By: Claude Sonnet 4.6 --- .../dind/templates/_helpers.tpl | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/charts/sourcegraph-executor/dind/templates/_helpers.tpl b/charts/sourcegraph-executor/dind/templates/_helpers.tpl index 091512ad..88685139 100644 --- a/charts/sourcegraph-executor/dind/templates/_helpers.tpl +++ b/charts/sourcegraph-executor/dind/templates/_helpers.tpl @@ -271,20 +271,18 @@ spec: livenessProbe: exec: command: - - docker - - -H - - tcp://127.0.0.1:2375 - - version + - wget + - -qO- + - http://127.0.0.1:2375/_ping initialDelaySeconds: 15 periodSeconds: 5 failureThreshold: 5 readinessProbe: exec: command: - - docker - - -H - - tcp://127.0.0.1:2375 - - version + - wget + - -qO- + - http://127.0.0.1:2375/_ping initialDelaySeconds: 20 periodSeconds: 5 failureThreshold: 5