Skip to content

Your repo, your workloads

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 kubectl on Kestrel for the escape-hatch workflow if you need to make temporary mutations.

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.

RepoWho owns itWhat lives there
ubernetes-applicationsRCS platform teamCluster addons, tenant definitions, platform ApplicationSets
Your repoYou (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.

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.yaml

Create one ArgoCD Application per workload in the ArgoCD UI (New App), as shown in Your first deployment — you cannot kubectl apply Application YAML yourself, because Applications live in the argo-cd namespace, where tenants have no direct Kubernetes access. Still commit the Application YAML to your repo as the record of what you created (in the app-of-apps layout it becomes the synced source of truth). 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.

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-applications
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: <your-tenant>-my-service
namespace: argo-cd
spec:
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=true

Replace <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.

The syncPolicy block above is the recommended default for every tenant Application:

FieldValueWhat it does
automated.prunetrueWhen you delete a manifest from Git, ArgoCD deletes the corresponding resource from the cluster. Without this, orphaned resources accumulate.
automated.selfHealtrueWhen someone (or something) changes a resource on the cluster directly, ArgoCD reverts it to match Git on the next sync (within ~30 s of detection; Git is polled every ~3 minutes). Git is the single source of truth.
syncOptionsCreateNamespace=trueArgoCD 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.

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 — with prune: 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 kubectl on Kestrel.

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.

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 priorityClassName for each workload.
  • Keep secrets out of plaintext Git with Sealed Secrets — encrypt them with kubeseal and commit the encrypted SealedSecret instead of a raw Secret.
  • See kubectl on Kestrel for the escape-hatch workflow when you need temporary kubectl mutations alongside GitOps.