Build & Package Cache Topology
빌드 & 패키지 캐시 토폴로지
Section titled “빌드 & 패키지 캐시 토폴로지”FractalOps는 패키지와 Docker Hub pull-through 캐시를 Nexus에, 재사용 가능한 OCI 빌드 레이어를 GHCR registry cache에 둡니다. 독립 registry-cache LXC(CT113 @ 10.10.10.150)는 2026-06-18에 해체됐으며 더 이상 별도 캐시 VM/LXC가 없습니다.
Nexus가 다음 패키지·pull-through 캐시를 소유합니다.
npm: Nexusnpm-grouppip: Nexuspypi-groupapt: Nexusapt-debian(ubuntu 미러를 풀 거면apt-ubuntu를 먼저 추가)docker.iopull-through: Nexusdocker-groupghcr.io: direct authenticated path; never use the anonymous Nexus upstream proxy- OCI 빌드 캐시 레지스트리(플랫폼 CI 이미지 빌드): HTTPS GHCR registry cache. Nexus
docker-internal은 내부 TLS/Gateway 경로가 생길 때만 명시적으로 writer가 될 수 있음.
한 장으로 보는 단일 Nexus 캐시 평면
Section titled “한 장으로 보는 단일 Nexus 캐시 평면”flowchart TB
subgraph nexus["Nexus (ns nexus, nexus.nexus.svc)\npackage + pull-through cache"]
npm[":8081 npm-group / pypi-group / apt-debian / web API"]
grp[":8083 docker-group\n(docker.io pull-through, V2)"]
internal[":8082 docker-internal (hosted)\nreserved for HTTPS/Gateway writer"]
end
k3s["K3s 노드\n/etc/rancher/k3s/registries.yaml\nmirror -> 127.0.0.1:30083"] --> grp
ws["Daytona 워크스페이스\n(container runtime 없음)\nFRACTALOPS_*_MIRROR_ENDPOINT"] --> grp
cf["Cloudflare Tunnel\nnexus-buildcache.yamon.io\nexternal projection only"] --> internal
ws --> npm
ci["플랫폼 CI 이미지 빌드\ncache_to/from"] --> ghcrcache["GHCR HTTPS registry cache"]
ci --> grp
up1["docker.io"] -. 업스트림 .-> grp
ci --> ghcr["ghcr.io direct authenticated path"]
라이브 엔드포인트 (Nexus)
Section titled “라이브 엔드포인트 (Nexus)”- 서비스:
nexus(네임스페이스nexus,nexus.nexus.svc); 공개https://nexus.yamon.io - npm / pypi / web API:
:8081(/repository/<repo>/) docker-group(docker.io pull-through, V2)::8083docker-internal(hosted; 현재 CI writer 아님)::8082- CI buildcache writer: GHCR HTTPS registry cache (
ghcr.io/<owner>/fractalops-api:*buildcache등) - External buildcache projection:
nexus-buildcache.yamon.io→ Cloudflare Tunnel → Traefiknexus-buildcache-edge→ Nexusdocker-internal:8082; do not use this for large CI layer cache pushes. - 노드 접근 docker 미러: NodePort
30083 -> 8083(선호), 또는 kube-proxy 경유 Nexus Service ClusterIP:8083.
토폴로지는 이를 registry_cache 키로 모델링합니다(역사적 이름; 값은 이제 Nexus를 가리킴 — host_ip는 Nexus ClusterIP, buildcache_ref: "", docker_proxy_port: 8083). render_env가 거기서 대응하는 FRACTALOPS_* env를 emit합니다. 이 Cloudflare projection은 topology evidence일 뿐 BuildKit registry cache writer가 아닙니다.
K3s 런타임
Section titled “K3s 런타임”모든 K3s 노드의 /etc/rancher/k3s/registries.yaml는 docker.io만 Nexus docker-group으로 미러합니다. GHCR은 각 런타임이 직접 인증합니다.
mirrors: docker.io: endpoint: ["http://127.0.0.1:30083"]configs: "127.0.0.1:30083": auth: username: "workspace-tools-puller" password: "<FRACTALOPS_NEXUS_PULL_PASSWORD from OpenBao runtime scope>"미러 자격증명은 OpenBao(runtime scope)에서 옵니다 — 손으로 편집하지 마세요. 노드별 cutover 절차 + 롤백은 Nexus Docker Mirror Cutover를 보세요.
비공개 GHCR 이미지는 Kubernetes imagePullSecret 또는 CI registry login으로 직접 인증합니다. Nexus의 인증 없는 GHCR upstream proxy는 token 401을 반복하므로 금지합니다.
플랫폼 CI 이미지 빌드
Section titled “플랫폼 CI 이미지 빌드”캐시 평면은 두 소비자를 서빙합니다: 개발자 워크스페이스(pull-through 미러)와 플랫폼 자신의 CI 이미지 릴리스 파이프라인(런타임 이미지 빌드 캐시). 프로젝트별 빌드 파이프라인도, in-sandbox 빌드/ship 평면도 없습니다 — 그 표면 전체가 삭제됐습니다. 개발 프리뷰는 bare 프로세스입니다. Dev Preview Plane 참고.
FractalOps API/worker 이미지는 CI-빌드 + GitOps-pinned입니다. CI는 Nexus pull-through 미러로 base 레이어를 pull하고, registry cache push/pull은 HTTPS GHCR로 유지합니다. plain HTTP nexus.nexus.svc.cluster.local:8082는 BuildKit registry cache exporter가 HTTPS로 붙어 실패할 수 있어 기본 writer가 아닙니다. Nexus를 writer로 쓰려면 내부 HTTPS/TLS 경로(예: Gateway API/HTTPRoute)와 명시적 FRACTALOPS_BUILDCACHE_REGISTRY가 먼저 필요합니다. Cloudflare nexus-buildcache.yamon.io는 외부 projection일 뿐 CI writer가 아닙니다. 빌드 시간/캐시 가용성/실패율 신호는 Build Plane Event 레코드입니다 — Build Plane Observability 참고. Temporal은 잡을 스케줄/실행할 뿐 메트릭 웨어하우스가 되지 않습니다.
Kubernetes BuildKit은 cleanup: false, replicas=1인 공유·경계형 실행면입니다. Pod가 유지되는 동안 작업 간 node-local cache를 재사용하지만 Longhorn/local-path PVC를 만들거나 확장하지 않습니다. Pod 교체 후에도 필요한 레이어는 GHCR registry cache가 소유합니다. 세부 계약은 BuildKit Kubernetes Driver를 보세요.
Harbor publish가 필요한 runner는 Buildx setup 전에 비밀값이 아닌 daytona/daytona-harbor-ca ConfigMap의 ca.crt를 /tmp/fractalops-buildkit-daytona-harbor-ca.crt로 준비합니다. BuildKit은 이 CA를 harbor.daytona.svc.cluster.local에만 적용하며 TLS 검증을 끄지 않습니다.
Portal 릴리스는 yamonco/fractalops-frontend에 있습니다. 현재 생산 경로는 Cloudflare Worker 배포라서 FractalOps API/worker처럼 OCI image pin을 만들지 않습니다. 이 컨트롤-플레인 저장소가 아니라 프론트엔드 저장소의 Cloudflare release workflow를 보세요.
gh workflow run "Cloudflare Portal Release" --repo yamonco/fractalops-frontendFractalOps API/worker 런타임 스모크 빌드는 의도적으로 한 최종 이미지를 승격하는 경우가 아니라면 GitOps를 불변으로 유지하세요.
FRACTALOPS_ALLOW_LOCAL_RUNTIME_RELEASE=1 \FRACTALOPS_RUNTIME_RELEASE_UPDATE_GITOPS=0 \./ops/containers/fractalops/release.sh출력된 image_ref=...로 명시적 스모크를 돌리세요. 최종 승격만이 platform/k8s/apps/fractalops-api/values.yaml과 platform/k8s/apps/fractalops-worker/values.yaml을 갱신해야 합니다.
개발자 워크스페이스 (컨테이너 런타임 없음)
Section titled “개발자 워크스페이스 (컨테이너 런타임 없음)”개발자 워크스페이스용으로, 기본 Daytona 템플릿은 토폴로지-파생 캐시 값을 export합니다.
FRACTALOPS_GHCR_REGISTRY_CACHE=ghcr.io/<owner>/<image>:<scope>-buildcacheFRACTALOPS_DOCKER_IO_MIRROR_ENDPOINT=<nexus-docker-group-url>FRACTALOPS_APT_CACHE_URL=<nexus-apt-debian-url>
샌드박스에는 컨테이너 런타임이 없습니다.
docker는 baked exit-127 stub으로 하드-월입니다(in-session에서도 stub 유지). in-sandbox compose/build 평면이 없습니다.- 라이브 프리뷰는 bare 개발 서버(vite / next / uvicorn,
0.0.0.0바인드)이며,dev-previewMCP(dev_preview_start/dev_preview_url/dev_preview_stop)로 daytona-proxy 서명 프리뷰 URL을 통해 노출됩니다. Dev Preview Plane 참고. - 프로젝트별 영구 호스팅(DB, 정적 사이트, big-facility compose)은 프로젝트의 Dokploy 평면이지 샌드박스가 아닙니다.
gh는 런처이며, GitHub App 프록시가 에이전트 issue/PR 쓰기를 워크스페이스에 토큰을 저장하지 않고 FractalOps GitHub App 브로커로 라우팅합니다.
운영 규칙 (Operating Rules)
Section titled “운영 규칙 (Operating Rules)”- 패키지·Docker Hub pull-through 캐시는 Nexus, OCI 빌드 레이어 캐시는 GHCR가 소유합니다. 독립 registry-cache VM/LXC를 다시 도입하지 말고 주소를 프로젝트 코드에 박지 마세요.
- 테스트/CI는 Test Execution Policy를 따릅니다. 먼저 덜 실행하고, 그 다음 병렬화하며, 마지막으로 캐시/환경 재사용을 적용합니다.
- 플랫폼 CI 이미지 빌드의 registry cache writer는 HTTPS GHCR입니다. Nexus hosted docker endpoint(
nexus.nexus.svc.cluster.local:8082)는 plain HTTP라 기본 writer로 쓰지 않습니다. 내부 TLS/Gateway 경로를 만든 뒤에만FRACTALOPS_BUILDCACHE_REGISTRY로 명시하세요.cache_to/from이ignore-error=true를 달고 있어 buildcache 오설정은 캐시 미스로 degrade하지 빌드 실패가 되지 않습니다. - Daytona 워크스페이스 이미지는 Docker 데몬을 설치/요구하면 안 됩니다. in-sandbox 빌드/ship 평면이 없고, 개발 프리뷰는 bare 프로세스입니다.
- 개발자는 기본 루프용으로 프로젝트별 DevSpace/watch/sync 규칙을 쓰면 안 됩니다. Daytona가 Kubernetes 런타임 모양을 숨깁니다.
- 빠른 Daytona 워크스페이스와 로컬 스크래치는
pve-worker0을, 메모리-무거운 작업은pve-worker3을 선호하세요. - Nexus는 자체 blob store + 스케줄된 cleanup/compaction을 소유합니다(외부
registry-gc.timer없음). - Nexus
nexus-dataPVC는60Gidurable Longhorn 볼륨입니다. 축소하거나 삭제하지 마세요. - Kubernetes BuildKit 로컬 상태는 공유 Pod의 bounded node-local ephemeral storage입니다. 컨테이너는
8Gi를 요청하고64Gi로 제한되며,/var/lib/buildkit은64GiemptyDir에 명시적으로 마운트됩니다. GC는12GB를 보존하고 최대56GB사용과8GB여유를 유지합니다. BuildKit compute/cache는kubernetes.io/os=linuxcapability를 선택하며 특정 hostname에 고정되지 않습니다. BuildKit은 일반 worker가 포화되면sandbox=trueworker를 bounded fallback으로 사용할 수 있습니다. CLI-only build runner는 노드 지역성이 필요 없어 스케줄러 배치를 사용하며, 둘 다 control-plane/etcd toleration을 갖지 않습니다. BuildKit은2CPU,3Gimemory,max-parallelism = 2로 제한됩니다. 정상 replica와 Pod quota는 정확히 하나이며Recreate가 교체 중 중복 Pod를 막습니다. durable layer cache는 GHCR가 소유합니다. 과거의 detached BuildKit PVC는 활성 빌드가 없음을 확인한 뒤 삭제 대상이지 확장 대상이 아닙니다. - Nexus
nexus-data는 durable blob store입니다. CNPG 용량 사고를 풀려고 Nexus PVC를 삭제하지 마세요. 필요한 정리는 Nexus cleanup task와 blob compaction으로 합니다.