- agent 설치가 어려운 대상을 위한 remote terminal bridge 개념 추가 - Edge terminal session broker와 Node terminal transport relay 흐름 설명 - native protocol에 remote terminal session event 추가 - Portal/Control Plane의 remote terminal bridge session 관리 기능 추가 - remote terminal bridge의 정책/audit 설계 항목 명시
247 lines
9.4 KiB
Markdown
247 lines
9.4 KiB
Markdown
# Dev Field Deployment
|
|
|
|
이 문서는 dev 필드 테스트 기준의 배포 단위를 정리한다. Control Plane과 Web은 compose 서비스로 묶고, Edge와 Node는 호스트에서 직접 실행하는 단일 바이너리로 배포한다.
|
|
|
|
## 배포 단위
|
|
|
|
```text
|
|
control host
|
|
docker compose
|
|
- postgres
|
|
- redis
|
|
- control-plane
|
|
- web
|
|
|
|
edge host
|
|
iop-edge binary
|
|
edge.yaml
|
|
|
|
node host
|
|
iop-node binary
|
|
node.yaml
|
|
|
|
oto build host
|
|
oto binary
|
|
agent.yaml
|
|
```
|
|
|
|
Edge와 Node는 Docker 이미지로 만들지 않는다. Jenkins는 repo의 shell entrypoint를 호출해 Edge/Node 바이너리 산출물을 만든다.
|
|
OTO는 별도 프로젝트의 단일 바이너리 산출물로 두고, IOP Edge는 장기적으로 OTO agent를 설치/등록시키는 bootstrap provider 역할을 가진다.
|
|
Agent 설치가 어렵거나 일회성 유지보수 대상인 host/device는 별도 배포 단위로 보지 않고, 대상에 접근 가능한 Node의 terminal profile을 통해 Edge가 remote terminal bridge session을 중계하는 방향으로 둔다.
|
|
|
|
## Edge/Node 바이너리 빌드
|
|
|
|
기본 빌드는 현재 호스트의 `GOOS/GOARCH` 대상으로 `edge`, `node`를 모두 만든다.
|
|
|
|
```bash
|
|
bin/build/field-binaries.sh
|
|
```
|
|
|
|
Jenkins에서 Linux amd64/arm64를 함께 만들 때는 다음처럼 호출한다.
|
|
|
|
```bash
|
|
TARGETS="linux/amd64 linux/arm64" \
|
|
VERSION="${BUILD_TAG}" \
|
|
COMMIT="${GIT_COMMIT}" \
|
|
bin/build/field-binaries.sh
|
|
```
|
|
|
|
산출물은 `dist/field/<version>/<goos>-<goarch>/` 아래에 생성된다.
|
|
|
|
```text
|
|
iop-edge
|
|
iop-edge.sha256
|
|
iop-node
|
|
iop-node.sha256
|
|
SHA256SUMS
|
|
manifest.env
|
|
```
|
|
|
|
## Control Plane/Web Compose
|
|
|
|
루트의 `.env.example`을 참고해 필요한 값만 `.env`로 복사해 조정한다.
|
|
|
|
```bash
|
|
cp .env.example .env
|
|
docker compose up --build -d
|
|
```
|
|
|
|
서비스 포트 기본값은 다음과 같다.
|
|
|
|
| Service | Port | Purpose |
|
|
|---|---:|---|
|
|
| web | 3000 | Web Portal |
|
|
| control-plane | 9080 | HTTP health/bootstrap |
|
|
| control-plane wire | 19080 | IOP wire endpoint |
|
|
| postgres | 5432 | Control Plane DB |
|
|
| redis | 6379 | Control Plane cache/queue 후보 |
|
|
|
|
현재 Control Plane 구현은 DB/Redis를 아직 사용하지 않지만, dev compose에는 먼저 포함해 이후 schema, queue, audit, event 처리 작업을 같은 배포 단위 안에서 진행할 수 있게 둔다.
|
|
로컬에서 Control Plane 바이너리를 직접 실행하는 테스트는 외부 `code-server-postgres`의 `iop-control-plane-local` DB와 외부 `code-server-redis`의 Redis DB 1, `iop:control-plane:local:` key prefix를 사용한다. dev compose 환경은 Postgres `iop-control-plane-dev` DB와 Redis DB 2, `iop:control-plane:dev:` key prefix를 사용한다. compose의 `control-plane` 서비스는 `IOP_DATABASE_URL`, `IOP_REDIS_URL`, `IOP_REDIS_KEY_PREFIX` 환경변수로 dev 값을 지정해 `configs/control-plane.yaml`의 로컬 기본값을 덮어쓴다.
|
|
|
|
헬스체크는 다음 명령으로 확인한다.
|
|
|
|
```bash
|
|
docker compose ps
|
|
curl -fsS http://localhost:${IOP_CONTROL_PLANE_HTTP_PORT:-9080}/healthz
|
|
curl -fsS http://localhost:${IOP_CONTROL_PLANE_HTTP_PORT:-9080}/readyz
|
|
```
|
|
|
|
## Edge 실행
|
|
|
|
Jenkins 산출물의 `iop-edge`를 edge host에 배포한 뒤, 초기에는 dev 환경의 `edge.yaml`을 지정해 직접 실행한다.
|
|
|
|
```bash
|
|
./iop-edge serve --config /etc/iop/edge.yaml
|
|
```
|
|
|
|
콘솔 기반 현장 smoke가 필요하면 다음처럼 실행한다.
|
|
|
|
```bash
|
|
./iop-edge console --config /etc/iop/edge.yaml
|
|
```
|
|
|
|
dev 초기 단계에서는 repo의 `configs/edge.yaml`을 기준으로 포트와 node token을 맞춘다. 이후 Control Plane enrollment/config sync가 붙으면 edge 설정 파일은 bootstrap 정보만 남기는 방향으로 줄인다.
|
|
|
|
## Node 실행
|
|
|
|
Jenkins 산출물의 `iop-node`를 node host에 배포한 뒤, 초기에는 edge 주소와 token이 들어 있는 `node.yaml`로 직접 실행한다.
|
|
|
|
```bash
|
|
./iop-node serve --config /etc/iop/node.yaml
|
|
```
|
|
|
|
repo root에서 수동으로 검증할 때는 기존 helper를 사용할 수 있다.
|
|
|
|
```bash
|
|
IOP_EDGE_ADDR=<edge-host>:9090 ./bin/node.sh
|
|
```
|
|
|
|
## OTO Agent Bootstrap 방향
|
|
|
|
OTO는 `iop-node`에 종속시키지 않고 Edge에 직접 붙는 build/deploy domain agent로 둔다. 목표 UX는 Jenkins node 연결처럼 Edge에서 먼저 OTO agent를 생성하고, Edge가 발급한 bootstrap command를 대상 빌드 머신에서 실행하는 방식이다.
|
|
|
|
Agent를 설치할 수 있는 대상은 bootstrap/enrollment를 우선한다. 설치가 어렵거나 임시 제어만 필요한 대상은 Edge가 remote terminal bridge session을 열고, 대상에 도달 가능한 Node가 SSH/WinRM/serial/local shell 같은 terminal transport를 실행해 relay한다. 이 경로는 target allowlist, credential 관리, timeout, session audit를 전제로 한다.
|
|
|
|
예상 흐름은 다음과 같다.
|
|
|
|
```text
|
|
Edge UI/API
|
|
-> oto agent 생성
|
|
-> one-time bootstrap token과 install command 발급
|
|
|
|
oto build host
|
|
-> bootstrap command 실행
|
|
-> OS/arch에 맞는 oto binary 다운로드
|
|
-> checksum/signature 검증
|
|
-> agent.yaml 생성
|
|
-> systemd/launchd/Windows service 등록
|
|
-> Edge에 outbound 등록
|
|
```
|
|
|
|
폐쇄망과 개발망에서는 도메인 인증서 발급이 어려울 수 있으므로 HTTPS를 필수 전제로 두지 않는다. 대신 HTTP local/insecure 모드는 명시적으로 선택하게 하고, one-time token, Edge fingerprint 또는 public key pinning, 바이너리 checksum/signature 검증, 등록 후 장기 credential 재발급을 함께 요구한다.
|
|
|
|
예시 command 형태는 다음처럼 둔다.
|
|
|
|
```bash
|
|
curl -fsSL http://edge.local:8080/bootstrap/oto.sh \
|
|
| sh -s -- --edge http://edge.local:8080 --token <one-time-token> --pool build-linux
|
|
```
|
|
|
|
## Field Smoke
|
|
|
|
최소 확인 순서는 다음을 기준으로 한다.
|
|
|
|
1. `docker compose ps`에서 `postgres`, `redis`, `control-plane`, `web`이 healthy/running인지 확인한다.
|
|
2. edge host에서 `iop-edge console --config /etc/iop/edge.yaml`을 실행한다.
|
|
3. node host에서 `iop-node serve --config /etc/iop/node.yaml`을 실행한다.
|
|
4. edge console에서 `/nodes`로 node 등록을 확인한다.
|
|
5. 메시지 2회를 보내고 각 요청의 start, message, complete event가 edge console에 표시되는지 확인한다.
|
|
6. `/capabilities`, `/transport`, `/sessions`를 실행해 command 응답을 확인한다.
|
|
|
|
보조 자동 smoke는 repo root에서 다음 명령으로 실행한다.
|
|
|
|
```bash
|
|
make test-e2e
|
|
```
|
|
|
|
이 명령은 보조 확인이며, 필드 배포 완료 기준은 실제 edge/node 바이너리 실행 흐름 확인이다.
|
|
|
|
## Edge setup CLI
|
|
|
|
Edge 바이너리는 호스트 환경 준비를 `setup` 명령으로 일원화한다. 공식 운영 경로는 하나다.
|
|
|
|
```bash
|
|
sudo iop-edge setup --enable --start
|
|
```
|
|
|
|
배포 전에 결과를 검토하려면 `--dry-run`을 쓴다.
|
|
|
|
```bash
|
|
sudo iop-edge setup --dry-run --binary /usr/local/bin/iop-edge
|
|
```
|
|
|
|
`setup`은 다음을 담당한다.
|
|
|
|
- 실행 user/group(`iop`) 준비
|
|
- `/etc/iop`와 `/var/lib/iop/edge` 디렉터리 준비
|
|
- 설정 파일이 없을 때만 기본 템플릿 생성 (`--overwrite-config`로 강제 갱신)
|
|
- systemd unit 생성 또는 갱신 (`/etc/systemd/system/iop-edge.service`)
|
|
- `systemctl daemon-reload`
|
|
- 옵션에 따른 `--enable`, `--start`, `--restart`
|
|
|
|
`setup`의 `--config` 기본값은 `/etc/iop/edge.yaml`이다. dev 단계 명령(`serve`, `console`, `config print/check`)의 root persistent `--config` 기본값(`configs/edge.yaml`)과는 다르다.
|
|
|
|
별도 `render`, `service install`, `service status` 명령은 초기 범위에 넣지 않는다. 검토와 CI 확인은 `setup --dry-run`으로 흡수하고, 상태/로그/재시작은 `systemctl`과 `journalctl`을 기준 운영 도구로 둔다.
|
|
|
|
현재 구현된 edge CLI 표면은 다음과 같다.
|
|
|
|
```text
|
|
iop-edge serve
|
|
iop-edge console
|
|
iop-edge setup
|
|
iop-edge config print
|
|
iop-edge config check
|
|
iop-edge version
|
|
```
|
|
|
|
`setup`은 여러 번 실행해도 같은 결과로 수렴한다. 기존 설정 파일은 기본적으로 덮어쓰지 않고, 강제 갱신이 필요하면 `--overwrite-config`를 지정한다.
|
|
|
|
## Node setup CLI
|
|
|
|
Node 바이너리는 호스트 환경 준비를 `setup` 명령으로 일원화한다. 공식 운영 경로는 하나다.
|
|
|
|
```bash
|
|
sudo iop-node setup --enable --start
|
|
```
|
|
|
|
배포 전에 결과를 검토하려면 `--dry-run`을 쓴다.
|
|
|
|
```bash
|
|
sudo iop-node setup --dry-run --binary /usr/local/bin/iop-node
|
|
```
|
|
|
|
`setup`은 다음을 담당한다.
|
|
|
|
- 실행 user/group(`iop`) 준비
|
|
- `/etc/iop`와 `/var/lib/iop/node` 디렉터리 준비
|
|
- 설정 파일이 없을 때만 기본 템플릿 생성 (`--overwrite-config`로 강제 갱신)
|
|
- systemd unit 생성 또는 갱신 (`/etc/systemd/system/iop-node.service`)
|
|
- `systemctl daemon-reload`
|
|
- 옵션에 따른 `--enable`, `--start`, `--restart`
|
|
|
|
`setup`의 `--config` 기본값은 `/etc/iop/node.yaml`이다. dev 단계 명령(`serve`, `config print/check`)의 root persistent `--config` 기본값(`configs/node.yaml`)과는 다르다.
|
|
|
|
별도 `render`, `service install`, `service status` 명령은 초기 범위에 넣지 않는다. 검토와 CI 확인은 `setup --dry-run`으로 흡수하고, 상태/로그/재시작은 `systemctl`과 `journalctl`을 기준 운영 도구로 둔다.
|
|
|
|
현재 구현된 node CLI 표면은 다음과 같다.
|
|
|
|
```text
|
|
iop-node serve
|
|
iop-node setup
|
|
iop-node config print
|
|
iop-node config check
|
|
iop-node version
|
|
```
|
|
|
|
`setup`은 여러 번 실행해도 같은 결과로 수렴한다. 기존 설정 파일은 기본적으로 덮어쓰지 않고, 강제 갱신이 필요하면 `--overwrite-config`를 지정한다.
|