Skip to main content

Configure sync and setup Jobs

Configure the controller's sync and setup Jobs to meet cluster policies. For Cortex's status exporter Deployment, use the exporter overlay.

Apply Job settings​

You need permission to manage ConfigMaps in kratix-platform-system and an installed Portal Controller. These settings apply to every portal, not just one Promise.

  1. Save the complete ConfigMap below as portal-workloads.yaml. Edit the example labels, annotations and node selector for your cluster; remove settings you do not need.

  2. Review the protected fields before adding container overrides.

  3. Apply the file:

    kubectl apply --filename portal-workloads.yaml
  4. Verify that new Jobs and their Pods carry the intended settings.

You configure these settings in the ske-portal-workloads-config ConfigMap in the kratix-platform-system namespace, under the workloads.yaml key:

apiVersion: v1
kind: ConfigMap
metadata:
name: ske-portal-workloads-config
namespace: kratix-platform-system
data:
workloads.yaml: |
jobTemplate:
metadata:
labels:
app.kubernetes.io/name: ske-portal
acs.customer.com/securityZone: dmz
annotations:
acs.customer.com/owner: platform-team
spec:
backoffLimit: 5
ttlSecondsAfterFinished: 3600
template:
spec:
nodeSelector:
kubernetes.io/os: linux

jobTemplate is a partial Kubernetes JobTemplateSpec. The controller merges it into each Job it builds: Promise sync Jobs, Resource sync Jobs, and portal setup Jobs.

Manage this ConfigMap directly; there is no equivalent SKEIntegration field. It applies to every portal instance.

note

Changes recreate affected Jobs. Deleting the ConfigMap restores defaults.

Labels and annotations reach the pods​

jobTemplate.metadata applies to Jobs and their Pods.

For Pod-only metadata, use jobTemplate.spec.template.metadata. Pod-level values win conflicts.

Quote your values

In YAML, 4711 is a number and yes is a boolean, but Kubernetes labels, annotations and nodeSelector values all have to be text. Put quote marks around anything that is not obviously a word:

labels:
acme.com/cost-centre: "4711" # not 4711
audited: "yes" # not yes

Unquoted non-string values are rejected. See configuration errors.

What you cannot set​

The controller restores these fields after merging:

FieldWhy the controller keeps it
metadata.name, metadata.namespaceIt finds and cleans up its Jobs by name
metadata.ownerReferencesThis is how a Promise notices its Job has finished
metadata.finalizersA finalizer would stop the controller deleting its own Job
Which containers existYou can change a container it builds, but not add one. A sync Job runs reader, generate and work-writer (writer on Cortex portals) as init containers, followed by status-writer. A setup Job runs a single setup container
Labels and annotations starting kratix.io/, and app.kubernetes.io/managed-byThese are how the controller finds its Jobs and protects them from being cleaned up early

Labels such as app.kubernetes.io/name, app.kubernetes.io/component and app.kubernetes.io/version are yours to set.

Override existing containers by name. You cannot add containers here.

Put your entry in the list the container runs in

Match the container's list: initContainers or containers. Entries in the wrong list are silently ignored.

Setting resources on a container​

This is how you set CPU, memory or ephemeral storage limits:

jobTemplate:
spec:
template:
spec:
initContainers:
- name: generate
resources:
limits:
memory: 512Mi
ephemeral-storage: 1Gi

Setting environment variables on a container​

Naming a container also lets you set environment variables on it.

Name all of the containers to reach everything the controller runs. A single document is merged onto every Job, and an entry for a container that a Job does not run is ignored, so one file covers both portal types, sync Jobs and setup Jobs:

jobTemplate:
spec:
template:
spec:
initContainers:
- name: reader
env:
- name: YOUR_ENV_VAR
value: "your-value"
- name: generate
env:
- name: YOUR_ENV_VAR
value: "your-value"
- name: writer
env:
- name: YOUR_ENV_VAR
value: "your-value"
- name: work-writer
env:
- name: YOUR_ENV_VAR
value: "your-value"
containers:
- name: status-writer
env:
- name: YOUR_ENV_VAR
value: "your-value"
- name: setup
env:
- name: YOUR_ENV_VAR
value: "your-value"

Each Job takes the entries matching the containers it runs. A Backstage sync Job takes reader, generate, work-writer and status-writer; a Cortex sync Job takes writer in place of work-writer; a setup Job takes setup. A delete Job runs fewer containers than a configure Job, and takes the entries for the ones it does run.

Your variables are added to the ones the controller already sets on those containers, which are left alone. If the setting is only needed where the controller calls a portal's API, that is writer on a Cortex sync Job and setup on a Cortex setup Job. Backstage portals make no such calls: they reach the Kubernetes API only.

Give every entry a name

name is how the merge finds the container to change. An entry without one matches no container, and the Jobs it would apply to are not created until you add the name.

When the file is wrong​

If workloads.yaml cannot be read, the controller creates no new Jobs until you fix it, and records a warning on the ConfigMap itself. Existing Jobs are left alone.

kubectl -n kratix-platform-system describe configmap ske-portal-workloads-config
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning PortalWorkloadConfigInvalid 110s portal-setup-controller could not parse the portal
workloads configuration: jobTemplate: json: cannot unmarshal number into Go struct field
ObjectMeta.metadata.labels of type string

That message is the unquoted number from the tip above.

The controller rejects anything it cannot make sense of: unknown fields, misspelled fields, values of the wrong type, and an empty (null) metadata or spec. It does not ignore them. That way a typo cannot quietly drop the labels your policy needs.

Two things keep working while the file is broken. Cleaning up after a portal connection you have removed from your configuration still runs. So does deleting a Resource, because its Job has to run for the Resource to finish being removed.

note

The warning appears on the ConfigMap, not on the Promises whose Jobs were not created. If a Promise has stopped syncing to its portal and you cannot see why, check this ConfigMap's events.

Verify Job settings​

Inspect ConfigMap events first, then a newly created setup or sync Job and one of its Pods. Select their names from the list; sync Jobs can run in a Promise's pipeline namespace:

kubectl describe configmap ske-portal-workloads-config --namespace kratix-platform-system
kubectl get jobs --all-namespaces
kubectl get job <JOB_NAME> --namespace <JOB_NAMESPACE> -o yaml
kubectl get pods --namespace <JOB_NAMESPACE> --selector job-name=<JOB_NAME>
kubectl get pod <POD_NAME> --namespace <JOB_NAMESPACE> -o yaml

Check your labels, annotations, node placement and container resources on the new objects. If they are missing, confirm the container name and whether it is in initContainers or containers. For PortalWorkloadConfigInvalid, correct the field reported by the event. Existing Jobs are not a reliable check of a newly applied template.

Return to Backstage or Cortex to verify publication.