13.3 런타임 환경과 데몬(Daemon) 인프라

13.3 런타임 환경과 데몬(Daemon) 인프라

소스와 오퍼레이터 코드를 아무리 잘 짜봤자, 이들을 끌어안고 실행 시켜 줄 “컴퓨터 속의 공장장” 이 없다면 코드는 구동되지 않는다.

이 챕터에서는 당신이 작성한 파이프라인(Dataflow) 을 실제로 호스팅하고, 스레드를 배분하며, 다른 노드들과 연결해 주는 백그라운드 데몬 프로세스인 Zenoh-Flow Daemon 의 철학적 구조와 세팅 런북을 다룬다.

1. Zenoh-Flow 런타임(Runtime)의 계층적 구조

만일 당신이 “파이프라인 실행 버튼을 누른다” 라고 생각했다면 틀렸다. 당신은 그저 런타임 환경에 설계도(YAML)를 제출(Submit) 할 뿐이다.

1.0.1 [인스펙션] 중앙집결형 컴파일 레이어

1. Zenoh-Flow 데몬의 독재
컴퓨터마다 1개의 데몬(zf-daemon) 이 항상 은밀하게 떠 있어야 한다. 이 데몬은 운영체제의 자원을 쥐고 있으며, 언제 날아올지 모르는 파이프라인 이식(Deployment) 요청을 24시간 감시한다.

2. 런타임 계층 분리

  • Control Layer (제어망): 당신이 zfctl 리모컨 명령어로 “파이프라인 켜라” 고 치면, 이 명령은 오직 데몬의 제어망을 타고 들어간다.
  • Data Layer (데이터망): 데몬이 파이프라인 생성을 마치고 나면, 데몬 자신은 뒤로 쏙 빠지고 생성된 노드들(Source, Operator) 끼리의 고속 직행망(Zenoh 터널) 이 열린다. 데몬이 과부하에 걸려도 당신의 로봇 제어 파이프라인 속도에는 0.1ms 의 락(Lock)도 걸리지 않는 락-프리 아키텍처다.

2. 노드 스케줄러(Scheduler) 및 워커(Worker) 스레드 풀 관리 기법

소스에서 데이터가 무수히 쏟아지는데, 필터(오퍼레이터)가 처리 속도를 못 따라간다면 큐(Queue)가 폭발하며 OOM(Out of Memory) 으로 죽는다. 데몬은 이 교통정리를 어떻게 수행하는가?

2.0.1 [Runbook] Rust Tokio 기반의 비동기 용광로 튜닝

Zenoh-Flow 의 스케줄러는 그 유명한 Rust 의 Tokio 비동기 런타임을 코어 엔진으로 삼고 있다.

1. 경량 워커(Worker) 스레드의 마법

  • 데몬은 컴퓨터의 CPU 코어 개수만큼만 물리적(OS) 스레드를 띄운다. (예: 쿼드코어면 4개).
  • 그리고 이 4개의 진짜 스레드 위에, 수만 개의 “가벼운 가상 스레드(Async Task)” 를 태워서 잘게 썰어 돌린다.
  • 필터(Operator) 가 계산을 마치고 I/O 를 기다릴 때, 운영체제 단위의 컨텍스트 스위칭(Context Switching) 이 일어나지 않는다. 스케줄러가 알아서 다음 노드(Task) 로 계산 권한을 넘긴다. 따라서 수만 개의 파이프라인을 돌려도 CPU 캐시 미스 가 제로에 수렴한다.

2. 스레드 풀 강제 할당 (Pinning)

  • 문제: 인공지능 추론(Inference) 노드는 비동기가 통하지 않는 연산 괴물(Blocking Heavy Task) 이다. 이런 녀석을 일반 스레드 풀에 놔두면 다른 노드들이 순서를 뺏겨 파이프라인이 즉각 마비된다.
  • 아키텍트의 개입: GPU나 무거운 필터를 태우는 노드는 스케줄러에게 “이 녀석은 별도의 블로킹 전용 독립 스레드에 가둬라!” 라고 데몬 파일에서 강제 격리 조치해야만 한다. 시스템 설계자의 피할 수 없는 임무다.

3. Zenoh-Flow 데몬 설치, 구성 및 백그라운드 실행

공장장(데몬) 을 컴퓨터에 취직시켜야 노드가 돈다.

3.0.1 [Runbook] 데몬(Daemon) 인프라 구축 매뉴얼

1. 코어 및 CLI 툴체인 설치
Rust 만이 유일한 정답이다. (빌드가 끝나면 20MB 남짓한 단일 바이너리만 남는다).

cargo install zenoh-flow-daemon
cargo install zenoh-flow-ctl    # 컨트롤러(리모컨)

