마운트 네임스페이스
- 시스템이 시작(booted)되면, 하나의 마운트 네임스페이스가 있고 이것은
"initial namespace"
라고 불린다. 새로운 마운트 네임스페이스들은clone()
또는unshare()
시스템 콜 그리고CLONE_NEWNS
플래그를 사용하여 만들어진다. - 새로운 마운트 네임스페이스가 생성되면, 그 새로운 네임스페이스는
clone()
또는unshare()
을 호출한 놈의 네임스페이스로 부터 (호출한 놈의)마운트 포인트 리스트의 복사본을 받는다.- 마운트 포인트 리스트 위치 -
/proc/mounts
- 마운트 포인트 리스트 위치 -
clone()
또는unshare()
시스템 콜에 따르면, 마운트 포인트들은 각각의 네임스페이스에서 독립적으로 추가되거나 제거될 수 있다(mount()
,umount()
를 통해서).- 마운트 포인트 리스트의 변경사항들은 프로세스가 거주하는 마운트 네임스페이스의 프로세스들에만 보여진다. 다른 마운트 네임스페이스에서는 변경사항들이 보이지 않는다.
Shared subtress
- 일단 마운트 네임스페이스의 구현이 완료되면, 유용성(usability) 문제를 맞닥뜨린다.
- 마운트 네임스페이스는 네임스페이스간 너무 강력한 격리(isolation)를 제공한다.
- 예를 들어, 새 디스크가 광디스크 드라이브에 로드된다고 하자. 원래 구현에서, 모든 마운트 네임스페이스에서 디스크를 보이게할 수 있는 유일한 방법은 각각의 네임스페이스에 따로 디스크를 마운트해야 한다.
- 대부분의 경우, 시스템에서 모든 마운트 네임스페이스에서 디스크를 볼 수 있게 만드는 마운트 명령은 한번만 수행하는 것이 바람직하다.
- 이러한 문제 때문에
shared subtrees feature
이Linux 2.6.15
버전에 추가되었다.shared subtrees
의 주요 이점은 네임스페이스간 mount, unmount 이벤트가 자동으로 제어되고 전파될 수 있도록 하는 것이다.- 예를 들어, 한 마운트 네임스페이스에서 광디스크를 마운트 하는 것이 다른 모든 네임스페이스에서 해당 디스크의 마운트를 발생시킬 수 있다.
shared subtrees feature
아래, 각 마운트 포인트에는propagation type
이 표시되어 이 마운트 포인트 하에서 생성 및 제거된 마운트 포인트가 다른 마운트 포인트로 전파되는지 여부를 결정한다.- 4개의 다른
propagation type
이 존재한다.MS_SHARED
: 이 마운트 포인트는 'peer group'의 멤버인 다른 마운트 포인트들과 mount와 unmount 이벤트를 공유한다. 마운트 포인트가 이 마운트 포인트 하에서 추가되거나 제거될 때, 이 변경사항은 peer 그룹으로 전파되어, mount 또는 unmount가 각각의 peer 마운트 포인트 하에서 발생하게 된다. 전파는 역방향으로도 발생하므로 peer 마운트의 mount, unmount 이벤트는 이 마운트 지점까지 전파될 것이다.MS_PRIVATE
: 이것은 공유 마운트 포인트(shared mount point)의 반대이다. 마운트 포인트는 어떠한 peer에게도 이벤트를 전파하지 않으며, 어느 peer로부터로도 전파를 받지 않는다.MS_SLAVE
: 이 전파 타입은 shared와 private의 중간이다. 슬레이브 마운트는 멤버가 mount, unmount 이벤트를 슬레이브 마운트로 전파하는 공유 peer 그룹(shared peer group)인 마스터가 있다. 그러나 슬레이브 마운트는 이벤트를 마스터 peer 그룹에게 전파하지 않는다.MS_UNBINDABLE
: 이 마운트 포인트는 바인딩할 수 없다. private 마운트 포인트처럼, 이 마운트 포인트는 피어로 혹은 피어로부터 이벤트를 전파하지 않는다.
- +a
propagation type
은 마운트 포인트별 셋팅이다. 네임스페이스 내에서, 몇몇 마운트 포인트들은shared
로 표시될 수 있고 다른 마운트 포인트들은private
,slave
,unbindable
로 표시될 수 있다.propagation type
은 마운트 포인트 아래에서의 mount, unmount 이벤트의 전파를 결정한다. 따라서shared
마운트 X 아래에 하위(child) 마운트 Y를 생성하면 해당 하위 마운트가 peer 그룹의 다른 마운트 포인트로 전파된다. 하지만 X의propagation type
은 Y 아래서 생성되고 제거된 마운트 포인트에 대해 영향을 끼치지 않는다. Y에 따른 이벤트가 전파되는지 여부는 Y에 대해 정의된propagation type
에 따라 달라진다. 마찬가지로, X 마운트 포인트 그 자체가 unmount 될 때 unmount 이벤트가 전파될지 안될지는 X의 부모 마운트의propagation type
에 따라 달라진다.이벤트
는 한 마운트 포인트의 몇몇 mount 또는 unmount 동작이 하나 또는 다른 마운트 포인트와 일치하는 동작을 유발(trigger)시켰다는 의미를 담고있다.
Peer groups
- peer 그룹은 mount, unmount 이벤트들을 다른 마운트 포인트에 전파하는 마운트 포인트들의 셋이다.
- peer 그룹은
propagation type
이share
인 마운트 포인트가 새 네임스페이스 생성 중에 복제되거나 bind mount의 소스로 사용될 때 새로운 멤버들을 얻는다. 두 경우 모두 새로운 마운트 포인트가 기존 마운트 포인트와 동일한 peer 그룹의 멤버로 지정된다. - 반대로, 마지막 구성원(멤버) 프로세스가 종료되거나 다른 네임 스페이스로 이동하여 마운트 네임 스페이스가 종료될 때 peer 그룹이 unmount 하면, 마운트 포인트가 peer 그룹의 멤버를 그만둔다.
- 예제
- 초기 마운트 네임스페이스에서 실행되는 shell에서 루트 마운트 포인트를
private
으로 설정하고 두개의shared
마운트 포인트를 만든다고 가정하자.sh1# mount --make-private / sh1# mount --make-shared /dev/sda3 /X sh1# mount --make-shared /dev/sda5 /Y
- 두번째 터미널에서 shell을 실행하는 새로운 마운트 네임스페이스를 생성하기 위해
unshare
명령을 사용한다.sh2# unshare -m --propagation unchanged sh
-m
옵션: 새로운 마운트 네임스페이스를 만든다.
- 첫번째 터미널로 돌아와서, /X 마운트 포인트에서 bind 마운트를 만든다.
sh1# mkdir /Z sh1# mount --bind /X /Z
-
- 이 시나리오에선 2가지 peer 그룹이 있다.
- 첫번째 peer 그룹은
X
,X'
마운트 포인트와Z
를 포함한다(X'
- 두번째 네임스페이스 생성 시 생성된 마운트 포인트 X의 복제 /Z
- 초기 네임스페이스에서 X 마운트 포인트에서 생성된 bind 마운트). - 두번째 peer 그룹은
Y
,Y'
마운트 포인트를 포함한다.
- 첫번째 peer 그룹은
- 두번째 네임스페이스가 생성된 후 초기 네임스페이스에서 생성된 bind 마운트
Z
는 상위(parent) 마운트(/
)가private
으로 표시되었기 때문에 두번째 네임스페이스에는 복제되지 않았다.
- 이 시나리오에선 2가지 peer 그룹이 있다.
- 초기 마운트 네임스페이스에서 실행되는 shell에서 루트 마운트 포인트를
/proc/PID/mountinfo
Examining propagation types and peer groups via /proc/PID/mountinfo
파일에는 프로세스 PID가 있는 마운트 네임스페이스의 마운트 포인트에 대한 다양한 정보가 표시된다. 동일한 마운트 네임스페이스에 있란는 모든 프로세스들은 이 파일에서 동일한 뷰를 볼 것이다. 이 파일은 이전의 확장 불가능/proc/PID/mounts
파일에서 가능한 것보다 더 많은 마운트 포인트에 대한 정보를 제공하도록 설계되었다. 이 파일의 각 기록에는 각 마운트의propagation type
및peer 그룹
에 대한 정보를 표시하는 소위optional fields
가 있다.shared
마운트의 경우,/proc/PID/mountinfo
의 해당 레코드안 optional fields에는shared:N
형태의 태그를 포함된다.shared
태그는 마운트가 peer 그룹과 전파 이벤트를 공유하고 있음을 나타낸다. peer 그룹은 peer 그룹을 유일하게 구분하는 정수 값인 N으로 식별된다. 이러한 ID들은 1부터 번호가 매겨지며, 모든 구성원이 그룹을 떠났기 때문에 peer 그룹이 더 이상 존재하지 않을 때 재활용 될 수 있다. 동일한 peer 그룹의 멤버인 모든 마운트 포인트들은/proc/PID/mountinfo
파일 안에 'N'과 동일한shared:N
태그를 보여줄 것이다.- 예를 들어, 위의 예제에서 언급한 shell의 첫번째
/proc/self/mountinfo
의 내용을 나열하면, 다음과 같다.sh1# cat /proc/self/mountinfo | sed 's/ - .*//' 61 0 8:2 / / rw,relatime 81 61 8:3 / /X rw,relatime shared:1 124 61 8:5 / /Y rw,relatime shared:2 228 61 8:3 / /Z rw,relatime shared:1
- 이 출력에서, 우리는 root 마운트 포인트가
private
이라는 것을 알 수 있다. optional fields에 아무 태그도 없기 때문이다. 우리는 또한 마운트 포인트/X
,/Y
가 동일 peer 그룹(with ID 1)의shared
마운트 포인트라는 것을 알 수 있다. 이는 두 마운트 중 하나에 따른 mount, unmount 이벤트가 다른 peer 그룹으로 전파된다는 것을 의미한다. 마운트/Y
는 다른 peer 그룹(ID 2)의shared
마운트로서, peer 그룹 1에 이벤트를 전파하거나 전파받지 않는다.
- 이 출력에서, 우리는 root 마운트 포인트가
/proc/PID/mountinfo
는 우리로 하여금 마운트 포인트 간 부모 관계를 볼 수 있게 해준다. 각 레코드의 첫번째 필드는 각 마운트 포인트에 대한 고유한 ID이다. 두번째 필드는 부모 마운트의 ID이다. 위의 출력에서, 우리는 마운트 포인트/X
,/Y
,/Z
는 모두 부모가 61이므로 루트 마운트의 하위 항목임을 알 수 있다.- 두번째 shell에서 같은 명령을 내려보자.
sh2# cat /proc/self/mountinfo | sed 's/ - .*//' 147 146 8:2 / / rw,relatime 221 147 8:3 / /X rw,relatime shared:1 224 147 8:5 / /Y rw,relatime shared:2
X
는 peer 그룹 1의shared
마운트이고 초기 마운트 네임스페이스의 마운트/X
,/Z
와 동일한 peer 그룹이다.Y
는 peer 그룹 2의shared
마운트이고 초기 마운트 네임스페이스의 마운트/Y
와 동일한 peer 그룹이다.- 마지막으로, 두번째 네임스페이스에서 복사된 마운트 포인트에는 초기 네임스페이스에서 해당 마운트의 ID와 다른 고유한 ID가 있다는 것에 주의하자.
Debating defaults
- 커널 관점에서, 새로운 장치 마운트가 생성될 때의 기본 값은 다음과 같다.
- 만일 마운트 포인트가 부모를(non-root mount point) 가지고 있고 부모의
propagation type
이MS_SHARED
인 경우, 새로운 마운트의propagation type
역시MS_SHARED
이다. - 그렇지 않으면, 새로운 마운트의
propagation type
은MS_PRIVATE
이다.
- 만일 마운트 포인트가 부모를(non-root mount point) 가지고 있고 부모의
- 위의 규칙에 따르면, 루트 마운트는
MS_PRIVATE
이 되며, 모든 하위 마운트도 기본적으로MS_PRIVATE
이 된다. 그러나MS_SHARED
는 더 일반적으로 사용되는propagation type
이기 때문에 더 나은 기본 값이다. 이러한 이유로systemd
는 모든 마운트 포인트의propagation type
을MS_SHARED
로 설정한다. 따라서 대부분의 현대 리눅스 배포에서 기본propagation type
은MS_SHARED
이다. - 그러나 이것은 이 주제에 대한 최종적인 결론은 아니다. 왜냐하면 util-linux의
unshare
기능 또한 할 말이 있기 때문이다. 새로운 마운트 네임스페이스를 만들 때,unshare
은 유저가 완전히 분리된 네임스페이스를 원한다고 가정하고, 다음과 같은 명령을 수행하여 모든 마운트 포인트를private
으로 만든다.mount --make-rprivate /
- 이것을 막기 위해 새로운 네임스페이스를 생성할 때 추가 옵션을 사용할 수 있다.
unshare -m --propagation unchanged <cmd>