Build a GitOps Pipeline with ArgoCD
Deploy apps to Kubernetes automatically by pushing changes to Git.
Introduction
30 Second Summary
Every time someone deploys software by running commands manually, things can go wrong. They might deploy the wrong version, target the wrong environment, or skip a step entirely.
In this project, you will build a GitOps deployment pipeline using ArgoCD on a local Kubernetes cluster. Instead of running manual deployment commands, you'll push changes to Git and watch them deploy automatically.
What You'll Build
A complete GitOps deployment pipeline running locally on your machine, with ArgoCD watching a GitHub repository and automatically deploying changes to a Kubernetes cluster.
By the end of this project, you'll have:
- A local Kubernetes cluster running via kind, with ArgoCD installed and accessible through its web UI.
- A GitHub repository serving as the single source of truth for your application's desired state.
- A working GitOps feedback loop where pushing a manifest change to Git triggers ArgoCD to update your cluster automatically.
- Secret Mission: Enable automated sync with self-healing so ArgoCD reverts any manual cluster changes back to match Git.
Are there any prerequisites?
You should be familiar with Git and basic terminal commands. You'll also need a basic understanding of what containers are. No Kubernetes experience is required.
Install kind and the ArgoCD CLI
Before you can create a local Kubernetes cluster and deploy applications through Git, you need two command-line tools installed on your machine.
In this step, you'll install kind (which creates local Kubernetes clusters inside Docker containers) and the ArgoCD CLI (which lets you manage ArgoCD from your terminal).
In this step, get ready to:
- Install kind for creating local Kubernetes clusters.
- Install the ArgoCD CLI for managing GitOps deployments.
- Verify Docker is running and ready to host your cluster.
Install kind
kind stands for "Kubernetes IN Docker." It creates a fully functional Kubernetes cluster using Docker containers as nodes, so you don't need a cloud account or a virtual machine.
- Check if kind is already installed by running this command in your terminal:
kind version
✔️ I see a version number
You're all set. kind is already installed and ready to go.
ⓧ Command not found
- Install kind using Homebrew by running:
brew install kind
- Confirm the installation succeeded by running:
kind version
You should see a version number printed (e.g. v0.31.0).
Seeing 'brew: command not found'?
This means Homebrew itself is not installed. Visit brew.sh and follow the installation instructions, then retry the brew install kind command.
help me install Homebrew so I can install kind
Install the ArgoCD CLI
The ArgoCD CLI lets you create applications, trigger syncs, and check deployment status directly from the terminal.
- Check if the ArgoCD CLI is already installed by running:
argocd version --client
✔️ I see a version number
The ArgoCD CLI is ready. You can move on to the next substep.
ⓧ Command not found
- Install the ArgoCD CLI using Homebrew by running:
brew install argocd
- Confirm the installation succeeded by running:
argocd version --client
You should see version information printed to the terminal.
Install hanging or failing?
The ArgoCD formula compiles from source if no pre-built bottle is available for your system. This can take a few minutes. If it fails entirely, make sure Homebrew is up to date by running brew update first, then retry.
help me troubleshoot my ArgoCD CLI installation
Verify Docker is running
kind uses Docker under the hood to create cluster nodes. Docker needs to be actively running (not just installed) before you can create a cluster in the next step.
- Confirm Docker is running by running this command:
docker info
You should see a wall of system information about your Docker installation. The key line to look for is Server Version near the top of the output.
Seeing 'Cannot connect to the Docker daemon'?
This means Docker Desktop is installed but not currently running. Open Docker Desktop and wait for it to fully start (you'll see the whale icon in your menu bar become steady), then run docker info again.
help me get Docker running on my machine
Your toolbox is ready. Next up, you'll use kind to spin up a local Kubernetes cluster where ArgoCD will live.
Create a Local Kubernetes Cluster
Your tools are installed and ready to go. Now it's time to create the environment where your GitOps pipeline will live.
In this step, you'll spin up a local Kubernetes cluster using kind. kind runs Kubernetes nodes as Docker containers on your machine, so no cloud account or remote server is needed.
In this step, get ready to:
- Create a local Kubernetes cluster using kind.
- Verify the cluster is running and the node is healthy.
Create your kind cluster
A kind cluster is a fully functional Kubernetes cluster running inside Docker containers. Creating one takes a single command and gives you the same Kubernetes API that production clusters use.
- Create a local Kubernetes cluster named argocd-demo by running this command:
kind create cluster --name argocd-demo --wait 60s
What does this command do?
- kind create cluster downloads a pre-built Kubernetes node image and starts it as a Docker container.
- --name argocd-demo names your cluster so you can reference it later with kubectl.
- --wait 60s tells kind to wait up to 60 seconds for the control plane to be ready before returning.
This takes 30-60 seconds depending on your machine. You should see output ending with:
Set kubectl context to "kind-argocd-demo"
- Confirm the cluster is running by checking its connection info:
kubectl cluster-info --context kind-argocd-demo
You should see output showing the Kubernetes control plane address and CoreDNS running at a local URL.
Cluster creation failed?
- Make sure Docker is running. Run docker info to confirm Docker is accessible.
- If you see a timeout error, your machine may be under heavy load. Try running the command again.
- If you see a permission error, make sure your user has access to Docker without sudo.
Help me troubleshoot why my kind cluster failed to create.
Confirm your node is ready
A Kubernetes cluster is made up of nodes. Your kind cluster has one node that acts as both the control plane and a worker.
- Check that your cluster's node is healthy by running:
kubectl get nodes
You should see one node listed with the status Ready.
What should I see?
The output looks something like this:
NAME STATUS ROLES AGE VERSION
argocd-demo-control-plane Ready control-plane 45s v1.35.0
The key thing is the Ready status. This means your node is healthy and can accept workloads.
Node showing NotReady?
- Wait 30 seconds and run kubectl get nodes again. The node may still be initializing.
- If it stays NotReady for more than 2 minutes, delete the cluster with kind delete cluster --name argocd-demo and recreate it.
My node is stuck in NotReady status after creating the kind cluster.
Your cluster is running and ready for workloads. Next up, you'll install ArgoCD on this cluster and access its web UI.
Install ArgoCD on Your Cluster
Your cluster is running, but it has nothing on it yet. A bare Kubernetes cluster is just empty infrastructure waiting for workloads.
In this step, you'll install ArgoCD on your cluster. ArgoCD is the GitOps controller that watches your Git repository and deploys changes automatically. Once it's running, you'll access its web UI to see your deployments in real time.
In this step, get ready to:
- Install ArgoCD v3.4.2 onto your local Kubernetes cluster.
- Verify all ArgoCD pods are running and healthy.
- Access the ArgoCD web UI and log in as admin.
Create the ArgoCD namespace and install ArgoCD
Kubernetes uses namespaces to isolate groups of resources. ArgoCD runs in its own dedicated namespace so its components stay separate from your application workloads.
- Create the argocd namespace and install ArgoCD from the official manifests by running these commands:
kubectl create namespace argocd
kubectl apply -n argocd --server-side --force-conflicts -f https://raw.githubusercontent.com/argoproj/argo-cd/v3.4.2/manifests/install.yaml
What do these commands do?
- kubectl create namespace argocd creates a new namespace called argocd to house all ArgoCD components.
- kubectl apply downloads and installs the official ArgoCD manifest file. This creates all the deployments, services, and roles ArgoCD needs.
- The --server-side --force-conflicts flags are required for ArgoCD v3.3+ installations to handle resource ownership correctly.
You should see a long list of resources being created (namespaces, service accounts, roles, deployments, and more). This is normal.
Seeing a connection error?
- Make sure Docker is still running. The kubectl apply command needs network access to download the manifest from GitHub.
- Confirm your cluster is still active by running kubectl cluster-info --context kind-argocd-demo. If the cluster isn't responding, Docker may have restarted.
Help me troubleshoot my ArgoCD installation on kind.
Wait for ArgoCD to be ready
The install command kicks off many pods. It takes a moment for them to download their container images and start up.
- Wait for the ArgoCD server to become available by running:
kubectl wait --for=condition=available --timeout=120s deployment/argocd-server -n argocd
What does this command do?
kubectl wait pauses your terminal until the specified condition is met. Here, it watches the argocd-server deployment and waits until it reports available status. The --timeout=120s flag gives it up to 2 minutes before giving up.
Once the command completes, you should see a message confirming the deployment condition was met.
- Confirm all ArgoCD pods are running by running:
kubectl get pods -n argocd
You should see several pods (including argocd-server, argocd-repo-server, and argocd-application-controller) all showing Running status.
Pods stuck in Pending or CrashLoopBackOff?
- If pods are Pending, your machine may not have enough resources allocated to Docker. Open Docker Desktop settings and increase the memory to at least 4 GB.
- If the kubectl wait command timed out, run it again. Some machines take longer on the first pull of container images.
Help me fix ArgoCD pods that aren't starting on my kind cluster.
Access the ArgoCD web UI
ArgoCD runs inside the cluster, so you can't access its UI directly from your browser. You'll use port-forwarding to create a tunnel from your machine to the ArgoCD server.
- Start port-forwarding to the ArgoCD server by running:
kubectl port-forward svc/argocd-server -n argocd 8080:443
What does this command do?
This forwards traffic from localhost:8080 on your machine to port 443 on the argocd-server service inside the cluster. ArgoCD serves its UI over HTTPS on port 443 internally.
This command keeps running and blocks your terminal. You'll need a new terminal window for the next commands.
- Open a new terminal window or tab. Press Cmd+T (macOS) or Ctrl+Shift+T (Windows/Linux) to open a new tab in your terminal.
- Retrieve the initial admin password by running:
argocd admin initial-password -n argocd
What does this command do?
When ArgoCD is installed, it generates a random admin password and stores it as a Kubernetes secret. This command reads that secret and prints the password for you. Copy the password that appears in the output.
- Open your web browser and navigate to https://localhost:8080.
Seeing a security warning?
Your browser will show a security warning because ArgoCD uses a self-signed certificate. This is expected for a local setup.
In Chrome, click Advanced then Proceed to localhost (unsafe). In Firefox, click Advanced then Accept the Risk and Continue.
- On the ArgoCD login page, enter admin in the Username field.
- Paste the password you copied earlier into the Password field.
- Click SIGN IN.
You should see the ArgoCD dashboard. It will be empty for now because you haven't connected any applications yet.
Can't reach localhost:8080?
- Check that your port-forward command is still running in the other terminal tab. If it stopped, run it again.
- Make sure nothing else is using port 8080 on your machine. If something is, stop the port-forward with Ctrl+C and try a different local port (e.g., kubectl port-forward svc/argocd-server -n argocd 9090:443, then visit https://localhost:9090).
Help me access the ArgoCD UI through port-forwarding.
ArgoCD is installed and you're logged into the dashboard. Next, you'll create a GitHub repository with Kubernetes manifests that ArgoCD will watch and deploy from.
Create Your GitOps Repository
Your ArgoCD controller is running and ready to watch a Git repository for changes. Now you need to give it something to watch.
In the GitOps model, a Git repository is the single source of truth for what should be running in your cluster. You declare your desired state as Kubernetes manifests, push them to a repo, and ArgoCD handles the rest. In this step, you will create that repository and populate it with your first set of manifests.
In this step, get ready to:
- Create a public GitHub repository for your Kubernetes manifests.
- Write a Deployment manifest and a Service manifest for an nginx application.
- Commit and push the manifests to your main branch.
Create and clone your GitHub repository
ArgoCD needs a remote Git repository to pull manifests from. You will create a public repo on GitHub so ArgoCD can access it without any authentication setup.
- Open a new terminal tab or window. Your port-forward from the previous step is still running in the other terminal, so leave that one alone.
- Go to https://github.com/new in your browser to create a new repository.
- Enter argocd-demo-app as the repository name.
- Select Public for the repository visibility.
- Do NOT check any of the initialization boxes (no README, no .gitignore, no license). You will push content from your local machine.
- Click Create repository.
Why a public repo?
A public repository lets ArgoCD clone your manifests without needing SSH keys or deploy tokens. This keeps the project focused on GitOps concepts instead of authentication configuration.
- Move to your Desktop by running this command:
cd ~/Desktop
- Clone the empty repository by running this command:
git clone https://github.com/[[GITHUB_USERNAME="your-github-username"]]/argocd-demo-app.git
- Move into the cloned repository by running:
cd argocd-demo-app
- Confirm you are inside the repo by running:
ls -la
You should see a .git directory listed. This confirms you are inside a valid Git repository.
Seeing 'repository not found'?
Double-check that you typed your GitHub username correctly in the clone URL. The repository must also be set to Public.
If Git asks for authentication, make sure you have a GitHub credential helper or personal access token configured.
Help me troubleshoot cloning my GitHub repository.
Create the Kubernetes Deployment manifest
A Deployment tells Kubernetes how many copies of your application to run and what container image to use. This is the manifest ArgoCD will read to create your nginx pods.
- Create a file called deployment.yaml inside your argocd-demo-app folder by running:
touch deployment.yaml
- Open deployment.yaml in your preferred text editor and paste in the following content:
# Kubernetes Deployment manifest for nginx
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
# Start with 1 replica - we'll scale this up later via Git
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
What does this manifest do?
- apiVersion: apps/v1 and kind: Deployment tell Kubernetes this is a Deployment resource.
- replicas: 1 means Kubernetes will run one copy of the nginx container. You will change this to 3 later through a Git commit to demonstrate the GitOps loop.
- image: nginx:1.27 pins the container to a specific stable version, following the platform engineering best practice of never using latest.
- The selector and template labels (app: nginx) connect the Deployment to the pods it manages.
- Save deployment.yaml.
- Confirm the file exists by running:
ls
You should see deployment.yaml listed in the output.
File not showing up?
Make sure you saved the file inside the argocd-demo-app folder, not in a parent directory. Run pwd to check your current location.
Help me find where my deployment.yaml file was saved.
Create the Kubernetes Service manifest
A Service provides a stable network endpoint for your pods. Without it, other applications in the cluster would have no consistent way to reach your nginx containers.
- Create a file called service.yaml by running:
touch service.yaml
- Open service.yaml in your text editor and paste in the following content:
# Kubernetes Service manifest - exposes nginx on port 80
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
# Matches pods with the app: nginx label from the Deployment
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
# ClusterIP means only accessible within the cluster
type: ClusterIP
What does this Service do?
- selector: app: nginx routes traffic to any pod with the matching label from your Deployment.
- port: 80 is the port other services in the cluster use to reach nginx. targetPort: 80 is the port inside the container.
- type: ClusterIP makes this Service accessible only within the cluster. This is the most common type for internal services.
- Save service.yaml.
- Confirm both files exist by running:
ls
You should see both deployment.yaml and service.yaml listed.
✔️ Awesome, I've got everything!
Great. Make sure both files are saved before moving on to the next substep.
ⓧ I'd like to double check the full code
Here is the full content of both files for comparison.
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
Commit and push the manifests to GitHub
Your manifests are ready locally. Now you need to push them to GitHub so ArgoCD can see them.
- Stage both files for commit by running:
git add .
- Commit the files with a descriptive message by running:
git commit -m "Add nginx deployment and service manifests"
- Push the commit to GitHub by running:
git push origin main
- Verify the push succeeded by visiting your repository at https://github.com/your-github-username/argocd-demo-app in your browser.
You should see deployment.yaml and service.yaml listed in the repository on the main branch.
Push rejected or branch not found?
If Git says the branch main does not exist, your local default branch may be called master. Rename it by running git branch -M main and then push again.
If you are prompted for credentials, use a personal access token as your password. GitHub no longer accepts account passwords for Git operations.
Help me push my manifests to GitHub.
Your Git repository is now the single source of truth for what should run in your cluster. Next up, you will connect ArgoCD to this repo so it can start deploying your manifests automatically.
Connect ArgoCD to Your Repository
You have ArgoCD running on your cluster and a GitHub repository with your desired state manifests. Right now, these two pieces are completely disconnected.
In this step, you'll bridge the gap by creating an ArgoCD Application resource. This is the core GitOps primitive that tells ArgoCD which repo to watch, which path to read manifests from, and which cluster to deploy them to.
In this step, get ready to:
- Log into ArgoCD from the command line.
- Create an ArgoCD Application that points to your GitHub repo.
- Sync the application and verify nginx is running on your cluster.
Log in to ArgoCD via the CLI
While you're already logged into the ArgoCD web UI, the CLI needs its own authentication session to create and manage applications.
Why a separate terminal tab?
Your port-forward command from the previous step is still running in one terminal tab. It needs to stay active so the CLI can reach ArgoCD at localhost:8080. You'll run all the commands in this step in a new terminal tab.
- Open a new terminal tab by pressing Cmd+T (macOS) or Ctrl+Shift+T (Windows/Linux).
- Log in to ArgoCD by running this command, replacing your-admin-password-here with the password you retrieved in the previous step:
argocd login localhost:8080 --username admin --password your-admin-password-here --insecure
What does this command do?
This command authenticates your CLI session with the ArgoCD server running on your local port-forward.
- localhost:8080 is where the port-forward is exposing the ArgoCD server.
- --username admin uses the default admin account.
- --insecure skips TLS certificate verification. This is fine for local development since we're using a self-signed certificate.
You should see a message confirming the login was successful and that the context was updated.
Login hanging or failing?
- Make sure the port-forward from the previous step is still running in your other terminal tab. If it stopped, restart it with kubectl port-forward svc/argocd-server -n argocd 8080:443.
- Double-check your password. You can retrieve it again by running argocd admin initial-password -n argocd.
- If the command hangs indefinitely, try adding the --skip-test-tls flag to bypass TLS testing.
Why can't I log in to ArgoCD from the CLI?
Create an ArgoCD Application
An Application in ArgoCD is the resource that connects a Git repository to a deployment target. It defines what to deploy, where to find it, and where to put it.
- Create the ArgoCD Application pointing to your GitHub repo by running this command:
argocd app create demo-app \
--repo https://github.com/[[GITHUB_USERNAME="your-github-username"]]/argocd-demo-app.git \
--path . \
--dest-server https://kubernetes.default.svc \
--dest-namespace default
What does each flag mean?
- demo-app is the name ArgoCD uses to track this application.
- --repo points to your GitHub repository containing the Kubernetes manifests.
- --path . tells ArgoCD to look at the root of the repo for manifest files.
- --dest-server https://kubernetes.default.svc targets the local cluster (the one ArgoCD is installed on).
- --dest-namespace default deploys resources into the default namespace.
You should see output confirming the application was created.
Seeing a permission or repository error?
- Make sure your GitHub repository is public. ArgoCD needs to read from the repo without credentials for this setup.
- Check that the repository URL is correct and ends with .git.
- Verify that your manifests (deployment.yaml and service.yaml) are pushed to the main branch.
Why is ArgoCD failing to connect to my repository?
Sync the application and verify deployment
Creating the Application told ArgoCD what to watch. Now you need to trigger the first sync to actually deploy the manifests to your cluster.
- Sync the application by running:
argocd app sync demo-app
What does sync mean?
Syncing tells ArgoCD to make your cluster match what's in Git. ArgoCD reads the manifests from your repo and applies them to the cluster using kubectl apply under the hood.
You should see a table of resources with their sync status and health. Both nginx-deployment and nginx-service should show as Synced.
- Verify the nginx pods are running by running:
kubectl get pods
You should see one pod with a name starting with nginx-deployment- in Running status.
- You can also check your ArgoCD web UI at https://localhost:8080. You should see the demo-app application showing a green Synced and Healthy status.
Pods not showing as Running?
- If the pod status shows ContainerCreating, wait 30 seconds and run kubectl get pods again. The first pull of the nginx image takes a moment.
- If the sync failed, run argocd app get demo-app to see detailed status information about what went wrong.
- If you see ImagePullBackOff, check your internet connection. The cluster needs to pull the nginx:1.27 image from Docker Hub.
Why are my pods not starting after syncing?
Your Git repository and your cluster are now connected through ArgoCD. Next up, you'll experience the full GitOps loop by making a change in Git and watching ArgoCD detect it.
Experience the GitOps Loop
Your ArgoCD Application is synced and healthy, which means your cluster matches what Git says it should be. Now it's time to see the real power of this setup: changing your infrastructure through a Git commit instead of a manual command.
This is the GitOps loop in action. You change a manifest in Git, ArgoCD detects the difference between Git and your cluster, and then it reconciles the cluster to match. No SSH-ing into servers, no running kubectl apply by hand.
In this step, get ready to:
- Push a manifest change to your GitHub repo.
- Watch ArgoCD detect the drift in its web UI.
- Sync the application and verify the new state in your cluster.
Update the replica count in your manifest
Right now your deployment.yaml specifies 1 replica of the nginx pod. You will scale it to 3 replicas by editing the file in Git, the same way a platform engineer would handle a production scaling request.
- In your terminal, make sure you are inside your argocd-demo-app folder.
- Open deployment.yaml in your text editor.
- Find this line near the top of the spec section:
replicas: 1
- Change 1 to 3, so the line now reads:
replicas: 3
- Save deployment.yaml.
✔️ Awesome, I've got everything!
Great. Double check you have saved the file before continuing.
ⓧ I'd like to double check the full code
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.27
ports:
- containerPort: 80
- Commit and push the change to GitHub by running these commands:
git add deployment.yaml
git commit -m "Scale nginx to 3 replicas"
git push origin main
What do these commands do?
- git add deployment.yaml stages your changed file for commit.
- git commit saves a snapshot of the change with a message describing what you did.
- git push origin main sends the commit to your GitHub repository on the main branch.
You should see output confirming the push was successful, ending with a line like main -> main.
Push failed or permission denied?
- Make sure you are inside the argocd-demo-app folder, not a parent directory.
- If you see an authentication error, confirm you are signed in to GitHub in your terminal. Run gh auth status to check.
Need more help? Help me debug my git push failure
Observe the OutOfSync status in ArgoCD
ArgoCD continuously compares the state in your Git repo against the live state in the cluster. Now that Git says 3 replicas but the cluster still has 1, ArgoCD will flag a difference.
- Switch back to the ArgoCD web UI at https://localhost:8080 in your browser.
- Click on the demo-app application tile.
- Wait up to 3 minutes for ArgoCD to poll your repo. The application status will change from Synced to OutOfSync.
What does OutOfSync mean?
OutOfSync means the live state of your application in the cluster does not match the desired state defined in your Git repository. ArgoCD detected that Git now declares 3 replicas, but the cluster still runs 1.
This is the reconciliation loop at work. ArgoCD continuously watches for drift between Git and the cluster, then reports it so you can decide when to sync.
Speed up the detection
If you do not want to wait for the default polling interval, click the Refresh button in the ArgoCD UI to force an immediate check against your repo.
Still showing Synced after 3 minutes?
- Confirm your push went through by checking your repo on GitHub. The deployment.yaml file should show replicas: 3.
- Click the Refresh button in the ArgoCD UI to trigger an immediate repo poll.
- Make sure the port-forward is still active in your terminal. If it dropped, restart it with kubectl port-forward svc/argocd-server -n argocd 8080:443.
Still stuck? Help me figure out why ArgoCD is not detecting my Git change
Sync the application and verify the new pods
ArgoCD detected the drift, but it will not apply the change automatically unless you enable auto-sync. With the default manual sync policy, you decide when to reconcile.
- Sync the application by running this command:
argocd app sync demo-app
What does syncing do?
When you sync, ArgoCD applies the manifests from your Git repo to the cluster. In this case it updates the nginx-deployment to run 3 replicas instead of 1.
This is the final leg of the GitOps loop: Git change detected, diff shown, human approves, cluster updated.
- Verify that 3 nginx pods are now running by running:
kubectl get pods
You should see three pods with names starting with nginx-deployment-, all in Running status.
Seeing fewer than 3 pods?
- Some pods may still be in ContainerCreating status. Wait 10-15 seconds and run kubectl get pods again.
- If the sync command returned an error, check that your port-forward is still active and you are still logged into the ArgoCD CLI.
Need help? Why don't I see 3 running pods after syncing?
- Switch back to the ArgoCD web UI. The demo-app application should now show Synced and Healthy again, with 3 pods visible in the resource tree.
Secret mission
Enable Self-Healing with Automated Sync
Right now, ArgoCD waits for you to manually sync changes. But what if someone bypasses Git and runs kubectl directly against the cluster? In production, that's called drift, and it's dangerous. Enable ArgoCD's self-healing mode to automatically revert any manual change, proving that Git is the one true source of truth.
Clean Up Your Resources
Clean Up Your Resources
Decide whether to keep your resources running, pause them to come back later, or delete them entirely. This project runs entirely locally using Docker containers, so there are no ongoing cloud costs.
Resources you used:
- kind cluster argocd-demo (runs as Docker containers on your machine, uses RAM and CPU).
- GitHub repository argocd-demo-app (stores your Kubernetes manifests on GitHub).
- kind and ArgoCD CLI tools (installed via Homebrew).
Keep everything running
No action needed. Choose this if you're still actively experimenting with ArgoCD and GitOps.
- Your kind cluster stays running until you restart Docker Desktop.
- The port-forward keeps the ArgoCD UI accessible at https://localhost:8080 as long as the terminal session is open.
- ArgoCD continues watching your GitHub repo for changes and auto-syncing.
- The kind CLI and ArgoCD CLI remain installed on your machine via Homebrew.
Pause - I'll come back to this later
Stop Docker Desktop to free up memory and CPU. Your cluster and its state will be restored when Docker starts again.
- Press Ctrl+C in the terminal running the port-forward to stop it.
- Quit Docker Desktop. This stops all containers (including the kind cluster) without deleting them.
- When you reopen Docker Desktop later, the kind cluster starts back up automatically.
- Re-run the port-forward command to access the ArgoCD UI again:
kubectl port-forward svc/argocd-server -n argocd 8080:443
Your GitHub repo and Homebrew-installed tools are unaffected by pausing Docker.
Delete - I don't want to use this again
Remove all project resources and start fresh. This frees all Docker containers and local storage used by the cluster.
- Press Ctrl+C in the terminal running the port-forward to stop it.
- Delete the kind cluster by running:
kind delete cluster --name argocd-demo
- Verify the cluster is gone by running:
kind get clusters
You should see no output, confirming the cluster has been removed.
- Delete the GitHub repository. Go to your argocd-demo-app repository on GitHub, click Settings, scroll down to the Danger Zone section, and click Delete this repository.
- Uninstall the kind and ArgoCD CLI tools by running:
brew uninstall kind
brew uninstall argocd
After these steps, your machine is back to its original state.
That's a Wrap!
That's a Wrap!
Nice work! You just built the delivery layer of a platform engineering stack.
You now understand the mental model that underpins all of platform engineering: declarative desired state + reconciliation. Every tool in the platform stack (Terraform, ArgoCD, Crossplane, Flux) follows this same pattern. You declare what you want, a controller makes it real, and if reality drifts, the controller corrects it.
You've learned how to:
- Set up a local Kubernetes cluster with kind and installed ArgoCD v3.4.2 as your GitOps controller.
- Created a GitHub repository as the single source of truth for deployments and connected ArgoCD to watch it.
- Experienced the full GitOps loop: push a manifest change to Git, ArgoCD detects the drift, and the cluster updates to match.
- Enabled automated sync with self-healing, proving that Git is the true source of truth by automatically reverting manual cluster changes.
Ready to quiz yourself?