Skip to content
In this Guide

In this Guide

Deep Dives

AI: Claude and Codex patterns

ConfigHub: Deploy and manage

Journey 4 of 5

My chart behaves differently in GitOps

A chart can decide things you never wrote, and helm install hides some of them. This Redis has run for a month from three lines of values. Under Argo CD its password changes on every sync, its image is tagged latest, and a preset you never chose sets its memory. A Flux HelmRelease runs Helm against the cluster, where this chart can read its password back, but the image and the preset are the same there. You can see all three before the move. The Workshop Catalog has a reviewed alternative without those three problems, but it is a different chart, cloudpirates/redis, so moving to it is a migration and not an upgrade. Your existing data, the PVC and the Service names do not carry over, and it needs a Secret that you create first.

Time. About six minutes. Needs. cub, the workshop plugin (0.6.26 or later), helm, oras, curl, and a network. No server, no account, no cluster.

Run it yourself

The journey is a folder in the public workshop-demo repository. Its script pauses before each command, and Enter runs it. Read each command before continuing; stop with Ctrl+C whenever you have the result you need. ConfigHub sign-in, upload and protected-update steps are optional later work, not prerequisites for the local check.

# get the journeys
$ git clone https://github.com/monadic/workshop-demo

# use the version this page describes
$ git -C workshop-demo checkout --quiet 0e91722fb417

# open this journey
$ cd workshop-demo/4-before-argo-takes-over

# walk the steps, one command at a time
$ ./run.sh

Or let your agent run it

Give your agent the journey's PROMPT.md and nothing else. It follows the same steps, with the same numbers, and shows you the command after each one. You decide at each step whether to go on.

Keep this page and the README from your agent. They say what each step finds, so an agent that reads them knows the answers before it starts.

The steps

These are the steps in the journey's README. Run them from the journey's folder. The output of a real run is in expected/.

# the steps write their output here
$ mkdir -p work

1. Read what has been running

Three lines, and nothing looks wrong.

2. See what it installs

New to cub? Install the cub CLI first. Public catalog packages pull and render anonymously, and you sign in only once a command saves or changes ConfigHub data.

$ mkdir -p work

$ helm template shop-redis oci://registry-1.docker.io/bitnamicharts/redis --version 25.5.3 --namespace shop -f values.yaml > work/bitnami.yaml

$ cub config check work/bitnami.yaml

Look for the NOTE line. The Redis image is bitnami/redis:latest, so the same name can pull a different Redis next week.

3. Render it twice, the way Argo CD will

Argo CD renders the chart on every sync, without reading anything back from your cluster.

$ helm template shop-redis oci://registry-1.docker.io/bitnamicharts/redis --version 25.5.3 --namespace shop -f values.yaml > work/bitnami-again.yaml

$ cub config diff work/bitnami.yaml work/bitnami-again.yaml

Look for one changed field, /data/redis-password. Same chart, same values, a different password. The diff shows a short hash of each value, never the value. Under Argo CD every sync writes a new password while the shop app holds the old one. helm install and helm upgrade hid this, because this chart reads the Secret back from the cluster.

4. Ask what the chart does that you did not write

$ cub config values oci://registry-1.docker.io/bitnamicharts/redis --version 25.5.3 --release shop-redis --namespace shop --values values.yaml

Look under What the chart does that you did not write. master.resourcesPreset is "nano" sets Redis's CPU and memory, a 192Mi memory limit, and you never chose it. The password field changes on every render.

5. Try to pin the image to a version

$ oras manifest fetch docker.io/bitnami/redis:7.4.1-debian-12-r2

$ oras manifest fetch --descriptor docker.io/bitnamilegacy/redis:7.4.1-debian-12-r2

That tag is the one an older release of this chart, 20.6.0, pinned. The first is refused and the second is found. Versioned Bitnami images now sit behind a paid tier, the bitnamilegacy copies get no updates, and the free chart runs latest. The Workshop's Did your Bitnami chart stop pulling? page records which pinned charts are affected, with its receipt.

