Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add content job template default requests and limits #634

Merged
merged 5 commits into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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":{},"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 | `{}` | 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:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to provide empty dictionaries by default for requests and limits?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch!

# 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 }}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI @samcofer I noticed while working on this PR that we forgot to add the hostAliases setting to the helm chart's job template version. Sorry about that, I'll try to remember to update those templates going forward

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
Loading