feat: 로컬 kind 개발 클러스터(yakcloud dev) — 개발 후 운영까지 직선 배포
yakcloud dev up|deploy|status|clean|down. 로컬 kind 를 dev 구간으로 삼아 관리형과 동일한 바인딩 env 계약을 로컬에서 재현(pg/mysql/mariadb/mongodb/redis). dev 에선 CLI 가 곧 컨트롤플레인 이라 오프라인 반복. 같은 매니페스트·같은 이미지로 promote --to val/prod 직선. VERSION 0.14.0. 문서 동시 갱신(SKILL·/yakcloud 명령·yakcloud.yaml·README·DATA-SOURCES). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
88
bin/yakcloud
88
bin/yakcloud
@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env bash
|
||||
# yakcloud — YakCloud 프로젝트 CLI. 개발·검증·운영 모두 yakcloud 클러스터(로컬 dev 없음, val 선택).
|
||||
# yakcloud — YakCloud 프로젝트 CLI. 개발=로컬 kind(직선 dev) 또는 yakcloud 클러스터, 검증·운영=yakcloud 클러스터(val 선택).
|
||||
#
|
||||
# yakcloud cluster create <name> [--template S|M] [--nodes N] [--golden] 클러스터 생성(완료까지 대기)
|
||||
# yakcloud cluster ls 내 클러스터 목록
|
||||
@ -16,7 +16,11 @@ set -uo pipefail # -e 미사용: 'test && action' 관용구가 값 없을 때
|
||||
|
||||
REPO="${YAKCLOUD_STARTER_REPO:-https://gitea.yakenator.io/yakenator/yakcloud-starter}"
|
||||
BRANCH="${YAKCLOUD_STARTER_BRANCH:-main}"
|
||||
VERSION="0.13.0"
|
||||
VERSION="0.14.0"
|
||||
# 로컬 개발 클러스터(kind) — 개발 후 운영까지 '직선 배포'의 dev 구간.
|
||||
DEV_CTX="${YAK_DEV_CONTEXT:-kind-yak-dev}"
|
||||
DEV_CLUSTER="${YAK_DEV_CLUSTER:-yak-dev}"
|
||||
INGRESS_MANIFEST="${YAK_DEV_INGRESS:-https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.11.3/deploy/static/provider/kind/deploy.yaml}"
|
||||
CONFIG_DIR="${YAKCLOUD_CONFIG_DIR:-$HOME/.config/yakcloud}"
|
||||
CONFIG_FILE="$CONFIG_DIR/config"
|
||||
|
||||
@ -381,6 +385,77 @@ PY
|
||||
esac
|
||||
}
|
||||
|
||||
# ── 로컬 개발 클러스터(kind) — '개발 후 운영까지 직선 배포'의 dev 구간 ─────────────
|
||||
# dev up 로컬 kind 생성 + 인그레스(80/443) — 최초 1회
|
||||
# dev deploy 매니페스트대로 이미지 빌드+kind load + 소스/워크로드/인그레스 로컬 리컨실(콘솔 API 불필요)
|
||||
# dev status 로컬 배포 상태 · dev clean 이 프로젝트 리소스만 삭제 · dev down kind 클러스터 삭제
|
||||
# 로컬 dev = CLI 로컬 완결(오프라인 반복). 같은 이미지를 push 하면 promote --to val/prod 로 그대로 직선.
|
||||
_dev_runtime() {
|
||||
if command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1; then echo docker; return; fi
|
||||
if command -v podman >/dev/null 2>&1 && podman info >/dev/null 2>&1; then echo podman; return; fi
|
||||
echo ""
|
||||
}
|
||||
|
||||
cmd_dev_up() {
|
||||
command -v kind >/dev/null 2>&1 || die "kind 필요 — 'brew install kind' (https://kind.sigs.k8s.io)"
|
||||
command -v kubectl >/dev/null 2>&1 || die "kubectl 필요"
|
||||
local rt; rt="$(_dev_runtime)"; [ -n "$rt" ] || die "docker 또는 podman 데몬이 실행 중이어야 합니다."
|
||||
local kenv=""; [ "$rt" = podman ] && kenv="KIND_EXPERIMENTAL_PROVIDER=podman"
|
||||
if env $kenv kind get clusters 2>/dev/null | grep -qx "$DEV_CLUSTER"; then
|
||||
info "kind 클러스터 '$DEV_CLUSTER' 이미 존재 → 재사용 ($rt)"
|
||||
else
|
||||
info "kind 클러스터 '$DEV_CLUSTER' 생성 ($rt) — 인그레스 80/443 host 매핑…"
|
||||
env $kenv kind create cluster --name "$DEV_CLUSTER" --config - <<'EOF' || die "kind 생성 실패"
|
||||
kind: Cluster
|
||||
apiVersion: kind.x-k8s.io/v1alpha4
|
||||
nodes:
|
||||
- role: control-plane
|
||||
kubeadmConfigPatches:
|
||||
- |
|
||||
kind: InitConfiguration
|
||||
nodeRegistration:
|
||||
kubeletExtraArgs:
|
||||
node-labels: "ingress-ready=true"
|
||||
extraPortMappings:
|
||||
- { containerPort: 80, hostPort: 80, protocol: TCP }
|
||||
- { containerPort: 443, hostPort: 443, protocol: TCP }
|
||||
EOF
|
||||
fi
|
||||
info "ingress-nginx 설치/확인…"
|
||||
kubectl --context "$DEV_CTX" apply -f "$INGRESS_MANIFEST" >/dev/null 2>&1 \
|
||||
|| warn_line "ingress-nginx 매니페스트 적용 경고(네트워크 확인). 이미 설치돼 있으면 무시."
|
||||
# 컨트롤러 파드가 아직 안 생겼을 때 'kubectl wait' 는 즉시 에러 → rollout status 로 견고하게 대기(짧은 초기 유예).
|
||||
sleep 3
|
||||
kubectl --context "$DEV_CTX" -n ingress-nginx rollout status deploy/ingress-nginx-controller --timeout=180s >/dev/null 2>&1 \
|
||||
|| warn_line "ingress 컨트롤러 준비 지연 — 잠시 후 'yakcloud dev deploy'."
|
||||
echo "✓ 로컬 dev 클러스터 준비 ($DEV_CTX). 다음: yakcloud dev deploy"
|
||||
}
|
||||
warn_line() { echo " ⚠ $*" >&2; }
|
||||
|
||||
cmd_dev() {
|
||||
local sub="${1:-}"; [ "$#" -gt 0 ] && shift
|
||||
case "$sub" in
|
||||
up) cmd_dev_up "$@" ;;
|
||||
deploy|status|clean)
|
||||
[ -f scripts/yakcloud_dev.py ] || die "프로젝트 폴더가 아닙니다 — 'yakcloud project init' 먼저"
|
||||
[ -f yakcloud.yaml ] || die "yakcloud.yaml 없음"
|
||||
ensure_pyyaml
|
||||
local rt tag=""; rt="$(_dev_runtime)"
|
||||
for a in "$@"; do case "$a" in -*) : ;; *) [ -z "$tag" ] && tag="$a" ;; esac; done
|
||||
local pysub="$sub"; [ "$sub" = clean ] && pysub="down"
|
||||
YAK_DEV_CONTEXT="$DEV_CTX" YAK_DEV_CLUSTER="$DEV_CLUSTER" YAK_DEV_RUNTIME="${rt:-docker}" \
|
||||
TAG="${tag:-${TAG:-dev}}" python3 scripts/yakcloud_dev.py "$pysub" yakcloud.yaml
|
||||
;;
|
||||
down)
|
||||
command -v kind >/dev/null 2>&1 || die "kind 필요"
|
||||
local rt kenv=""; rt="$(_dev_runtime)"; [ "$rt" = podman ] && kenv="KIND_EXPERIMENTAL_PROVIDER=podman"
|
||||
info "kind 클러스터 '$DEV_CLUSTER' 삭제…"
|
||||
env $kenv kind delete cluster --name "$DEV_CLUSTER" && echo "✓ 삭제 완료"
|
||||
;;
|
||||
*) echo "yakcloud dev <up|deploy [tag]|status|clean|down>"; exit 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# 전역 CLI 자기 갱신 — 버전이 같아도 항상 최신 파일을 강제로 다시 받아 덮어쓴다(캐시 우회).
|
||||
# Claude Code 전역 슬래시 명령(/yakcloud) 설치/최신화 — 설치·업그레이드 시 함께 실행.
|
||||
# opt-out: YAKCLOUD_NO_CLAUDE_CMD=1. 실패해도 CLI 동작엔 지장 없음(비치명적).
|
||||
@ -427,7 +502,8 @@ cmd_project_update() {
|
||||
mkdir -p scripts .gitea/workflows .claude/skills
|
||||
cp "$tmp/s/scripts/yakcloud_deploy.py" scripts/ 2>/dev/null || true
|
||||
cp "$tmp/s/scripts/yakcloud_ctl.py" scripts/ 2>/dev/null || true
|
||||
rm -f scripts/yakcloud_dev.py scripts/yakcloud_migrate.py # 옛 로컬 dev/migrate 잔재 제거
|
||||
cp "$tmp/s/scripts/yakcloud_dev.py" scripts/ 2>/dev/null || true # 로컬 kind 리컨실 엔진(직선 dev)
|
||||
rm -f scripts/yakcloud_migrate.py # 옛 migrate 잔재 제거
|
||||
cp "$tmp/s/.gitea/workflows/deploy.yml" .gitea/workflows/ 2>/dev/null || true
|
||||
cp "$tmp/s/DATA-SOURCES.md" DATA-SOURCES.md 2>/dev/null || true
|
||||
rm -rf .claude/skills/yakcloud-deploy
|
||||
@ -442,6 +518,11 @@ usage() {
|
||||
yakcloud $VERSION — YakCloud 프로젝트 CLI (개발·검증·운영 모두 yakcloud 클러스터, val 선택)
|
||||
cluster create <name> [--template S|M] [--nodes N] [--golden] 클러스터 생성(프로비저닝 완료까지 대기)
|
||||
cluster ls 내 클러스터 목록(이름·상태·노드·기본 도메인)
|
||||
── 로컬 개발 클러스터(kind) — 개발 후 운영까지 직선 배포의 dev 구간 ──
|
||||
dev up 로컬 kind 생성 + 인그레스(80/443) — 최초 1회
|
||||
dev deploy [tag] 매니페스트대로 로컬 리컨실(이미지 빌드+load, 소스/워크로드/인그레스; 콘솔 API 불필요)
|
||||
dev status | dev clean 로컬 배포 상태 / 이 프로젝트 리소스 삭제
|
||||
dev down 로컬 kind 클러스터 삭제
|
||||
project init [name] 빈 폴더에 스타터 스캐폴딩(대화형 마법사) + 자격 프롬프트
|
||||
project deploy [vX.Y.Z] 커밋 + 태그 push → CI 빌드 → **개발 클러스터** 배포(버전 생략=자동 버전업)
|
||||
project deploy --local 러너 없이 로컬 build/push/리컨실(CI 대안, 개발 클러스터)
|
||||
@ -481,6 +562,7 @@ case "${1:-help}" in
|
||||
*) echo "yakcloud project <init|deploy|promote|info|check|update>"; exit 1 ;;
|
||||
esac ;;
|
||||
cluster) shift; cmd_cluster "$@" ;;
|
||||
dev) shift; cmd_dev "$@" ;;
|
||||
login) cmd_login ;;
|
||||
config) cmd_config ;;
|
||||
logout) cmd_logout ;;
|
||||
|
||||
Reference in New Issue
Block a user