이번 문서는 packet flow는 kolla 7.0 으로 배포한 구성에서 DVR을 활성화 하였을 경우 Floating ip를 추가 하여 packet이 어떻게 흘러가는지 확인 한 것이다.
1. "North-south" traffic(vm → internet)
배포 서버 혹은 openstack client 가 설치된 노드에서 openstack 명령어를 이용 하여 아래와 같이
"test"이름의 인스턴스가 "demo-net" 이름으로 172.12.10.4 아이피가 할당 되어 있으며,floating ip 로 192.168.10.106 가 설정 되어 있는 것을 확인 한다.
[root@cy2-deploy ~]# openstack server show test
+-------------------------------------+----------------------------------------------------------+
| Field | Value |
+-------------------------------------+----------------------------------------------------------+
| OS-DCF:diskConfig | AUTO |
| OS-EXT-AZ:availability_zone | nova |
| OS-EXT-SRV-ATTR:host | cy2-compute02 |
| OS-EXT-SRV-ATTR:hypervisor_hostname | cy2-compute02 |
| OS-EXT-SRV-ATTR:instance_name | instance-00000003 |
| OS-EXT-STS:power_state | Running |
| OS-EXT-STS:task_state | None |
| OS-EXT-STS:vm_state | active |
| OS-SRV-USG:launched_at | 2018-11-25T08:30:49.000000 |
| OS-SRV-USG:terminated_at | None |
| accessIPv4 | |
| accessIPv6 | |
| addresses | selfservice2=172.12.10.4, 192.168.10.106 |
| config_drive | |
| created | 2018-11-25T08:30:10Z |
| flavor | m1.medium (3) |
| hostId | 525330417c94af77f6cddd5850764a01445dfeb6d10620f35910d25f |
| id | aac0a6c0-4235-4543-b80d-bf7dcd349f77 |
| image | |
| key_name | mykey |
| name | test |
| progress | 0 |
| project_id | cceb34e1bc91413cb0137011e8734425 |
| properties | |
| security_groups | name='default' |
| status | ACTIVE |
| updated | 2018-11-26T03:54:51Z |
| user_id | e5b3cb7ad1f94ad5950bac42bf0aacf3 |
| volumes_attached | id='a8a24f42-ee15-4c33-9500-db289d307bc2' |
+-------------------------------------+----------------------------------------------------------+
기본적으로 같은 네트워크가 아닌 외부 인터넷 네트워크에 대하여 Default gateway인 172.12.10.1 로 보내며, 해당 gateway의 mac address인
fa:16:3e:78:d6:60 으로 포워딩 하게 설정 되어 있다.
[centos@test ~]$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc pfifo_fast state UP qlen 1000
link/ether fa:16:3e:ae:b3:e7 brd ff:ff:ff:ff:ff:ff
inet 172.12.10.4/24 brd 172.12.10.255 scope global dynamic eth0
valid_lft 80160sec preferred_lft 80160sec
inet6 fe80::f816:3eff:feae:b3e7/64 scope link
valid_lft forever preferred_lft forever
[centos@test ~]$ route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.12.10.1 0.0.0.0 UG 0 0 0 eth0
172.12.10.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
[centos@test ~]$ arp -a
gateway (172.12.10.1) at fa:16:3e:78:d6:60 [ether] on eth0
openstack por list 를 이용 하여 172.12.10.4 아이피를 사용 하는 포트의 정보를 확인 하면 MAC 주소,해당 포트의 아이디 등을 알 수 있다.
이중 8aa5e3b4-6c0b-4d77-8c45-146cacf576ec 라는 포트 아이디에서 앞의 10개의 문자를 기반으로 인터페이스 및 브릿지 등의 해당 포트의 관련된 아이디로 사용 된다.
즉 8aa5e3b4-6c0b-4d77-8c45-146cacf576ec 아이디에서 8aa5e3b4-6c 으로 실제 연결된 가상 인터페이스의 이름 등을 확인 할 수 있다.
[root@cy2-deploy ~]# openstack port list -f yaml | grep 172.12.10.4 -A 2
- {Fixed IP Addresses: 'ip_address=''172.12.10.4'', subnet_id=''39f6cf8d-0dc7-45c1-b63b-8cd83623b68d''',
ID: 8aa5e3b4-6c0b-4d77-8c45-146cacf576ec, MAC Address: 'fa:16:3e:ae:b3:e7', Name: '',
Status: ACTIVE}
논리적으로 아래 그림과 같이 인스턴스에 해당 포트의 아이디의 아이피가 연결 된것으로 볼 수 있다.
해당 인스턴스가 실행 되고 있는 compute node에서 "brctl show"를 이용 하여 앞에서 확인한 포트의 아이디 8aa5e3b4-6c 가 있는 브릿지를 확인 해본다.
인스턴스는 tap8aa5e3b4-6c 이름의 가상 인터페이스와 연결 되어 있으며, 해당 tap가상 인터페이스는 qbr8aa5e3b4-6c 이름의 linuxbridge로 연결 되어 있다.
해당 브릿지에 있는 iptables security group을 거친뒤 linuxbridge에는 qvb8aa5e3b4-6c 인터페이스로 패킷으로 보내거나 받는다.
[root@cy2-compute02 ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242b0a568b3 no
qbr8aa5e3b4-6c 8000.fa596f2d2f32 no qvb8aa5e3b4-6c
tap8aa5e3b4-6c
compute node의 iptables정책에서 8aa5e3b4-6c 아이디 중 앞의4자리인 8aa5으로 검색하면 아래와 같이 security group의 정책이 iptables의 정책으로 설정 되어 있는 것을 확인 할 수 있다.
[root@cy2-compute02 ~]# iptables -S | grep 8aa5
-N neutron-openvswi-i8aa5e3b4-6
-N neutron-openvswi-o8aa5e3b4-6
-N neutron-openvswi-s8aa5e3b4-6
-A neutron-openvswi-FORWARD -m physdev --physdev-out tap8aa5e3b4-6c --physdev-is-bridged -m comment --comment "Direct traffic from the VM interface to the security group chain." -j neutron-openvswi-sg-chain
-A neutron-openvswi-FORWARD -m physdev --physdev-in tap8aa5e3b4-6c --physdev-is-bridged -m comment --comment "Direct traffic from the VM interface to the security group chain." -j neutron-openvswi-sg-chain
-A neutron-openvswi-INPUT -m physdev --physdev-in tap8aa5e3b4-6c --physdev-is-bridged -m comment --comment "Direct incoming traffic from VM to the security group chain." -j neutron-openvswi-o8aa5e3b4-6
-A neutron-openvswi-i8aa5e3b4-6 -m state --state RELATED,ESTABLISHED -m comment --comment "Direct packets associated with a known session to the RETURN chain." -j RETURN
-A neutron-openvswi-i8aa5e3b4-6 -d 172.12.10.4/32 -p udp -m udp --sport 67 --dport 68 -j RETURN
-A neutron-openvswi-i8aa5e3b4-6 -d 255.255.255.255/32 -p udp -m udp --sport 67 --dport 68 -j RETURN
-A neutron-openvswi-i8aa5e3b4-6 -p icmp -j RETURN
-A neutron-openvswi-i8aa5e3b4-6 -m set --match-set NIPv415ca6cb4-09b4-418e-aee4- src -j RETURN
-A neutron-openvswi-i8aa5e3b4-6 -p tcp -m tcp -m multiport --dports 1:65535 -j RETURN
-A neutron-openvswi-i8aa5e3b4-6 -m state --state INVALID -m comment --comment "Drop packets that appear related to an existing connection (e.g. TCP ACK/FIN) but do not have an entry in conntrack." -j DROP
-A neutron-openvswi-i8aa5e3b4-6 -m comment --comment "Send unmatched traffic to the fallback chain." -j neutron-openvswi-sg-fallback
-A neutron-openvswi-o8aa5e3b4-6 -s 0.0.0.0/32 -d 255.255.255.255/32 -p udp -m udp --sport 68 --dport 67 -m comment --comment "Allow DHCP client traffic." -j RETURN
-A neutron-openvswi-o8aa5e3b4-6 -j neutron-openvswi-s8aa5e3b4-6
-A neutron-openvswi-o8aa5e3b4-6 -p udp -m udp --sport 68 --dport 67 -m comment --comment "Allow DHCP client traffic." -j RETURN
-A neutron-openvswi-o8aa5e3b4-6 -p udp -m udp --sport 67 --dport 68 -m comment --comment "Prevent DHCP Spoofing by VM." -j DROP
-A neutron-openvswi-o8aa5e3b4-6 -m state --state RELATED,ESTABLISHED -m comment --comment "Direct packets associated with a known session to the RETURN chain." -j RETURN
-A neutron-openvswi-o8aa5e3b4-6 -j RETURN
-A neutron-openvswi-o8aa5e3b4-6 -m state --state INVALID -m comment --comment "Drop packets that appear related to an existing connection (e.g. TCP ACK/FIN) but do not have an entry in conntrack." -j DROP
-A neutron-openvswi-o8aa5e3b4-6 -m comment --comment "Send unmatched traffic to the fallback chain." -j neutron-openvswi-sg-fallback
-A neutron-openvswi-s8aa5e3b4-6 -s 172.12.10.4/32 -m mac --mac-source FA:16:3E:AE:B3:E7 -m comment --comment "Allow traffic from defined IP/MAC pairs." -j RETURN
-A neutron-openvswi-s8aa5e3b4-6 -m comment --comment "Drop traffic without an IP/MAC allow rule." -j DROP
-A neutron-openvswi-sg-chain -m physdev --physdev-out tap8aa5e3b4-6c --physdev-is-bridged -m comment --comment "Jump to the VM specific chain." -j neutron-openvswi-i8aa5e3b4-6
-A neutron-openvswi-sg-chain -m physdev --physdev-in tap8aa5e3b4-6c --physdev-is-bridged -m comment --comment "Jump to the VM specific chain." -j neutron-openvswi-o8aa5e3b4-6
[root@cy2-compute02 ~]#
위 linux bridge 과정을 추가한 구성도를 보면 아래와 같은 구성인 것을 확인 할 수 있다.
ovs-vsctl show 명령어를 통하여 openvswitch 를 통하여 관리 되는 브릿지 들의 정보를 확인 한다.
이중 qvb8aa5e3b4-6c 와 연결되어 있는 br-int를 확인 해봐야 한다. br-int에는 qvo8aa5e3b4-6c 이름의 인터페이스가 qvb와 연결 되어 있다.
[root@cy2-compute02 ~]# docker exec -uroot -it neutron_openvswitch_agent ovs-vsctl show
27dd7152-b796-4d59-b1a7-afc5ee8d9889
Manager "ptcp:6640:127.0.0.1"
is_connected: true
Bridge br-tun
Controller "tcp:127.0.0.1:6633"
is_connected: true
fail_mode: secure
Port patch-int
Interface patch-int
type: patch
options: {peer=patch-tun}
Port br-tun
Interface br-tun
type: internal
Port "vxlan-0a0a140d"
Interface "vxlan-0a0a140d"
type: vxlan
options: {df_default="true", in_key=flow, local_ip="10.10.20.22", out_key=flow, remote_ip="10.10.20.13"}
Port "vxlan-0a0a140b"
Interface "vxlan-0a0a140b"
type: vxlan
options: {df_default="true", in_key=flow, local_ip="10.10.20.22", out_key=flow, remote_ip="10.10.20.11"}
Port "vxlan-0a0a140c"
Interface "vxlan-0a0a140c"
type: vxlan
options: {df_default="true", in_key=flow, local_ip="10.10.20.22", out_key=flow, remote_ip="10.10.20.12"}
Bridge br-int
Controller "tcp:127.0.0.1:6633"
is_connected: true
fail_mode: secure
Port patch-tun
Interface patch-tun
type: patch
options: {peer=patch-int}
Port "qr-56718ce4-c6"
tag: 1
Interface "qr-56718ce4-c6"
type: internal
Port "fg-38f32d91-3d"
tag: 2
Interface "fg-38f32d91-3d"
type: internal
Port br-int
Interface br-int
type: internal
Port "qvo8aa5e3b4-6c"
tag: 1
Interface "qvo8aa5e3b4-6c"
Port int-br-ex
Interface int-br-ex
type: patch
options: {peer=phy-br-ex}
Bridge br-ex
Controller "tcp:127.0.0.1:6633"
is_connected: true
fail_mode: secure
Port br-ex
Interface br-ex
type: internal
Port phy-br-ex
Interface phy-br-ex
type: patch
options: {peer=int-br-ex}
Port "eth4"
Interface "eth4"
ovs-appctl 를 사용하여 mac address table을 확인 하기 위해서는 해당 openvswitch의 pid나, ctl파일을 지정 해야 한다.
kolla로 배포 할 경우 이름 특정 번호로 생성 되기 때문에 ls 를 사용 하여 파일 이름을 확인 한다.
[root@cy-compute01 ~]# docker exec -it openvswitch_vswitchd ls -a /var/run/openvswitch/ovs-vswitchd.*.ctl
/var/run/openvswitch/ovs-vswitchd.14.ctl
이제 ovs-appctl 명령어에 fdb/show 옵션을 추가(FDB→forward data base) 하고 위에서 확인한 ctl파일을 지정 하여 br-int의 mac address table을 확인 하여 본다.
일반적인 L2 스위치의 FDB와 동일한 형태로 vlan 과 포워딩될 포트의 이름 aging time이 표현 된다.
앞에서 확인한 Default gateway(172.12.10.1) 의 mac address가 fa:16:3e:78:d6:60 라는 것을 확인 했었다. 해당 테이블에서 fa:16:3e:78:d6:60 주소는 vlan 1으로 설정 4번 포트로 포워딩 되도록 설정 되어 있다.
[root@cy-compute01 ~]# docker exec -it openvswitch_vswitchd ovs-appctl -t /var/run/openvswitch/ovs-vswitchd.14.ctl fdb/show br-int
port VLAN MAC Age
1 2 a0:c5:89:0e:a6:c8 297
1 2 52:54:00:0d:10:e8 264
1 2 00:14:5e:0a:80:66 240
1 2 00:0c:29:93:61:b3 187
1 2 7e:a1:17:1c:0d:ca 168
1 2 c4:85:08:cf:12:8c 166
1 2 00:1a:4a:16:01:ae 141
1 2 40:9c:28:5b:2a:80 126
1 2 28:d2:44:a0:a2:9b 122
...
4 1 fa:16:3e:78:d6:60 0
포워딩 될 포트를 알았으니, 해당 포트가 어떤 인터페이스인지 확인 해본다. ovs-ofctl show 명령어는 해당 브릿지의 포트의 정보를 확인 할 수 있는 명령어다.
4번포트에는 qr-56718ce4-c6 이름의 인터페이스로 되어 있으며 172.12.10.1 은 해당 이름의 포트로 포워딩 된다.
[root@cy2-compute02 ~]# docker exec -it openvswitch_vswitchd ovs-ofctl show br-int
OFPT_FEATURES_REPLY (xid=0x2): dpid:0000de935f730140
n_tables:254, n_buffers:0
capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS ARP_MATCH_IP
actions: output enqueue set_vlan_vid set_vlan_pcp strip_vlan mod_dl_src mod_dl_dst mod_nw_src mod_nw_dst mod_nw_tos mod_tp_src mod_tp_dst
1(int-br-ex): addr:fa:08:89:2f:91:b9
config: 0
state: 0
speed: 0 Mbps now, 0 Mbps max
2(patch-tun): addr:c6:3b:47:ae:1a:54
config: 0
state: 0
speed: 0 Mbps now, 0 Mbps max
4(qr-56718ce4-c6): addr:00:00:00:00:00:00
config: PORT_DOWN
state: LINK_DOWN
speed: 0 Mbps now, 0 Mbps max
6(fg-38f32d91-3d): addr:00:00:00:00:00:00
config: PORT_DOWN
state: LINK_DOWN
speed: 0 Mbps now, 0 Mbps max
8(qvo8aa5e3b4-6c): addr:ce:a3:0f:17:54:f8
config: 0
state: 0
current: 10GB-FD COPPER
speed: 10000 Mbps now, 0 Mbps max
LOCAL(br-int): addr:de:93:5f:73:01:40
config: PORT_DOWN
state: LINK_DOWN
speed: 0 Mbps now, 0 Mbps max
OFPT_GET_CONFIG_REPLY (xid=0x4): frags=normal miss_send_len=0
qr-56718ce4-c6 인터페이스는 이름에서 유추 할 수 있는 것 처럼 라우터 네임스페이스 연결 되는 가상인터페이스이다.
해당 노드의 namespace를 확인하면 qrouter-65710e96-0467-4281-9ada-63d3bdd4cd5e 라우터 네임스페이스를 확인 할 수 있다.
[root@cy2-compute02 ~]# ip netns
fip-eddc07d8-7544-4f3a-b9f4-27f005fb114f
qrouter-d3218b9c-73bb-4788-87e4-5828625fe586
해당 네임스페이스의 인터페이스를 확인해보자.
qr-56718ce4-c6 인터페이스가 해당 네임스페이스에 있는 것을 볼 수 있다. qr-56718ce4-c6 인터페이스는 172.12.10.0/24 대역의 게이트웨이인 172.12.10.1 이 할당 되어 있다.
vm은 해당 gateway 가 있는 네임스페이스 까지 패킷이 포워딩 된다.
[root@cy2-compute02 ~]# ip netns exec qrouter-d3218b9c-73bb-4788-87e4-5828625fe586 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: rfp-d3218b9c-7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
link/ether 96:80:29:54:59:f6 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 169.254.106.114/31 scope global rfp-d3218b9c-7
valid_lft forever preferred_lft forever
inet6 fe80::9480:29ff:fe54:59f6/64 scope link
valid_lft forever preferred_lft forever
15: qr-56718ce4-c6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN qlen 1000
link/ether fa:16:3e:78:d6:60 brd ff:ff:ff:ff:ff:ff
inet 172.12.10.1/24 brd 172.12.10.255 scope global qr-56718ce4-c6
valid_lft forever preferred_lft forever
inet6 fe80::f816:3eff:fe78:d660/64 scope link
valid_lft forever preferred_lft forever
qrouter 의 namespace까지의 구성을 보면 아래와 같은 그림으로 구성 된것을 확인 한다.
qrouter namespace에서는 fip 사용 유무에 따라서 s/dnat 를 수행 한다. 현 과정은 instance에서 외부 인터넷으로 나가기 때문에 내부 아이피172.12.10.4 아이피가 fip 192.168.10.106으로 snat 되야 한다. qrouter namespace 에서 nat 테이블에 neutron-l3-agent-float-snat 체인에서 출발지 아이피 172.12.10.4 아이피가 192.168.10.106 으로 snat되는 부분을 iptables에서 확인 할 수 있다. (-A neutron-l3-agent-float-snat -s 172.12.10.4/32 -j SNAT --to-source 192.168.10.106)
[root@cy2-compute02 ~]# ip netns exec qrouter-d3218b9c-73bb-4788-87e4-5828625fe586 iptables -S -t nat
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-N neutron-l3-agent-OUTPUT
-N neutron-l3-agent-POSTROUTING
-N neutron-l3-agent-PREROUTING
-N neutron-l3-agent-float-snat
-N neutron-l3-agent-snat
-N neutron-postrouting-bottom
-A PREROUTING -j neutron-l3-agent-PREROUTING
-A OUTPUT -j neutron-l3-agent-OUTPUT
-A POSTROUTING -j neutron-l3-agent-POSTROUTING
-A POSTROUTING -j neutron-postrouting-bottom
-A neutron-l3-agent-POSTROUTING ! -i rfp-d3218b9c-7 ! -o rfp-d3218b9c-7 -m conntrack ! --ctstate DNAT -j ACCEPT
-A neutron-l3-agent-PREROUTING -d 192.168.10.106/32 -i rfp-d3218b9c-7 -j DNAT --to-destination 172.12.10.4
-A neutron-l3-agent-PREROUTING -d 169.254.169.254/32 -i qr-+ -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 9697
-A neutron-l3-agent-float-snat -s 172.12.10.4/32 -j SNAT --to-source 192.168.10.106
-A neutron-l3-agent-snat -j neutron-l3-agent-float-snat
-A neutron-postrouting-bottom -m comment --comment "Perform source NAT on outgoing traffic." -j neutron-l3-agent-snat
해당 nat 과정을 거친 패킷은 외부로 어떻게 나갈까? 단순하게 qrouter namespace에서 route명령어로 확인 하면 어떤 인터페이스로 가야 할지 모른다.
[root@cy2-compute02 ~]# ip netns exec qrouter-d3218b9c-73bb-4788-87e4-5828625fe586 route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
169.254.106.114 0.0.0.0 255.255.255.254 U 0 0 0 rfp-d3218b9c-7
172.12.10.0 0.0.0.0 255.255.255.0 U 0 0 0 qr-56718ce4-c6
ip 명령어로 라우팅 테이블의 rule 을 확인 하면 기본적으로 있는 main,local,default외에 추가적인 rule을 볼 수 있다.
[root@cy2-compute02 ~]# ip netns exec qrouter-d3218b9c-73bb-4788-87e4-5828625fe586 ip rule ls
0: from all lookup local
32766: from all lookup main
32767: from all lookup default
57481: from 172.12.10.4 lookup 16
2886470145: from 172.12.10.1/24 lookup 2886470145
main,local,default 에서 처리 되지 못한 패킷이 16 이라는 라우팅 테이블에서 default 라우팅 되어 있는것을 볼 수 있다.(숫자가 main,default,local 보다 숫자가 높기 때문에)
즉, 16 라우팅 테이블에서 아래와 같이 169.254.106.115 아이피를 목적으로 rfp-d3218b9c-7 인터페이스를 통하여 snat 되어 패킷이 간다는 것을 알 수 있다.
[root@cy2-compute02 ~]# ip netns exec qrouter-d3218b9c-73bb-4788-87e4-5828625fe586 ip route ls table 16
default via 169.254.106.115 dev rfp-d3218b9c-7
다시 qrouter namspace에서 rfp-d3218b9c-7 인터페이스를 확인 하면 169.254.106.114 로 할당 되어 있다.
[root@cy2-compute02 ~]# ip netns exec qrouter-d3218b9c-73bb-4788-87e4-5828625fe586 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: rfp-d3218b9c-7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
link/ether 96:80:29:54:59:f6 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 169.254.106.114/31 scope global rfp-d3218b9c-7
valid_lft forever preferred_lft forever
inet6 fe80::9480:29ff:fe54:59f6/64 scope link
valid_lft forever preferred_lft forever
15: qr-56718ce4-c6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN qlen 1000
link/ether fa:16:3e:78:d6:60 brd ff:ff:ff:ff:ff:ff
inet 172.12.10.1/24 brd 172.12.10.255 scope global qr-56718ce4-c6
valid_lft forever preferred_lft forever
inet6 fe80::f816:3eff:fe78:d660/64 scope link
valid_lft forever preferred_lft forever
rfp-d3218b9c-7 인터페이스는 fip-eddc07d8-75 namespace에 fpr-d3218b9c-7 인터페이스와 peer to peer로 연결 되어 있어 해당 qrouter에서 처리된 패킷이 fip 으로 포워딩 된다.
또한 같은 namespace안에 있는 fg-38f32d91-3d 는 fip와 같은 대역을 같은 아이피로 floating ip의 gateway역할을 한다. (외부->내부)
[root@cy2-compute02 ~]# ip netns
fip-eddc07d8-7544-4f3a-b9f4-27f005fb114f
qrouter-d3218b9c-73bb-4788-87e4-5828625fe586
[root@cy2-compute02 ~]# ip netns exec fip-eddc07d8-7544-4f3a-b9f4-27f005fb114f ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: fpr-d3218b9c-7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
link/ether f2:d4:ad:59:11:7d brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 169.254.106.115/31 scope global fpr-d3218b9c-7
valid_lft forever preferred_lft forever
inet6 fe80::f0d4:adff:fe59:117d/64 scope link
valid_lft forever preferred_lft forever
16: fg-38f32d91-3d: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN qlen 1000
link/ether fa:16:3e:30:c9:5b brd ff:ff:ff:ff:ff:ff
inet 192.168.10.103/16 brd 192.168.255.255 scope global fg-38f32d91-3d
valid_lft forever preferred_lft forever
inet6 fe80::f816:3eff:fe30:c95b/64 scope link
valid_lft forever preferred_lft forever
[root@cy2-compute02 ~]#
fip namespace 도 동일하게 route table 중 가장 마지막 table에서 fip의 실제 gateway인 192.168.0.1.아이피를 목적으로 fg인터페이스로 연결 보내도록 설정 되어 있어서
인스턴스에서 보낸 패킷이 fg패킷을 통하여 포워딩 된다.
[root@cy2-compute02 ~]# ip netns exec fip-eddc07d8-7544-4f3a-b9f4-27f005fb114f ip rule
0: from all lookup local
32766: from all lookup main
32767: from all lookup default
2852022899: from all iif fpr-d3218b9c-7 lookup 2852022899
[root@cy2-compute02 ~]# ip netns exec fip-eddc07d8-7544-4f3a-b9f4-27f005fb114f ip route ls table 2852022899
default via 192.168.0.1 dev fg-38f32d91-3d
fg-38f32d91-3d 인터페이스는 다시 br-int 브릿지로 연결 된다. 아래와 같이 fg-38f32d91-3d 이름으로 연결 되어 있는것을 확인 할 수 있다
[root@cy2-compute02 ~]# docker exec -uroot -it neutron_openvswitch_agent ovs-vsctl show
...
Bridge br-int
Controller "tcp:127.0.0.1:6633"
is_connected: true
fail_mode: secure
Port patch-tun
Interface patch-tun
type: patch
options: {peer=patch-int}
Port "qr-56718ce4-c6"
tag: 1
Interface "qr-56718ce4-c6"
type: internal
Port "fg-38f32d91-3d"
tag: 2
Interface "fg-38f32d91-3d"
type: internal
Port br-int
Interface br-int
type: internal
Port "qvo8aa5e3b4-6c"
tag: 1
Interface "qvo8aa5e3b4-6c"
Port int-br-ex
Interface int-br-ex
type: patch
options: {peer=phy-br-ex}
...
지금까지 따라온 구조를 보면 아래와 같이 인스턴스에서 qbr 리눅스 브릿지를 통하여 security group 을 거쳤으며, 그뒤 br-int라는 openVswitch 브릿지를 통하여 qrouter namspace로 들어 온뒤
snat되어 fip namespace로 전달 되고, 다시 br-int까지 내려오는 구조라는 것을 확인 하였다.
이제 br-int에서 외부 gateway인 192.168.0.1이 어떻게 나가는지 확인 해야 한다.
arp -a 를 통하여 192.168.0.1의 mac주소를 90:9f:33:65:47:02 라는 것을 확인 한다.
[root@cy2-deploy ~]# arp -a | grep 192.168.0.1
gateway (192.168.0.1) at 90:9f:33:65:47:02 [ether] on eth1
br-int의 mac address table 에서 해당 mac이 1번 포트로 포워딩 되는 것을 확인 할 수 있으며,
1번 포트에는 int-br-ex 라는 인터페이스가 연결 되어 있는 것을 확인 할 수 있다.
[root@cy2-compute02 ~]# docker exec -it openvswitch_vswitchd ovs-appctl -t /var/run/openvswitch/ovs-vswitchd.14.ctl fdb/show br-int | grep 90:9f:33:65:47:02
port VLAN MAC Age
1 2 f8:63:3f:26:27:0d 209
1 2 e4:2b:34:25:3f:08 194
1 2 da:4e:e4:94:06:71 180
1 2 52:54:00:8c:91:81 178
1 2 82:58:13:e7:2c:9b 158
....
1 2 90:9f:33:65:47:02 2
[root@cy2-compute02 ~]# docker exec -it openvswitch_vswitchd ovs-ofctl show br-int
OFPT_FEATURES_REPLY (xid=0x2): dpid:0000de935f730140
n_tables:254, n_buffers:0
capabilities: FLOW_STATS TABLE_STATS PORT_STATS QUEUE_STATS ARP_MATCH_IP
actions: output enqueue set_vlan_vid set_vlan_pcp strip_vlan mod_dl_src mod_dl_dst mod_nw_src mod_nw_dst mod_nw_tos mod_tp_src mod_tp_dst
1(int-br-ex): addr:fa:08:89:2f:91:b9
config: 0
state: 0
speed: 0 Mbps now, 0 Mbps max
2(patch-tun): addr:c6:3b:47:ae:1a:54
config: 0
state: 0
speed: 0 Mbps now, 0 Mbps max
4(qr-56718ce4-c6): addr:00:00:00:00:00:00
config: PORT_DOWN
state: LINK_DOWN
speed: 0 Mbps now, 0 Mbps max
6(fg-38f32d91-3d): addr:00:00:00:00:00:00
config: PORT_DOWN
state: LINK_DOWN
speed: 0 Mbps now, 0 Mbps max
8(qvo8aa5e3b4-6c): addr:ce:a3:0f:17:54:f8
config: 0
state: 0
current: 10GB-FD COPPER
speed: 10000 Mbps now, 0 Mbps max
LOCAL(br-int): addr:de:93:5f:73:01:40
config: PORT_DOWN
state: LINK_DOWN
speed: 0 Mbps now, 0 Mbps max
OFPT_GET_CONFIG_REPLY (xid=0x4): frags=normal miss_send_len=0
다시 ovs-vsctl 을 통하여 브릿지들의 정보를 보면 int-br-ex 포트가 phy-br-ex 포트워 patch 타입으로 연결 되어 있으며 phy-br-ex는 br-ex 라는 브릿지에 속하여 있다.
br-ex에서는 최종적으로 포트 eth4을 통하여 나가며,해당 포트는 실제 인터 페이스 eth4를 통하여 포워딩 된다.
[root@cy2-compute02 ~]# docker exec -it openvswitch_vswitchd ovs-vsctl show
...
Bridge br-int
Controller "tcp:127.0.0.1:6633"
is_connected: true
fail_mode: secure
...
Port int-br-ex
Interface int-br-ex
type: patch
options: {peer=phy-br-ex}
Bridge br-ex
Controller "tcp:127.0.0.1:6633"
is_connected: true
fail_mode: secure
Port br-ex
Interface br-ex
type: internal
Port phy-br-ex
Interface phy-br-ex
type: patch
options: {peer=int-br-ex}
Port "eth4"
Interface "eth4"
최종적으로는 아래와 같은 형태로 실제 물리 인터페이스 eth4를 통하여 패킷이 gateway까지 포워딩 된다.
2. North-south traffic(internet → vm)
vm의 fip 인 192.168.10.106의 arp를 확인 하고, 해당 arp와 동일한 mac 주소를 확인 하면 192.168.10.103이라는 아이피를 확인 할 수 있다.
[root@cy2-deploy ~]# arp -a | grep 192.168.10.106
? (192.168.10.106) at fa:16:3e:30:c9:5b [ether] on eth1
[root@cy2-deploy ~]# arp -a | grep fa:16:3e:30:c9:5b
? (192.168.10.106) at fa:16:3e:30:c9:5b [ether] on eth1
? (192.168.10.103) at fa:16:3e:30:c9:5b [ether] on eth1
192.168.10.103은 해당 vm이 있는 노드의 fip가 포워딩 되는 fip namespace에서 fg 인터페이스에 할당 된 아이피로, 해당 인터페이스에서
Proxy Arp( 자신이 알고 있는 network 의 정보에 대하여 대신해서 arp응답을 해주는 기능)를 통하여 vm이 있는 네트워크 까지 올 수 있도록 해준다.
[root@cy2-compute02 ~]# ip netns exec fip-eddc07d8-7544-4f3a-b9f4-27f005fb114f ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: fpr-d3218b9c-7: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
link/ether f2:d4:ad:59:11:7d brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 169.254.106.115/31 scope global fpr-d3218b9c-7
valid_lft forever preferred_lft forever
inet6 fe80::f0d4:adff:fe59:117d/64 scope link
valid_lft forever preferred_lft forever
16: fg-38f32d91-3d: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN qlen 1000
link/ether fa:16:3e:30:c9:5b brd ff:ff:ff:ff:ff:ff
inet 192.168.10.103/16 brd 192.168.255.255 scope global fg-38f32d91-3d
valid_lft forever preferred_lft forever
inet6 fe80::f816:3eff:fe30:c95b/64 scope link
valid_lft forever preferred_lft forever
아래 그림과 같이 (1) 이 있는 부분으로 외부 게이트웨이를 통하여 들어온 패킷이 fg까지 가기 위해서(2)br-ex의 port eth4와 pyh-br-ex 를 거쳐서 br-int로 가게 된다.
(3)에서 br-int의 fg 포트를 통하여 fip namespace의 fg 인터페이스 192.168.10.103까지 전달 된다.
mac을 통하여 fip namespace에 왔지만 실제 fip 192.168.10.106을 찾아 가야 한다. fip라우팅 테이블을 확인 하면 fpr-d3218b9c-7 인터페이스를 통하여 qrouter로 포워딩 되게 설정 되어 있다.
[root@cy2-compute02 ~]# ip netns exec fip-eddc07d8-7544-4f3a-b9f4-27f005fb114f route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
169.254.106.114 0.0.0.0 255.255.255.254 U 0 0 0 fpr-d3218b9c-7
192.168.0.0 0.0.0.0 255.255.0.0 U 0 0 0 fg-38f32d91-3d
192.168.10.106 169.254.106.114 255.255.255.255 UGH 0 0 0 fpr-d3218b9c-7
qrouter로 들어온 패킷은 iptables 의 nat테이블에서 DNAT되어 도착지 아이피가 fip가 아닌 실제 할당된 내부 아이피로 변환 된다.
(-A neutron-l3-agent-PREROUTING -d 192.168.10.106/32 -i rfp-d3218b9c-7 -j DNAT --to-destination 172.12.10.4)
[root@cy2-compute02 ~]# ip netns exec qrouter-d3218b9c-73bb-4788-87e4-5828625fe586 iptables -S -t nat
-P PREROUTING ACCEPT
-P INPUT ACCEPT
-P OUTPUT ACCEPT
-P POSTROUTING ACCEPT
-N neutron-l3-agent-OUTPUT
-N neutron-l3-agent-POSTROUTING
-N neutron-l3-agent-PREROUTING
-N neutron-l3-agent-float-snat
-N neutron-l3-agent-snat
-N neutron-postrouting-bottom
-A PREROUTING -j neutron-l3-agent-PREROUTING
-A OUTPUT -j neutron-l3-agent-OUTPUT
-A POSTROUTING -j neutron-l3-agent-POSTROUTING
-A POSTROUTING -j neutron-postrouting-bottom
-A neutron-l3-agent-POSTROUTING ! -i rfp-d3218b9c-7 ! -o rfp-d3218b9c-7 -m conntrack ! --ctstate DNAT -j ACCEPT
-A neutron-l3-agent-PREROUTING -d 192.168.10.106/32 -i rfp-d3218b9c-7 -j DNAT --to-destination 172.12.10.4
-A neutron-l3-agent-PREROUTING -d 169.254.169.254/32 -i qr-+ -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 9697
-A neutron-l3-agent-float-snat -s 172.12.10.4/32 -j SNAT --to-source 192.168.10.106
-A neutron-l3-agent-snat -j neutron-l3-agent-float-snat
-A neutron-postrouting-bottom -m comment --comment "Perform source NAT on outgoing traffic." -j neutron-l3-agent-snat
172.12.10.4의 내부 아이피로 nat된 도착지 아이피는 qrouter namespace의 라우팅 테이블에 의하여 qr-56718ce4-c6 인터페이스로 포워딩 된다.
[root@cy2-compute02 ~]# ip netns exec qrouter-d3218b9c-73bb-4788-87e4-5828625fe586 route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
169.254.106.114 0.0.0.0 255.255.255.254 U 0 0 0 rfp-d3218b9c-7
172.12.10.0 0.0.0.0 255.255.255.0 U 0 0 0 qr-56718ce4-c6
qr-56718ce4-c6는 위에서 확인 한 것 처럼 br-int에 연결 되어 있는데, br-int의 mac address table을 확인 하면 8번 포트의
qvo8aa5e3b4-6c 로 qbr8aa5e3b4-6c 의 리눅스 브릿지를 통하여 까지 패킷이 포워딩 된다.
[root@cy2-compute02 ~]# ip netns exec qrouter-d3218b9c-73bb-4788-87e4-5828625fe586 arp -a | grep 172.12.10.4
? (172.12.10.4) at fa:16:3e:ae:b3:e7 [ether] PERM on qr-56718ce4-c6
[root@cy2-compute02 ~]# docker exec -it openvswitch_vswitchd ovs-appctl -t /var/run/openvswitch/ovs-vswitchd.14.ctl fdb/show br-int| grep fa:16:3e:ae:b3:e7
port VLAN MAC Age
....
8 1 fa:16:3e:ae:b3:e7 0
[root@cy2-compute02 ~]# docker exec -it openvswitch_vswitchd ovs-ofctl show br-int
....
8(qvo8aa5e3b4-6c): addr:ce:a3:0f:17:54:f8
config: 0
state: 0
current: 10GB-FD COPPER
speed: 10000 Mbps now, 0 Mbps max
....
아래 그림과 같이 (6)을 통하여 br-int로 전달 되고, br-int에서 qbr을 거쳐서 vm으로 전달 되는 과정이다.
반응형
'Openstack' 카테고리의 다른 글
openstack instance and kubernetes pod communication using ovs (0) | 2020.08.09 |
---|---|
openstack helm을 이용한 kubernetes환경에서 openstack 배포 (0) | 2020.08.02 |
Ansible Cloud(openstack) 모듈을 이용한 볼륨/인스턴스 생성 (0) | 2018.10.21 |
Openstack barbican install/Barbican-cinder encryption (0) | 2018.07.26 |
Openstack LBaaS (0) | 2018.05.12 |