DevPod Developer Workspaces
DevPod 개발자 워크스페이스 (DevPod Developer Workspaces)
Section titled “DevPod 개발자 워크스페이스 (DevPod Developer Workspaces)”회사 개발자가 본인 로컬 VS Code에서 Microsoft 계정으로 프로젝트 워크스페이스에 연결하는 방법을 설명합니다. 워크스페이스는 당신 개인 네임스페이스 안의 파드로 뜨고, 안에는 claude / codex / agy CLI와 매칭 VS Code 익스텐션이 들어 있으며, 모델 트래픽은 per-employee 계측을 거쳐 cliproxy로 라우팅됩니다.
무엇인가 (What it is)
Section titled “무엇인가 (What it is)”Portal launch -> workspace record -> controller devpod up -> Keycloak(Microsoft 로그인) -> kube-api.yamon.io -> 내 네임스페이스의 워크스페이스 파드- DevPod: OIDC 게이트가 걸린, 레포 바인딩된 개발 환경입니다. 컨트롤러가 공식 loft-sh
devpodCLI와 kubernetes provider로 workspace pod를 materialize하고, 사용자는 준비된 workspace에 attach합니다. - 워크스페이스는 당신 전용 네임스페이스(
fops-dev-default-<project>-<employee>-<hash>)의 파드로 실행됩니다. 같은 프로젝트/레포/브랜치라도 직원별workspace_name,provider_name, namespace가 분리됩니다. - Daytona와의 경계: Daytona는 에이전트 샌드박스와 자동 작업 실행면입니다. DevPod는 사람이 본인 OIDC 신원으로 들어가는 개발 워크스페이스입니다.
사전 준비 (Prerequisites)
Section titled “사전 준비 (Prerequisites)”로컬에 다음을 설치하세요.
- DevPod Desktop (또는
devpodCLI) — 공식 배포본 (https://devpod.sh) - DevPod VS Code 익스텐션
kubectl+oidc-login(kubelogin) 플러그인 — Keycloak/Microsoft 토큰으로 kube-apiserver에 인증하는 데 필요합니다.
연결 절차 (Connect flow)
Section titled “연결 절차 (Connect flow)”-
Portal에서 본인 프로젝트를 열고 DevPod connect 액션을 사용합니다. 백엔드는 principal을 확인한 뒤 SpiceDB
CheckPermission으로 프로젝트/직원/워크스페이스 권한을 판정하고, 허용된 요청만 Proposal/Temporal queue에 workspace lease로 기록합니다. 컨트롤러는 pending lease를 공식 DevPod CLI로 materialize합니다. 백엔드는 연결/진단용 material도 제공합니다.provider.yaml(kubernetes driver, cliproxy 라우팅 env)- OIDC exec(oidc-login) kubeconfig
- 수동 재현이 필요할 때만 실행할
devpod up명령 - 발급 경로:
GET /v1/portal/launches/devpod/provider.yaml?workspace_scope=...,GET /v1/portal/launches/devpod/kubeconfig?workspace_scope=...(공유 launch 경로GET /v1/portal/launches/{solution_id}에서 provider=devpod 로 연결 자료를 받습니다). 두 material endpoint는 Pomerium/Portal principal 뒤에서 tenant + workspace owner를 확인하고, SpiceDB가 허용한 lease scope만 반환합니다. - 관리 경로:
GET /v1/portal/launches/devpod/workspaces는 본인 DevPod workspace record만 나열하고, 각 item의reconnect_material에 provider/kubeconfig URL,devpod provider add,devpod up, MCP loadout, 사용량 링크를 함께 싣습니다.DELETE /v1/portal/launches/devpod/workspaces/{workspace_scope}는 본인 record를release_requested로 전환하고 같은 workspace shape을 반환합니다. 컨트롤러가 공식devpod stop을 실행하고 성공하면suspended가 됩니다. 다시 launch하면 같은 프로젝트/레포/브랜치/직원 identity로 재큐됩니다. - Portal 프로젝트 저장소 launch 패널은 같은 경로를 사용해 DevPod workspace 생성, refresh, stop, provider/kubeconfig, 사용량 링크를 한 화면에 보여줍니다.
-
워크스페이스 상태가
ready가 되면 제공된 material로 접속합니다. 일반 사용자 흐름은 이미 떠 있는 workspace에 attach하는 것이고, 로컬에서 수동 재현이 필요할 때만 같은 명령을 실행합니다.Terminal window # Portal이 제공하는 provider.yaml URL로 provider 추가devpod provider add <provider_yaml_url> --name <provider_name># 프로젝트@브랜치로 워크스페이스 updevpod up <project>@<branch> --provider <provider_name> --ide openvscode -
브라우저가 열립니다 → Keycloak → “Sign in with Microsoft”(Entra federation) → kube-apiserver(
https://kube-api.yamon.io)가 토큰을 검증 → Kubernetes RBAC가 이미 SpiceDB에서 허용된 본인 네임스페이스로 실행면을 스코핑합니다.- kubeconfig의
oidc-loginclient는 Headlamp와 같은 kube-access client(headlamp)입니다. Pomerium/웹 IDE용devpodclient와 섞지 않습니다.
- kubeconfig의
-
DevPod가 워크스페이스 파드(FractalOps 골든 devcontainer)를 만들고, 로컬 VS Code가 거기에 연결됩니다.
flowchart LR vscode["로컬 VS Code\n+ DevPod 익스텐션"] -->|Portal command| launch["Portal launch\nemployee-scoped workspace"] launch --> lease["Proposal/Temporal queue\nworkspace lease"] lease --> controller["DevPod controller\nofficial devpod CLI"] controller --> ns["fops-dev-default-<project>-<employee>-<hash>\n워크스페이스 파드 (골든 devcontainer)"] launch --> material["provider.yaml\n+ oidc-login kubeconfig"] material -->|attach/manual fallback| vscode vscode --> kc["Keycloak\nSign in with Microsoft (Entra)"] kc --> api["kube-api.yamon.io\n(apiserver: 토큰 검증)"] api -->|RBAC scope| ns ns --> vscode
워크스페이스 안에는 무엇이 있나 (What is inside)
Section titled “워크스페이스 안에는 무엇이 있나 (What is inside)”claude/codex/agy(Antigravity) CLI + 매칭 VS Code 익스텐션(Claude Code, Codex/ChatGPT).agybinary는 워크스페이스 로드아웃에 포함되지만, DevPod smoke와 중앙 계측은 nativeagyOAuth가 아니라 CLIProxy의 Antigravity 채널을 검증합니다.- 모델 트래픽은 전부 중앙 cliproxy로 라우팅되며, per-employee 계측기(
<meter>/u/<employee-slug>)를 거칩니다 — 사용량이 당신에게 귀속됩니다(fops_devpod_tokens{fops_employee}/fops_devpod_requests{fops_employee}메트릭). - Launch payload와 workspace list payload는
usage_observability를 포함합니다. 여기에는employee_slug, meter path, Grafana dashboard UID(devpod-token-spend), dashboard path, dashboard URL, metric names, employee label이 들어 있습니다. workspace list item은 같은 값을reconnect_material.usage_observability에도 싣습니다. 프론트엔드는 이 값을 그대로 사용하고 metric 이름/label을 재합성하지 않습니다. claude는ANTHROPIC_BASE_URL+ANTHROPIC_AUTH_TOKEN,codex는OPENAI_BASE_URL+OPENAI_API_KEY+ 실행 시--config openai_base_url=...를 사용합니다. Antigravity는 DevPod smoke에서agybinary 존재를 확인한 뒤fractalops-antigravityalias를 per-employee meter의 CLIProxy Anthropic-compatible API로 호출합니다. nativeagyOAuth bundle을 워크스페이스에 주입하지 않으므로 사용자별 meter URL/token은 DevPod provider env에서 런타임 바인딩되고, 에이전트나 사용자가 바뀔 때 이미지를 다시 빌드하지 않습니다. 이미지의fractalops-cli-wrapper도 같은 계약을 한 번 더 보정합니다.CLIPROXY_CLIENT_API_KEY가 없으면 provider material 생성이devpod_cliproxy_client_token_missing으로 실패합니다. base URL만 있는 워크스페이스를 띄워 CLI가 나중에 인증 실패하는 상태를 허용하지 않습니다.- 중앙 cliproxy는 OSS CLIProxyAPI plane입니다. OAuth 계정, load balancing,
oauth-model-alias, excluded model, quota-exceeded reroute,/v1/models, log/management는 중앙 plane이 맡습니다. DevPod는 모델 목록, quota, upstream account 상태를 추론하지 않고, 그 plane을 향한 사용자별 endpoint/token/Armory 설정만 reconcile합니다. - CLIProxyAPI Web UI는 본체가 제공하는
/management.html을 우선 사용하고, Management API(/v0/management)를 통해 config/credentials/logs를 다룹니다. 중앙 plane의 config/auth state는 공식PGSTORE_DSN으로 CNPG에 저장되므로 사용자/계정 바인딩 때문에 DevPod나 agent 이미지를 다시 빌드하지 않습니다. - 모델 / reasoning-effort / 속도는 cliproxy와 CLI가 결정합니다. 익스텐션 UI나 CLI 플래그가 요청을 보내면 cliproxy가 현재 등록된 계정/alias/quota 기준으로 라우팅합니다. DevPod 이미지와 provider material은 모델을 핀하지 않습니다.
- Armory MCP 서버가 런타임 바인딩됩니다(
FRACTALOPS_DEVPOD_MCP_CONFIG_JSON->.mcp.json+ codex/agy 등가 설정). launch 때 선택된 서버 목록과 config가 workspace metadata에 저장되므로 controller reconcile이 같은 Armory loadout을 재생합니다. MCP 인증은 per-user OIDC로 Armory 게이트웨이/ContextForge 엣지에서 수행됩니다 — 베이크된 토큰 없음(당신이 본인 신원으로 OIDC 플로우를 탑니다). - DevPod controller/workspace image pin은 base chart가 아니라
platform/k8s/environments/lxc-pve-lab/runtime.cue와 generated values(values/devpod-developer-workspaces.yaml)가 소유합니다. Runtime GitOps bump도 같은 CUE source와 generated overlay만 갱신하므로 직원/agent/model 바인딩 변경 때문에 이미지를 다시 빌드하지 않습니다. - DevPod devcontainer startup은 공식 prebuild consumer 경로를 씁니다. Portal launch material과 controller reconcile은
FRACTALOPS_DEVPOD_PREBUILD_REPOSITORY를devpod up --prebuild-repository로 전달합니다. DevPod는devpod-<hash>태그가 있으면 그 이미지를 사용하고, 없으면 기존처럼 빌드로 degrade합니다. prebuild producer는 같은 repository에 공식devpod build ... --repository <repo>로 태그를 채워야 합니다. openvscodeIDE는 golden workspace image 안의/home/devuser/.openvscode-server/bin/openvscode-server를 사용합니다. workspace startup 중 GitHub release tarball을 받지 않습니다.- 워크스페이스 scratch disk는
FRACTALOPS_DEVPOD_WORKSPACE_DISK_SIZE,FRACTALOPS_DEVPOD_WORKSPACE_STORAGE_CLASS,FRACTALOPS_DEVPOD_WORKSPACE_DISK_ACCESS_MODE/ chartprovider.workspaceDisk*가 소유합니다. provider.yaml 경계에서만 공식 DevPodagent.kubernetes.diskSize,storageClass,pvcAccessMode로 렌더링됩니다. 이전persistentVolumeSize명칭은 쓰지 않습니다. ops-runtime-control.yml의devpod-launch-proof는 launch/provider/workspace list를 지나 실제 workspace PVC까지 검사합니다. provider material과 live PVC가10Gi,fractalops-scratch,RWO를 만족하지 않으면workspace_scratch_disk_ready=true가 나오지 않고 proof가 실패합니다. Proof용 임시 workspace는 준비 완료와 scratch disk 검증 뒤DELETE /v1/portal/launches/devpod/workspaces/{workspace_scope}를 호출해release_requested로 돌려 찌꺼기를 남기지 않습니다.
수명 / TTL (Lifecycle)
Section titled “수명 / TTL (Lifecycle)”- 유휴 워크스페이스는 비활성 타임아웃(공식 DevPod
INACTIVITY_TIMEOUT, 기본 약 30분) 이후 자동 정지됩니다. 이것은 커스텀 reaper가 아니라 DevPod kubernetes provider의 공식 auto-stop입니다. - DevPod kubernetes provider는 workspace disk를 Kubernetes PVC 필드로 구현하지만, FractalOps 내부 언어에서는 이를 scratch workspace disk로만 취급합니다. 기본값은
10Gi,fractalops-scratch,RWO이며 durable state는 Git/Nexus/CNPG/object storage에 둡니다. - 컨트롤러는
readyworkspace record도 가볍게 관찰합니다. 같은DEVPOD_WORKSPACE_ID를 가진 DevPod pod/PVC가 여러 개 남으면 최신 ready pod와 그 PVC만 보존하고, older sibling pod/PVC를 정리합니다. 이것은 user home 보존 정책을 바꾸지 않는 duplicate-resource janitor입니다. - 컨트롤러 상태는
https://devpod.yamon.io/healthz에서 확인합니다. 응답에는reconcile_enabled,reconcile_interval_seconds,reconcile_in_progress,last_reconcile_started_at,last_reconcile_at,last_reconcile_error,last_reconcile.processed/ready/stopped/errored/stale_provisioning/cleaned_workspace_resources/workspace_cleanup_errors,pending_sample_scopes,release_sample_scopes,provisioning_sample_scopes가 포함됩니다. HTTP 200만으로 완료 판단하지 말고reconcile_in_progress,last_reconcile_error,errored,stale_provisioning,workspace_cleanup_errors를 같이 봅니다. - 공식 DevPod CLI 호출은 컨트롤러에서
FRACTALOPS_DEVPOD_CLI_TIMEOUT_SECONDS(기본 300초)로 제한합니다. 컨트롤러는 공식devpod up에--open-ide=false를 붙여 서버 reconcile이 로컬 IDE open까지 시도하지 않게 합니다. 컨트롤러 재시작이나 kill 때문에provisioning이 남으면FRACTALOPS_DEVPOD_PROVISIONING_STALE_SECONDS(기본 420초) 이후error로 회수합니다.
접근 권한 (Access)
Section titled “접근 권한 (Access)”워크스페이스는 SpiceDB 관계 그래프의 프로젝트 역할에 따라 제공됩니다.
| 역할 | 워크스페이스 |
|---|---|
| owner | 제공 |
| maintainer | 제공 |
| contributor | 제공 |
| viewer | 제공 안 함 |
접근 SSOT는 SpiceDB입니다(devpod_viewer_only / devpod_project_access_denied). Keycloak과 Pomerium은 신원/세션을 제공하고, Kubernetes RBAC는 이미 허용된 네임스페이스 실행면을 강제합니다. viewer는 프로젝트를 볼 수는 있어도 개발자 워크스페이스는 받지 못합니다.
트러블슈팅 (Troubleshooting)
Section titled “트러블슈팅 (Troubleshooting)”- 로그인/토큰 문제:
kubectl oidc-login토큰을 다시 받거나(kubectl oidc-login get-token ...재실행) 캐시된 토큰을 지우세요. 그래도 안 되면 브라우저에서 Microsoft 로그인을 다시 완료하세요. - 이미지 풀 실패 / 네임스페이스 미준비: 컨트롤러가 당신의 네임스페이스 + 풀 시크릿을 프로비저닝하는 중일 수 있습니다. 잠시 후
devpod up을 재시도하세요. - 워크스페이스가 아직 안 뜸: Portal launch 직후 상태는
pending입니다. 컨트롤러가 공식 DevPod CLI로provisioning→ready까지 진행합니다.provisioning_sample_scopes에 보이면 실제 작업 중이고, timeout/stale window를 넘으면error와last_error로 확정됩니다. 실패한error상태는 다시 launch하면pending으로 재큐됩니다. - 워크스페이스 정지가 안 끝남: stop 요청 직후 상태는
release_requested입니다. 컨트롤러가releasing으로 바꾸고 공식devpod stop성공 시suspended로 닫습니다.release_sample_scopes에 계속 남아 있으면 컨트롤러 reconcile이 아직 명령을 잡지 못한 상태입니다. - resume 지연: 자동 정지 후 resume은 보통 약 90초가 걸립니다(파드 재시작 + PVC 재연결). 정상입니다.
- connect가 계속 실패: 롤아웃 중일 수 있습니다 — 플랫폼 팀에 문의하세요.
참고 (References)
Section titled “참고 (References)”- CLIProxyAPI 공식 문서: https://router-for-me-cliproxyapi.mintlify.app/introduction
- CLIProxyAPI GitHub: https://github.com/router-for-me/CLIProxyAPI
- CLIProxyAPI Management Center: https://github.com/router-for-me/Cli-Proxy-API-Management-Center
- 아키텍처 맥락: Workspace Access Contract, Dev Preview Plane, Project Dev Service Plane
- 운영 맥락: Engineering Handoff