Argo CD and GitOps on Kubernetes: Install and Deploy Your First App
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
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: 80The Application resource #
An Application tells Argo CD which repository path to deploy and where:
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
automatedsyncs on every commit. Without it you press Sync in the UI.prune: truedeletes resources that you remove from Git.selfHeal: truereverts 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 #
spec:
source:
repoURL: https://kubernetes.github.io/ingress-nginx
chart: ingress-nginx
targetRevision: 4.11.3
helm:
valuesObject:
controller:
replicaCount: 2App 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.