Argo CD and GitOps on Kubernetes: Install and Deploy Your First App

· 2 min read · Kubernetes Tutorials

GitOps in a few words #

GitOps means that Git is the single source of truth for what runs in a Kubernetes cluster. A controller inside the cluster watches a repository and makes the cluster match it. You deploy by merging a pull request, not by running kubectl apply from a laptop or a pipeline with cluster credentials. You get review, history, easy rollbacks (revert the commit) and automatic correction of manual changes.

Argo CD is the most used GitOps controller, and a CNCF graduated project. Flux is the other popular one.

Infrastructure vs application #

A common division:

  • Terraform or OpenTofu creates the cluster and its base: network, EKS, IAM roles and installs Argo CD itself (Helm provider).
  • Argo CD deploys everything that runs on the cluster from Git.

Install Argo CD #

On any cluster, for example a local K3s:

$ kubectl create namespace argocd
$ kubectl apply -n argocd \
    -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
$ kubectl -n argocd rollout status deploy/argocd-server

Or with Helm:

$ helm repo add argo https://argoproj.github.io/argo-helm
$ helm install argocd argo/argo-cd -n argocd --create-namespace

Get the initial admin password and open the UI:

$ kubectl -n argocd get secret argocd-initial-admin-secret \
    -o jsonpath="{.data.password}" | base64 -d; echo
$ kubectl -n argocd port-forward svc/argocd-server 8080:443

Browse to https://localhost:8080 and sign in as admin. Change the password and delete the initial secret. For production, expose it with an ingress and use SSO.

The repository #

A Git repository with plain manifests (or a Helm chart or Kustomize overlay):

apps/
  hello/
    deployment.yaml
    service.yaml
apps/hello/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello
spec:
  replicas: 2
  selector:
    matchLabels:
      app: hello
  template:
    metadata:
      labels:
        app: hello
    spec:
      containers:
        - name: hello
          image: nginxdemos/hello:latest
          ports:
            - containerPort: 80

The Application resource #

An Application tells Argo CD which repository path to deploy and where:

hello-application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: hello
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/my-org/my-gitops-repo.git
    targetRevision: main
    path: apps/hello
  destination:
    server: https://kubernetes.default.svc
    namespace: hello
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true
$ kubectl apply -f hello-application.yaml
$ kubectl -n argocd get applications
  • automated syncs on every commit. Without it you press Sync in the UI.
  • prune: true deletes resources that you remove from Git.
  • selfHeal: true reverts manual changes in the cluster. This is the drift correction that GitOps adds.

Use a pinned image tag in real projects, not latest.

Helm charts #

ingress-nginx-application.yaml
spec:
  source:
    repoURL: https://kubernetes.github.io/ingress-nginx
    chart: ingress-nginx
    targetRevision: 4.11.3
    helm:
      valuesObject:
        controller:
          replicaCount: 2

App of apps and ApplicationSets #

To manage many applications and clusters, create one root Application that points to a directory of Application manifests ("app of apps"), or use an ApplicationSet that generates Applications from a list, a Git directory structure or a cluster list.

Secrets #

Do not store plain secrets in Git. Use Sealed Secrets, SOPS or the External Secrets Operator with AWS Secrets Manager. See secrets management.

Progressive delivery #

Argo Rollouts adds canary and blue-green deployments, in the same spirit as the Istio traffic splitting patterns.

Summary #

Terraform for the platform, Argo CD for the applications, Git for both. See also the Terraform CI/CD pipeline for the infrastructure side.

#Kubernetes #Helm #Docker