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