VxLAN գործարան. Մաս 1

Բարև, հաբր. Ես ներկայումս OTUS-ում Ցանցային ինժեների դասընթացի դասընթացի ղեկավարն եմ:
Դասընթացի համար նոր գրանցման մեկնարկի ակնկալիքով «Ցանցային ինժեներ», ես պատրաստել եմ հոդվածների շարք VxLAN EVPN տեխնոլոգիայի վերաբերյալ։

Հսկայական քանակությամբ նյութ կա այն մասին, թե ինչպես է աշխատում VxLAN EVPN-ը, ուստի ես ցանկանում եմ հավաքել տարբեր առաջադրանքներ և պրակտիկա ժամանակակից տվյալների կենտրոնում խնդիրների լուծման համար:

VxLAN գործարան. Մաս 1

VxLAN EVPN տեխնոլոգիայի մասին շարքի առաջին մասում ես ուզում եմ դիտարկել L2 կապը ցանցային հյուսվածքի վերևում հոսթերների միջև կազմակերպելու միջոց:

Բոլոր օրինակները կկատարվեն Cisco Nexus 9000v-ի վրա՝ հավաքված Spine-Leaf տոպոլոգիայում: Այս հոդվածում մենք չենք անդրադառնա Underlay ցանցի ստեղծման վրա:

  1. Ներքևի ցանց
  2. BGP peering հասցե-ընտանիքի համար l2vpn evpn
  3. NVE-ի կարգավորում
  4. Ճնշել-արփ

Ներքևի ցանց

Օգտագործված տոպոլոգիան հետևյալն է.

VxLAN գործարան. Մաս 1

Եկեք կարգավորենք հասցեավորումը բոլոր սարքերում.

Spine-1 - 10.255.1.101
Spine-2 - 10.255.1.102

Leaf-11 - 10.255.1.11
Leaf-12 - 10.255.1.12
Leaf-21 - 10.255.1.21

Host-1 - 192.168.10.10
Host-2 - 192.168.10.20

Եկեք ստուգենք, որ կա IP կապ բոլոր սարքերի միջև.

Leaf21# sh ip route
<........>
10.255.1.11/32, ubest/mbest: 2/0                      ! Leaf-11 доступен чеерз два Spine
    *via 10.255.1.101, Eth1/4, [110/81], 00:00:03, ospf-UNDERLAY, intra
    *via 10.255.1.102, Eth1/3, [110/81], 00:00:03, ospf-UNDERLAY, intra
10.255.1.12/32, ubest/mbest: 2/0                      ! Leaf-12 доступен чеерз два Spine
    *via 10.255.1.101, Eth1/4, [110/81], 00:00:03, ospf-UNDERLAY, intra
    *via 10.255.1.102, Eth1/3, [110/81], 00:00:03, ospf-UNDERLAY, intra
10.255.1.21/32, ubest/mbest: 2/0, attached
    *via 10.255.1.22, Lo0, [0/0], 00:02:20, local
    *via 10.255.1.22, Lo0, [0/0], 00:02:20, direct
10.255.1.101/32, ubest/mbest: 1/0
    *via 10.255.1.101, Eth1/4, [110/41], 00:00:06, ospf-UNDERLAY, intra
10.255.1.102/32, ubest/mbest: 1/0
    *via 10.255.1.102, Eth1/3, [110/41], 00:00:03, ospf-UNDERLAY, intra

Եկեք ստուգենք, որ VPC տիրույթը ստեղծվել է, և երկու անջատիչները անցել են հետևողականության ստուգումը, և երկու հանգույցների պարամետրերը նույնական են.

Leaf11# show vpc 

vPC domain id                     : 1
Peer status                       : peer adjacency formed ok
vPC keep-alive status             : peer is alive
Configuration consistency status  : success
Per-vlan consistency status       : success
Type-2 consistency status         : success
vPC role                          : primary
Number of vPCs configured         : 0
Peer Gateway                      : Disabled
Dual-active excluded VLANs        : -
Graceful Consistency Check        : Enabled
Auto-recovery status              : Disabled
Delay-restore status              : Timer is off.(timeout = 30s)
Delay-restore SVI status          : Timer is off.(timeout = 10s)
Operational Layer3 Peer-router    : Disabled

