> ## Documentation Index
> Fetch the complete documentation index at: https://docs.pangolin.net/llms.txt
> Use this file to discover all available pages before exploring further.

# Kustomize

> Customize Helm-rendered Kubernetes manifests with Kustomize overlays.

<div id="pangolin-toc-cta" className="pangolin-toc-cta-source">
  <Card title="Try free on Pangolin Cloud" icon="cloud" href="https://app.pangolin.net/auth/signup" arrow="true" cta="Sign up free">
    Fastest way to get started with Pangolin using the hosted control plane. No credit card required.
  </Card>
</div>

Kustomize can be used to customize Kubernetes manifests with bases, overlays, and patches.

For Pangolin and Newt, the supported Kustomize workflow is to render the Helm charts into manifests and use those rendered manifests as the Kustomize base.

Use Kustomize when you need:

* environment-specific overlays for dev, staging, or production
* explicit manifest patches in Git
* a manifest-driven workflow for GitOps tools
* small changes on top of a shared base without maintaining separate full manifests

## Supported workflow

The chart repository does not provide native Kustomize bases. Use this workflow instead:

<Steps>
  <Step title="Render chart manifests">
    Render the Helm chart with your values file and save the output as base manifests.
  </Step>

  <Step title="Commit base manifests">
    Commit rendered manifests as the Kustomize base in Git.
  </Step>

  <Step title="Create environment overlays">
    Create overlays for each environment (for example dev, staging, production).
  </Step>

  <Step title="Apply or reconcile">
    Apply overlays manually or reconcile them with Argo CD or Flux.
  </Step>
</Steps>

<Warning>
  Do not manage the same resources with both a live Helm release and Kustomize. Pick one ownership model per environment.
</Warning>

Recommended ownership model:

* Use Helm only to render manifests.
* Use Kustomize, Argo CD, or Flux to apply and reconcile the rendered manifests.
* Re-render the base when upgrading the chart version.

## Example repository layout

```text theme={"theme":"gruvbox-light-hard"}
my-pangolin-k8s/
├── base/
│   ├── kustomization.yaml
│   ├── pangolin.yaml
│   └── newt.yaml
├── overlays/
│   ├── dev/
│   │   ├── kustomization.yaml
│   │   └── pangolin-resources.patch.yaml
│   ├── staging/
│   │   ├── kustomization.yaml
│   │   └── pangolin-resources.patch.yaml
│   └── prod/
│       ├── kustomization.yaml
│       └── pangolin-resources.patch.yaml
└── values/
    ├── values-pangolin.yaml
    └── values-newt.yaml
```

## Step 1: Render manifests from Helm

Create a base directory:

```bash theme={"theme":"gruvbox-light-hard"}
mkdir -p base overlays/dev overlays/staging overlays/prod
```

Render Pangolin:

<CodeGroup>
  ```bash Classic Helm repository theme={"theme":"gruvbox-light-hard"}
  helm template pangolin fossorial/pangolin \
    --namespace pangolin \
    --values values/values-pangolin.yaml \
    > base/pangolin.yaml
  ```

  ```bash OCI (GHCR) theme={"theme":"gruvbox-light-hard"}
  helm template pangolin oci://ghcr.io/fosrl/helm-charts/pangolin \
    --version 0.1.0-alpha.0 \
    --namespace pangolin \
    --values values/values-pangolin.yaml \
    > base/pangolin.yaml
  ```
</CodeGroup>

Render Newt:

<CodeGroup>
  ```bash Classic Helm repository theme={"theme":"gruvbox-light-hard"}
  helm template newt fossorial/newt \
    --namespace pangolin \
    --values values/values-newt.yaml \
    > base/newt.yaml
  ```

  ```bash OCI (GHCR) theme={"theme":"gruvbox-light-hard"}
  helm template newt oci://ghcr.io/fosrl/helm-charts/newt \
    --version 1.4.0 \
    --namespace pangolin \
    --values values/values-newt.yaml \
    > base/newt.yaml
  ```
</CodeGroup>

## Step 2: Create the base kustomization

```yaml theme={"theme":"gruvbox-light-hard"}
# base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - pangolin.yaml
  - newt.yaml
```

## Step 3: Create an overlay

Use `resources` to reference the base.

```yaml theme={"theme":"gruvbox-light-hard"}
# overlays/prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - ../../base

labels:
  - pairs:
      app.kubernetes.io/environment: production
      app.kubernetes.io/managed-by: kustomize

patches:
  - path: pangolin-resources.patch.yaml
    target:
      group: apps
      version: v1
      kind: Deployment
      name: pangolin
```

<Note>
  Avoid `namePrefix` and `nameSuffix` for Helm-rendered bases unless you have verified every generated reference. Renaming chart-generated resources can break service names, selectors, secret references, and workload dependencies.
</Note>

## Step 4: Add patches

Example Strategic Merge patch for container resources:

```yaml theme={"theme":"gruvbox-light-hard"}
# overlays/prod/pangolin-resources.patch.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pangolin
spec:
  template:
    spec:
      containers:
        - name: pangolin
          resources:
            requests:
              cpu: 1000m
              memory: 1Gi
            limits:
              memory: 2Gi
```

Example JSON6902-style inline patch:

