Skip to content
Merged
Show file tree
Hide file tree
Changes from 64 commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
394d20f
Add native-Go OHE support to Connect chart and update RBAC
dbkegley Feb 24, 2026
58e88ac
Update charts/rstudio-connect/values.yaml
dbkegley Mar 9, 2026
c702ebd
Update charts/rstudio-connect/values.yaml
dbkegley Mar 9, 2026
07f0257
Update charts/rstudio-connect/values.yaml
dbkegley Mar 9, 2026
702bb35
Refactor RBAC: dedicated permissions for native-Go runner
lucasrod16 Apr 1, 2026
8457b3e
Bump chart version to 0.9.0
lucasrod16 Apr 1, 2026
7894853
Rename values key from kubernetes to backends.kubernetes
lucasrod16 Apr 1, 2026
97f9f23
Rename defaultJobOverlay/defaultServiceOverlay to defaultResourceJobB…
lucasrod16 Apr 1, 2026
93d76d9
Move init container into chart logic and default defaultResourceJobBa…
lucasrod16 Apr 1, 2026
c6fc17b
Fix prestart volumeMount missing for native runner
lucasrod16 Apr 2, 2026
267c656
Add CI values file for native Kubernetes runner
lucasrod16 Apr 2, 2026
3a0b586
Add migration examples and gitignore notes.md
lucasrod16 Apr 2, 2026
6c66480
Add before/after launcher migration examples
lucasrod16 Apr 3, 2026
3a7313c
Fix prestart volumeMount guard and hardcoded resource base mount paths
lucasrod16 Apr 3, 2026
25a4c59
Add tests for prestart guard and custom resource base mount paths
lucasrod16 Apr 3, 2026
f6d3a72
Ensure rsc-volume mount on user-provided connect-content-init
lucasrod16 Apr 3, 2026
381182a
Add RBAC, configmap-prestart, and init image tag tests
lucasrod16 Apr 3, 2026
c8712a5
Tighten RBAC, checksum, and init tag test assertions
lucasrod16 Apr 3, 2026
3dffe84
Check both name and mountPath for connect-content rsc-volume mount
lucasrod16 Apr 3, 2026
381971f
Fail fast on reserved mountPath conflicts in job base
lucasrod16 Apr 3, 2026
73ca942
Update NEWS.md with 0.9.0 release notes and remove Go references
lucasrod16 Apr 3, 2026
fb984d7
Add command and defaultSecurityContext to migration examples
lucasrod16 Apr 6, 2026
9215537
Address review findings: docs accuracy and completeness
lucasrod16 Apr 6, 2026
c56643e
Guard config.Kubernetes dereferences with dig for nil safety
lucasrod16 Apr 6, 2026
9eefea6
Strip empty DefaultResource*Base from config before merge
lucasrod16 Apr 6, 2026
43d6d8f
Link executionEnvironments to chart README instead of Connect docs
lucasrod16 Apr 7, 2026
731a688
Simplify minimal migration docs and clarify DataDirPVCName auto-config
lucasrod16 Apr 7, 2026
599f089
Document runner-managed fields and overlay behavior in migration exam…
lucasrod16 Apr 7, 2026
0d482f7
Replace native terminology with direct Kubernetes runner
lucasrod16 Apr 7, 2026
35495d7
Replace migration terminology with upgrade per PR feedback
lucasrod16 Apr 7, 2026
6a596d3
Rename migration directory and files to upgrade
lucasrod16 Apr 7, 2026
0b205c4
Remove rollback-to-launcher guidance from upgrade docs
lucasrod16 Apr 7, 2026
8b8ecdf
Add upgrade callout in NOTES.txt when launcher.enabled with appVersio…
lucasrod16 Apr 7, 2026
0dc8f1c
Note profiles functionality is achievable via defaultResourceJobBase
lucasrod16 Apr 7, 2026
663ce4e
Remove unreleased Connect docs link from values.yaml
lucasrod16 Apr 7, 2026
410c705
Refactor minimal upgrade section into a mapping table
lucasrod16 Apr 8, 2026
e822a25
Remove internal-detail rows from values-with-no-equivalent table
lucasrod16 Apr 8, 2026
36edb90
Move important notes section to top of upgrade guide
lucasrod16 Apr 8, 2026
f221e80
Remove redundant sharedStorage note from minimal upgrade intro
lucasrod16 Apr 8, 2026
25ecd91
Add imagePullPolicy, resources, securityContext to backends defaultIn…
lucasrod16 Apr 8, 2026
5802894
Simplify config.Launcher row in upgrade table
lucasrod16 Apr 8, 2026
c7bc702
Split templateValues examples into dedicated navigable sections
lucasrod16 Apr 8, 2026
43b3e08
Reorder example sections by admin configuration priority
lucasrod16 Apr 8, 2026
174ccb7
Simplify pod security context example
lucasrod16 Apr 8, 2026
fb3c9e2
Use runAsNonRoot in security context example
lucasrod16 Apr 8, 2026
6763300
Update mountContent description to cover both launcher and backends.k…
lucasrod16 Apr 8, 2026
64007cd
Remove pre-release items for early merge
lucasrod16 Apr 9, 2026
223492b
Address PR review feedback from nihara-thomas
lucasrod16 Apr 13, 2026
7b22e7f
Use consistent upgrade terminology in title and sidebar
lucasrod16 Apr 13, 2026
e3682df
Validate config.Kubernetes does not conflict with backends.kubernetes
lucasrod16 Apr 14, 2026
8c8dbc9
Normalize config.Kubernetes.Enabled check to be case-insensitive
lucasrod16 Apr 14, 2026
35c9e4e
Add test for shared storage requirement with backends.kubernetes
lucasrod16 Apr 14, 2026
0c5a57b
Guard init container image override with hasKey check
lucasrod16 Apr 14, 2026
539a995
Test user-provided init container image is preserved
lucasrod16 Apr 14, 2026
b2ad07d
Add test validating Role rules for direct Kubernetes runner RBAC
lucasrod16 Apr 14, 2026
7aaffb2
Add tests for service.yaml configmap presence
lucasrod16 Apr 14, 2026
b9dc3ba
Add default apiVersion and kind to service base
lucasrod16 Apr 14, 2026
d819407
Update securityContext comment to mention backends.kubernetes
lucasrod16 Apr 14, 2026
c3ca637
Expand config generation comment to include backends.kubernetes
lucasrod16 Apr 14, 2026
2a09ea5
Update charts/rstudio-connect/values.yaml
lucasrod16 Apr 14, 2026
1952cfa
Add 0.9.0 upgrade guidance section linking to upgrade guide
lucasrod16 Apr 14, 2026
3ddb10a
Extract oheEnabled helper for launcher/kubernetes conditional
lucasrod16 Apr 14, 2026
78a1c28
Regenerate README.md
lucasrod16 Apr 14, 2026
d047cca
Fix upgrade guide link path in README.md.gotmpl
lucasrod16 Apr 14, 2026
f3af1cf
Add minimum Connect version callout to upgrade guide
lucasrod16 Apr 14, 2026
ced65d7
Validate kind on defaultResourceJobBase and defaultResourceServiceBase
lucasrod16 Apr 14, 2026
4288b45
Add tests for kind validation on job and service base
lucasrod16 Apr 14, 2026
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: 2 additions & 0 deletions _quarto.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ website:
file: charts/rstudio-connect/README.md
- text: Changelog
file: charts/rstudio-connect/NEWS.md
- text: Upgrading to the direct Kubernetes runner
file: examples/connect/upgrade-launcher-to-kubernetes/launcher-to-kubernetes.qmd
- text: Examples
file: examples/connect/index.qmd
- section: "Posit Package Manager"
Expand Down
6 changes: 3 additions & 3 deletions charts/rstudio-connect/Chart.lock
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
dependencies:
- name: rstudio-library
repository: https://helm.rstudio.com
version: 0.1.35
digest: sha256:59fe5e712690610495d2ff32c6c78cc136e9685a785151d4cdba4b914d110f87
generated: "2025-10-09T13:37:20.639004-05:00"
version: 0.1.36
digest: sha256:cde061b0b7da43d7adbfcbc8d90e6d466d453dd707d8dad4f702fec6aeea103b
generated: "2026-04-01T12:03:45.783681-05:00"
4 changes: 2 additions & 2 deletions 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.8.38
version: 0.9.0
apiVersion: v2
appVersion: 2026.03.1
icon: https://raw.githubusercontent.com/rstudio/helm/main/images/posit-icon-fullcolor.svg
Expand All @@ -13,7 +13,7 @@ maintainers:
url: https://github.com/sol-eng
dependencies:
- name: rstudio-library
version: 0.1.35
version: 0.1.36
repository: https://helm.rstudio.com
annotations:
artifacthub.io/images: |
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.9.0

