이쿠의 슬기로운 개발생활

함께 성장하기 위한 보안 개발자 EverNote 내용 공유

Kubernetes/Kubernetes 보안

gVisor와 runtimeclass

이쿠우우 2022. 6. 8. 19:35
반응형

 

gVisor

 
 

목표

kubernetes gVisor는 무엇이며, 
어떤 경우에 사용해야하고
어떻게 사용해야하는지 알아봄
 

 

Container 취약점

 
container runtime tool을 통해 생성된 일반적인 Container는 
아래와 같이 Host의 kernel을 공유하고 있음. 

 
실제로 확인해보면 다음과 같이 container에서 실행한 system call 명령이
container에서 실행한 결과와 host의 결과가 동일한 것을 확인할 수 있음.

 

이러한 container의 특징은 보안적으로 문제가 될 수 있음.
다음과 같이 특정 container를 통해서 공격자가 kernel에 접근해서 다른 container를 공격할수도 있고
host kernel자체를 공격할 수 있음.
예를 들면 Dirty Cow 취약점이 있음.

 

 
그렇기 때문에 external network에서 접근 가능한 container라던가
또는 다른 방식으로 노출되어있는 container에 대해서는 보안 기능이 추가로 들어가야함.
이에 대한 해결책으로 gVisor가 있음.
 
 

 

 
 
 

gVisor

 VM과 Container의 가장 큰 차이점이라면
VM은 하드웨어 계층부터 가상화 해서 host kernel을 공유하지 않음.
하지만 Container는 위에서 설명한대로 host kernel을 공유함.
gVisor는 이러한 VM과 Container의 장점을 조합해서 만든 프로젝트로
linux의 sanbox기능을 활용해 container가 host의 kernel을 격리시켜주는 tool임.
한줄로 설명하자면 sanbox container 생성 tool이라고 생각하면 됨.

 

위 그림과 같이 container와 kerenl 사이에 gVisor가 존재해서
container가 host의 kernel에 접근하지 못하게 해줌.
 
license : Apache License 2.0
개발언어 : Golang
개발사 : Google
 

sandbox란?

sandbox는 OS의 kernel영역에는 영향을 주지 않도록 
각자의 박스 즉 고유의 영역에서만 리소스를 사용하도록 해주는 기술.
 
 
 

 

 

kubernetes runtimeclass

 
kubernetes에 gVisor container를 배포하기 위해서는 
먼저 runtimeclass에 대해 알아야함.
 

kubernetes runtimeclass란?

kubernetes는 최초설치될 때 있던 container runtime tool을 통해 container를 생성함.
하지만 runtimeclass를 사용한다면 
pod로 container를 생성 시 어떤 container runtime tool을 사용할건지 지정이 가능함.
 
[runtimeclass 예제]
runtimeclass 생성
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: myclass
handler: myconfiguration # container 생성 시 사용하고자 하는 CRI를 설정.
 
test로 존재하지 않는 CRI를 입력하고 pod를 생성해봄.
runtimeclass를 생성하고

 
pod에 runtimeclass를 설정함
runtimeClassName: testclass

 
pod생성 결과를 확인해보면 ContainerCreating상태에서 멈춤
log를 확인해보면 다음과 같음
 
[error]
Failed to create pod sandbox: rpc error: code = Unknown desc = failed to get sandbox runtime: no runtime for "test" is configured

 
test라는 CRI가 없어서 container를 생성하지 못함.
즉 runtimeclass 사용 시 host에 있는 CRI를 지정해줘야함.
 

 

 

 

runtimeclass로 사용가능한 CRI 확인

 
먼저 node에서 사용중인 container runtime을 확인
예제는 containerd를 사용 중임.

 
containerd의 CRI를 확인해야함
containerd의 경우 /etc/containerd/config.toml 파일을 통해 확인 가능
해당 파일에서 
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.${HANDLER_NAME}]
부분을 확인.

확인해보니 runc 임을 확인할 수 있음.
 
 
runtimeclass의 handler를 runc로 입력
apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: testclass
handler: runc
 
정상적인 cri를 입력하니 해당 cri로 pod가 생성됨.
 
 

 
 
 

kubernetes gVisor

 
kubernetes에서 gVisor를 사용해보겠음.
 

gVisor install

 
kubernetes cluster를 구성하는 node에 설치
 
[1. default tool 설치] 
sudo apt-get update && \
sudo apt-get install -y \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common
 
 
[2. gVisor install]
문서의 Install latest release 항목 확인
(
  set -e
  ARCH=$(uname -m)
  wget ${URL}/runsc ${URL}/runsc.sha512 \
    ${URL}/containerd-shim-runsc-v1 ${URL}/containerd-shim-runsc-v1.sha512
  sha512sum -c runsc.sha512 \
    -c containerd-shim-runsc-v1.sha512
  rm -f *.sha512
  chmod a+rx runsc containerd-shim-runsc-v1
  sudo mv runsc containerd-shim-runsc-v1 /usr/local/bin
)
 
 
[3. /etc/containerd/config.toml 파일 편집]
설치 시 gVisor 설치 및 
containerd의 경우
/etc/containerd/config.toml 파일에 cri를 추가해줘야함.
gVisor 전용 cri의 경우 "runsc"
  [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runsc]
    runtime_type = "io.containerd.runsc.v1"
 
 
[4. containerd 재기동]
systemctl restart containerd
 
 
[gVisor 설치 참고]
 
 

gVisor runtimeclass 생성

apiVersion: node.k8s.io/v1
kind: RuntimeClass
metadata:
  name: testclass
handler: runsc
 

gVisor를 사용한 pod 생성

apiVersion: v1
kind: Pod
metadata:
  labels:
    run: testpod
  name: testpod
spec:
  runtimeClassName: testclass
  containers:
  - image: nginx
    name: testpod
 

pod가 gVisor로 실행되고 있는지 확인

 
[명령어]
kubectl exec testpod -- dmesg | grep -i gvisor

 

gVisor로 실행되면 host kernel과 격리되는지 확인

실제로 container 내부에서 system call 명령을 확인해보면
container의 결과와 host의 결과가 다른 것을 확인할 수 있음.

 


 
참고
 
drity cow

 

반응형