TT Lab
Get started
Learn Learning paths Courses

CAPA — Argo Project Associate

Assembling an Application Manifest

Continue in TT Lab

Goal

Build an Argo CD Application manifest to completion one field at a time, then put the namespace and Deployment that the app will deploy into a real cluster, and confirm by hand even how Argo CD recognizes its own resources.

Why it matters

An Application is a declaration of "what (source) to align, where (destination), and by what rules (syncPolicy)." It matters more to know what incident each field exists to prevent than to memorize field names. If you do not turn on prune, resources deleted from Git remain in the cluster forever; if you turn on selfHeal, values changed by hand are reverted; and if you use an HPA without ignoreDifferences, Argo CD and the HPA fight endlessly over replicas. The file you build in this lab is stacked up in the order that prevents those incidents one by one.

Steps

  1. Create the /root/capa-app/ directory and create application.yaml in it. The apiVersion is argoproj.io/v1alpha1, the kind is Application, metadata.name is guestbook, and metadata.namespace is argocd.
  2. In the same file, fill in spec.project as capa-demo, spec.source.repoURL as https://gitea.homelab.internal/platform/guestbook.git, spec.source.targetRevision as main, and spec.source.path as overlays/prod.
  3. Set spec.destination.server to https://kubernetes.default.svc and spec.destination.namespace to capa-guestbook. Do not use destination.name.
  4. Set both spec.syncPolicy.automated.prune and spec.syncPolicy.automated.selfHeal to true, and put two items, CreateNamespace=true and PruneLast=true, in spec.syncPolicy.syncOptions.
  5. Set spec.syncPolicy.retry.limit to 5, spec.syncPolicy.retry.backoff.duration to 5s, factor to 2, and maxDuration to 3m.
  6. In the first item of spec.ignoreDifferences, put group: apps, kind: Deployment, and /spec/replicas in jsonPointers, to exclude the field managed by the HPA from the comparison.
  7. Actually create the namespace capa-guestbook in the cluster and attach the label app.kubernetes.io/part-of=capa.
  8. Actually create the Deployment guestbook-ui in the namespace capa-guestbook. Set replicas to 2, the container image to nginx:1.27, and attach argocd.argoproj.io/tracking-id as the Deployment's own annotation in Argo CD's format. The app name is guestbook.

Notes

Working directory and the Application skeleton

Create the /root/capa-app/ directory and create application.yaml in it. The apiVersion is argoproj.io/v1alpha1, the kind is Application, metadata.name is guestbook, and metadata.namespace is argocd.

An Application is a custom resource in the argoproj.io group. metadata.namespace is where the Application object itself lives, not the deployment target, and it is usually the namespace where Argo CD is installed.

source — what to fetch

In the same file, fill in spec.project as capa-demo, spec.source.repoURL as https://gitea.homelab.internal/platform/guestbook.git, spec.source.targetRevision as main, and spec.source.path as overlays/prod.

Under spec.source go three things: the repository address, the revision, and the path. targetRevision accepts a branch, a tag, or a commit SHA, and in production it is safer to use a fixed name than HEAD.

destination — where to put it

Set spec.destination.server to https://kubernetes.default.svc and spec.destination.namespace to capa-guestbook. Do not use destination.name.

There is a fixed address used when deploying inside the same cluster. server and name are two ways of pointing at the same thing, so you must not use them at the same time.

Automated sync and syncOptions

Set both spec.syncPolicy.automated.prune and spec.syncPolicy.automated.selfHeal to true, and put two items, CreateNamespace=true and PruneLast=true, in spec.syncPolicy.syncOptions.

The two booleans under automated decide, respectively, "should what was deleted from Git also be deleted from the cluster?" and "should values changed by hand be reverted?" syncOptions is an array of strings written in key=value form.

Designing the retry backoff

Set spec.syncPolicy.retry.limit to 5, spec.syncPolicy.retry.backoff.duration to 5s, factor to 2, and maxDuration to 3m.

The backoff starts at duration, grows by a factor each time, and stops at maxDuration. Multiply it out yourself and see whether the required values give 5, 10, 20, 40, and 80 seconds.

Exclude the HPA-managed field from the diff

In the first item of spec.ignoreDifferences, put group: apps, kind: Deployment, and /spec/replicas in jsonPointers, to exclude the field managed by the HPA from the comparison.

ignoreDifferences is an array, and each item narrows the target with group/kind and then points at fields with jsonPointers. A JSON Pointer writes the path with slashes, not dots.

Actually create the target namespace

Actually create the namespace capa-guestbook in the cluster and attach the label app.kubernetes.io/part-of=capa.

From here on it is a real cluster, not files. You can create it with kubectl create namespace and then attach the label, or write a manifest and apply it.

A Deployment with the tracking annotation attached

Actually create the Deployment guestbook-ui in the namespace capa-guestbook. Set replicas to 2, the container image to nginx:1.27, and attach argocd.argoproj.io/tracking-id as the Deployment's own annotation in Argo CD's format. The app name is guestbook.

The tracking ID format is APP_NAME:GROUP/KIND:NAMESPACE/NAME. Note that because this is a Deployment in the apps group, the GROUP slot is not empty.