Published: 2026-06-01 โ€ข Updated: 2026-07-05

Working with Helm Charts in ArgoCD: Enterprise GitOps Patterns

An industry-grade, deep-dive guide to declarative Helm deployments, OCI registries, multi-source applications, secret management, and performance scaling in ArgoCD.


Table of Contents


What is Helm in ArgoCD?

Featured Snippet Definition: Helm in ArgoCD is a native integration where the argocd-repo-server acts as a rendering engine, running helm template under the hood to compile Helm charts into flat Kubernetes manifests. Unlike standard Helm CLI deployments, ArgoCD does not store release metadata in Kubernetes Secrets or use the Helm release history. Instead, it tracks application state directly through its GitOps controller, treating the Helm chart as a template source and managing the lifecycle of the rendered resources dynamically.

In a traditional Kubernetes workflow, Helm acts as both a package manager and a deployment engine. Developers run helm install or helm upgrade, and Helm stores release history in cluster-level Secrets. However, in an enterprise GitOps model, this approach introduces a state split: Helm thinks it owns the state, while Git is supposed to be the single source of truth.

ArgoCD solves this friction by decoupling templating from deployment. ArgoCD pulls your Helm chart, injects the values you specify, compiles the manifests locally within its controller environment, and then applies them using its own highly optimized reconciliation engine. This gives you the packaging power of Helm combined with the continuous drift detection, self-healing, and RBAC security of ArgoCD.

What You Will Learn

This comprehensive guide covers the following advanced GitOps and Helm integration concepts:

  • The internal mechanics of the argocd-repo-server during Helm compilation.
  • How to structure Helm repositories, including OCI (Open Container Initiative) registries and Git-backed charts.
  • Declarative configurations for mono-charts, umbrella charts, and ArgoCD Multi-Source Applications.
  • Enterprise patterns for injecting secrets into Helm values without committing sensitive data to Git.
  • Aligning Helm lifecycle hooks with ArgoCD Sync Waves to prevent application startup race conditions.
  • Strategies for managing large-scale Custom Resource Definitions (CRDs) without breaking dry-run operations.
  • Performance tuning for high-throughput GitOps pipelines deploying hundreds of Helm charts simultaneously.

Prerequisites

To get the most out of this masterclass lesson, you should have:

  • A solid understanding of Kubernetes core resources (Deployments, Services, ConfigMaps, CRDs).
  • Familiarity with standard Helm concepts, such as values.yaml, templates, helper functions, and dependencies.
  • An operational ArgoCD instance (v2.6 or higher recommended to support multi-source features).
  • Access to a terminal with kubectl and helm CLI installed for local validation.
  • Read the previous lesson on Declarative Application Management.

Architecture and Internal Workflows

Understanding how ArgoCD processes Helm charts is critical for debugging performance bottlenecks and rendering issues. The architecture relies heavily on the separation of concerns between the repository controller and the state reconciliation controller.

The Rendering Pipeline

The diagram below illustrates the sequence of events when an ArgoCD Application pointing to a Helm chart is created or synchronized:

+------------------+          1. Polls / Webhook Trigger          +------------------+
|  Git Repository  | <------------------------------------------ |                  |
|        or        |                                             |   ArgoCD Repo    |
|  Helm Registry   | ------------------------------------------> |     Server       |
+------------------+          2. Pulls Chart & values.yaml       |                  |
                                                                 +------------------+
                                                                          |
                                                                          | 3. Runs 'helm template'
                                                                          |    with overrides
                                                                          v
+------------------+          5. Compares State & Applies        +------------------+
|  Kubernetes API  | <------------------------------------------ |  ArgoCD App      |
|     Cluster      |                                             |  Controller      |
+------------------+ <------------------------------------------ +------------------+
                                  6. Monitors Drift                       ^
                                                                          |
                                  4. Sends Flat Manifests (JSON/YAML) ----+

