A Process In Isolation, 프로세스 단위의 고립성 수준을 이용하는 도커 컨테이너
도커 컨테이너의 8가지 주요 특징
MNT - filesystem access and structure
chroot() - Controls location of filesystem root
Cgroups - Resource protection
PID - Process identifiers and process capabilities
NET - Network access and structure
UTS - Host and domain name
USR - Usernames and identifiers
IPC - Communication by shared memory
6.1 자원 사용 가능 제어
주어진 물리 머신에서 CPU 사용과 메모리의 자원은 한정적이다.
6.1.1 메모리 제한
도커를 생성하거나 시작할 때 -m, --memory 옵션을 사용하면 메모리 사용 제한을 걸 수 있다.
docker container run -d
--name ch6_mariadb
--memory 256m
--cpu-shares 1024
--cap-drop net_raw
-e MYSQL_ROOT_PASSWORD=test
mariadb:5.5
메모리 제한 옵션은 해당 메모리 크기 만큼 예약을 하는 것이 아니다. 과다 사용만을 방지하는 옵션이다.
과다 사용이 탐지되는 경우 리눅스 커널에서 이를 효율적으로 방지한다.
어플리케이션마다 해당 과다 사용에 대한 에러 발생에 대한 처리가 필요할 수 있으며 얼마나 많은 메모리를 사용할 것 인가에 대한 판단이 필요하다.
6.1.2 CPU 제한
CPU 사용에 대해 옵션으로 제어할 수 있다.
--cpu-shares 옵션은 도커 컨테이너가 다른 컨테이너 대비 얼마 만큼이나 CPU를 사용할 수 있는 지를 가중치로 지정한다.
--cpus 옵션은 최대 x 개의 CPU를 사용할 수 있도록 하는 옵션이다.
--cpuset-cpus 옵션은 멀티 코어 시스템에서 특정 CPU를 사용하고 context-switch 비용을 낮추도록 한다.
외부 디바이스 접근 제어
호스트에 설치된 웹캠과 같은 디바이스를 컨테이너에 주입하여 사용할 수 있도록 한다.
docker container run -it --rm --device /dev/video0:/dev/video0 ubuntu:16.04 ls -al /dev
6.2 메모리 공유
프로세스 간 메모리를 공유(interprocess communication)하는 방법을 제공한다.
IPC를 사용하는 도커는 각 컨테이너마다 고유의 IPC 이름 공간을 생성한다. linux가 제공하는 IPC는 이름 공간으로 분리된 shared memory, 세마 포어, 메시지 큐와 같은 기본적인 공유 메모리를 제공한다.
docker container run -d -u nobody --name ch6_ipc_producer --ipc shareable dockerinaction/ch6_ipc -producer
docker container run -d -u nobody --name ch6_ipc_consumer --ipc container:ch6_ipc_producer dockerinaction/ch6_ipc -consumer
- ch6_ipc_producer 컨테이너는 "shareable" 공유 가능한 ipc를 가진 컨테이너이다. (--ipc shareable)
- ch6_ipc_consumer 컨테이너는 ch6_ipc_producer 컨테이너의 IPC를 조인하여 실행한다. (--ipc container:ch6_ipc_producer)
- --ipc=host 옵션의 경우 호스트와 공유 가능하다.
6.3 Users
도커 컨테이너를 시작하면 이미지 메타데이터에 기록된 기본 유저를 사용한다. (주로 root 유저)
root 유저는 컨테이너 상태에 모든 접근 권한을 가진다.
이미지를 pull 한 이후 inspect 명령어를 사용하여 유저 이름을 확인할 수 있다.
docker image pull busybox:1.29
docker image inspect busybox:1.29
docker inspect --format "{{.Config.User}}" busybox:1.29
결과가 비어있다면, 컨테이너는 root 유저로 실행 중인 것이다. 그렇지 않다면, 이미지에 run-as 로 지정된 유저를 사용하거나 컨테이너를 생성할 때 지정한 유저가 출력된다.
linux는 미리 정의된 유저들을 사용한다. 다음과 같이 이미지에서 사용가능한 유저들을 알아 볼 수 있다.
docker contaienr run --rm busybox:1.29 awk -F: '$0=$1' /etc/passwd
위 리스트 중 유저를 선택하여 컨테이너를 시작한다면, 다음과 같이 -u 혹은 --user 옵션을 사용한다.
docker container run --rm --user nobody busybox:1.29 id
유저 이름을 지정하는 대신 UID를 직접 지정하여 유저를 설정할 수 있다.
docker container run --rm -u nobody:nogroup busybox:1.29 id
docker container run --rm -u 10000:20000 busybox:1.29 id
user:group 혹은 UID:GID, 유저와 그룹을 설정한다.
6.3.2 유저와 볼륨
볼륨으로 마운트한 파일에 호스트의 유저 중 하나로 소유자가 지정된 경우, 컨테이너에 지정된 유저가 접근이 허용되지 않을 수 있다.
root 유저 권한으로 지정한 파일을 컨테이너에 마운트 한 경우 같은 파일 권한을 가진다. 즉, root 유저가 아니라면 파일 접근이 허용되지 않게 된다.
6.3.3 linux user namespace와 UID remapping
linux의 user namespace(USR)는 유저를 한 이름 공간에서 다른 이름 공간의 유저로 맵핑한다. user namespace는 PID namspace 와 같이 컨테이너 UIDs와 GIDs는 호스트의 기본 개체들로 부터 할당된다.
도커는 USR namespace 기능을 기본값으로 사용하지 않는다. 그렇게 해야 호스트로 부터 마운트한 파일들 권한 유저를 컨테이너에서도 같은 유저 (UID)로 유지 할 수 있기 때문이다.
USR namespace 기능은 호스트 유저 중 권한을 상속받지 않은 유저를 컨테이너에서 사용하려 할 때 동작한다. 기능은 subuid와 subgid을 정의하고 usernamespace remapping을 한다. 그리고 도커 데몬 서비스의 userns-remap 설정을 구성한다. 맵핑은 호스트의 user namespace 에서 컨테이너의 user namspace 맵핑을 정의한다.
예를 들면 호스트의 5000 번 부터 시작하는 UID는 총 1000개의 UID 에 대해 컨테이너 내부에서는 0번 부터 1000번대까지로 맵핑한다.
6.4 OS 기능 사용하기 (capabilities)
host가 linux 일 경우 capabilties 기능은 컨테이너의 OS 기능을 선택적으로 상속한다.
컨테이너를 시작할 경우, 도커는 특별히 어플리케이션에 필요하여 명시적으로 지정하지 않은 경우를 제외 하고 모든 capabilites를 drop 한다.
drop 되는 capbilities는 다음과 같다.
SYS_MODULE - Insert/remove kernel modules
SYS_RAWIO Modify kerner memory
SYS_NICE Modify priorty of processes
SYS_RESOURCE override resource limits
...
추가로 capabilities를 drop 하고자하는 경우 --cap-drop 옵션을 지정하여 컨테이너를 실행한다.
docker container run --rm -u nobody \
--cap-drop net_raw ubuntu:16.04 /bin/bash -c "capsh --print | grep net_raw"
--cap-add 옵션은 반대로 capability를 컨테이너로 상속한다.
6.5 full previlege로 컨테이너 실행하기
시스템 관리자로서 컨테이너 내부에 작업을 수행해야할 때 유용하다. full previlege 컨테이너는 고립된 파일 시스템과 네트워크를 유지하지만 공유 메모리와 디바이스에 대한 전체 접근 권한과 system capabilites를 모두 획득한다.
docker container run --rm --priviledged ubuntu:16.04 id // check IDs
docker container run --rm --priviledged ubuntu:16.04 cpash --print // check capabilities
docker container run --rm --priviledged ubuntu:16.04 ls /dev // check list of mounted devices
6.6 고급 도구로 컨테이너 사용하기
현대 linux 커널은 seccomp 도구를 제공하는데 강력한 시스템 보안 기능을 제공한다.
도커의 기본 seccomp는 40 개의 커널 시스템 콜을 사용하지 못 하게 한다. 또한 추가 도구를 사용하여 도커 컨테이너를 강화할 수 있다. 예를 들면, seccomp 프로필을 커스터마이즈 하거나 AppArmor, SELinux 와 같은 도구가 있다.
6.6.1 추가 보안 옵션 지정하기
--security-opt 플래그는 리눅스의 seccomp 와 Linux Security Modules (LSM) 기능을 구성한다.
Seccomp은 리눅스 시스템 콜을 제어한다. 도커의 기본 seccomp 프로필은 기본적으로 모든 시스템 콜을 차단하며 260개의 명시한 시스템 콜만 안전하다고 보고 허용한다. 44개의 시스템 콜은 보통 프로그램에서 호출되지 않게 한다.
seccomp 프로필을 설정하려면 다음과 같이 커스텀 프로필 파일을 제공한다.
docker contaienr run --rm -t --security-opt seccomp=<FULL_PATH_TO_PROFILE> ubuntu:16.04 sh
Linux Security Modules (LSM)는 프레임워크로 리눅스 OS와 보안 기능 공급자 사이의 인터페이스를 제공한다. AppArmor와 SELinux는 그러한 보안 기능 공급자 (security providers)이다. ACL이나 MAC 주소 검증 그리고 기본 리눅스 discrtionary access control을 대체하는 기능을 제공한다.
6.7 어플레케이션 고려 사항
해커에게 취약하지 않은 어플리케이션을 실행하고 운영하는 방법
- 제한된 권한을 가진 유저로 어플리케이션을 실행한다.
- system capabilites를 제한한다. 시스템 구성 설정이 보호될 것이다.
- CPU와 메모리 사용량을 제한한다. 호스트 머신의 필수적인 프로세스들의 높은 반응성을 유지시켜줄 것이다.
- 접근하는 디바이스를 제어한다. webcam, usb를 목적에 맞지 않은 사용을 방지하자.
요약
- 도커는 cgroup을 사용하여 메모리 제한과 CPU 가중치 할당, 제한, 코어 할당, 디바이스 접근 제어를 가능하게 한다.
- 각 컨테이너는 고유의 IPC 이름 공간을 가지며, 다른 컨테이너 혹은 호스트와 공유하여 공유 메모리를 접근할 수 있게 한다.
- 도커는 격리된 USR namespace를 사용한다. 기본적으로 호스트와 같은 user, group ID를 사용하지만 호스트에 있지 않은 컨테이너의 user, group ID는 호스트로 부터 재맵핑된다.
- --user 옵션으로 root 유저가 아닌 컨테이너를 실행할 유저를 지정할 수 있다.
- previledge 모드 관리자 작업을 가능하게 한다 가능하다면 previledge 모드로 컨테이너를 실행하지 말자.
- linux capabilites는 OS 기능 권한을 제공한다. 도커는 격리의 이유로 몇몇 capabilites를 호스트로부터 상속하지 않는다.
- capbilites 상속 혹은 제거는 --cap-add 또는 --cap-drop으로 가능하다.
- 더 격리된 환경을 제공하고 높은 보안 수준을 위해 seccomp, SELinux, AppArmor와 같은 도구를 같이 사용하여 컨테이너 실행하는 것을 고려하라.
'Cloud > Docker' 카테고리의 다른 글
Docker In Action 8. Building image automaticall with Dockerfiles (1) | 2024.12.08 |
---|---|
Docker In Action 7. Packaging software in images (1) | 2024.12.06 |
Docker In Action 5. Single-host networking (0) | 2023.10.22 |
Docker In Action 4. Working with Storage and Volumes (0) | 2023.10.19 |
Docker In Action 3. Software Installation Simplified (0) | 2023.10.16 |