feat(dev): 로컬 kind 워커 노드 추가(dev up --workers N + environments.dev.workers) — 0.22.0

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-08-30 18:41:16 +09:00
parent 922f8157fd
commit bb0295a527
2 changed files with 17 additions and 6 deletions

View File

@ -16,7 +16,7 @@ set -uo pipefail # -e 미사용: 'test && action' 관용구가 값 없을 때
REPO="${YAKCLOUD_STARTER_REPO:-https://gitea.yakenator.io/yakenator/yakcloud-starter}" REPO="${YAKCLOUD_STARTER_REPO:-https://gitea.yakenator.io/yakenator/yakcloud-starter}"
BRANCH="${YAKCLOUD_STARTER_BRANCH:-main}" BRANCH="${YAKCLOUD_STARTER_BRANCH:-main}"
VERSION="0.21.4" VERSION="0.22.0"
# 로컬 개발 클러스터(kind) — 개발 후 운영까지 '직선 배포'의 dev 구간. # 로컬 개발 클러스터(kind) — 개발 후 운영까지 '직선 배포'의 dev 구간.
DEV_CTX="${YAK_DEV_CONTEXT:-kind-yak-dev}" DEV_CTX="${YAK_DEV_CONTEXT:-kind-yak-dev}"
DEV_CLUSTER="${YAK_DEV_CLUSTER:-yak-dev}" DEV_CLUSTER="${YAK_DEV_CLUSTER:-yak-dev}"
@ -467,7 +467,7 @@ _podman_auth_fix() {
# --name dev2 --port N → kind 'yak-dev2', ctx 'kind-yak-dev2', 등록명 <host>-dev2, 인그레스 N (80은 기본 클러스터 몫) # --name dev2 --port N → kind 'yak-dev2', ctx 'kind-yak-dev2', 등록명 <host>-dev2, 인그레스 N (80은 기본 클러스터 몫)
# 나머지 인자(태그 등)는 DEV_ARGS 배열에 남긴다(--name 값이 태그로 오인되지 않게 여기서 소비). # 나머지 인자(태그 등)는 DEV_ARGS 배열에 남긴다(--name 값이 태그로 오인되지 않게 여기서 소비).
_dev_resolve() { _dev_resolve() {
DEV_NAME="dev"; DEV_HTTP_PORT="80"; DEV_PORT_EXPLICIT=0; DEV_ARGS=() DEV_NAME="dev"; DEV_HTTP_PORT="80"; DEV_PORT_EXPLICIT=0; DEV_WORKERS=0; DEV_ARGS=()
while [ "$#" -gt 0 ]; do while [ "$#" -gt 0 ]; do
case "$1" in case "$1" in
--name|--cluster) DEV_NAME="${2:-}"; shift 2 || shift ;; --name|--cluster) DEV_NAME="${2:-}"; shift 2 || shift ;;
@ -475,9 +475,14 @@ _dev_resolve() {
--cluster=*) DEV_NAME="${1#--cluster=}"; shift ;; --cluster=*) DEV_NAME="${1#--cluster=}"; shift ;;
--port) DEV_HTTP_PORT="${2:-}"; DEV_PORT_EXPLICIT=1; shift 2 || shift ;; --port) DEV_HTTP_PORT="${2:-}"; DEV_PORT_EXPLICIT=1; shift 2 || shift ;;
--port=*) DEV_HTTP_PORT="${1#--port=}"; DEV_PORT_EXPLICIT=1; shift ;; --port=*) DEV_HTTP_PORT="${1#--port=}"; DEV_PORT_EXPLICIT=1; shift ;;
--workers|--worker) DEV_WORKERS="${2:-0}"; shift 2 || shift ;;
--workers=*) DEV_WORKERS="${1#--workers=}"; shift ;;
--worker=*) DEV_WORKERS="${1#--worker=}"; shift ;;
*) DEV_ARGS+=("$1"); shift ;; *) DEV_ARGS+=("$1"); shift ;;
esac esac
done done
case "$DEV_WORKERS" in ''|*[!0-9]*) DEV_WORKERS=0 ;; esac
[ "$DEV_WORKERS" -gt 5 ] && DEV_WORKERS=5 # 노트북 자원 보호(과도한 노드 방지)
DEV_NAME="$(printf '%s' "$DEV_NAME" | tr '[:upper:]' '[:lower:]' | tr -cs 'a-z0-9-' '-' | sed 's/^-*//; s/-*$//')" DEV_NAME="$(printf '%s' "$DEV_NAME" | tr '[:upper:]' '[:lower:]' | tr -cs 'a-z0-9-' '-' | sed 's/^-*//; s/-*$//')"
[ -z "$DEV_NAME" ] && DEV_NAME="dev" [ -z "$DEV_NAME" ] && DEV_NAME="dev"
DEV_CLUSTER="${YAK_DEV_CLUSTER:-yak-$DEV_NAME}" DEV_CLUSTER="${YAK_DEV_CLUSTER:-yak-$DEV_NAME}"
@ -500,10 +505,14 @@ cmd_dev_up() {
if [ "$DEV_HTTP_PORT" -lt 1 ] || [ "$DEV_HTTP_PORT" -gt 65535 ]; then if [ "$DEV_HTTP_PORT" -lt 1 ] || [ "$DEV_HTTP_PORT" -gt 65535 ]; then
die "포트는 1-65535 범위여야 합니다: '$DEV_HTTP_PORT'" die "포트는 1-65535 범위여야 합니다: '$DEV_HTTP_PORT'"
fi fi
info "kind 클러스터 '$DEV_CLUSTER' 생성 ($rt) — 인그레스 http 포트 ${DEV_HTTP_PORT}…" local nw="${DEV_WORKERS:-0}"
info "kind 클러스터 '$DEV_CLUSTER' 생성 ($rt) — 인그레스 http 포트 ${DEV_HTTP_PORT}, 워커 ${nw}개…"
local ports=" - { containerPort: 80, hostPort: ${DEV_HTTP_PORT}, protocol: TCP }" local ports=" - { containerPort: 80, hostPort: ${DEV_HTTP_PORT}, protocol: TCP }"
[ "$DEV_HTTP_PORT" = "80" ] && ports="$ports [ "$DEV_HTTP_PORT" = "80" ] && ports="$ports
- { containerPort: 443, hostPort: 443, protocol: TCP }" - { containerPort: 443, hostPort: 443, protocol: TCP }"
# 워커 노드(N개) — 인그레스는 CP(ingress-ready 라벨·포트매핑) 몫이라 워커는 순수 워크로드 스케줄 대상.
local workers=""
[ "$nw" -gt 0 ] && workers="$(for _ in $(seq 1 "$nw"); do echo "- role: worker"; done)"
env $kenv kind create cluster --name "$DEV_CLUSTER" --config - <<EOF || die "kind 생성 실패(포트 ${DEV_HTTP_PORT} 가 이미 사용 중일 수 있음)" env $kenv kind create cluster --name "$DEV_CLUSTER" --config - <<EOF || die "kind 생성 실패(포트 ${DEV_HTTP_PORT} 가 이미 사용 중일 수 있음)"
kind: Cluster kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4 apiVersion: kind.x-k8s.io/v1alpha4
@ -517,6 +526,7 @@ nodes:
node-labels: "ingress-ready=true" node-labels: "ingress-ready=true"
extraPortMappings: extraPortMappings:
${ports} ${ports}
${workers}
EOF EOF
fi fi
info "ingress-nginx 설치/확인…" info "ingress-nginx 설치/확인…"
@ -663,10 +673,11 @@ cmd_dev() {
case "$sub" in case "$sub" in
up|deploy|status|clean) up|deploy|status|clean)
if [ "$name_given" = 0 ] && [ -f yakcloud.yaml ]; then if [ "$name_given" = 0 ] && [ -f yakcloud.yaml ]; then
local _mn _mp; _mn="$(_manifest_env dev cluster 2>/dev/null)"; _mp="$(_manifest_env dev port 2>/dev/null)" local _mn _mp _mw; _mn="$(_manifest_env dev cluster 2>/dev/null)"; _mp="$(_manifest_env dev port 2>/dev/null)"; _mw="$(_manifest_env dev workers 2>/dev/null)"
if [ -n "$_mn" ]; then if [ -n "$_mn" ]; then
local _inj=(--name "$_mn") local _inj=(--name "$_mn")
{ [ -n "$_mp" ] && [ "$_mp" != "80" ]; } && _inj+=(--port "$_mp") { [ -n "$_mp" ] && [ "$_mp" != "80" ]; } && _inj+=(--port "$_mp")
case " $* " in *" --worker"*) : ;; *) { [ -n "$_mw" ] && [ "$_mw" != "0" ]; } && _inj+=(--workers "$_mw") ;; esac
set -- "${_inj[@]}" "$@"; name_given=1 set -- "${_inj[@]}" "$@"; name_given=1
fi fi
fi fi
@ -755,7 +766,7 @@ yakcloud $VERSION — YakCloud 프로젝트 CLI (개발·검증·운영 모두
cluster create <name> [--template S|M] [--nodes N] [--golden] 클러스터 생성(프로비저닝 완료까지 대기) cluster create <name> [--template S|M] [--nodes N] [--golden] 클러스터 생성(프로비저닝 완료까지 대기)
cluster ls 내 클러스터 목록(이름·상태·노드·기본 도메인) cluster ls 내 클러스터 목록(이름·상태·노드·기본 도메인)
── 로컬 개발 클러스터(kind) — 개발 후 운영까지 직선 배포의 dev 구간 ── ── 로컬 개발 클러스터(kind) — 개발 후 운영까지 직선 배포의 dev 구간 ──
dev up 로컬 kind 생성 + 인그레스(80/443) — 최초 1회 dev up [--workers N] 로컬 kind 생성 + 인그레스(80/443) — 최초 1회. --workers N=워커 노드 추가(기본 0=CP만, 매니페스트 environments.dev.workers 도 가능)
dev deploy [tag] 매니페스트대로 로컬 리컨실(이미지 빌드+load, 소스/워크로드/인그레스; 콘솔 API 불필요) dev deploy [tag] 매니페스트대로 로컬 리컨실(이미지 빌드+load, 소스/워크로드/인그레스; 콘솔 API 불필요)
dev ls 로컬 클러스터 목록(kind 이름 / --name / 콘솔 등록명) — 삭제 전 대상 확인 dev ls 로컬 클러스터 목록(kind 이름 / --name / 콘솔 등록명) — 삭제 전 대상 확인
dev status | dev clean 로컬 배포 상태 / 이 프로젝트 리소스 삭제 dev status | dev clean 로컬 배포 상태 / 이 프로젝트 리소스 삭제

View File

@ -12,7 +12,7 @@ project: my-app # 프로젝트 이름(이미지 경로/표
# val/prod = **관리형**. yakcloud project promote --to val|prod → 이미지 build+push(이미 있으면 재빌드 없이) 후 리컨실 + 도메인. # val/prod = **관리형**. yakcloud project promote --to val|prod → 이미지 build+push(이미 있으면 재빌드 없이) 후 리컨실 + 도메인.
# (기본 도메인 c-xxxx.yakenator.io 은 자동. 운영 커스텀 도메인은 prod.domains 에.) # (기본 도메인 c-xxxx.yakenator.io 은 자동. 운영 커스텀 도메인은 prod.domains 에.)
environments: environments:
dev: { cluster: dev, port: 80 } # 로컬 kind (project deploy). cluster=로컬 이름, port=인그레스 포트(이름!=dev면 비80) dev: { cluster: dev, port: 80 } # 로컬 kind (project deploy). cluster=로컬 이름, port=인그레스 포트(이름!=dev면 비80). 워커 추가는 workers: N (기본 0=CP만)
val: { cluster: my-val-cluster } # 관리형 (promote --to val) val: { cluster: my-val-cluster } # 관리형 (promote --to val)
prod: { cluster: my-prod-cluster, domains: [] } # 관리형 (promote --to prod, domains 예: [app.example.com]) prod: { cluster: my-prod-cluster, domains: [] } # 관리형 (promote --to prod, domains 예: [app.example.com])