Unikernels were hard. key word: were
유니커널은 어려웠습니다. 과거형으로 말하는 이유
유니커널은 애플리케이션과 운영체제 기능을 하나의 이미지로 묶어 단일 작업만 실행하는 방식입니다. 글쓴이는 AI 에이전트가 부족한 라이브러리와 도구를 빠르게 만들면서 과거의 개발 장벽이 낮아졌다고 주장하고, 공격 표면 축소와 개발 언어의 변화 가능성을 설명합니다.
- 주제
AI 요약
유니커널(Unikernel)은 애플리케이션이 운영체제 역할까지 맡는 구조입니다. 별도 사용자 공간(userland)이나 셸, 프로세스 실행 기능을 두지 않고, 네트워크·저장소 같은 기능을 애플리케이션에 라이브러리로 연결합니다. MirageOS를 비롯한 초기 구현은 TCP와 HTTPS 스택을 갖췄지만 저장소 기능과 드라이버가 부족했습니다. 글쓴이는 당시 개발이 어려웠던 이유를 생태계의 빈틈에서 찾습니다. 이제는 AI 에이전트로 부족한 라이브러리를 포팅하고 도구를 구현할 수 있으므로, 유니커널을 어렵다고 여기던 관성도 다시 검토해야 한다고 주장합니다.
운영체제와 공격 표면
글쓴이는 다중 사용자와 여러 프로그램 실행을 전제로 설계한 운영체제를 과거의 설계 부채라고 봅니다. 애플리케이션에서 원격 코드 실행(RCE)이 발생하면 공격자는 셸을 발판 삼아 정보를 빼내고 다른 시스템으로 이동할 수 있습니다. 유니커널은 셸이나 인터프리터 같은 다음 실행 경로를 줄여 침해 뒤의 확산을 어렵게 만들 수 있다는 설명입니다. 글쓴이는 운영 환경에서 컴파일러를 빼고, 빌드 컨테이너와 최소 이미지, Chainguard를 도입해 온 흐름도 공격 표면을 줄이려는 시도로 듭니다.
다만 대담 상대 Justin Cormack은 공격 표면 축소를 단순히 코드 줄 수로 따지면 안 된다고 지적합니다. 셸을 제거한 컨테이너에도 다른 프로그램을 실행하는 인터프리터가 남을 수 있고, 메모리 안전성과 공격에 쓸 수 있는 코드 조각도 고려해야 합니다. 글쓴이는 그 점을 인정하면서도, 셸과 인터프리터가 없으면 침해 뒤 공격자가 활용할 도구가 줄어든다고 봅니다. 다만 유니커널도 취약점이나 하이퍼바이저 탈출 문제에서 자유롭지 않습니다. 글은 KVM 취약점 사례와 주간 커널 패치 부담을 언급하며 운영체제 계층을 계속 덧대는 대신 다른 경계를 설계하자고 제안합니다.
AI가 메우는 생태계의 빈틈
유니커널을 둘러싼 전통적인 반론은 필요한 라이브러리가 없다는 점입니다. 예를 들어 OCaml에서 Stripe를 쓰려면 라이브러리를 직접 작성해야 했지만, 글쓴이는 이제 에이전트에게 Go 라이브러리를 OCaml로 포팅하게 할 수 있다고 말합니다. Justin Cormack은 최소 Linux 이미지에 필요한 XFS 파일시스템 생성 도구 mkfs.xfs를 Rust로 구현한 사례를 소개합니다. 기존 도구를 기준 구현(golden oracle)으로 삼고 여러 크기의 파일시스템을 생성한 뒤 결과를 비교했습니다. 블록 크기별 테스트도 옮겨 몇 시간 만에 플래그 동작까지 맞췄다고 합니다.
저장소는 S3를 주 저장소로 쓰고 로컬 NVMe를 캐시로 활용하는 방안을 제시합니다. Nix에서는 여러 머신을 띄워 네트워크 규칙과 애플리케이션 동작을 검증하는 NixOS machine tests를 강조합니다. 의존성이 깨지거나 공급망 문제가 생기면 upstream 유지관리자를 기다리는 대신 overlay로 직접 수정할 수 있다는 주장도 이어집니다. 글쓴이는 에이전트가 바이너리를 가져다 쓰는 데 그치지 않고, 소스 코드를 직접 바꾸는 개발 환경을 갖춰야 한다고 봅니다.
Spaceleans와 언어 선택
글쓴이는 MirageOS에 NTP 클라이언트와 서버, 네트워크 스택, DNS, HTTP, 구조화 로그, OpenTelemetry, Anthropic·OpenAI 클라이언트, 결제 기능 등을 추가했다고 설명합니다. 가장 큰 실험은 Microsoft Orleans를 OCaml로 옮긴 Spaceleans입니다. Orleans는 분산 액터 시스템으로, 여러 머신의 액터를 하나의 주소 공간처럼 다루고 필요하면 저장소에서 상태를 복원합니다. 글쓴이는 이를 유니커널에서 실행해 분산 시스템과 파일시스템을 구성했으며, 일주일 만에 구현했다고 합니다. 이 사례를 들어 유니커널 개발이 더는 불가능할 만큼 어렵지 않다고 주장합니다.
언어 선택에서도 에이전트의 작업 속도와 피드백 주기를 따집니다. OCaml은 모듈 시그니처인 .mli, Functor, 빠른 컴파일이 에이전트에게 유용하다고 평가합니다. Rust도 에이전트가 잘 다루지만, 대형 코드베이스에서 컴파일 시간이 길어지면 오류를 고치는 시도가 줄어드는 비용이 생긴다고 지적합니다. Haskell의 타입 시스템은 강점이지만 런타임에서 드러나는 공간 누수(space leak)를 우려합니다. Zig처럼 메모리를 미리 할당하고 이후에는 할당하지 않는 전략은 게임 개발의 오래된 기법이지만, 학습 데이터에 흔치 않아 에이전트가 구현하기 어려울 수 있다고 덧붙입니다.
글쓴이는 Cursed라는 언어를 Sonnet 3.5와 3.7로 개발한 경험도 전합니다. C, Rust, Zig를 거쳐 약 6,000달러를 들였고, 이를 세 차례 반복했습니다. 문법과 어휘 구조를 모델의 문맥에 제공하면 학습 데이터에 없는 언어로도 코드를 작성하게 할 수 있었다고 합니다. 다음 단계로는 에이전트가 언어의 변경 사항을 자동으로 반영하도록 skill pack을 제공하고, 과거의 하위 호환성 원칙을 재검토하자고 제안합니다.
보안과 운영상의 반론
댓글에서는 유니커널이 줄이는 공격 표면과 운영체제가 제공하는 격리·관측 기능을 함께 따져야 한다는 논쟁이 이어집니다. 한쪽은 단일 애플리케이션만 실행하면 권한과 구성 요소를 줄일 수 있다고 봅니다. 다른 쪽은 하이퍼바이저가 결국 자원 분리와 하드웨어 중재를 맡으므로 운영체제의 역할이 다른 계층으로 옮겨갈 뿐이라고 지적합니다. strace, eBPF, lsof, ss 같은 도구를 잃는 운영 부담도 반론으로 나옵니다. 글쓴이는 구조화 로그와 OpenTelemetry를 언급하지만, 댓글에서는 단일 프로세스 환경에서도 관측성과 디버깅을 충분히 제공할 수 있는지가 쟁점이 됩니다.
Hacker News 반응
- @eyberg — 공격 표면을 줄이는 일도 장점이지만, 유니커널의 가장 큰 보안 이점과는 거리가 멉니다. 저는 공격 표면 축소를 많이 이야기하는 걸 별로 좋아하지 않습니다. 사람들이 줄어든 코드 줄 수로 논의를 돌리기 때문입니다. 취약점 악용은 데이터 침해의 주요 진입점이고, CISA의 작년 KEV에서 OS 명령 주입은 가장 흔한 CWE였습니다. 작년 DBIR에는 시스템 침입이 약 64번 반복해서 나옵니다. 운영체제는 본래 여러 프로그램을 실행하므로 그 자체가 문제입니다. 유니커널은 하나만 실행합니다.
- @fsflover — “운영체제 자체가 문제입니다. 본래 여러 프로그램을 실행하기 때문이고, 유니커널은 하나만 실행합니다.” 보안 구획화에 의존하는 경우는 다릅니다. Qubes OS를 보세요.
- @eyberg — 솔직히 제가 활동하는 Nanos와 Qubes에는 비슷한 점이 많다고 봅니다. 큰 차이는 Qubes가 데스크톱과 소비자용에 가깝고 Nanos는 서버용이라는 점입니다. 환경에 따라 설계가 달라지지만 같은 이념과 원칙이 드러납니다.
- @terabytest — 제가 요점을 놓친 것일 수 있지만, 운영체제의 목적은 파일시스템과 네트워크를 매번 직접 바이브 코딩하지 않는 데 있지 않나요? 유니커널은 다른 애플리케이션과 어떻게 협력하나요? 하이퍼바이저가 관리하는 네트워크 연결형 유니커널을 따로 띄우나요? 각자 파일시스템과 네트워크를 구현하면 미묘한 버그와 불일치가 생겨 결국 공유 프리미티브가 필요해지지 않나요? 공통 네트워크·파일시스템 라이브러리를 표준에 맞춰 재사용하는 절충안이 나을 수도 있겠습니다.
- @cmrdporcupine — 네트워크나 파일시스템을 매번 직접 만드는 게 아닙니다. 검토와 유지관리를 거친 라이브러리를 저장소에서 가져옵니다. MirageOS 같은 프로젝트가 그렇게 작동합니다. 누군가 TCP/IP를 작성하고 애플리케이션에 연결합니다. 운영체제와 다른 점은 공유 서비스나 시스템 호출이 없고, 서브루틴 호출을 쓴다는 것입니다. 하이퍼바이저 수준을 제외하면 시분할도 없습니다. 가상화된 하드웨어에서 실행하는 단일 런타임입니다. 이 기술이 달라진 배경에는 지난 30년 동안 하드웨어가 발전한 점도 있습니다. 그런데도 우리는 운영체제를 가장 좋은 자원 공유 단위로 취급합니다. 애플리케이션 하나를 실행하려고 여러 사용자와 프로그램을 함께 돌리도록 만든 거대한 Linux 커널을 부팅한다면 검토할 거리가 있습니다. 유니커널 생태계가 미성숙한 점은 별개입니다. “매번 바이브 코딩한다”는 말을 강조할 필요는 없습니다. 글에서 말하는 건 에이전트 도구로 생태계의 빈틈을 더 빨리 메울 수 있다는 점입니다.
- @Joker_vD — “하이퍼바이저에서 가상화된 하드웨어를 직접 실행한다”고 했습니다. 그렇다면 실제 운영체제는 하이퍼바이저입니다. 이름과 시스템 인터페이스를 바꿨을 뿐, 하드웨어 접근을 다시 가상화하고 사용자와 애플리케이션을 분리합니다.
- @cmrdporcupine — 이름을 어디에 붙일지는 별로 중요하지 않습니다. MirageOS에도 이름에 “OS”가 들어갑니다. 중요한 건 코드 전체 크기, 권한과 보안, 메모리 관리, 드라이버와 프로세스 관리가 달라진다는 점입니다.
- @teiferer — 하이퍼바이저 아래에서 N개의 유니커널을 VM으로 실행하면, 기존 커널을 쓰는 잠금된 OS에서 정적 바이너리를 돌리는 것과 어떻게 다른가요? 글에서도 KVM 탈출을 언급하듯 유니커널에서도 빠져나올 수 있습니다. 이름만 달리 부르는 것 아닌가요? 앱은 유니커널과 앱이 되고 커널은 하이퍼바이저가 됩니다.
- @torginus — 둘 다 약점은 있습니다. 하지만 OS에서는 앱 메모리 페이징, 별도 주소 공간, 사용자 공간과 커널 공간의 데이터 구조 중복, 시스템 호출 비용 같은 병목이 생깁니다. 이 경우 OS가 하드웨어 접근을 중재하지 않으므로 불필요한 복잡성과 비용이 됩니다. 그렇다고 유니커널이 더 안전하다고 단정하긴 어렵지만, 문제가 생길 만한 복잡성은 훨씬 줄어듭니다.
- @scottlamb — 이 글은 완전한 OS가 주는 이점을 과소평가합니다. “유니커널에서는 관측 표면이 훨씬 작습니다. 애플리케이션에 기능이 없다면 SRE는 다음 경로가 없어 곤란해집니다”라고 바꿔 말할 수도 있습니다.
strace, eBPF,lsof,ss같은 도구는 큰 가치가 있습니다. 글은 구조화 로그와 OpenTelemetry를 언급하지만 관측 기능을 많이 버립니다.- @FridgeSeal — 앱만 실행하고 커널 전체가 라이브러리라면 필요한 만큼 그 라이브러리에 관측 기능을 넣으면 됩니다. 그러면 CPU와 I/O를 어느 프로세스가 쓰는지 걱정할 필요도 없습니다. 전부 한 프로세스니까요.
- @tkfu — 글은 LLM이 유니커널 개발을 쉽게 만들고, 전체 OS 스택이 공격 표면을 키운다는 주장입니다. 하지만 LLM으로 Linux를 제대로 강화하는 일도 쉬워졌습니다. 실제 애플리케이션에 맞는 설정과 커널 명령줄을 쓰고 KSPP 권고를 적용하며 MAC LSM을 제대로 설정하면 작년의 대형 취약점 상당수를 피할 수 있었습니다. 에이전트에게 라이브러리 포팅을 맡기면서 결과를 신뢰한다면, Linux 강화도 맡기지 못할 이유가 있나요? LLM을 보안 문제의 답으로 지지하는 건 아니지만, 글의 비교는 같은 조건을 놓고 한 비교가 아닙니다.
- @KaiserPro — 유니커널의 보안 이점은 단순히 참과 거짓으로 나뉘지 않습니다. 이론상 공격 표면은 작지만 실제로 꼭 그런 것은 아닙니다. 필요 없는 도구를 빼면 횡적 이동은 훨씬 어려워져도, 첫 침입을 막지는 못합니다. 포팅한 라이브러리의 취약점을 찾고 업데이트하는 책임도 직접 져야 합니다. 어떤 버전이 들어갔는지, 포팅 과정에서 같은 버그가 생겼는지, LLM이 잘못 옮기지는 않았는지 확인해야 합니다. “유니커널이면 안전하다”는 말은 기껏해야 오해를 부릅니다.
원문: Hacker News / 번역·요약: Trawling