Skip to content

Instantly share code, notes, and snippets.

@tnm
Last active November 21, 2025 02:59
Show Gist options
  • Select an option

  • Save tnm/f2cc981d822f86a2828ece6b39d359a4 to your computer and use it in GitHub Desktop.

Select an option

Save tnm/f2cc981d822f86a2828ece6b39d359a4 to your computer and use it in GitHub Desktop.
ArgoCD Load Testing Script - Create realistic applications for load testing and demos

ArgoCD Load Testing Script

A bash script to create realistic ArgoCD applications for load testing and demo purposes.

Quick Start

# Download the script
curl -O https://gist.githubusercontent.com/tnm/f2cc981d822f86a2828ece6b39d359a4/raw/load-test-argocd.sh
chmod +x load-test-argocd.sh

# Create 400 applications
./load-test-argocd.sh 400

What It Creates

  • 4 repositories: ArgoCD examples, Kubernetes examples, Bitnami, NGINX
  • 32 namespaces: 8 teams × 4 environments (team-environment pattern)
  • N applications: Distributed across shared namespaces with realistic labels
  • Realistic distribution: 70% auto-sync, 30% manual sync

Usage

./load-test-argocd.sh [NUM_APPS]

# Examples:
./load-test-argocd.sh           # Create 50 apps (default)
./load-test-argocd.sh 400       # Create 400 apps
./load-test-argocd.sh 1000      # Create 1000 apps

What You Get

Each application includes:

  • Labels: team, service, environment, app-type, load-test=true
  • Teams: platform, product, data, infrastructure, security, payments, growth, mobile
  • Environments: prod, staging, dev, qa
  • Services: api, web, worker, frontend, backend, db, cache, queue, auth, payments, notifications, analytics, search, admin, mobile-api

Filtering Applications

# View all load test apps
kubectl get applications -n argocd -l load-test=true

# Filter by environment
kubectl get applications -n argocd -l load-test=true,environment=prod

# Filter by team
kubectl get applications -n argocd -l load-test=true,team=platform

# Filter by service
kubectl get applications -n argocd -l load-test=true,service=api

Performance

  • Creation speed: ~4 apps/second on typical cluster
  • 400 apps: ~90 seconds
  • 1000 apps: ~4 minutes
  • Batch processing: Creates apps in batches of 50 for optimal performance

Cleanup

Remove all test applications and namespaces:

kubectl delete applications -n argocd -l load-test=true --wait=false
kubectl delete namespaces -l load-test=true --wait=false

Requirements

  • ArgoCD installed in your cluster
  • kubectl configured with cluster access
  • Permissions to create Applications, Namespaces, and Secrets in the argocd namespace

Use Cases

  • Load testing: Test your ArgoCD UI performance with hundreds of applications
  • Demo environments: Showcase ArgoCD with realistic multi-team setups
  • Performance benchmarking: Measure sync times, API latency, etc.
  • Training: Provide realistic environments for learning ArgoCD

Example Output

Load Testing ArgoCD with 400 realistic applications...

Adding test repositories...
  - Added argocd-example-apps
  - Added kubernetes-examples
  - Added Bitnami Helm repo
  - Added NGINX Helm repo

Creating realistic namespaces...
  - Created 32 namespaces (team-environment combinations)

Creating 400 realistic applications...
  Using batch size of 50 for optimal performance
  - Created 50/400 applications... (4 apps/sec)
  - Created 100/400 applications... (4 apps/sec)
  ...
  - Created 400/400 applications... (4 apps/sec)

Load test setup complete in 93 seconds!

SUMMARY:
  - 4 repositories added
  - 32 namespaces created (team-environment combinations)
  - 400 applications created
  - Average: 4 apps/second

Application distribution:
  - guestbook: 80 apps
  - helm-guestbook: 80 apps
  - kustomize-guestbook: 80 apps
  - sock-shop: 80 apps
  - ksonnet-guestbook: 80 apps

Environment distribution:
  - prod: 94 apps
  - staging: 93 apps
  - dev: 93 apps
  - qa: 94 apps

Sync policies:
  - Auto-sync: 280 apps (~70%)
  - Manual sync: 120 apps (~30%)

License

MIT