```yaml theme={"theme":"gruvbox-light-hard"}
# overlays/prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
  - ../../base

patches:
  - target:
      group: apps
      version: v1
      kind: Deployment
      name: pangolin
    patch: |-
      - op: replace
        path: /spec/template/spec/containers/0/resources/requests/cpu
        value: "1000m"
```

<Note>
  Modern Kustomize uses the `patches` field for both Strategic Merge and JSON6902-style patches. Avoid `patchesStrategicMerge`, `patchesJson6902`, and `bases` in new examples.
</Note>

## Apply an overlay

Preview the rendered output:

```bash theme={"theme":"gruvbox-light-hard"}
kustomize build overlays/prod
```

Compare with the live cluster:

```bash theme={"theme":"gruvbox-light-hard"}
kustomize build overlays/prod | kubectl diff -f -
```

Apply the overlay:

```bash theme={"theme":"gruvbox-light-hard"}
kubectl apply -k overlays/prod
```

Or apply the rendered output:

```bash theme={"theme":"gruvbox-light-hard"}
kustomize build overlays/prod | kubectl apply -f -
```

## Updating the base

When upgrading chart versions or changing Helm values, re-render the base and review the diff.

```bash theme={"theme":"gruvbox-light-hard"}
helm repo update fossorial
```

Render the updated chart output:

```bash theme={"theme":"gruvbox-light-hard"}
helm template pangolin fossorial/pangolin \
  --namespace pangolin \
  --values values/values-pangolin.yaml \
  > base/pangolin.yaml
```

```bash theme={"theme":"gruvbox-light-hard"}
helm template newt fossorial/newt \
  --namespace pangolin \
  --values values/values-newt.yaml \
  > base/newt.yaml
```

Then validate the overlay:

```bash theme={"theme":"gruvbox-light-hard"}
kustomize build overlays/prod
```

Review changes before applying:

```bash theme={"theme":"gruvbox-light-hard"}
git diff
kustomize build overlays/prod | kubectl diff -f -
```

Apply after review:

```bash theme={"theme":"gruvbox-light-hard"}
kubectl apply -k overlays/prod
```

## Important considerations

### Namespace handling

Render the charts with the namespace you intend to use:

```bash theme={"theme":"gruvbox-light-hard"}
helm template pangolin fossorial/pangolin \
  --namespace pangolin \
  --values values/values-pangolin.yaml \
  > base/pangolin.yaml
```

Create the namespace before applying the overlay:

```bash theme={"theme":"gruvbox-light-hard"}
kubectl create namespace pangolin
```

Apply any required Pod Security Admission labels or cluster-policy labels before workloads are created.

### Secrets

Do not commit plaintext secrets into rendered manifests.

Use one of these approaches instead:

* reference existing Kubernetes Secrets in the values file before rendering
* create secrets separately with your secret-management workflow
* use Sealed Secrets, External Secrets Operator, SOPS, or another GitOps-safe secret solution

### Do not mix ownership models

Avoid this pattern:

```text theme={"theme":"gruvbox-light-hard"}
helm upgrade pangolin fossorial/pangolin
kubectl apply -k overlays/prod
```

This creates two tools managing the same objects.

Use one of these models instead:

| Model             | Description                                                                              |
| ----------------- | ---------------------------------------------------------------------------------------- |
| Helm-managed      | Helm installs and upgrades the live release. Kustomize is not used for the same objects. |
| Kustomize-managed | Helm only renders the base. Kustomize applies and owns the live objects.                 |
| GitOps-managed    | Argo CD or Flux applies the Kustomize overlay and owns reconciliation.                   |

## Troubleshooting

Validate the overlay:

```bash theme={"theme":"gruvbox-light-hard"}
kustomize build overlays/prod
```

Check the generated YAML:

```bash theme={"theme":"gruvbox-light-hard"}
kustomize build overlays/prod > manifests.yaml
```

Run a server-side dry run:

```bash theme={"theme":"gruvbox-light-hard"}
kubectl apply -f manifests.yaml --dry-run=server
```

Preview live changes:

```bash theme={"theme":"gruvbox-light-hard"}
kubectl diff -f manifests.yaml
```

Check live resources:

```bash theme={"theme":"gruvbox-light-hard"}
kubectl get all -n pangolin
kubectl get events -n pangolin --sort-by=.lastTimestamp
```

## Next steps

<CardGroup cols={2}>
  <Card title="Pangolin Kustomize Install" href="/self-host/manual/kubernetes/pangolin/kustomize" icon="server">
    Install Pangolin with rendered manifests and Kustomize overlays.
  </Card>

  <Card title="Newt Kustomize Install" href="/self-host/manual/kubernetes/newt/kustomize" icon="globe">
    Install Newt with rendered manifests and Kustomize overlays.
  </Card>

  <Card title="Argo CD" href="/self-host/manual/kubernetes/gitops/argocd" icon="code-branch">
    Reconcile Kustomize overlays with Argo CD.
  </Card>

  <Card title="Flux" href="/self-host/manual/kubernetes/gitops/flux" icon="code-branch">
    Reconcile Kustomize overlays with Flux.
  </Card>

  <Card title="Troubleshooting" href="/self-host/manual/kubernetes/pangolin/troubleshooting" icon="circle-question">
    Troubleshoot Pangolin deployments on Kubernetes.
  </Card>
</CardGroup>
