Skip to content

Deploy apps with GitOps using Argo CD

Deployment

Deploy apps with GitOps using Argo CD

Argo CD is a GitOps controller for Kubernetes. It watches a git repository that holds your Kubernetes manifests and reconciles the cluster to match what the repository declares. You change the repository, and Argo CD applies the change. Someone edits a live resource by hand, and Argo CD reverts it to the committed state.

Stand up Argo CD on a Quake AI Kubernetes cluster from the validated OpenTofu template k8s-cluster. You install Argo CD, connect a git repository that holds a sample app, deploy it with a sync, watch a repository change roll out, and watch Argo CD correct manual drift.

DeveloperGit repositoryKubernetes manifestsKubernetes clusterArgo CDcontrollerSample appDeployment + Service applies + reconcilescommit + pushwatched sourceUI + CLI over tunnel
Click to zoom
Argo CD runs in the cluster, watches a git repository of Kubernetes manifests, and reconciles the running app to match each commit

Monthly cost estimate

Pricing calculator ↗

Sized as a custom package on a mix of shared and dedicated vCPU.

Starting template$238.80/mo

Monthly total for the required template above. Use the configurator below to add optional pieces and see the total update.

What each resource is for

Control plane

m2a.xlarge · 4 dedicated vCPU, 16 GiB RAM, 1 Gbps

$132.00/mo

3× Worker node

s1a.medium · 4 shared vCPU, 4 GiB RAM, 0.5 Gbps

$99.00/mo

Compute shown per role at custom-package rates ($29/dedicated vCPU, $7.25/shared vCPU, $1/GiB RAM). The headline above is the billed total: the cheaper of a named plan and the custom package, plus add-ons.

Included in baseline

m2a.xlarge

4 dedicated vCPU, 16 GiB RAM, 1 Gbps

$132.00

s1a.medium

4 shared vCPU, 4 GiB RAM, 0.5 Gbps

$33.00

s1a.medium

4 shared vCPU, 4 GiB RAM, 0.5 Gbps

$33.00

s1a.medium

4 shared vCPU, 4 GiB RAM, 0.5 Gbps

$33.00

Compute + RAM rate basis

16 vCPU + 28 GiB RAM at $29/dedicated vCPU, $7.25/shared vCPU, $1/GiB RAM (regular). Totals apply the flat −$5/mo package promotion.

—

Block storage (160 GiB)

160 GiB at $0.08/GiB/mo

$12.80

Public IP (included)

1 included with the custom package

$0.00

Package promotional discount

Flat −$5.00/mo on the custom package (same promotion as named plans).

$-5.00

Included at no charge

These line items are zero on Quake AI. Many other providers meter them separately.

Data transfer (inbound and outbound)

Unlimited data transfer on every plan; Quake AI does not meter per-GB egress.

AWS, GCP, and Azure meter outbound transfer per GB. DigitalOcean and Hetzner include an allowance on compute plans, then charge overage.

Learn more
$0.00

Private networking

Private networks, subnets, Neutron routers, and security groups are included with the plan.

VPC objects are usually free to create elsewhere, but NAT gateways bill hourly plus per-GB processed. Quake AI uses router SNAT with no separate NAT line item.

$0.00

Control-plane API requests

OpenStack API calls for provisioning and management are included.

Some managed services on other clouds meter API calls or charge for premium control-plane features.

$0.00

Kubernetes control plane

Magnum clusters run on Nova instances; there is no separate K8s platform fee in Quake AI pricing.

Managed Kubernetes on AWS, GCP, and Azure charges a control-plane fee on top of worker nodes.

Learn more
$0.00

Dev/test vs production

Start on shared CPU for dev/test, then promote to dedicated for production with a flavor resize. The network, storage, and template stay the same.

Dev/test on shared CPU

Burstable s1a flavors; suited to prototyping and low or bursty load.

$139.80/mo

Production on the configured CPU

