Compare commits

...
Sign in to create a new pull request.

1 commit

Author SHA1 Message Date
Timofei Larkin
482255a7f1 [cozystack-scheduler] Publish SchedulingClass demo
## What this PR does

Publish the scripts used for running the Cozystack scheduler demo at the
community meetup on 19.03.2026.

### Release note

```release-note
[cozystack-scheduler] Add demo scripts to the cozystack-scheduler system
packages.
```
2026-03-20 11:15:52 +03:00
14 changed files with 951 additions and 0 deletions

View file

@ -0,0 +1,121 @@
#!/bin/bash
# Helper functions for the scheduling classes demo
# Source this file in other scripts: source "$(dirname "$0")/00-helpers.sh"
# ANSI color codes
export RED='\033[0;31m'
export GREEN='\033[0;32m'
export YELLOW='\033[1;33m'
export BLUE='\033[0;34m'
export MAGENTA='\033[0;35m'
export CYAN='\033[0;36m'
export WHITE='\033[1;37m'
export NC='\033[0m' # No Color
export BOLD='\033[1m'
log_info() {
echo -e "${BLUE}${NC} $*" >&2
}
log_success() {
echo -e "${GREEN}${NC} $*" >&2
}
log_warning() {
echo -e "${YELLOW}${NC} $*" >&2
}
log_error() {
echo -e "${RED}${NC} $*" >&2
}
log_step() {
echo -e "\n${MAGENTA}${BOLD}$*${NC}" >&2
}
log_command() {
echo -e "${WHITE} \$ $*${NC}" >&2
}
separator() {
echo -e "\n${CYAN}────────────────────────────────────────────────────────────${NC}\n" >&2
}
print_header() {
local title="$1"
echo -e "\n${MAGENTA}${BOLD}╔════════════════════════════════════════════════════════════╗${NC}" >&2
echo -e "${MAGENTA}${BOLD}${NC} ${WHITE}${BOLD}$title${NC}" >&2
echo -e "${MAGENTA}${BOLD}╚════════════════════════════════════════════════════════════╝${NC}\n" >&2
}
# Display a YAML manifest with syntax highlighting (just colored output)
show_manifest() {
echo -e "${YELLOW}$1${NC}" >&2
}
# Wait for user to press any key
pause() {
echo -e "\n${CYAN}Press any key to continue...${NC}" >&2
read -rsn1
}
# Wait for pods to appear and stabilize
wait_for_pods() {
local namespace="$1"
local label="${2:-}"
local timeout="${3:-120}"
local elapsed=0
log_info "Waiting for pods in $namespace..."
while true; do
local count
if [[ -n "$label" ]]; then
count=$(kubectl get pods -n "$namespace" -l "$label" --no-headers 2>/dev/null | wc -l)
else
count=$(kubectl get pods -n "$namespace" --no-headers 2>/dev/null | wc -l)
fi
if [[ "$count" -gt 0 ]]; then
break
fi
if [[ $elapsed -ge $timeout ]]; then
log_warning "Timed out waiting for pods"
return 1
fi
sleep 2
elapsed=$((elapsed + 2))
done
# Give pods a moment to get node assignments
sleep 3
}
# Show pods with node placement
show_pods() {
local namespace="$1"
echo "" >&2
kubectl get pods -n "$namespace" -o wide 2>&1 >&2
echo "" >&2
}
# Wait for a Redis resource to be ready (HelmRelease applied)
wait_for_redis_ready() {
local namespace="$1"
local name="$2"
local timeout="${3:-180}"
local elapsed=0
log_info "Waiting for Redis $name in $namespace to become ready..."
while true; do
local phase
phase=$(kubectl get redis "$name" -n "$namespace" -o jsonpath='{.status.conditions[0].status}' 2>/dev/null || echo "")
if [[ "$phase" == "True" ]]; then
log_success "Redis $name is ready"
break
fi
if [[ $elapsed -ge $timeout ]]; then
log_warning "Timed out waiting for Redis to be ready, continuing anyway..."
break
fi
sleep 5
elapsed=$((elapsed + 5))
done
}

View file

