내용이 하나의 글로 하기엔 너무 길어기 때문에, "Concept", "Implementation" 등으로 구분하여 쓰고, 관련 실습을 추가할 예정이다. 

2.3.2 Namespaces
 Namespace는 하나의 수행되는 시스템에 서로 다른 관점을 제공하는 것처럼 하는 lightweight 한 가상화의 형태를 제공하는 것이다. 이 매커니즘은 FreeBSD 의 jail 이나 Solaris의 zone과 비슷한 것이다. 

Concept
 전통적으로, Unix 계열의 시스템 뿐만아니라 Linux에서는 시스템이 가지고 있는 많은 자원을 전체적으로 관리한다. 예를 들어, 시스템에 있는 모든 process들은 그것들이 가지고 있는 PID 숫자로 확인되며, 이 PID 리스트는 커널에서 관리되어야 한다. 마찬가지로, uname system call로 반환된 시스템에 관한 정보는(kernel에 관한 약간의 정보와 system의 이름을 반환) 호출한 모든 사용자가 같은 값을 볼 수 있을 것이다. User ID 또한 이와 비슷한 방법으로 관리된다 : 각 user는 시스템에 유일한 UID 값을 가진다. 

uname -r : kernel version 확인
uname -a : system 정보 및 kernel 정보

User 의 ID는 kernel이 선택적으로 특정 권한에 대한 행동을 승인 혹은 거부를 한다. UID 0을 가진 root user는 기본적으로 모든 명령 및 행동이 가능하지만 0 이상의 값을 가진 UID는 제한적 기능만을 제공한다. PID n 의 값을 가진 user가 있다면, 자신의 pid n과 다른 m의 user가 실행 시킨 process는 시스템에서 제거할 수 없다. (ps -ef 명령으로 각 process의 pid와 uid를 확인할 수 있다). 물론 ps 명령어로 다른 사용자가 실행한 process는 확인 가능하다. User N은 다른 User M이 이 시스템에 활성화(사용하고 있는지)가 되어 있는지 볼 수 있다. 이것은 사용자가 자신이 가지고 있는 process들만 가지고 놀 수(?) 있는 한 다른 사용자가 가지고 있는 process를 관찰하는 것까지 막을 필요가 없기 때문에 아무 문제가 되지 않는다. 

 그러나 위의 경우를 원치 않은 경우가 있다. web 공급자가 고객들에게 Linux 시스템에 root 권한을 비롯한 모든 접근 권한을 주는 경우를 생각해 보자. 그렇다면 web service를 제공하는 고객들 한명당 하나의 linux 머신을 제공해야 하기 때문에 엄청난 비용이 든다. 그래서 KVM이나 VMware같은 가상화 환경으로 제공하면 이같은 문제를 해결 할 수 있지만, 이 가상화 방법은 시스템의 자원을 원할하게 분배하지 못하는 단점이 있다. 가상화 시스템은 각 고객들에게 분리된 kernel을 제공해야하는 것이 요구되며, 각 가상화 머신에 리눅스를 각각 설치를 해주고 설정을 완료해 줘야 한다. 

 다른 해결책으로는 namespace를 통해 가상화보다 적은 자원을 들여 같은 서비스를 제공할 수 있다. 하나의 물리적인 머신에 여러 커널을 수행하는 가상화 시스템(물론 서로 다른 운영체제를 수행하는데는 이 방법이 더 좋다)을 제공하는 대신에 하나의 물리적인 머신에 하나의 커널이 수행되고 namespace내부에 미리 모든 시스템의 자원을 추상화 해놓는 것이다. 이것은 하나의 container 에 process 그룹을 넣어두고 다른 container(물론 여기도 process 그룹이..)와는 완벽히 분리 해놓은 것이다. 이러한 분리는 하나의 container에 묶인 사용자들이 다른 container로의 연결을 할 수 없다. 그렇지만 container가 유지되는 동안 특정 경우에 다른 container와 공유하기 위해 그 container의 분리를 느슨하게(?) 할 수 있다. 예를 들어 container안의 PID 의 셋을 가지고 운영되지만, 서로 다른 container와 filesystem의 부분은 여전히 공유 될 수 있다. 

Namespace는 기본적으로 시스템의 다른 view를 생성한다. 모든 이전에 생성된 자원은 container data 구조체로 싸여져 있어야 하고 자원의 리스트 셋과 namespace에 포함하는 내용은 시스템 내부에서 유일해야 한다. 주어진 container 안에서 그 자원이 충분히 활용하고 있지만 외부에 그 자원의  고유 identity(예를 들어 PID, 아래의 예제확인)를 제공하지 않는다. (내부에서만 사용하고 운영한다는 얘기인듯.) 그림 2-3이 상황을 개략적으로 볼 수 있다. 

//그림 2-3  --> 나중에...

세 개의 서로 다른 namespace가 시스템이 있다고 생각해 보자. namespace는 계층적으로 연결될 수 있다고 고려되었다. 하나는 parent namespace이고 이는 두개의 child namespace를 생성했다. 이 container들은 각각 하나의 linux 머신에서 제공되는 것처럼 보이도록 하여 web 호스팅 설정을 할 수 있게 제공한다고 가정하자. 각 container에서는 각각 pid 가 0 인 init task를 가지고 있어야 하며 오름차순으로 생성된 다른 task들을 가지고 있어야 한다. 두 child namespace 내부에는 init task(PID == 0)인 것과 2, 3의 pid를 가지는 task가 있다.(그림 2-3) PID 값은 하나의 시스템에서 고유의 값을 가지므로 이런 식으로 container 내부에서 가지는 pid의 값은 시스템 전체에서 고유의 값이 될 수 없다. 

child container는 시스템의 다른 container에게 자신의 상태를 알려주거나 연결이 되지 않기 때문에 parent container에서 child 관련 정보를 취급해서 child 내부에서 실행되는 모든 process를 볼 수 있어야 한다. 그림 2-3 에서 parent 4~9번 process는 child의 process와 대응되어 있다. 비록 시스템에는 9개의 process들이 있는 것이지만 4~9번의 PID를 가진 process는 하나 이상의 PID를 가지기 때문에 실제적으로 15 개의 PID가 요구된다. 

Namespace는 만약 간결한 분량의 container를 포함하는 경우 비계층적 구조(위의 계층적 구조와는 다른)를 가질 수 있다.(UTS Namespace의 예제를 보면서 확인하자)

꽤나 오래전에 linux는 chroot 시스템 콜을 이용한 간단한 형태의 namespace를 지원하고 있었다.  이 방법은 filesystem의 특정 부분을 동작중인 process들이 root 디렉토리로 인식함으로써 설정된 디렉토리 밖에서 접근 하지 못하도록 진행하는 것이어서 이것 또한 namespace의 한 형태라고 볼 수 있다. 하지만 진정한 namespace는 단지 filesystem을 제어하는 것 이외에도 많은 것을 컨트롤 할 수 있도록 만들어 주는 것이다. 

namespace를 만드는 방법은 두 가지가 있다. 
1. 새로운 process가 fork나 clone 시스템 콜로 생성될 때, 특정 option으로 parent process와 namespace가 공유될 수 있도록 만들어 질 수 있다. 또는 새로운 namespace 가 생성될 수 있다. 

2. unshare 시스템 콜로 parent 로 부터 생성된 process를 분리하고 새로운 namespace를 할당 할수 있다. manual page 를 확인 하자(unshare(2))

관련 자료를 검색 중 찾은 간단한 예제로 확인해 보자

http://woodz.tistory.com/23 <-- namespace 의 간단한 실습 내용.

+ Recent posts