vPC status
----------------------------------------------------------------------------
Id    Port          Status Consistency Reason                Active vlans
--    ------------  ------ ----------- ------                ---------------
5     Po5           up     success     success               1

BGP peering

Վերջապես, կարող եք անցնել Overlay ցանցի ստեղծմանը:

Որպես հոդվածի մաս, անհրաժեշտ է ցանց կազմակերպել հոսթների միջև, ինչպես ցույց է տրված ստորև ներկայացված դիագրամում.

VxLAN գործարան. Մաս 1

Overlay ցանցը կարգավորելու համար դուք պետք է միացնեք BGP-ն ողնաշարի և տերևի անջատիչների վրա՝ l2vpn evpn ընտանիքի աջակցությամբ.

feature bgp
nv overlay evpn

Հաջորդը, դուք պետք է կարգավորեք BGP peering-ը Leaf-ի և Spine-ի միջև: Կարգավորումը պարզեցնելու և երթուղային տեղեկատվության բաշխումը օպտիմալացնելու համար մենք կարգավորում ենք Spine-ը որպես Route-Reflector սերվեր: Մենք կգրենք ամբողջ Leaf-ը կազմաձևում՝ օգտագործելով ձևանմուշներ՝ կարգավորումն օպտիմալացնելու համար:

Այսպիսով, Spine-ի կարգավորումներն այսպիսի տեսք ունեն.

router bgp 65001
  template peer LEAF 
    remote-as 65001
    update-source loopback0
    address-family l2vpn evpn
      send-community
      send-community extended
      route-reflector-client
  neighbor 10.255.1.11
    inherit peer LEAF
  neighbor 10.255.1.12
    inherit peer LEAF
  neighbor 10.255.1.21
    inherit peer LEAF

Leaf անջատիչի տեղադրումը նման է.

router bgp 65001
  template peer SPINE
    remote-as 65001
    update-source loopback0
    address-family l2vpn evpn
      send-community
      send-community extended
  neighbor 10.255.1.101
    inherit peer SPINE
  neighbor 10.255.1.102
    inherit peer SPINE

«Ողնաշարի» վրա եկեք ստուգենք «Peering»-ը բոլոր Leaf անջատիչների հետ.

Spine1# sh bgp l2vpn evpn summary
<.....>
Neighbor        V    AS MsgRcvd MsgSent   TblVer  InQ OutQ Up/Down  State/PfxRcd
10.255.1.11     4 65001       7       8        6    0    0 00:01:45 0
10.255.1.12     4 65001       7       7        6    0    0 00:01:16 0
10.255.1.21     4 65001       7       7        6    0    0 00:01:01 0

Ինչպես տեսնում եք, BGP-ի հետ կապված խնդիրներ չեն եղել: Եկեք անցնենք VxLAN-ի ստեղծմանը: Հետագա կոնֆիգուրացիան կկատարվի միայն անջատիչների տերևային կողմում: Ողնաշարը գործում է միայն որպես ցանցի առանցք և ներգրավված է միայն երթևեկության փոխանցման մեջ: Ամբողջ ինկապսուլյացիայի և ճանապարհի որոշման աշխատանքները կատարվում են միայն Leaf անջատիչների վրա:

NVE-ի կարգավորում

NVE - ցանցային վիրտուալ ինտերֆեյս

Նախքան կարգավորումը սկսելը, եկեք ներկայացնենք որոշ տերմինաբանություն.

VTEP - Vitual Tunnel End Point, սարքը, որով սկսվում կամ ավարտվում է VxLAN թունելը: VTEP-ը պարտադիր չէ, որ ցանցային սարք լինի: VxLAN տեխնոլոգիան աջակցող սերվերը կարող է նաև գործել որպես սերվեր: Մեր տոպոլոգիայում բոլոր Leaf անջատիչները VTEP են:

VNI - Վիրտուալ ցանցի ինդեքս - ցանցի նույնացուցիչ VxLAN-ի ներսում: VLAN-ի հետ կարելի է անալոգիա անել: Այնուամենայնիվ, կան որոշ տարբերություններ. Գործվածք օգտագործելիս VLAN-ները դառնում են եզակի միայն մեկ Leaf անջատիչի ներսում և չեն փոխանցվում ցանցով: Բայց յուրաքանչյուր VLAN կարող է ունենալ իր հետ կապված VNI համար, որն արդեն փոխանցվում է ցանցով: Ինչ տեսք ունի այն և ինչպես կարող է այն օգտագործվել, կքննարկվի հետագա:

Եկեք միացնենք VxLAN տեխնոլոգիայի գործառույթը և VLAN համարները VNI համարի հետ կապելու հնարավորությունը.

feature nv overlay
feature vn-segment-vlan-based

Եկեք կարգավորենք NVE ինտերֆեյսը, որը պատասխանատու է VxLAN-ի աշխատանքի համար: Այս ինտերֆեյսը պատասխանատու է VxLAN վերնագրերում շրջանակները ներառելու համար: Դուք կարող եք անալոգիա նկարել Թունելի ինտերֆեյսի հետ GRE-ի համար.

interface nve1
  no shutdown
  host-reachability protocol bgp ! используем BGP для передачи маршрутной информации
  source-interface loopback0    ! интерфейс  с которого отправляем пакеты loopback0

Leaf-21 անջատիչի վրա ամեն ինչ ստեղծված է առանց խնդիրների: Այնուամենայնիվ, եթե ստուգենք հրամանի ելքը show nve peers, ապա այն դատարկ կլինի։ Այստեղ դուք պետք է վերադառնաք VPC կոնֆիգուրացիան: Մենք տեսնում ենք, որ Leaf-11-ը և Leaf-12-ը աշխատում են զույգերով և միավորված են VPC տիրույթով: Սա մեզ տալիս է հետևյալ իրավիճակը.

Host-2-ն ուղարկում է մեկ շրջանակ դեպի Leaf-21, որպեսզի այն փոխանցի ցանցի միջոցով դեպի Host-1: Այնուամենայնիվ, Leaf-21-ը տեսնում է, որ Host-1-ի MAC հասցեն հասանելի է միանգամից երկու VTEP-ի միջոցով: Ի՞նչ պետք է անի Leaf-21-ն այս դեպքում: Ի վերջո, սա նշանակում է, որ ցանցում կարող է հայտնվել հանգույց:

Այս իրավիճակը լուծելու համար մեզ անհրաժեշտ է, որ Leaf-11-ը և Leaf-12-ը նույնպես գործեն որպես մեկ սարք գործարանում: Լուծումը բավականին պարզ է. Loopback ինտերֆեյսի վրա, որից մենք կառուցում ենք թունելը, ավելացրեք երկրորդական հասցե: Երկրորդական հասցեն պետք է լինի նույնը երկու VTEP-ների վրա:

interface loopback0
 ip add 10.255.1.10/32 secondary

Այսպիսով, այլ VTEP-ների տեսանկյունից մենք ստանում ենք հետևյալ տոպոլոգիան.

VxLAN գործարան. Մաս 1

Այսինքն՝ այժմ թունելը կկառուցվի Leaf-21-ի IP հասցեի և երկու Leaf-11-ի և Leaf-12-ի վիրտուալ IP-ի միջև։ Այժմ երկու սարքերից MAC հասցեն սովորելու հետ կապված խնդիրներ չեն լինի, և երթևեկությունը կարող է տեղափոխվել մեկ VTEP-ից մյուսը: Երկու VTEP-ներից որն է մշակելու երթևեկությունը, որոշվում է Spine-ի երթուղային աղյուսակի միջոցով.

Spine1# sh ip route
<.....>
10.255.1.10/32, ubest/mbest: 2/0
    *via 10.255.1.11, Eth1/1, [110/41], 1d01h, ospf-UNDERLAY, intra
    *via 10.255.1.12, Eth1/2, [110/41], 1d01h, ospf-UNDERLAY, intra
10.255.1.11/32, ubest/mbest: 1/0
    *via 10.255.1.11, Eth1/1, [110/41], 1d22h, ospf-UNDERLAY, intra
10.255.1.12/32, ubest/mbest: 1/0
    *via 10.255.1.12, Eth1/2, [110/41], 1d01h, ospf-UNDERLAY, intra

Ինչպես տեսնում եք վերևում, 10.255.1.10 հասցեն հասանելի է անմիջապես երկու Next hops-ի միջոցով:

Այս փուլում մենք գործ ունենք հիմնական կապի հետ: Եկեք անցնենք NVE ինտերֆեյսի ստեղծմանը.
Եկեք անմիջապես միացնենք Vlan 10-ը և այն կապենք VNI 10000-ի հետ յուրաքանչյուր Leaf-ի վրա տանտերերի համար: Եկեք ստեղծենք L2 թունել տանտերերի միջև

vlan 10                 ! Включаем VLAN на всех VTEP подключенных к необходимым хостам
  vn-segment 10000      ! Ассоциируем VLAN с номер VNI 

interface nve1
  member vni 10000      ! Добавляем VNI 10000 для работы через интерфейс NVE. для инкапсуляции в VxLAN
    ingress-replication protocol bgp    ! указываем, что для распространения информации о хосте используем BGP

Այժմ եկեք ստուգենք nve գործընկերները և աղյուսակը BGP EVPN-ի համար.

Leaf21# sh nve peers
Interface Peer-IP          State LearnType Uptime   Router-Mac
--------- ---------------  ----- --------- -------- -----------------
nve1      10.255.1.10      Up    CP        00:00:41 n/a                 ! Видим что peer доступен с secondary адреса

Leaf11# sh bgp l2vpn evpn

   Network            Next Hop            Metric     LocPrf     Weight Path
Route Distinguisher: 10.255.1.11:32777    (L2VNI 10000)        ! От кого именно пришел этот l2VNI
*>l[3]:[0]:[32]:[10.255.1.10]/88                                   ! EVPN route-type 3 - показывает нашего соседа, который так же знает об l2VNI10000
                      10.255.1.10                       100      32768 i
*>i[3]:[0]:[32]:[10.255.1.20]/88
                      10.255.1.20                       100          0 i
* i                   10.255.1.20                       100          0 i

Route Distinguisher: 10.255.1.21:32777
* i[3]:[0]:[32]:[10.255.1.20]/88
                      10.255.1.20                       100          0 i
*>i                   10.255.1.20                       100          0 i

Վերևում մենք տեսնում ենք միայն EVPN երթուղու 3-րդ տիպի երթուղիներ: Այս տեսակի երթուղիները խոսում են նմանակի (Leaf) մասին, բայց որտե՞ղ են մեր տանտերերը:
Բանն այն է, որ MAC հոսթների մասին տեղեկատվությունը փոխանցվում է EVPN երթուղու տիպի 2-ի միջոցով

Մեր հյուրընկալողներին տեսնելու համար դուք պետք է կարգավորեք EVPN երթուղու տիպ 2.

evpn
  vni 10000 l2
    route-target import auto   ! в рамках данной статьи используем автоматический номер для route-target
    route-target export auto

Եկեք պինգ կատարենք Host-2-ից Host-1:

Firewall2# ping 192.168.10.1
PING 192.168.10.1 (192.168.10.1): 56 data bytes
36 bytes from 192.168.10.2: Destination Host Unreachable
Request 0 timed out
64 bytes from 192.168.10.1: icmp_seq=1 ttl=254 time=215.555 ms
64 bytes from 192.168.10.1: icmp_seq=2 ttl=254 time=38.756 ms
64 bytes from 192.168.10.1: icmp_seq=3 ttl=254 time=42.484 ms
64 bytes from 192.168.10.1: icmp_seq=4 ttl=254 time=40.983 ms

Իսկ ստորև մենք կարող ենք տեսնել, որ 2-րդ երթուղին հյուրընկալող MAC հասցեով հայտնվել է BGP աղյուսակում՝ 5001.0007.0007 և 5001.0008.0007:

Leaf11# sh bgp l2vpn evpn
<......>

   Network            Next Hop            Metric     LocPrf     Weight Path
Route Distinguisher: 10.255.1.11:32777    (L2VNI 10000)
*>l[2]:[0]:[0]:[48]:[5001.0007.0007]:[0]:[0.0.0.0]/216                      !  evpn route-type 2 и mac адрес хоста 1
                      10.255.1.10                       100      32768 i
*>i[2]:[0]:[0]:[48]:[5001.0008.0007]:[0]:[0.0.0.0]/216                      ! evpn route-type 2 и mac адрес хоста 2
* i                   10.255.1.20                       100          0 i
*>l[3]:[0]:[32]:[10.255.1.10]/88
                      10.255.1.10                       100      32768 i
Route Distinguisher: 10.255.1.21:32777
* i[2]:[0]:[0]:[48]:[5001.0008.0007]:[0]:[0.0.0.0]/216
                      10.255.1.20                       100          0 i