@ -0,0 +1,133 @@
#!/bin/bash
# Script 01: Create SchedulingClasses
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/00-helpers.sh"
print_header "Step 1: Create SchedulingClasses"
# --- pin-to-node2 ---
log_step "SchedulingClass: pin-to-node2"
log_info "All pods will always be scheduled to node2."
show_manifest "apiVersion: cozystack.io/v1alpha1
kind: SchedulingClass
metadata:
name: pin-to-node2
spec:
nodeSelector:
kubernetes.io/hostname: node2"
pause
kubectl apply -f - <<'EOF'
apiVersion: cozystack.io/v1alpha1
kind: SchedulingClass
metadata:
name: pin-to-node2
spec:
nodeSelector:
kubernetes.io/hostname: node2
EOF
log_success "Created SchedulingClass pin-to-node2"
separator
# --- one-per-node ---
log_step "SchedulingClass: one-per-node"
log_info "Pods of the same application will never share a node."
show_manifest "apiVersion: cozystack.io/v1alpha1
kind: SchedulingClass
metadata:
name: one-per-node
spec:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- topologyKey: kubernetes.io/hostname"
pause
kubectl apply -f - <<'EOF'
apiVersion: cozystack.io/v1alpha1
kind: SchedulingClass
metadata:
name: one-per-node
spec:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- topologyKey: kubernetes.io/hostname
EOF
log_success "Created SchedulingClass one-per-node"
separator
# --- spread-evenly ---
log_step "SchedulingClass: spread-evenly"
log_info "Pods will be spread evenly across nodes (maxSkew=1)."
show_manifest "apiVersion: cozystack.io/v1alpha1
kind: SchedulingClass
metadata:
name: spread-evenly
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule"
pause
kubectl apply -f - <<'EOF'
apiVersion: cozystack.io/v1alpha1
kind: SchedulingClass
metadata:
name: spread-evenly
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule
EOF
log_success "Created SchedulingClass spread-evenly"
separator
# --- colocate ---
log_step "SchedulingClass: colocate"
log_info "All pods of the same application will land on the same node."
show_manifest "apiVersion: cozystack.io/v1alpha1
kind: SchedulingClass
metadata:
name: colocate
spec:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- topologyKey: kubernetes.io/hostname"
pause
kubectl apply -f - <<'EOF'
apiVersion: cozystack.io/v1alpha1
kind: SchedulingClass
metadata:
name: colocate
spec:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- topologyKey: kubernetes.io/hostname
EOF
log_success "Created SchedulingClass colocate"
separator
log_success "All SchedulingClasses created."
log_command "kubectl get schedulingclasses"
kubectl get schedulingclasses >&2
echo -e "\n${GREEN}${BOLD}Next step:${NC} ./02-create-tenants.sh"

View file

@ -0,0 +1,121 @@
#!/bin/bash
# Script 02: Create tenants, one per scheduling class
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/00-helpers.sh"
print_header "Step 2: Create Tenants"
# --- tenant colocate ---
log_step "Tenant: colocate (schedulingClass: colocate)"
show_manifest "apiVersion: apps.cozystack.io/v1alpha1
kind: Tenant
metadata:
name: colocate
namespace: tenant-root
spec:
schedulingClass: colocate"
pause
kubectl apply -f - <<'EOF'
apiVersion: apps.cozystack.io/v1alpha1
kind: Tenant
metadata:
name: colocate
namespace: tenant-root
spec:
schedulingClass: colocate
EOF
log_success "Created tenant colocate"
separator
# --- tenant onepernode ---
log_step "Tenant: onepernode (schedulingClass: one-per-node)"
show_manifest "apiVersion: apps.cozystack.io/v1alpha1
kind: Tenant
metadata:
name: onepernode
namespace: tenant-root
spec:
schedulingClass: one-per-node"
pause
kubectl apply -f - <<'EOF'
apiVersion: apps.cozystack.io/v1alpha1
kind: Tenant
metadata:
name: onepernode
namespace: tenant-root
spec:
schedulingClass: one-per-node
EOF
log_success "Created tenant onepernode"
separator
# --- tenant spread ---
log_step "Tenant: spread (schedulingClass: spread-evenly)"
show_manifest "apiVersion: apps.cozystack.io/v1alpha1
kind: Tenant
metadata:
name: spread
namespace: tenant-root
spec:
schedulingClass: spread-evenly"
pause
kubectl apply -f - <<'EOF'
apiVersion: apps.cozystack.io/v1alpha1
kind: Tenant
metadata:
name: spread
namespace: tenant-root
spec:
schedulingClass: spread-evenly
EOF
log_success "Created tenant spread"
separator
# --- tenant node2 ---
log_step "Tenant: node2 (schedulingClass: pin-to-node2)"
show_manifest "apiVersion: apps.cozystack.io/v1alpha1
kind: Tenant
metadata:
name: node2
namespace: tenant-root
spec:
schedulingClass: pin-to-node2"
pause
kubectl apply -f - <<'EOF'
apiVersion: apps.cozystack.io/v1alpha1
kind: Tenant
metadata:
name: node2
namespace: tenant-root
spec:
schedulingClass: pin-to-node2
EOF
log_success "Created tenant node2"
separator
log_success "All tenants created."
log_command "kubectl get tenants -n tenant-root"
kubectl get tenants -n tenant-root >&2
echo -e "\n${GREEN}${BOLD}Next step:${NC} ./03-colocate-demo.sh"