2. 데몬 설정 및 백그라운드 구동 (Systemd)
데몬은 로봇이 부팅될 때 운영체제 서비스로 깨어나게 만들어야 한다.

## /etc/systemd/system/zf-daemon.service
[Unit]
Description=Zenoh-Flow Runtime Daemon
After=network.target zenohd.service  # Zenoh 라우터가 먼저 켜진 후 기동!

[Service]
ExecStart=/usr/local/bin/zf-daemon --config /etc/zf-daemon.yml
Restart=always
User=robot_user

[Install]
WantedBy=multi-user.target

이 런북으로 인해 당신의 리눅스 보드는 파이프라인의 명령을 대기하는 완벽한 “Zenoh-Flow 워커 토드” 로 각성했다.

4. 데몬 간의 오토 디스커버리(Auto Discovery)와 토폴로지 동기화 프로세스

로봇 안에 데몬(A) 이 깨어나고, AWS 서버에 데몬(B) 이 깨어났다. 내가 내 방 노트북(리모컨) 에서 AWS 에 접속해 “A와 B를 이어서 파이프라인을 돌려!” 라고 명령하면, 쟤들은 어떻게 서로를 찾을까?

4.0.1 [인스펙션] 중앙 없는 군집 결성 (Swarm Formation)

모든 해답은 기반 인프라인 “Zenoh Router (zenohd)” 시스템에 있다.

1. 공유된 이름표 (Shared State)

  • 데몬이 켜지는 즉시, 뒷단의 Zenoh 라우터 망에 대고 가상의 간판을 하나 단다.
  • “내 데몬 아이디는 robot_daemon_01 이고 이 IP 주소로 나한테 명령을 내릴 수 있어!”
  • 이 정보는 Zenoh 망 특유의 Key Expression (zenoh-flow/daemons/...) 상단에 실시간으로 기록(Put) 된다.

2. 컨트롤러(zfctl) 의 전지적 시점
당신이 노트북에서 zfctl 리모컨을 켜는 순간, 이 툴은 묻지도 따지지도 않고 가장 가까운 Zenoh 라우터에 쿼형(Query) 을 던진다. “지금 세상에 켜져 있는 데몬 다 나와봐!”
라우터가 수합해 준 전 세계 데몬 100 대의 리스트를 확보한 컨트롤러는, 당신이 설계한 YAML 도면을 읽고는 정확히 A데몬과 B데몬의 멱살을 잡고 명령을 분배(Deploy) 하기 시작한다.
IP 하드코딩 따위는 멸종된 세계관이다.

5. 런타임 환경에서의 리소스 격리와 메모리 관리

내가 짠 이상한 파이퍼라인 노드 하나에서 C 언어 포인터 에러가 터져서(Segfault) 메모리 누수가 발생했다 치자. 전체 시스템(데몬) 이 죽어버리는가?

5.0.1 [Runbook] 모래상자(Sandbox) 방어 체계

데몬은 당신이 짠 플러그인 바이너리(노드) 를 자신의 몸통 안에 라이브러리(.so 파일) 로 심는다.

1. 프로세스 격리 한계점 (공유 런타임의 양날의 검)

  • Zenoh-Flow 의 데몬은 Docker 같은 극단적인 “프로세스 물리 격리(Container)” 를 하지 않는다. 왜냐하면 컨테이너 사이에 데이터를 넘기는 것 자체가 오버헤드이기 때문이다. 노드들은 데몬(하나의 프로세스) 의 메모리를 같은 주소 안에서 공유(Shared Memory) 한다.
  • 위험 경고: 결국 당신이 작성한 C/Rust 노드 모듈 안에서 malloc() 후에 free() 를 잊어버리거나 스택을 터뜨리면(Buffer Overflow), 데몬의 심장을 칼로 찌르는 것과 시너지를 일으켜 “동체 마비(Crash)” 로 이어질 위험이 있다.

2. 아키텍트의 회피 전술: 다중 데몬 배치
만약 보안이나 에러 확률이 높은 외주 개발팀의 필터(Operator) 를 써야 한다면?

  • 절대 로봇 코어 제어를 담당하는 01번 데몬에 그 노드를 올려선 안된다.
  • 같은 컴퓨터 안에 도커 컨테이너를 하나 더 띄우고 “격리 전용 데몬 02” 를 띄워라. 그리고 파이프라인 설계도(YAML) 상에서 수상한 필터는 “데몬 02” 위치에 강제 할당(Mapping) 시킨다.
    어차피 같은 PC 내부라 통신 지연은 제로에 수렴하지만 운영체제의 프로세스 방어막이 쳐져 시스템 붕괴를 틀어막는 생존 런북이다.