<@ULVA73B9P> in Prefect version 3.6.28 self hosted...
# ask-marvin
r
@Marvin in Prefect version 3.6.28 self hosted kubernetes, I use the prefect-helm charts and modify those for our needs. So we have separate values.yaml for a tst and prd environments for prefect-worker. However, we have a single configmap for our modified base job template which uses json format. I am still relatively new to writing helm charts. How can I pass the imageTag from the values.yaml into that configMap? For example the values.yaml for tst would use the imageTag tst and prd would use latest. I am pretty sure it will need some kind of {{ }} string templating but also keen to read your approach. What say you, Marvin?
m
thought for 17.5 seconds
Yes — Helm templating with
{{ ... }}
is the right approach. If your ConfigMap itself is rendered by Helm, you can inject values from
values.yaml
directly into the JSON you store there. Typical approach In your environment-specific
values.yaml
files:
Copy code
yaml
worker:
  image:
    repository: my-registry/prefect-worker
    tag: tst
and in `prd`:
Copy code
yaml
worker:
  image:
    repository: my-registry/prefect-worker
    tag: latest
Then in your
configmap.yaml
template, render the JSON using Helm values:
Copy code
yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: prefect-base-job-template
data:
  baseJobTemplate.json: |
    {
      "job_configuration": {
        "image": "{{ .Values.worker.image.repository }}:{{ .Values.worker.image.tag }}"
      }
    }
That would produce
...:tst
in test and
...:latest
in prod. Important caveat This only works if the ConfigMap is part of the Helm template rendering process, e.g. under
templates/
. If you have a static JSON file that Kubernetes reads directly, Helm will not substitute anything inside it unless you explicitly tell Helm to treat it as a template. If your JSON lives in a separate file, a common pattern is to load it and run
tpl
on it. Example:
files/base-job-template.json
Copy code
json
{
  "job_configuration": {
    "image": "{{ .Values.worker.image.repository }}:{{ .Values.worker.image.tag }}"
  }
}
Then in your ConfigMap template:
Copy code
yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: prefect-base-job-template
data:
  baseJobTemplate.json: |
{{ tpl (.Files.Get "files/base-job-template.json") . | indent 4 }}
Why
tpl
?
Because
.Files.Get
reads the file as plain text;
tpl
tells Helm to evaluate any Helm template expressions inside that text. My recommendation For maintainability, I’d suggest: 1. Put the tag in
values.yaml
2. Keep the base job template in a separate file if it’s large 3. Use
tpl
to render that file into the ConfigMap 4. Optionally use a single computed value like:
Copy code
yaml
worker:
  image:
    repository: my-registry/prefect-worker
    tag: tst
    full: my-registry/prefect-worker:tst
But usually it’s cleaner to compute the full image string in the template instead of duplicating it in values. Even better pattern If you want a default with override support:
Copy code
yaml
worker:
  image:
    repository: my-registry/prefect-worker
    tag: latest
Then your
tst
override file only needs:
Copy code
yaml
worker:
  image:
    tag: tst
and deploy with the appropriate values file. One thing to watch for with Prefect Since you’re modifying the base job template for a Kubernetes worker, make sure the JSON field you’re updating matches the worker’s expected schema for your Prefect version. If you want, I can help you craft the exact
baseJobTemplate.json
snippet for Prefect 3.6.28 Kubernetes workers. Useful Helm docs: - Helm template functions - Using the tpl function - Accessing files inside templates If you want, paste your current
values.yaml
and ConfigMap template and I’ll rewrite them into the cleanest Helm version.
r
@Marvin That is great and all but one of us is confused. I do not want to change the imageTag of prefect-worker itself but rather of the jobs that it creates based on the job template. For example prefect-worker will use an image that has no business logic in it to keep it smaller and clean. The jobs, however, will use a different image that has the business logic. How does that change your answer, sir?
m
thought for 33.1 seconds
Got it — that does change the answer a bit, but the Helm mechanism is the same. You want: - the worker pod image to stay fixed - the job image inside the worker’s base job template to vary by environment So the value you template into the ConfigMap should not come from the worker image settings. It should come from a separate values key dedicated to the flow run / job image. Recommended structure In your `values.yaml`:
Copy code
yaml
worker:
  image:
    repository: my-registry/prefect-worker
    tag: 3.6.28

