From 89597f83e8e79796c1d99863f1e274164e4616a5 Mon Sep 17 00:00:00 2001 From: LeaYeh Date: Sun, 5 Oct 2025 17:59:12 +0200 Subject: [PATCH 1/8] refactor: Restructure setup script for part3 --- scripts/setup_host.sh | 276 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 241 insertions(+), 35 deletions(-) diff --git a/scripts/setup_host.sh b/scripts/setup_host.sh index 2502582..d54d75c 100755 --- a/scripts/setup_host.sh +++ b/scripts/setup_host.sh @@ -1,41 +1,247 @@ -#!/bin/bash -set -e - -VAGRANT_VERSION="2.4.7" -ARCH="amd64" -DEB_FILE="vagrant_${VAGRANT_VERSION}-1_${ARCH}.deb" -DOWNLOAD_URL="https://releases.hashicorp.com/vagrant/${VAGRANT_VERSION}/${DEB_FILE}" - -echo "Installing dependencies..." -sudo apt update -sudo apt install -y wget curl gnupg lsb-release - -# Remove old version if any -if command -v vagrant >/dev/null; then - echo "Removing existing Vagrant installation..." - sudo apt remove -y vagrant -fi +#!/usr/bin/env bash +set -euo pipefail + +# ========================= +# Config (env or args) +# ========================= +VAGRANT_VERSION="${VAGRANT_VERSION:-2.4.7}" +CLUSTER_NAME="${CLUSTER_NAME:-k3d-cluster}" +ARGOCD_MANIFEST_URL="https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml" + +# ========================= +# Helpers +# ========================= +log() { echo -e "👉 \e[1m$*\e[0m"; } +ok() { echo -e "✅ $*"; } +warn() { echo -e "⚠️ $*"; } +die() { echo -e "❌ $*" >&2; exit 1; } + +DISTRO_CODENAME="$(lsb_release -cs 2>/dev/null || echo bookworm)" +ARCH_DEB="$(dpkg --print-architecture)" +ARCH_UNAME="$(uname -m)" + +case "${ARCH_DEB}" in + amd64) KUBECTL_ARCH="amd64" ;; + arm64) KUBECTL_ARCH="arm64" ;; + *) die "Unsupported arch: ${ARCH_DEB}" ;; +esac + +# default: install all +DO_VAGRANT=1 +DO_PART3=1 +DO_PROVISION=1 + +usage() { + cat </dev/null 2>&1; then + echo "❌ Cannot access Docker Daemon (/var/run/docker.sock)." + echo " Check group and service status, then retry." + exit 1 + fi +} + +# ========================= +# Common base +# ========================= +install_base() { + log "Installing base packages..." + sudo apt-get update -y + sudo apt-get install -y ca-certificates curl wget gnupg lsb-release apt-transport-https software-properties-common jq + ok "Base packages installed" +} -# Download and install the .deb file -echo "Downloading Vagrant ${VAGRANT_VERSION}..." -wget -q "${DOWNLOAD_URL}" -O "/tmp/${DEB_FILE}" +# ========================= +# Vagrant (Part1/2) +# ========================= +install_vagrant() { + log "Installing/updating Vagrant ${VAGRANT_VERSION}..." + local DEB_FILE="vagrant_${VAGRANT_VERSION}-1_${ARCH_DEB}.deb" + local URL="https://releases.hashicorp.com/vagrant/${VAGRANT_VERSION}/${DEB_FILE}" -echo "Installing Vagrant..." -sudo dpkg -i "/tmp/${DEB_FILE}" + if command -v vagrant >/dev/null 2>&1; then + warn "Detected existing Vagrant: $(vagrant --version). Attempting to update/overwrite to ${VAGRANT_VERSION}" + sudo apt-get remove -y vagrant || true + fi -# Cleanup -rm "/tmp/${DEB_FILE}" + wget -q "${URL}" -O "/tmp/${DEB_FILE}" || die "Failed to download Vagrant: ${URL}" + sudo dpkg -i "/tmp/${DEB_FILE}" || sudo apt-get -f install -y + rm -f "/tmp/${DEB_FILE}" + ok "Vagrant installed: $(vagrant --version)" +} -# Verify installation -echo "✅ Vagrant installed successfully:" -vagrant --version +install_virtualbox_amd64() { + log "installing VirtualBox (amd64) as Vagrant provider..." + # Oracle keyring + wget -qO- https://www.virtualbox.org/download/oracle_vbox_2016.asc \ + | sudo gpg --dearmor -o /usr/share/keyrings/oracle_vbox_2016.gpg + echo "deb [arch=amd64 signed-by=/usr/share/keyrings/oracle_vbox_2016.gpg] http://download.virtualbox.org/virtualbox/debian ${DISTRO_CODENAME} contrib" \ + | sudo tee /etc/apt/sources.list.d/virtualbox.list >/dev/null + sudo apt-get update -y + sudo apt-get install -y virtualbox-7.1 + ok "VirtualBox installed: $(vboxmanage --version || echo ok)" +} -echo "Installing VirtualBox..." -wget -O- -q https://www.virtualbox.org/download/oracle_vbox_2016.asc | sudo gpg --dearmour -o /usr/share/keyrings/oracle_vbox_2016.gpg -echo "deb [arch=amd64 signed-by=/usr/share/keyrings/oracle_vbox_2016.gpg] http://download.virtualbox.org/virtualbox/debian bookworm contrib" | sudo tee /etc/apt/sources.list.d/virtualbox.list -sudo apt update -sudo apt install virtualbox-7.1 +install_libvirt_arm64() { + log "installing libvirt + QEMU (arm64) as Vagrant provider..." + sudo apt-get update -y + sudo apt-get install -y qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils ebtables dnsmasq-base + sudo systemctl enable --now libvirtd + sudo usermod -aG libvirt,kvm "$USER" || true + # install vagrant-libvirt plugin + vagrant plugin install vagrant-libvirt + ok "libvirt/kvm and vagrant-libvirt plugin installed. (Please re-login for group changes to take effect)" +} + +install_vagrant_with_provider() { + install_vagrant + if [[ "${ARCH_DEB}" == "amd64" ]]; then + install_virtualbox_amd64 + ok "Part1/2: Vagrant + VirtualBox ready." + else + install_libvirt_arm64 + ok "Part1/2: Vagrant + libvirt ready. (VirtualBox not supported on ARM)" + fi +} + +# ========================= +# Part3: Docker + kubectl + k3d +# ========================= +install_docker() { + if command -v docker >/dev/null 2>&1; then + ok "Docker already installed: $(docker --version)" + return + fi + log "Installing Docker (official script)..." + curl -fsSL https://get.docker.com | sh + sudo usermod -aG docker "$USER" || true + newgrp docker + ok "Docker installed." +} + +install_kubectl() { + if command -v kubectl >/dev/null 2>&1; then + ok "kubectl already installed: $(kubectl version --client --output=yaml | grep gitVersion || true)" + return + fi + log "Installing kubectl (stable)..." + tmpdir="$(mktemp -d)" + pushd "$tmpdir" >/dev/null + KVER="$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)" + curl -LO "https://storage.googleapis.com/kubernetes-release/release/${KVER}/bin/linux/${KUBECTL_ARCH}/kubectl" + chmod +x kubectl + sudo mv kubectl /usr/local/bin/ + popd >/dev/null + rm -rf "$tmpdir" + ok "kubectl installed: $(kubectl version --client --short | tr -s ' ')" +} + +install_k3d() { + if command -v k3d >/dev/null 2>&1; then + ok "k3d already installed: $(k3d version | head -n1)" + return + fi + log "Installing k3d..." + curl -s https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash + ok "k3d installed: $(k3d version | head -n1)" +} + +create_k3d_cluster() { + if k3d cluster list | grep -q "^${CLUSTER_NAME}\b"; then + ok "k3d cluster ${CLUSTER_NAME} already exists, skipping creation." + return + fi + log "Creating k3d cluster: ${CLUSTER_NAME} ..." + k3d cluster create "${CLUSTER_NAME}" --wait + ok "k3d cluster created." +} + +bootstrap_argocd() { + log "Creating namespaces (argocd, dev)..." + kubectl create ns argocd --dry-run=client -o yaml | kubectl apply -f - + kubectl create ns dev --dry-run=client -o yaml | kubectl apply -f - + ok "Namespaces created." + + log "Installing Argo CD (inside cluster)..." + kubectl apply -n argocd -f "${ARGOCD_MANIFEST_URL}" + log "Waiting for argocd-server Ready (up to 5 minutes)..." + kubectl rollout status deploy/argocd-server -n argocd --timeout=300s || true + + ok "Argo CD installed." +} + +part3_stack() { + install_docker + install_kubectl + install_k3d + if [[ "${DO_PROVISION}" -eq 1 ]]; then + ensure_docker_ready + create_k3d_cluster + bootstrap_argocd + else + warn "--no-provision: Only installing tools, skipping cluster creation/Argo CD installation." + fi +} + +# ========================= +# Run +# ========================= +install_base + +if [[ "${DO_VAGRANT}" -eq 1 ]]; then + install_vagrant_with_provider +else + warn "Skipping Vagrant installation (--part3-only)" +fi + +if [[ "${DO_PART3}" -eq 1 ]]; then + part3_stack +else + warn "Skipping Part3 (Docker/k3d/kubectl) installation (--vagrant-only)" +fi -# Verify VirtualBox installation -echo "✅ VirtualBox installed successfully:" -virtualbox --help | head -n 1 +ok "All done 🎉" +warn "If you just added docker/libvirt/kvm groups, please re-login for the changes to take effect." From c6e1d501b1f064e80a393de35f67c30a08891517 Mon Sep 17 00:00:00 2001 From: LeaYeh Date: Sun, 5 Oct 2025 19:39:57 +0200 Subject: [PATCH 2/8] chore: Move boostrap argocd out of the setup host vm script --- scripts/setup_host.sh | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/scripts/setup_host.sh b/scripts/setup_host.sh index d54d75c..f6c0381 100755 --- a/scripts/setup_host.sh +++ b/scripts/setup_host.sh @@ -199,20 +199,6 @@ create_k3d_cluster() { ok "k3d cluster created." } -bootstrap_argocd() { - log "Creating namespaces (argocd, dev)..." - kubectl create ns argocd --dry-run=client -o yaml | kubectl apply -f - - kubectl create ns dev --dry-run=client -o yaml | kubectl apply -f - - ok "Namespaces created." - - log "Installing Argo CD (inside cluster)..." - kubectl apply -n argocd -f "${ARGOCD_MANIFEST_URL}" - log "Waiting for argocd-server Ready (up to 5 minutes)..." - kubectl rollout status deploy/argocd-server -n argocd --timeout=300s || true - - ok "Argo CD installed." -} - part3_stack() { install_docker install_kubectl @@ -220,7 +206,6 @@ part3_stack() { if [[ "${DO_PROVISION}" -eq 1 ]]; then ensure_docker_ready create_k3d_cluster - bootstrap_argocd else warn "--no-provision: Only installing tools, skipping cluster creation/Argo CD installation." fi From 353fbc1defd2912d9af72f47c9bfddc97e395bc8 Mon Sep 17 00:00:00 2001 From: LeaYeh Date: Sun, 12 Oct 2025 17:28:03 +0200 Subject: [PATCH 3/8] feat: Setup admin and apply application config --- p3/tools/bootstrap_argocd.sh | 49 ++++++++++++++++++++++++++++++++++++ scripts/setup_host.sh | 1 - 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100755 p3/tools/bootstrap_argocd.sh diff --git a/p3/tools/bootstrap_argocd.sh b/p3/tools/bootstrap_argocd.sh new file mode 100755 index 0000000..c91f043 --- /dev/null +++ b/p3/tools/bootstrap_argocd.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash +set -euo pipefail + +# ========================= +# Helpers +# ========================= +log() { echo -e "👉 \e[1m$*\e[0m"; } +ok() { echo -e "✅ $*"; } +warn() { echo -e "⚠️ $*"; } +die() { echo -e "❌ $*" >&2; exit 1; } + + +ARGOCD_INSTALL_URL=${ARGOCD_INSTALL_URL:-"https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml"} + +# ========================= +# Argo CD +# ========================= +bootstrap_argocd() { + log "Creating namespaces (argocd, dev)..." + kubectl create ns argocd --dry-run=client -o yaml | kubectl apply -f - + kubectl create ns dev --dry-run=client -o yaml | kubectl apply -f - + ok "Namespaces created." + + log "Installing Argo CD (inside cluster)..." + kubectl apply -n argocd -f "${ARGOCD_INSTALL_URL}" + log "Waiting for argocd-server Ready (up to 5 minutes)..." + kubectl rollout status deploy/argocd-server -n argocd --timeout=300s || true + + ok "Argo CD installed." + + log "Retrieving initial admin password..." + ARGOCD_ADMIN_PASSWORD=$(kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d) + ok "Initial admin password: ${ARGOCD_ADMIN_PASSWORD}" + log "port-forwarding argocd-server to http://localhost:8080 ..." + kubectl port-forward -n argocd svc/argocd-server 8080:443 >/dev/null 2>&1 & + sleep 3 + ok "Argo CD UI: https://localhost:8080 (username: admin, password: ${ARGOCD_ADMIN_PASSWORD})" + + log "Applying Argo CD Application (dev/playground)..." + kubectl apply -f p3/manifests/argocd/application-dev.yaml + ok "Argo CD Application(dev/playground) applied." + +} + +# ========================= +# Main +# ========================= +bootstrap_argocd +ok "Bootstrap completed." diff --git a/scripts/setup_host.sh b/scripts/setup_host.sh index f6c0381..d99e84a 100755 --- a/scripts/setup_host.sh +++ b/scripts/setup_host.sh @@ -6,7 +6,6 @@ set -euo pipefail # ========================= VAGRANT_VERSION="${VAGRANT_VERSION:-2.4.7}" CLUSTER_NAME="${CLUSTER_NAME:-k3d-cluster}" -ARGOCD_MANIFEST_URL="https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml" # ========================= # Helpers From ff4ec44e63e8f195732ad4639baae133c3c22298 Mon Sep 17 00:00:00 2001 From: LeaYeh Date: Sun, 12 Oct 2025 17:28:30 +0200 Subject: [PATCH 4/8] feat: Config kustomize for argocd and app --- p3/manifests/argocd/application-dev.yaml | 18 ++++++++++++++++++ p3/manifests/dev/deployment.yaml | 21 +++++++++++++++++++++ p3/manifests/dev/kustomization.yaml | 8 ++++++++ p3/manifests/dev/service.yaml | 13 +++++++++++++ 4 files changed, 60 insertions(+) create mode 100644 p3/manifests/argocd/application-dev.yaml create mode 100644 p3/manifests/dev/deployment.yaml create mode 100644 p3/manifests/dev/kustomization.yaml create mode 100644 p3/manifests/dev/service.yaml diff --git a/p3/manifests/argocd/application-dev.yaml b/p3/manifests/argocd/application-dev.yaml new file mode 100644 index 0000000..e3f31a7 --- /dev/null +++ b/p3/manifests/argocd/application-dev.yaml @@ -0,0 +1,18 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: p3-dev + namespace: argocd +spec: + project: default + source: + repoURL: https://github.com/42-CC-RNCP/Inception-of-Things.git + targetRevision: lea/p3 + path: p3/manifests/dev + destination: + server: https://kubernetes.default.svc + namespace: dev + syncPolicy: + automated: + prune: true + selfHeal: true diff --git a/p3/manifests/dev/deployment.yaml b/p3/manifests/dev/deployment.yaml new file mode 100644 index 0000000..0b7cd61 --- /dev/null +++ b/p3/manifests/dev/deployment.yaml @@ -0,0 +1,21 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: playground + namespace: dev +spec: + replicas: 1 + selector: + matchLabels: + app: playground + template: + metadata: + labels: + app: playground + spec: + containers: + - name: app + image: wil42/playground:v1 + ports: + - containerPort: 8888 + imagePullPolicy: IfNotPresent diff --git a/p3/manifests/dev/kustomization.yaml b/p3/manifests/dev/kustomization.yaml new file mode 100644 index 0000000..481acde --- /dev/null +++ b/p3/manifests/dev/kustomization.yaml @@ -0,0 +1,8 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - deployment.yaml + - service.yaml +images: + - name: wil42/playground + newTag: v1 diff --git a/p3/manifests/dev/service.yaml b/p3/manifests/dev/service.yaml new file mode 100644 index 0000000..b2e3b2b --- /dev/null +++ b/p3/manifests/dev/service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: playground-svc + namespace: dev +spec: + selector: + app: playground + ports: + - port: 8888 + targetPort: 8888 + protocol: TCP + type: ClusterIP From 04613c1adc7096d2d1a98ca7f5742cbc3241b636 Mon Sep 17 00:00:00 2001 From: LeaYeh Date: Sun, 12 Oct 2025 17:39:44 +0200 Subject: [PATCH 5/8] build: Add port forwarding for app --- p3/tools/bootstrap_argocd.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/p3/tools/bootstrap_argocd.sh b/p3/tools/bootstrap_argocd.sh index c91f043..d520058 100755 --- a/p3/tools/bootstrap_argocd.sh +++ b/p3/tools/bootstrap_argocd.sh @@ -40,6 +40,10 @@ bootstrap_argocd() { kubectl apply -f p3/manifests/argocd/application-dev.yaml ok "Argo CD Application(dev/playground) applied." + log "port-forwarding playground service to http://localhost:8888 ..." + kubectl port-forward -n dev svc/playground-svc 8888:8888 >/dev/null 2>&1 & + sleep 3 + ok "Playground app: http://localhost:8888" } # ========================= From ac0ef8b4ec557c133170230c4bdc1c08510551a5 Mon Sep 17 00:00:00 2001 From: LeaYeh Date: Sun, 12 Oct 2025 18:17:07 +0200 Subject: [PATCH 6/8] build: Change the service type to loadbalancer --- p3/manifests/dev/service.yaml | 2 +- p3/tools/bootstrap_argocd.sh | 147 ++++++++++++++++++++++++++++++---- 2 files changed, 131 insertions(+), 18 deletions(-) diff --git a/p3/manifests/dev/service.yaml b/p3/manifests/dev/service.yaml index b2e3b2b..6b17c01 100644 --- a/p3/manifests/dev/service.yaml +++ b/p3/manifests/dev/service.yaml @@ -10,4 +10,4 @@ spec: - port: 8888 targetPort: 8888 protocol: TCP - type: ClusterIP + type: LoadBalancer diff --git a/p3/tools/bootstrap_argocd.sh b/p3/tools/bootstrap_argocd.sh index d520058..beb850f 100755 --- a/p3/tools/bootstrap_argocd.sh +++ b/p3/tools/bootstrap_argocd.sh @@ -9,9 +9,90 @@ ok() { echo -e "✅ $*"; } warn() { echo -e "⚠️ $*"; } die() { echo -e "❌ $*" >&2; exit 1; } - +# ========================= +# Config +# ========================= +CLUSTER_NAME="${CLUSTER_NAME:-mycluster}" ARGOCD_INSTALL_URL=${ARGOCD_INSTALL_URL:-"https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml"} +# host → k3d serverlb 端口對應 +# 8080 對應叢集 LB 的 8443(我們會把 argocd-server Service 開 8443 指到 Pod 的 443) +ARGOCD_HOST_PORT="${ARGOCD_HOST_PORT:-8080}" # maps to cluster LB :8443 +APP_HOST_PORT="${APP_HOST_PORT:-8888}" # maps to cluster LB :8888 + +# ========================= +# Pre-flight +# ========================= +need() { command -v "$1" >/dev/null 2>&1 || die "Missing command: $1"; } + +ensure_docker_ready() { + need docker + if ! systemctl is-active --quiet docker; then + log "Starting Docker service..." + sudo systemctl enable --now docker + fi + if ! id -nG "$USER" | grep -qw docker; then + die "Current user is not in the 'docker' group. Run: sudo usermod -aG docker $USER && re-login (or run 'newgrp docker')." + fi + docker ps >/dev/null 2>&1 || die "Cannot connect to Docker daemon. Check /var/run/docker.sock permissions." +} + +ensure_k3d_cluster_with_ports() { + need k3d + if k3d cluster list | awk 'NR>1 {print $1}' | grep -qx "${CLUSTER_NAME}"; then + warn "Detected existing k3d cluster: ${CLUSTER_NAME}" + local lb_name="k3d-${CLUSTER_NAME}-serverlb" + local lb_id; lb_id=$(docker ps -q -f "name=^/${lb_name}$" || true) + if [[ -z "${lb_id}" ]]; then + warn "Server LB container '${lb_name}' not found; possibly old k3d or custom setup." + else + local ports; ports=$(docker port "${lb_id}" || true) + echo "${ports}" + if ! grep -q "${ARGOCD_HOST_PORT}.*->" <<<"${ports}" || ! grep -q "${APP_HOST_PORT}.*->" <<<"${ports}"; then + warn "Existing cluster lacks required host port mappings:" + warn " Need host ${ARGOCD_HOST_PORT} → LB:8443 and host ${APP_HOST_PORT} → LB:8888" + warn "Consider recreating the cluster:" + warn " k3d cluster delete ${CLUSTER_NAME} && \\" + warn " k3d cluster create ${CLUSTER_NAME} --wait \\" + warn " --port \"${ARGOCD_HOST_PORT}:8443@loadbalancer\" \\" + warn " --port \"${APP_HOST_PORT}:8888@loadbalancer\"" + else + ok "Existing cluster has required host port mappings." + fi + fi + return + fi + + log "Creating k3d cluster '${CLUSTER_NAME}' with host port mappings..." + k3d cluster create "${CLUSTER_NAME}" --wait \ + --port "${ARGOCD_HOST_PORT}:8443@loadbalancer" \ + --port "${APP_HOST_PORT}:8888@loadbalancer" + ok "k3d cluster created." +} + +# ========================= +# Waiters (ServiceLB: svclb-*) +# ========================= +wait_svclb_ready() { + local ns="$1"; local svc="$2"; local timeout="${3:-300}" + log "Waiting for ServiceLB helper pod 'svclb-${svc}-*' in namespace '${ns}' (timeout ${timeout}s)..." + local end=$((SECONDS+timeout)) + while (( SECONDS <= end )); do + local lines + lines="$(kubectl -n "${ns}" get pods --no-headers 2>/dev/null | awk '/^svclb-'"${svc}"'-/ {print $1, $2, $3}')" + if [[ -n "${lines}" ]]; then + local notready + notready="$(awk '$2!="1/1" || $3!="Running" {print $0}' <<<"${lines}" || true)" + if [[ -z "${notready}" ]]; then + ok "ServiceLB helper for '${svc}' is Running." + return 0 + fi + fi + sleep 3 + done + die "ServiceLB helper for '${svc}' not ready within ${timeout}s" +} + # ========================= # Argo CD # ========================= @@ -19,35 +100,67 @@ bootstrap_argocd() { log "Creating namespaces (argocd, dev)..." kubectl create ns argocd --dry-run=client -o yaml | kubectl apply -f - kubectl create ns dev --dry-run=client -o yaml | kubectl apply -f - - ok "Namespaces created." + ok "Namespaces ready." - log "Installing Argo CD (inside cluster)..." + log "Installing Argo CD (in-cluster)..." kubectl apply -n argocd -f "${ARGOCD_INSTALL_URL}" - log "Waiting for argocd-server Ready (up to 5 minutes)..." + + log "Waiting for argocd-server to be ready (up to 5 minutes)..." kubectl rollout status deploy/argocd-server -n argocd --timeout=300s || true - ok "Argo CD installed." + # Make argocd-server Service type=LoadBalancer and add port 8443 + log "Exposing argocd-server as LoadBalancer and adding 8443 port..." + kubectl -n argocd patch svc argocd-server -p '{"spec":{"type":"LoadBalancer"}}' >/dev/null + kubectl -n argocd patch svc argocd-server --type merge -p '{ + "spec": { + "ports": [ + {"name":"http","port":80,"targetPort":8080}, + {"name":"https","port":443,"targetPort":443}, + {"name":"https-alt","port":8443,"targetPort":443} + ] + } + }' >/dev/null - log "Retrieving initial admin password..." + # wait svclb_ready or it will get connection refused + wait_svclb_ready argocd argocd-server 300 + + log "Retrieving Argo CD initial admin password..." ARGOCD_ADMIN_PASSWORD=$(kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d) - ok "Initial admin password: ${ARGOCD_ADMIN_PASSWORD}" - log "port-forwarding argocd-server to http://localhost:8080 ..." - kubectl port-forward -n argocd svc/argocd-server 8080:443 >/dev/null 2>&1 & - sleep 3 - ok "Argo CD UI: https://localhost:8080 (username: admin, password: ${ARGOCD_ADMIN_PASSWORD})" + ok "Argo CD UI: https://localhost:${ARGOCD_HOST_PORT} (user: admin, password: ${ARGOCD_ADMIN_PASSWORD})" + # apply Application log "Applying Argo CD Application (dev/playground)..." kubectl apply -f p3/manifests/argocd/application-dev.yaml - ok "Argo CD Application(dev/playground) applied." + ok "Application applied." + + if kubectl -n dev get deploy playground >/dev/null 2>&1; then + log "Waiting for Deployment 'playground' Available..." + kubectl -n dev wait --for=condition=available deploy/playground --timeout=300s || true + else + warn "Deployment 'playground' not found yet; will continue and rely on Argo CD sync." + fi + + log "Waiting for Service 'playground-svc' to be created by Argo CD..." + local end=$((SECONDS+300)) + until kubectl -n dev get svc playground-svc >/dev/null 2>&1; do + if (( SECONDS > end )); then die "Service 'playground-svc' not created within 300s"; fi + sleep 3 + done + + # Make playground-svc type=LoadBalancer should be defined in manifest + kubectl -n dev patch svc playground-svc -p '{"spec":{"type":"LoadBalancer"}}' >/dev/null || true + + # wait svclb_ready or it will get connection refused + wait_svclb_ready dev playground-svc 300 - log "port-forwarding playground service to http://localhost:8888 ..." - kubectl port-forward -n dev svc/playground-svc 8888:8888 >/dev/null 2>&1 & - sleep 3 - ok "Playground app: http://localhost:8888" + ok "Playground app: http://localhost:${APP_HOST_PORT}" } # ========================= # Main # ========================= +need kubectl +ensure_docker_ready +ensure_k3d_cluster_with_ports bootstrap_argocd -ok "Bootstrap completed." +ok "All done 🎉 Open: https://localhost:${ARGOCD_HOST_PORT} and http://localhost:${APP_HOST_PORT}" From 8476190adefecfaa2579ca1c1a7b966b5d292056 Mon Sep 17 00:00:00 2001 From: LeaYeh Date: Sun, 12 Oct 2025 20:05:12 +0200 Subject: [PATCH 7/8] build: Add makefile to simplfy the cmd --- p3/Makefile | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 p3/Makefile diff --git a/p3/Makefile b/p3/Makefile new file mode 100644 index 0000000..242020c --- /dev/null +++ b/p3/Makefile @@ -0,0 +1,31 @@ +SHELL := /bin/bash + +CLUSTER_NAME ?= mycluster +ARGOCD_HOST_PORT ?= 8080 +APP_HOST_PORT ?= 8888 +BOOTSTRAP_SCRIPT ?= tools/bootstrap_argocd.sh + +KUBECTL ?= kubectl +K3D ?= k3d + +.PHONY: all clean fclean re + +all: + @echo "==> Running bootstrap with CLUSTER_NAME=$(CLUSTER_NAME) ARGOCD_HOST_PORT=$(ARGOCD_HOST_PORT) APP_HOST_PORT=$(APP_HOST_PORT)" + @CLUSTER_NAME="$(CLUSTER_NAME)" ARGOCD_HOST_PORT="$(ARGOCD_HOST_PORT)" APP_HOST_PORT="$(APP_HOST_PORT)" "$(BOOTSTRAP_SCRIPT)" + +## Remove app + Argo CD namespaces (cluster remains) +clean: + @echo "==> Deleting Argo CD Application (if any) and namespaces (argocd, dev)" + -@$(KUBECTL) -n argocd delete application p3-dev 2>/dev/null || true + -@$(KUBECTL) delete ns dev argocd 2>/dev/null || true + @echo "==> Clean done (cluster '$(CLUSTER_NAME)' still present)" + +## Full clean: clean + delete k3d cluster +fclean: clean + @echo "==> Deleting k3d cluster '$(CLUSTER_NAME)'" + -@$(K3D) cluster delete "$(CLUSTER_NAME)" 2>/dev/null || true + @echo "==> Full clean done" + +## Rebuild from scratch +re: fclean all From 5600cdd4c42fca9c197cda89ee0ce62d00b36a19 Mon Sep 17 00:00:00 2001 From: LeaYeh Date: Sun, 12 Oct 2025 20:17:36 +0200 Subject: [PATCH 8/8] fix: Change app name --- p3/manifests/dev/deployment.yaml | 6 +++--- p3/manifests/dev/service.yaml | 2 +- p3/tools/bootstrap_argocd.sh | 26 +++++++------------------- 3 files changed, 11 insertions(+), 23 deletions(-) diff --git a/p3/manifests/dev/deployment.yaml b/p3/manifests/dev/deployment.yaml index 0b7cd61..b43f0e7 100644 --- a/p3/manifests/dev/deployment.yaml +++ b/p3/manifests/dev/deployment.yaml @@ -1,17 +1,17 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: playground + name: wil-playground namespace: dev spec: replicas: 1 selector: matchLabels: - app: playground + app: wil-playground template: metadata: labels: - app: playground + app: wil-playground spec: containers: - name: app diff --git a/p3/manifests/dev/service.yaml b/p3/manifests/dev/service.yaml index 6b17c01..9a1a0b0 100644 --- a/p3/manifests/dev/service.yaml +++ b/p3/manifests/dev/service.yaml @@ -5,7 +5,7 @@ metadata: namespace: dev spec: selector: - app: playground + app: wil-playground ports: - port: 8888 targetPort: 8888 diff --git a/p3/tools/bootstrap_argocd.sh b/p3/tools/bootstrap_argocd.sh index beb850f..ba872c7 100755 --- a/p3/tools/bootstrap_argocd.sh +++ b/p3/tools/bootstrap_argocd.sh @@ -14,11 +14,9 @@ die() { echo -e "❌ $*" >&2; exit 1; } # ========================= CLUSTER_NAME="${CLUSTER_NAME:-mycluster}" ARGOCD_INSTALL_URL=${ARGOCD_INSTALL_URL:-"https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml"} - -# host → k3d serverlb 端口對應 -# 8080 對應叢集 LB 的 8443(我們會把 argocd-server Service 開 8443 指到 Pod 的 443) ARGOCD_HOST_PORT="${ARGOCD_HOST_PORT:-8080}" # maps to cluster LB :8443 APP_HOST_PORT="${APP_HOST_PORT:-8888}" # maps to cluster LB :8888 +ARGOCD_MANIFESTS_DIR="${ARGOCD_MANIFESTS_DIR:-manifests/argocd}" # ========================= # Pre-flight @@ -113,16 +111,16 @@ bootstrap_argocd() { kubectl -n argocd patch svc argocd-server -p '{"spec":{"type":"LoadBalancer"}}' >/dev/null kubectl -n argocd patch svc argocd-server --type merge -p '{ "spec": { + "type": "LoadBalancer", "ports": [ - {"name":"http","port":80,"targetPort":8080}, - {"name":"https","port":443,"targetPort":443}, - {"name":"https-alt","port":8443,"targetPort":443} + {"name":"https-alt","port":8443,"targetPort":8080} ] } }' >/dev/null + # wait svclb_ready or it will get connection refused - wait_svclb_ready argocd argocd-server 300 + wait_svclb_ready kube-system argocd-server 300 log "Retrieving Argo CD initial admin password..." ARGOCD_ADMIN_PASSWORD=$(kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d) @@ -130,7 +128,7 @@ bootstrap_argocd() { # apply Application log "Applying Argo CD Application (dev/playground)..." - kubectl apply -f p3/manifests/argocd/application-dev.yaml + kubectl apply -f "${ARGOCD_MANIFESTS_DIR}/application-dev.yaml" ok "Application applied." if kubectl -n dev get deploy playground >/dev/null 2>&1; then @@ -140,18 +138,8 @@ bootstrap_argocd() { warn "Deployment 'playground' not found yet; will continue and rely on Argo CD sync." fi - log "Waiting for Service 'playground-svc' to be created by Argo CD..." - local end=$((SECONDS+300)) - until kubectl -n dev get svc playground-svc >/dev/null 2>&1; do - if (( SECONDS > end )); then die "Service 'playground-svc' not created within 300s"; fi - sleep 3 - done - - # Make playground-svc type=LoadBalancer should be defined in manifest - kubectl -n dev patch svc playground-svc -p '{"spec":{"type":"LoadBalancer"}}' >/dev/null || true - # wait svclb_ready or it will get connection refused - wait_svclb_ready dev playground-svc 300 + wait_svclb_ready kube-system playground-svc 300 ok "Playground app: http://localhost:${APP_HOST_PORT}" }