ㅍㅍㅋㄷ

Linux namespace - NS (File System) 본문

IT/Linux

Linux namespace - NS (File System)

클쏭 2016. 5. 4. 18:59

NS (File system) namespace




[Contents]


  1. Linux namespace

  2. Linux namespace - UTS

  3. Linux namespace - IPC

  4. Linux namespace - PID

  5. Linux namespace - NS(File System)

  6. Linux namespace - NET




 최근 lightweight 한 가상화 플랫폼인 Docker나 Linux container LXC 가 주목을 받고 있는데, 여기에 사용된 기반 기술 중 하나로 namespace 라는 것이 있다. namespace 에 대한 설명은 이전 포스팅 참고 ( Linux namespace ) 


 namespace 는 크게 6가지로 분류되는데, 이번 포스팅에는 NS namespace에 대해 알아볼 예정이다. 


1. UTS namespace : hostname 을 변경하고 분할

2. IPC namespace : Inter-process communication. 프로세스간 통신 격리

3. PID namespace : PID (Process ID)를 분할 관리

4. NS namepsace : file system 의 mount 지점을 분할하여 격리

5. NET namespace : Network interface, iptables 등 network 리소스와 관련된 정보를 분할

6. USER namespace : user와 group ID를 분할 격리



 지난 포스팅에서 PID namespace를 이용하여 Process Tree의 최상단인 PID 1을 새롭게 생성하여 분기 시켜보았다. ( 지난 포스팅 참고 : Linux namespace - PID )


 하지만, ps 명령어로 프로세스를 확인해 보면, 자신의 관리 영역 외에도 존재하는 모든 process 리스트가 보였다. 이것은 Process를 기록하고 관리하는 filesystem 영역인 /proc 은 아직 공유하고 있었기 때문이다. filesystem 격리는 NS namespace 를 통해 구현해 보자



Clone을 이용한 NS namespace 구성 방법 


 NS namespace를 생성하는 방법도 지금까지 했던 방식과 동일하다. clone() 생성시 flag로 CLONE_NEWNS 만 추가해 주면 된다. 


int child_pid = clone(child_main, child_stack+STACK_SIZE, CLONE_NEWNS | SIGCHLDNULL);



지난 포스팅에서 했던 소스 코드에서 CLONE_NEWNS flag만 추가해 보자. 


#define _GNU_SOURCE

#include <sys/types.h>

#include <sys/wait.h>

#include <stdio.h>

#include <sched.h>

#include <signal.h>

#include <unistd.h>


#define STACK_SIZE (1024 * 1024)


static char child_stack[STACK_SIZE];

charconst child_args[] = {

  "/bin/bash",

  NULL

};


int child_main(void* arg)

{

  printf(" - [%4d] Current namspace, Parent PID : %d\n", getpid(), getppid() );

  sethostname("namespace"12);

  execv(child_args[0], child_args);

  return 1;

}


int main()

{

  printf(" - [%4d] New namespace, Parent PID : %d\n", getpid(), getppid() );

  int child_pid = clone(child_main, child_stack+STACK_SIZE, CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWPID | CLONE_NEWNS | SIGCHLDNULL);

  waitpid(child_pid, NULL0);

  return 0;

}



실행해 보면 결과는 이전과 다르지 않다. 


root@~~# ./newns

 - [1225] Current namespace, Parent PID : 1228

 - [      1] New namespace, Parent PID : 0

root@namespace:~# 


 눈에 보이진 않지만, 현재 새롭게 생성된 namespace는 file system 또한 격리화 되어 관리되고 있는 상태이다. 

 이제 process 리스트가 관리 되는 proc file system 을 새롭게 mount 해보자.

 

일단, proc file system을 새롭게 mount 할 디렉토리를 생성한다. 


root@namespace:~# mkdir -p /tmp/proc


proc file system을 새롭게 mount 한다. 


root@namespace:~# mount -t proc /tmp/proc /proc



mount 명령어로 확인해 보면, 아래와 같이 proc type의 file system이 새롭게 mount 되어 있는것을 볼 수 있다.


root@namespace:~# mount

/dev/vda2 on / type ext4 (rw,nodev,noatime)

... (중략)

/root/proc on /proc type proc (rw)


이제 ps 명령어로 process 리스트를 확인해 보자. 


root@namespace:~# ps -aef

UID        PID  PPID  C STIME TTY          TIME CMD

root         1     0  0 18:34 pts/0    00:00:00 /bin/bash

root        16     1  0 18:41 pts/0    00:00:00 ps -aef

root@namespace:~# pstree -p

bash(1)───pstree(17)


위와 같이 현재 자신이 속한 namespace의 process 만 확인이 가능하다. 마치 docker를 사용할때와 같은 느낌적인 느낌. 

새롭게 터미널을 열어 namespace 가 아닌 기존 환경으로 접속하여 ps 명령어를 치면, 기존 process 리스트를 확인할 수 있다. 


만약, 예제를 실행시키자 마자 바로 proc 을 mount 하려면 아래와 같이 추가하면 된다. 


 #define _GNU_SOURCE

#include <sys/types.h>

#include <sys/wait.h>

#include <stdio.h>

#include <sched.h>

#include <signal.h>

#include <unistd.h>

#include <sys/mount.h>


#define STACK_SIZE (1024 * 1024)


static char child_stack[STACK_SIZE];

charconst child_args[] = {

  "/bin/bash",

  NULL

};


int child_main(void* arg)

{

  printf(" - [%4d] Current namspace, Parent PID : %d\n", getpid(), getppid() );

  sethostname("namespace"12);

  mount("/root/proc", "/proc", "proc", 0, NULL);

  execv(child_args[0], child_args);

  return 1;

}


int main()

{

  printf(" - [%4d] New namespace, Parent PID : %d\n", getpid(), getppid() );

  int child_pid = clone(child_main, child_stack+STACK_SIZE, CLONE_NEWUTS | CLONE_NEWIPC | CLONE_NEWPID | CLONE_NEWNS | SIGCHLDNULL);

  waitpid(child_pid, NULL0);

  return 0;

}


mount 함수에 대한 설명은 여길 참고 : http://man7.org/linux/man-pages/man2/mount.2.html



[참고]

    • https://blog.yadutaf.fr/2014/01/12/introduction-to-linux-namespaces-part-4-ns-fs/


'IT > Linux' 카테고리의 다른 글

Linux namespace - NET  (4) 2016.05.10
Linux namespace - PID  (1) 2015.07.14
Linux namespace - IPC  (0) 2015.07.13
Linux namespace - UTS  (2) 2015.07.03
Linux namespace  (0) 2015.07.02
Comments