Self-Managed Argo CD — App Of Everything
Argo CD is one of the most popular continuous deployment tools used in Kubernetes. It is very simple to use and quite powerful. Personally, it is the first tool in my mind when I think of Kubernetes GitOps.
Argo CD has an App of Apps pattern for cluster bootstrapping. That allows us to programmatically and automatically create Argo CD apps instead of creating each application manually. The concept is simple; create one Argo CD application looking at some git repo path and place all Argo CD application definition files into there. So that once any application definition file is created on that git repo path, the Argo CD application is also created automatically. Inspiring with that, it can be created or managed by any Kubernetes object even Argo CD itself.
In this article, I will try to explain how we can install Argo CD with the App of Apps pattern in an automated way. I will use Kind to create a local Kubernetes cluster, Github for the repo and Helm to install the initial setup. After you complete the steps, you will have an Argo CD managed by itself, two Argo CD applications that are responsible for creating Argo CD applications and Argo CD projects automatically. Finally, we test it with a sample application.
Before beginning, please note my previous article about Argo CD LDAP configuration and RBAC for LDAP.
Argo CD Ldap Authentication And RBAC Configuration
Argo CD is a declarative ,GitOps continuous delivery tool for Kubernetes. It’s very easy to install and use. So that it…
If you have already have a Kubernetes cluster you can skip first part and continue on second section “Designing Git Repository Hierarchy”
1. Creating Local Kubernetes Cluster
kind is a tool for running local Kubernetes clusters using Docker container “nodes”. To initiate a kind cluster first we need docker installed. If you don’t have running docker, you can follow this link.
Install kind binary.
On Linux:
curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.11.1/kind-linux-amd64
chmod +x ./kind
mv ./kind /some-dir-in-your-PATH/kind
On Mac (homebrew):
brew install kind
On Windows:
curl.exe -Lo kind-windows-amd64.exe https://kind.sigs.k8s.io/dl/v0.11.1/kind-windows-amd64
Move-Item .\kind-windows-amd64.exe c:\some-dir-in-your-PATH\kind.exe
On Windows via Chocolatey (https://chocolatey.org/packages/kind)
choco install kind
Create local Kubernetes Cluster.
$ kind create cluster --name my-cluster
Creating cluster “my-cluster” …
✓ Ensuring node image (kindest/node:v1.21.1) 🖼
✓ Preparing nodes 📦
✓ Writing configuration 📜
✓ Starting control-plane 🕹️
✓ Installing CNI 🔌
✓ Installing StorageClass 💾
Set kubectl context to “kind-my-cluster”
You can now use your cluster with:
kubectl cluster-info — context kind-my-cluster
Thanks for using kind! 😊
Check cluster is running and healthy.
$ kubectl cluster-info — context kind-my-cluster
Kubernetes control plane is running at https://127.0.0.1:50589
KubeDNS is running at https://127.0.0.1:50589/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use ‘kubectl cluster-info dump’.
2. Designing Git Repository Hierarchy
Git repository can be designed in any hierarchy. Usually creating three folders for Argo CD installation, Argo CD Applications and Argo CD Application Projects is pretty enough. I have prepared this repository with given folder structure below.
Repository folder tree:
argocd/
├── argocd-appprojects # stores ArgoCD App Project's yaml files
├── argocd-apps # stores ArgoCD Application's yaml files
├── argocd-install # stores Argo CD installation files
│ ├── argo-cd # argo/argo-cd helm chart
│ └── values-override.yaml # custom values.yaml for argo-cd chart
3. Create App Of Everything Pattern
If we checkout values-override.yaml file, it can be seen that there is three application definition and one app project definition exist. In addition, source git repository is added in “server.config.repositories” section.
Application “argocd” is for management for Argo CD itself. It consists of argo-cd helm chart and custom values files. Application “argocd-apps” is an example of app of apps pattern. It looks “argocd-apps” folder that contains Argo CD application definition files. Whenever a new application yaml created in that folder, argocd-apps application automatically apply this yaml to cluster and so that Argo CD application automatically created. Application “argocd-appprojects” is similar to “argocd-apps”. It is responsible for creating Argo CD Application Projects.
Additional project “argocd” is used in argocd additional applications to provide proper access control.
server:
configEnabled: true
config:
repositories: |
- type: git
url: https://github.com/gokul0815/argocd.git
- name: argo-helm
type: helm
url: https://argoproj.github.io/argo-helm
additionalApplications:
- name: argocd
namespace: argocd
destination:
namespace: argocd
server: https://kubernetes.default.svc
project: argocd
source:
helm:
version: v3
valueFiles:
- values.yaml
- ../values-override.yaml
path: argocd-install/argo-cd
repoURL: https://github.com/gokul0815/argocd.git
targetRevision: HEAD
syncPolicy:
syncOptions:
- CreateNamespace=true
- name: argocd-apps
namespace: argocd
destination:
namespace: argocd
server: https://kubernetes.default.svc
project: argocd
source:
path: argocd-apps
repoURL: https://github.com/gokul0815/argocd.git
targetRevision: HEAD
directory:
recurse: true
jsonnet: {}
syncPolicy:
automated:
selfHeal: true
prune: true
- name: argocd-appprojects
namespace: argocd
destination:
namespace: argocd
server: https://kubernetes.default.svc
project: argocd
source:
path: argocd-appprojects
repoURL: https://github.com/gokul0815/argocd.git
targetRevision: HEAD
directory:
recurse: true
jsonnet: {}
syncPolicy:
automated:
selfHeal: true
prune: true
additionalProjects:
- name: argocd
namespace: argocd
additionalLabels: {}
additionalAnnotations: {}
description: Argocd Project
sourceRepos:
- '*'
destinations:
- namespace: argocd
server: https://kubernetes.default.svc
clusterResourceWhitelist:
- group: '*'
kind: '*'
orphanedResources:
warn: false
With that configuration we have configured our Argo CD installation for both self management and app of apps pattern.
4. Install… Ready !
We are ready to install. Pull the repo and run helm install command.
$ git clone https://github.com/gokul0815/argocd.git
$ cd argocd/argocd-install/
$ helm install argocd ./argo-cd \
--namespace=argocd \
--create-namespace \
-f values-override.yaml
Wait until all pods are running.
$ kubectl -n argocd get podsNAME READY STATUS RESTARTS
argocd-application-controller-bcc4f7584-vsbc7 1/1 Running 0
argocd-dex-server-77f6fc6cfb-v844k 1/1 Running 0
argocd-redis-7966999975-68hm7 1/1 Running 0
argocd-repo-server-6b76b7ff6b-2fgqr 1/1 Running 0
argocd-server-848dbc6cb4-r48qp 1/1 Running 0
Get initial admin password.
$ kubectl -n argocd get secrets argocd-initial-admin-secret \
-o jsonpath='{.data.password}' | base64 -d
Forward argocd-server service port 80 to localhost:8080 using kubectl.
$ kubectl -n argocd port-forward service/argocd-server 8080:80
Browse http://localhost:8080 and login with initial admin password. As you can see three applications we described in our values-override.yaml file is ready. Application “argocd” looks out of sync but don’t worry. It’s a result of using different templating parameter of my local helm binary and Argo CD ‘s hem binary. Simply click “Sync” button and wait until it’s green.
Finally we have self managed Argo CD with app of apps pattern. All configuration and definitions are located at our git repository. It’s enough to push changes to our git repo to configure Argo CD or to create/update an application. If you want you can also enable auto-sync for “argocd” application. But I recommend to keep it manual to have more secure and stable management.
5. Sample Application Demo
In this demo we will create an application project called “sample-project” that can access only to “sample-app” namespace and create an application called “sample-app” in that project.
Let’s start with “sample-project”.
Create a yaml file with below content and place it in application project folder in your git repo. In my case it is “argocd-appprojects” folder.
$ cat << EOF > argocd-appprojects/sample-project.yaml
> apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: sample-project
namespace: argocd
spec:
clusterResourceWhitelist:
- group: '*'
kind: '*'
destinations:
- namespace: sample-app
server: https://kubernetes.default.svc
orphanedResources:
warn: false
sourceRepos:
- '*'
EOF
Push changes to your repository.
$ git add argocd-appprojects/sample-project.yaml
$ git commit -m "Create sample-project"
$ git push
Argo CD checks git repo every three minutes. You can wait a couple of minutes or click “Refresh” button of “argocd-appproject” application. After synchronization you can see “sample-project” is created. It is also possible to check it under Project menu of Setting pane.
Next, “sample-app”.
Create a yaml file with below content and place it in application folder in your git repo. In my case it is “argocd-apps” folder. You can check Argo CD official documentation for all available fields and parameters.
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: sample-app
namespace: argocd
spec:
destination:
namespace: sample-app
server: https://kubernetes.default.svc
project: sample-project
source:
path: sample-app/
repoURL: https://github.com/kurtburak/argocd.git
targetRevision: HEAD
syncPolicy:
syncOptions:
- CreateNamespace=true
automated:
selfHeal: true
prune: true
Push changes to your repository.
$ git add argocd-apps/sample-app.yaml
$ git commit -m "Create application"
$ git push
In several minutes or by clicking the refresh button of “argocd-apps”, you can observe creation of “sample-app” on GUI.
You can also verify with kubectl commands.
$ kubectl -n sample-app get all
NAME READY STATUS AGE
pod/details-v1-79f774bdb9-7sw9q 1/1 Running 112m
pod/productpage-v1-6b746f74dc-vwkdq 1/1 Running 112m
pod/ratings-v1-b6994bb9-rf7lk 1/1 Running 112m
pod/reviews-v1-545db77b95-pzcj9 1/1 Running 112m
pod/reviews-v2-7bf8c9648f-q8b6m 1/1 Running 112m
pod/reviews-v3-84779c7bbc-9nfp4 1/1 Running 112mNAME TYPE CLUSTER-IP PORT(S) AGE
service/details ClusterIP 10.96.27.232 9080/TCP 112m
service/productpage ClusterIP 10.96.72.223 9080/TCP 112m
service/ratings ClusterIP 10.96.0.174 9080/TCP 112m
service/reviews ClusterIP 10.96.115.169 9080/TCP 112mNAME READY UP-TO-DATE AVAILABLE
deployment.apps/details-v1 1/1 1 1
deployment.apps/productpage-v1 1/1 1 1
deployment.apps/ratings-v1 1/1 1 1
deployment.apps/reviews-v1 1/1 1 1
deployment.apps/reviews-v2 1/1 1 1
deployment.apps/reviews-v3 1/1 1 1NAME DESIRED CURRENT READY
replicaset.apps/details-v1-79f774bdb9 1 1 1
replicaset.apps/productpage-v1-6b746f74dc 1 1 1
replicaset.apps/ratings-v1-b6994bb9 1 1 1
replicaset.apps/reviews-v1-545db77b95 1 1 1
replicaset.apps/reviews-v2-7bf8c9648f 1 1 1
replicaset.apps/reviews-v3-84779c7bbc 1 1 1
Everything is running and ready!
6. Cleanup
Remove application and application project definition files in git repo.
$ rm -f argocd-apps/sample-app.yaml
$ rm -f argocd-appprojects/sample-project.yaml
$ git rm argocd-apps/sample-app.yaml
$ git rm argocd-appprojects/sample-project.yaml
$ git commit -m "Remove app and project."
$ git push
Delete application “sample-app”.
Synchronize “argocd-apps” and “argocd-appprojects” with selecting “Prune” option.
Uninstall argo-cd helm deployment.
$ helm uninstall argocd
Wait until all resources are deleted in argocd namespace.
$ kubectl -n argocd get pods
NAME READY STATUS
argocd-application-controller-bcc4f7584-vsbc7 0/1 Terminating
argocd-dex-server-77f6fc6cfb-v844k 0/1 Terminating
argocd-redis-7966999975-68hm7 0/1 Terminating
argocd-repo-server-6b76b7ff6b-2fgqr 0/1 Terminating
argocd-server-848dbc6cb4-r48qp 0/1 Terminating
Delete “argocd” and “sample-app” namespaces.
$ kubectl delete ns argocd
$ kubectl delete ns sample-app
Delete kind cluster.
$ kind delete cluster --name my-cluster
Deleting cluster "my-cluster" ...