ㅍㅍㅋㄷ

Linux namespace - NET 본문

IT/Linux

Linux namespace - NET

클쏭 2016. 5. 10. 14:43

NET namespace







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


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



 NET namespace 는 격리화된 network interface를 제공하는 기술이다. 이것 또한 기존 namespace 와 같은 방식으로 clone system call 에서 CLONE_NEWNET flag를 추가해서 구현이 가능하다. 


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


 한가지 반가운 점은, NET namespace의 경우 iproute2 의 ip netns 라는 명령어를 이용하여 손쉽게 구현할 수 있도록 제공하고 있다.  

 먼저 ip 명령어를 통해 현재 서버의 interface 정보를 확인해 보자.


root@~~# ip link list

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default 

    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000

    link/ether fa:16:3e:8e:40:2d brd ff:ff:ff:ff:ff:ff


 현재 interface는 loopback 과 eth0 두개가 있는것을 볼 수 있다. 






iproute2 를 이용한 network namespace  생성


 이제 ip netns로 새로운 namespace를 생성해 보자. song_ns 라는 이름으로 만들어 보자.  


root@~~# ip netns add song_ns


  생성된 namespace는 아래와 같이 확인이 가능하다. 

root@~~# ip netns

song_ns



 이제 방금 생성한 namespace인 song_ns 내부에 interface 정보를 보자. 

 ip netns exec 라는 명령어를 이용하면 지정한 namespace 내부에 명령어를 입력할 수 있다. 

 

root@~~# ip netns exec song_ns ip link list

1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default 

    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00


 위 결과는  song_ns namespace 내부에서 ip link list 라는 명령어를 출력한 것이다. 

 song_ns 내부에는 위와 같이 loopback interface 하나만 있는걸 확인할 수 있다. state 또한 DOWN 상태이다. 

 

 loopback interface를 up 해보자.


root@~~# ip netns exec song_ns ip link set lo up


interface를 다시 확인해 보면 아래와같이 DOWN 상태에서 UNKNOWN 상태로 변경된걸 볼 수 있다. 


root@~~# ip netns exec song_ns ip link list

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default 

    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00



 그렇다면, 이렇게 생성한 network namespace 는 어떻게 외부와 통신할 수 있을까?


 가장 간단한 방법은 veth interface를 이용하는 방법이다. veth interface의 가장 큰 특징은 두개의 interface가 pair로 동작한다는 점이다. 

 한쪽 interface 에 packet이 들어오면 pair로 맺어진 다른쪽 interface로 나가도록 동작한다. 

 

 이것을 이용하여 veth pair 의 한쪽 interface는 namespace 내부에, 한쪽은 외부에 생성하게 되면 namespace 내/외부로 통신이 가능하다. 

 아래와 같이 veth0 와 veth1 interface를 생성하고 두 interface를 pair로 설정하자.

 

 root@~~# ip link add veth0 type veth peer name veth1

 


 ip link list 로 살펴보면 아래와 같이 veth0과 veth1 interface 가 생성된 것을 볼 수 있다. 


root@~~# ip link list

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default 

    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000

    link/ether fa:16:3e:8e:40:2d brd ff:ff:ff:ff:ff:ff

3: veth1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000

    link/ether 02:86:c2:3c:82:0c brd ff:ff:ff:ff:ff:ff

4: veth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000

    link/ether 6e:a4:7a:5b:25:d4 brd ff:ff:ff:ff:ff:ff



 두 interface가 pair로 맺어져 있다는 것은 ethtool을 이용하여 확인할 수 있다.


root@~~# ethtool -S veth0

NIC statistics:

     peer_ifindex: 3



 veth0 interface가 peer_ifindex 가 3으로 설정되어 있다. 이는 ip link list 로 확인했을때 veth1의 index임을 알 수 있다. 

 즉, 두 interface가 pair로 설정되어 있다는 의미이다.


3: veth1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000

    link/ether 02:86:c2:3c:82:0c brd ff:ff:ff:ff:ff:ff



이제 veth1 interface를 아까 생성한 song_ns namespace에 할당해 보자. 