Step-by-Step Execution Lifecycle

  1. Discovery and Fetching: The argocd-repo-server detects a change in Git or a new target revision in the Helm registry. It fetches the chart payload. If the source is an OCI registry, it authenticates and downloads the tarball to its local cache directory (typically /tmp).
  2. Dependency Resolution: If the chart contains subcharts declared in Chart.yaml under dependencies, and they are not packaged within the chart, the repo-server runs helm dependency build to fetch the subcharts.
  3. Manifest Generation: The repo-server executes a dry-run templating operation. This is equivalent to running:
    helm template [RELEASE_NAME] [CHART_PATH] --values [VALUE_FILES] --set [PARAMETER_OVERRIDES]
    ArgoCD injects system variables, such as the target namespace and release name, to ensure the templates render with the correct metadata context.
  4. Manifest Transfer: The generated raw YAML manifests are parsed into JSON objects and sent over a secure gRPC channel from the argocd-repo-server to the argocd-application-controller.
  5. State Comparison and Diffing: The Application Controller queries the live Kubernetes API server to get the current state of the resources. It performs a semantic three-way diff between the Git-defined target state, the live cluster state, and the last applied configuration.
  6. Pruning and Reconciliation: If out-of-sync resources are found and auto-sync is enabled, the Application Controller applies the changes. It bypasses Helm entirely during deployment, using standard server-side or client-side apply mechanisms.

Why ArgoCD Does Not Use "Helm List"

Because ArgoCD converts the Helm chart to raw manifests before communicating with the cluster, running helm list -n my-namespace on your cluster will return an empty list. This is expected behavior.

This design choice has major benefits:

  • No Release Locks: Standard Helm runs can hang if a release gets stuck in a PENDING_UPGRADE state. ArgoCD avoids this entirely by managing resource states directly via the Kubernetes API.
  • Granular Drift Detection: ArgoCD can detect if a single field in a Deployment (e.g., replica count) was manually changed on the cluster and immediately mark the application as OutOfSync. Helm CLI cannot do this natively without external plugins.
  • Uniform RBAC: Security policies are applied uniformly across all applications, whether they are defined as Kustomize, raw YAML, or Helm charts.

Methods for Deploying Helm Charts

Depending on your enterprise topology, security boundaries, and repository structures, you can choose from four primary patterns to deploy Helm charts in ArgoCD.

Pattern Source Location Values Location Best Use Case
Direct Registry Source Public/Private Helm Repo (HTTPS/OCI) Inlined in ArgoCD Application CRD Third-party off-the-shelf software (e.g., Prometheus, NGINX Ingress) with minimal configuration overrides.
Git-Backed Local Chart Internal Git Repository In Git (alongside the templates) Proprietary microservices where developers own both the chart templates and the deployment values.
Umbrella Chart Pattern Internal Git Repository In Git (defining dependencies) Complex environments requiring orchestrations of multiple subcharts (e.g., deploying a complete database, cache, and backend stack together).
Multi-Source Application Helm Registry (Chart) + Git Repo (Values) In Git (completely decoupled) Enterprise platform engineering teams managing third-party charts where configuration values must be kept in secure, environment-specific Git folders.

1. Direct Registry Source

In this model, your ArgoCD Application references an external Helm registry directly. You define overrides in the Application manifest under the helm.parameters or helm.values fields. This is simple but can make the Application manifest bloated if you have hundreds of custom values.

2. Git-Backed Local Chart

Here, you commit the entire Helm chart directory (containing Chart.yaml, values.yaml, and the templates/ folder) into your application's Git repository. ArgoCD references the Git repository path. This is ideal for internal applications where the chart lifecycle is tightly coupled with the application code.

3. The Umbrella Chart Pattern

An umbrella chart is a standard Helm chart that does not contain any templates of its own. Instead, its Chart.yaml lists other charts as dependencies. You commit this umbrella chart to a Git repository and use its values.yaml to configure the subcharts.

This is highly recommended for enterprise platform stacks. For example, you can create an umbrella chart named monitoring-stack that pulls in Grafana, Prometheus, and Loki, configuring them to interoperate out of the box.

4. Multi-Source Applications (ArgoCD v2.6+)

Historically, ArgoCD restricted an Application to a single source repository. If you wanted to use a public Helm chart but keep your values.yaml in a private Git repository, you had to use the Umbrella Chart pattern.

With Multi-Source support, you can point to the Helm registry for the chart templates, and point to a Git repository for the environment-specific values.yaml. ArgoCD combines them in memory during rendering.


Production Code Manifests

Below are fully commented, production-grade manifest definitions for the core Helm patterns in ArgoCD.

Example 1: Direct OCI Helm Registry Integration

OCI (Open Container Initiative) is now the standard for distributing Helm charts using container registries like Amazon ECR, GHCR, or Harbor. The following manifest demonstrates how to configure an ArgoCD Application to pull a chart from an authenticated OCI registry.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: enterprise-redis-cluster
  namespace: argocd
  labels:
    environment: production
    tier: database
