Your repo, your workloads
Why GitOps?
Section titled “Why GitOps?”Every workload on Kestrel deploys through ArgoCD. You commit Kubernetes manifests to a Git repository you control, point an ArgoCD Application at that repo, and ArgoCD keeps the cluster in sync with your commits. This is the only supported deployment path.
The alternative — running kubectl apply directly — works at the RBAC level (you have admin inside your tenant namespaces), but any change you make is reverted automatically when ArgoCD’s next sync fires. See running/kubectl for the escape-hatch workflow if you need to make temporary mutations.
The hard boundary
Section titled “The hard boundary”RCS manages platform infrastructure in a repo called ubernetes-applications. You never touch this repo. Your workloads live in your own Git repository — a greenfield repo you create yourself (the path that works today), or, once it ships, a fork of the RCS template.
| Repo | Who owns it | What lives there |
|---|---|---|
ubernetes-applications | RCS platform team | Cluster addons, tenant definitions, platform ApplicationSets |
| Your repo | You (the tenant) | Your workload manifests, your ArgoCD Applications |
If you need something changed in ubernetes-applications (a new tenant namespace, a quota bump, a new addon), open a ticket with RCS.
Repo shape
Section titled “Repo shape”There are two ways to structure your workload repo. The greenfield path is the recommended default — it works today. The template-fork path is a planned convenience that depends on an RCS template repo that has not shipped yet.
Start with a fresh Git repo containing just your manifests:
<your-repo>/└── manifests/ └── my-service/ ├── deployment.yaml ├── service.yaml └── ingress.yamlCreate one ArgoCD Application per workload — either through the ArgoCD UI or by committing Application YAML to your repo and registering it once. For a single workload this is simpler than the app-of-apps root. If you later grow to 3+ workloads, you can restructure into the app-of-apps layout described in the other tab.
Once the RCS template repo ships, forking it will give you an app-of-apps structure out of the box:
<your-fork>/├── root-app.yaml # The one Application you register with ArgoCD├── apps/│ └── children/│ └── demo-nginx.yaml # Child Application — points at manifests/demo-nginx/├── manifests/│ └── demo-nginx/│ ├── deployment.yaml│ ├── service.yaml│ └── ingress.yaml└── README.mdThe root Application (root-app.yaml) watches apps/children/ and auto-syncs every child Application it finds. Each child points at a subdirectory under manifests/. To add a new workload, you would:
- Create a new directory under
manifests/with your Kubernetes YAML. - Create a new child Application YAML under
apps/children/pointing at that directory. - Commit and push. ArgoCD picks up the new child on the next sync.
This is the standard app-of-apps pattern. For 3+ workloads it saves you from registering each one individually in the ArgoCD UI. Until the template ships, you can build this same structure by hand in a greenfield repo.
The canonical Application YAML
Section titled “The canonical Application YAML”Whichever repo shape you pick, each workload needs an ArgoCD Application resource. Here is the recommended shape:
# You own this — commit to your own repo, not ubernetes-applicationsapiVersion: argoproj.io/v1alpha1kind: Applicationmetadata: name: <your-tenant>-my-service namespace: argo-cdspec: project: <your-tenant> # Your tenant's auto-generated AppProject source: repoURL: https://git.computecanada.ca/<your-group>/<your-repo>.git targetRevision: main path: manifests/my-service # Directory containing your k8s manifests destination: server: https://kubernetes.default.svc namespace: <your-tenant>-prod # Must be tenant-prefixed syncPolicy: automated: prune: true selfHeal: true syncOptions: - CreateNamespace=trueReplace <your-tenant> with your RAP group name and <your-group>/<your-repo> with your GitLab project path.
If you completed Your first deployment, the Application you registered there follows this same pattern — the difference is that this page locks the recommended syncPolicy for ongoing workloads.
Recommended sync defaults
Section titled “Recommended sync defaults”The syncPolicy block above is the recommended default for every tenant Application:
| Field | Value | What it does |
|---|---|---|
automated.prune | true | When you delete a manifest from Git, ArgoCD deletes the corresponding resource from the cluster. Without this, orphaned resources accumulate. |
automated.selfHeal | true | When someone (or something) changes a resource on the cluster directly, ArgoCD reverts it to match Git on the next sync (~30 seconds). Git is the single source of truth. |
syncOptions | CreateNamespace=true | ArgoCD auto-creates the destination namespace on the first sync if it doesn’t exist. Without this, the first sync fails with a “namespace not found” error. |
What selfHeal means in practice
Section titled “What selfHeal means in practice”With selfHeal: true, any kubectl mutation to an ArgoCD-managed resource is temporary. ArgoCD polls your Git repo on a default 3-minute interval and reconciles drift within ~30 seconds of detecting it.
This means:
kubectl scale deployment/my-app --replicas=5— replicas revert to whatever your manifest says on the next sync.kubectl edit deployment/my-app— your edits are overwritten.kubectl delete pod/my-app-xyz— Kubernetes recreates the Pod (normal Deployment behavior), and ArgoCD sees no manifest drift.kubectl delete deployment/my-app— withprune: true, ArgoCD recreates the Deployment from Git on the next sync.
This is by design. If you need to make a temporary mutation (debugging, testing a config change), use the pause-mutate-capture workflow in running/kubectl.
What prune means in practice
Section titled “What prune means in practice”With prune: true, deleting a manifest file from your repo tells ArgoCD: “I no longer want this resource.” ArgoCD deletes it from the cluster on the next sync.
Without prune: true, deleted manifests leave orphaned resources running on the cluster indefinitely. You would need to kubectl delete them manually — and if selfHeal is also off, ArgoCD would not interfere. The recommended default avoids this accumulation.
Next steps
Section titled “Next steps”With your repo structure and sync defaults in place:
- Browse Workload recipes for ready-to-use Deployment, Job, and dev-pod templates that follow these conventions.
- Review priority classes to pick the right
priorityClassNamefor each workload. - See
running/kubectlfor the escape-hatch workflow when you need temporarykubectlmutations alongside GitOps.