root@~~# ip link set veth1 netns song_ns 



이제 ip link list를 확인해 보면?

 

root@~~# ip link list

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default 

    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT group default qlen 1000

    link/ether fa:16:3e:8e:40:2d brd ff:ff:ff:ff:ff:ff

4: veth0: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000

    link/ether 6e:a4:7a:5b:25:d4 brd ff:ff:ff:ff:ff:ff



veth1이 보이지 않을 것이다. song_ns 내부에 할당되어 격리되었기 때문이다. 

ip netns exec 를 이용하여 song_ns 내부의 interface 정보를 보자. 


root@~~# ip netns exec song_ns ip link list

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default 

    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

3: veth1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000

    link/ether 02:86:c2:3c:82:0c brd ff:ff:ff:ff:ff:ff


veth1이 song_ns 내부에 할당된 것을 확인할 수 있다. 


이제 실제 통신 되는것을 확인해 보기 위해 veth0과 veth1 모두 interface 를 up 하고, IP도 할당해 보자. 

IP는 veth0은 172.21.0.1/24 veth1은 172.21.0.2/24 로 설정하였다. 


root@~~# ip link set veth0 up

root@~~# ip link add 172.21.0.1/24 dev veth0

root@~~# 

root@~~# ip netns exec song_ns ip link set veth1 up

root@~~# ip netns exec song_ns ip link add 172.21.0.1/24 dev veth1



두 interface모두 ip가 잘 설정되었는지 확인해 보자.

확인은 ip address show 로 해보자. 물론 ifconfig로 해도 된다.


root@~~# ip address show veth0

4: veth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000

    link/ether 6e:a4:7a:5b:25:d4 brd ff:ff:ff:ff:ff:ff

    inet 172.21.0.1/24 scope global veth0

       valid_lft forever preferred_lft forever



root@~~# ip netns exec song_ns ip address show veth1

3: veth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000

    link/ether 02:86:c2:3c:82:0c brd ff:ff:ff:ff:ff:ff

    inet 172.21.0.2/24 scope global veth1

       valid_lft forever preferred_lft forever

    inet6 fe80::86:c2ff:fe3c:820c/64 scope link 

       valid_lft forever preferred_lft forever


위와같이 잘 설정되어 있는것을 볼 수 있다. 

ping 명령어를 이용하여 namespace 내부로 통신이 되는지 확인해 보자. 


song_ns에 할당한 veth1의 IP가 172.21.0.2 이므로 여기로 ping을 쏴보자. 


root@~~# ping 172.21.0.2

PING 172.21.0.2 (172.21.0.2) 56(84) bytes of data.

64 bytes from 172.21.0.2: icmp_seq=1 ttl=64 time=0.025 ms

64 bytes from 172.21.0.2: icmp_seq=2 ttl=64 time=0.025 ms

64 bytes from 172.21.0.2: icmp_seq=3 ttl=64 time=0.021 ms 


반대로 namespace 내부에서 외부 host로 ping 을 확인해 봐도 결과는 동일하다. 


root@~~# ip netns exec song_ns ping 172.21.0.1

PING 172.21.0.1 (172.21.0.1) 56(84) bytes of data.

64 bytes from 172.21.0.1: icmp_seq=1 ttl=64 time=0.027 ms

64 bytes from 172.21.0.1: icmp_seq=2 ttl=64 time=0.021 ms

64 bytes from 172.21.0.1: icmp_seq=3 ttl=64 time=0.020 ms

64 bytes from 172.21.0.1: icmp_seq=4 ttl=64 time=0.021 ms

64 bytes from 172.21.0.1: icmp_seq=5 ttl=64 time=0.024 ms 




위에서 확인한 namespace 와 veth pair 방식은 docker container에서 사용하는 방식과 동일하다. 

아래는 docker container의 network 구조에 대한 내용이니 참고 

Docker Network 구조(1) - docker0와 container network 구조


  • 참고 : https://blog.yadutaf.fr/2014/01/19/introduction-to-linux-namespaces-part-5-net/


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

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 - UTS  (2) 2015.07.03
Linux namespace  (0) 2015.07.02
Comments