feat(ex01): ArgoCD bootstrap — Vagrantfile, helm install, app-of-apps
- Vagrantfile: Ubuntu 24.04, k3s (no traefik/servicelb), Helm, yq, host-only 192.168.56.10, pre-pulls key images - scripts/bootstrap.sh: installs ArgoCD via Helm, applies root app - apps/project.yaml: permissive AppProject for workshop - apps/root.yaml: App-of-Apps watching apps/ directory - apps/argocd.yaml: ArgoCD self-manages via Helm chart 7.7.11 - manifests/argocd/values.yaml: insecure mode, port-forward access
This commit is contained in:
commit
621d2cbcde
7 changed files with 325 additions and 0 deletions
10
.gitignore
vendored
Normal file
10
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
# AI session / planning files — local only, not for participants
|
||||||
|
CLAUDE.md
|
||||||
|
sessions.md
|
||||||
|
roadmap.md
|
||||||
|
|
||||||
|
# Vagrant
|
||||||
|
.vagrant/
|
||||||
|
|
||||||
|
# macOS
|
||||||
|
.DS_Store
|
||||||
126
Vagrantfile
vendored
Normal file
126
Vagrantfile
vendored
Normal file
|
|
@ -0,0 +1,126 @@
|
||||||
|
# -*- mode: ruby -*-
|
||||||
|
# vi: set ft=ruby :
|
||||||
|
|
||||||
|
# ops-demo Vagrantfile
|
||||||
|
# Provisions Ubuntu 24.04 + k3s (no traefik, no servicelb) + Helm + Git
|
||||||
|
# Two network adapters:
|
||||||
|
# Adapter 1: NAT (internet access)
|
||||||
|
# Adapter 2: Host-only 192.168.56.x (MetalLB L2 — reachable from laptop)
|
||||||
|
|
||||||
|
VAGRANTFILE_API_VERSION = "2"
|
||||||
|
|
||||||
|
VM_NAME = "ops-demo"
|
||||||
|
VM_CPUS = 4
|
||||||
|
VM_MEMORY = 8192 # 8 GB — ArgoCD + Tekton need headroom
|
||||||
|
HOST_ONLY_IP = "192.168.56.10"
|
||||||
|
|
||||||
|
# k3s version — pin so the workshop is reproducible
|
||||||
|
K3S_VERSION = "v1.31.4+k3s1"
|
||||||
|
|
||||||
|
$provision = <<-SHELL
|
||||||
|
set -euxo pipefail
|
||||||
|
|
||||||
|
export DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
# ── 1. System packages ─────────────────────────────────────────────────────
|
||||||
|
apt-get update -qq
|
||||||
|
apt-get install -y -qq \
|
||||||
|
curl git jq unzip bash-completion
|
||||||
|
|
||||||
|
# ── 2. k3s ─────────────────────────────────────────────────────────────────
|
||||||
|
# Disable traefik and the built-in service-lb so MetalLB can take over.
|
||||||
|
# Bind to the host-only interface so ArgoCD LB IP is reachable from the host.
|
||||||
|
curl -sfL https://get.k3s.io | \
|
||||||
|
INSTALL_K3S_VERSION="#{K3S_VERSION}" \
|
||||||
|
K3S_KUBECONFIG_MODE="644" \
|
||||||
|
sh -s - server \
|
||||||
|
--disable=traefik \
|
||||||
|
--disable=servicelb \
|
||||||
|
--node-ip=#{HOST_ONLY_IP} \
|
||||||
|
--advertise-address=#{HOST_ONLY_IP}
|
||||||
|
|
||||||
|
# Wait for k3s to be ready
|
||||||
|
until kubectl get nodes 2>/dev/null | grep -q ' Ready'; do
|
||||||
|
echo "Waiting for k3s node to be ready..."
|
||||||
|
sleep 5
|
||||||
|
done
|
||||||
|
echo "k3s is ready."
|
||||||
|
|
||||||
|
# ── 3. kubeconfig for vagrant user ─────────────────────────────────────────
|
||||||
|
mkdir -p /home/vagrant/.kube
|
||||||
|
cp /etc/rancher/k3s/k3s.yaml /home/vagrant/.kube/config
|
||||||
|
# Point server to host-only IP so it works outside the VM too
|
||||||
|
sed -i "s|127.0.0.1|#{HOST_ONLY_IP}|g" /home/vagrant/.kube/config
|
||||||
|
chown -R vagrant:vagrant /home/vagrant/.kube
|
||||||
|
|
||||||
|
# Also export KUBECONFIG in .bashrc
|
||||||
|
echo 'export KUBECONFIG=/home/vagrant/.kube/config' >> /home/vagrant/.bashrc
|
||||||
|
echo 'source <(kubectl completion bash)' >> /home/vagrant/.bashrc
|
||||||
|
echo 'alias k=kubectl' >> /home/vagrant/.bashrc
|
||||||
|
echo 'complete -o default -F __start_kubectl k' >> /home/vagrant/.bashrc
|
||||||
|
|
||||||
|
# ── 4. Helm ────────────────────────────────────────────────────────────────
|
||||||
|
HELM_VERSION="v3.16.4"
|
||||||
|
curl -sSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | \
|
||||||
|
DESIRED_VERSION="${HELM_VERSION}" bash
|
||||||
|
echo 'source <(helm completion bash)' >> /home/vagrant/.bashrc
|
||||||
|
|
||||||
|
# ── 5. yq (used by Tekton bump-image-tag task) ─────────────────────────────
|
||||||
|
YQ_VERSION="v4.44.3"
|
||||||
|
curl -sSL "https://github.com/mikefarah/yq/releases/download/${YQ_VERSION}/yq_linux_amd64" \
|
||||||
|
-o /usr/local/bin/yq
|
||||||
|
chmod +x /usr/local/bin/yq
|
||||||
|
|
||||||
|
# ── 6. Pre-pull key images (offline resilience) ────────────────────────────
|
||||||
|
# k3s uses containerd; pull via ctr
|
||||||
|
export CONTAINERD_ADDRESS=/run/k3s/containerd/containerd.sock
|
||||||
|
export CONTAINERD_NAMESPACE=k8s.io
|
||||||
|
|
||||||
|
images=(
|
||||||
|
"quay.io/argoproj/argocd:v2.13.3"
|
||||||
|
"ghcr.io/stefanprodan/podinfo:6.6.2"
|
||||||
|
"ghcr.io/stefanprodan/podinfo:6.7.0"
|
||||||
|
"quay.io/metallb/controller:v0.14.9"
|
||||||
|
"quay.io/metallb/speaker:v0.14.9"
|
||||||
|
"registry.k8s.io/ingress-nginx/controller:v1.12.0"
|
||||||
|
"gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/controller:v0.65.1"
|
||||||
|
"gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/webhook:v0.65.1"
|
||||||
|
"alpine/git:latest"
|
||||||
|
"mikefarah/yq:4.44.3"
|
||||||
|
)
|
||||||
|
|
||||||
|
for img in "${images[@]}"; do
|
||||||
|
echo "Pre-pulling: ${img}"
|
||||||
|
k3s ctr images pull "${img}" || echo "WARNING: failed to pull ${img} (will retry at runtime)"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "════════════════════════════════════════════════════════"
|
||||||
|
echo " VM provisioned successfully!"
|
||||||
|
echo " SSH: vagrant ssh"
|
||||||
|
echo " Next step: follow docs/vm-setup.md to verify, then"
|
||||||
|
echo " run scripts/bootstrap.sh to install ArgoCD"
|
||||||
|
echo "════════════════════════════════════════════════════════"
|
||||||
|
SHELL
|
||||||
|
|
||||||
|
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
|
||||||
|
config.vm.box = "bento/ubuntu-24.04"
|
||||||
|
config.vm.box_version = "~> 202502" # pin major release; allows patch updates
|
||||||
|
config.vm.hostname = VM_NAME
|
||||||
|
|
||||||
|
# Adapter 2: host-only so MetalLB IPs are reachable from the laptop
|
||||||
|
config.vm.network "private_network", ip: HOST_ONLY_IP
|
||||||
|
|
||||||
|
# Sync the repo into /vagrant (default) — participants work inside the VM
|
||||||
|
config.vm.synced_folder ".", "/vagrant", type: "virtualbox"
|
||||||
|
|
||||||
|
config.vm.provider "virtualbox" do |vb|
|
||||||
|
vb.name = VM_NAME
|
||||||
|
vb.cpus = VM_CPUS
|
||||||
|
vb.memory = VM_MEMORY
|
||||||
|
# Needed for nested networking
|
||||||
|
vb.customize ["modifyvm", :id, "--nicpromisc2", "allow-all"]
|
||||||
|
end
|
||||||
|
|
||||||
|
config.vm.provision "shell", inline: $provision, privileged: true
|
||||||
|
end
|
||||||
36
apps/argocd.yaml
Normal file
36
apps/argocd.yaml
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: argocd
|
||||||
|
namespace: argocd
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: "0"
|
||||||
|
spec:
|
||||||
|
project: workshop
|
||||||
|
source:
|
||||||
|
repoURL: https://argoproj.github.io/argo-helm
|
||||||
|
chart: argo-cd
|
||||||
|
targetRevision: "7.7.11"
|
||||||
|
helm:
|
||||||
|
valueFiles:
|
||||||
|
- $values/manifests/argocd/values.yaml
|
||||||
|
sources:
|
||||||
|
- repoURL: https://argoproj.github.io/argo-helm
|
||||||
|
chart: argo-cd
|
||||||
|
targetRevision: "7.7.11"
|
||||||
|
helm:
|
||||||
|
valueFiles:
|
||||||
|
- $values/manifests/argocd/values.yaml
|
||||||
|
- repoURL: https://github.com/innspire/ops-demo.git
|
||||||
|
targetRevision: HEAD
|
||||||
|
ref: values
|
||||||
|
destination:
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
namespace: argocd
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
|
- ServerSideApply=true
|
||||||
20
apps/project.yaml
Normal file
20
apps/project.yaml
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: AppProject
|
||||||
|
metadata:
|
||||||
|
name: workshop
|
||||||
|
namespace: argocd
|
||||||
|
annotations:
|
||||||
|
argocd.argoproj.io/sync-wave: "-1"
|
||||||
|
spec:
|
||||||
|
description: Permissive project for workshop exercises
|
||||||
|
sourceRepos:
|
||||||
|
- "*"
|
||||||
|
destinations:
|
||||||
|
- namespace: "*"
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
clusterResourceWhitelist:
|
||||||
|
- group: "*"
|
||||||
|
kind: "*"
|
||||||
|
namespaceResourceWhitelist:
|
||||||
|
- group: "*"
|
||||||
|
kind: "*"
|
||||||
20
apps/root.yaml
Normal file
20
apps/root.yaml
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: root
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: workshop
|
||||||
|
source:
|
||||||
|
repoURL: https://github.com/innspire/ops-demo.git
|
||||||
|
targetRevision: HEAD
|
||||||
|
path: apps
|
||||||
|
destination:
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
namespace: argocd
|
||||||
|
syncPolicy:
|
||||||
|
automated:
|
||||||
|
prune: true
|
||||||
|
selfHeal: true
|
||||||
|
syncOptions:
|
||||||
|
- CreateNamespace=true
|
||||||
48
manifests/argocd/values.yaml
Normal file
48
manifests/argocd/values.yaml
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
# ArgoCD Helm values for the workshop
|
||||||
|
# Phase 1: insecure mode + port-forward access only
|
||||||
|
# Phase 3: ingress added (see comment below)
|
||||||
|
|
||||||
|
global:
|
||||||
|
nodeSelector: {}
|
||||||
|
|
||||||
|
server:
|
||||||
|
# Run in insecure mode (no TLS on the server itself).
|
||||||
|
# TLS termination is handled by Ingress-Nginx in Exercise 03.
|
||||||
|
extraArgs:
|
||||||
|
- --insecure
|
||||||
|
|
||||||
|
# ── Exercise 03: uncomment this block after Ingress-Nginx is deployed ──────
|
||||||
|
# ingress:
|
||||||
|
# enabled: true
|
||||||
|
# ingressClassName: nginx
|
||||||
|
# hostname: argocd.192.168.56.200.nip.io
|
||||||
|
# annotations:
|
||||||
|
# nginx.ingress.kubernetes.io/ssl-passthrough: "false"
|
||||||
|
# nginx.ingress.kubernetes.io/backend-protocol: "HTTP"
|
||||||
|
# ──────────────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
configs:
|
||||||
|
params:
|
||||||
|
server.insecure: true
|
||||||
|
|
||||||
|
cm:
|
||||||
|
# Allow the root app to manage itself
|
||||||
|
application.resourceTrackingMethod: annotation
|
||||||
|
|
||||||
|
repoServer:
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 100m
|
||||||
|
memory: 256Mi
|
||||||
|
|
||||||
|
applicationSet:
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
cpu: 50m
|
||||||
|
memory: 128Mi
|
||||||
|
|
||||||
|
notifications:
|
||||||
|
enabled: false
|
||||||
|
|
||||||
|
dex:
|
||||||
|
enabled: false
|
||||||
65
scripts/bootstrap.sh
Executable file
65
scripts/bootstrap.sh
Executable file
|
|
@ -0,0 +1,65 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
# bootstrap.sh — Install ArgoCD via Helm and apply the root App-of-Apps
|
||||||
|
# Run this once inside the VM after `vagrant up`.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# cd /vagrant
|
||||||
|
# ./scripts/bootstrap.sh
|
||||||
|
#
|
||||||
|
# What it does:
|
||||||
|
# 1. Creates the argocd namespace
|
||||||
|
# 2. Installs ArgoCD via Helm using manifests/argocd/values.yaml
|
||||||
|
# 3. Waits for ArgoCD server to be ready
|
||||||
|
# 4. Applies apps/root.yaml (App-of-Apps entry point)
|
||||||
|
# 5. Prints the initial admin password and a port-forward hint
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ARGOCD_NAMESPACE="argocd"
|
||||||
|
ARGOCD_CHART_VERSION="7.7.11" # ArgoCD chart 7.x → ArgoCD v2.13.x
|
||||||
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||||
|
|
||||||
|
echo "══════════════════════════════════════════════"
|
||||||
|
echo " ops-demo Bootstrap"
|
||||||
|
echo "══════════════════════════════════════════════"
|
||||||
|
|
||||||
|
# ── 1. Namespace ──────────────────────────────────────────────────────────────
|
||||||
|
echo "→ Creating namespace: ${ARGOCD_NAMESPACE}"
|
||||||
|
kubectl create namespace "${ARGOCD_NAMESPACE}" --dry-run=client -o yaml | kubectl apply -f -
|
||||||
|
|
||||||
|
# ── 2. Helm install ArgoCD ────────────────────────────────────────────────────
|
||||||
|
echo "→ Adding Argo Helm repo"
|
||||||
|
helm repo add argo https://argoproj.github.io/argo-helm --force-update
|
||||||
|
helm repo update argo
|
||||||
|
|
||||||
|
echo "→ Installing ArgoCD (chart ${ARGOCD_CHART_VERSION})"
|
||||||
|
helm upgrade --install argocd argo/argo-cd \
|
||||||
|
--namespace "${ARGOCD_NAMESPACE}" \
|
||||||
|
--version "${ARGOCD_CHART_VERSION}" \
|
||||||
|
--values "${REPO_ROOT}/manifests/argocd/values.yaml" \
|
||||||
|
--wait \
|
||||||
|
--timeout 5m
|
||||||
|
|
||||||
|
# ── 3. Apply root App-of-Apps ─────────────────────────────────────────────────
|
||||||
|
echo "→ Applying root App-of-Apps"
|
||||||
|
kubectl apply -f "${REPO_ROOT}/apps/project.yaml"
|
||||||
|
kubectl apply -f "${REPO_ROOT}/apps/root.yaml"
|
||||||
|
|
||||||
|
# ── 4. Print admin password ───────────────────────────────────────────────────
|
||||||
|
ARGOCD_PASSWORD=$(kubectl -n "${ARGOCD_NAMESPACE}" get secret argocd-initial-admin-secret \
|
||||||
|
-o jsonpath="{.data.password}" | base64 -d)
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "══════════════════════════════════════════════"
|
||||||
|
echo " Bootstrap complete!"
|
||||||
|
echo ""
|
||||||
|
echo " ArgoCD admin password: ${ARGOCD_PASSWORD}"
|
||||||
|
echo ""
|
||||||
|
echo " To open the ArgoCD UI, run in a new terminal:"
|
||||||
|
echo " kubectl port-forward svc/argocd-server -n argocd 8080:443"
|
||||||
|
echo " Then open: https://localhost:8080"
|
||||||
|
echo " Login: admin / ${ARGOCD_PASSWORD}"
|
||||||
|
echo ""
|
||||||
|
echo " After Exercise 03, ArgoCD will also be reachable at:"
|
||||||
|
echo " https://argocd.192.168.56.200.nip.io"
|
||||||
|
echo "══════════════════════════════════════════════"
|
||||||
Loading…
Add table
Reference in a new issue