DPVS Tutorial
Для компиляции и запуска DPVS, пожалуйста, проверьте README.md для этого проекта.
О концепциях Full-NAT (FNAT
), DR, Tunnel, TOA, OSPF/ECMP
и keepalived, пожалуйста, обратитесь к LVS и Alibaba/LVS.
Обратите внимание, что DPVS поддерживает режимы пересылки FNAT, DR, Tunnel, NAT, SNAT, и каждый режим может быть настроен как топология one-arm или two-arm, с или без OSPF/ECMP/keepalived. Существует слишком много комбинаций, я не могу перечислить все примеры здесь. Давайте просто приведём несколько популярных рабочих моделей, используемых в нашей повседневной работе.
Термин two-arm означает, что у вас есть клиенты на одной стороне балансировщика нагрузки (LB
) и серверы (RS
) на другой стороне, затем LB
пересылает пакеты между двумя своими логическими сетевыми интерфейсами. Например, балансировка нагрузки WAN-to-LAN.
С другой стороны, one-arm означает, что все клиенты и серверы находятся на одной стороне от балансировщика нагрузки, LB
пересылает трафик через один и тот же логический сетевой интерфейс.
Логический интерфейс (или устройство) может быть физическим интерфейсом DPDK или виртуальными устройствами DPVS, такими как bonding, vlan и tunnel.
Чтобы упростить задачу, мы пока не рассматриваем виртуальные устройства. Таким образом, топологии two-arm требуется:
/etc/dpvs.conf
также должен быть настроен с двумя интерфейсами. Пожалуйста, обратитесь к файлу conf/dpvs.conf.sample.Для one-arm нужен только один интерфейс DPDK, и вы можете обратиться к conf/dpvs.conf.single-nic.sample.
Как и LVS, DPVS можно развернуть в различных моделях кластеров для обеспечения высокой доступности (HA). Поддерживаются модели OSPF/ECMP и Master/Backup. Для модели OSPF/ECMP требуется пакет quagga и его программы zebra и ospfd. А для модели master/back требуется Keepalived.
Учитывая, что приложение DPDK полностью управляет сетевым интерфейсом (за исключением дополнительного управляющего сетевого адаптера, если он существует), программы Linux, работающие на стеке TCP/IP ядра, не могут напрямую получать пакеты от интерфейса DPDK. Чтобы программы Linux, такие как sshd, zebra/ospfd и keepalived работали, используется устройство DPDK kni. Затем программы Linux могут работать на устройстве kni со стеком TCP/IP Linux. Фактически, DPVS передаёт пакеты, которые ему не интересны, на устройство kni. Например, пакеты OSPF/VRRP/ssh. Так что программы, «работающие» на стеке Linux, могут их обрабатывать.
Следует отметить, что Keepalived — это... LVS
Исходный код TOA включён в проект DPVS (в каталоге kmod/toa) начиная с версии 1.7 для поддержки IPv6 и NAT64. Он получен из Alibaba TOA. Для приложений IPv6, которым требуется реальный IP-адрес клиента, рекомендуется использовать эту версию TOA.
Обратите внимание, что приложению могут потребоваться некоторые изменения, если вы используете NAT64. Необходимо вызвать дополнительный getsockopt, чтобы получить реальный IPv6-адрес клиента из сокета IPv4 на RS. В качестве примера приведён патч NAT64 для nginx-1.14 (../kmod/toa/example_nat64/nginx/nginx-1.14.0-nat64-toa.patch). Кстати, если вам не нужен реальный IP-адрес клиента, приложение не требует изменений.
Для работы с OSPF необходимо применить патч в patch/dpdk-xxx/ к соответствующим исходным кодам DPDK и установить правильный rte_kni.ko.
Модель кластера OSPF DPVS выглядит следующим образом, она использует OSPF / ECMP для обеспечения высокой доступности и масштабируемости. Эта модель широко используется на практике.
Для DPVS всё становится сложнее. Как упоминалось выше, программа DPDK (здесь dpvs) полностью контролирует сетевые адаптеры DPDK, поэтому программе Linux (ospfd) необходимо получать/отправлять пакеты через устройство kni (dpdk1.kni), связанное с устройством DPDK (dpdk1).
Таким образом, внутренняя взаимосвязь между интерфейсами и программами выглядит следующим образом:
Теперь конфигурация состоит из двух частей: одна для dpvs, а другая для zebra/ospfd.
Часть dpvs почти такая же, как в примере простого fnat, за исключением того, что:
Если вы добавляете какой-либо маршрут kni_host, который означает, что все пакеты будут отправляться в ядро с помощью dpvs, префикс длины kni_host должен быть равен 32.
#!/bin/sh -
# routes for LAN access
./dpip route add 192.168.100.0/24 dev dpdk0
# add service <VIP:vport> to forwarding, scheduling mode is RR.
# use ipvsadm --help for more info.
./ipvsadm -A -t 123.1.2.3:80 -s rr
# add two RS-es for service, forwarding mode is FNAT (-b)
./ipvsadm -a -t 123.1.2.3:80 -r 192.168.100.2 -b
./ipvsadm -a -t 123.1.2.3:80 -r 192.168.100.3 -b
# add at Local-IPs (LIPs) for FNAT on LAN interface
./ipvsadm --add-laddr -z 192.168.100.200 -t 123.1.2.3:80 -F dpdk0
./ipvsadm --add-laddr -z 192.168.100.201 -t 123.1.2.3:80 -F dpdk0
# add addr/route for dpvs.
./dpip addr add 123.1.2.3/32 dev dpdk1
./dpip addr add 172.10.0.2/30 dev dpdk1
./dpip route add default via 172.10.0.1 dev dpdk1
Затем часть zebra/ospfd. Во-первых, запустите протокол OSPF между сервером DPVS и wan-стороне L3-коммутатором с «интерконнект-сетью» (здесь 172.10.0.2/30). Для DPVS мы устанавливаем межсетевой IP на dpdk1.kni.
Предполагая, что пакет quagga установлен, если нет, пожалуйста, используйте yum (CentOS) или apt-get (Ubuntu) для его установки. После установки у вас должны быть zebra и ospfd, а также их конфигурационные файлы.
$ ip link set dpdk1.kni up
$ ip addr add 172.10.0.2/30 dev dpdk1.kni
$ ip addr add 123.1.2.3/32 dev dpdk1.kni # add VIP to kni for ospfd
$ ip route add default via 172.10.0.1 dev dpdk1.kni
VIP должен быть добавлен в устройство kni, чтобы позволить ospfd опубликовать его.
Проверьте работу межсетевого соединения с помощью ping коммутатора. 172.10.0.1: icmp_seq=1 ttl=255 time=2,19 ms
Теперь настроим zebra и ospfd. Для zebra ничего особенного, просто используем конфигурацию по умолчанию.
$ cat /etc/quagga/zebra.conf # может быть установлен в другой путь
! -*- zebra -*-
!
! zebra sample configuration file
!
! Id: zebra.conf.sample,v 1.1 2002/12/13 20:15:30 paul Exp $
!
hostname localhost.localdomain # изменить на реальное имя хоста
password ****
enable password ****
log file /var/log/quagga/zebra.log
service password-encryption
Для ospfd необходимо установить следующие параметры:
$ cat /etc/quagga/ospfd.conf # может быть установлен в другой путь
log file /var/log/quagga/ospf.log
log stdout
log syslog
password ****
enable password ****
interface dpdk1.kni # должно быть устройство kni на стороне wan
ip ospf hello-interval 10
ip ospf dead-interval 40
router ospf
ospf router-id 192.168.100.200 # просто использовать LAN IP
log-adjacency-changes
auto-cost reference-bandwidth 1000
network 172.10.0.0/30 area 0.0.0.0 # анонсировать межсетевую сеть
network 123.1.2.3/32 area 0.0.0.0 # анонсировать VIP
Учитывая, что маршрут VIP настроен на интерфейсе KNI, альтернативным способом публикации VIP является разрешение ospfd перераспределять подключённые маршруты, которые соответствуют VIP. Таким образом, вам не нужно изменять файл ospfd.conf и перезагружать ospfd каждый раз, когда вы хотите добавить больше VIP-адресов.
$ cat /etc/quagga/ospfd.conf # может быть установлен в другой путь
log file /var/log/quagga/ospf.log
log stdout
log syslog
password ****
enable password ****
access-list 1 permit 123.1.2.0 0.0.0.255 # access-list 1 разрешает сегмент VIP 123.1.2.0/24
route-map ecmp permit 10 # route-map «ecmp» соответствует IP-адресу из access-list 1
match ip address 1
interface dpdk1.kni # должно быть устройство KNI на стороне WAN
ip ospf hello-interval 10
ip ospf dead-interval 40
router ospf
ospf router-id 192.168.100.200 # просто использовать LAN IP
log-adjacency-changes
auto-cost reference-bandwidth 1000
redistribute connected route-map ecmp # перераспределить VIP в route-map «ecmp», route-map не обязателен, но рекомендуется
Обратите внимание, что OSPF также должен быть настроен на L3-коммутаторе. Этот учебник не о конфигурации OSPF, поэтому больше ничего о коммутаторе здесь нет.
Теперь запустите zebra и ospfd:
service restart zebra
service restart ospfd
Надеемся (если OSPF работает), что VIP будет доступен клиенту:
client: curl 123.1.2.3
Существуют и другие решения для достижения модели кластера OSPF и тому подобного. Например, OSPF и quagga можно заменить на BGP и bird, соответственно. Если вам интересно, пожалуйста, обратитесь к соответствующим документам или проконсультируйтесь с сетевым администратором.
Это пример использования FullNAT во внутренней сети (LAN). Keepalived (модифицированная версия DPVS) используется для того, чтобы DPVS работал как модель Master/Backup.
Используя keepalived, маршруты, LIP, VIP и RS можно настроить через конфигурационный файл keepalived. Обратите внимание, что параметры конфигурации для DPVS модифицированного keepalived немного отличаются от оригинального keepalived.
$ cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
foo@example.com
}
notification_email_from bar@example.com
smtp_server 1.2.3.4
smtp_connect_timeout 60
router_id DPVS_DEVEL
}
local_address_group laddr_g1 {
192.168.100.200 dpdk0 # использовать интерфейс DPDK
192.168.100.201 dpdk0 # использовать DPDK ```
interface
}
#
# VRRP section
#
vrrp_instance VI_1 {
state MASTER # master
interface dpdk0.kni # должен быть интерфейс kni
dpdk_interface dpdk0 # должен быть DPDK интерфейс
virtual_router_id 123 # VID должен быть уникальным в сети
priority 100 # приоритет мастера больше, чем у рабочего
advert_int 1
authentication {
auth_type PASS
auth_pass ****
}
virtual_ipaddress {
192.168.100.254
}
}
#
# Virtual Server Section
#
virtual_server_group 192.168.100.254-80 {
192.168.100.254 80
}
virtual_server group 192.168.100.254-80 {
delay_loop 3
lb_algo rr # алгоритм планирования Round-Robin
lb_kind FNAT # режим пересылки Full-NAT
protocol TCP # протокол TCP
laddr_group_name laddr_g1 # имя группы локальных IP-адресов
real_server 192.168.100.2 80 { # реальный сервер
weight 100
inhibit_on_failure
TCP_CHECK { # проверка работоспособности
nb_sock_retry 2
connect_timeout 3
connect_port 80
}
}
real_server 192.168.100.3 80 { # реальный сервер
weight 100
inhibit_on_failure
TCP_CHECK { # проверка работоспособности
nb_sock_retry 2
connect_timeout 3
connect_port 80
}
}
}
Конфигурация keepalived для резервного копирования такая же, как и для основного сервера, за исключением:
local_address_group laddr_g1 {
192.168.100.202 dpdk0 # использовать интерфейс DPDK
192.168.100.203 dpdk0 # использовать интерфейс DPDK
}
... ...
vrrp_instance VI_1 {
состояние BACKUP
приоритет 80
... ...
}
Запустите keepalived на основном сервере и резервном сервере.
./keepalived -f /etc/keepalived/keepalived.conf
Затем добавьте маршруты к интерфейсу DPDK вручную на основном и резервном серверах.
./dpip route add 192.168.100.0/24 dev dpdk0
Наконец, настройте dpdk0.kni, чтобы keepalived работал правильно.
ip link set dpdk0.kni up
ip addr add 192.168.100.28/24 dev dpdk0.kni # назначить IP для dpdk0.kni
dpip route add 192.168.100.28/32 scope kni_host dev dpdk0 # направить пакеты, предназначенные для 192.168.100.28, на dpdk0.kni
Обратите внимание, что IP-адреса dpdk0.kni должны отличаться для основного и резервного серверов.
Проверьте правильность установленных параметров:
$ ./ipvsadm -ln
IP Virtual Server version 0.0.0 (size=0)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.100.254:80 rr
-> 192.168.100.2:80 FullNat 100 0 0
-> 192.168.100.3:80 FullNat 100 0 0
$ ./dpip addr show -s
inet 192.168.100.254/32 scope global dpdk0
valid_lft forever preferred_lft forever
inet 192.168.100.201/32 scope global dpdk0
valid_lft forever preferred_lft forever sa_used 0 sa_free 1032176 sa_miss 0
inet 192.168.100.200/32 scope global dpdk0
valid_lft forever preferred_lft forever sa_used 0 sa_free 1032176 sa_miss 0
$ ./dpip route show
inet 192.168.100.28/32 via 0.0.0.0 src 0.0.0.0 dev dpdk0 mtu 1500 tos 0 scope kni_host metric 0 proto auto
inet 192.168.100.200/32 via 0.0.0.0 src 0.0.0.0 dev dpdk0 mtu 1500 tos 0 scope host metric 0 proto auto
inet 192.168.100.201/32 via 0.0.0.0 src 0.0.0.0 dev dpdk0 mtu 1500 tos 0 scope host metric 0 proto auto
inet 192.168.100.254/32 via 0.0.0.0 src 0.0.0.0 dev dpdk0 mtu 1500 tos 0 scope host metric 0 proto auto
inet 192.168.100.0/24 via 0.0.0.0 src 0.0.0.0 dev dpdk0 mtu 1500 tos 0 scope link metric 0 proto auto
$ ./ipvsadm -G
VIP:VPORT TOTAL SNAT_IP CONFLICTS CONNS
192.168.100.254:80 2
192.168.100.200 0 0
192.168.100.201 0 0
Кажется, всё хорошо, затем попробуйте получить доступ к VIP от клиента.
client$ curl 192.168.100.254
Your ip:port : 192.168.100.146:42394
``` **Перевод текста на русский язык:**
Keepalived, и не проверять, работает ли функция master/backup, предоставляемая Keepalived. При необходимости обратитесь к документации LVS.
> 2. Отказоустойчивость master/backup Keepalived может не сработать, если коммутатор включил подавление широковещательной рассылки ARP (к сожалению, это часто бывает). Если вы не хотите изменять конфигурацию своего коммутатора, уменьшение количества бесплатных пакетов ARP, отправляемых Keepalived (dpvs) при переключении, может помочь.
global_defs { ... ... vrrp_garp_master_repeat 1 # количество повторов для основного состояния gratuitous arp vrrp_garp_master_delay 1 # время перезапуска gratuitous arp после переключения на основной режим, в секундах vrrp_garp_master_refresh 600 # интервал времени для периодического обновления gratuitous arp (0 = нет), в секундах vrrp_garp_master_refresh_repeat 1 # количество повторений для периодического обновления gratuitous arp ... ... }
<a id='dr'/>
# DR-режим (одноплечевой)
Давайте рассмотрим простой пример DR-режима, который может понадобиться некоторым пользователям.

Чтобы использовать DR:
* dpvs сначала нужен IP-адрес локальной сети. (для одноплечевого режима он должен отличаться от VIP).
* RS и DPVS должны находиться в одной подсети (*on-link*).
* На RS: VIP должен быть добавлен к его интерфейсу lo.
* На RS: arp_ignore должен быть установлен для интерфейса lo.
> DPVS требуется IP-адрес, обращённый к RS (здесь означает «IP-адрес со стороны LAN», это не та концепция, что Local-IP (LIP), используемый FNAT, просто обычный IP-адрес). Потому что DPVS необходимо взаимодействовать с RS. Для одноплечевого режима этот IP-адрес LAN и VIP находятся на одном и том же интерфейсе DPDK. Но они не могут быть одинаковыми, потому что VIP также будет установлен на RS, если мы не используем отдельный IP-адрес LAN, RS не ответит на запрос ARP. Кроме того, IP-адрес LAN DPVS должен быть добавлен **перед** VIP.
> Для двухплечевого DR DPVS также требуется IP-адрес со стороны локальной сети для взаимодействия с хостами со стороны локальной сети, а VIP настроен на клиентском интерфейсе (WAN).
На DPVS конфигурация DR может быть следующей:
```bash
# на DPVS
# добавить IP-адрес для DPVS, он должен отличаться от VIP
# и должен быть добавлен перед VIP.
./dpip addr add 192.168.100.1/24 dev dpdk0
# добавить VIP, и маршрут будет создан автоматически.
./dpip addr add 192.168.100.254/32 dev dpdk0
# маршрут для сети LAN, просто подсказка.
#./dpip route add 192.168.100.0/24 dev dpdk0
# добавьте сервис <VIP:vport> для пересылки, режим планирования — RR.
# используйте ipvsadm --help для получения дополнительной информации.
./ipvsadm -A -t 192.168.100.254:80 -s rr
# добавьте два RS для сервиса, режим пересылки — DR
./ipvsadm -a -t 192.168.100.254:80 -r 192.168.100.2 -g
./ipvsadm -a -t 192.168.100.254:80 -r 192.168.100.3 -g
А затем на RS:
# для каждого реального сервера
rs$ ip addr add 192.168.100.254/32 dev lo # добавить VIP к каждому RS's lo
rs$ sysctl -w net.ipv4.conf.lo.arp_ignore=1 # игнорировать ARP на lo
net.ipv4.conf.lo.arp_ignore = 1
Попробуйте, сможет ли клиент получить доступ к VIP в режиме DR.
client$ curl 192.168.100.254
Your ip:port : 192.168.100.46:13862
Режим DR для двухплечевого аналогичен двухплечевому FNAT, пожалуйста, измените режим пересылки с помощью ipvsadm -g, и вам НЕ нужно настраивать LIP. Конфигурация RS такая же, как и для одноплечевого.
Поток трафика туннельного режима такой же, как у DR-режима. Он перенаправляет пакеты на RS, а затем RS отправляет ответы клиентам напрямую. В отличие от DR-режима, туннельный режим может пересылать пакеты через сеть L2 через ipip-туннели между DPVS и RS.
Конфигурации DPVS на приведённой выше диаграмме следующие.
## Конфигурации DPVS ##
# настроить сеть LAN на dpdk0
./dpip addr add 10.140.16.48/20 dev dpdk0
# настроить маршрут по умолчанию, `src` должен быть установлен для туннельного режима
./dpip route add default via 10.140.31.254 src 10.140.16.48 dev dpdk0
# добавить сервис <VIP:vport> для переадресации, режим планирования — RR
./ipvsadm -A -t 10.140.31.48:80 -s rr
# добавить RS в той же подсети, что и DPVS, режим переадресации — туннельный
./ipvsadm -a -t 10.140.31.48:80 -r 10.140.18.33 -i
# добавить ещё один RS в другой подсети с DPVS, режим переадресации — туннельный
./ipvsadm -a -t 10.140.31.48:80 -r 10.40.84.170 -i
# добавить VIP и маршрут будет сгенерирован автоматически
**Примечание**: в тексте запроса присутствуют фрагменты кода на языке программирования Bash, которые были оставлены без перевода. **Текст запроса написан на языке программирования bash.**
uses "match" service instead of *<vip:vport>* for TCP/UDP,
* default route may be needed on DPVS WAN interface.
> `match` supports `proto`, `src-range`, `dst-range`, `oif` and `iif`. For example: `proto=tcp,src-range=192.168.0.0-192.168.0.254,dst-range=0.0.0.0:1-1024,oif=dpdk1`.
The SNAT setting could be:
```bash
#!/bin/sh -
WAN_IP=123.1.2.3 # WAN IP can access Internet.
WAN_PREF=24 # WAN side network prefix length.
GATEWAY=123.1.2.1 # WAN side gateway
LAN_IP=192.168.100.1
LAN_PREF=24
# add WAN-side IP with sapool
./dpip addr add $WAN_IP/$WAN_PREF dev dpdk1 sapool # must add sapool for WAN-side IP
# add LAN-side IP as well as LAN route (generated)
./dpip addr add $LAN_IP/$LAN_PREF dev dpdk0
# add default route for WAN interface
./dpip route add default via $GATEWAY dev dpdk1
# SNAT section
# -H MATCH SNAT uses -H for "match" service instead of -t or -u
# MATCH support "proto", "src-range", "oif" and "iif".
# -r <WIP:0> used to specify the WAN IP after SNAT translation,
# the "port" part must be 0.
# -J for "SNAT" forwarding mode.
MATCH0='proto=tcp,src-range=192.168.100.0-192.168.100.254,oif=dpdk1'
MATCH1='proto=icmp,src-range=192.168.100.0-192.168.100.254,oif=dpdk1'
./ipvsadm -A -s rr -H $MATCH0
./ipvsadm -a -H $MATCH0 -r $WAN_IP:0 -w 100 -J
./ipvsadm -A -s rr -H $MATCH1
./ipvsadm -a -H $MATCH1 -r $WAN_IP:0 -w 100 -J
You can also use keepalived to configure SNAT instead of using ipvsadm. Every SNAT serivce should has parameter 'match':
virtual_server match SNAT1 {
protocol UDP
lb_algo rr
lb_kind SNAT
src-range 192.168.100.0-192.168.100.254
oif dpdk1
real_server 123.1.2.1 0 {
weight 4
}
}
virtual_server match SNAT2 {
protocol ICMP
lb_algo wrr
lb_kind SNAT
src-range 192.168.100.1-192.168.100.254
dst-range 123.1.2.0-123.1.2.254
oif dpdk1
iif dpdk0
real_server 123.1.2.1 0 {
weight 4
}
}
If you also want to use keepalived instead of using dpip to configure WAN/LAN IP, you can using 'alpha' and 'omega' to configure keepalived. Healthy check is needed in alpha mode, so you have to make a healthy check. And the result of the healthy check must always be true or RS(LAN IP in fact) will be deleted. You can use MISC_CHECK to make real_server/WAN IP always be healthy:
virtual_server match SNAT {
protocol UDP
delay_loop 3
lb_algo rr
lb_kind SNAT
src-range 192.168.100.0-192.168.100.254
oif dpdk1
alpha
omega
quorum 1
quorum_up "dpip addr add XXX;" ##Here is your cmd, you can also use a script.
quorum_down "dpip addr del XXX;"
real_server 123.1.2.2 0 {
weight 4
MISC_CHECK {
misc_path "exit 0"##Just make a healthy check which will always judge real_server healthy
misc_timeout 10
}
}
}
For hosts in "LAN", the default route should be set to DPVS
server's LAN IP.
host$ ip route add default via 192.168.100.1 dev eth0
Then try Internet access from hosts through SNAT DPVS
server.
host$ ping www.iqiyi.com
host$ curl www.iqiyi.com
DPVS support IPv6-IPv6 since v1.7 which means VIP/client IP/local IP/rs IP can be IPv6. You can configure IPv6 fullnat just like IPv4:
#!/bin/sh -
# add VIP to WAN interface
./dpip addr add 2001::1/128 dev dpdk1
# route for WAN/LAN access
# add routes for other network or default route if needed.
./dpip route -6 add 2001::/64 dev dpdk1
# add service <VIP:vport> to forwarding, scheduling mode is RR.
# use ipvsadm --help for more info.
./ipvsadm -A -t [2001::1]:80 -s rr
# add two RS for service, forwarding mode is FNAT (-b)
./ipvsadm -a -t [2001::1]:80 -r 2001::3 -b
./ipvsadm -a -t [2001::1]:80 -r 2001::4 -b
# add at least one Local-IP (LIP) for FNAT on LAN interface
./ipvsadm --add-laddr -z 2001::2 -t [2001::1]:80 -F dpdk0
You can use commands to check what's you have set like IPv4 except route:
$./dpip route -6 show
inet6 **Конфигурация IPv6 OSPF:**
```bash
$ cat /etc/quagga/ospf6d.conf # может быть установлен в другой путь
log file /var/log/quagga/ospf6.log
log stdout
log syslog
password ****
enable password ****
interface dpdk1.kni
ipv6 ospf6 network point-to-point
ipv6 ospf6 hello-interval 10
ipv6 ospf6 dead-interval 40
!
router ospf6
router-id 192.168.100.200
area 0.0.0.0 range 2001::1/64 # объявить VIP
area 0.0.0.0 range fec0::172:10:10:11/127 # объявить сеть межсоединения
interface dpdk1.kni area 0.0.0.0
!
Если вы предпочитаете keepalived, вы можете настроить его следующим образом:
$ cat /etc/keepalived/keepalived.conf
! Configuration File for keepalived
global_defs {
notification_email {
foo@example.com
}
notification_email_from bar@example.com
smtp_server 1.2.3.4
smtp_connect_timeout 60
router_id DPVS_DEVEL
}
local_address_group laddr_g1 {
2001::2 dpdk0 # использовать интерфейс DPDK
}
#
# VRRP раздел
#
vrrp_instance VI_1 {
state MASTER # мастер
interface dpdk0.kni # должен быть интерфейс kni, и IPv4 должен быть настроен для vrrp
dpdk_interface dpdk0 # должен быть интерфейс DPDK
virtual_router_id 123 # VID должен быть уникальным в сети
priority 100 # приоритет мастера больше, чем у рабочего
advert_int 1
authentication {
auth_type PASS
auth_pass ****
}
virtual_ipaddress {
2001::1
}
}
#
# Раздел виртуального сервера
#
virtual_server_group 2001-1-80 {
2001::1 80
}
virtual_server group 2001-1-80 {
delay_loop 3
lb_algo rr # алгоритм планирования Round-Robin
lb_kind FNAT # режим переадресации Full-NAT
protocol TCP # протокол TCP
laddr_group_name laddr_g1 # Идентификатор группы локальных IP-адресов
real_server 2001::3 80 { # реальный сервер
weight 100
inhibit_on_failure
TCP_CHECK { # проверка работоспособности
nb_sock_retry 2
connect_timeout 3
connect_port 80
}
}
real_server 2001::4 80 { # реальный сервер
weight 100
inhibit_on_failure
TCP_CHECK { # проверка работоспособности
nb_sock_retry 2
connect_timeout 3
connect_port 80
}
}
}
DPVS поддерживает IPv6-IPv4 для fullnat, что означает, что VIP/клиентский IP может быть IPv6, а локальный IP/RS IP может быть IPv4, вы можете настроить это следующим образом:
#!/bin/sh -
# добавить VIP на WAN-интерфейс
./dpip addr add 2001::1/128 dev dpdk1
# маршрут для доступа WAN/LAN
# добавьте маршруты для других сетей или по умолчанию, если необходимо.
./dpip route -6 add 2001::/64 dev dpdk1
./dpip route add 10.0.0.0/8 dev dpdk0
# добавить сервис <VIP:vport> в переадресацию, режим планирования — RR.
# используйте ipvsadm --help для получения дополнительной информации.
./ipvsadm -A -t [2001::1]:80 -s rr
# добавить два RS для сервиса, режим переадресации — FNAT (-b)
./ipvsadm -a -t [2001::1]:80 -r 10.0.0.1 -b
./ipvsadm -a -t [2001::1]:80 -r 10.0.0.2 -b
# добавить хотя бы один Local-IP (LIP) для FNAT на LAN-интерфейсе
./ipvsadm --add-laddr -z 10.0.0.3 -t [2001::1]:80 -F dpdk0
OSPF можно настроить так же, как IPv6-IPv6. Если вы предпочитаете keepalived, то можете настроить его так же, как и IPv6-IPv6, за исключением real_server/local_address_group.
IPv6 и управление потоком
Мы обнаружили, что некоторые сетевые карты не поддерживают (полностью) управление потоком IPv6, требуемое IPv6.
Например, rte_flow контроллера 82599 10GE (ixgbe PMD) опирается на старый тип потока flow director
(fdir), который не поддерживает IPv6 в своём идеальном режиме и поддерживает только один локальный IPv4 или IPv6 в сигнатурном режиме. DPVS поддерживает конфигурацию режима fdir для совместимости.
netif_defs {
...
mode signature
}
Другой способ избежать проблемы с не полностью поддерживаемым rte_flow — использовать перенаправление пересылки, которое перенаправляет полученные пакеты на правильный рабочий lcore, где находится сессия, с помощью незаблокированных колец DPDK.
Если вы хотите попробовать этот метод, включите: Перенаправление (redirect) в файле dpvs.conf
:
ipvs_defs {
conn {
...
redirect on
}
...
}
Следует отметить, что перенаправление может в определённой степени снизить производительность. Не используйте его, если у вас нет других решений.
Сохраняйте состояние «off», если только у вас нет иных решений.
DPVS
поддерживает виртуальные устройства, такие как Bonding, VLAN, IP-in-IP и GRE туннель.
Для устройства Bonding и DPVS
, и подключённый коммутатор/маршрутизатор должны установить интерфейсы Bonding с одинаковым режимом Bonding. Обратите внимание, что DPVS
пока поддерживает режимы Bonding 0 и 4. Чтобы включить устройство Bonding на DPVS
, обратитесь к conf/dpvs.bond.conf.sample. Каждому устройству Bonding требуется один или несколько DPDK физических устройств (dpdk0
, ...) для работы в качестве ведомых.
Чтобы использовать устройство VLAN, вы можете использовать инструмент dpip
. Устройство VLAN можно создать на основе реального физического устройства DPDK (например, dpdk0
, dpdk1
) или устройства Bonding (например, bond0
). Но нельзя создать устройство VLAN на устройстве VLAN.
Это пример VLAN, проверьте dpip vlan help
для получения дополнительной информации.
$ dpip vlan add dpdk0.100 link dpdk0 proto 802.1q id 100
$ dpip vann add link dpdk0 proto 802.1q id 101 # автогенерация имени устройства
$ dpip vlan add link dpdk1 id 102
$ dpip vlan add link bond1 id 103
DPVS
поддерживает туннельные устройства, включая IP-in-IP
и GRE
туннели. Это можно использовать, например, для кластера «SNAT-GRE», где удалённые хосты используют туннель для доступа в Интернет через SNAT-кластер DPVS
.
Настройка туннельного устройства аналогична тому, что мы делаем в Linux, но используем dpip
вместо ip(8)
.
$ dpip tunnel add mode ipip ipip1 local 1.1.1.1 remote 2.2.2.2
$ dpip tunnel add gre1 mode gre local 1.1.1.1 remote 2.2.2.2 dev dpdk0
Вы также можете использовать keepalived для настройки туннеля вместо использования ipvsadm
.
tunnel_group tunnel_gre {
tunnel_entry gre100 {
kind gre
local 10.62.5.10
remote 10.62.5.20
}
tunnel_entry gre200 {
kind gre
local 10.62.5.10
remote 10.62.6.10
}
tunnel_entry gre300 {
kind gre
local 10.62.5.10
remote 10.62.6.11
}
}
Также проверьте dpip tunnel help
для подробностей.
Примечания:
- RSS распределяет все пакеты по одной очереди/ЦП, поскольку исходный IP-адрес подслоя может быть одинаковым. Если одно ядро lcore получает полный
sa_pool
, происходитsa_miss
. Это не проблема для некоторых сетевых карт, которые поддерживают внутренний RSS для туннелирования. 2.rte_flow
/rss
не будут хорошо работать на туннельном устройстве, не используйте туннель для FNAT.
Как и физические устройства DPDK, виртуальные устройства Bonding и VLAN (например, bond0
и dpdk0.100
) имеют свои собственные связанные устройства KNI
в среде Linux (например, bond0.kni
, dpdk0.100.kni
).
Пример взаимосвязи между физическими устройствами, устройствами vlan, bonding и устройствами KNI
.
Настроить DPVS
(FNAT/DR/Tunnel/SNAT, one-arm/two-arm, keepalived/ospfd) для виртуального устройства не составляет труда. Просто «замените» логические интерфейсы в разделах выше (например, dpdk0
, dpdk1
, dpdk1.kni
) соответствующими виртуальными устройствами.
Как известно, TOA используется для получения реального клиентского IP/порта TCP в режиме LVS FNAT. Мы представляем UDP Option of Address или UOA, чтобы позволить RS получать реальный клиентский IP/порт для сценария, когда исходный IP/порт изменены промежуточными устройствами (такими как UDP FNAT).
Для этого необходимо:
uoa.ko
на RS.getsockopt(2)
, чтобы получить реальный клиентский IP/порт.Пример кода C для RS, чтобы получить реальный IP клиента, можно найти здесь.
rs$ insmod uoa.ko
rs$ cat /proc/net/uoa_stats
Success Miss Invalid|UOA Got None Saved Ack-Fail
12866352 317136864 0 3637127 341266254 3628560 0
Статистика поддерживается для целей отладки. Обратите внимание на то, что... PID-файл, конфигурационный файл и файл сокета IPC, которые задаются следующими опциями DPVS соответственно:
Например:
./bin/dpvs -c /etc/dpvs1.conf -p /var/run/dpvs1.pid -x /var/run/dpvs1.ipc -- --file-prefix=dpvs1 -a 0000:4b:00.0 -a 0000:4b:00.1 -l 0-8 --main-lcore 0
Изоляция процесса Keepalived
Один экземпляр DPVS соответствует одному экземпляру keepalived, и наоборот. Аналогично, разные процессы keepalived должны иметь уникальные конфигурационные файлы и PID-файлы. Обратите внимание, что в зависимости от конфигурации keepalived для DPVS может состоять из трёх процессов-демонов: основного процесса, подпроцесса проверки работоспособности и подпроцесса VRRP. Конфигурационные файлы и файлы PID для разных экземпляров keepalived можно задать с помощью следующих опций соответственно:
Например:
./bin/keepalived -D -f etc/keepalived/keepalived1.conf --pid=/var/run/keepalived1.pid --vrrp_pid=/var/run/vrrp1.pid --checkers_pid=/var/run/checkers1.pid
Взаимодействие с различными экземплярами DPVS с помощью dpip/ipvsadm
Dpip и ipvsadm — это инструменты, используемые для настройки DPVS. По умолчанию они хорошо работают на сервере с одним экземпляром DPVS без каких-либо дополнительных настроек. Но на сервере с несколькими экземплярами DPVS следует предварительно установить переменную среды DPVS_IPC_FILE как файл сокетов IPC DPVS, с которым хотят взаимодействовать ipvsadm/dpip. Обратитесь к предыдущей части «Изоляция процессов DPVS» для получения информации о том, как указать различные файлы сокетов IPC для нескольких экземпляров DPVS. Например:
DPVS_IPC_FILE=/var/run/dpvs1.ipc ipvsadm -ln
# или эквивалентно:
export DPVS_IPC_FILE=/var/run/dpvs1.ipc
ipvsadm -ln
Порты NIC, KNI и маршруты
Несколько экземпляров DPVS, работающих на сервере, независимы, то есть DPVS использует модель развёртывания Running Multiple Independent DPDK Applications, которая требует, чтобы экземпляры не могли совместно использовать порты NIC. Мы можем использовать опции EAL -a, --allow или -b, --block, чтобы разрешить/запретить использование портов NIC для экземпляра DPVS. Однако модуль ядра Linux KNI поддерживает только один экземпляр DPVS в конкретном сетевом пространстве имён (см. kernel/linux/kni/kni_misc.c). В основном DPVS предлагает два решения этой проблемы.
# dpvs.conf
global_defs {
...
<init> kni on <default on, on|off>
...
}
Сначала создайте новое сетевое пространство имён, например, «dpvsns».
/usr/sbin/ip netns add dpvsns
Затем переместите порты NIC для этого экземпляра DPVS в только что созданное сетевое пространство имён.
/usr/sbin/ip link set eth1 netns dpvsns
/usr/sbin/ip link set eth2 netns dpvsns
/usr/sbin/ip link set eth3 netns dpvsns
Наконец, запустите DPVS и все связанные с ним процессы (например, keepalived, маршрутизирующий демон) в сетевом пространстве имён.
/usr/sbin/ip netns exec dpvsns ./bin/dpvs -c /etc/dpvs2.conf -p /var/run/dpvs2.pid -x /var/run/dpvs2.ipc -- --file-prefix=dpvs2 -a 0000:cb:00.1 -a 0000:ca:00.0 -a 0000:ca:00.1 -l 12-20 --main-lcore 12
/usr/sbin/ip netns exec dpvsns ./bin/keepalived -D --pid=/var/run/keepalived2.pid --vrrp_pid=/var/run/vrrp2.pid --checkers_pid=/var/run/checkers2.pid -f etc/keepalived/keepalived2.conf
/usr/sbin/ip netns exec dpvsns /usr/sbin/bird -f -c /etc/bird2.conf -s /var/run/bird2/bird.ctl
...
Для повышения производительности мы можем включить режим нескольких kthread при развёртывании нескольких экземпляров DPVS на сервере. В этом режиме каждый порт KNI является... Отладка DPVS
Если DPVS работает не так, как ожидается, рассмотрите следующие решения для отладки, перечисленные в порядке от простого к сложному.
Мы не будем подробно рассматривать отладку на основе исходного кода, поскольку она ничем не отличается от отладки других пользовательских программ. Просто включите флаг DEBUG, определённый в src/Makefile, перекомпилируйте DPVS и пошагово отлаживайте его с помощью gdb. Это самое базовое и эффективное решение для отладки, хотя оно требует некоторых знаний об исходном коде DPVS и навыков отладки.
Отладка с использованием логов
Во-первых, по умолчанию DPVS запускается с уровнем журнала WARNING. Вы можете изменить его в /etc/dpvs.conf
и перезагрузить DPVS с помощью команды kill -SIGHUP
. DPVS поддерживает 8 уровней журналов:
Использование более низких уровней журнала, таких как «INFO» или «DEBUG», может помочь найти больше информации о вашей проблеме.
Во-вторых, некоторые модули поддерживают более подробную отладочную информацию, которую можно включить при компиляции DPVS. Модульные параметры отладки доступны в config.mk, некоторые из них перечислены ниже. Измените значение на «y» и перекомпилируйте DPVS, если вы хотите отладить модуль.
- CONFIG_DPVS_IPVS_DEBUG # для отладки переадресации ipvs
- CONFIG_RECORD_BIG_LOOP # для настройки производительности
- CONFIG_TIMER_MEASURE # для отладки точности таймера
- CONFIG_TIMER_DEBUG # для отладки таймеров dpvs
- CONFIG_MSG_DEBUG # для отладки lcore msg и ipc dpvs
- CONFIG_DPVS_MBUF_DEBUG # для отладки mbuf
- CONFIG_DPVS_NEIGH_DEBUG # для отладки модуля соседа
- CONFIG_NDISC_DEBUG # для отладки модуля ndisc
- CONFIG_DPVS_SAPOOL_DEBUG # для отладки модуля sapool
- CONFIG_SYNPROXY_DEBUG # для отладки syn-proxy
- CONFIG_DPVS_MP_DEBUG # для отладки пула памяти
- ... ...
Обратите внимание, что логи могут сильно влиять на производительность. Рекомендуется отключить журналы отладки в производственных средах.
Захват пакетов и Tcpdump
Поскольку DPVS управляется драйвером PMD DPDK и обходит ядро, традиционные инструменты захвата пакетов, такие как tcpdump и wireshark, не могут работать напрямую с DPVS. DPVS поддерживает два механизма захвата пакетов: forward-to-kni и dpdk-pdump.
Обратите внимание: оба механизма захвата пакетов сильно влияют на производительность. Не включайте их в рабочих средах!
Для объяснения этих двух механизмов мы используем следующий тестовый пример.
# cat pkt-cap.sh
#!/bin/bash
./bin/dpvs &
sleep 40 # wait for DPVS up
./bin/dpip addr add 192.168.88.12/24 dev dpdk0 # Host IP address
./bin/dpip addr add 192.168.88.100/32 dev dpdk0 # VIP
./bin/ipvsadm -A -t 192.168.88.100:80 -s mh
./bin/ipvsadm -a -t 192.168.88.100:80 -r 192.168.88.15:80 -b # FNAT mode
./bin/ipvsadm -Pt 192.168.88.100:80 -z 192.168.88.241 -F dpdk0 # Local IP address
После успешного выполнения скрипта проверьте конфигурации.
$ ./bin/dpip addr show -s
inet 192.168.88.12/24 scope global dpdk0
valid_lft forever preferred_lft forever
inet 192.168.88.100/32 scope global dpdk0
valid_lft forever preferred_lft forever
inet 192.168.88.241/32 scope global dpdk0
valid_lft forever preferred_lft forever sa_used 0 sa_free 1032176 sa_miss 0
$ ./bin/dpip route show
inet 192.168.88.12/32 via 0.0.0.0 src 0.0.0.0 dev dpdk0 mtu 1500 tos 0 scope host metric 0 proto auto
inet 192.168.88.100/32 via 0.0.0.0 src 0.0.0.0 dev dpdk0 mtu 1500 tos 0 scope host metric 0 proto auto
inet 192.168.88.241/32 via 0.0.0.0 src 0.0.0.0 dev dpdk0 mtu 1500 tos 0 scope host metric 0 proto auto
inet 192.168.88.0/24 via 0.0.0.0 src 192.168.88.12 dev dpdk0 mtu 1500 tos 0 scope link metric 0 proto auto
$ ./bin/ipvsadm -ln
IP Virtual Server version 0.0.0 (size=0)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port
``` Наконец, мы можем проверить файлы pcap с захваченными пакетами с помощью `tcpdump` или `wireshark`.
```bash
$ tcpdump -nn -r /tmp/icmp.pcap
чтение из файла /tmp/icmp.pcap, тип ссылки EN10MB (Ethernet)
18:21:01.327633 IP 192.168.88.15 > 192.168.88.12: ICMP эхо-запрос, идентификатор 35422, последовательность 1, длина 64
18:21:01.327679 IP 192.168.88.12 > 192.168.88.15: ICMP эхо-ответ, идентификатор 35422, последовательность 1, длина 64
$ tcpdump -nn -r /tmp/tcp.pcap
чтение из файла /tmp/tcp.pcap, тип ссылки EN10MB (Ethernet)
18:21:22.572153 IP 192.168.88.15.53186 > 192.168.88.100.80: флаги [S], последовательность 889492797, окно 29200, опции [mss 1460,nop,nop,sackOK,nop,wscale 9], длина 0
18:21:22.572203 IP 192.168.88.241.1028 > 192.168.88.15.80: флаги [S], последовательность 3216285976, окно 29200, опции [exp-cfc2,mss 1460,nop,nop,sackOK,nop,wscale 9], длина 0
18:21:22.572243 IP 192.168.88.15.80 > 192.168.88.241.1028: флаги [S.], последовательность 1294831393, подтверждение 3216285977, окно 29200, опции [mss 1460,nop,nop,sackOK,nop,wscale 9], длина 0
18:21:22.572248 IP 192.168.88.100.80 > 192.168.88.15.53186: флаги [S.], последовательность 1294831393, подтверждение 889492798, окно 29200, опции [mss 1452,nop,nop,sackOK,nop,wscale 9], длина 0
18:21:22.572286 IP 192.168.88.15.53186 > 192.168.88.100.80: флаги [.], подтверждение 1, окно 58, длина 0
18:21:22.572288 IP 192.168.88.241.1028 > 192.168.88.15.80: флаги [.], подтверждение 1, окно 58, опции [exp-cfc2], длина 0
18:21:22.572339 IP 192.168.88.15.53186 > 192.168.88.100.80: флаги [P.], последовательность 1:79, подтверждение 1, окно 58, длина 78
18:21:22.572340 IP 192.168.88.241.1028 > 192.168.88.15.80: флаги [P.], последовательность 1:79, подтверждение 1, окно 58, опции [exp-cfc2], длина 78
18:21:22.572384 IP 192.168.88.15.80 > 192.168.88.241.1028: флаги [.], подтверждение 79, окно 58, длина 0
18:21:22.572385 IP 192.168.88.100.80 > 192.168.88.15.53186: флаги [.], подтверждение 79, окно 58, длина 0
18:21:22.572452 IP 192.168.88.15.80 > 192.168.88.241.1028: флаги [P.], последовательность 1:273, подтверждение 79, окно 58, длина 272
18:21:22.572454 IP 192.168.88.100.80 > 192.168.88.15.53186: флаги [P.], последовательность 1:273, подтверждение 79, окно 58, длина 272
18:21:22.572481 IP 192.168.88.15.53186 > 192.168.88.100.80: флаги [.], подтверждение 273, окно 60, длина 0
18:21:22.572482 IP 192.168.88.241.1028 > 192.168.88.15.80: флаги [.], подтверждение 273, окно 60, длина 0
18:21:22.572556 IP 192.168.88.15.53186 > 192.168.88.100.80: флаги [F.], последовательность 79, подтверждение 273, окно 60, длина 0
18:21:22.572557 IP 192.168.88.241.1028 > 192.168.88.15.80: флаги [F.], последовательность 79, подтверждение 273, окно 60, длина 0
18:21:22.572590 IP 192.168.88.15.80 > 192.168.88.241.1028: флаги [F.], последовательность 273, подтверждение 80, окно 58, длина 0
18:21:22.572591 IP 192.168.88.100.80 > 192.168.88.15.53186: флаги [F.], последовательность 273, подтверждение 80, окно 58, длина 0
18:21:22.572619 IP 192.168.88.15.53186 > 192.168.88.100.80: флаги [.], подтверждение 274, окно 60, длина 0
18:21:22.572620 IP 192.168.88.241.1028 > 192.168.88.15.80: флаги [.], подтверждение 274, окно 60, длина 0
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )