Stein 오픈스택 클라우드 분석(4) - 호스트 시스템에서의 가상 네트워크 구조 분석

blog post 

 

 

지난 포스팅에서 내외부 네트워크를 구축하고 라우터까지 배치해 보았습니다. 이번 포스팅에서는 실제로 호스트 시스템에서는 어떤식으로 네트워크 인터페이스가 구축되는지 살펴보도록 하겠습니다. 아직 가상 네트워크 구축 포스트를 보지 못하신 분들은 먼저 해당 글을 참고 하시길 바랍니다.

 

현재 컴퓨트 노드에서는 아직 별다른 인스턴스를 생성하지 않은 상태이므로 네트워크 노드를 위주로 살펴보도록 하겠습니다.

 

네트워크 노드에서 현재 오픈스택 네트워크 관련 인터페이스 구성 상태는 아래와 같습니다.

 

[root@Network ~]# ovs-vsctl show                                                                                                                               
25bab28b-f4e3-4cc1-8369-1267ca847c93
    Manager "ptcp:6640:127.0.0.1"
        is_connected: true
    Bridge br-int
        Controller "tcp:127.0.0.1:6633"
            is_connected: true
        fail_mode: secure
        Port "qr-bdc12328-5a"
            tag: 5
            Interface "qr-bdc12328-5a"
                type: internal
        Port "tapacc1dec2-5c"
            tag: 5
            Interface "tapacc1dec2-5c"
                type: internal
        Port "qg-df00644b-3f"
            tag: 4
            Interface "qg-df00644b-3f"
                type: internal
        Port "tap627aa34a-16"
            tag: 4
            Interface "tap627aa34a-16"
                type: internal
        Port "int-br-eth1"
            Interface "int-br-eth1"
                type: patch
                options: {peer="phy-br-eth1"}
        Port patch-tun
            Interface patch-tun
                type: patch
                options: {peer=patch-int}
        Port br-int
            Interface br-int
                type: internal
    Bridge br-tun
        Controller "tcp:127.0.0.1:6633"
            is_connected: true
        fail_mode: secure
        Port br-tun
            Interface br-tun
                type: internal
        Port "vxlan-0a000019"
            Interface "vxlan-0a000019"
                type: vxlan
                options: {df_default="true", egress_pkt_mark="0", in_key=flow, local_ip="10.0.0.27", out_key=flow, remote_ip="10.0.0.25"}
        Port patch-int
            Interface patch-int
                type: patch
                options: {peer=patch-tun}
    Bridge "br-eth1"
        Controller "tcp:127.0.0.1:6633"
            is_connected: true
        fail_mode: secure
        Port "phy-br-eth1"
            Interface "phy-br-eth1"
                type: patch
                options: {peer="int-br-eth1"}
        Port "br-eth1"
            Interface "br-eth1"
                type: internal
        Port "eno16777736"
            Interface "eno16777736"
    ovs_version: "2.11.0"

 

이전 호스트 네트워크 포스트에서 봤던 기본 인터페이스 구성에서 아래와 같은 인터페이스가 br-int 브릿지에 추가된 것을 확인할 수 있습니다.

 

        Port "qr-bdc12328-5a"
            tag: 5
            Interface "qr-bdc12328-5a"
                type: internal
        Port "tapacc1dec2-5c"
            tag: 5
            Interface "tapacc1dec2-5c"
                type: internal
        Port "qg-df00644b-3f"
            tag: 4
            Interface "qg-df00644b-3f"
                type: internal
        Port "tap627aa34a-16"
            tag: 4
            Interface "tap627aa34a-16"
                type: internal

 

ifconfig -a 명령으로 확인해보면 위의 인터페이스는 보이지 않습니다. 위의 인터페이스는 리눅스 시스템의 기본 네트워크 스택에서 분리된 별도의 네트워크 스택에 구성되어있기 때문입니다.

 

 



아시다시피 리눅스는 기본적인 네트워크 네임스페이스를 제공하고 있습니다. 기본 네트워크 네임스페이스에서 라우팅 룰을 통해 네트워킹을 수행하지만, 구성이 복잡해지면 룰 역시 복잡해질 수 밖에 없습니다. 따라서 네트워크 스택을 분리하여 또 다른 네임스페이스를 생성함으로써, 리눅스의 기본 네임스페이스와 격리된 라우팅 룰을 가지게 할 수 있습니다. 즉 쉽게 새로운 네트워크 구성이 가능하죠. (관련 내용은 좀 더 자세하게 별도의 포스팅에서 다루도록 하겠습니다)

 

오픈스택에서는 이러한 리눅스의 기능을 활용하여 br-int에 묶여있는 포트의 실제 인터페이스는 별도의 네트워크 네임스페이스에 생성하고 관리합니다.

 

우선 리눅스에서 네트워크 네임스페이스를 확인하는 대표적인 방법은 ip netns 명령을 활용하는 것입니다.

아래와 같이 네트워크 노드에서 ip netns 명령을 실행해보면 네트워크 네임 스페이스 리스트를 확인할 수 있습니다.

 

[root@Network ~]# ip netns
qdhcp-585040c0-8dea-43f0-ba73-001955f59ce1 (id: 2)
qrouter-700c5054-6612-477a-970c-f3f7eebbaea6 (id: 1)
qdhcp-b7fc4869-1e35-4d34-9f84-2a66b6d3c984 (id: 0)
ns1

 

 

각 라인이 기본 네트워크 스택에서 분리된 네임스페이스입니다. 각 네임스페이스의 명칭을 통해서 알 수 있듯이, dhcp와 라우터를 기반으로 네트워크 네임스페이스를 생성하는 것을 확인할 수 있습니다.

 

그 뒤에 붙는 번호는 dhcp의 경우 해당 dhcp 에이전트가 속한 네트워크의 id, 라우터는 라우터의 id를 가져다 붙입니다. 이 id는 오픈스택 대시보드나 커맨드를 활용하여 확인할 수 있습니다. 여기에서는 오픈스택 커맨드를 활용하여 해당 네임스페이스가 어떤 dhcp나 라우터의 네임스페이스인지 확인하는 방법에 관하여 알아보겠습니다.

 

우선 라우터 정보를 보겠습니다.

 

[root@Controller ~]# openstack router list -c ID -c Name
+--------------------------------------+---------+
| ID                                   | Name    |
+--------------------------------------+---------+
| 700c5054-6612-477a-970c-f3f7eebbaea6 | Router1 |
+--------------------------------------+---------+

 

한눈에 봐도 라우터의 네임스페이스는 라우터 id를 가져다 사용했음을 확인할 수 있습니다.

 

다음으로 dhcp 네임스페이스를 확인해 보겠습니다. dhcp는 현재 2개인데 어떤 포트가 internal agent이고 external agent인지 파악하기 어렵습니다. dhcp 정보는 다음과 같이 port 정보를 통해 확인할 수 있습니다.

 

[root@Controller ~]# openstack port list -c ID -c 'Fixed IP Addresses'
+--------------------------------------+------------------------------------------------------------------------------+
| ID                                   | Fixed IP Addresses                                                           |
+--------------------------------------+------------------------------------------------------------------------------+
| 627aa34a-16d5-4a2f-9fc9-a77ec18a4c23 | ip_address='192.168.0.129', subnet_id='a92c3382-9e0a-4d98-af4e-720a0fe66f56' |
| acc1dec2-5cd5-45b7-a1e0-d54d5da47612 | ip_address='10.10.0.2', subnet_id='f00e8075-5b9e-4430-93b6-788aac1e65eb'     |
| bdc12328-5af8-44fd-acd6-9722efee21e0 | ip_address='10.10.0.1', subnet_id='f00e8075-5b9e-4430-93b6-788aac1e65eb'     |
| df00644b-3f72-41b9-b710-22166d1624b6 | ip_address='192.168.0.159', subnet_id='a92c3382-9e0a-4d98-af4e-720a0fe66f56' |
+--------------------------------------+------------------------------------------------------------------------------+

 

 이전 포스트에서 우리가 생성한 라우터에 할당된 두 개의 포트의 ip는 현재 10.10.0.1과 192.168.0.159 입니다. 그러면 나머지 두개의 포트가 dhcp agent 포트(10.10.0.2, 192.168.0.129)임을 알 수 있습니다.

 

그러면 이제 dhcp agent가 사용하는 포트 정보는 알아냈으나, 네임스페이스의 id와 다르다는 것을 알 수 있습니다. 앞서 말씀드린 것과 같이 dhcp agent의 네임스페이스는 해당 dhcp agent가 속한 네트워크의 id와의 조합으로 생성됩니다. 따라서 다음과 같이 두 dhcp agent 포트의 상세 정보를 통해 네트워크 id를 확인할 수 있습니다.

 

[root@Controller ~]# openstack port show acc1dec2-5cd5-45b7-a1e0-d54d5da47612 | egrep "device_owner|network_id"
| device_owner            | network:dhcp                                                                                                                                                               
| network_id              | 585040c0-8dea-43f0-ba73-001955f59ce1                                                                                                                                       
[root@Controller ~]# openstack port show 627aa34a-16d5-4a2f-9fc9-a77ec18a4c23 | egrep "device_owner|network_id"                                                                   
| device_owner            | network:dhcp                                                                                                                                                                       
| network_id              | b7fc4869-1e35-4d34-9f84-2a66b6d3c984                                                                                                                                               

 

 

 

 

이런식으로 openstack 커맨드를 통해 네임스페이스의 용도를 확인할 수도 있지만, 직접 각 네임스페이스의 내부에서 인터페이스 정보를 통해 확인해 볼 수도 있습니다. 이 때에는 네트워크 노드에서 "ip netns exec <namespace id> ifconfig" 명령을 활용하면 됩니다.

 

[root@Network ~]# ip netns exec qdhcp-b7fc4869-1e35-4d34-9f84-2a66b6d3c984 ifconfig                                                                                               
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

tap627aa34a-16: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.129  netmask 255.255.255.192  broadcast 192.168.0.191
        inet6 xxxx::xxxx:xxxx:xxxx:xxxx  prefixlen 64  scopeid 0x20<link>
        ether xx:xx:xx:xx:xx:xx  txqueuelen 1000  (Ethernet)
        RX packets 42649  bytes 7794831 (7.4 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 5  bytes 446 (446.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

[root@Network ~]# ip netns exec qrouter-700c5054-6612-477a-970c-f3f7eebbaea6 ifconfig                                                                                             
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

qg-df00644b-3f: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.0.159  netmask 255.255.255.192  broadcast 192.168.0.191
        inet6 xxxx::xxxx:xxxx:xxxx:xxxx  prefixlen 64  scopeid 0x20<link>
        ether xx:xx:xx:xx:xx:xx  txqueuelen 1000  (Ethernet)
        RX packets 33943  bytes 6342610 (6.0 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 23  bytes 1530 (1.4 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

qr-bdc12328-5a: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 10.10.0.1  netmask 255.255.255.0  broadcast 10.10.0.255
        inet6 xxxx::xxxx:xxxx:xxxx:xxxx  prefixlen 64  scopeid 0x20<link>
        ether xx:xx:xx:xx:xx:xx  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 14  bytes 1068 (1.0 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0       

[root@Network ~]# ip netns exec qdhcp-585040c0-8dea-43f0-ba73-001955f59ce1 ifconfig                                                                                 
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

tapacc1dec2-5c: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1450
        inet 169.254.169.254  netmask 255.255.0.0  broadcast 169.254.255.255
        inet6 xxxx::xxxx:xxxx:xxxx:xxxx  prefixlen 64  scopeid 0x20<link>
        ether xx:xx:xx:xx:xx:xx  txqueuelen 1000  (Ethernet)
        RX packets 8  bytes 496 (496.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 5  bytes 446 (446.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

 

 

위 정보들을 통해 몇 가지 알 수 있는 정보들이 있습니다.

 

첫번째로, 앞서 언급한 4개의 port가 실제 인터페이스에서 보이지 않는 이유가 분리된 네임스페이스에 할당되었기 때문이라고 말씀 드렸습니다. 보시는 것과 같이 해당 인터페이스들이 각 네임스페이스에 생성되어 있는 것을 확인할 수 있습니다.

 

두번째로, 각 인터페이스에 할당된 ip 를 통해 해당 네임스페이스가 어떤 네임스페이스인지 알 수 있습니다. 우선 qdhcp-b7fc... 를 봤을 때  ip만 봐도 외부 네트워크의 dhcp agent를 위한 네임스페이스임을 알 수 있습니다.

 

라우터의 경우 현재는 1개이기 때문에 찾는데 어려움이 없지만 만약 라우터를 여러개 사용하는 경우에도 이런식으로 ip를 통해 해당 네임스페이스가 어떤 라우터의 네임스페이스인지 확인할 수 있습니다.

 

마지막으로 qdhcp-5850... 인터페이스가 있는 네임스페이스가 내부 네트워크의 dhcp agent를 위한 네임스페이스임을 알 수 있지만, 인터페이스에 할당된 ip가 특이합니다. (추후에 기회가 되면 포스팅하도록 하겠습니다)

 

최종적으로 앞서 분석한 내용을 바탕으로 전체 아키텍처를 구성해보면 아래 그림과 같습니다.

 

 

이상으로 가상 네트워크를 구성하면 실제 호스트에서는 어떻게 구성되는지 알아보았습니다. 본 포스팅의 핵심은 가상의 dhcp 에이전트와 라우터를 리눅스의 네임스페이스를 활용하여 구현한다는 것입니다.

 

이어서 다음 포스트에서는 가상머신을 생성하기 위한 과정을 진행해보고 또 호스트에서는 어떻게 동작하는지 분석하는 포스팅을 하도록 하겠습니다.

 

TAGS.

Comments