Skip to content

Instantly share code, notes, and snippets.

@corbtastik
Created July 10, 2025 14:52
Show Gist options
  • Save corbtastik/0e23ff3c7185946018de00ed24338407 to your computer and use it in GitHub Desktop.
Save corbtastik/0e23ff3c7185946018de00ed24338407 to your computer and use it in GitHub Desktop.
Bash script to install kind on podman for MacOS
#!/bin/bash
set -e
# =========[ Configurable Environment Variables ]=========
PODMAN_MACHINE_NAME="${PODMAN_MACHINE_NAME:-podman-machine-default}"
CLUSTER_NAME="podman-kind"
KIND_CONFIG_FILE="kind-podman.yaml"
KIND_NODE_IMAGE="kindest/node:v1.29.1"
EXTRA_PORT_RANGE="${EXTRA_PORT_RANGE:-30000-30010}"
KIND_HOST_VOLUME_DIR="${KIND_HOST_VOLUME_DIR:-$HOME/kind-volumes/mongodb}" # Host path to persist MongoDB
# =========[ Dependency Check ]=========
function check_dependencies() {
echo "πŸ”§ Checking dependencies..."
for cmd in podman kind kubectl; do
if ! command -v $cmd &>/dev/null; then
echo "❌ '$cmd' is not installed. Please run: brew install $cmd"
exit 1
fi
done
}
# =========[ Kind Config Generation ]=========
function setup_kind_config() {
echo "πŸ“ Writing kind config to '$KIND_CONFIG_FILE'..."
# Ensure host volume path exists
echo "πŸ“ Ensuring host volume path exists: $KIND_HOST_VOLUME_DIR"
mkdir -p "$KIND_HOST_VOLUME_DIR"
# Parse extra port mappings
PORT_MAPPINGS=""
IFS='-' read -r START_PORT END_PORT <<< "$EXTRA_PORT_RANGE"
for (( PORT=START_PORT; PORT<=END_PORT; PORT++ )); do
PORT_MAPPINGS+="
- containerPort: $PORT
hostPort: $PORT
protocol: TCP"
done
cat > "$KIND_CONFIG_FILE" <<EOF
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
disableDefaultCNI: false
ipFamily: ipv4
apiServerAddress: "0.0.0.0"
nodes:
- role: control-plane
image: $KIND_NODE_IMAGE
extraPortMappings:
- containerPort: 80
hostPort: 8080
protocol: TCP
- containerPort: 80
hostPort: 8081
protocol: TCP
- containerPort: 27017
hostPort: 27017
protocol: TCP$PORT_MAPPINGS
extraMounts:
- hostPath: $(realpath "$KIND_HOST_VOLUME_DIR")
containerPath: /data/kind/mongodb
- role: worker
image: $KIND_NODE_IMAGE
extraMounts:
- hostPath: $(realpath "$KIND_HOST_VOLUME_DIR")
containerPath: /data/kind/mongodb
EOF
}
# =========[ Cluster Setup ]=========
function setup_cluster() {
check_dependencies
echo "πŸš€ Initializing podman machine: $PODMAN_MACHINE_NAME"
if ! podman machine list | grep "$PODMAN_MACHINE_NAME.*running"; then
if ! podman machine list | grep "$PODMAN_MACHINE_NAME"; then
podman machine init --cpus 4 --memory 4096 --name "$PODMAN_MACHINE_NAME"
fi
podman machine start "$PODMAN_MACHINE_NAME"
else
echo "βœ… Podman machine '$PODMAN_MACHINE_NAME' already running."
fi
echo "🌱 Setting KIND_EXPERIMENTAL_PROVIDER=podman..."
export KIND_EXPERIMENTAL_PROVIDER=podman
setup_kind_config
echo "🧹 Deleting existing cluster (if any)..."
kind delete cluster --name "$CLUSTER_NAME" || true
echo "πŸ› οΈ Creating kind cluster with Podman..."
kind create cluster --name "$CLUSTER_NAME" --config "$KIND_CONFIG_FILE"
echo "🏷️ Labeling control-plane node for Ingress..."
kubectl label node "$CLUSTER_NAME-control-plane" ingress-ready=true --overwrite
echo "πŸ” Verifying cluster..."
kubectl cluster-info --context kind-$CLUSTER_NAME
kubectl get nodes
setup_nginx_ingress
echo "βœ… Cluster is ready with Ingress and persistent MongoDB volume!"
echo "🌐 Ingress test: http://localhost:8081"
echo "πŸƒ MongoDB access: mongodb://localhost:27017"
echo "πŸ’Ύ MongoDB volume (host): $KIND_HOST_VOLUME_DIR"
}
# =========[ Ingress Setup ]=========
function setup_nginx_ingress() {
echo "🌐 Installing NGINX Ingress Controller..."
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.10.1/deploy/static/provider/kind/deploy.yaml
echo "⏳ Waiting for Ingress controller to be ready..."
kubectl wait --namespace ingress-nginx \
--for=condition=ready pod \
--selector=app.kubernetes.io/component=controller \
--timeout=120s
}
# =========[ Teardown ]=========
function teardown_cluster() {
echo "🧨 Deleting kind cluster named '$CLUSTER_NAME'..."
kind delete cluster --name "$CLUSTER_NAME" || echo "⚠️ Kind cluster not found."
echo "🧼 Stopping Podman machine '$PODMAN_MACHINE_NAME'..."
if podman machine list | grep "$PODMAN_MACHINE_NAME.*running"; then
podman machine stop "$PODMAN_MACHINE_NAME"
fi
read -p "πŸ—‘οΈ Do you want to **delete the Podman VM** '$PODMAN_MACHINE_NAME'? (yes/no): " CONFIRM
if [[ "$CONFIRM" == "yes" ]]; then
echo "πŸ”₯ Deleting Podman VM..."
podman machine rm -f "$PODMAN_MACHINE_NAME"
echo "βœ… Podman VM '$PODMAN_MACHINE_NAME' removed."
else
echo "❎ Podman VM left intact."
fi
echo "βœ… Teardown complete."
}
# =========[ Connect ]=========
function connect() {
echo "πŸ”— Connecting to MongoDB via port-forward..."
MONGO_USER="${MONGO_USER:-root}"
MONGO_PASS="${MONGO_PASS:-example}"
AUTH_DB="${AUTH_DB:-admin}"
NAMESPACE="mongodb"
SERVICE_NAME="mongodb"
LOCAL_PORT=27017
if ! kubectl get svc "$SERVICE_NAME" -n "$NAMESPACE" &>/dev/null; then
echo "❌ MongoDB service '$SERVICE_NAME' not found in namespace '$NAMESPACE'."
exit 1
fi
echo "πŸš€ Starting port-forward on localhost:$LOCAL_PORT..."
kubectl port-forward svc/"$SERVICE_NAME" $LOCAL_PORT:$LOCAL_PORT -n "$NAMESPACE" >/tmp/mongo-pf.log 2>&1 &
PF_PID=$!
cleanup() {
echo "πŸ›‘ Stopping port-forward (PID $PF_PID)..."
kill "$PF_PID" >/dev/null 2>&1 || true
}
trap cleanup EXIT
# Wait for readiness
for i in {1..10}; do
if nc -z localhost $LOCAL_PORT; then
break
fi
sleep 1
done
echo "πŸ” Verifying MongoDB connection via mongosh..."
mongosh "mongodb://$MONGO_USER:$MONGO_PASS@localhost:$LOCAL_PORT/?authSource=$AUTH_DB" --quiet <<EOF
db.runCommand({ ping: 1 })
EOF
echo "βœ… Connection verified!"
}
# =========[ Help ]=========
function show_help() {
cat <<EOF
🧰 Usage: $0 [command]
Commands:
setup Create a kind cluster using Podman CLI on macOS with Ingress and MongoDB volume
teardown Delete the kind cluster and optionally remove the Podman VM\
connect Port-forward MongoDB to localhost and verify connection via mongosh
help Show this help message
Environment Variables:
PODMAN_MACHINE_NAME Name of the Podman VM (default: podman-machine-default)
EXTRA_PORT_RANGE Extra NodePort range to expose (default: 30000-30010)
KIND_HOST_VOLUME_DIR Host directory for MongoDB volume (default: ~/kind-volumes/mongodb)
Access:
- Ingress β†’ http://localhost:8081
- MongoDB β†’ mongodb://localhost:27017
- MongoDB data β†’ persisted at \$KIND_HOST_VOLUME_DIR
Examples:
KIND_HOST_VOLUME_DIR=~/data/mongo ./kind-podman-tool.sh setup
PODMAN_MACHINE_NAME=devbox ./kind-podman-tool.sh setup
EOF
}
# =========[ Entry Point ]=========
case "$1" in
setup)
setup_cluster
;;
teardown)
teardown_cluster
;;
help|"")
show_help
;;
connect|"")
connect
;;
*)
echo "❌ Unknown command: '$1'"
show_help
exit 1
;;
esac
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment