Validate Vind (lightweight Kubernetes) cluster creation, migrate from Kind to Vind, and perform cross-architecture testing for resource-constrained environments. Trigger with /vind-status
"Kind is great. But have you tried running it on a NAS with 4GB RAM?"
I validate and manage Vind clusters—lightweight Kubernetes distributions designed for resource-constrained environments. This skill helps migrate from Kind (too heavy for Synology NAS) to Vind, and enables cross-architecture testing where x86 Vind clusters validate ARM64 manifests before CozyStack deployment.
Context: Vind emerged from the Sunkworks episode we never quite reached—the realization that Kind's node containers are too memory-hungry for homelab NAS devices. Vind provides a lighter alternative while maintaining Kubernetes API compatibility.
/vind-statusRuns Vind validation workflow:
Usage: Type /vind-status to validate Vind cluster health.
Script Verification: Before executing, verify the script integrity:
sha256sum .github/skills/vind-operator/scripts/validate.sh
# Expected: b42e83b65ad548a97be2464feaed426f882356eb2bccd76f579cf912c6d45a71
Execute validation:
bash .github/skills/vind-operator/scripts/validate.sh
/vind-status (slash command)| Failure Mode | Symptoms | Est. Recovery Time | |--------------|----------|-------------------| | OOM during creation | Container killed, cluster partially created | 15-30 min | | Image pull timeout | Node stuck in ContainerCreating | 10-20 min | | Network bridge conflict | Multiple Vind clusters fail to start | 20-30 min | | Storage driver incompatibility | Container fails immediately | 30-60 min |
| Failure Mode | Symptoms | Est. Recovery Time | |--------------|----------|-------------------| | Multi-arch image missing | ImagePullBackOff on ARM target | 20-40 min | | Architecture-specific configs | Works on x86, fails on ARM | 30-60 min | | Resource limits too tight | ARM device has less headroom | 15-30 min |
| Failure Mode | Symptoms | Workaround | |--------------|----------|------------| | Kind-specific features | Extraportmappings, node labels | Manual reconfiguration | | Volume mount differences | PV/PVC paths don't match | Update volume specs | | Network policy variance | CNI behavior differences | Validate policies separately |
# Create single-node Vind cluster (minimal resources)
vind create cluster --name sunkworks-dev \
--memory 2048 \
--cpus 2
# Verify creation
kubectl cluster-info --context vind-sunkworks-dev
For Synology NAS and similar devices:
# vind-config.yaml
kind: Cluster
apiVersion: vind.io/v1alpha1
metadata:
name: synology-minimal
spec:
nodes:
- role: control-plane
resources:
memory: "1536Mi" # Synology-safe
cpu: "1500m" # Leave headroom for DSM
extraMounts:
- hostPath: /volume1/kubernetes
containerPath: /var/lib/kubernetes
networking:
disableDefaultCNI: false
podSubnet: "10.244.0.0/16"
# Disable resource-heavy features
featureGates:
EphemeralContainers: false
# Create from config
vind create cluster --config vind-config.yaml
# Set Kubernetes component resource limits
vind create cluster --name minimal \
--kube-apiserver-extra-args="--max-requests-inflight=100" \
--kubelet-extra-args="--max-pods=50" \
--controller-extra-args="--concurrent-deployment-syncs=2"
# Get current Kind cluster config
kind get clusters
kind export kubeconfig --name <kind-cluster>
# Export workloads (not including system pods)
kubectl get all -A -o yaml > kind-workloads.yaml
Kind Config:
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 80
hostPort: 80
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
Equivalent Vind Config:
kind: Cluster
apiVersion: vind.io/v1alpha1
metadata:
name: migrated-cluster
spec:
nodes:
- role: control-plane
portMappings:
- port: 80
hostPort: 80
labels:
ingress-ready: "true"
resources:
memory: "2048Mi"
cpu: "2000m"
#!/bin/bash
# migrate-kind-to-vind.sh
KIND_CLUSTER=$1
VIND_CLUSTER=${2:-"vind-$KIND_CLUSTER"}
echo "=== Migrating Kind cluster '$KIND_CLUSTER' to Vind '$VIND_CLUSTER' ==="
# Step 1: Export from Kind
echo "Step 1: Exporting Kind cluster state..."
kind export kubeconfig --name $KIND_CLUSTER
kubectl get all -A -o yaml > /tmp/kind-export.yaml
# Step 2: Stop Kind cluster
echo "Step 2: Stopping Kind cluster..."
kind delete cluster --name $KIND_CLUSTER
# Step 3: Create Vind cluster
echo "Step 3: Creating Vind cluster..."
vind create cluster --name $VIND_CLUSTER
# Step 4: Apply workloads
echo "Step 4: Applying workloads to Vind..."
kubectl --context vind-$VIND_CLUSTER apply -f /tmp/kind-export.yaml
echo "=== Migration complete ==="
The Sunkworks pattern: Validate manifests on x86 Vind before deploying to ARM64 CozyStack.
#!/bin/bash
# cross-arch-validate.sh
MANIFEST=$1
X86_CONTEXT="vind-x86-test"
ARM_TARGET_CONTEXT="cozystack-arm64"
echo "=== Cross-Architecture Validation ==="
echo "Manifest: $MANIFEST"
# Step 1: Apply to x86 Vind cluster
echo "Step 1: Testing on x86 Vind..."
kubectl --context $X86_CONTEXT apply --dry-run=server -f $MANIFEST
if [ $? -ne 0 ]; then
echo "ERROR: Manifest failed validation on x86"
exit 1
fi
echo "✓ x86 dry-run passed"
# Step 2: Check image architectures
echo "Step 2: Validating image architectures..."
IMAGES=$(kubectl --context $X86_CONTEXT apply --dry-run=client -f $MANIFEST -o jsonpath='{.spec.template.spec.containers[*].image}' 2>/dev/null)
for IMAGE in $IMAGES; do
echo " Checking $IMAGE..."
# Query registry for manifest list
docker manifest inspect $IMAGE 2>/dev/null | jq -e '.manifests[] | select(.platform.architecture == "arm64")' > /dev/null
if [ $? -ne 0 ]; then
echo " WARNING: $IMAGE may not have arm64 support"
else
echo " ✓ arm64 manifest found"
fi
done
# Step 3: Apply to x86 and verify
echo "Step 3: Full deployment test on x86..."
kubectl --context $X86_CONTEXT apply -f $MANIFEST
kubectl --context $X86_CONTEXT rollout status deployment -l app.kubernetes.io/instance=$(basename $MANIFEST .yaml) --timeout=120s
echo "=== Validation Complete ==="
echo "Safe to deploy to ARM64 target"
ARM devices typically have less memory headroom:
# Cross-architecture deployment with adjusted limits
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
spec:
template:
spec:
containers:
- name: app
resources:
# x86 values (test cluster has more headroom)
# ARM values should be ~75% of these
requests:
memory: "128Mi" # ARM: 96Mi
cpu: "100m" # ARM: 75m
limits:
memory: "256Mi" # ARM: 192Mi
cpu: "200m" # ARM: 150m
# Check Vind cluster node resources
kubectl top nodes
# Check system pod resource usage
kubectl -n kube-system top pods
# Monitor resource pressure
kubectl get nodes -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.status.conditions[?(@.type=="MemoryPressure")].status}{"\t"}{.status.conditions[?(@.type=="DiskPressure")].status}{"\n"}{end}'
# Check Docker/containerd memory usage on Synology
ssh admin@synology-ip "docker stats --no-stream"
# Check system memory
ssh admin@synology-ip "free -m"
# Monitor DSM resource usage
ssh admin@synology-ip "top -bn1 | head -20"
vind delete cluster --name <name>kubectl describe pod <name>docker manifest inspect <image>| Feature | Kind | Vind | Winner for NAS | |---------|------|------|----------------| | Base memory usage | ~2GB | ~1GB | Vind | | Startup time | 60-90s | 30-45s | Vind | | Multi-node support | Yes | Yes | Tie | | Ingress | Extra config | Built-in | Vind | | GPU passthrough | Limited | Limited | Tie | | Community size | Large | Growing | Kind | | Documentation | Extensive | Adequate | Kind |
"The episode where we tried to run Kind on the NAS... and learned why Vind exists."
free -m before cluster creationSearch for places (restaurants, cafes, etc.) via Google Places API proxy on localhost.
Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries.
Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
Start voice calls via the OpenClaw voice-call plugin.
Notion API for creating and managing pages, databases, and blocks.
Gemini CLI for one-shot Q&A, summaries, and generation.
Category:developer