#!/bin/bash
#
# ArgoCD Load Testing Script
#
# Creates realistic ArgoCD applications for load testing Cased CD Enterprise.
#
# USAGE:
# ./load-test-argocd.sh [NUM_APPS]
#
# EXAMPLES:
# ./load-test-argocd.sh # Create 50 apps (default)
# ./load-test-argocd.sh 1000 # Create 1000 apps
#
# WHAT IT CREATES:
# - 4 repositories (ArgoCD examples, Kubernetes examples, Bitnami, NGINX)
# - 32 namespaces (8 teams × 4 environments: team-environment pattern)
# - N applications distributed across shared namespaces
# - Realistic labels: team, service, environment, app-type
# - 70% auto-sync, 30% manual sync (realistic distribution)
#
# CLEANUP:
# kubectl delete applications -n argocd -l load-test=true --wait=false
# kubectl delete namespaces -l load-test=true --wait=false
#
# FILTERING:
# kubectl get applications -n argocd -l load-test=true
# kubectl get applications -n argocd -l load-test=true,environment=prod
# kubectl get applications -n argocd -l load-test=true,team=platform
#
set -e
# Number of applications to create (default: 50)
NUM_APPS=${1:-50}
BATCH_SIZE=50 # Create apps in batches for better performance
echo "Load Testing ArgoCD with $NUM_APPS realistic applications..."
echo ""
# Add test repositories using kubectl
echo "Adding test repositories..."
# ArgoCD example apps repo
cat <<EEOF | kubectl apply -f - > /dev/null
apiVersion: v1
kind: Secret
metadata:
name: repo-argocd-examples
namespace: argocd
labels:
argocd.argoproj.io/secret-type: repository
stringData:
url: https://github.com/argoproj/argocd-example-apps.git
type: git
name: argocd-examples
EEOF
echo " - Added argocd-example-apps"
# Kubernetes examples repo
cat <<EEOF | kubectl apply -f - > /dev/null
apiVersion: v1
kind: Secret
metadata:
name: repo-kubernetes-examples
namespace: argocd
labels:
argocd.argoproj.io/secret-type: repository
stringData:
url: https://github.com/kubernetes/examples.git
type: git
name: kubernetes-examples
EEOF
echo " - Added kubernetes-examples"
# Bitnami Helm repo
cat <<EEOF | kubectl apply -f - > /dev/null
apiVersion: v1
kind: Secret
metadata:
name: repo-bitnami
namespace: argocd
labels:
argocd.argoproj.io/secret-type: repository
stringData:
url: https://charts.bitnami.com/bitnami
type: helm
name: bitnami
EEOF
echo " - Added Bitnami Helm repo"
# NGINX Helm repo
cat <<EEOF | kubectl apply -f - > /dev/null
apiVersion: v1
kind: Secret
metadata:
name: repo-nginx
namespace: argocd
labels:
argocd.argoproj.io/secret-type: repository
stringData:
url: https://kubernetes.github.io/ingress-nginx
type: helm
name: nginx
EEOF
echo " - Added NGINX Helm repo"
echo ""
echo "Creating realistic namespaces..."
echo ""
# Realistic app components and environments
SERVICES=("api" "web" "worker" "frontend" "backend" "db" "cache" "queue" "auth" "payments" "notifications" "analytics" "search" "admin" "mobile-api")
TEAMS=("platform" "product" "data" "infrastructure" "security" "payments" "growth" "mobile")
ENVS=("prod" "staging" "dev" "qa")
# Create team-environment namespaces (realistic: 8 teams × 4 envs = 32 namespaces)
NAMESPACE_COUNT=0
for team in "${TEAMS[@]}"; do
for env in "${ENVS[@]}"; do
NAMESPACE="$team-$env"
cat <<EEOF | kubectl apply -f - > /dev/null 2>&1
apiVersion: v1
kind: Namespace
metadata:
name: $NAMESPACE
labels:
load-test: "true"
team: "$team"
environment: "$env"
EEOF
NAMESPACE_COUNT=$((NAMESPACE_COUNT + 1))
done
done
echo " - Created $NAMESPACE_COUNT namespaces (team-environment combinations)"
echo ""
echo "Creating $NUM_APPS realistic applications..."
echo " Using batch size of $BATCH_SIZE for optimal performance"
echo ""
# App templates with more variety
APPS=(
"guestbook|https://github.com/argoproj/argocd-example-apps.git|guestbook"
"helm-guestbook|https://github.com/argoproj/argocd-example-apps.git|helm-guestbook"
"kustomize-guestbook|https://github.com/argoproj/argocd-example-apps.git|kustomize-guestbook"
"sock-shop|https://github.com/argoproj/argocd-example-apps.git|sock-shop"
"ksonnet-guestbook|https://github.com/argoproj/argocd-example-apps.git|ksonnet-guestbook"
)
# Function to generate realistic app name
generate_app_name() {
local idx=$1
local service_idx=$((idx % ${#SERVICES[@]}))
local team_idx=$((idx % ${#TEAMS[@]}))
local env_idx=$((idx % ${#ENVS[@]}))
echo "${TEAMS[$team_idx]}-${SERVICES[$service_idx]}-${ENVS[$env_idx]}-$idx"
}
# Function to generate sync policy (mix of auto and manual)
generate_sync_policy() {
local idx=$1
# 70% auto-sync, 30% manual
if [ $((idx % 10)) -lt 7 ]; then
cat <<'POLICY'
syncPolicy:
automated:
prune: true
selfHeal: true
POLICY
else
echo ""
fi
}
# Create applications in batches
START_TIME=$(date +%s)
BATCH_FILE="/tmp/argocd-batch-apps-$$.yaml"
for i in $(seq 1 $NUM_APPS); do
# Pick app template
TEMPLATE_IDX=$((i % ${#APPS[@]}))
TEMPLATE=${APPS[$TEMPLATE_IDX]}
# Parse template using bash parameter expansion
IFS='|' read -r BASE_APP REPO_URL APP_PATH <<< "$TEMPLATE"
# Generate realistic names
APP_NAME=$(generate_app_name $i)
# Parse app name using bash parameter expansion
IFS='-' read -r TEAM SERVICE ENV REST <<< "$APP_NAME"
# Use shared team-environment namespace (realistic!)
NAMESPACE="$TEAM-$ENV"
# Get sync policy
SYNC_POLICY=$(generate_sync_policy $i)
# Append application to batch file
cat <<EEOF >> $BATCH_FILE
---
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: $APP_NAME
namespace: argocd
labels:
load-test: "true"
app-type: "$BASE_APP"
team: "$TEAM"
service: "$SERVICE"
environment: "$ENV"
annotations:
load-test/created-at: "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
spec:
project: default
source:
repoURL: $REPO_URL
targetRevision: HEAD
path: $APP_PATH
destination:
server: https://kubernetes.default.svc
namespace: $NAMESPACE
$SYNC_POLICY
EEOF
# Apply in batches
if [ $((i % BATCH_SIZE)) -eq 0 ] || [ $i -eq $NUM_APPS ]; then
kubectl apply -f $BATCH_FILE
rm -f $BATCH_FILE
CURRENT_TIME=$(date +%s)
ELAPSED=$((CURRENT_TIME - START_TIME))
RATE=$((i / (ELAPSED + 1)))
echo " - Created $i/$NUM_APPS applications... (${RATE} apps/sec)"
fi
done
# Clean up batch file if it exists
rm -f $BATCH_FILE
END_TIME=$(date +%s)
TOTAL_TIME=$((END_TIME - START_TIME))
echo ""
echo "Load test setup complete in ${TOTAL_TIME} seconds!"
echo ""
echo "SUMMARY:"
echo " - 4 repositories added"
echo " - $NAMESPACE_COUNT namespaces created (team-environment combinations)"
echo " - $NUM_APPS applications created"
echo " - Average: $((NUM_APPS / (TOTAL_TIME + 1))) apps/second"
echo ""
# Count apps by type
echo "Application distribution:"
for app in "${APPS[@]}"; do
IFS='|' read -r BASE_NAME _ _ <<< "$app"
COUNT=$(kubectl get applications -n argocd -l app-type=$BASE_NAME --no-headers 2>/dev/null | wc -l | tr -d ' ')
echo " - $BASE_NAME: $COUNT apps"
done
echo ""
# Count apps by environment
echo "Environment distribution:"
for env in "${ENVS[@]}"; do
COUNT=$(kubectl get applications -n argocd -l environment=$env,load-test=true --no-headers 2>/dev/null | wc -l | tr -d ' ')
echo " - $env: $COUNT apps"
done
echo ""
# Count sync policies
AUTO_COUNT=$(kubectl get applications -n argocd -l load-test=true -o jsonpath='{range .items[*]}{.spec.syncPolicy.automated}{"\n"}{end}' 2>/dev/null | grep -c -v '^$' || echo "0")
MANUAL_COUNT=$((NUM_APPS - AUTO_COUNT))
echo "Sync policies:"
echo " - Auto-sync: $AUTO_COUNT apps (~$((AUTO_COUNT * 100 / NUM_APPS))%)"
echo " - Manual sync: $MANUAL_COUNT apps (~$((MANUAL_COUNT * 100 / NUM_APPS))%)"
echo ""
echo "To clean up all test apps, run:"
echo " kubectl delete applications -n argocd -l load-test=true --wait=false"
echo " kubectl delete namespaces -l load-test=true --wait=false"
echo ""
echo "To view status:"
echo " kubectl get applications -n argocd -l load-test=true"
echo " kubectl get applications -n argocd -l load-test=true,environment=prod"
echo " kubectl get applications -n argocd -l load-test=true,team=platform"
echo ""
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment