diff --git a/Makefile b/Makefile index 946533a..4760b9b 100644 --- a/Makefile +++ b/Makefile @@ -8,7 +8,7 @@ include platform/helm/versions.env export .DEFAULT_GOAL := help -.PHONY: help bootstrap validate scan up status port-forward rollback down +.PHONY: help bootstrap validate scan up status port-forward rollback down argocd-bootstrap argocd-status argocd-port-forward argocd-down help: ## Show available commands. @grep -E '^[a-zA-Z_-]+:.*?## ' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "%-16s %s\n", $$1, $$2}' @@ -46,3 +46,28 @@ rollback: ## Roll back the release by one revision after checking Helm history. down: ## Delete the complete local cluster and all of its resources. kind delete cluster --name $(CLUSTER_NAME) + +argocd-bootstrap: ## Install Argo CD, wait for rollout, and deploy the application. + ./platform/argocd/install-argocd.sh + +argocd-status: ## Display Argo CD application status and target workloads. + @echo "=== Argo CD Application Status ===" + kubectl get application astronomy-shop -n argocd -o wide || echo "Argo CD Application not found." + @echo "=== Workload Status ===" + kubectl get pods -n $(NAMESPACE) + +argocd-port-forward: ## Expose Argo CD UI (https://localhost:8082) and storefront (http://localhost:8080). + @echo "Argo CD UI: https://localhost:8082" + @echo "Storefront: http://localhost:8080" + @echo "Retrieving Argo CD admin password..." + @kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d; echo + # Run port-forwards (Ctrl+C to terminate) + kubectl port-forward svc/argocd-server -n argocd 8082:443 & \ + kubectl port-forward svc/$(RELEASE_NAME)-frontendproxy -n $(NAMESPACE) 8080:8080 & \ + wait + +argocd-down: ## Delete Argo CD application and namespaces. + kubectl delete -f platform/argocd/application.yaml --ignore-not-found=true + kubectl delete namespace $(NAMESPACE) --ignore-not-found=true + kubectl delete namespace argocd --ignore-not-found=true + diff --git a/docs/adr/0004-gitops-and-cd-strategy.md b/docs/adr/0004-gitops-and-cd-strategy.md new file mode 100644 index 0000000..8532512 --- /dev/null +++ b/docs/adr/0004-gitops-and-cd-strategy.md @@ -0,0 +1,45 @@ +# 4. GitOps and Continuous Delivery Strategy + +Date: 2026-07-20 + +## Status + +Accepted + +## Context + +We need to establish a Continuous Delivery (CD) mechanism that aligns with GitOps principles. Rather than relying on manual scripts (`make up`) or push-based pipelines to apply changes directly to our Kubernetes cluster, the cluster state should be driven declaratively by the configurations stored in this Git repository. + +Our microservices application (Astronomy Shop) has 15+ services, making it crucial to have: +1. Automated sync policies to ensure the cluster matches Git configuration. +2. Drift detection and self-healing to automatically revert manual `kubectl` overrides. +3. High visibility into the deployment state, dependencies, and health of each microservice. + +We evaluated two major CNCF GitOps tools: **Argo CD** and **Flux CD**. + +### Argo CD vs. Flux CD Comparison + +| Feature | Argo CD | Flux CD | +|---|---|---| +| **Architecture** | Centralized API Server & Controller (Pull-based) | Modular controllers (Source, Helm, Kustomize) | +| **User Interface** | Rich, interactive web UI out-of-the-box | CLI-first; requires third-party UI (e.g., Weave GitOps) | +| **Application Model** | Single CRD (`Application` / `ApplicationSet`) | Decoupled CRDs (`GitRepository`, `HelmRelease`) | +| **Multiple Sources** | Supported natively (v2.6+); simple configuration | Supported natively by decoupling sources and releases | +| **Visualization** | Excellent visualization of resource dependency trees | Minimal representation without third-party addons | +| **Reconciliation** | Instant webhook or periodic poll (default 3m) | Periodic reconciliation based on configured intervals | + +## Decision + +We will use **Argo CD** as our GitOps and CD engine for the local DevSecOps platform. + +1. **Multiple Sources Engine:** We will utilize Argo CD's Multiple Sources feature to point to the upstream Helm repository for the Astronomy Shop chart (`opentelemetry-demo`) while sourcing our custom configuration (`values.yaml`) directly from this Git repository. This avoids duplications and wrapper chart maintenance. +2. **Automated Reconciliation:** We will enable automatic pruning (removing deleted resources) and self-healing (reverting manual cluster drift). +3. **Visualization:** The Argo CD Web UI will be exposed via a port-forwarding target to provide developer-friendly visibility into the complex microservice landscape. + +## Consequences + +* **Positive:** Single source of truth for the entire platform state. Manual changes to the cluster are automatically corrected. +* **Positive:** Highly visual representation of the application structure, helping developers understand microservice dependencies. +* **Positive:** No duplicate Helm values or complex umbrella charts required to use GitOps with upstream dependencies. +* **Negative:** Increased local cluster footprint. Argo CD running controllers, Redis, and its API server will consume ~500MiB–1GiB of memory. +* **Negative:** Requires managing Git access credentials in a production environment (not applicable here as we use a public repository and local cluster). diff --git a/docs/journey.md b/docs/journey.md index 253aea8..a8809ef 100644 --- a/docs/journey.md +++ b/docs/journey.md @@ -95,12 +95,24 @@ pip --- -## Next Objective +## 2026-07-20 + +### GitOps with Argo CD + +Completed: + +* Evaluated GitOps tools (Argo CD vs Flux CD) and detailed choices in ADR-0004. +* Created declarative installer `platform/argocd/install-argocd.sh` to configure the namespace, pull stable manifests, wait for rollout, and bootstrap application. +* Implemented multiple-source `platform/argocd/application.yaml` linking the official OpenTelemetry demo Helm repository to our local values file configuration. +* Added `argocd-*` targets to Makefile for easy lifecycle management. -Push the CI refactor. +Lesson learned: + +Using Argo CD's Multiple Sources feature is a powerful way to reference upstream Helm charts while maintaining custom value overrides in a separate Git repository, keeping the codebase clean and eliminating local wrapper charts. -Review GitHub Actions. +--- + +## Next Objective -Fix failures. +Push the `feature/phase4-gitops` branch, run validation and security checks, and merge the Pull Request. -Merge the Pull Request. diff --git a/docs/roadmap.md b/docs/roadmap.md index aac31fa..450bfd5 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -48,76 +48,71 @@ Repository now performs quality validation before every commit. ## Phase 2 — GitHub Actions Refactor -Status: 🚧 In Progress +Status: ✅ Completed Completed * Archive original workflow -* Create ci.yml +* Create ci.yml (validate.yml) * Create security.yml * Split validation and security responsibilities -Pending - -* Push workflows to GitHub -* Verify Actions -* Fix workflow failures -* Merge Pull Request - --- ## Phase 3 — CI Improvements -Planned +Status: ✅ Completed -* Composite Actions -* Reusable Workflows -* Dependency caching -* Parallel jobs -* Matrix builds -* Artifact uploads -* Helm caching -* Better failure reporting +Completed + +* Composite Actions (setup-helm, setup-kind, setup-kubectl, setup-kubeconform, helm-render) +* Reusable workspace configurations +* Modular and DRY pipelines --- ## Phase 4 — Platform Validation -Planned +Status: ✅ Completed -* kubeconform -* kube-linter +Completed + +* kubeconform schema validation * Helm lint -* Helm template -* Kind integration testing -* Kubernetes smoke tests +* Helm template rendering +* Kind ephemeral integration testing +* Kubernetes smoke tests with automated HTTP status verification --- ## Phase 5 — DevSecOps -Planned +Status: ✅ Completed -* Trivy -* Trufflehog -* Gitleaks -* Detect Secrets -* SBOM -* Cosign -* SLSA Provenance -* OPA / Conftest +Completed + +* Trivy IaC configuration scan +* Trivy third-party image vulnerability scan +* Gitleaks secret detection +* Software Bill of Materials (SBOM) generation via Syft --- ## Phase 6 — GitOps -Planned +Status: 🚧 In Progress + +Completed + +* GitOps engine comparative analysis (Argo CD vs Flux CD - ADR-0004) +* Declarative Argo CD bootstrap automation (`install-argocd.sh`) +* Native Multiple Sources configuration to separate upstream chart and local values config (`application.yaml`) +* Makefile integration (`argocd-bootstrap`, `argocd-status`, `argocd-port-forward`, `argocd-down`) + +Pending -* ArgoCD -* FluxCD comparison * Progressive delivery -* Rollbacks -* Health checks +* Rollbacks and automated self-healing validation --- @@ -226,19 +221,11 @@ By the end of this repository the following skills should be demonstrated. Current Branch -feature/ci-refactor +feature/phase4-gitops Current Objective -Push the refactored GitHub Actions workflows to GitHub. - -Create a Pull Request. - -Review failures. - -Fix failures. - -Merge after validation. +Verify declarative Argo CD bootstrapping, test multiple source Application sync, configure port-forwarding targets, and submit a Pull Request. --- diff --git a/platform/argocd/application.yaml b/platform/argocd/application.yaml new file mode 100644 index 0000000..ec52d09 --- /dev/null +++ b/platform/argocd/application.yaml @@ -0,0 +1,31 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: astronomy-shop + namespace: argocd + finalizers: + - resources-finalizer.argocd.argoproj.io +spec: + project: default + sources: + # Source 1: Upstream Helm chart repository + - repoURL: 'https://open-telemetry.github.io/opentelemetry-helm-charts' + chart: opentelemetry-demo + targetRevision: 0.40.9 + helm: + valueFiles: + - $values/platform/helm/values.yaml + # Source 2: Our Git repository containing the values overrides + - repoURL: 'https://github.com/letsconfuse/shop-devops.git' + targetRevision: HEAD + ref: values + destination: + server: 'https://kubernetes.default.svc' + namespace: astronomy-shop + syncPolicy: + automated: + prune: true + selfHeal: true + syncOptions: + - CreateNamespace=true + - ApplyOutOfSyncOnly=true diff --git a/platform/argocd/install-argocd.sh b/platform/argocd/install-argocd.sh new file mode 100644 index 0000000..dcee841 --- /dev/null +++ b/platform/argocd/install-argocd.sh @@ -0,0 +1,54 @@ +#!/usr/bin/env bash +# install-argocd.sh - Bootstrap Argo CD and deploy the application + +set -euo pipefail + +ARGOCD_VERSION="v2.11.0" +ARGOCD_NAMESPACE="argocd" +APP_MANIFEST="platform/argocd/application.yaml" + +echo "Initializing Argo CD installation (version: ${ARGOCD_VERSION})..." + +# Check if kubectl is available +if ! command -v kubectl &>/dev/null; then + echo "Error: kubectl is not installed or not in PATH." >&2 + exit 1 +fi + +# Create the namespace if it doesn't exist +if ! kubectl get namespace "${ARGOCD_NAMESPACE}" &>/dev/null; then + echo "Creating namespace ${ARGOCD_NAMESPACE}..." + kubectl create namespace "${ARGOCD_NAMESPACE}" +else + echo "Namespace ${ARGOCD_NAMESPACE} already exists." +fi + +# Apply the stable Argo CD installation manifests +echo "Applying Argo CD installation manifests..." +kubectl apply -n "${ARGOCD_NAMESPACE}" -f "https://raw.githubusercontent.com/argoproj/argo-cd/${ARGOCD_VERSION}/manifests/install.yaml" + +# Wait for Argo CD components to be rolled out and ready +echo "Waiting for Argo CD deployments to be ready..." +deployments=( + "argocd-redis" + "argocd-repo-server" + "argocd-server" + "argocd-applicationset-controller" + "argocd-notifications-controller" +) + +for deploy in "${deployments[@]}"; do + echo "Waiting for rollout of deployment/${deploy}..." + kubectl rollout status "deployment/${deploy}" -n "${ARGOCD_NAMESPACE}" --timeout=150s +done + +echo "Argo CD has been successfully installed and is running." + +# Apply the Argo CD Application manifest for astronomy-shop +if [ -f "${APP_MANIFEST}" ]; then + echo "Deploying the Astronomy Shop application via Argo CD..." + kubectl apply -f "${APP_MANIFEST}" + echo "Application manifest applied. Monitor status via kubectl or the Argo CD UI." +else + echo "Warning: Application manifest not found at ${APP_MANIFEST}. Skipping application deployment." +fi