The headline estimate above; predictable steady-load performance.

$238.80/mo

Saves $99.00/mo while you build on shared CPU.

Shared flavors carry less RAM (m2a.xlarge (16 GiB RAM) -> s1a.medium (4 GiB RAM)). A resize reboots the instance; data on attached volumes persists. Size the dedicated flavor for the RAM your production workload needs.

Pricing data last validated: . For current rates, check quake.ai/pricing.

Prerequisites#

You need:

  • A running Kubernetes cluster on Quake AI from the Kubernetes cluster bootstrap template. The managed Kubernetes path in Deploy your first app on Kubernetes works the same way once you have kubectl access.
  • kubectl configured to reach that cluster. Run kubectl get nodes and confirm every node reports Ready.
  • The Argo CD CLI installed on your workstation.
  • A git repository you can push to (GitHub, GitLab, or a self-hosted forge). The repository can be public for a first sync; Argo CD also connects to private repositories with credentials.

Step 1: Confirm cluster access#

Check that kubectl reaches the cluster and every node is ready before you install anything:

bash
kubectl get nodes

Every node should report Ready. If the command times out or returns an authentication error, fix cluster access before continuing.

Step 2: Install Argo CD#

Create the argocd namespace and apply the upstream install manifest:

bash
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

Wait for the API server deployment to roll out:

bash
kubectl -n argocd rollout status deploy/argocd-server --timeout=300s

The command returns deployment "argocd-server" successfully rolled out once Argo CD is running. Confirm the pods:

bash
kubectl -n argocd get pods

Each pod should report Running.

Step 3: Reach the Argo CD UI and read the admin password#

Argo CD installs without a public endpoint. Forward its API port to your workstation:

bash
kubectl -n argocd port-forward svc/argocd-server 8080:443

Leave that command running and open a second terminal. Read the initial admin password from the secret Argo CD generated at install:

bash
kubectl -n argocd get secret argocd-initial-admin-secret \
  -o jsonpath="{.data.password}" | base64 -d; echo

With the port-forward open, visit https://localhost:8080 in your browser. The certificate is self-signed, so accept the browser warning. Log in with the username admin and the password you read above.

Step 4: Log in with the CLI#

With the port-forward from step 3 still running, log in from the Argo CD CLI:

bash
argocd login localhost:8080 --username admin --insecure

Enter the admin password when prompted. The --insecure flag accepts the self-signed certificate served over the port-forward. Confirm the connection:

bash
argocd version

Step 5: Prepare a git repository of manifests#

Argo CD deploys what your git repository declares. You can author manifests by hand, or render them from a quake.yaml manifest using the reference GitOps renderer in consumers/gitops/.

Option A: Render from quake.yaml#

If your app already carries a quake.yaml launch manifest, generate Kubernetes manifests and commit them instead of writing each resource by hand:

bash
# Produce a handoff packet from your manifest (MCP prepare_launch, or export from CI)
python3 consumers/gitops/quake_yaml_k8s_renderer.py \
  --packet handoff.json \
  --out-dir manifests \
  --environments production \
  --repo-url https://github.com/YOUR_USER/YOUR_REPO \
  --image ghcr.io/YOUR_USER/web:main

The renderer writes a production/ directory (Deployment, Service, Ingress when domain is set, optional in-cluster Postgres/Redis, and Secret stubs for names only). It also writes argocd/application-production.yaml you can apply or adapt. Populate app-secrets and datastore auth Secrets out of band before the first sync; the renderer never writes secret values into git. See consumers/gitops/README.md in the platform repository for the full mapping table and unmapped-service behavior.

Commit the output and push:

bash
git add manifests/
git commit -m "Add rendered web app manifests"
git push

Skip to step 6 and set path: production (or path: manifests/production if you nested the output).

Option B: Hand-written sample app#

Create a manifests directory in your repository with a small app.

manifests/deployment.yaml:

