# Procedure — Onboard a new app to an existing cluster > **Layer:** Layer 1 — Agent-Writable. > **Blast radius:** one new Helm release on one cluster. > **Approval:** app owner + cluster owner. This procedure adds a new infrastructure-tooling Helm release to a cluster that already exists in `helm-overrides/`. It covers the slice owned by `devops-infra-helm-charts`. The matching Argo `Application` lives in `github.com/Meesho/devops-infra-argo-config` and must be paired. --- ## Inputs | Input | Example | |-------|---------| | Chart name (must exist in `helm-templates/`) | `kube-state-metrics` | | Target cluster directory | `k8s-supply-prd-ase1` | | Release name | `kube-state-metrics` (matches chart name; may be different for variants) | | Workload namespace | `monitoring` | | Image tag | `v2.10.1` | | Sized resources (CPU/memory requests + limits) | `250m / 512Mi` | | Node-pool key (per cluster) | `dedicated: monitoring` | | Whether this needs a sidecar `external-dns` Service | yes / no | --- ## Pre-conditions - [ ] The chart exists in `helm-templates//` with a current `Chart.yaml`. - [ ] The cluster directory exists in `helm-overrides//`. - [ ] The chart is appropriate for an *infra* release (services don't go here — they live in `devops-argo-config`). - [ ] The matching sister-repo `Application` PR is drafted (or will be drafted in parallel). - [ ] CMR ticket open if required by BU policy. --- ## Steps ### 1. Verify the chart renders with a sibling cluster's values Pick a cluster that already runs this chart and use its values as a starting point: ```bash sibling=$(find helm-overrides -maxdepth 2 -type d -name '' | head -1) helm template helm-templates/ -f "$sibling/custom-values.yaml" | head -60 ``` If the render errors → the chart's dependencies may be unresolved. Run `helm dependency update helm-templates/` first. ### 2. Identify the cluster's scheduling profile ```bash # Standard GKE: uses 'dedicated:' keys grep -rh 'dedicated:' helm-overrides//*/custom-values.yaml | sort -u # GKE Autopilot: uses 'cloud.google.com/compute-class' keys grep -rh 'cloud.google.com/compute-class' helm-overrides//*/custom-values.yaml | sort -u ``` For Contour, cross-reference [contour-nodeselector-tolerations-summary.md](../../../contour-nodeselector-tolerations-summary.md). For others, copy from a sibling app on the **same** cluster — never from the same app on a different cluster ([SANCTITY_RULES R5](../../global/SANCTITY_RULES.md)). ### 3. Create the directory and `custom-values.yaml` ```bash mkdir -p helm-overrides// $EDITOR helm-overrides///custom-values.yaml ``` Author from scratch using [custom-values-schema.md](../schemas/custom-values-schema.md) and the cluster's scheduling profile from step 2. Do **not** copy a sibling cluster's values verbatim. Skeleton: ```yaml image: registry: asia-southeast1-docker.pkg.dev repository: meesho-devops-admin-0622/admin/sre/ tag: replicaCount: resources: requests: {cpu: , memory: } limits: {cpu: , memory: } nodeSelector: : tolerations: - {key: , value: , effect: NoSchedule} ``` ### 4. (If needed) Add sidecar raw manifests If the app needs sidecar resources (e.g. `external-dns` `Service`, `ComputeClass`, `ExternalSecret`), drop them in the same directory under a subfolder: ``` helm-overrides/// custom-values.yaml external-dns-services/.yaml computeclass/-cc.yaml ``` See [raw-manifest-sidecar-schema.md](../schemas/raw-manifest-sidecar-schema.md). ### 5. Validate locally ```bash yamllint helm-overrides///custom-values.yaml # Render helm template helm-templates/ \ -f helm-overrides///custom-values.yaml | head -60 # Optional: dry-run diff against the live cluster (requires kubectl context + helm-diff plugin) helm diff upgrade helm-templates/ \ -f helm-overrides///custom-values.yaml \ --kube-context= ``` ### 6. Open the sister-repo PR In `github.com/Meesho/devops-infra-argo-config`, draft an `Application` (or add to an existing `ApplicationSet`): ```yaml apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: - spec: destination: name: namespace: source: repoURL: https://github.com/Meesho/devops-infra-helm-charts.git targetRevision: main path: helm-overrides// helm: valueFiles: [custom-values.yaml] syncPolicy: syncOptions: [CreateNamespace=true] # Most infra apps DO NOT use automated sync — see ADR-A5 ``` ### 7. Open the values-side PR (this repo) ```bash git checkout -b onboard/-on- git add helm-overrides/// git commit # pre-commit hook runs TruffleHog git push origin onboard/-on- gh pr create --base main --title "Onboard to " ``` PR description: - Procedure followed: this file. - App owner approver tag. - Cluster owner approver tag. - Sister-repo PR link (`devops-infra-argo-config#`). - CMR ticket reference (if applicable). - Confirmation that the chart renders cleanly and `helm diff` (if run) showed only additions. ### 8. After both merge — sync in Argo CD `devops-infra-argo-config`'s reconciler will create the `Application` resource on the cluster's Argo CD. Most infra apps are **manual sync** ([ADR-A5](../../../wiki/analyses/ADR-A5-manual-sync-default-for-infra.md)), so the workload deploy is a separate step: 1. Open the cluster's Argo CD UI. 2. Search for the new `Application`. 3. Verify the manifest renders (Diff view shows the chart's resources). 4. Click **Sync**. 5. Watch the rollout: `kubectl --context= get pods -n -w`. --- ## Anti-patterns 1. **Copying the entire `helm-overrides///` directory** verbatim. Per-cluster scheduling differs. 2. **Bundling onboarding with a chart-version bump.** Two separate PRs. 3. **Skipping the sister-repo PR.** Without an `Application`, the values do nothing. 4. **Setting `automated.{prune,selfHeal}: true`** in the sister-repo `Application` "to make life easier." Manual sync is the default safety property. 5. **Inlining secrets** in `custom-values.yaml`. Use `ExternalSecret`. --- ## Rollback If the merge causes a problem before Sync: - Revert the values-side PR (and the sister-repo PR). - Argo CD will prune the `Application` resource on next reconcile of the sister repo. If Sync was clicked and the workload broke: - Click **Rollback** in Argo CD UI to the previous synced revision (if there is one). - Or revert both PRs and re-Sync — the previous state had no `Application`, so the workload is removed. --- ## Related - Schema: [custom-values-schema.md](../schemas/custom-values-schema.md), [raw-manifest-sidecar-schema.md](../schemas/raw-manifest-sidecar-schema.md). - Procedure: [update-chart-version.md](update-chart-version.md) for bumping after onboarding. - Procedure: [deboard-app.md](deboard-app.md) for retirement. - Skill: [skills/infra/onboard-app.md](../../../skills/infra/onboard-app.md) — agent-callable wrapper. - ADR: [ADR-A3-per-cluster-scheduling.md](../../../wiki/analyses/ADR-A3-per-cluster-scheduling.md).