docker에 설치된 호스트에는 다수의 운영 체제 프로세스나 deamon, ssh 서버 등으로 실행되는 프로세스의 집합을 가지고 있다. 가상머신과 달리 컨테이너는 호스트로부터 완전히 격리되어 있지 않다. 그래서 컨테이너와 호스트가 같은 커널을 공유한다.
컨테이너는 리눅스에서 namespace를 이용해 격리된다. 컨테이너에 의해 실행되는 모든 프로세스는 호스트 자체에서 실행되지만 고유의 네임스페이스에서 실행된다.
고유의 네임스페이스에 있어 고유의 프로세스만 볼 수 있다. 바깥이나 다른 네임스페이스에서는 볼 수 없다.
sleep 3600 명령어를 수행하는 docker conatainer 내에서 ps aux 명령어로 docker contaner 내의 프로세스를 나열하면 PID 1로 sleep 3600 프로세스를 볼 수 있다.
호스트에서 ps aux 명령어로 호스트 내의 프로세스를 나열하면 sleep 3600를 실행 중인 다른 PID를 확인할 수 있다.
이는 프로세스가 다른 네임스페이스에서 다른 PID를 가질 수 있기 때문이다. 이것이 docker가 시스템 내에서 컨테이너를 격리하는 방식이다.
docker 호스트는 루트 유저 한 명과 다수의 비루트 유저로 이루어진 사용자 집합을 갖고 있다.
기본값으로 docker는 루트 사용자로서 컨테이너 내의 프로세스를 실행한다. 컨테이너 안과 밖의 모든 프로세스는 루트 사용자로 실행된다.
컨테이너 내의 프로세스가 루트 사용자로 실행되길 원하지 않는다면 docker run 명령 안에서 '--user' 옵션을 사용해 사용자를 설정하고 새 사용자 ID를 명시하면 된다. 명시된 USER ID로 프로세스가 실행되는 것을 확인할 수 있다.
사용자 보안을 실행하는 또 다른 방법은 Dockerfile에서 USER를 지정하는 것이다.
docker는 컨테이너 내 루트 사용자의 능력을 제한하는 보안 기능을 제공한다.
컨테이너 안의 루트 사용자는 호스트의 루트 사용자와는 다르다.
docker는 이것을 구현하기 위해 리눅스 기능을 사용한다.
루트 사용자는 시스템에서 가장 강력한 사용자이다. 루트 사용자는 뭐든 할 수 있고 루트 사용자에 의한 프로세스도 마찬가지로 시스템의 제한 없이 접근할 수 있다. '/usr/include/linux/capability.h'에서 루트 사용자가 할 수 있는 기능의 리스트를 확인할 수 있다.
기본값으로 docker는 컨테이너의 기능을 제한한다.
호스트를 재부팅하거나 같은 호스트에서 실행되는 호스트나 다른 컨테이너를 방해할 수 없다.
이 동작을 재정의하고 추가적인 특권을 제공하고 싶다면 docker run 명령에 '--cap-add [추가할 권한]' 옵션을 추가하면 된다.
드롭 특권을 사용하고 싶다면 '--cap-drop [제거할 권한]' 옵션을 사용하면 된다.
모든 권한이 활성화된 컨테이너를 실행하고 싶다면 '--previleged' 옵션을 사용하면 된다.
지난 강의에서 봤듯이 docker 컨테이너를 실행할 때 보안 표준 집합을 정의할 옵션이 있다.
쿠버네티스에서도 설정할 수 있다.
쿠버네티스에서는 컨테이너를 파드에 넣어 보관한다. 그래서 컨테이너 수준이나 파드 수준에서 보안 설정을 선택할 수 있다.
파드 수준으로 설정하면 파드 내 모든 컨테이너에 설정값이 전달된다.
파드 정의 파일에서 securityContext 영역을 통해 파드 수준의 보안 설정을 할 수 있다.
runAsUser 필드으로 파드 사용자 ID를 설정한다.
컨테이너 수준에서 보안을 설정하려면 containers 영역에 securityContext 영역을 추가하면 된다.
그리고 capabilities 영역에 추가할 기능 목록을 명시하면 된다. capabilities 영역은 컨테이너 수준에서만 지정 가능하다!
테스트 문제 기록
kubectl exec ubuntu-sleeper -- whoami
apiVersion: v1
kind: Pod
metadata:
name: ubuntu-sleeper
namespace: default
spec:
securityContext:
runAsUser: 1010
containers:
- command:
- sleep
- "4800"
image: ubuntu
name: ubuntu-sleeper
apiVersion: v1
kind: Pod
metadata:
name: ubuntu-sleeper
namespace: default
spec:
containers:
- command:
- sleep
- "4800"
image: ubuntu
name: ubuntu-sleeper
securityContext:
capabilities:
add: ["SYS_TIME", "NET_ADMIN"]
테스트 통과 완료