Skip to content

Commit

Permalink
Merge pull request #634 from rstudio/kegs/job-resources-overrides
Browse files Browse the repository at this point in the history
Add content job template default requests and limits
  • Loading branch information
dbkegley authored Jan 6, 2025
2 parents d6ab67d + 72fc140 commit 6ac3842
Show file tree
Hide file tree
Showing 8 changed files with 378 additions and 8 deletions.
2 changes: 1 addition & 1 deletion charts/rstudio-connect/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: rstudio-connect
description: Official Helm chart for Posit Connect
version: 0.7.18
version: 0.7.19
apiVersion: v2
appVersion: 2024.12.0
icon: https://rstudio.com/wp-content/uploads/2018/10/RStudio-Logo-Flat.png
Expand Down
7 changes: 7 additions & 0 deletions charts/rstudio-connect/NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## 0.7.19

- Allow overriding the default content Job resource requests/limits settings via the values file
using the `launcher.templateValues.pod.resources` key. Note that these settings are applied
globally for _all_ jobs including environment restores, document renders, and interactive
applications.

## 0.7.18

- Bumps Connect version to 2024.12.0
Expand Down
9 changes: 5 additions & 4 deletions charts/rstudio-connect/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Posit Connect

![Version: 0.7.18](https://img.shields.io/badge/Version-0.7.18-informational?style=flat-square) ![AppVersion: 2024.12.0](https://img.shields.io/badge/AppVersion-2024.12.0-informational?style=flat-square)
![Version: 0.7.19](https://img.shields.io/badge/Version-0.7.19-informational?style=flat-square) ![AppVersion: 2024.12.0](https://img.shields.io/badge/AppVersion-2024.12.0-informational?style=flat-square)

#### _Official Helm chart for Posit Connect_

Expand Down Expand Up @@ -30,11 +30,11 @@ To ensure reproducibility in your environment and insulate yourself from future

## Installing the chart

To install the chart with the release name `my-release` at version 0.7.18:
To install the chart with the release name `my-release` at version 0.7.19:

```{.bash}
helm repo add rstudio https://helm.rstudio.com
helm upgrade --install my-release rstudio/rstudio-connect --version=0.7.18
helm upgrade --install my-release rstudio/rstudio-connect --version=0.7.19
```

To explore other chart versions, look at:
Expand Down Expand Up @@ -180,8 +180,9 @@ The Helm `config` values are converted into the `rstudio-connect.gcfg` service c
| launcher.includeTemplateValues | bool | `true` | whether to include the templateValues rendering process |
| launcher.launcherKubernetesProfilesConf | object | `{}` | User definition of launcher.kubernetes.profiles.conf for job customization |
| launcher.namespace | string | `""` | The namespace to launch sessions into. Uses the Release namespace by default |
| launcher.templateValues | object | `{"job":{"annotations":{},"labels":{}},"pod":{"affinity":{},"annotations":{},"command":[],"containerSecurityContext":{},"defaultSecurityContext":{},"env":[],"extraContainers":[],"hostAliases":[],"imagePullPolicy":"","imagePullSecrets":[],"initContainers":[],"labels":{},"nodeSelector":{},"priorityClassName":"","securityContext":{},"serviceAccountName":"","tolerations":[],"volumeMounts":[],"volumes":[]},"service":{"annotations":{},"labels":{},"type":"ClusterIP"}}` | Values to pass along to the Posit Connect session templating process |
| launcher.templateValues | object | `{"job":{"annotations":{},"labels":{}},"pod":{"affinity":{},"annotations":{},"command":[],"containerSecurityContext":{},"defaultSecurityContext":{},"env":[],"extraContainers":[],"hostAliases":[],"imagePullPolicy":"","imagePullSecrets":[],"initContainers":[],"labels":{},"nodeSelector":{},"priorityClassName":"","resources":{"limits":{},"requests":{}},"securityContext":{},"serviceAccountName":"","tolerations":[],"volumeMounts":[],"volumes":[]},"service":{"annotations":{},"labels":{},"type":"ClusterIP"}}` | Values to pass along to the Posit Connect session templating process |
| launcher.templateValues.pod.command | list | `[]` | command for all pods. This is really not something we should expose and will be removed once we have a better option |
| launcher.templateValues.pod.resources | object | `{"limits":{},"requests":{}}` | to be used when none are provided in the content runtime settings |
| launcher.useTemplates | bool | `true` | Whether to use launcher templates when launching sessions. Defaults to true |
| license.file | object | `{"contents":false,"mountPath":"/etc/rstudio-licensing","mountSubPath":false,"secret":false,"secretKey":"license.lic"}` | the file section is used for licensing with a license file |
| license.file.contents | bool | `false` | contents is an in-line license file |
Expand Down
6 changes: 3 additions & 3 deletions charts/rstudio-connect/files/job.tpl
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Version: 2.4.0
# DO NOT MODIFY the "Version: " key
# Helm Version: v1
# Helm Version: v2
{{- $templateData := include "rstudio-library.templates.data" nil | mustFromJson }}
apiVersion: batch/v1
kind: Job
Expand Down Expand Up @@ -244,8 +244,8 @@ spec:
hostPort: {{ .publishedPort }}
{{- end }}
{{- end }}
{{- $limits := dict }}
{{- $requests := dict }}
{{- $limits := $templateData.pod.resources.limits }}
{{- $requests := $templateData.pod.resources.requests }}
{{- range .Job.resourceLimits }}
{{- if eq .type "cpuCount" }}
{{- $_ := set $limits "cpu" .value }}
Expand Down
11 changes: 11 additions & 0 deletions charts/rstudio-connect/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,17 @@ launcher:
env: []
imagePullPolicy: ""
imagePullSecrets: []
# -- sets the default resource requests and limits for Jobs launched by Connect
# -- to be used when none are provided in the content runtime settings
resources:
requests: {}
# memory: "1Gi"
# cpu: "500m"
# ephemeral-storage: "100Mi"
limits: {}
# memory: "1Gi"
# cpu: "500m"
# ephemeral-storage: "100Mi"
initContainers: []
extraContainers: []
containerSecurityContext: {}
Expand Down
4 changes: 4 additions & 0 deletions examples/launcher-templates/helm/2.4.0-v1/job.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ spec:
{{- if or $templateData.pod.serviceAccountName .Job.serviceAccountName }}
serviceAccountName: {{ .Job.serviceAccountName | default $templateData.pod.serviceAccountName | quote }}
{{- end }}
{{- with $templateData.pod.hostAliases }}
hostAliases:
{{- toYaml . | nindent 8 }}
{{- end }}
shareProcessNamespace: {{ .Job.shareProcessNamespace }}
{{- if or (ne (len .Job.volumes) 0) (ne (len $templateData.pod.volumes) 0) }}
volumes:
Expand Down
296 changes: 296 additions & 0 deletions examples/launcher-templates/helm/2.4.0-v2/job.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,296 @@
# Version: 2.4.0
# DO NOT MODIFY the "Version: " key
# Helm Version: v2
{{- $templateData := include "rstudio-library.templates.data" nil | mustFromJson }}
apiVersion: batch/v1
kind: Job
metadata:
annotations:
{{- with .Job.metadata.job.annotations }}
{{- range $key, $val := . }}
{{ $key }}: {{ toYaml $val | indent 4 | trimPrefix (repeat 4 " ") }}
{{- end }}
{{- end }}
{{- with $templateData.job.annotations }}
{{- range $key, $val := . }}
{{ $key }}: {{ toYaml $val | indent 4 | trimPrefix (repeat 4 " ") }}
{{- end }}
{{- end }}
labels:
app.kubernetes.io/managed-by: "launcher"
{{- with .Job.instanceId }}
launcher-instance-id: {{ toYaml . }}
{{- end }}
{{- with .Job.metadata.job.labels }}
{{- range $key, $val := . }}
{{ $key }}: {{ toYaml $val | indent 4 | trimPrefix (repeat 4 " ") }}
{{- end }}
{{- end }}
{{- with $templateData.job.labels }}
{{- range $key, $val := . }}
{{ $key }}: {{ toYaml $val | indent 4 | trimPrefix (repeat 4 " ") }}
{{- end }}
{{- end }}
generateName: {{ toYaml .Job.generateName }}
spec:
{{- if $templateData.job.ttlSecondsAfterFinished }}
ttlSecondsAfterFinished: {{ $templateData.job.ttlSecondsAfterFinished }}
{{- end }}
backoffLimit: 0
template:
metadata:
annotations:
{{- if .Job.tags }}
{{- $i := 0 }}
{{- range .Job.tags }}
USER_TAG_{{ $i }}: {{ toYaml . | indent 8 | trimPrefix (repeat 8 " ") }}
{{- $i = add $i 1 }}
{{- end }}
{{- end }}
stdin: {{ toYaml .Job.stdin | indent 8 | trimPrefix (repeat 8 " ") }}
user: {{ toYaml .Job.user }}
name: {{ toYaml .Job.name }}
service_ports: {{ toYaml .Job.servicePortsJson }}
{{- if .Job.metadata }}
user_metadata: {{ toJson .Job.metadata | toYaml | indent 8 | trimPrefix (repeat 8 " ") }}
{{- end }}
{{- with .Job.metadata.pod.annotations }}
{{- range $key, $val := . }}
{{ $key }}: {{ toYaml $val | indent 8 | trimPrefix (repeat 8 " ") }}
{{- end }}
{{- end }}
{{- with $templateData.pod.annotations }}
{{- range $key, $val := . }}
{{ $key }}: {{ toYaml $val | indent 8 | trimPrefix (repeat 8 " ") }}
{{- end }}
{{- end }}
labels:
{{- with .Job.instanceId }}
launcher-instance-id: {{ toYaml . }}
{{- end }}
{{- with .Job.metadata.pod.labels }}
{{- range $key, $val := . }}
{{ $key }}: {{ toYaml $val | indent 8 | trimPrefix (repeat 8 " ") }}
{{- end }}
{{- end }}
{{- with $templateData.pod.labels }}
{{- range $key, $val := . }}
{{ $key }}: {{ toYaml $val | indent 8 | trimPrefix (repeat 8 " ") }}
{{- end }}
{{- end }}
generateName: {{ toYaml .Job.generateName }}
spec:
{{- if .Job.host }}
nodeName: {{ toYaml .Job.host }}
{{- end }}
enableServiceLinks: {{ if hasKey $templateData.pod "enableServiceLinks" }}{{ $templateData.pod.enableServiceLinks }}{{ else }}false{{ end }}
restartPolicy: Never
{{- if or $templateData.pod.serviceAccountName .Job.serviceAccountName }}
serviceAccountName: {{ .Job.serviceAccountName | default $templateData.pod.serviceAccountName | quote }}
{{- end }}
{{- with $templateData.pod.hostAliases }}
hostAliases:
{{- toYaml . | nindent 8 }}
{{- end }}
shareProcessNamespace: {{ .Job.shareProcessNamespace }}
{{- if or (ne (len .Job.volumes) 0) (ne (len $templateData.pod.volumes) 0) }}
volumes:
{{- range .Job.volumes }}
- {{ nindent 10 (toYaml .) | trim -}}
{{- end }}
{{- range $templateData.pod.volumes }}
- {{ nindent 10 (toYaml .) | trim -}}
{{- end }}
{{- end }}
{{- with $templateData.pod.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with $templateData.pod.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- if or (ne (len .Job.placementConstraints) 0) (and $templateData.pod.nodeSelector (ne (len $templateData.pod.nodeSelector) 0)) }}
nodeSelector:
{{- range .Job.placementConstraints }}
{{ .name }}: {{ toYaml .value }}
{{- end }}
{{- range $key,$val := $templateData.pod.nodeSelector }}
{{ $key }}: {{- toYaml $val | nindent 10 }}
{{- end }}
{{- end }}
{{- with $templateData.pod.priorityClassName }}
priorityClassName:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- $securityContext := $templateData.pod.defaultSecurityContext }}
{{- if .Job.container.runAsUserId }}
{{- $_ := set $securityContext "runAsUser" .Job.container.runAsUserId }}
{{- end }}
{{- if .Job.container.runAsGroupId }}
{{- $_ := set $securityContext "runAsGroup" .Job.container.runAsGroupId }}
{{- end }}
{{- if .Job.container.supplementalGroupIds }}
{{- $groupIds := list }}
{{- range .Job.container.supplementalGroupIds }}
{{- $groupIds = append $groupIds . }}
{{- end }}
{{- $_ := set $securityContext "supplementalGroups" (cat "[" ($groupIds | join ", ") "]") }}
{{- $securityContext := mergeOverwrite $securityContext $templateData.pod.securityContext }}
{{- end }}
{{- if $securityContext }}
securityContext:
{{- range $key, $val := $securityContext }}
{{ $key }}: {{ $val }}
{{- end }}
{{- end }}
{{- with $templateData.pod.imagePullSecrets }}
imagePullSecrets: {{ toYaml . | nindent 12 }}
{{- end }}
initContainers:
{{- with .Job.metadata.pod.initContainers }}
{{- range . }}
- {{ toYaml . | indent 10 | trimPrefix (repeat 10 " ") }}
{{- end }}
{{- end }}
{{- with $templateData.pod.initContainers }}
{{- range . }}
- {{ toYaml . | indent 10 | trimPrefix (repeat 10 " ") }}
{{- end }}
{{- end }}
containers:
- name: rs-launcher-container
image: {{ toYaml .Job.container.image }}
{{- with $templateData.pod.imagePullPolicy }}
imagePullPolicy: {{- . | nindent 12 }}
{{- end }}
{{- $isShell := false }}
{{- if $templateData.pod.command }}
command: {{- toYaml $templateData.pod.command | nindent 12 }}
{{- if .Job.command }}{{- $isShell = true }}{{- end }}
{{- else if .Job.command }}
command: ['/bin/sh']
{{- $isShell = true }}
{{- else }}
command: [{{ toYaml .Job.exe }}]
{{- $isShell = false }}
{{- end }}
{{- if .Job.stdin }}
stdin: true
{{- else }}
stdin: false
{{- end }}
stdinOnce: true
{{- if .Job.workingDirectory }}
workingDir: {{ toYaml .Job.workingDirectory }}
{{- end }}
{{- if or (ne (len .Job.args) 0) $isShell }}
args:
{{- if $isShell }}
- '-c'
{{- if ne (len .Job.args) 0 }}
- {{ .Job.args | join " " | cat .Job.command | toYaml | indent 12 | trimPrefix (repeat 12 " ") }}
{{- else }}
- {{ .Job.command | toYaml | indent 12 | trimPrefix (repeat 12 " ") }}
{{- end }}
{{- else }}
{{- range .Job.args }}
- {{ toYaml . | indent 12 | trimPrefix (repeat 12 " ") }}
{{- end }}
{{- end }}
{{- end }}
{{- $secrets := list }}
{{- range .Job.config }}
{{- if eq .name "secret" }}
{{- $packedSecret := .value }}
{{- $secret := dict }}
{{- $_ := set $secret "secret" (splitList ":" $packedSecret | first) }}
{{- $_ := set $secret "key" (slice (splitList ":" $packedSecret) 1 2 | first) }}
{{- $_ := set $secret "name" (splitList ":" $packedSecret | last) }}
{{- $secrets = append $secrets $secret }}
{{- end }}
{{- end }}
{{- if or (ne (len .Job.environment) 0) (ne (len $secrets) 0) (ne (len $templateData.pod.env) 0) }}
env:
{{- range .Job.environment }}
- name: {{ toYaml .name | indent 14 | trimPrefix (repeat 14 " ") }}
value: {{ toYaml .value | indent 14 | trimPrefix (repeat 14 " ") }}
{{- end }}
{{- range $secrets }}
- name: {{ get . "name"}}
valueFrom:
secretKeyRef:
name: {{ get . "secret" }}
key: {{ get . "key" }}
{{- end }}
{{- if $templateData.pod.env }}
{{- toYaml $templateData.pod.env | nindent 12 }}
{{- end }}
{{- end }}
{{- with $templateData.pod.containerSecurityContext }}
securityContext:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- $exposedPorts := list }}
{{- range .Job.exposedPorts }}
{{- if .publishedPort }}
{{- $exposedPorts = append $exposedPorts . }}
{{- end }}
{{- end }}
{{- if ne (len $exposedPorts) 0 }}
ports:
{{- range $exposedPorts }}
- containerPort: {{ .targetPort }}
hostPort: {{ .publishedPort }}
{{- end }}
{{- end }}
{{- $limits := $templateData.pod.resources.limits }}
{{- $requests := $templateData.pod.resources.requests }}
{{- range .Job.resourceLimits }}
{{- if eq .type "cpuCount" }}
{{- $_ := set $limits "cpu" .value }}
{{- else if eq .type "CPU Request" }}
{{- $_ := set $requests "cpu" .value }}
{{- else if eq .type "memory" }}
{{- $_ := set $limits "memory" (printf "%s%s" .value "M") }}
{{- else if eq .type "Memory Request" }}
{{- $_ := set $requests "memory" (printf "%s%s" .value "M") }}
{{- else if eq .type "NVIDIA GPUs" }}
{{- $val := float64 .value }}
{{- if ne $val 0.0 }}
{{- $_ := set $limits "nvidia.com/gpu" $val }}
{{- end }}
{{- else if eq .type "AMD GPUs" }}
{{- $val := float64 .value }}
{{- if ne $val 0.0 }}
{{- $_ := set $limits "amd.com/gpu" $val }}
{{- end }}
{{- end }}
{{- end }}
{{- if any (ne (len $requests) 0) (ne (len $limits) 0) }}
resources:
{{- if ne (len $requests) 0 }}
requests:
{{- range $key, $val := $requests }}
{{ $key }}: {{ toYaml $val }}
{{- end }}
{{- end }}
{{- if ne (len $limits) 0 }}
limits:
{{- range $key, $val := $limits }}
{{ $key }}: {{ toYaml $val }}
{{- end }}
{{- end }}
{{- end }}
{{- if or (ne (len .Job.volumes) 0) (ne (len $templateData.pod.volumeMounts) 0) }}
volumeMounts:
{{- range .Job.volumeMounts }}
- {{ nindent 14 (toYaml .) | trim -}}
{{- end }}
{{- range $templateData.pod.volumeMounts }}
- {{ nindent 14 (toYaml .) | trim -}}
{{- end }}
{{- end }}
{{- with $templateData.pod.extraContainers }}
{{- toYaml . | nindent 8 }}
{{- end }}
Loading

0 comments on commit 6ac3842

Please sign in to comment.