원격 macOS에서 빈 prompt 인자가 oneshot CLI에 전달되어 cwd 테스트가 실패했고, app-server cwd 검증은 고정 sleep 레이스에 의존했다. dev 배포가 같은 기준으로 반복되도록 inventory와 capacity smoke 절차도 함께 정리한다.
190 lines
7.6 KiB
Markdown
190 lines
7.6 KiB
Markdown
# Edge Local Quickstart
|
|
|
|
이 문서는 `toki-labs.com` Control Plane에 native Edge를 붙이고, Ollama Node를 연결해 OpenAI-compatible smoke까지 확인하는 최소 절차다.
|
|
|
|
설정 기준은 `edge.yaml`이다. 주소는 환경 변수로 흩뿌리지 않는다.
|
|
|
|
## 1. Package
|
|
|
|
현재 `toki-labs.com` 원격처럼 Apple Silicon macOS에서 실행한다.
|
|
|
|
```bash
|
|
make build
|
|
```
|
|
|
|
## 2. Edge 설정
|
|
|
|
```bash
|
|
rm -rf "$HOME/iop-edge-test"
|
|
mkdir -p "$HOME/iop-edge-test"
|
|
tar -xzf build/packages/iop-edge-darwin-arm64.tar.gz -C "$HOME/iop-edge-test"
|
|
cd "$HOME/iop-edge-test/iop-edge-darwin-arm64"
|
|
./iop-edge config init
|
|
```
|
|
|
|
`edge.yaml`에서 아래 값만 맞춘다. 모델만 필요하면 바꾼다.
|
|
|
|
```yaml
|
|
edge:
|
|
id: "edge-toki-labs"
|
|
name: "Toki Labs Edge"
|
|
|
|
server:
|
|
listen: "0.0.0.0:19090"
|
|
advertise_host: "toki-labs.com"
|
|
|
|
bootstrap:
|
|
listen: "0.0.0.0:18080"
|
|
artifact_base_url: "http://toki-labs.com:18080"
|
|
artifact_dir: "artifacts"
|
|
|
|
control_plane:
|
|
enabled: true
|
|
wire_addr: "toki-labs.com:19081"
|
|
|
|
refresh:
|
|
enabled: true
|
|
listen: "127.0.0.1:19093"
|
|
|
|
openai:
|
|
enabled: true
|
|
listen: "0.0.0.0:18081"
|
|
adapter: "ollama"
|
|
target: "gemma4:26b"
|
|
models:
|
|
- "gemma4:26b"
|
|
timeout_sec: 300
|
|
|
|
nodes: []
|
|
```
|
|
|
|
확인:
|
|
|
|
```bash
|
|
./iop-edge --config edge.yaml env
|
|
./iop-edge --config edge.yaml config check
|
|
```
|
|
|
|
## 3. Node 등록
|
|
|
|
```bash
|
|
./iop-edge --config edge.yaml node register node-ollama-1 \
|
|
--adapter ollama \
|
|
--ollama-base-url http://127.0.0.1:11434
|
|
```
|
|
|
|
출력된 OS별 bootstrap 명령 원문을 보관한다. 명령 원문에는 실제 token이 포함되므로 tracked 문서에는 기록하지 않는다.
|
|
|
|
## 4. Edge 실행
|
|
|
|
```bash
|
|
mkdir -p logs run
|
|
nohup ./iop-edge --config edge.yaml serve > logs/edge.stdout.log 2>&1 &
|
|
echo $! > run/iop-edge.pid
|
|
```
|
|
|
|
확인:
|
|
|
|
```bash
|
|
curl -fsS http://toki-labs.com:18000/edges
|
|
```
|
|
|
|
## 5. Node 실행
|
|
|
|
3단계에서 출력된 bootstrap 명령을 Node host에서 그대로 실행한다. Linux/macOS는 generated `curl | bash` 명령을 사용하고, Windows native PowerShell은 generated `.ps1` bootstrap과 `Start-IopNode` 함수를 사용한다.
|
|
|
|
Node 연결 확인:
|
|
|
|
```bash
|
|
curl -fsS http://toki-labs.com:18000/edges/edge-toki-labs/status
|
|
```
|
|
|
|
## 6. dev-runtime provider pool 반복 기준
|
|
|
|
현재 GX10 vLLM과 OneXPlayer Lemonade를 같은 model alias로 묶어 검증하는 dev-runtime 기준은 원격 runner의 동기화된 iop checkout과 `build/dev-runtime/edge.yaml`이다.
|
|
|
|
배포 전 원격 runner checkout은 보존 대상이 아니다. 항상 clean sync 후 dev-runtime binary를 다시 빌드한다.
|
|
|
|
```bash
|
|
cd /Users/toki/agent-work/iop-dev
|
|
git fetch origin main
|
|
git reset --hard origin/main
|
|
git clean -fd
|
|
|
|
go build -trimpath -o build/dev-runtime/bin/edge ./apps/edge/cmd/edge
|
|
go build -trimpath -o build/dev-runtime/bin/iop-node ./apps/node/cmd/node
|
|
GOOS=linux GOARCH=arm64 go build -trimpath -o build/dev-runtime/bin/iop-node-linux-arm64 ./apps/node/cmd/node
|
|
GOOS=windows GOARCH=amd64 go build -trimpath -o build/dev-runtime/bin/iop-node-windows-amd64.exe ./apps/node/cmd/node
|
|
```
|
|
|
|
기준 주소:
|
|
|
|
- Control Plane status: 원격 host의 `http://127.0.0.1:18001`
|
|
- dev-runtime Edge id: `edge-toki-labs-dev`
|
|
- bootstrap HTTP: `http://toki-labs.com:18082`
|
|
- Edge OpenAI-compatible base URL: `http://toki-labs.com:18083/v1`
|
|
- Edge-Node TCP transport: `toki-labs.com:18084`
|
|
|
|
기준 provider pool:
|
|
|
|
- model alias: `qwen3.6:35b`
|
|
- provider candidate: `gx10-vllm` on `gx10-vllm-node`, capacity `4`
|
|
- provider candidate: `onexplayer-lemonade` on `onexplayer-lemonade-node`, capacity `3`
|
|
- connected non-candidate: `mac-codex-node`
|
|
|
|
OneXPlayer Lemonade Node는 원격 runner나 Edge host에서 다시 SSH하거나 proxy process로 띄우지 않는다. 현재 작업 호스트에서 Windows host에 `ssh r0bin@192.168.0.59`로 직접 접속한 뒤, 그 host 안에서 generated PowerShell bootstrap 명령을 실행한다. 이때 Node 작업 경로는 `$HOME\iop-field`이며, Lemonade provider endpoint는 Windows host 로컬에서 접근 가능한 값을 기준으로 검증한다.
|
|
|
|
SSH 세션 안의 `Start-Process`는 세션 종료와 함께 `iop-node.exe`가 정리될 수 있다. 반복 배포에서는 Windows host에서 `Win32_Process.Create` 방식으로 세션 독립 실행한다.
|
|
|
|
```powershell
|
|
$work = "$HOME\iop-field"
|
|
$cmd = 'cmd.exe /c "cd /d C:\Users\r0bin\iop-field && iop-node.exe --config node.yaml serve >> iop-node.wmi.stdout.log 2>> iop-node.wmi.stderr.log"'
|
|
Invoke-CimMethod -ClassName Win32_Process -MethodName Create -Arguments @{ CommandLine = $cmd; CurrentDirectory = $work }
|
|
```
|
|
|
|
capacity, provider mapping, model alias 변경은 후보 `edge.yaml` 수정 후 `config check`, refresh dry-run, refresh apply 순서로 반영한다. `config refresh` subcommand나 `19093` admin port가 없으면 dev-runtime binary rebuild 누락으로 보고 clean sync/rebuild부터 다시 수행한다.
|
|
|
|
dev-runtime 번들은 바이너리를 `build/dev-runtime/bin/edge`에 둔다. 명령은 그 경로를 `EDGE_BIN`으로 잡고 실행한다.
|
|
|
|
```bash
|
|
EDGE_BIN=build/dev-runtime/bin/edge
|
|
"$EDGE_BIN" --config build/dev-runtime/edge.yaml config check
|
|
"$EDGE_BIN" --config build/dev-runtime/edge.yaml config refresh --mode dry-run --addr 127.0.0.1:19093
|
|
"$EDGE_BIN" --config build/dev-runtime/edge.yaml config refresh --mode apply --addr 127.0.0.1:19093
|
|
```
|
|
|
|
Node host OS 재부팅은 필요하지 않다. Edge process 재시작이나 일시 단절은 Node reconnect 정책으로 처리한다. Node는 최초 연결 성공 이후 기본 `10s` 간격으로 최대 `10`회 재접속을 시도하므로, retry window 안에서 Edge가 회복되면 bootstrap 명령을 다시 실행하지 않는다. retry 한계를 넘겨 Node process가 종료된 경우에만 해당 host에서 새 bootstrap 실행이 필요하다.
|
|
|
|
반복 검증 순서:
|
|
|
|
1. Control Plane status에서 `edge-toki-labs-dev`의 connected node 수와 node id를 확인한다.
|
|
2. Edge host에서 `toki-labs.com:18084`의 established node TCP connection 수를 확인한다.
|
|
3. Edge process를 재시작하고 bootstrap 재실행 없이 3개 Node 연결이 회복되는지 확인한다.
|
|
4. `http://toki-labs.com:18083/healthz`와 `/v1/models`를 확인한다.
|
|
5. capacity를 `gx10-vllm=4`, `onexplayer-lemonade=3`로 맞춘 후보 config를 refresh apply하고 Edge process가 유지되는지 확인한다.
|
|
6. `qwen3.6:35b`로 `/v1/responses`와 `/v1/chat/completions` 각각에 provider capacity 총합 + 1개 동시 요청을 보낸다.
|
|
7. capacity `gx10-vllm=4`, `onexplayer-lemonade=3` 기준이면 endpoint별 8개 동시 요청에서 Control Plane status의 provider snapshot이 총 `in_flight=7`, `queued>=1`을 한 번 이상 보여야 한다.
|
|
8. 요청 완료 후 provider snapshot이 `in_flight=0`, `queued=0`으로 회복되는지 확인한다.
|
|
|
|
Qwen 계열 모델은 thinking/reasoning 텍스트를 포함해 응답할 수 있다. 이 dev smoke에서는 thinking 출력을 실패로 보지 않고, HTTP 성공, final marker 포함, provider log/run count 증가를 기준으로 판정한다.
|
|
|
|
현재 공개 API는 개별 request의 최종 `node_id`를 응답에 노출하지 않는다. 요청별 배정을 확정해야 할 때는 Edge dispatch trace/log를 추가한 뒤 판정한다.
|
|
|
|
## 7. 기본 Smoke
|
|
|
|
아래는 dev-runtime provider pool이 아니라 기본 field/local OpenAI-compatible profile 기준 예시다. dev-runtime provider pool 검증은 위의 `18083`/`qwen3.6:35b` 기준을 따른다.
|
|
|
|
```bash
|
|
curl -fsS http://toki-labs.com:18081/v1/models
|
|
|
|
./iop-edge --config edge.yaml smoke openai \
|
|
--model gemma4:26b \
|
|
--base-url http://toki-labs.com:18081 \
|
|
--timeout 60s
|
|
```
|
|
|
|
외부 OpenAI-compatible client base URL:
|
|
|
|
```text
|
|
http://toki-labs.com:18081/v1
|
|
```
|