1. 개요

gVisor 는 컨테이너 안의 앱이 부르는 시스템 콜을 호스트 커널 대신 받아 처리하는 사용자 공간 커널이다. Google 이 Go 로 만들었고, OCI 런타임 runsc 로 쓴다.

일반 컨테이너(runc)는 Namespace 와 cgroup 으로 칸을 나눌 뿐, 앱의 시스템 콜은 모두 호스트 커널이 그대로 처리한다. 커널 취약점 하나로 컨테이너를 빠져나갈 수 있는 이유다. gVisor 는 앱과 호스트 커널 사이에 커널을 하나 더 끼워, 앱이 호스트 커널에 직접 닿는 길을 줄인다.

runc                         gVisor (runsc)

 앱                           앱
  │ 시스템 콜                  │ 시스템 콜
  ▼                           ▼
 호스트 커널                   Sentry (gVisor 커널, 사용자 공간)
                               │ 꼭 필요한 일부 시스템 콜만
                               ▼
                              호스트 커널

컨테이너 안에서 uname -r 을 찍으면 호스트 커널이 아니라 gVisor 가 보여 주는 커널 버전이 나온다.

2. 구성 요소

구성 요소하는 일
runscOCI 런타임. runc 자리에 들어가 샌드박스를 만들고 컨테이너를 띄운다
SentrygVisor 의 커널. 앱의 시스템 콜·메모리·시그널·파일 시스템을 처리한다
Gofer호스트 파일 시스템 접근을 대신 맡는 별도 프로세스
NetstackgVisor 자체 TCP/IP 스택. 앱의 네트워크를 호스트 커널 스택 대신 처리한다
containerd-shim-runsc-v1containerd 가 runsc 를 부를 때 쓰는 shim

최근 릴리스 묶음은 runsc 실행 파일 하나가 아니라, runsc 옆의 gvisor-bin/ 디렉터리에 Sentry 등 보조 프로그램을 따로 둔다. runsc 만 설치하면 샌드박스가 만들어지지 않는다.

gvisor.tar.bz2
├── runsc
├── containerd-shim-runsc-v1
└── gvisor-bin/
    ├── gvisor_sentry
    ├── gvisor-sentry-prewarmer
    ├── checkpointgofer
    ├── runsc-fd-parking
    └── runsc-metric-server

3. 플랫폼

플랫폼은 앱의 시스템 콜을 Sentry 로 가로채는 방법이다.

플랫폼방식쓰는 곳
systrapseccomp 의 trap 으로 시스템 콜을 가로챈다기본값. 일반 VM·클라우드 인스턴스
KVM하드웨어 가상화로 가로챈다KVM 을 쓸 수 있는 bare metal 등
ptraceptrace 로 가로챈다예전 기본값. 느려서 권장하지 않음

AWS 의 일반 EC2 인스턴스(t3, m5a 등)는 중첩 가상화를 주지 않으므로 systrap 으로 돈다.

4. 쿠버네티스 연결

쿠버네티스는 RuntimeClass 로 Pod 마다 런타임을 고른다.

apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: gvisor
handler: runsc            # containerd 설정의 런타임 이름
---
apiVersion: v1
kind: Pod
spec:
  runtimeClassName: gvisor

노드의 containerd 에는 같은 이름의 런타임을 등록한다.

# containerd 2.x (config version 3)
[plugins."io.containerd.cri.v1.runtime".containerd.runtimes.runsc]
  runtime_type = "io.containerd.runsc.v1"

runtimeClassName 이 없는 Pod 는 그대로 runc 로 돈다. 핸들러는 있는데 runsc 바이너리가 없으면 그 Pod 는 뜨지 않는다(FailedCreatePodSandBox).

관리형 지원은 클라우드마다 다르다.

클라우드gVisor 지원
GKEGKE Sandbox (노드 풀 옵션)
EKS관리형 옵션 없음. 노드 부팅 스크립트나 AMI 로 직접 설치

5. seccomp 와의 관계

gVisor Pod 안에서는 seccomp 필터가 적용되지 않는다(/proc/self/status 의 Seccomp: 0). 시스템 콜을 Sentry 가 받으므로 seccomp 가 막을 대상이 호스트 커널까지 내려가지 않는다. gVisor 자체가 그 역할을 한다.

다만 Pod Security restricted 는 seccompProfile 설정을 요구한다. 설정을 지우면 Pod 가 거부되므로, 실제로 적용되지 않더라도 RuntimeDefault 를 남겨 둔다.

6. 비용과 제약

항목내용
성능시스템 콜이 많은 작업(파일 I/O, 많은 작은 네트워크 요청)이 느려진다. CPU 만 쓰는 계산은 차이가 작다
호환성모든 리눅스 시스템 콜을 구현하지는 않는다. 드문 기능을 쓰는 앱은 실패할 수 있다
네트워크Netstack 을 거치므로 CNI 의 일부 소켓 단계 기능(예: Cilium 소켓 LB)이 적용되지 않는다
운영관리형이 아니면 버전 관리·설치를 직접 한다

7. 다른 샌드박스와 비교

방식격리 수준필요한 것
runcNamespace·cgroup. 커널 공유없음
gVisor사용자 공간 커널일반 VM 에서 동작
Kata Containers경량 VM하드웨어 가상화 (클라우드에서는 보통 bare metal)
FirecrackermicroVM하드웨어 가상화
AWS FargatePod 마다 microVM관리형. DaemonSet 불가

8. 관련 문서

  • CNI — Pod 네트워크를 붙이는 규격. gVisor Pod 도 CNI 가 만든 인터페이스를 쓴다
  • Cilium — gVisor 와 함께 쓸 때 socketLB.hostNamespaceOnly 가 필요하다
  • IMDS — 컨테이너 탈출이 노리는 노드 IAM 권한의 출처
  • CRI — kubelet 이 containerd 를 부르는 규격
  • seccomp (예정) — 커널이 허용할 시스템 콜을 거르는 필터
  • Pod Security (예정) — restricted 수준의 요구 사항

9. 출처