Порядок передачи unicast трафика внутри фабрики Cisco ACI подробно описан в различных источниках, хотя внимательно изучить их и не свихнуться – та ещё задачка. Распространению BUM внутри overlay посвящены несколько секций, но вот то, что происходит в underlay, на мой взгляд, сознательно вынесено из основного документа. Тут вовлечена некая сущность – FTAG: один из spine становится корнем дерева, к которому присоединяются все leaf-коммутаторы. Общее количество активных FTAG – 12; очевидно, так сделали, чтобы обеспечить отказоусточивость и некую балансировку нагрузки.
Описание выше разумно, однако оно вызывает несколько вопросов:
-
Как происходит передача BUM трафика, когда uplink на leaf-коммутаторе выходит из строя? Если только один spine участвует в построении дерева, то трафик при таком сценарии некуда слать, значит, придётся отбросить – не очень-то отказоустойчиво получается.
-
Рассмотрим применение Remote Leaf: RL отправляют BUM трафик на anycast адрес spine-коммутаторов. Что произойдёт, если такой трафик попадёт на spine, который не участвует в нужном FTAG? Тот же самый вопрос справедлив и для Multi-Site архитектуры.
На сайте CiscoLive есть хороший семинар, который поможет нам ответить на эти вопросы. Схема лабы очень проста:
Всё, что нам нужно – это поднять связность между двумя endpoint в одном EPG.
Модуль Tenant:
resource "aci_tenant" "TestTenant" { name = "TestTenant" } resource "aci_vrf" "TestVrf" { tenant_dn = aci_tenant.TestTenant.id name = "TestVrf" } resource "aci_bridge_domain" "TestBD1" { tenant_dn = aci_tenant.TestTenant.id name = "TestBD1" relation_fv_rs_ctx = aci_vrf.TestVrf.id } resource "aci_subnet" "Subnet1" { parent_dn = aci_bridge_domain.TestBD1.id ip = "192.168.0.254/24" scope = ["private", "shared"] } resource "aci_application_profile" "TestAP" { tenant_dn = aci_tenant.TestTenant.id name = "TestAP" } resource "aci_application_epg" "TestEPG1" { application_profile_dn = aci_application_profile.TestAP.id name = "TestEPG1" relation_fv_rs_bd = aci_bridge_domain.TestBD1.id } resource "aci_epg_to_domain" "EPG1Domain" { application_epg_dn = aci_application_epg.TestEPG1.id tdn = aci_physical_domain.PhysicalDomain.id } resource "aci_bulk_epg_to_static_path" "TestEPG1StaticPath" { application_epg_dn = aci_application_epg.TestEPG1.id static_path { interface_dn = "topology/pod-1/paths-101/pathep-[eth1/2]" encap = "vlan-101" } static_path { interface_dn = "topology/pod-1/paths-104/pathep-[eth1/2]" encap = "vlan-101" } }
Модуль Access policies:
resource "aci_vlan_pool" "TestPool" { name = "TestPool" description = "From Terraform" alloc_mode = "static" } resource "aci_ranges" "TestRange" { vlan_pool_dn = aci_vlan_pool.TestPool.id from = "vlan-1" to = "vlan-1000" alloc_mode = "static" } resource "aci_physical_domain" "PhysicalDomain" { name = "PhysicalDomain" relation_infra_rs_vlan_ns = aci_vlan_pool.TestPool.id } resource "aci_attachable_access_entity_profile" "TestAAEP" { name = "TestAAEP" } resource "aci_aaep_to_domain" "PhysicalDomain-to-TestAAEP" { attachable_access_entity_profile_dn = aci_attachable_access_entity_profile.TestAAEP.id domain_dn = aci_physical_domain.PhysicalDomain.id } resource "aci_leaf_interface_profile" "TestInterfaceProfile" { name = "TestInterfaceProfile" } resource "aci_access_port_block" "TestAccessBlockSelector" { access_port_selector_dn = aci_access_port_selector.TestAccessPortSelector.id name = "TestAccessBlockSelector" from_card = "1" from_port = "2" to_card = "1" to_port = "2" } resource "aci_access_port_selector" "TestAccessPortSelector" { leaf_interface_profile_dn = aci_leaf_interface_profile.TestInterfaceProfile.id name = "TestAccessPortSelector" access_port_selector_type = "range" relation_infra_rs_acc_base_grp = aci_leaf_access_port_policy_group.TestAccessInterfacePolicy.id } resource "aci_leaf_access_port_policy_group" "TestAccessInterfacePolicy" { name = "TestAccessInterfaceProfile" relation_infra_rs_att_ent_p = aci_attachable_access_entity_profile.TestAAEP.id } resource "aci_leaf_profile" "TestSwitchProfile" { name = "TestSwitchProfile" leaf_selector { name = "LeafSelector" switch_association_type = "range" node_block { name = "Leaf101" from_ = "101" to_ = "101" } node_block { name = "Leaf104" from_ = "104" to_ = "104" } } relation_infra_rs_acc_port_p = [aci_leaf_interface_profile.TestInterfaceProfile.id] }
Если пробежаться по презентации, можно заметить, что схема FTAG немного отличается от таковой в документации: spine-коммутаторы, которые не являются корневыми, всё равно участвуют в FTAG, подключаясь к дереву через один-единственный leaf. Помните, что выбор корня FTAG происходит через расширение IS-IS? Заглянем в консоль:
Spine202# show isis internal mcast routes ftag <output omitted> FTAG ID: 0 [Root] [Enabled] Cost:( 2/ 13/ 0) ---------------------------------- Root port: Ethernet1/1.68 OIF List: FTAG ID: 1 [Root] [Enabled] Cost:( 0/ 0/ 0) ---------------------------------- Root port: - OIF List: Ethernet1/1.68 Ethernet1/2.67 Ethernet1/3.70 Ethernet1/4.69 FTAG ID: 2 [Root] [Enabled] Cost:( 0/ 0/ 0) ---------------------------------- Root port: - OIF List: Ethernet1/1.68 Ethernet1/2.67 Ethernet1/3.70 Ethernet1/4.69 FTAG ID: 3 [Root] [Enabled] Cost:( 0/ 0/ 0) ---------------------------------- Root port: - OIF List: Ethernet1/1.68 Ethernet1/2.67 Ethernet1/3.70 Ethernet1/4.69 FTAG ID: 4 [Root] [Enabled] Cost:( 0/ 0/ 0) ---------------------------------- Root port: - OIF List: Ethernet1/1.68 Ethernet1/2.67 Ethernet1/3.70 Ethernet1/4.69 FTAG ID: 5 [Enabled] Cost:( 2/ 7/ 0) ---------------------------------- Root port: Ethernet1/3.70 OIF List: FTAG ID: 6 [Enabled] Cost:( 2/ 8/ 0) ---------------------------------- Root port: Ethernet1/2.67 OIF List: FTAG ID: 7 [Enabled] Cost:( 2/ 9/ 0) ---------------------------------- Root port: Ethernet1/2.67 OIF List: FTAG ID: 8 [Enabled] Cost:( 2/ 8/ 0) ---------------------------------- Root port: Ethernet1/3.70 OIF List: FTAG ID: 9 [Enabled] Cost:( 2/ 7/ 0) ---------------------------------- Root port: Ethernet1/4.69 OIF List: FTAG ID: 10 [Enabled] Cost:( 2/ 12/ 0) ---------------------------------- Root port: Ethernet1/1.68 OIF List: FTAG ID: 11 [Root] [Enabled] Cost:( 0/ 0/ 0) ---------------------------------- Root port: - OIF List: Ethernet1/1.68 Ethernet1/2.67 Ethernet1/3.70 Ethernet1/4.69 FTAG ID: 12 [Root] [Enabled] Cost:( 0/ 0/ 0) ---------------------------------- Root port: - OIF List: Ethernet1/1.68 Ethernet1/2.67 Ethernet1/3.70 Ethernet1/4.69 FTAG ID: 13 [Disabled] FTAG ID: 14 [Disabled] FTAG ID: 15 [Disabled]
Spine201# show isis internal mcast route ftag <output omitted> FTAG ID: 0 [Root] [Enabled] Cost:( 0/ 0/ 0) ---------------------------------- Root port: - OIF List: Ethernet1/1.68 Ethernet1/2.67 Ethernet1/3.69 Ethernet1/4.70 FTAG ID: 1 [Enabled] Cost:( 2/ 8/ 0) ---------------------------------- Root port: Ethernet1/2.67 OIF List: FTAG ID: 2 [Enabled] Cost:( 2/ 9/ 0) ---------------------------------- Root port: Ethernet1/2.67 OIF List: FTAG ID: 3 [Enabled] Cost:( 2/ 8/ 0) ---------------------------------- Root port: Ethernet1/3.69 OIF List: FTAG ID: 4 [Enabled] Cost:( 2/ 8/ 0) ---------------------------------- Root port: Ethernet1/4.70 OIF List: FTAG ID: 5 [Root] [Enabled] Cost:( 0/ 0/ 0) ---------------------------------- Root port: - OIF List: Ethernet1/1.68 Ethernet1/2.67 Ethernet1/3.69 Ethernet1/4.70 FTAG ID: 6 [Root] [Enabled] Cost:( 0/ 0/ 0) ---------------------------------- Root port: - OIF List: Ethernet1/1.68 Ethernet1/2.67 Ethernet1/3.69 Ethernet1/4.70 FTAG ID: 7 [Root] [Enabled] Cost:( 0/ 0/ 0) ---------------------------------- Root port: - OIF List: Ethernet1/1.68 Ethernet1/2.67 Ethernet1/3.69 Ethernet1/4.70 FTAG ID: 8 [Root] [Enabled] Cost:( 0/ 0/ 0) ---------------------------------- Root port: - OIF List: Ethernet1/1.68 Ethernet1/2.67 Ethernet1/3.69 Ethernet1/4.70 FTAG ID: 9 [Root] [Enabled] Cost:( 0/ 0/ 0) ---------------------------------- Root port: - OIF List: Ethernet1/1.68 Ethernet1/2.67 Ethernet1/3.69 Ethernet1/4.70 FTAG ID: 10 [Root] [Enabled] Cost:( 0/ 0/ 0) ---------------------------------- Root port: - OIF List: Ethernet1/1.68 Ethernet1/2.67 Ethernet1/3.69 Ethernet1/4.70 FTAG ID: 11 [Enabled] Cost:( 2/ 12/ 0) ---------------------------------- Root port: Ethernet1/1.68 OIF List: FTAG ID: 12 [Enabled] Cost:( 2/ 13/ 0) ---------------------------------- Root port: Ethernet1/1.68 OIF List: FTAG ID: 13 [Disabled] FTAG ID: 14 [Disabled] FTAG ID: 15 [Disabled]
Действительно, все spine-коммутаторы участвуют в FTAG: если spine не является корнем, то у него не пуст Root port вместо OIL. GIPo адрес группы, которая соответствует BD – 225.0.69.80, поэтому она должна попадать в FTAG 0:
Такая топология позволяет естественным образом ответить на первый вопрос: если Leaf104 потеряет uplink в сторону Spine201, то он сможет использовать путь через Spine202 для передачи трафика внутри FTAG 0:
Spine202# show isis internal mcast routes ftag <output omitted> FTAG ID: 0 [Root][DEFERED] [Enabled] Cost:( 2/ 13/ 0) ---------------------------------- Root port: Ethernet1/1.68 OIF List: Ethernet1/4.69 <--------- link towards Leaf104 <output omitted>
Leaf104# show isis internal mcast routes ftag <output omitted> FTAG ID: 0 [Enabled] Cost:( 3/ 13/ 0) ---------------------------------- Root port: Ethernet1/50.12 <--------- link towards Spine202 OIF List: <output omitted>
Ответ на второй вопрос тоже понятен: если трафик попадает на некорневой spine, тот передаёт полученные пакеты через один из leaf-коммутаторов в нужный FTAG.
Spine202# show isis internal mcast route gipo <output omitted> GIPo: 225.0.69.80 [LOCAL] OIF List: Ethernet1/1.68 Ethernet1/4.70 Tunnel4 <--------- Multi-Site tunnel <output omitted>
Должен существовать некий механизм, предотвращающий отправку «внешнего» трафика обратно в сторону Remote Leaf или другого Site, но я не смог найти информацию о том, как именно он реализован (ставлю на некий бит в iVXLAN заголовке).
Имеет ли описанное выше какое-либо значение для эксплуатации ACI? Пожалуй, нет, в конце концов ACI – это решение «под ключ», которое прячет сложность внутри себя, в отличие от подхода «сделай сам». Впрочем, мне всё же кажется, было бы неплохо понимать, что именно происходит внутри подобной системы, а также иметь возможность в общем виде связать между собой подходы, присущие разным этапам эволюции продукта.
Спасибо за рецензию: Анастасии Куралёвой
Канал в Телеграме: https://t.me/networking_it_ru
ссылка на оригинал статьи https://habr.com/ru/articles/710696/
Добавить комментарий