How to use imagePullSecrets in Helm 3
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
When a Kubernetes workload pulls images from a private registry, authentication must be available to the kubelet before the container starts. The standard mechanism is imagePullSecrets. In Helm 3 charts, teams often struggle with where to define those secrets, how to support multiple environments, and how to avoid hardcoding secret names in templates.
A clean setup keeps credentials outside the chart, passes secret names through values, and references them consistently in either Pod specs or ServiceAccounts. This article shows a production-friendly pattern, including templating, environment overrides, and troubleshooting when pulls fail with ImagePullBackOff.
Core Sections
1) Create registry credentials as Kubernetes Secret
Create the secret once per namespace where workloads run.
For GitOps workflows, you can also manage this as encrypted manifests using your preferred secret management tool.
2) Expose secret names in values.yaml
Keep templates reusable by passing one or more pull secrets from values.
Environment-specific value files can override this list without touching chart templates.
3) Render imagePullSecrets in Deployment template
Using with keeps output clean when no secret is configured.
4) Alternative: attach secrets to ServiceAccount
If many workloads share the same registry auth, attach secrets once to a ServiceAccount.
Then configure workloads with serviceAccountName: app-sa. This centralizes auth config and reduces repeated template fragments.
5) Validate rendered manifests and runtime behavior
Before deploy, run:
If pulls fail, inspect events. Common signals include unauthorized, wrong registry host, missing secret in namespace, or incorrect secret type (must be kubernetes.io/dockerconfigjson for Docker config).
6) Production checklist for Helm imagePullSecrets configuration
Before shipping this approach in a real project, validate it in a controlled workflow that mirrors production traffic, data shape, and failure modes. Start with one measurable success metric such as latency, error rate, or precision, then define acceptable limits. Run the implementation with representative inputs, not toy samples, and collect logs that explain both successes and failures. If behavior depends on external services or user input, include at least one negative test path so you can confirm how the system reacts when assumptions are violated.
Next, create an operational checklist for rollout. Document required configuration values, version constraints, and environment variables in one place. Add a lightweight smoke test that can run in CI and after deployment. Decide who owns alerts and what threshold should trigger investigation. For high-impact systems, define a rollback switch or feature flag so you can disable the new behavior without a full release cycle.
Finally, capture maintenance notes that future contributors will need: edge cases, known limitations, and links to test fixtures. This short documentation step reduces regressions during refactors and keeps the implementation understandable after the original author rotates to another project.
Common Pitfalls
- Creating
imagePullSecretsin one namespace and deploying workloads in another namespace. - Hardcoding secret names in templates instead of values, which breaks environment portability.
- Forgetting to pass the secret list in production values and only testing with public images locally.
- Assuming Pod-level and ServiceAccount-level configuration are both required when one approach is enough.
- Storing raw registry credentials in chart files instead of using secure secret management workflows.
Summary
imagePullSecrets in Helm 3 is straightforward once you separate responsibilities: create registry credentials securely, reference secret names through values, and render them in a consistent place (Pod spec or ServiceAccount). Validate with helm template and Kubernetes events before debugging deeper platform issues. With this pattern, private registry access remains portable across environments and easier to operate safely.
Related reading
- How to use kubectl command instead of sudo kubectl
- How to use kubectl cp to copy files automatically from a local system to kubernetes Pods with list filter
- How to use nginx ingress TCP service on different namespace
- How to use NodePort with kind?
- How to use PodTemplate
- How to use rabbitmqctl to connect to the rabbitmqserver in the docker container?
- how to use kafka acls?
- How to use MDC with thread pools?

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.