View file

@ -0,0 +1,69 @@
#!/bin/bash
# Script 03: Colocate demo - all pods of a Redis land on the same node
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/00-helpers.sh"
NAMESPACE="tenant-colocate"
REDIS_NAME="redis-demo"
print_header "Step 3: Colocate Demo"
log_step "Creating Redis in $NAMESPACE (1 replica + 3 sentinels)"
show_manifest "apiVersion: apps.cozystack.io/v1alpha1
kind: Redis
metadata:
name: $REDIS_NAME
namespace: $NAMESPACE
spec:
replicas: 1
storageClass: local
resourcesPreset: nano
authEnabled: false"
pause
kubectl apply -f - <<EOF
apiVersion: apps.cozystack.io/v1alpha1
kind: Redis
metadata:
name: $REDIS_NAME
namespace: $NAMESPACE
spec:
replicas: 1
storageClass: local
resourcesPreset: nano
authEnabled: false
EOF
log_success "Redis $REDIS_NAME created"
separator
log_step "Waiting for pods to be scheduled..."
wait_for_redis_ready "$NAMESPACE" "$REDIS_NAME"
wait_for_pods "$NAMESPACE"
log_step "All pods should be on the SAME node:"
show_pods "$NAMESPACE"
pause
separator
log_step "Scaling up replicas to 9..."
log_command "kubectl patch redis $REDIS_NAME -n $NAMESPACE --type=merge -p '{\"spec\":{\"replicas\":9}}'"
kubectl patch redis "$REDIS_NAME" -n "$NAMESPACE" --type=merge -p '{"spec":{"replicas":9}}'
log_info "Waiting for new pods..."
sleep 15
log_step "All pods (storage + sentinels) are still on the same node:"
show_pods "$NAMESPACE"
separator
log_success "Colocate demo complete. All pods landed on one node."
echo -e "\n${GREEN}${BOLD}Next step:${NC} ./04-colocate-second-redis.sh"

View file

@ -0,0 +1,61 @@
#!/bin/bash
# Script 04: Second Redis in colocate tenant - shows cross-app independence
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/00-helpers.sh"
NAMESPACE="tenant-colocate"
REDIS_NAME="redis-demo2"
print_header "Step 4: Colocate - Second Redis (cross-app independence)"
log_step "Cleaning up $REDIS_NAME if it already exists..."
kubectl delete redis "$REDIS_NAME" -n "$NAMESPACE" --ignore-not-found >&2
sleep 3
separator
log_step "Creating a second Redis in $NAMESPACE"
log_info "This Redis will colocate its own pods together,"
log_info "but may land on a DIFFERENT node than the first Redis."
show_manifest "apiVersion: apps.cozystack.io/v1alpha1
kind: Redis
metadata:
name: $REDIS_NAME
namespace: $NAMESPACE
spec:
replicas: 1
storageClass: local
resourcesPreset: nano
authEnabled: false"
pause
kubectl apply -f - <<EOF
apiVersion: apps.cozystack.io/v1alpha1
kind: Redis
metadata:
name: $REDIS_NAME
namespace: $NAMESPACE
spec:
replicas: 1
storageClass: local
resourcesPreset: nano
authEnabled: false
EOF
log_success "Redis $REDIS_NAME created"
log_step "Waiting for pods to be scheduled..."
wait_for_redis_ready "$NAMESPACE" "$REDIS_NAME"
wait_for_pods "$NAMESPACE"
log_step "Pod placement for both Redis instances:"
log_info "Each Redis colocates its own pods, but the two Redises are independent."
show_pods "$NAMESPACE"
separator
log_success "Second Redis demo complete."
echo -e "\n${GREEN}${BOLD}Next step:${NC} ./05-colocate-cleanup.sh"

