Kubernetes Job and Service resource bases

Overview

Kubernetes resource bases allow administrators to customize the Job and Service resources that Connect creates for off-host execution. A resource base is similar to a Kustomize “base”

Resource bases are YAML definitions that serve as a base, which Connect then merges with its runtime configuration to produce the final Kubernetes resources. Connect applies job runtime values on top of the resource base definition.

For example, the following configurations can be applied to the Job resource base, just like any other Kubernetes Job:

  • image pull secrets
  • security context customizations (like fsGroup)
  • node selectors and (anti-)affinity rules
  • volumes and volume mounts
  • tolerations and priority classes
  • topology spread constraints

These resource base configurations are currently applied to all content that Connect executes on Kubernetes. Applying different resource bases for individual content items, execution environments, or content types is not currently supported.

Connect preserves most resource base fields while selectively overriding specific fields it needs to control for correct execution.

Configuration

Resource bases are configured in the Connect configuration and provided via Helm chart values. The defaultResourceJobBase configuration is entirely optional and only necessary if you wish to modify the content jobs that Connect submits to Kubernetes at runtime.

The following example:

  • Sets the nodeSelector for all jobs
  • Adds an initContainer to configure a cache volume for all jobs
  • Adds a fluent-bit logging sidecar container
  • Modifies the connect-content container to mount and configure the cache volume

Note that the connect-content container and the connect-content-init initContainer are reserved. Some parts of these containers can be modified, but Connect uses these containers to execute your content and some modifications may be overwritten by Connect. The full set of fields that Connect uses are enumerated below.

backends:
  kubernetes:
    enabled: true
    defaultResourceJobBase:
      apiVersion: batch/v1
      kind: Job
      spec:
        template:
          spec:
            nodeSelector:
              workload: rstudio-connect
            initContainers:
            - name: setup-cache
              image: busybox:1.36
              command: ['sh', '-c', 'mkdir -p /cache && chmod 777 /cache']
              volumeMounts:
              - name: cache-volume
                mountPath: /cache
            containers:
            - name: log-shipper
              image: fluent/fluent-bit:2.1
              env:
              - name: LOG_LEVEL
                value: info
              - name: OUTPUT_HOST
                value: logging-service.default.svc.cluster.local
              volumeMounts:
              - name: shared-logs
                mountPath: /var/log
            - name: connect-content
              env:
              - name: CACHE_DIR
                value: /cache
              volumeMounts:
              - name: cache-volume
                mountPath: /cache
            volumes:
            - name: cache-volume
              emptyDir:
                sizeLimit: 1Gi
            - name: shared-logs
              emptyDir: {}

How Merging Works

When you specify a resource base, Connect loads it and then applies its runtime values according to the behavior rules below.

Example: Merged labels

Your job base:

apiVersion: batch/v1
kind: Job
metadata:
  labels:
    my-company.com/cost-center: "engineering"
    my-company.com/team: "data-science"

Connect’s runtime labels:

- posit.co/content-guid: "abc-123"
- posit.co/execution-id: "xyz-789"

Final merged Job (precedence: connect-overrides):

metadata:
  labels:
    my-company.com/cost-center: "engineering"      # from base
    my-company.com/team: "data-science"            # from base
    posit.co/content-guid: "abc-123"               # from Connect
    posit.co/execution-id: "xyz-789"               # from Connect

If your base also specifies posit.co/content-guid, Connect’s value wins.

Field Behavior Categories

  • cannot-override: Connect must control these fields for correct execution (resource base values ignored)
  • merged: Resource base and Connect values are combined (Connect wins on conflicts)
  • appended: Connect adds to resource base values (both preserved)
  • conditionally-set: Connect sets a default only if resource base doesn’t specify

Precedence Values

  • connect-overrides: Connect values override resource base values when names conflict (used for merged maps)
  • connect-appended: Connect values added after resource base values (used for appended lists)

Service Account Configuration

When using custom service accounts in your resource base, they must be labeled for Connect to use them:

kubectl label serviceaccount <service-account-name> connect.posit.co/service-account=true -n <namespace>

Without this label, Connect ignores the service account and falls back to the namespace default. This applies to service accounts specified in: - Job resource base (spec.template.spec.serviceAccountName) - Content-level service account configuration applied via the v1/content api field service_account_name

Job resource base fields

These fields describe how Connect merges your job resource base with its runtime configuration when creating Kubernetes Jobs.

metadata.name

Behavior: cannot-override
Reason: Connect generates unique Job names via generateName

metadata.generateName

Behavior: cannot-override
Reason: Connect sets name prefix based on content name

metadata.namespace

Behavior: cannot-override
Reason: Connect controls Job namespace from configuration

spec.template.spec.serviceAccountName

Behavior: conditionally-set
Reason: Connect selects valid service account: content-specified > job-base-specified > namespace default. All service accounts must have the connect.posit.co/service-account label

