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
nodeSelectorfor all jobs - Adds an
initContainerto configure a cache volume for all jobs - Adds a
fluent-bitlogging sidecar container - Modifies the
connect-contentcontainer to mount and configure the cache volume
Note that the
connect-contentcontainer and theconnect-content-initinitContainer 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 ConnectIf 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