*>i                   10.255.1.20                       100          0 i

Հաջորդը, դուք կարող եք տեսնել մանրամասն տեղեկատվություն Update-ի վերաբերյալ, որում դուք տեղեկատվություն եք ստացել MAC Host-ի մասին: Ստորև բերված է ոչ բոլոր հրամանների ելքը:

Leaf21# sh bgp l2vpn evpn 5001.0007.0007

BGP routing table information for VRF default, address family L2VPN EVPN
Route Distinguisher: 10.255.1.11:32777        !  отправил Update с MAC Host. Не виртуальный адрес VPC, а адрес Leaf
BGP routing table entry for [2]:[0]:[0]:[48]:[5001.0007.0007]:[0]:[0.0.0.0]/216,
 version 1507
Paths: (2 available, best #2)
Flags: (0x000202) (high32 00000000) on xmit-list, is not in l2rib/evpn, is not i
n HW

  Path type: internal, path is valid, not best reason: Neighbor Address, no labe
led nexthop
  AS-Path: NONE, path sourced internal to AS
    10.255.1.10 (metric 81) from 10.255.1.102 (10.255.1.102)    ! с кем именно строим VxLAN тоннель
      Origin IGP, MED not set, localpref 100, weight 0
      Received label 10000         ! Номер VNI, который ассоциирован с VLAN, в котором находится Host
      Extcommunity: RT:65001:10000 SOO:10.255.1.10:0 ENCAP:8        ! Тут видно, что RT сформировался автоматически на основе номеров AS и VNI
      Originator: 10.255.1.11 Cluster list: 10.255.1.102
<........>

Տեսնենք, թե ինչ տեսք ունեն շրջանակները, երբ դրանք անցնում են գործարանով.

VxLAN գործարան. Մաս 1

Suppress-ARP

Հիանալի է, մենք այժմ ունենք L2 հաղորդակցություն տանտերերի միջև և կարող ենք ավարտել այնտեղ: Այնուամենայնիվ, ամեն ինչ այնքան էլ պարզ չէ: Քանի դեռ տանտերերը քիչ են, խնդիրներ չեն լինի։ Բայց եկեք պատկերացնենք մի իրավիճակ, երբ մենք ունենք հարյուրավոր և հազարավոր հյուրընկալողներ: Ի՞նչ խնդրի կարող ենք հանդիպել:

Այս խնդիրը BUM (Broadcast, Unknown Unicast, Multicast) տրաֆիկն է: Այս հոդվածում մենք կքննարկենք հեռարձակման տրաֆիկի հետ գործ ունենալու տարբերակը:
Ethernet ցանցերում Հեռարձակման հիմնական գեներատորը հենց իրենք՝ հյուրընկալողներն են՝ ARP արձանագրության միջոցով:

Nexus-ն իրականացնում է ARP հարցումների դեմ պայքարելու հետևյալ մեխանիզմը՝ suppress-arp:
Այս հատկությունը գործում է հետևյալ կերպ.

  1. Host-1-ը APR հարցում է ուղարկում իր ցանցի Հեռարձակման հասցեին:
  2. Հարցումը հասնում է Leaf switch-ին և այս հարցումը գործվածքին Host-2 փոխանցելու փոխարեն, Leaf-ն ինքն է պատասխանում և ցույց է տալիս անհրաժեշտ IP-ն և MAC-ը:

Այսպիսով, Broadcast-ի հարցումը գործարան չի գնացել։ Բայց ինչպե՞ս կարող է դա աշխատել, եթե Leaf-ը գիտի միայն MAC հասցեն:

Ամեն ինչ բավականին պարզ է, EVPN երթուղու տիպ 2, բացի MAC հասցեից, կարող է փոխանցել MAC/IP համակցություն: Դա անելու համար դուք պետք է կարգավորեք IP հասցեն VLAN-ում Leaf-ում: Հարց է առաջանում՝ ի՞նչ IP պետք է դնեմ։ Nexus-ում հնարավոր է ստեղծել բաշխված (նույն) հասցե բոլոր անջատիչների վրա.

feature interface-vlan

fabric forwarding anycast-gateway-mac 0001.0001.0001    ! задаем virtual mac для создания распределенного шлюза между всеми коммутаторами

interface Vlan10
  no shutdown
  ip address 192.168.10.254/24          ! на всех Leaf задаем одинаковый IP
  fabric forwarding mode anycast-gateway    ! говорим использовать Virtual mac

Այսպիսով, տանտերերի տեսանկյունից ցանցը կունենա հետևյալ տեսքը.

VxLAN գործարան. Մաս 1

Եկեք ստուգենք BGP l2route evpn

Leaf11# sh bgp l2vpn evpn
<......>

   Network            Next Hop            Metric     LocPrf     Weight Path
Route Distinguisher: 10.255.1.11:32777    (L2VNI 10000)
*>l[2]:[0]:[0]:[48]:[5001.0007.0007]:[0]:[0.0.0.0]/216
                      10.255.1.21                       100      32768 i
*>i[2]:[0]:[0]:[48]:[5001.0008.0007]:[0]:[0.0.0.0]/216
                      10.255.1.10                       100          0 i
* i                   10.255.1.10                       100          0 i
* i[2]:[0]:[0]:[48]:[5001.0008.0007]:[32]:[192.168.10.20]/248
                      10.255.1.10                       100          0 i
*>i                   10.255.1.10                       100          0 i

<......>

Route Distinguisher: 10.255.1.21:32777
* i[2]:[0]:[0]:[48]:[5001.0008.0007]:[0]:[0.0.0.0]/216
                      10.255.1.20                       100          0 i
*>i                   10.255.1.20                       100          0 i
* i[2]:[0]:[0]:[48]:[5001.0008.0007]:[32]:[192.168.10.20]/248
*>i                   10.255.1.20                       100          0 i

<......>

Հրամանի ելքից կարող եք տեսնել, որ EVPN երթուղու տիպ 2-ում, բացի MAC-ից, մենք այժմ տեսնում ենք նաև հյուրընկալող IP հասցեն:

Եկեք վերադառնանք suppress-arp-ի կարգավորումներին: Այս պարամետրը միացված է յուրաքանչյուր VNI-ի համար առանձին՝

interface nve1
  member vni 10000   
    suppress-arp

Այնուհետև առաջանում է որոշակի բարդություն.

  • Որպեսզի այս ֆունկցիան աշխատի, TCAM հիշողության մեջ տեղ է պահանջվում: Ահա suppress-arp-ի կարգավորումների օրինակ.

hardware access-list tcam region arp-ether 256

Այս կարգավորումը կպահանջի կրկնակի լայնություն: Այսինքն, եթե դուք սահմանել եք 256, ապա դուք պետք է ազատեք 512-ը TCAM-ում: TCAM-ի կարգավորումը դուրս է այս հոդվածի շրջանակներից, քանի որ TCAM-ի կարգավորումը կախված է միայն ձեզ հանձնարարված առաջադրանքից և կարող է տարբերվել ցանցից մյուսը:

  • Suppress-arp-ի ներդրումը պետք է կատարվի բոլոր Leaf անջատիչների վրա: Այնուամենայնիվ, բարդություն կարող է առաջանալ VPC տիրույթում բնակվող Leaf զույգերի վրա կազմաձևելիս: Եթե ​​TCAM-ը փոխվի, զույգերի միջև հետևողականությունը կխախտվի, և մեկ հանգույց կարող է դուրս գալ աշխատանքից: Բացի այդ, TCAM-ի փոփոխության կարգավորումը կիրառելու համար կարող է պահանջվել սարքի վերագործարկում:

Արդյունքում, դուք պետք է ուշադիր մտածեք, թե արդյոք ձեր իրավիճակում արժե այս կարգավորումն իրականացնել գործող գործարանում:

Սրանով ավարտվում է շարքի առաջին մասը։ Հաջորդ մասում մենք կանդրադառնանք VxLAN գործվածքի միջոցով երթուղիներին՝ ցանցերի տարանջատմամբ տարբեր VRF-ների:

Իսկ հիմա բոլորին հրավիրում եմ անվճար վեբինար, որի շրջանակներում մանրամասն կպատմեմ դասընթացի մասին։ Այս վեբինարին գրանցված առաջին 20 մասնակիցները հեռարձակումից հետո 1-2 օրվա ընթացքում էլփոստի միջոցով կստանան զեղչի վկայական:

Source: www.habr.com

Добавить комментарий