- Nitro는 임베디드, 서버, 데스크톱, 컨테이너에 모두 적용 가능한 초소형 프로세스 슈퍼바이저 및 init 시스템임
- 시스템 상태를 RAM에만 저장하여 읽기 전용 파일 시스템에서도 무리 없이 동작하며, 빠르고 효율적인 이벤트 기반 설계를 제공함
- 구성 방식은 단순한 스크립트 디렉터리 구조로, 복잡한 설정 파일이나 부가적인 빌드 과정 없이 서비스 관리가 가능함
- Parmetrized 서비스, 견고한 재시작, 개별 서비스별 신뢰성 높은 로깅 기능 등 컨테이너, 임베디드 환경에 최적화된 기능을 지원함
- nitroctl 툴을 통한 원격 제어, 신호 기반 동작 제어 등 높은 유연성과 통제력을 보장함
개요
Nitro는 Linux에서 pid 1로도 사용할 수 있는 초소형 프로세스 슈퍼바이저임
주요 적용 분야는 아래와 같음
- 임베디드, 데스크톱, 서버 등 다양한 용도의 Linux 머신용 init
- Linux initramfs의 init
- Docker/Podman/LXC/Kubernetes 등 컨테이너 환경의 init
- POSIX 시스템에서 권한 없이 동작하는 슈퍼비전 데몬
구성은 디렉터리 기반 스크립트 구조를 사용하며, 기본 위치는 /etc/nitro임
요구사항
- 커널의 Unix 소켓 지원 필요
tmpfs또는 쓰기 가능한/run디렉터리 필요
다른 시스템 대비 장점
- 모든 상태 정보는 RAM에만 유지되어 읽기 전용 루트 파일 시스템에서도 별도 트릭 없이 동작함
- 이벤트 기반, 폴링 없는 동작 방식으로 효율성 제공
- 런타임 중 메모리 동적 할당이 없음
- 파일 디스크립터가 무한정 소모되지 않음
- 하나의 self-contained 바이너리(옵션으로 제어 바이너리 추가) 만 필요함
- 설정 파일 변환 및 컴파일 필요 없음, 서비스는 스크립트가 들어 있는 단순 디렉터리임
- 서비스 재시작 및 로깅 체인 지원
- 시스템 시계가 정확하지 않아도 정상 동작
- FreeBSD에서
/etc/ttys를 통해 실행 가능 - musl libc 사용 시 초소형 static 바이너리 제작 가능
서비스 관리
-
각 서비스 디렉터리(기본
/etc/nitro내부)는 아래 파일을 포함할 수 있음setup: 서비스 시작 전 실행되는 (옵션) 스크립트, 정상 종료(0) 시에만 서비스 시작 가능run: 서비스 동작 스크립트, 종료되지 않는 한 서비스가 살아있는 상태로 인식됨, 미구현 시 one-shot 서비스로 처리됨finish:run종료 후 실행되는 (옵션) 스크립트, 종료 상태 및 시그널 값을 인자로 전달log: 다른 서비스 디렉터리를 가리키는 심볼릭 링크, run 출력 내용을 해당 서비스의 입력으로 파이프 연결(로깅 체인 활용 가능)down: 이 파일이 존재하면 nitro가 기본적으로 이 서비스를 올리지 않음- 디렉터리명이 '@'로 끝나면 무시되어 파라미터 서비스로 활용 가능
- 서비스명은 64글자 미만,
/,,, 줄바꿈 문자를 포함할 수 없음
-
runit의
chpst유틸리티가run스크립트 작성 시 유용함
특수 서비스
LOG: log 링크가 없는 모든 서비스의 로그 기록용 디폴트 서비스SYS:SYS/setup은 모든 서비스 구동 전 실행, 순서 있는 서비스 구동 구현 가능SYS/finish: 전체 종료 단계 진입 전 실행SYS/final: 모든 프로세스 종료 후 실행SYS/fatal: 치명적 에러 발생 시 종료 대신 실행(있을 경우)SYS/reincarnate: shutdown 대신 실행되어 예컨대 initramfs 재구현 등에 활용 가능
파라미터라이즈드 서비스
- '@'로 끝나는 서비스 디렉터리는 nitro가 무시하지만, 심볼릭 링크 또는
nitroctl명령을 통해 직접 지정 가능 - '@' 뒤 파라미터가 첫 번째 인자로 각 스크립트에 전달됨
- 예:
agetty@/run와agetty@tty1심볼릭 링크가 있으면agetty@/run tty1실행 nitroctl up agetty@tty2입력 시agetty@/run tty2실행 가능(디렉터리 존재 여부 무관)
- 예:
동작 모드
- 전체 라이프사이클은 부팅, 서비스 실행(슈퍼비전), 종료 세 단계로 구성
- 부팅: 특수 서비스
SYS가 존재하면setup부터 실행, 이후 모든 non-down 서비스 실행 - 서비스가 종료되면 재시작, 단 최근 재시작이 빠르면 2초 대기
nitroctl Reboot또는Shutdown으로 종료 신호 전달 가능- 이때
SYS/finish→ 모든 서비스 SIGTERM(최대 7초 대기) → SIGKILL →SYS/final→ 종료 시퀀스
- 이때
- 컨테이너나 권한 없는 슈퍼바이저용일 경우 프로세스만 종료
- 부팅: 특수 서비스
nitroctl을 이용한 제어
- nitroctl CLI 도구로 멀리서 nitro를 제어할 수 있음
명령어 예시:
- list: 서비스 목록, 상태, PID, uptime, 마지막 종료 상태 출력
- up/down/start/stop/restart: 서비스 시작·중지·재시작 등 제어
- 신호 전송: p(SIGSTOP), c(SIGCONT), h(SIGHUP), a(SIGALRM), i(SIGINT), q(SIGQUIT), 1(SIGUSR1), 2(SIGUSR2), t(SIGTERM), k(SIGKILL)
- pidof: 지정 서비스의 PID 출력
- rescan: 서비스 디렉터리 재읽기, 추가·제거 서비스 반영
- Shutdown/Reboot: 전체 시스템 종료·재부팅
신호를 통한 제어
- nitro 프로세스에 시그널 직접 전송으로 컨트롤 가능
- SIGHUP: 서비스 재스캔(rescan)
- SIGINT: 재부팅
- SIGTERM: 종료(nitro가 pid 1이 아니면)
Linux에서 init으로서의 nitro
- Nitro는 자체 포함형 바이너리로 Linux pid 1로 직접 부팅 가능
/dev,/run을 필요 시 마운트하며, 기타 동작은SYS/setup에서 처리- Ctrl-Alt-Del 이벤트에 질서 정연한 재부팅 트리거
Docker 컨테이너에서 init으로서 Nitro 사용
- Nitro는 정적으로 빌드되어 컨테이너에 간단히 포함 가능
/run이 컨테이너에 존재해야 기본 소켓 경로 사용 가능- 컨트롤 소켓을 바인드 마운트 처리하면 외부에서 nitroctl로 원격 제어 가능
FreeBSD에서의 Nitro
/etc/ttys에 다음 줄 추가로 FreeBSD init에서 nitro를 슈퍼바이즈 가능/etc/nitro "/usr/local/sbin/nitro" "" on
저자
- Leah Neukirchen leah@vuxu.org
감사
- daemontools, freedt, runit, perp, s6 등 기존 프로세스 슈퍼비전 시스템들의 상세 분석 위에서 개발됨
라이선스
- 0BSD 라이선스(자세한 내용은 LICENSE 파일 참조)