Helm Release Naming Gotchas#

Helm charts derive Kubernetes resource names from the release name, but every chart does it differently. If you assume a consistent pattern, you will get bitten by DNS resolution failures, broken connection strings, and mysterious “service not found” errors.

Bitnami PostgreSQL: Names Are Not What You Expect#

The Bitnami PostgreSQL chart names resources using the release name directly, not {release-name}-postgresql. This catches nearly everyone.

# You deploy like this:
helm upgrade --install dt-postgresql bitnami/postgresql \
  --namespace dream-team \
  --set auth.database=mattermost \
  --set auth.username=mmuser

# You expect these resource names:
#   Pod:     dt-postgresql-postgresql-0   <-- WRONG
#   Service: dt-postgresql-postgresql     <-- WRONG

# Actual names:
#   Pod:     dt-postgresql-0
#   Service: dt-postgresql

This means your application connection string should reference dt-postgresql, not dt-postgresql-postgresql. If you chose release name postgresql, your service is just postgresql – which might collide with other things in your namespace.

Debug it: When your app cannot connect to the database, check the actual service name first:

kubectl get svc -n dream-team | grep post
# dt-postgresql   ClusterIP   10.96.45.12   <none>   5432/TCP

Image Tag Gotcha#

Bitnami PostgreSQL does not publish a bare 17 tag. If you set image.tag: "17", the pull will fail:

# WRONG - this tag does not exist
image:
  tag: "17"

# CORRECT - omit the tag entirely, let the chart use its default
# (or use the full tag like "17.2.0-debian-12-r5")

initdb.scripts Run Once#

The initdb.scripts block only executes on the first boot of the PostgreSQL container. A semaphore file inside the data volume prevents re-execution. If you need to change init scripts, you must delete the PVC and let the StatefulSet recreate it:

kubectl delete pvc data-dt-postgresql-0 -n dream-team
kubectl delete pod dt-postgresql-0 -n dream-team
# Pod will be recreated by StatefulSet, PVC will be reprovisioned, init scripts will run

Mattermost: Two Naming Surprises#

The Mattermost Team Edition Helm chart has its own naming quirks.

Service name ignores the release name. Regardless of what you name your release, the service is always mattermost-team-edition:

helm upgrade --install my-mm mattermost/mattermost-team-edition ...
kubectl get svc -n dream-team
# mattermost-team-edition   ClusterIP   10.96.88.3   <none>   8065/TCP
# NOT "my-mm-mattermost-team-edition"

Connection string format matters. The externalConnectionString value should NOT include the postgres:// prefix because the chart adds it:

# WRONG - double prefix results in "postgres://postgres://..."
externalConnectionString: "postgres://mmuser:password@dt-postgresql:5432/mattermost?sslmode=disable"

# CORRECT - just the credentials and host
externalConnectionString: "mmuser:password@dt-postgresql:5432/mattermost?sslmode=disable"

CRD Ordering: Install Order Matters#

If you install a chart that creates ServiceMonitor resources before the Prometheus Operator CRDs exist, Helm will fail. The fix is to install CRDs first, or disable ServiceMonitor creation:

# Option 1: Install CRDs first
helm upgrade --install prometheus-crds prometheus-community/prometheus-operator-crds

# Option 2: Disable ServiceMonitor in the chart
helm upgrade --install dt-postgresql bitnami/postgresql \
  --set metrics.serviceMonitor.enabled=false

Label Selector Immutability#

Once a Deployment or StatefulSet is created, Kubernetes does not allow you to change its spec.selector.matchLabels. If a chart update changes label selectors, you will see:

Error: UPGRADE FAILED: cannot patch "my-app" with kind Deployment:
Deployment.apps "my-app" is invalid: spec.selector: Invalid value: ... field is immutable

The only fix is to delete and recreate the resource:

kubectl delete deployment my-app -n dream-team
helm upgrade --install my-app ./my-chart

Safe Helm Patterns#

helm upgrade --install is idempotent. Use it in Makefile targets without worrying about “already exists” errors:

.PHONY: db
db:
	helm upgrade --install dt-postgresql bitnami/postgresql \
		--namespace dream-team --create-namespace \
		-f values/postgresql.yaml --wait --timeout 120s

Quick Debugging Checklist#

  1. Service not found? Run kubectl get svc -n <namespace> to see actual names.
  2. Pod not starting? Check kubectl describe pod <name> for image pull errors (bad tags).
  3. Init scripts did not run? Delete the PVC to force re-initialization.
  4. Connection refused? Verify the connection string format – some charts add protocol prefixes automatically.
  5. Upgrade failed on selectors? Delete the resource and re-run the install.