블로그

멀티 테넌트 호스팅을 위한 Docker 컨테이너 강화: 단계별 격리 가이드

멀티 테넌트 환경에서 Docker 컨테이너를 안전하게 보호하는 방법을 알아보세요. 비루트 사용자, 권한 삭제, 읽기 전용 파일 시스템, 네트워크 격리와 같은 실용적인 보안 조치를 다룹니다.

요약

멀티 테넌트 Docker 호스팅 플랫폼을 운영하려면 테넌트가 서로 간섭하거나 호스트로 탈출하는 것을 방지하기 위해 견고한 컨테이너 격리가 필요합니다. 이 가이드는 오늘 바로 적용할 수 있는 구체적이고 단계별 강화 프로세스를 제공합니다. 비루트 사용자 구성, 불필요한 Linux 기능 제거, 파일 시스템 읽기 전용 마운트, cgroup을 통한 리소스 제한 적용, 네트워크 분할, seccomp 또는 AppArmor 프로필 적용 방법을 배우게 됩니다. 또한 최대 보안을 위해 가상 머신으로 컨테이너를 보강해야 하는 경우도 다룹니다. 마지막으로 일반적인 컨테이너 탈출 벡터를 체계적으로 제거하고 멀티 테넌트 인프라를 진정으로 격리 상태로 유지하기 위한 체크리스트를 제공합니다.

멀티 테넌트 컨테이너의 실제 문제

Docker 컨테이너는 호스트 커널을 공유하며, 격리가 잘못 구성되면 한 테넌트가 다른 테넌트의 데이터에 접근하거나 모든 CPU를 소비하거나 호스트로 탈출할 수 있습니다. 호스팅 제공자로서 컨테이너의 성능 이점을 희생하지 않으면서 견고한 경계가 필요합니다. 많은 팀이 개발용으로 설계된 기본 Docker 설정으로 시작하지만, 이는 프로덕션 멀티 테넌시에 적합하지 않습니다. 좋은 소식은 체계적인 강화 체크리스트를 통해 Docker의 속도를 유지하면서 각 컨테이너를 VM 수준에 가까운 격리로 잠글 수 있다는 것입니다.

이 문서는 실용적인 예제와 주의 사항과 함께 각 강화 단계를 안내합니다. 마지막에는 안전한 멀티 테넌트 컨테이너를 배포하기 위한 반복 가능한 프로세스를 갖게 됩니다.

1단계: 컨테이너를 비루트로 실행

기본적으로 Docker 컨테이너는 root로 실행됩니다. 컨테이너가 손상되면 공격자는 컨테이너 내에서 root 권한을 획득하고 컨테이너 탈출을 시도할 수 있습니다. 먼저 Dockerfile에서 전용 사용자를 생성하고 전환하세요:

FROM ubuntu:22.04
RUN useradd -m appuser
USER appuser

주의 사항: 일부 프로세스(예: 1024 미만 포트 바인딩)는 root가 필요합니다. 이러한 경우 --cap-add 플래그를 사용하여 필요한 기능만 부여하고(예: --cap-add=NET_BIND_SERVICE) 계속해서 비루트 사용자로 프로세스를 실행하세요.

기본적인 격리에 대한 자세한 내용은 Docker에서 진정한 멀티 테넌트 격리 달성 가이드를 참조하세요.

2단계: 모든 Linux 기능을 제거하고 필요한 것만 다시 추가

Linux 기능은 root 권한을 작은 단위로 분할합니다. Docker 컨테이너에는 기본적으로 멀티 테넌트 호스팅에 너무 관대한 기능 집합이 포함되어 있습니다. 모두 제거하고 애플리케이션에 필요한 것만 다시 추가하세요:

docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE my-app

피해야 할 일반적인 기능: SYS_ADMIN(컨테이너 탈출), NET_RAW(패킷 스니핑), SYS_PTRACE(프로세스 디버깅). --security-opt no-new-privileges와 함께 docker run을 사용하여 setuid 바이너리를 통한 권한 상승을 방지하세요.

3단계: 루트 파일 시스템을 읽기 전용으로 마운트

공격자는 종종 컨테이너 파일 시스템에 악성 스크립트를 작성합니다. 루트 파일 시스템을 읽기 전용으로 설정하면 이를 방지할 수 있습니다:

docker run --read-only --tmpfs /tmp:rw,noexec,nosuid,size=64m my-app

--tmpfs/tmp/var/run과 같은 디렉토리에 임시 쓰기 가능 마운트를 생성합니다. noexec 플래그는 해당 마운트에서 실행을 방지합니다. 이 접근 방식은 공격자가 쓰기 가능한 디렉토리를 통해 피벗하도록 강제하며, 이를 모니터링할 수 있습니다.

