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

> Learn what GitOps is and install Argo CD in a Kubernetes cluster to deploy applications automatically from Git, with an Application example, sync policies and Helm.

- Source: https://www.itwonderlab.com/argocd-gitops-kubernetes/
- Published: 2026-06-15
- Updated: 2026-06-15
- Author: Javier Ruiz Jiménez (https://www.javierruizjimenez.com/)
- Site: IT Wonder Lab (https://www.itwonderlab.com/)

---

## GitOps in a few words

**GitOps** means that Git is the single source of truth for what runs in a [Kubernetes](https://www.itwonderlab.com/tutorials/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](https://argo-cd.readthedocs.io/) 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](https://www.itwonderlab.com/terraform-eks/), IAM roles and installs Argo CD itself ([Helm provider](https://www.itwonderlab.com/terraform-helm-provider-kubernetes/)).
- **Argo CD** deploys everything that runs on the cluster from Git.

### Install Argo CD

On any cluster, for example a local [K3s](https://www.itwonderlab.com/install-kubernetes-k3s/):

```shell
$ 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](https://www.itwonderlab.com/install-kubernetes-helm/):

```shell
$ 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:

```shell
$ 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
```

```yaml title="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:

```yaml title="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
```

```shell
$ 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](https://www.itwonderlab.com/terraform-drift/) correction that GitOps adds.

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

### Helm charts

```yaml title="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](https://www.itwonderlab.com/terraform-aws-kms-secrets-manager/). See [secrets management](https://www.itwonderlab.com/terraform-secrets-management/).

### Progressive delivery

Argo Rollouts adds canary and blue-green deployments, in the same spirit as the [Istio traffic splitting](https://www.itwonderlab.com/istio-patterns-traffic-splitting-in-kubernetes-header-based/) patterns.

### Summary

Terraform for the platform, Argo CD for the applications, Git for both. See also the [Terraform CI/CD](https://www.itwonderlab.com/aws-terraform-tutorial-terraform-cicd/) pipeline for the infrastructure side.
