dev up/deploy 가 배포토큰으로 콘솔에 로컬 클러스터를 best-effort 메타 등록/heartbeat, dev down 이 해제. 로그인 없으면 조용히 스킵(오프라인 dev 불변식). 콘솔 사이드바가 '내 로컬 클러스터'/'내 원격 클러스터'로 분리. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
11 KiB
name, description
| name | description |
|---|---|
| yakcloud-deploy | Scaffold and wire up YakCloud declarative CI/CD for a project — Gitea Actions (tag push) → build/push images → reconcile data sources → deploy workloads → bind → tenant cluster. Use when the user wants to deploy this project to YakCloud, set up the Gitea Actions workflow, create the yakcloud.yaml manifest, bind data sources, add a custom domain, or start a brand-new project from a minimal starter. |
YakCloud 배포 스킬 (선언적 CI/CD)
VS Code로 개발 → 커밋 → v* 태그 push 하면, Gitea Actions가 이미지를 빌드/푸시하고
YakCloud 콘솔 API로 데이터소스 리컨실 + 워크로드 배포 + 바인딩을 자동 처리한다.
이 스킬은 아무 프로젝트에나 이 파이프라인을 심는다. yakcloud CLI(권장) 또는 스타터 레포로
스캐폴딩하고, 매니페스트를 채운 뒤 1회 시크릿만 설정하면 끝. 빈 프로젝트면 프레임워크 중립 스타터로 바로 시작.
이 스킬은 번들 파일을 두지 않는다(SKILL.md 하나). 실제 템플릿은 CLI 또는 스타터 레포(
yakenator/yakcloud-starter)에서 온다.
언제 쓰나
- "이 프로젝트를 YakCloud에 배포/자동화" / "Gitea CI/CD 붙여줘" / "yakcloud.yaml 만들어줘"
- "새 프로젝트 시작해서 배포까지" (→
yakcloud project init) - "데이터소스(Postgres/Mongo/…) 연결/바인딩" / "커스텀 도메인으로 노출"
CLI 가 있으면 우선 사용
yakcloud CLI 가 설치돼 있으면(command -v yakcloud) 스캐폴딩/배포/환경설정을 이걸로 처리한다.
설치: curl -fsSL https://gitea.yakenator.io/yakenator/yakcloud-starter/raw/branch/main/install.sh | sh
설치 시 Claude Code 전역 슬래시 명령
/yakcloud도 함께 생성된다(~/.claude/commands/yakcloud.md). 예:/yakcloud project init my-app,/yakcloud datasource ls,/yakcloud project deploy. 이후yakcloud upgrade가 CLI와 슬래시 명령을 함께 최신화.
프로젝트 라이프사이클 (로컬 kind dev → 관리형 val/prod, 한 줄기 직선)
- "클러스터 생성" →
yakcloud cluster create <name> [--template S|M] [--nodes N] [--golden](배포토큰으로 프로비저닝, 완료까지 대기).yakcloud cluster ls로 목록. 검증/운영 클러스터를 만들어 매니페스트 environments 에 지정. - "프로젝트 초기화" → 빈 폴더에서
yakcloud project init [name](스타터+CI+매니페스트+이 스킬) - "로컬 개발"(권장 반복 루프) →
yakcloud dev up(최초 1회 — 로컬 kind 생성+인그레스) →yakcloud dev deploy.requires소스+workloads가 로컬에서 관리형과 동일한 바인딩 env로 뜬다(콘솔/CI·인터넷 불필요, 오프라인 반복).dev status/dev clean/dev down. 로그인돼 있으면 이 로컬 클러스터가 콘솔 클러스터 목록('내 로컬 클러스터')에도 자동 등록/해제된다(콘솔은 접속 않고 목록 표시만). 상세docs/local-dev-cluster.md. - "개발 배포"(관리형 개발 클러스터) →
yakcloud project deploy(자동 버전업 → 태그 push → CI 빌드 → 개발 클러스터). 기본 도메인으로 확인. - "승격"(개발→검증→운영) →
yakcloud project promote [vX.Y.Z] [--to val|prod](그 이미지를 재빌드 없이 상위 환경으로;--to prod는 운영 도메인 부착). 검증계(val)는 선택 —environments에 없으면 개발→운영 2단계 - "프로젝트 개괄" →
yakcloud project info· 사전 점검 →yakcloud project check [--env dev|val|prod] - 매니페스트
environments.{dev,val,prod}.cluster(val 선택, +prod.domains). 로컬 개발은yakcloud dev(로컬 kind), 상위 환경(val/prod)은 관리형 클러스터 — 같은 매니페스트·같은 바인딩 계약(직선 파리티).
배포환경 설정(앱별) — 매니페스트 수정 + 배포중이면 재빌드 없이 라이브 반영
yakcloud domain <fqdn> [wl]도메인 등록 + 워크로드 할당yakcloud scale <wl> <n>replicasyakcloud set <wl> --image/--port/--health/--cpu/--mem/--path/--rewriteyakcloud env <wl> KEY=VAL … [--secret KEY] [--unset KEY]yakcloud datasource ls(=source ls) 클러스터에서 이용 가능한 소스 목록(이름·타입·내부/외부·상태·플랜)yakcloud source add <name> <type> [plan]·yakcloud source rm <name>yakcloud bind <wl> <source> <alias>·yakcloud unbind <wl> <alias>
CLI 가 없거나 세밀 조정이 필요하면 아래 수동 절차를 따른다.
에이전트 실행 절차
0) 상황 파악
- 이미
yakcloud project init으로 스캐폴딩된 프로젝트면 루트에yakcloud.yaml·scripts/·.gitea/·app.py가 이미 있다 → 바로 §3 이후로. - 빈/신규면 §1, 기존 앱이면 §1-B. Gitea 원격 여부(
git remote -v)도 확인(없으면 사용자에게 레포 URL 요청).
1) 스캐폴딩 (신규/빈 프로젝트)
- CLI 있으면(권장):
yakcloud project init [name]— 앱·CI·매니페스트·이 스킬을 한 번에 생성. - CLI 없으면:
install.sh로 CLI 설치 후 init, 또는 스타터 레포에서 루트 파일을 복사:스타터 앱 = 프레임워크 무의존 최소 HTTP 서버(git clone --depth 1 https://gitea.yakenator.io/yakenator/yakcloud-starter .yc-tmp cp -R .yc-tmp/app.py .yc-tmp/Dockerfile .yc-tmp/yakcloud.yaml .yc-tmp/scripts .yc-tmp/DATA-SOURCES.md . cp -R .yc-tmp/.gitea . && rm -rf .yc-tmpPORT리슨,/healthz200). 이후 §3 매니페스트 작성.
1-B) 기존 앱에 부착
- 앱이
PORTenv로 리슨 +/healthz(또는 health 경로) 제공하는지 확인. 없으면 추가 제안. - 데이터소스 접속정보를 하드코딩하지 말고 주입 env(
<ALIAS>_URL등)로 읽도록 수정 제안. 키 규약: 루트DATA-SOURCES.md(스타터에서 복사). - 각 배포 단위마다
Dockerfile필요(없으면 언어에 맞게 생성). 베이스 이미지는 Gitea 미러(gitea.yakenator.io/yakenator/{node,python,...}). - CI/배포 플러밍(
scripts/yakcloud_deploy.py·scripts/yakcloud_ctl.py·.gitea/workflows/deploy.yml·yakcloud.yaml)은 §1 처럼 스타터 레포에서 복사(또는yakcloud project init이 대신 처리).
3) 매니페스트(yakcloud.yaml) 채우기 (핵심)
사용자와 함께 값을 정한다:
project: 프로젝트 이름(이미지 경로에 사용).cluster: 배포 대상 클러스터 이름 또는 콘솔 id (콘솔 대시보드에서 확인). 여러 개면 여기서 특정.requires: 필요한 데이터 소스 목록{ name, type, plan }. 없으면[].type∈postgresql·mysql·mariadb·mongodb·redis·minio·rabbitmq·solr·oracle,plan∈small·medium·large.- 이 이름의 소스가 클러스터에 이미 READY면 스킵, 없으면 자동 프로비저닝.
workloads[]:build: 도커 빌드 컨텍스트 경로(예./또는./api). CI가 이 컨텍스트를 빌드해image로 push.image:gitea.yakenator.io/<GITEA_USER>/<project>-<name>:${TAG}(${TAG}=릴리스 태그로 치환).port·health·replicas(≥2 권장 → 무중단 롤링)·resources{cpu,mem}.expose:{ path, rewrite, host? }—host지정 시 등록 도메인으로 노출(미지정=클러스터 기본 도메인). 여러 도메인은hosts: [a, b].binds[]:{ alias, source }—source는 위requires이름,alias는 env 프리픽스(대문자화). 예alias: db→DB_URL/DB_HOST/…주입.
4) 1회 준비 (사용자에게 안내 — 에이전트가 대신 못 함)
아래를 사용자가 설정하도록 명확히 출력:
- 배포 토큰(PAT): 콘솔 → 설정 → 배포 토큰 → 발급(
yakd_…, 한 번만 표시). 계정 스코프(어느 클러스터든). - Gitea 토큰: 스코프
read:repository+write:package+read:package. (레포 read 없으면 CIgit clone403) - 레포 시크릿(Gitea: Settings → Actions → Secrets):
이름 값 YAKCLOUD_URLhttps://console.yakenator.ioYAKCLOUD_TOKEN1의 배포 토큰( yakd_…)YAKCLOUD_CLUSTER대상 클러스터 이름/ id (생략 시 매니페스트 cluster:)REGISTRY_TOKEN2의 Gitea 토큰 - 러너: 전용 러너(라벨
ci-polyglot)가 이미 공유로 떠 있으면 레포 Actions만 켜면 됨. 없으면 GUIDE의 러너 등록 참고.
5) 배포
git add -A && git commit -m "yakcloud: CI/CD 스캐폴딩"
git push origin main
git tag v0.1.0 && git push origin v0.1.0 # v* 태그만 배포 트리거(일반 커밋은 배포 안 함)
→ Gitea Actions 탭에서 실행 확인. 성공 시 콘솔 앱 탭 / 데이터 소스 / 도메인에 반영.
로컬 사전 점검: YAKCLOUD_URL=… YAKCLOUD_TOKEN=… python3 scripts/yakcloud_deploy.py yakcloud.yaml --dry-run
6) 커스텀 도메인(선택)
콘솔 설정 → 도메인 → 도메인 추가로 등록(관리형 도메인은 즉시 Active). 매니페스트 expose.host에 지정하거나
콘솔 앱 편집 폼에서 선택. 여러 도메인은 expose.hosts: [a.example.com, b.example.com].
동작/규약 요점
- 트리거:
v*태그 push만. 일반 커밋은 배포 안 함. - 멱등/무중단: 기존 배포는 이미지 PATCH(→ kubectl apply 롤링). replicas≥2 + health면 무중단.
- 자격: 데이터소스 비밀번호/키는 인클러스터 Secret으로 주입되고 브라우저/포털에 노출되지 않음. 앱은
<ALIAS>_URL등으로 접속.
트러블슈팅(실제 겪은 것)
| 증상 | 원인 → 해결 |
|---|---|
CI git clone … 403 |
REGISTRY_TOKEN에 레포 read 없음 → read:repository 추가 |
docker create 실패(잡 시작 안 됨) |
러너 config에서 docker.sock 중복 마운트 → act 기본 마운트만(수동 제거) |
배포 중 429 RATE_LIMITED |
CLI가 retryAfterSec 백오프로 재시도(내장) |
| 다른 러너가 잡 가져감 | 라벨 충돌 → 전용 라벨(runs-on) 사용 |
소스 프로비저닝 405 |
배포 토큰엔 소스 생성 권한 없음 → (1) 인클러스터(local): 콘솔에서 소스 먼저 만들고 requires[].name·binds[].source를 그 소스명으로; (2) 공유 외부(shared, 소용량 S용): requires 에 mode: shared 선언(yakcloud source add <name> mongodb --shared; 콘솔/API 등록도 가능) → 배포 시 백엔드가 클러스터별 격리 DB/계정 민팅. yakcloud project check가 미리 경고(READY 소스 목록 출력) |
| 태그 push 했는데 아무 일도 안 남 | 레포에 러너 0개(잡이 조용히 큐잉) → yakcloud project deploy가 배포 전 러너 프리플라이트 경고. 러너 없으면 yakcloud project deploy --local(로컬 빌드·push 후 API 배포) |
헬스체크 /healthz 404/이상 |
엣지가 /healthz를 가로챔 → 배포 검증은 앱 실제 경로(/)로. 컨테이너 readiness엔 여전히 health: 사용 OK |
ModuleNotFoundError: yaml(직접 배포) |
pip install pyyaml(또는 pip3 install --break-system-packages pyyaml). CI 이미지엔 포함됨 |