From 3847f3b297b357a724560dc6308b406068547083 Mon Sep 17 00:00:00 2001 From: leo-wr-ps Date: Mon, 24 Nov 2025 23:06:33 +0100 Subject: [PATCH] feat(helm): add priorityClassName support (#20678) **Add priorityClassName support to Coder Helm chart** Add coder.priorityClassName configuration to the Helm chart that allows setting the pod's priorityClassName in the deployment **Usage:** ``` coder: priorityClassName: high-priority ``` See: https://github.com/coder/coder/discussions/20676 --------- Co-authored-by: Rowan Smith --- helm/coder/tests/chart_test.go | 4 + .../tests/testdata/priority_class_name.golden | 206 ++++++++++++++++++ .../tests/testdata/priority_class_name.yaml | 4 + .../testdata/priority_class_name_coder.golden | 206 ++++++++++++++++++ helm/coder/values.yaml | 5 + helm/libcoder/templates/_coder.yaml | 3 + 6 files changed, 428 insertions(+) create mode 100644 helm/coder/tests/testdata/priority_class_name.golden create mode 100644 helm/coder/tests/testdata/priority_class_name.yaml create mode 100644 helm/coder/tests/testdata/priority_class_name_coder.golden diff --git a/helm/coder/tests/chart_test.go b/helm/coder/tests/chart_test.go index 0e6d5cda10..d175bab802 100644 --- a/helm/coder/tests/chart_test.go +++ b/helm/coder/tests/chart_test.go @@ -133,6 +133,10 @@ var testCases = []testCase{ name: "namespace_rbac", expectedError: "", }, + { + name: "priority_class_name", + expectedError: "", + }, } type testCase struct { diff --git a/helm/coder/tests/testdata/priority_class_name.golden b/helm/coder/tests/testdata/priority_class_name.golden new file mode 100644 index 0000000000..0736d9dabb --- /dev/null +++ b/helm/coder/tests/testdata/priority_class_name.golden @@ -0,0 +1,206 @@ +--- +# Source: coder/templates/coder.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + annotations: {} + labels: + app.kubernetes.io/instance: release-name + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: coder + app.kubernetes.io/part-of: coder + app.kubernetes.io/version: 0.1.0 + helm.sh/chart: coder-0.1.0 + name: coder + namespace: default +--- +# Source: coder/templates/rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: coder-workspace-perms + namespace: default +rules: + - apiGroups: [""] + resources: ["pods"] + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch + - apiGroups: [""] + resources: ["persistentvolumeclaims"] + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch + - apiGroups: + - apps + resources: + - deployments + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch +--- +# Source: coder/templates/rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: "coder" + namespace: default +subjects: + - kind: ServiceAccount + name: "coder" +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: coder-workspace-perms +--- +# Source: coder/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: coder + namespace: default + labels: + helm.sh/chart: coder-0.1.0 + app.kubernetes.io/name: coder + app.kubernetes.io/instance: release-name + app.kubernetes.io/part-of: coder + app.kubernetes.io/version: "0.1.0" + app.kubernetes.io/managed-by: Helm + annotations: + {} +spec: + type: LoadBalancer + sessionAffinity: None + ports: + - name: "http" + port: 80 + targetPort: "http" + protocol: TCP + nodePort: + externalTrafficPolicy: "Cluster" + selector: + app.kubernetes.io/name: coder + app.kubernetes.io/instance: release-name +--- +# Source: coder/templates/coder.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: {} + labels: + app.kubernetes.io/instance: release-name + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: coder + app.kubernetes.io/part-of: coder + app.kubernetes.io/version: 0.1.0 + helm.sh/chart: coder-0.1.0 + name: coder + namespace: default +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/instance: release-name + app.kubernetes.io/name: coder + template: + metadata: + annotations: {} + labels: + app.kubernetes.io/instance: release-name + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: coder + app.kubernetes.io/part-of: coder + app.kubernetes.io/version: 0.1.0 + helm.sh/chart: coder-0.1.0 + spec: + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchExpressions: + - key: app.kubernetes.io/instance + operator: In + values: + - coder + topologyKey: kubernetes.io/hostname + weight: 1 + containers: + - args: + - server + command: + - /opt/coder + env: + - name: CODER_HTTP_ADDRESS + value: 0.0.0.0:8080 + - name: CODER_PROMETHEUS_ADDRESS + value: 0.0.0.0:2112 + - name: CODER_PPROF_ADDRESS + value: 0.0.0.0:6060 + - name: CODER_ACCESS_URL + value: http://coder.default.svc.cluster.local + - name: KUBE_POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: CODER_DERP_SERVER_RELAY_URL + value: http://$(KUBE_POD_IP):8080 + image: ghcr.io/coder/coder:latest + imagePullPolicy: IfNotPresent + lifecycle: {} + livenessProbe: + httpGet: + path: /healthz + port: http + scheme: HTTP + initialDelaySeconds: 0 + name: coder + ports: + - containerPort: 8080 + name: http + protocol: TCP + readinessProbe: + httpGet: + path: /healthz + port: http + scheme: HTTP + initialDelaySeconds: 0 + resources: + limits: + cpu: 2000m + memory: 4096Mi + requests: + cpu: 2000m + memory: 4096Mi + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: null + runAsGroup: 1000 + runAsNonRoot: true + runAsUser: 1000 + seccompProfile: + type: RuntimeDefault + volumeMounts: [] + priorityClassName: high-priority + restartPolicy: Always + serviceAccountName: coder + terminationGracePeriodSeconds: 60 + volumes: [] diff --git a/helm/coder/tests/testdata/priority_class_name.yaml b/helm/coder/tests/testdata/priority_class_name.yaml new file mode 100644 index 0000000000..15ed574c28 --- /dev/null +++ b/helm/coder/tests/testdata/priority_class_name.yaml @@ -0,0 +1,4 @@ +coder: + image: + tag: latest + priorityClassName: high-priority diff --git a/helm/coder/tests/testdata/priority_class_name_coder.golden b/helm/coder/tests/testdata/priority_class_name_coder.golden new file mode 100644 index 0000000000..e06d69dcf3 --- /dev/null +++ b/helm/coder/tests/testdata/priority_class_name_coder.golden @@ -0,0 +1,206 @@ +--- +# Source: coder/templates/coder.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + annotations: {} + labels: + app.kubernetes.io/instance: release-name + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: coder + app.kubernetes.io/part-of: coder + app.kubernetes.io/version: 0.1.0 + helm.sh/chart: coder-0.1.0 + name: coder + namespace: coder +--- +# Source: coder/templates/rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: coder-workspace-perms + namespace: coder +rules: + - apiGroups: [""] + resources: ["pods"] + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch + - apiGroups: [""] + resources: ["persistentvolumeclaims"] + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch + - apiGroups: + - apps + resources: + - deployments + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch +--- +# Source: coder/templates/rbac.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: "coder" + namespace: coder +subjects: + - kind: ServiceAccount + name: "coder" +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: coder-workspace-perms +--- +# Source: coder/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: coder + namespace: coder + labels: + helm.sh/chart: coder-0.1.0 + app.kubernetes.io/name: coder + app.kubernetes.io/instance: release-name + app.kubernetes.io/part-of: coder + app.kubernetes.io/version: "0.1.0" + app.kubernetes.io/managed-by: Helm + annotations: + {} +spec: + type: LoadBalancer + sessionAffinity: None + ports: + - name: "http" + port: 80 + targetPort: "http" + protocol: TCP + nodePort: + externalTrafficPolicy: "Cluster" + selector: + app.kubernetes.io/name: coder + app.kubernetes.io/instance: release-name +--- +# Source: coder/templates/coder.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + annotations: {} + labels: + app.kubernetes.io/instance: release-name + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: coder + app.kubernetes.io/part-of: coder + app.kubernetes.io/version: 0.1.0 + helm.sh/chart: coder-0.1.0 + name: coder + namespace: coder +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/instance: release-name + app.kubernetes.io/name: coder + template: + metadata: + annotations: {} + labels: + app.kubernetes.io/instance: release-name + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/name: coder + app.kubernetes.io/part-of: coder + app.kubernetes.io/version: 0.1.0 + helm.sh/chart: coder-0.1.0 + spec: + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchExpressions: + - key: app.kubernetes.io/instance + operator: In + values: + - coder + topologyKey: kubernetes.io/hostname + weight: 1 + containers: + - args: + - server + command: + - /opt/coder + env: + - name: CODER_HTTP_ADDRESS + value: 0.0.0.0:8080 + - name: CODER_PROMETHEUS_ADDRESS + value: 0.0.0.0:2112 + - name: CODER_PPROF_ADDRESS + value: 0.0.0.0:6060 + - name: CODER_ACCESS_URL + value: http://coder.coder.svc.cluster.local + - name: KUBE_POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: CODER_DERP_SERVER_RELAY_URL + value: http://$(KUBE_POD_IP):8080 + image: ghcr.io/coder/coder:latest + imagePullPolicy: IfNotPresent + lifecycle: {} + livenessProbe: + httpGet: + path: /healthz + port: http + scheme: HTTP + initialDelaySeconds: 0 + name: coder + ports: + - containerPort: 8080 + name: http + protocol: TCP + readinessProbe: + httpGet: + path: /healthz + port: http + scheme: HTTP + initialDelaySeconds: 0 + resources: + limits: + cpu: 2000m + memory: 4096Mi + requests: + cpu: 2000m + memory: 4096Mi + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: null + runAsGroup: 1000 + runAsNonRoot: true + runAsUser: 1000 + seccompProfile: + type: RuntimeDefault + volumeMounts: [] + priorityClassName: high-priority + restartPolicy: Always + serviceAccountName: coder + terminationGracePeriodSeconds: 60 + volumes: [] diff --git a/helm/coder/values.yaml b/helm/coder/values.yaml index 467a7d1c57..85a4e4519f 100644 --- a/helm/coder/values.yaml +++ b/helm/coder/values.yaml @@ -82,6 +82,11 @@ coder: # https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ podLabels: {} + # coder.priorityClassName -- The priority class name to assign to the Coder pod. See: + # https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ + # The PriorityClass must exist in the cluster prior to deploying Coder with this set. + priorityClassName: "" + # coder.serviceAccount -- Configuration for the automatically created service # account. Creation of the service account cannot be disabled. serviceAccount: diff --git a/helm/libcoder/templates/_coder.yaml b/helm/libcoder/templates/_coder.yaml index 6001df90d6..52caaf5891 100644 --- a/helm/libcoder/templates/_coder.yaml +++ b/helm/libcoder/templates/_coder.yaml @@ -26,6 +26,9 @@ spec: {{- toYaml .Values.coder.podAnnotations | nindent 8 }} spec: serviceAccountName: {{ .Values.coder.serviceAccount.name | quote }} + {{- with .Values.coder.priorityClassName }} + priorityClassName: {{ . | quote }} + {{- end }} {{- with .Values.coder.podSecurityContext }} securityContext: {{- toYaml . | nindent 8 }}