6. Ask the Workshop Catalog for a reviewed alternative

The Catalog is public data, with no account.

$ curl -s -o work/index.json https://confighub.github.io/helm-expt/site/listings/index.json

$ grep -o '"id": "cloudpirates-redis[^"]*"' work/index.json

$ curl -s -o work/listing.json https://confighub.github.io/helm-expt/site/listings/cloudpirates-redis-0-34-11-reuse-existing-secret.json

$ grep -m 3 -o -E '"(name|version|base)": "[^"]*"' work/listing.json

$ grep -m 1 -o '"sourcePackageRef": "[^"]*"' work/listing.json

Look for cloudpirates/redis 0.34.11 with the base reuse-existing-secret, which keeps the password in a Secret you create, and the reviewed package pinned by digest.

7. Check the alternative, with your memory limit

$ helm template shop-redis oci://registry-1.docker.io/cloudpirates/redis --version 0.34.11 --namespace shop -f values-successor.yaml > work/successor.yaml

$ cub config check work/successor.yaml

$ cub config values oci://registry-1.docker.io/cloudpirates/redis --version 0.34.11 --release shop-redis --namespace shop --values values-successor.yaml

Look for images tagged latest or not tagged: 0, because the image is pinned by digest. Every value applies, and there is no preset and no field that changes on every render.

Look also at what the check does not say. The reuse-existing-secret base reads the password from a Secret named redis-existing-secret, key redis-password, and the chart does not create it. cub config check names the shop namespace that must already exist, but it does not warn about the missing Secret, and without it the Redis pod cannot start. The local walkthrough stops at checking the files; it does not create this Secret.

Optional, before a real deployment. Skip this command for the local demo. It writes to your selected Kubernetes cluster and requires kubectl, openssl, permission to create Secrets, and an existing shop namespace. Create the Secret before installing the alternative:

$ kubectl create secret generic redis-existing-secret --namespace shop --from-literal=redis-password="$(openssl rand -base64 24)"

Point the shop app at the same Secret, so both read one password that no sync changes.

This is a different chart, so the move is a migration. The Bitnami chart's Service is shop-redis-master and its PVC is redis-data-shop-redis-master-0. This chart's Service is shop-redis and its PVC is data-shop-redis-0. The new Redis starts on an empty volume, so copy any data you need to keep, and change the host the shop app connects to.

8. Render the alternative twice

$ helm template shop-redis oci://registry-1.docker.io/cloudpirates/redis --version 0.34.11 --namespace shop -f values-successor.yaml > work/successor-again.yaml

$ cub config diff work/successor.yaml work/successor-again.yaml

Look for 0 changed. Argo CD would find nothing to change.

Use it on your own configuration

Render your own chart twice with your own values, the way Argo CD will, and compare. A field that changes is one Argo CD would change on every sync. Give the chart as its registry address, such as oci://registry-1.docker.io/bitnamicharts/redis, and use the release and namespace you run.

# render your chart twice
$ helm template <release> <chart> --version <version> --namespace <namespace> -f <values>.yaml > first.yaml

$ helm template <release> <chart> --version <version> --namespace <namespace> -f <values>.yaml > second.yaml

# look for an image tagged latest
$ cub config check first.yaml

# name every field that differs between the two
$ cub config diff first.yaml second.yaml

# ask what the chart does that you did not write
$ cub config values <chart> --version <version> --release <release> --namespace <namespace> --values <values>.yaml

These Guides go further: Run it with Flux, Argo CD, or kubectl · Use ConfigHub with Argo CD or Flux · Harden Argo CD before production.

Why it happens

What charts hide explains it.

How the check knows

cub config check reads every container image in the rendered objects. cub config values renders the chart twice with the same values and names every field that differs. It then sets each resourcesPreset it finds to none and renders again, so it reports only a preset that is really in force. Nothing is applied and no value is printed.

Where it continues

Configs, with a reviewed base variant. The next journey is My app installs but will not start.