View file

@ -0,0 +1,24 @@
#!/bin/bash
# Script 05: Clean up Redis instances in tenant-colocate
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/00-helpers.sh"
NAMESPACE="tenant-colocate"
print_header "Step 5: Clean up tenant-colocate"
log_step "Deleting all Redis instances in $NAMESPACE..."
kubectl delete redis --all -n "$NAMESPACE" --ignore-not-found >&2
log_info "Waiting for pods to terminate..."
sleep 10
log_step "Remaining pods:"
show_pods "$NAMESPACE"
separator
log_success "Cleanup complete."
echo -e "\n${GREEN}${BOLD}Next step:${NC} ./06-onepernode-demo.sh"

View file

@ -0,0 +1,92 @@
#!/bin/bash
# Script 06: One-per-node demo - anti-affinity prevents pods on the same node
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/00-helpers.sh"
NAMESPACE="tenant-onepernode"
REDIS_NAME="redis-demo"
print_header "Step 6: One-per-node Demo"
log_step "Creating Redis in $NAMESPACE (1 replica)"
log_info "We'll also reduce sentinels to 2 (1 storage + 2 sentinels = 3 pods for 3 nodes)."
show_manifest "apiVersion: apps.cozystack.io/v1alpha1
kind: Redis
metadata:
name: $REDIS_NAME
namespace: $NAMESPACE
spec:
replicas: 1
storageClass: local
resourcesPreset: nano
authEnabled: false"
pause
kubectl apply -f - <<EOF
apiVersion: apps.cozystack.io/v1alpha1
kind: Redis
metadata:
name: $REDIS_NAME
namespace: $NAMESPACE
spec:
replicas: 1
storageClass: local
resourcesPreset: nano
authEnabled: false
EOF
log_success "Redis $REDIS_NAME created"
log_info "Waiting for RedisFailover to appear..."
sleep 10
log_step "Patching RedisFailover to use 2 sentinels instead of 3"
log_info "With 3 nodes and anti-affinity, 1 storage + 3 sentinels = 4 pods won't fit."
log_command "kubectl patch rf $REDIS_NAME -n $NAMESPACE --type=merge -p '{\"spec\":{\"sentinel\":{\"replicas\":2}}}'"
kubectl patch rf redis-"$REDIS_NAME" -n "$NAMESPACE" --type=merge -p '{"spec":{"sentinel":{"replicas":2}}}'
log_info "Waiting for pods to be scheduled..."
wait_for_pods "$NAMESPACE"
sleep 5
log_step "Each pod is on a different node (1 storage + 2 sentinels on 3 nodes):"
show_pods "$NAMESPACE"
pause
separator
log_step "Scaling up to 3 replicas..."
log_command "kubectl patch redis $REDIS_NAME -n $NAMESPACE --type=merge -p '{\"spec\":{\"replicas\":3}}'"
kubectl patch redis "$REDIS_NAME" -n "$NAMESPACE" --type=merge -p '{"spec":{"replicas":3}}'
log_info "Waiting for new pods..."
sleep 15
log_step "Some pods should now be Pending (anti-affinity prevents scheduling):"
show_pods "$NAMESPACE"
pause
separator
log_step "Describing a Pending pod to see why it can't be scheduled..."
PENDING_POD=$(kubectl get pods -n "$NAMESPACE" --field-selector=status.phase=Pending -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || echo "")
if [[ -n "$PENDING_POD" ]]; then
log_command "kubectl describe pod $PENDING_POD -n $NAMESPACE | tail -10"
kubectl describe pod "$PENDING_POD" -n "$NAMESPACE" 2>&1 | tail -10 >&2
else
log_warning "No Pending pods found (pods may still be initializing)."
log_command "kubectl get pods -n $NAMESPACE -o wide"
fi
separator
log_success "One-per-node demo complete. Anti-affinity prevents co-scheduling."
echo -e "\n${GREEN}${BOLD}Next step:${NC} ./07-onepernode-second-redis.sh"

View file