- Add support for an alternative Kubernetes backend via `backends.kubernetes.enabled`, which replaces the Launcher's template system with standard Kubernetes Job and Service manifests configured through `defaultResourceJobBase` and `defaultResourceServiceBase`. This backend will be available starting with Connect 2026.04.0.
- Add mutual-exclusion validation: `launcher.enabled` and `backends.kubernetes.enabled` cannot both be true.
- Add dedicated RBAC for the direct Kubernetes runner with least-privilege permissions, including automatic ClusterRole creation for NodePort service types.
- Add upgrade guide and examples in `examples/connect/upgrade-launcher-to-kubernetes/`.

## 0.8.38

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

![Version: 0.8.38](https://img.shields.io/badge/Version-0.8.38-informational?style=flat-square) ![AppVersion: 2026.03.1](https://img.shields.io/badge/AppVersion-2026.03.1-informational?style=flat-square)
![Version: 0.9.0](https://img.shields.io/badge/Version-0.9.0-informational?style=flat-square) ![AppVersion: 2026.03.1](https://img.shields.io/badge/AppVersion-2026.03.1-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.8.38:
To install the chart with the release name `my-release` at version 0.9.0:

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

To explore other chart versions, look at:
Expand All @@ -45,10 +45,14 @@ helm search repo rstudio/rstudio-connect -l

## Upgrade guidance

### 0.9.0

- Chart version 0.9.0 adds support for the direct Kubernetes runner via `backends.kubernetes.enabled`. See the [upgrade guide](../../examples/connect/upgrade-launcher-to-kubernetes/launcher-to-kubernetes.qmd) for details on transitioning from `launcher.enabled`.

### 0.8.0

- When upgrading to version 0.8.0 or later, Connect now runs in [Off-Host Execution mode](https://docs.posit.co/connect/admin/getting-started/off-host-install/) by default
- If you desire to run Connect not in Off-Host Execution mode, then set `securityContext.privileged: true` and `launcher.enabled: false`
- If you desire to run Connect in Local Execution mode, then set `securityContext.privileged: true` and `launcher.enabled: false`

## Required configuration

Expand Down Expand Up @@ -262,6 +266,17 @@ The Helm `config` values are converted into the `rstudio-connect.gcfg` service c
|-----|------|---------|-------------|
| affinity | object | `{}` | A map used verbatim as the pod's "affinity" definition |
| args | list | `[]` | The pod's run arguments. By default, it uses the container's default |
| backends.kubernetes.defaultInitContainer.enabled | bool | `true` | Whether to enable the defaultInitContainer. If disabled, you must ensure that the session components are available another way. Changing the default setting is an advanced option and not recommended. For more information on how Connect uses the session init container refer to https://docs.posit.co/connect/admin/appendix/off-host/arch-overview/#runtime-init-container |
| backends.kubernetes.defaultInitContainer.imagePullPolicy | string | `""` | The imagePullPolicy for the default initContainer |
| backends.kubernetes.defaultInitContainer.repository | string | `"ghcr.io/rstudio/rstudio-connect-content-init"` | The repository to use for the Content InitContainer image |
| backends.kubernetes.defaultInitContainer.resources | object | `{}` | Optional resources for the default initContainer |
| backends.kubernetes.defaultInitContainer.securityContext | object | `{}` | The securityContext for the default initContainer |
| backends.kubernetes.defaultInitContainer.tag | string | `""` | Overrides the image tag whose default is the chart appVersion. |
| backends.kubernetes.defaultInitContainer.tagPrefix | string | `"ubuntu2204-"` | A tag prefix for the Content InitContainer image (common selections: jammy-, ubuntu2204-). Only used if tag is not defined |
| backends.kubernetes.defaultResourceJobBase | object | `{}` | defaultResourceJobBase is an optional Kubernetes Job definition used as the base when launching content jobs. The chart automatically adds the init container and runtime volume when backends.kubernetes.defaultInitContainer.enabled is true. Only set this if you need to customize the job (e.g., add sidecars, node selectors, tolerations). https://kubernetes.io/docs/concepts/workloads/controllers/job/ |
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

TODO: link to updated Connect resource base docs

| backends.kubernetes.defaultResourceServiceBase | object | `{}` | defaultResourceServiceBase contains the Kubernetes Service definition which is used as an overlay "base" when creating a content job's Service in Kubernetes. Conceptually this is similar to a Kustomize base. Connect then applies any required Service configuration on-top of the overlay base to produce a final Service definition. https://kubernetes.io/docs/concepts/services-networking/service/ https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/#bases-and-overlays |
| backends.kubernetes.enabled | bool | `false` | Whether to enable off-host execution for running content-jobs in remote Kubernetes pods. |
| backends.kubernetes.namespace | string | `""` | The namespace to launch connect-content jobs into. Uses the Release namespace by default |
| chronicleAgent.agentEnvironment | string | `""` | An environment tag to apply to all metrics reported by this agent ([reference](https://docs.posit.co/chronicle/appendix/library/advanced-agent.html#environment)) |
| chronicleAgent.autoDiscovery | bool | `true` | If true, the chart will attempt to lookup the Chronicle Server address and version in the cluster |
| chronicleAgent.connectApiKey | object | `{"value":"","valueFrom":{}}` | An Administrator permissions API key generated in Connect for the Chronicle agent to use, API keys can only be created after Connect has been deployed so this value may need to be filled in later if performing an initial deployment ([reference](https://docs.posit.co/connect/user/api-keys/#api-keys-creating)) |
Expand Down Expand Up @@ -349,13 +364,13 @@ The Helm `config` values are converted into the `rstudio-connect.gcfg` service c
| priorityClassName | string | `""` | The pod's priorityClassName |
| prometheus.enabled | bool | `true` | The parent setting for whether to enable prometheus metrics. Default is to use the built-in product exporter |
| prometheus.port | int | `3232` | The port that prometheus will listen on |
| rbac.clusterRoleCreate | bool | `false` | Whether to create the ClusterRole that grants access to the Kubernetes nodes API. This is used by the Launcher to get all of the IP addresses associated with the node that is running a particular job. In most cases, this can be disabled as the node's internal address is sufficient to allow proper functionality. |
| rbac.create | bool | `true` | Whether to create rbac. (also depends on launcher.enabled = true) |
| rbac.serviceAccount | object | `{"annotations":{},"create":true,"labels":{},"name":""}` | The serviceAccount to be associated with rbac (also depends on launcher.enabled = true) |
| rbac.clusterRoleCreate | bool | `false` | Whether to create the ClusterRole that grants access to the Kubernetes nodes API. This is used by the Launcher or direct Kubernetes runner to get all of the IP addresses associated with the node that is running a particular job. When backends.kubernetes.enabled is true, the ClusterRole is also auto-created if the service base type is NodePort. In most cases, this can be disabled as the node's internal address is sufficient to allow proper functionality. |
| rbac.create | bool | `true` | Whether to create rbac. (also depends on launcher.enabled = true or backends.kubernetes.enabled = true) |
| rbac.serviceAccount | object | `{"annotations":{},"create":true,"labels":{},"name":""}` | The serviceAccount to be associated with rbac (also depends on launcher.enabled = true or backends.kubernetes.enabled = true) |
| readinessProbe | object | `{"enabled":true,"failureThreshold":3,"httpGet":{"path":"/__ping__","port":3939},"initialDelaySeconds":3,"periodSeconds":3,"successThreshold":1,"timeoutSeconds":1}` | Used to configure the container's readinessProbe. Only included if enabled = true |
| replicas | int | `1` | The number of replica pods to maintain for this service |
| resources | object | `{}` | Defines resources for the rstudio-connect container |
| securityContext | object | `{}` | Values to set the `securityContext` for the Connect container. It must include "privileged: true" or "CAP_SYS_ADMIN" when launcher is not enabled. If launcher is enabled, this can be removed with `securityContext: {}` |
| securityContext | object | `{}` | Values to set the `securityContext` for the Connect container. It must include "privileged: true" or "CAP_SYS_ADMIN" when running in local execution mode. If launcher or backends.kubernetes is enabled, this can be removed with `securityContext: {}` |
| service.annotations | object | `{}` | Annotations for the service, for example to specify [an internal load balancer](https://kubernetes.io/docs/concepts/services-networking/service/#internal-load-balancer) |
| service.clusterIP | string | `""` | The cluster-internal IP to use with `service.type` ClusterIP |
| service.loadBalancerIP | string | `""` | The external IP to use with `service.type` LoadBalancer, when supported by the cloud provider |
Expand All @@ -370,7 +385,7 @@ The Helm `config` values are converted into the `rstudio-connect.gcfg` service c
| sharedStorage.annotations | object | `{"helm.sh/resource-policy":"keep"}` | Annotations for the Persistent Volume Claim |
| sharedStorage.create | bool | `false` | Whether to create the persistentVolumeClaim for shared storage |
| sharedStorage.mount | bool | `false` | Whether the persistentVolumeClaim should be mounted (even if not created) |
| sharedStorage.mountContent | bool | `true` | Whether the persistentVolumeClaim should be mounted to the content pods created by the Launcher |
| sharedStorage.mountContent | bool | `true` | Whether the persistentVolumeClaim should be mounted to content pods. When true, the chart automatically configures DataDirPVCName for both Launcher and backends.kubernetes modes. |
| sharedStorage.name | string | `""` | The name of the pvc. By default, computes a value from the release name |
| sharedStorage.path | string | `"/var/lib/rstudio-connect"` | The path to mount the sharedStorage claim within the Connect pod |
| sharedStorage.requests.storage | string | `"10Gi"` | The volume of storage to request for this persistent volume claim |
Expand Down
6 changes: 5 additions & 1 deletion charts/rstudio-connect/README.md.gotmpl
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,14 @@

## Upgrade guidance

### 0.9.0

- Chart version 0.9.0 adds support for the direct Kubernetes runner via `backends.kubernetes.enabled`. See the [upgrade guide](../../examples/connect/upgrade-launcher-to-kubernetes/launcher-to-kubernetes.qmd) for details on transitioning from `launcher.enabled`.

### 0.8.0
Comment thread
lucasrod16 marked this conversation as resolved.

- When upgrading to version 0.8.0 or later, Connect now runs in [Off-Host Execution mode](https://docs.posit.co/connect/admin/getting-started/off-host-install/) by default
- If you desire to run Connect not in Off-Host Execution mode, then set `securityContext.privileged: true` and `launcher.enabled: false`
- If you desire to run Connect in Local Execution mode, then set `securityContext.privileged: true` and `launcher.enabled: false`

## Required configuration

Expand Down
18 changes: 18 additions & 0 deletions charts/rstudio-connect/ci/kubernetes-values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
license:
file:
secret: pct-license
secretKey: pct.lic

launcher:
enabled: false

backends:
kubernetes:
enabled: true

# a PVC is required for Connect to run in OHE (now the default)
sharedStorage:
create: true
# normally this should be ReadWriteMany, setting just for CI
accessModes:
- ReadWriteOnce
20 changes: 20 additions & 0 deletions charts/rstudio-connect/templates/NOTES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,22 @@ Please consider removing this configuration value.

{{- /* chart deprecations and misconfiguration warnings */ -}}

{{- if and .Values.launcher.enabled .Values.backends.kubernetes.enabled }}
{{- fail "\n\n`launcher.enabled` and `backends.kubernetes.enabled` cannot both be true"}}
{{- end }}

{{- if .Values.backends.kubernetes.enabled }}
{{- $configEnabled := dig "Kubernetes" "Enabled" "" .Values.config | printf "%v" | lower }}
{{- if or (eq $configEnabled "false") (eq $configEnabled "0") }}
{{- fail "\n\n`config.Kubernetes.Enabled` is set to false but `backends.kubernetes.enabled` is true. Remove `config.Kubernetes.Enabled` because the chart sets it automatically." }}
{{- end }}
{{- $configNs := dig "Kubernetes" "Namespace" "" .Values.config }}
{{- $chartNs := default $.Release.Namespace .Values.backends.kubernetes.namespace }}
{{- if and $configNs (ne $configNs $chartNs) }}
{{- fail (printf "\n\n`config.Kubernetes.Namespace` (%s) conflicts with `backends.kubernetes.namespace` (%s). Remove `config.Kubernetes.Namespace` because the chart sets it automatically from `backends.kubernetes.namespace`." $configNs $chartNs) }}
{{- end }}
{{- end }}

{{- if and .Values.launcher.useTemplates .Values.launcher.enabled }}
{{- range $k,$v := .Values.launcher.launcherKubernetesProfilesConf }}
{{- if hasKey $v "job-json-overrides" }}
Expand All @@ -46,6 +62,10 @@ Please consider removing this configuration value.
{{- fail "\n\nWhen launcher is enabled, persistent storage must be provided.\nThis is usually done via a PersistentVolumeClaim (PVC) with `sharedStorage.create=true`, although there are other options."}}
{{- end }}
Comment thread
lucasrod16 marked this conversation as resolved.

{{- if and .Values.backends.kubernetes.enabled (not .Values.sharedStorage.create) (not .Values.sharedStorage.mount) (not (dig "Kubernetes" "DataDirPVCName" "" .Values.config)) }}
{{- fail "\n\nWhen backends.kubernetes is enabled, persistent storage must be provided.\nThis is usually done via a PersistentVolumeClaim (PVC) with `sharedStorage.create=true`, although there are other options."}}
{{- end }}

{{- if .Values.launcher.contentInitContainer }}
{{- fail "\n\n`launcher.contentInitContainer` values are now stored at `launcher.defaultInitContainer`" }}
{{- end }}
Expand Down
Loading
Loading