Make imagePullPolicy a template variable instead of hardcoding it #3

Merged
GuillaumeHemmen merged 1 commit from fix/image-pull-policy into master 2026-09-29 15:03:24 +00:00
Member

Problem

image_pull_policy was hardcoded to "Always", so every workspace start made kubelet re-resolve the tag against the Forgejo registry even when the full layer set was already cached on the node.

Approach

Rather than flipping the constant, this exposes it as a template variable so whoever pushes the template decides. It validates against Always / IfNotPresent / Never, plus auto.

variable "image_pull_policy" {
    type    = string
    default = "auto"
    validation {
        condition     = contains(["auto", "Always", "IfNotPresent", "Never"], var.image_pull_policy)
        error_message = "image_pull_policy must be one of: auto, Always, IfNotPresent, Never."
    }
}

Why auto is the default

The policy and the tag are not independent knobs. Current registry digests:

coder-xfce-vnc-latest   -> sha256:b2c68494...
coder-xfce-vnc-26.37.0  -> sha256:b2c68494...   (same digest today)
coder-latest            -> sha256:50bda30e...
coder-26.37.0           -> sha256:50bda30e...   (same digest today)

latest is a moving alias CI re-points at each release, so it needs Always or a workspace silently pins to whatever layer set its node happened to have cached. Version and build-SHA tags are published once and never reused, so IfNotPresent is always correct for them.

auto derives the policy from image_tag on exactly that rule. Since image_tag still defaults to "latest", auto preserves today's behaviour on the default path and only relaxes it where relaxing is safe. An admin who wants a fixed policy sets one explicitly.

What this actually buys

Resilience, not speed. The registry round-trip measured 75ms on the last workspace start, so this saves no meaningful wall-clock time. The real gain is decoupling: under Always, a workspace on a pinned tag fails with ImagePullBackOff whenever the registry is unreachable, even though the 2.6 GB image is already on the node. Forgejo runs in this same cluster, so a registry outage currently takes pinned workspaces down with it.

Testing

Not applied to the cluster; investigation was read-only. terraform validate was not run (terraform is not installed in the workspace) — worth a terraform validate or a dry-run template push before merging, since this adds a validation block and a locals block rather than just changing a literal. Digests above were read from the Forgejo registry API. Verification is to push the template and confirm a pinned-tag workspace starts with no Pulling event.

Follow-up to #2.

🤖 Generated with Claude Code

https://claude.ai/code/session_015QKnVbbjpAi4TaSmrkNXAE

## Problem `image_pull_policy` was hardcoded to `"Always"`, so every workspace start made kubelet re-resolve the tag against the Forgejo registry even when the full layer set was already cached on the node. ## Approach Rather than flipping the constant, this exposes it as a **template variable** so whoever pushes the template decides. It validates against `Always` / `IfNotPresent` / `Never`, plus `auto`. ```terraform variable "image_pull_policy" { type = string default = "auto" validation { condition = contains(["auto", "Always", "IfNotPresent", "Never"], var.image_pull_policy) error_message = "image_pull_policy must be one of: auto, Always, IfNotPresent, Never." } } ``` ## Why `auto` is the default The policy and the tag are not independent knobs. Current registry digests: ``` coder-xfce-vnc-latest -> sha256:b2c68494... coder-xfce-vnc-26.37.0 -> sha256:b2c68494... (same digest today) coder-latest -> sha256:50bda30e... coder-26.37.0 -> sha256:50bda30e... (same digest today) ``` `latest` is a moving alias CI re-points at each release, so it needs `Always` or a workspace silently pins to whatever layer set its node happened to have cached. Version and build-SHA tags are published once and never reused, so `IfNotPresent` is always correct for them. `auto` derives the policy from `image_tag` on exactly that rule. Since `image_tag` still defaults to `"latest"`, **`auto` preserves today's behaviour on the default path** and only relaxes it where relaxing is safe. An admin who wants a fixed policy sets one explicitly. ## What this actually buys **Resilience, not speed.** The registry round-trip measured 75ms on the last workspace start, so this saves no meaningful wall-clock time. The real gain is decoupling: under `Always`, a workspace on a pinned tag fails with `ImagePullBackOff` whenever the registry is unreachable, *even though the 2.6 GB image is already on the node*. Forgejo runs in this same cluster, so a registry outage currently takes pinned workspaces down with it. ## Testing Not applied to the cluster; investigation was read-only. `terraform validate` was **not** run (terraform is not installed in the workspace) — worth a `terraform validate` or a dry-run template push before merging, since this adds a `validation` block and a `locals` block rather than just changing a literal. Digests above were read from the Forgejo registry API. Verification is to push the template and confirm a pinned-tag workspace starts with no `Pulling` event. Follow-up to #2. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_015QKnVbbjpAi4TaSmrkNXAE
claude-bot force-pushed fix/image-pull-policy from c43d7967d1 to 45eae290e7 2026-09-29 15:00:05 +00:00 Compare
claude-bot changed title from Only force image re-pull when the tag is a moving alias to Make imagePullPolicy a template variable instead of hardcoding it 2026-09-29 15:00:23 +00:00
Author
Member

Reworked per review: instead of hardcoding IfNotPresent, the policy is now a template variable (image_pull_policy) chosen at coder templates push, validated against auto / Always / IfNotPresent / Never.

image_tag is left as-is, as requested.

The default is auto, which derives the policy from image_tag — Always for the moving latest alias, IfNotPresent for pinned version/SHA tags. Since image_tag still defaults to latest, this preserves current behaviour on the default path.

Branch was force-pushed (c43d796 -> 45eae29); the earlier hardcoded-conditional commit is gone. README variables table updated too.

Reworked per review: instead of hardcoding `IfNotPresent`, the policy is now a template variable (`image_pull_policy`) chosen at `coder templates push`, validated against `auto` / `Always` / `IfNotPresent` / `Never`. `image_tag` is left as-is, as requested. The default is `auto`, which derives the policy from `image_tag` — `Always` for the moving `latest` alias, `IfNotPresent` for pinned version/SHA tags. Since `image_tag` still defaults to `latest`, this preserves current behaviour on the default path. Branch was force-pushed (`c43d796` -> `45eae29`); the earlier hardcoded-conditional commit is gone. README variables table updated too.
GuillaumeHemmen deleted branch fix/image-pull-policy 2026-09-29 15:03:24 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
GuillaumeHemmen-k8s/coder-sindri-deployment!3
No description provided.