@ -0,0 +1,68 @@
#!/bin/bash
# Script 07: Second Redis in one-per-node tenant - shows cross-app independence
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/00-helpers.sh"
NAMESPACE="tenant-onepernode"
REDIS_NAME="redis-demo2"
print_header "Step 7: One-per-node - Second Redis (cross-app independence)"
log_step "Cleaning up $REDIS_NAME if it already exists..."
kubectl delete redis "$REDIS_NAME" -n "$NAMESPACE" --ignore-not-found >&2
sleep 3
separator
log_step "Creating a second Redis in $NAMESPACE"
log_info "Anti-affinity only applies WITHIN the same application."
log_info "This second Redis has no anti-affinity against the first one."
show_manifest "apiVersion: apps.cozystack.io/v1alpha1
kind: Redis
metadata:
name: $REDIS_NAME
namespace: $NAMESPACE
spec:
replicas: 1
storageClass: local
resourcesPreset: nano
authEnabled: false"
pause
kubectl apply -f - <<EOF
apiVersion: apps.cozystack.io/v1alpha1
kind: Redis
metadata:
name: $REDIS_NAME
namespace: $NAMESPACE
spec:
replicas: 1
storageClass: local
resourcesPreset: nano
authEnabled: false
EOF
log_success "Redis $REDIS_NAME created"
log_info "Waiting for RedisFailover to appear..."
sleep 10
log_step "Patching sentinels to 2 for the second Redis as well"
kubectl patch rf redis-"$REDIS_NAME" -n "$NAMESPACE" --type=merge -p '{"spec":{"sentinel":{"replicas":2}}}'
log_info "Waiting for pods to be scheduled..."
wait_for_pods "$NAMESPACE"
sleep 5
log_step "Pod placement for both Redis instances:"
log_info "Each Redis spreads its own pods one-per-node independently."
log_info "The two Redises CAN share nodes — anti-affinity is per-application."
show_pods "$NAMESPACE"
separator
log_success "Second Redis demo complete."
echo -e "\n${GREEN}${BOLD}Next step:${NC} ./08-onepernode-cleanup.sh"

View file

@ -0,0 +1,24 @@
#!/bin/bash
# Script 08: Clean up Redis instances in tenant-onepernode
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/00-helpers.sh"
NAMESPACE="tenant-onepernode"
print_header "Step 8: Clean up tenant-onepernode"
log_step "Deleting all Redis instances in $NAMESPACE..."
kubectl delete redis --all -n "$NAMESPACE" --ignore-not-found >&2
log_info "Waiting for pods to terminate..."
sleep 10
log_step "Remaining pods:"
show_pods "$NAMESPACE"
separator
log_success "Cleanup complete."
echo -e "\n${GREEN}${BOLD}Next step:${NC} ./09-spread-demo.sh"

View file

@ -0,0 +1,73 @@
#!/bin/bash
# Script 09: Spread-evenly demo - topology spread constraints
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/00-helpers.sh"
NAMESPACE="tenant-spread"
REDIS_NAME="redis-demo"
print_header "Step 9: Spread-evenly Demo"
log_step "Creating Redis in $NAMESPACE (1 replica)"
show_manifest "apiVersion: apps.cozystack.io/v1alpha1
kind: Redis
metadata:
name: $REDIS_NAME
namespace: $NAMESPACE
spec:
replicas: 1
storageClass: local
resourcesPreset: nano
authEnabled: false"
pause
kubectl apply -f - <<EOF
apiVersion: apps.cozystack.io/v1alpha1
kind: Redis
metadata:
name: $REDIS_NAME
namespace: $NAMESPACE
spec:
replicas: 1
storageClass: local
resourcesPreset: nano
authEnabled: false
EOF
log_success "Redis $REDIS_NAME created"
log_info "Waiting for pods to be scheduled..."
wait_for_redis_ready "$NAMESPACE" "$REDIS_NAME"
wait_for_pods "$NAMESPACE"
log_step "Initial pod distribution (1 storage + 3 sentinels):"
show_pods "$NAMESPACE"
pause
separator
log_step "Scaling up to 9 replicas..."
log_command "kubectl patch redis $REDIS_NAME -n $NAMESPACE --type=merge -p '{\"spec\":{\"replicas\":9}}'"
kubectl patch redis "$REDIS_NAME" -n "$NAMESPACE" --type=merge -p '{"spec":{"replicas":9}}'
log_info "Waiting for new pods..."
sleep 20
log_step "Pods should be evenly distributed across all nodes (maxSkew=1):"
show_pods "$NAMESPACE"
separator
log_step "Pod count per node:"
kubectl get pods -n "$NAMESPACE" -o wide --no-headers 2>/dev/null \
| awk '{print $7}' | sort | uniq -c | sort -rn >&2
separator
log_success "Spread-evenly demo complete. Pods are balanced across nodes."
echo -e "\n${GREEN}${BOLD}Next step:${NC} ./10-spread-cleanup.sh"