4단계: cgroup으로 리소스 제한 적용

제한이 없는 컨테이너는 호스트 메모리나 CPU를 고갈시켜 서비스 거부 공격을 수행할 수 있습니다. Docker의 런타임 제약 조건을 사용하세요:

docker run --memory=512m --memory-swap=512m --cpus=0.5 --pids-limit=100 my-app
  • --memory--memory-swap는 하드 제한을 설정합니다(스왑 없음).
  • --cpus는 CPU를 제한합니다.
  • --pids-limit는 프로세스 수를 제한하여 포크 폭탄을 방지합니다.

주의 사항: 리소스 제한은 cgroup에 의해 적용되지만 네트워크를 통한 데이터 유출을 방지하지는 않습니다. 네트워크 격리(다음 단계)와 결합하세요.

5단계: Docker 사용자 정의 네트워크로 네트워크 분할

기본적으로 Docker 컨테이너는 브리지 네트워크를 공유합니다. 멀티 테넌트 설정에서는 각 테넌트의 네트워크 스택을 격리해야 합니다. 테넌트당 전용 네트워크를 생성하세요:

docker network create tenant-alpha --internal
docker run --network tenant-alpha my-app

--internal 플래그를 사용하여 아웃바운드 인터넷 액세스를 차단한 다음 -p를 통해 필요한 포트만 노출하세요. 고급 네트워크 분할에 대해서는 Docker 격리로 웹 앱 보호를 고려하세요.

주의 사항: 내부 네트워크는 테넌트 간 직접 컨테이너 통신을 방지하지만 호스트 네트워킹을 사용하는 경우 DNS 누출이 발생할 수 있습니다. 브리지 또는 오버레이 네트워크를 사용하세요.

6단계: Seccomp 및 AppArmor 프로필 적용

Seccomp는 시스템 호출을 필터링하고 AppArmor(또는 SELinux)는 강제 액세스 제어를 적용합니다. Docker는 특정 플래그가 있는 clone과 같은 위험한 시스템 호출을 차단하는 기본 seccomp 프로필을 제공합니다. 더 엄격한 격리를 위해 사용자 정의 프로필을 생성하세요:

docker run --security-opt seccomp=./custom.json --security-opt apparmor=docker-default my-app

docker run --rm -it --security-opt seccomp=unconfined my-app strace -c -S time을 사용하여 기본 프로필을 생성한 다음 다듬을 수 있습니다. 주의 사항: 지나치게 제한적인 프로필은 합법적인 기능을 중단시킬 수 있습니다. 스테이징 환경에서 철저히 테스트하세요.

7단계: 가상 머신과의 하이브리드 격리 고려

테넌트가 절대적인 격리를 요구하는 경우(예: 규제 산업) 경량 VM 내에서 컨테이너를 실행하세요. Sysbox 또는 Kata Containers와 같은 도구는 컨테이너 속도를 희생하지 않으면서 하드웨어 수준의 분리를 제공합니다. 이는 Docker의 Enhanced Container Isolation(ECI)에서 사용하는 접근 방식입니다. 오버헤드는 일반 컨테이너보다 높지만 워크로드당 전체 VM보다는 훨씬 낮습니다.

올바른 격리 수준 선택에 대한 자세한 내용은 멀티 테넌트 Docker 아키텍처 설계를 읽어보세요.

종합: 강화 체크리스트

  1. 비루트 사용자로 컨테이너 빌드.
  2. 모든 기능 제거, 필요한 것만 추가.
  3. 임시 쓰기 가능 마운트로 파일 시스템 읽기 전용 마운트.
  4. 메모리, CPU, PID 제한 설정.
  5. 테넌트별 격리된 Docker 네트워크 생성.
  6. 사용자 정의 seccomp 및 AppArmor 프로필 적용.
  7. 높은 보안 요구 사항에 대해 하이브리드 VM 컨테이너 평가.

결론

컨테이너 강화는 일회성 작업이 아니라 지속적인 훈련입니다. 위의 단계는 멀티 테넌트 호스팅을 위한 보안 기준을 형성합니다. 단일 조치로 안전이 보장되지 않는다는 점을 기억하세요. 심층 방어가 핵심입니다. 기본 사항(비루트 사용자 및 기능 제거)부터 시작한 다음 리소스 제한 및 네트워크 분할을 계층화하세요. 가장 민감한 워크로드의 경우 컨테이너와 VM을 결합하세요. 이 가이드를 통해 효율적이고 안전한 멀티 테넌트 Docker 환경을 자신 있게 배포할 수 있습니다.

Sources (5)