spec:
  project: default
  source:
    # Notice the 'oci://' prefix and the absence of the chart name in the repoURL
    repoURL: oci://ghcr.io/enterprise-charts
    chart: redis-operator
    targetRevision: 3.4.1
    helm:
      # Release name overrides the default application name
      releaseName: prod-redis
      # Direct inline values overrides
      values: |
        replicaCount: 3
        sentinel:
          enabled: true
        resources:
          limits:
            cpu: 1000m
            memory: 2Gi
          requests:
            cpu: 500m
            memory: 1Gi
        metrics:
          enabled: true
          serviceMonitor:
            enabled: true
            additionalLabels:
              release: prometheus-stack
  destination:
    server: https://kubernetes.default.svc
    namespace: database-prod
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true
      - ServerSideApply=true

Example 2: The Umbrella Chart Configuration

This example shows how to declare an application using an umbrella chart stored in Git. First, let's look at the Chart.yaml file of your umbrella chart:

# Chart.yaml stored in Git under /deployments/umbrella-app/
apiVersion: v2
name: enterprise-application-stack
description: Umbrella chart to deploy core application dependencies
type: application
version: 1.0.0
appVersion: "1.0.0"
dependencies:
  - name: postgresql
    version: 12.5.6
    repository: https://charts.bitnami.com/bitnami
  - name: rabbitmq
    version: 11.15.0
    repository: https://charts.bitnami.com/bitnami

Next, the corresponding values.yaml file residing in the same directory:

# values.yaml stored in Git under /deployments/umbrella-app/
postgresql:
  auth:
    database: app_db
    username: app_user
  primary:
    persistence:
      size: 50Gi

rabbitmq:
  auth:
    username: rabbit_user
  replicaCount: 3

Finally, the ArgoCD Application manifest that points to this Git directory:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: production-app-stack
  namespace: argocd
spec:
  project: default
  source:
    # Points to your internal Git repository containing the umbrella chart
    repoURL: https://github.com/enterprise-org/gitops-infrastructure.git
    targetRevision: main
    path: deployments/umbrella-app
    helm:
      # Instructs ArgoCD to resolve dependencies defined in Chart.yaml
      valueFiles:
        - values.yaml
  destination:
    server: https://kubernetes.default.svc
    namespace: core-services
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

Example 3: Multi-Source Application (Decoupled Values)

This pattern pulls the base chart from an official public Helm registry and merges it with custom configuration files pulled from your private Git repository.

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: external-dns-multi-source
  namespace: argocd
spec:
  project: default
  sources:
    # Source 1: The official Helm Chart from a remote repository
    - repoURL: https://kubernetes-sigs.github.io/external-dns/
      chart: external-dns
      targetRevision: 1.13.0
      ref: external-dns-chart
    # Source 2: Your private Git repo containing environment-specific values
    - repoURL: https://github.com/enterprise-org/gitops-infrastructure.git
      targetRevision: main
      ref: gitops-repo
  # Direct ArgoCD to run Helm templating on the Helm chart (Source 1)
  # using the values file from the Git repository (Source 2)
  sourcePositions:
    chart: 1
  helm:
    valueFiles:
      - $gitops-repo/environments/production/external-dns/values.yaml
  destination:
    server: https://kubernetes.default.svc
    namespace: kube-system
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

Handling Secrets and Dynamic Values in GitOps

One of the biggest challenges in GitOps is managing secrets. Since Git is the single source of truth, committing plaintext secrets (like database passwords or API tokens) into a values.yaml file is a critical security violation.

To maintain strict security compliance, you should use one of the following enterprise patterns.

Pattern A: External Secrets Operator (ESO)

The External Secrets Operator is the industry-standard way to fetch secrets from external managers (HashiCorp Vault, AWS Secrets Manager, Google Secret Manager, Azure Key Vault) and inject them into Kubernetes native Secrets.

Under this pattern:

  1. Your Helm chart references a native Kubernetes Secret name and key in its environment variables or mounting definitions.
  2. You deploy an ExternalSecret resource alongside your Application. This resource instructs ESO to sync the secret from your secure vault into the local cluster namespace.
  3. When the application pod starts up, the Secret is already present on the cluster, populated with the correct credentials.
+----------------------------+          1. Syncs Secret Metadata          +----------------------------+
|  AWS/Vault Secret Manager  | <----------------------------------------- |  External Secrets Operator |
+----------------------------+                                            +----------------------------+
              |                                                                         |
              | 2. Delivers Payload                                                     | 3. Generates
              v                                                                         v
+----------------------------+                                            +----------------------------+
|  Kubernetes Native Secret  | <----------------------------------------- |   Target App Pod Mounts    |
+----------------------------+                                            +----------------------------+

Pattern B: ArgoCD Vault Plugin (AVP)

If you prefer secrets to be injected during the rendering phase rather than dynamically inside the cluster, you can use the ArgoCD Vault Plugin. AVP parses placeholders in your Git-tracked files (e.g., <path:secret/data/production/db#password>) and replaces them with actual secret values during the argocd-repo-server rendering cycle.

Note: This requires configuring custom tooling in your ArgoCD repo-server image and is generally more operationally complex than using ESO.


Helm Hooks vs. ArgoCD Sync Waves & Hooks

Helm charts often use Helm Hooks (e.g., helm.sh/hook: pre-install) to run database migrations, clear caches, or perform health checks before or after updating resources.

Because ArgoCD converts Helm templates into flat manifests and applies them using its own controller, Helm Hooks are translated into ArgoCD Hooks by default. However, there are subtle differences in behavior that can break complex deployment orchestrations.

Comparison of Lifecycle Mechanics

Feature Helm Native Hooks ArgoCD Resource Hooks
Declaration Annotation helm.sh/hook argocd.argoproj.io/hook
Execution Engine Helm CLI (client-side orchestration) ArgoCD Application Controller (cluster-side controller loop)
Deletion Policies helm.sh/hook-delete-policy argocd.argoproj.io/hook-delete-policy
Granular Phase Control Limited (PreInstall, PostInstall, etc.) Extensive (PreSync, Sync, PostSync, SyncFail)
Wave Orchestration Hook weights (numeric execution order) Sync Waves (argocd.argoproj.io/sync-wave)

Best Practice: Explicit Migration to ArgoCD Annotations

If you are writing internal Helm charts, it is highly recommended to use ArgoCD annotations instead of Helm annotations. This ensures predictable state transitions and allows you to view hook execution stages in the ArgoCD UI.

Here is an example of a database migration Job configured natively for ArgoCD within a Helm chart:

apiVersion: batch/v1
kind: Job
metadata:
  name: {{ include "my-app.fullname" . }}-db-migrate
  annotations:
    # Run this job before applying the main resources (Deployments, Services)
    argocd.argoproj.io/hook: PreSync
    # Delete the job pod only after it has successfully completed
    argocd.argoproj.io/hook-delete-policy: HookSucceeded
    # Execute this job in sync wave -2 (lower numbers run first)
    argocd.argoproj.io/sync-wave: "-2"
spec:
  template:
    spec:
      containers:
        - name: migration
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          command: ["/app/migrate.sh"]
      restartPolicy: OnFailure

Managing Custom Resource Definitions (CRDs) with Helm in ArgoCD

Managing Custom Resource Definitions (CRDs) in Helm charts is one of the most contentious topics in the Kubernetes community. Helm natively places CRDs in a special crds/ directory. According to Helm specifications:

  • CRDs in the crds/ directory are only installed during the initial installation of the chart.
  • They are never updated or deleted during subsequent upgrades of the chart to prevent accidental data loss.

The ArgoCD CRD Conflict

When ArgoCD processes a Helm chart containing a crds/ directory, it honors the initial installation. However, because ArgoCD does not use standard Helm upgrade mechanisms, updating CRDs in upstream charts (like prometheus-operator or cert-manager) during a version upgrade will fail to apply.

Enterprise Solutions for CRD Management

To resolve this, choose one of the following two production-tested strategies:

Strategy 1: Separate CRD Lifecycle App (Recommended)

Decouple your CRD lifecycle from your application lifecycle. Create an independent ArgoCD Application that deploys only the CRDs from raw YAML manifests or a dedicated CRD chart. Once the CRDs are stable on the cluster, deploy the main Helm chart.

Strategy 2: Enable Server-Side Apply and Skip Dry-Run

If you must deploy CRDs within the same Helm chart, configure your ArgoCD Application to use Server-Side Apply. This allows Kubernetes to handle large CRD manifests that would otherwise exceed the default annotations size limit (262,144 bytes).

spec:
  syncPolicy:
    syncOptions:
      # Bypasses client-side validation which can fail if CRDs are not yet registered
      - SkipDryRunOnMissingResource=true
      # Uses Server-Side Apply to avoid annotation size limits
      - ServerSideApply=true

Performance Optimization and Scaling

In a large enterprise cluster with thousands of applications, the argocd-repo-server can quickly become a performance bottleneck. Because Helm templating is a CPU-intensive process, simultaneous reconciliations can cause container restarts, high latency, and application synchronization delays.

1. Horizontal Pod Autoscaling (HPA) for Repo Server

The argocd-repo-server is stateless. You can scale it horizontally to handle high load. Ensure you have an HPA defined for the repo-server deployment in your management cluster:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: argocd-repo-server-hpa
  namespace: argocd
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: argocd-repo-server
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 80

2. Configuring the Manifest Cache

ArgoCD uses Redis to cache rendered manifests. By caching the output of helm template, ArgoCD avoids re-rendering charts on every reconciliation loop unless a commit change is detected.

Ensure your Redis instance is sized appropriately and that you configure cache expiration times in the argocd-cm ConfigMap:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  # Cache manifest generation results for 24 hours (default is 24h)
  # Decrease this only if you rely on dynamic values from external systems
  manifest.cache.duration: "24h"

3. Optimizing Helm Dependency Builds

If your Helm charts rely on remote subcharts, ArgoCD must fetch them during compilation. By default, this requires executing network calls to external registries.

  • Pre-package Subcharts: Whenever possible, run helm dependency update locally and commit the resulting .tgz files inside the charts/ directory of your Git repository. This removes the network overhead during ArgoCD rendering.
  • Increase Timeout Thresholds: If you must fetch dependencies on the fly, increase the repository server's execution timeout limit to prevent timeouts on large charts. Set the environment variable ARGOCD_EXEC_TIMEOUT on the argocd-repo-server container (e.g., 180s).

Troubleshooting Common Helm Failures

Deploying Helm charts via a declarative GitOps controller introduces unique failure modes. Below is a guide to diagnosing and resolving the most common issues.

Error 1: RPC Timeout During Manifest Generation

Symptom: The application status shows ComparisonError with an error message like: rpc error: code = DeadlineExceeded desc = context deadline exceeded.

Root Cause: The argocd-repo-server took longer than the configured timeout limit (default 90 seconds) to download the chart, resolve dependencies, and run helm template.

Resolution:

  • Check the CPU usage of the argocd-repo-server pods. If they are throttling, increase CPU requests/limits.
  • Check network latency between the repo-server and the Helm registry.
  • Increase the execution timeout limit by editing the ArgoCD deployments and adding the environment variable:
    ARGOCD_EXEC_TIMEOUT=180s

Error 2: Failed to Connect to OCI Registry

Symptom: rpc error: code = Unknown desc = repository not found or unauthorized: authentication required.

Root Cause: ArgoCD does not have the correct credentials to access your private OCI registry.

Resolution: Register the OCI registry credentials globally in ArgoCD. You must configure this in the argocd-secrets or via the UI/CLI. Here is a declarative Secret definition:

apiVersion: v1
kind: Secret
metadata:
  name: private-ghcr-oci
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: repository
type: Opaque
stringData:
  type: helm
  # Notice: The URL must not contain the chart name
  url: oci://ghcr.io/enterprise-org
  enableOCI: "true"
  username: gitops-robot
  password: ghp_SomeGitHubPersonalAccessTokenHere

Error 3: CRD Validation Failure on Dry-Run

Symptom: ValidationError(MyCustomResource): unknown field "spec" during synchronization.

Root Cause: ArgoCD attempted to perform a dry-run validation of a Custom Resource before the corresponding Custom Resource Definition (CRD) was fully registered or updated in the cluster.

Resolution: Enable SkipDryRunOnMissingResource=true in your Application's syncOptions. This allows ArgoCD to skip validation for resources whose definitions are missing from the API server during the dry-run phase.


Interview Questions and Answers

Question 1: How does ArgoCD render and apply Helm charts differently than the Helm CLI?

Answer: The Helm CLI performs templating locally and applies the resources using the Helm engine, saving the release metadata as a Kubernetes Secret in the target namespace. This metadata tracks history and rollback states.

ArgoCD, on the other hand, uses the argocd-repo-server to run helm template to render the chart into flat Kubernetes manifests. It then bypasses the Helm engine entirely, sending these raw manifests to the argocd-application-controller, which reconciles them against the live cluster state using its own three-way diff engine. No Helm release history Secrets are created in the target namespace.

Question 2: What is the purpose of the "SkipDryRunOnMissingResource" sync option when deploying Helm charts?

Answer: When ArgoCD synchronizes resources, it runs a dry-run validation against the Kubernetes API. If a Helm chart contains both a Custom Resource Definition (CRD) and a Custom Resource (CR) that depends on that CRD, the dry-run will fail because the CRD does not exist in the cluster yet.

Setting SkipDryRunOnMissingResource=true tells ArgoCD to skip the dry-run validation step for any resource whose API definition (CRD) is not yet registered in the cluster. This allows the CRD to be applied first, after which the CR can be successfully applied during the same sync loop.

Question 3: How do you handle a scenario where you need to deploy a third-party Helm chart but must override values with secrets stored in AWS Secrets Manager?

Answer: The recommended enterprise pattern is to use the External Secrets Operator (ESO). You would:

  1. Deploy an ExternalSecret resource alongside your ArgoCD Application.
  2. Configure the ExternalSecret to fetch the sensitive data from AWS Secrets Manager and write it to a standard Kubernetes Secret in the application's namespace.
  3. In your Helm chart configuration (or values overrides in the Application spec), map the application's environment variables or volume mounts to reference this Kubernetes Secret.

This keeps credentials completely decoupled from Git and handles rotation dynamically.

Question 4: What are the advantages of using Multi-Source Applications over the traditional Umbrella Chart pattern?

Answer: The traditional Umbrella Chart pattern requires you to create and maintain a wrapper Helm chart in a Git repository simply to reference external subcharts and store their values.

Multi-Source Applications (introduced in ArgoCD v2.6) allow you to reference the upstream Helm chart registry and your private Git configuration directory as two independent sources within a single ArgoCD Application manifest. This removes the overhead of maintaining wrapper charts, simplifies directory structures, and makes it easier to track upstream chart versions.


Frequently Asked Questions (FAQs)

Can I run "helm rollback" on an application managed by ArgoCD?

No. Because ArgoCD does not store Helm release metadata on the cluster, the helm rollback command will not work. To roll back an application in a GitOps model, you must revert the commit in your Git repository. ArgoCD will detect the change and automatically synchronize the cluster back to the previous state.

How does ArgoCD handle private Helm repositories that require authentication?

You must register the private repository credentials in ArgoCD. This can be done via the ArgoCD UI, the CLI, or declaratively by creating a Kubernetes Secret in the argocd namespace with the label argocd.argoproj.io/secret-type: repository.

What happens if a Helm chart has subcharts? Does ArgoCD download them automatically?

Yes. If the subcharts are declared in Chart.yaml, the argocd-repo-server will automatically run helm dependency build to fetch the dependencies before rendering the templates. To speed up rendering, you can pre-package and commit the subcharts to your Git repository.

Why does ArgoCD mark my Helm-deployed application as OutOfSync immediately after a successful sync?

This usually happens due to dynamic fields in your Helm templates (such as random password generators or timestamps like helm.sh/chart: mychart-1.0.0-timestamp). Since these values change every time helm template is run, ArgoCD detects a drift from the live cluster state. You can resolve this by using fixed values or by configuring ignoreDifferences in your Application manifest.

Can I use Helm hooks like pre-install and post-install with ArgoCD?

Yes. ArgoCD natively translates Helm hooks into ArgoCD hooks. However, for more predictable behavior and better integration with the ArgoCD UI, it is highly recommended to migrate native Helm hooks to ArgoCD Resource Hooks using the argocd.argoproj.io/hook annotation.

How do I deploy different Helm values for dev, staging, and production environments?

You can use the Multi-Source Application pattern to point to a single base Helm chart while pulling different values files (e.g., values-dev.yaml, values-prod.yaml) from environment-specific folders in your Git repository.


Summary and Next Steps

Integrating Helm with ArgoCD combines the packaging power of Helm with the continuous reconciliation and security of GitOps. By understanding how the argocd-repo-server compiles templates, utilizing modern OCI registries, adopting multi-source architectures, and managing secrets securely, you can build resilient and highly scalable deployment pipelines.

About the Author

Naresh Kumar

Naresh Kumar

Senior Java Backend Engineer experienced in Banking, Payments, ISO 20022, Spring Boot, Microservices, Kafka, Docker, Kubernetes, AWS and Cloud Native Systems.

Built enterprise payment solutions, transaction processing systems, API platforms and scalable microservices used in production.

LinkedIn Profile