spec.template.spec.securityContext.runAsUser

Behavior: cannot-override
Reason: Connect sets user ID depending on the configured RunAs user

spec.template.spec.securityContext.runAsGroup

Behavior: cannot-override
Reason: Connect sets group ID from shared group configuration

spec.template.spec.securityContext.supplementalGroups

Behavior: cannot-override
Reason: Connect sets supplemental groups from the effective RunAs user’s group memberships

metadata.annotations

Behavior: merged
Precedence: connect-overrides
Reason: Job base annotations kept unless Connect provides the same key, then Connect value wins

metadata.labels

Behavior: merged
Precedence: connect-overrides
Reason: Job base labels kept unless Connect provides the same key, then Connect value wins

spec.template.metadata.annotations

Behavior: merged
Precedence: connect-overrides
Reason: Job base pod annotations kept unless Connect provides the same key, then Connect value wins

spec.template.metadata.labels

Behavior: merged
Precedence: connect-overrides
Reason: Job base pod labels kept unless Connect provides the same key, then Connect value wins

spec.backoffLimit

Behavior: cannot-override
Reason: Connect sets to 0 (never retry failed jobs)

spec.parallelism

Behavior: cannot-override
Reason: Connect requires parallelism=1 for correct execution tracking

spec.template.spec.restartPolicy

Behavior: cannot-override
Reason: Jobs must not restart to ensure proper cleanup and status tracking

spec.ttlSecondsAfterFinished

Behavior: conditionally-set
Reason: Connect defaults to 300 seconds (5 minutes) if unset by job base

spec.template.spec.volumes

Behavior: appended
Precedence: connect-appended
Reason: Connect appends content-specific volumes (with “connect-” prefix) to job base volumes

spec.template.spec.containers[name=connect-content].image

Behavior: cannot-override
Reason: Connect sets image from content bundle

spec.template.spec.containers[name=connect-content].workingDir

Behavior: cannot-override
Reason: Connect sets working directory from content configuration

spec.template.spec.containers[name=connect-content].command

Behavior: cannot-override
Reason: Connect sets command from content execution requirements

spec.template.spec.containers[name=connect-content].args

Behavior: cannot-override
Reason: Connect sets args from content execution requirements

spec.template.spec.containers[name=connect-content].ports

Behavior: cannot-override
Reason: Connect sets ports from content exposed ports configuration

spec.template.spec.containers[name=connect-content].stdin

Behavior: cannot-override
Reason: Connect requires stdin=true for content input forwarding

spec.template.spec.containers[name=connect-content].stdinOnce

Behavior: cannot-override
Reason: Connect requires stdinOnce=true for content input forwarding

spec.template.spec.containers[name=connect-content].securityContext.runAsUser

Behavior: cannot-override
Reason: Cleared to use pod-level security context (includes supplemental groups)

spec.template.spec.containers[name=connect-content].securityContext.runAsGroup

Behavior: cannot-override
Reason: Cleared to use pod-level security context (includes supplemental groups)

spec.template.spec.containers[name=connect-content].env

Behavior: merged
Precedence: connect-overrides
Reason: Job base env vars kept except where Connect defines the same name, then Connect value wins

spec.template.spec.containers[name=connect-content].resources.limits

Behavior: merged
Precedence: connect-overrides
Reason: Job base resources preserved, Connect resources override

spec.template.spec.containers[name=connect-content].resources.requests

Behavior: merged
Precedence: connect-overrides
Reason: Job base resources preserved, Connect resources override

spec.template.spec.containers[name=connect-content].volumeMounts

Behavior: appended
Precedence: connect-appended
Reason: Connect appends content-specific volume mounts to job base mounts

Service resource base fields

These fields describe how Connect merges your service resource base with its runtime configuration when creating Kubernetes Services.

metadata.name

Behavior: cannot-override
Reason: Connect sets name to match Job name for lifecycle management

metadata.namespace

Behavior: cannot-override
Reason: Connect controls Service namespace from configuration

metadata.annotations

Behavior: merged
Precedence: connect-overrides
Reason: Service base annotations kept unless Connect provides the same key, then Connect value wins

metadata.labels

Behavior: merged
Precedence: connect-overrides
Reason: Service base labels kept unless Connect provides the same key, then Connect value wins

metadata.ownerReferences

Behavior: cannot-override
Reason: Connect sets owner reference to Job for automatic garbage collection

spec.selector

Behavior: cannot-override
Reason: Connect sets selector to match Job pods for correct routing

spec.type

Behavior: conditionally-set
Reason: Connect defaults to ClusterIP if unset by service base. Assumes that Connect is running in the same kubernetes cluster as the content

spec.ports

Behavior: appended
Precedence: connect-appended
Reason: Connect appends ports from content exposed ports configuration