View file

@ -0,0 +1,24 @@
#!/bin/bash
# Script 10: Clean up Redis instances in tenant-spread
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/00-helpers.sh"
NAMESPACE="tenant-spread"
print_header "Step 10: Clean up tenant-spread"
log_step "Deleting all Redis instances in $NAMESPACE..."
kubectl delete redis --all -n "$NAMESPACE" --ignore-not-found >&2
log_info "Waiting for pods to terminate..."
sleep 10
log_step "Remaining pods:"
show_pods "$NAMESPACE"
separator
log_success "Cleanup complete."
echo -e "\n${GREEN}${BOLD}Next step:${NC} ./11-node2-demo.sh"

View file

@ -0,0 +1,94 @@
#!/bin/bash
# Script 11: Pin-to-node2 demo - all pods on a specific node
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/00-helpers.sh"
NAMESPACE="tenant-node2"
REDIS1="redis-demo"
REDIS2="redis-demo2"
print_header "Step 11: Pin-to-node2 Demo"
log_step "Creating first Redis in $NAMESPACE"
show_manifest "apiVersion: apps.cozystack.io/v1alpha1
kind: Redis
metadata:
name: $REDIS1
namespace: $NAMESPACE
spec:
replicas: 1
storageClass: local
resourcesPreset: nano
authEnabled: false"
pause
kubectl apply -f - <<EOF
apiVersion: apps.cozystack.io/v1alpha1
kind: Redis
metadata:
name: $REDIS1
namespace: $NAMESPACE
spec:
replicas: 1
storageClass: local
resourcesPreset: nano
authEnabled: false
EOF
log_success "Redis $REDIS1 created"
log_info "Waiting for pods to be scheduled..."
wait_for_redis_ready "$NAMESPACE" "$REDIS1"
wait_for_pods "$NAMESPACE"
log_step "All pods should be on node2:"
show_pods "$NAMESPACE"
pause
separator
log_step "Creating a second Redis in $NAMESPACE"
show_manifest "apiVersion: apps.cozystack.io/v1alpha1
kind: Redis
metadata:
name: $REDIS2
namespace: $NAMESPACE
spec:
replicas: 1
storageClass: local
resourcesPreset: nano
authEnabled: false"
pause
kubectl apply -f - <<EOF
apiVersion: apps.cozystack.io/v1alpha1
kind: Redis
metadata:
name: $REDIS2
namespace: $NAMESPACE
spec:
replicas: 1
storageClass: local
resourcesPreset: nano
authEnabled: false
EOF
log_success "Redis $REDIS2 created"
log_info "Waiting for pods to be scheduled..."
wait_for_redis_ready "$NAMESPACE" "$REDIS2"
wait_for_pods "$NAMESPACE"
log_step "Both Redis instances — all pods pinned to node2:"
show_pods "$NAMESPACE"
separator
log_success "Pin-to-node2 demo complete."
echo -e "\n${GREEN}${BOLD}Next step:${NC} ./12-node2-cleanup.sh"

View file

@ -0,0 +1,23 @@
#!/bin/bash
# Script 12: Clean up Redis instances in tenant-node2
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/00-helpers.sh"
NAMESPACE="tenant-node2"
print_header "Step 12: Clean up tenant-node2"
log_step "Deleting all Redis instances in $NAMESPACE..."
kubectl delete redis --all -n "$NAMESPACE" --ignore-not-found >&2
log_info "Waiting for pods to terminate..."
sleep 10
log_step "Remaining pods:"
show_pods "$NAMESPACE"
separator
log_success "Cleanup complete. Demo finished!"

View file

@ -0,0 +1,24 @@
#!/bin/bash
# Script 13: Tear down all tenants and scheduling classes
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/00-helpers.sh"
print_header "Teardown: Remove tenants and scheduling classes"
log_step "Deleting tenants..."
for t in colocate onepernode spread node2; do
kubectl delete tenant "$t" -n tenant-root --ignore-not-found >&2
done
log_info "Waiting for tenant namespaces to be cleaned up..."
sleep 15
log_step "Deleting scheduling classes..."
for sc in colocate one-per-node spread-evenly pin-to-node2; do
kubectl delete schedulingclass "$sc" --ignore-not-found >&2
done
separator
log_success "Teardown complete."