Argo CD doesn’t actually deploy Kustomize apps; it renders Kustomize manifests and then applies those rendered manifests to your cluster.

Let’s see this in action. Imagine you have a Kustomize project structured like this:

my-app/
├── base/
│   ├── deployment.yaml
│   └── service.yaml
└── overlays/
    └── dev/
        ├── kustomization.yaml
        └── ingress.yaml

base/deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-app
        image: nginx:latest

base/service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: my-app-service
spec:
  selector:
    app: my-app
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

overlays/dev/kustomization.yaml:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base

patchesStrategicMerge:
- deployment-patch.yaml
- service-patch.yaml

overlays/dev/deployment-patch.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app # Must match the name in base
spec:
  template:
    spec:
      containers:
      - name: my-app # Must match the container name in base
        image: nginx:1.21.0 # Overridden image

overlays/dev/service-patch.yaml:

apiVersion: v1
kind: Service
metadata:
  name: my-app-service # Must match the name in base
spec:
  type: ClusterIP # Overridden service type

overlays/dev/ingress.yaml:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app-ingress
spec:
  rules:
  - host: dev.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: my-app-service
            port:
              number: 80

When you configure Argo CD to sync this application, you’d point it to the Git repository containing my-app and specify the path as my-app/overlays/dev. Argo CD then does the following:

  1. Fetches the Git repository: It clones the specified branch and revision.
  2. Invokes kustomize build: Argo CD internally runs kustomize build <path-to-overlay> (e.g., kustomize build my-app/overlays/dev). This command reads the kustomization.yaml file in the specified overlay directory.
  3. Applies Kustomize logic: Kustomize merges the resources from the base, applies the strategic merge patches (deployment-patch.yaml, service-patch.yaml), and includes the additional resource (ingress.yaml).
  4. Generates final manifests: The output of kustomize build is a single YAML stream containing the complete, rendered Kubernetes manifests.
  5. Applies manifests to the cluster: Argo CD takes these generated manifests and applies them to your Kubernetes cluster using kubectl apply or its own internal diffing and patching mechanisms.

The key is that Argo CD doesn’t understand Kustomize in the way you might think. It’s not a Kustomize-native controller. It’s a GitOps tool that knows how to execute Kustomize to produce standard Kubernetes YAML, and then it manages the lifecycle of those YAML objects in your cluster.

The problem this solves is a common one: managing application configurations that vary across environments (dev, staging, prod) without duplicating large amounts of YAML. Kustomize’s declarative approach allows you to define a common "base" and then apply environment-specific modifications (patches, additions) without forking the entire configuration. Argo CD then automates the deployment of these Kustomize-generated configurations from Git.

You control the behavior by defining your Kustomize structure. The kustomization.yaml file is the heart of it.

  • resources: Points to other Kustomize directories or raw YAML files that form the base configuration.
  • patchesStrategicMerge: Applies patches to existing resources defined in resources. The patch file must have the same apiVersion, kind, metadata.name, and metadata.namespace as the resource it’s patching.
  • patchesJson6902: Allows for more precise JSON patch operations.
  • commonLabels, commonAnnotations: Apply labels or annotations to all resources defined in the kustomization.yaml.
  • images: Allows you to override image tags or names for all containers within the Kustomize build.

When you configure an Argo CD Application to use Kustomize, you provide the Git repository URL, the branch, and the path within the repository that contains the Kustomize kustomization.yaml file. Argo CD automatically detects that it’s a Kustomize project (based on the presence of kustomization.yaml) and performs the build step.

The one thing most people don’t realize is that Argo CD’s Kustomize integration is essentially a thin wrapper around the kustomize CLI. If you can build your manifests locally with kustomize build ./my-app/overlays/dev, Argo CD can deploy it. This means you can use any valid Kustomize feature, including complex plugins, and Argo CD will execute them as part of its build process. The rendered output is what Argo CD actually applies.

The next concept you’ll likely encounter is managing Helm charts alongside Kustomize applications within Argo CD, or exploring more advanced Kustomize features like server-side apply compatibility.

Want structured learning?

Take the full Argocd course →