ㅍㅍㅋㄷ

Linux namespace - UTS 본문

IT/Linux

Linux namespace - UTS

클쏭 2015. 7. 3. 16:46

UTS namespace






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


 namespace 는 크게 6가지로 분류되는데 이번 포스팅에는 UTS 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를 분할 격리



UTS namespace는 system의 hostname을 namespace 별로 격리 시켜 준다.

자세히 말하자면, Linux system call 중 하나인 uname에서 utsname 라는 struct 에 정의된 식별자 중 nodename 를 isolate 하는 것이다.


아래는 /usr/include/linux/utsname.h 에 선언된 new_utsname struct의 내용이다.


#define __NEW_UTS_LEN 64


struct new_utsname {

char sysname[__NEW_UTS_LEN + 1];

char nodename[__NEW_UTS_LEN + 1];

char release[__NEW_UTS_LEN + 1];

char version[__NEW_UTS_LEN + 1];

char machine[__NEW_UTS_LEN + 1];

char domainname[__NEW_UTS_LEN + 1];

};




Clone을 이용한 UTS namespace 테스트


UTS namespace 를 테스트 하는 방법은 간단하다.

아래 source를 보자.


#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];

char* const child_args[] = {

  "/bin/bash",

  NULL

};


int child_main(void* arg)

{

  sethostname("namespace", 12);

  execv(child_args[0], child_args);

  return 1;

}


int main()

{

  int child_pid = clone(child_main, child_stack+STACK_SIZE, CLONE_NEWUTS | SIGCHLD, NULL);

  waitpid(child_pid, NULL, 0);

  return 0;

}


먼저 main에서 clone()을 이용해, child process를 생성하는데, 

flag 로 CLONE_NEWUTS 를 넣어 실행한다. 이것은 namespace 중에서도 UTS 관련 namespace로 생성되도록 하는 것이다. 

( 참고 : http://linux.die.net/man/2/clone )


그리고 child process가 만들어질때, sethostname() 이라는 함수를 이용하여, hostname을 변경하도록 하여 기존과 다른 hostname을 가진 namespace를 만든다.


결과는 아래와 같다.

root@ip-song:~# ./newuts 

root@namespace:~#          <-- namespace 환경 

root@namespace:~#

root@namespace:~# hostname

namespace

root@namespace:~# exit  <-- namespace 종료

root@ip-song:~#                   





Unshare를 이용한 namespace 테스트


 위 clone 을 사용한 예제 보다 더 간단한 방법으로 UTS namespace를 확인하는 방법도 있다.

unshare 라는 command 를 이용하는 방법이다.


unshare 도 위 예제에서 사용한 clone 과 비슷하게 namespace 환경을 생성할수 있다.

먼저 namespace를 만들기 전에 현재 hostname을 살펴보자.

uname에 옵션으로 -n을 붙이면면 현재 hostname을 알 수 있다. 


root@ip-song:~# uname -n

ip-song



unshare로 namespace를 만드는데, 옵션으로 -u을 주면 UTS namespace가 부모 프로세스와 unshared 된 상태로 생성된다.


root@ip-song:~# 

root@ip-song:~# unshare -u /bin/bash

root@ip-song:~#            <-- namespace 환경 

root@ip-song:~

root@ip-song:~# hostname change-uts

root@ip-song:~#

root@ip-song:~# uname -n

change-uts    <-- uts namespace가 변경된 상황



이때, 다른 터미널로 접속하여, uname -n을 입력하면, uts namespace 를 바꾸기 전 hostname 으로 응답하는걸 볼 수 있다.




참고로, 아래는 uname 에 정의된 utsname 값을 확인 해 보는 간단한 예제이다.

#define _GNU_SOURCE

#include <sys/utsname.h>

#include <stdio.h>


int main()

{

    struct utsname my_uname;

    if(uname(&my_uname) == -1)

        printf("uname call failed!");

    else

        printf("System name: %s\nNodename:%s\nRelease:%s\nVersion:%s\nMachine:%s\n",

                my_uname.sysname, my_uname.nodename, my_uname.release,my_uname.version,my_uname.machine);

}



결과는 아래와 같다.

root@ip-song:~#  uname

System name: Linux

Nodename:ip-song

Release:3.13.0-48-generic

Version:#80-Ubuntu SMP Thu Mar 12 11:16:15 UTC 2015

Machine:x86_64

root@ip-song:~# 




참고

  • https://blog.jtlebi.fr/2013/12/22/introduction-to-linux-namespaces-part-1-uts/


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

Linux namespace - NET  (4) 2016.05.10
Linux namespace - NS (File System)  (0) 2016.05.04
Linux namespace - PID  (1) 2015.07.14
Linux namespace - IPC  (0) 2015.07.13
Linux namespace  (0) 2015.07.02
Comments