OS/Linux

[Linux] UTS namespace 맛보기

UTS namespace 맛보기

컨테이너 공부를 하다가 네임스페이스라는 부분이 재밌어서 다양한 네임스페이스에 대해서 공부중입니다.

그 중 UTS 네임스페이스는 컨테이너마다 호스트네임을 부여할 수 있는 특징을 가집니다. 또한 네트워크 네임스페이스를 통해 네트워크 인터페이스 격리도 할 수 있습니다.

테스트 환경은,



컨테이너가 호스트네임을? IP를?


실제로 가상 머신이 아니라 프로세스로 다루는 컨테이너가 고유한 호스트네임을 가지면서, 가상 네트워크 인터페이스와 컨테이너만을 위한 내부 IP를 가지는게 아주 신기했습니다.

간단하게 nginx 컨테이너를 띄우고

$ docker run --name nginx01 -d nginx:latest
$ docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED         STATUS         PORTS     NAMES
9c25d3c0477d   nginx:latest   "/docker-entrypoint.…"   5 seconds ago   Up 4 seconds   80/tcp    nginx01

다음 명령어로 방금 실행한 컨테이너의 Hostname과 IP를 확인가능합니다.

$ docker inspect -f='Hostname:{{.Config.Hostname}}, IP: {{.NetworkSettings.IPAddress}}' nginx01
Hostname:9c25d3c0477d, IP: 172.17.0.2

호스트에서 ping을 보내면 정상적으로 접근이 가능합니다.

$ ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.117 ms

이렇게 컨테이너가 호스트네임을 가질 수 있게해주는 기능을 UTS 네임스페이스로 구현가능합니다.


호스트네임을 분리해주는 UTS 네임스페이스

  • unshare 명령어를 사용하면 간단하게 네임스페이스를 격리 하는 기능을 사용할 수 있습니다.

호스트네임은 현재 네트워크 상에서 기기에 부여된 고유한 이름입니다.

$ hostname
ubuntu-bionic

먼저 네임스페이스 테스트를 위해서 빈 파일을 만듭니다.

$ touch /tmp/utsns1

조금 이상할 수 있지만 unshare를 사용하면서 이 빈 파일을 통해 네임스페이스의 영속화(namespace persistent)를 가능하게 해준다. 네임스페이스가 영속화되면, 이후에 해당 네임스페이스를 다시 재사용하는 것이 가능해집니다.

unshare 를 사용해 UTS 네임스페이스를 생성하고 utsns1이라는 호스트네임을 부여합니다.

$ unshare --uts=/tmp/utsns1 hostname utsns1

unshare의 사용법은 chrootdocker 등과 같은 일반 명령어와 유사합니다. unshare 뒤에 옵션이 따라오고 마지막으로 실행하고자하는 명령어를 지정합니다. 여기서는 hostname utsns1을 실행하여 /tmp/utsns1에 영속화된 네임스페이스에서 hostname을 utsns1으로 변경하는 명령을 실행하라는 의미입니다.

다시 한번 호스트의 hostname을 확인합니다.

root@ubuntu-bionic64:~# hostname
ubuntu-bionic64

--uts=/tmp/utsns1에 영속화된 네임스페이스를 기반으로 호스트 이름을 확인합니다. (네임스페이스를 만들때는 unshare 를 사용하지만, 분리한 이후 nsenter 를 사용하여 네임스페이스에 들어갑니다.)

root@ubuntu-bionic64:~# nsenter --uts=/tmp/utsns1 hostname
utsns1

UTS 네임스페이스에 Bash 셸을 바로 띄울 수도 있습니다.

root@ubuntu-bionic64:~# nsenter --uts=/tmp/utsns1 bash
root@utsns1:~# hostname
utsns1
root@utsns1:~# exit
root@ubuntu-bionic64:~#



정말 네임스페이스가 분리되었나?

호스트와 분리된 네임스페이스(utsns1)에서 Shell 프롬프트를 확인합니다.

# 호스트
root@ubuntu-bionic64:~# echo $$
18594
root@ubuntu-bionic64:~# nsenter --uts=/tmp/utsns1 bash
# 분리된 네임스페이스(utsns1)
root@utsns1:~# echo $$
18620
  • $$는 현재 bash 셸의 PID를 의미

리눅스에서는 /proc/<PID> 디렉터리에서 프로세스와 관련된 정보를 확인할 수 있습니다.

먼저 18594(호스트 bash)의 uts 파일을 살펴봅니다.

root@utsns1:/proc/18594/ns# ls -la uts
lrwxrwxrwx 1 root root 0 Apr  1 12:49 uts -> 'uts:[4026531838]'

기본적으로 모든 프로세스는 init 프로세스를 공유합니다.
따라서, 1번 프로세스의 UTS 네임스페이스 고유값도 확인합니다.

root@utsns1:/proc/18594/ns# cd /proc/1/ns/
root@utsns1:/proc/1/ns# ls -la uts
lrwxrwxrwx 1 root root 0 Apr  1 12:50 uts -> 'uts:[4026531838]'

=> 18594(호스트 bash)와 1(init)프로세스의 UTS 네임스페이스 고유값이 동일합니다.

이번에는 18620(분리된 네임스페이스 utsns1)의 UTS 네임스페이스 고유값을 확인합니다.

root@utsns1:/proc/1/ns# cd /proc/18684/ns/
root@utsns1:/proc/18684/ns# ls -al uts
lrwxrwxrwx 1 root root 0 Apr  1 12:56 /proc/18684/ns/uts -> 'uts:[4026532186]'

=> 분리된 18620(utsns1) 프로세스는 1번(init) 프로세스와 18594번(호스트) 프로세스와 네임스페이스의 고유값이 다릅니다. = 즉, 분리된 네임스페이스를 가집니다.

마지막으로 글쓴이가 UTS 네임스페이스가 분리되었음을 이해한 것을 그림을 그려 이해를 더 도울 수 있을꺼 같아서 첨부합니다.




Ref

즐겨보는 44bits의 글의 래퍼런스를 테스트하고 이해하고 포스팅합니다.
문제가 생긴다면 글을 삭제하도록하겠습니다.
44bits.io - UTS 네임스페이스를 사용한 호스트네임 격리