Platform Engineering Starter Kit Series: GitOps Bootstrap with Argo CD (3)
In Post 1 we set up our workstation and baseline repo, and in Post 2 we scaffolded Terraform modules, bootstrapped a GKE cluster, and added a Makefile for repeatable workflows.
Now we’ll introduce GitOps — the practice of managing infrastructure and application deployments entirely from Git.
By the end of this post, you’ll have:
- Argo CD running in your GKE cluster
- A GitOps “app-of-apps” setup to manage your platform components from Git
0. Starting Point
If you finished Post 2:
git checkout -b post-03-argo-cd-gitopsIf you skipped Post 2, you can start from its branch:
git clone -b post-02-repo-scaffolding-infra https://github.com/JiminByun0101/platform-starter-kit.git
cd platform-starter-kit
git checkout -b post-03-gitops-bootstrapMake sure your GKE dev cluster is running:
make kubeconfig
kubectl get nodesIf you destroyed the cluster after Post 2, run make apply before make kubeconfig.
1. Why GitOps + Argo CD?
Traditional CI/CD pushes code directly into your cluster, often from your pipeline.
With GitOps, the cluster pulls its desired state from Git. Argo CD watches your Git repo and applies changes automatically, ensuring:
- Version-controlled deployments: Rollback to any Git commit
- Cluster state drift detection: See if something changed outside Git
- Self-healing: Argo CD syncs the cluster back to the declared state
In our platform, we’ll:
- Deploy Argo CD via Helm
- Store Argo CD “Application” manifests in
argocd/ - Use an “app-of-apps” pattern so new services can be added by just creating a new manifest in Git
2. Repo Layout Update
We’ll add an argocd/ folder for GitOps manifests and a Helm chart for Argo CD itself:
platform-starter-kit/
├── argocd/
│ ├── apps/ # App-of-apps children
│ │ ├── platform-monitoring.yaml
│ │ └── sample-app.yaml
│ └── root-app.yaml # The root Argo CD app-of-apps
├── helm/
│ └── argocd/ # Helm chart for Argo CD
│ ├── values.yaml
│ └── Chart.yaml3. Create Argo CD Values File
mkdir -p helm/argocd
cat > helm/argocd/values.yaml <<'EOF'
global:
image:
tag: v3.0.12 # Pin Argo CD app version for reproducibility
server:
service:
type: ClusterIP # Avoid external LB cost until Post 4
ingress:
enabled: false
configs:
params:
server.insecure: true # For local/dev use only
EOF4. Install Argo CD via Helm
4.1 Create Namespace
kubectl create namespace argocd4.2 Add Argo CD Helm Repo
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update4.3 Helm Install (Initial)
We’ll keep the config minimal here — later posts will customize authentication, RBAC, and ingress.
helm upgrade --install argocd argo/argo-cd \
--namespace argocd \
--version 8.2.7 \
-f helm/argocd/values.yaml4.4 Verify Installation
Run through these checks to confirm Argo CD is up and running:
4.4.1 Check pods are running
kubectl get pods -n argocdAll pods should be Running (or Completed for init jobs).
4.4.2. Port-forward to access the UI
We set server.insecure: true for dev, so forward port 80:
kubectl -n argocd port-forward svc/argocd-server 8080:80Open https://localhost:8080 and accept the certificate warning.
4.4.3. Get the initial admin password
kubectl -n argocd get secret argocd-initial-admin-secret \
-o jsonpath="{.data.password}" | base64 -d; echoLogin with:
Username: admin
Password: <output above>Once logged in, open the left menu and click Applications — it should be empty. That’s expected; we’ll add it next.
In Argo CD, Applications are definitions telling Argo CD what to deploy (e.g., a Helm chart or Kubernetes manifests) and where to deploy it.
Right after installation, it will be empty because Argo CD isn’t yet linked to any Git repository — we’ll do that by applying our root application in the next step.
5. Define the Root App (App-of-Apps Pattern)
The root application tells Argo CD where to find all your other apps.
It’s the only app you install manually — everything else is managed by Git.
platform-starter-kit/argocd/root-app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: root-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/<your-username>/platform-starter-kit.git
targetRevision: post-03-gitops-bootstrap # Temporary branch for this post
path: argocd/apps
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: trueNote: We set targetRevision to the branch for this post (post-03-gitops-bootstrap) so that Argo CD only syncs what’s ready at this stage of the series. After the series is complete and merged to main, change this to main (or HEAD).
Push the branch now so Argo CD can see it:
git add .
git commit -m "Post 03: Add helm values.yaml for Argo CD and its root app"
git push -u origin post-03-gitops-bootstrapOnce pushed, we can apply it in Step 7 and verify it appears in the Argo CD UI.
You can also view the full code for this post on GitHub: Post 3 branch on GitHub
6. Add a placeholder Child App
We’ll create a dummy application manifest so that the root app has something to display in Argo CD.
This one is for a future platform monitoring stack (Prometheus, Grafana, Loki), which we’ll fully implement with a Helm chart in Post 5.
For now, it’s only here to demonstrate the app-of-apps pattern and avoid errors about a missing argocd/apps path.
platform-starter-kit/argocd/apps/platform-monitoring.yaml
mkdir -p argocd/apps
cat > argocd/apps/platform-monitoring.yaml <<'EOF'
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: platform-monitoring
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/<your-username>/platform-starter-kit.git
targetRevision: post-03-gitops-bootstrap
path: helm/platform-monitoring # will exist in Post 5
destination:
server: https://kubernetes.default.svc
namespace: monitoring
syncPolicy:
automated:
prune: true
selfHeal: true
EOF
git add argocd/apps/platform-monitoring.yaml
git commit -m "Post 03: add placeholder child app"
git push -u origin post-03-gitops-bootstrap7. Bootstrap the GitOps Root App
Once Argo CD is installed:
kubectl apply -f argocd/root-app.yamlArgo CD will see the argocd/apps folder in your repo and deploy all child apps.
Verify in Argo CD UI
- Access the Argo CD UI
kubectl -n argocd port-forward svc/argocd-server 8080:80Open https://localhost:8080, Login with admin and the password from step 4.4.
2. Check Applications page
- You should now see
root-applisted. - Status should be:
- Synced (green check) if it successfully pulled from the repo.
- Healthy (green heart) if all child apps are in a good state. - If you’ve created the placeholder
platform-monitoringapp (Step 6), it will also appear here.
Its status will likely be Unknown because we haven’t created thehelm/platform-monitoringchart yet. This is expected and will be resolved in Post 5.
8. Cost & Cleanup Warning
Argo CD’s footprint is small, but your GKE cluster still incurs costs.
If you’re pausing work:
make destroyNext in the Series
In Post 4, we’ll:
- Secure Argo CD with HTTPS via Ingress + Cert-Manager
- Add SSO authentication
- Organize platform components into separate Argo CD Projects