jobTemplate:
  image:
    repository: my-registry/my-business-logic
    tag: tst
And in prod:
Copy code
yaml
worker:
  image:
    repository: my-registry/prefect-worker
    tag: 3.6.28

jobTemplate:
  image:
    repository: my-registry/my-business-logic
    tag: latest
Then in the ConfigMap that contains your base job template JSON:
Copy code
yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: prefect-base-job-template
data:
  baseJobTemplate.json: |
    {
      "job_configuration": {
        "image": "{{ .Values.jobTemplate.image.repository }}:{{ .Values.jobTemplate.image.tag }}"
      }
    }
So now: -
worker.image.*
controls the prefect-worker deployment image -
jobTemplate.image.*
controls the image used by jobs created by that worker That separation is the cleanest model. If your JSON is in a separate file Same idea, just with `tpl`:
files/base-job-template.json
Copy code
json
{
  "job_configuration": {
    "image": "{{ .Values.jobTemplate.image.repository }}:{{ .Values.jobTemplate.image.tag }}"
  }
}
templates/configmap.yaml
Copy code
yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: prefect-base-job-template
data:
  baseJobTemplate.json: |
{{ tpl (.Files.Get "files/base-job-template.json") . | indent 4 }}
Why this is the right model for Prefect workers In Prefect Kubernetes work pools / workers, the worker process is just the control plane agent that submits jobs. The image in the base job template is what the actual execution pod runs. So it’s perfectly reasonable — and common — to keep: - a slim worker image - a separate runtime image for flow execution One more practical suggestion If the business logic image name itself changes by environment, keep repository and tag separate as above. If only the tag changes, you can simplify:
Copy code
yaml
jobTemplate:
  image:
    repository: my-registry/my-business-logic
    tag: tst
Then only override the tag in env-specific files. Base values:
Copy code
yaml
jobTemplate:
  image:
    repository: my-registry/my-business-logic
    tag: latest
tst-values.yaml
Copy code
yaml
jobTemplate:
  image:
    tag: tst
prd-values.yaml
Copy code
yaml
jobTemplate:
  image:
    tag: latest
One subtle but important point If this ConfigMap is used to create/update the Prefect work pool’s base job template, changing the ConfigMap alone does not always automatically update whatever Prefect object consumed it, depending on how you apply it in your setup. So there are really two layers: 1. Helm renders the ConfigMap 2. Something uses that rendered JSON to configure the Prefect worker/work pool/job template If you are mounting the ConfigMap directly into the worker and the worker reads it on startup, then a restart may be enough. If instead you used the JSON once when creating the work pool, then you may need to re-apply that work pool configuration after changing the ConfigMap. So the answer changes from “use worker.image.tag” to “use a separate values key like jobTemplate.image.tag” Example final layout:
values.yaml
Copy code
yaml
worker:
  image:
    repository: my-registry/prefect-worker
    tag: 3.6.28

jobTemplate:
  image:
    repository: my-registry/my-business-logic
    tag: latest
tst-values.yaml
Copy code
yaml
jobTemplate:
  image:
    tag: tst
prd-values.yaml
Copy code
yaml
jobTemplate:
  image:
    tag: latest
templates/configmap.yaml
```yaml apiVersion: v1 kind: ConfigMap metadata: name: prefect-base-job-template
data: baseJobTemplate.json: | { "job_configuration": { "image": "{{ .Values.jobTemplate.image.repository }}:{{ .Values.jobTemplate.image.tag }}" } } ``` If you want, paste your actual current base job template JSON and I can show you exactly where the
image
field should be templated for your Prefect Kubernetes worker setup.