YAML
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: web
          image: nginx:1.27-alpine
          ports:
            - containerPort: 80

manifests/service.yaml:

YAML
apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  selector:
    app: web
  ports:
    - port: 80
      targetPort: 80

Commit both files and push:

bash
git add manifests/
git commit -m "Add web app manifests"
git push

Step 6: Create an Argo CD Application#

An Application resource tells Argo CD which repository to watch, which path in it to apply, and where to deploy. Create application.yaml on your workstation and set repoURL to your repository:

YAML
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: web
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/YOUR_USER/YOUR_REPO
    targetRevision: main
    path: manifests
  destination:
    server: https://kubernetes.default.svc
    namespace: web
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true

Apply the Application to the cluster:

bash
kubectl apply -f application.yaml

automated turns on continuous reconciliation: prune removes resources you delete from the repository, and selfHeal reverts manual changes to live resources. CreateNamespace=true creates the web namespace on the first sync.

Step 7: Sync and verify the deployment#

With automated set, Argo CD syncs on its own within a few minutes. Trigger it immediately instead of waiting:

bash
argocd app sync web

Check that the Application reports healthy and synced:

bash
argocd app get web

Look for Sync Status: Synced and Health Status: Healthy. Confirm the workload directly:

bash
kubectl -n web get deployment web
kubectl -n web get pods

You should see two web pods in Running state.

Step 8: Roll out a change from git#

Change the running app by changing the repository. Edit manifests/deployment.yaml and set replicas: 3, then commit and push:

bash
git commit -am "Scale web to 3 replicas"
git push

Argo CD detects the new commit on its next poll (every 3 minutes by default) and reconciles. To apply it at once, sync again:

bash
argocd app sync web
kubectl -n web get pods

A third web pod starts. The repository is the source of truth: the cluster now runs what main declares.

Step 9: Watch Argo CD correct drift#

Because selfHeal is on, Argo CD reverts changes made directly against the cluster. Scale the deployment by hand to create drift:

bash
kubectl -n web scale deployment/web --replicas=10
kubectl -n web get pods --watch

Argo CD compares the live state to the repository, finds 10 replicas where the manifest declares 3, and scales the deployment back to 3 within seconds. Press Ctrl+C to stop watching once the pod count settles. The committed state wins over the manual edit.

What you built#

  • Installed Argo CD into its own namespace from the upstream manifest
  • Reached the Argo CD UI and CLI over a port-forward without exposing a public endpoint
  • Connected a git repository of Kubernetes manifests as the deployment source
  • Created an Application with automated sync, pruning, and self-heal
  • Rolled out a change by committing to the repository
  • Watched Argo CD correct drift by reverting a manual edit to the committed state

Operating this deployment#

You own Argo CD and the cluster it runs on. Plan for the operational work:

  • Upgrades. Track Argo CD releases and reapply the pinned manifest version on your own schedule. Read the upgrade notes before a major version jump.
  • Access control. Replace the local admin account with single sign-on and define RBAC roles before more than one person uses the instance.
  • Secrets. Keep secret values out of the git repository. Use a secrets controller (for example the External Secrets Operator or sealed secrets) so Argo CD applies references, not plaintext credentials. See How to store application secrets and inject them at runtime.
  • Backups. The Application definitions live in git, but the Argo CD configuration (projects, repositories, RBAC) lives in the cluster. Back up the argocd namespace or manage its configuration as declarative files in git as well.

Next steps#

Clean up#

Remove the Application and Argo CD, then release the cluster. Deleting the Application with the cascade also removes the web namespace it created:

bash
argocd app delete web --cascade
kubectl delete namespace argocd

If you provisioned the cluster only for this deployment, destroy it from the template directory:

bash
tofu destroy

Follow the clean-up steps in Deploy the Kubernetes cluster bootstrap template with OpenTofu for the full teardown, and remove any kubeconfig or SSH key files you no longer need from your workstation.

Quick answers

Was this page helpful?