Коли контейнер LXC «має IP», але не може пропінгувати шлюз, це не загадка. Це відсутній факт. Помилки мережі в Proxmox рідко бувають тонкими; вони просто розподілені по неймспейсах, бриджах, шарах фаєрвола й одній неправильно зрозумілій галочці.
Це промисловий чекліст для конкретної болі: трафік через veth/tap/bridge не йде. Він написаний, щоб змусити до ясності: де пакет помирає, чому, і яке рішення ви ухвалюєте далі.
Швидкий план діагностики
Якщо ви на чергуванні, вам не потрібна теорія. Потрібен воронка. Це порядок, що зазвичай найшвидше знаходить вузьке місце.
1) Визначте: проблема тільки в контейнері чи й на хості теж?
- Якщо хост може досягти шлюзу й інтернету, а контейнер — ні: підозрюйте бридж, фаєрвол, VLAN, rp_filter, маршрут у контейнері або MTU.
- Якщо хост теж не може: припиніть лізти в LXC. Спершу виправляйте фізичну мережу, маршрути хоста або фаєрвол хоста.
2) Підтвердіть, що veth існує й приєднаний до очікуваного бриджа
- Немає veth на хості: контейнер не стартував коректно, помилка конфігурації або створення veth не вдалося через імена/ліміти.
- veth існує, але не на vmbrX: неправильне ім’я бриджа в конфігу контейнера або є застарілий бридж, що був перейменований.
3) Спочатку перевіряйте L2, потім L3, потім політику
- L2: лінк UP, членство в бриджі, фільтрація VLAN, навчання/форвардинг MAC.
- L3: IP/маска контейнера, маршрут за замовчуванням, ARP/neighbor, маршрути хоста.
- Політика: Proxmox firewall (datacenter/node/CT), nftables/iptables, sysctl (rp_filter, forwarding).
4) Використайте один «відомий хороший» тестовий пакет
- З контейнера: пінгувати IP шлюзу, потім IP бриджа хоста, потім зовнішній IP.
- Якщо пінг шлюзу не проходить — дивіться ARP/neigh і перевірки bridge/VLAN, перш ніж гаяти час на NAT/DNS.
5) Захопіть трафік з обох боків veth
- Захопіть на veth хоста та на vmbrX. Якщо бачите вихідний пакет, але немає вхідного — бридж або правила VLAN скидають пакети.
- Якщо взагалі нічого не бачите на veth хоста — контейнер не відправляв пакет (проблеми з маршрутом, інтерфейс опущений, політика всередині CT).
Цитата, яку варто мати при собі, коли хочеться «просто перезавантажити»: Надія — не стратегія.
— General Gordon R. Sullivan (часто цитують в операційних колах).
Ментальна модель: veth, бриджі та неймспейси (без міфів)
У Proxmox LXC контейнер не отримує «реальний NIC». Він отримує один кінець veth-пари. Інший кінець знаходиться на хості і зазвичай підключений до Linux-бриджу, наприклад vmbr0. Ось і вся хитрість.
Де люди губляться — мережа простягається через:
- Мережевий неймспейс контейнера (його інтерфейси, маршрути, ARP-кеш).
- Грань veth-пари (два інтерфейси, постійно з’єднані «технічною» кабеллю).
- Бридж хоста (поведінка як комутатор: база переадресації, фільтрація VLAN, налаштування STP).
- IP-стек хоста (якщо хост роутить/NAT або застосовується фаєрвол на хості).
- Proxmox firewall (це не магія; це правила, що кінцево потрапляють у netfilter).
- Верхня ланка: комутатор, що йде вгору (VLAN-транки, ліміти MAC, порт-сек’юріті, MTU, LACP особливості).
Tap зазвичай зустрічається з QEMU VM, де tap-пристрої з’єднують VM з бриджем хоста. LXC за замовчуванням використовує veth. Але патерни збоїв часто збігаються: неправильний бридж, невірний VLAN, скид фаєрволом, невідповідність MTU або «інтерфейс UP, але не форвардить».
Найкорисніша спрощена модель:
- veth = віртуальний Ethernet-кабель з двома кінцями. Якщо один кінець UP, інший може бути DOWN. Ставтесь як до реального кабеля.
- bridge = віртуальний комутатор. Якщо ввімкнена фільтрація VLAN, він може поводитися як керований комутатор і тихо скидати кадри.
- namespace = кімната з власною таблицею маршрутів і ARP-кешем. Ви не зможете дебажити кімнату, у яку ніколи не заходили.
Жарт №1 (коротко, по суті): veth-пара схожа на шлюб: якщо одна сторона припиняє говорити, інша все ще вважає, що все «UP».
Цікаві факти й контекст (бо вашому майбутньому я варто це пам’ятати)
- veth-пари з’явилися в Linux задовго до масової популярності контейнерів. Вони починалися як загальний спосіб з’єднати неймспейси та віртуальні комутатори; Docker просто популяризував патерн.
- Linux-бридж у багатьох розгортаннях старший за Open vSwitch. Він старий, стабільний і дуже потужний — особливо після того, як дозріли фільтрація VLAN та netfilter hooks.
- Proxmox firewall не є окремим фаєрвол-апаратом. Він генерує правила netfilter на вузлі. Якщо ви тримаєте свої nftables-правила, ви співавторите політику.
- ARP/neighbor — перша канарка. Якщо контейнер не може дотягнутися до шлюзу, у 80% випадків ARP не вдається через VLAN, бридж або фільтрацію MAC — а не через «проблеми з DNS».
- Reverse path filtering (rp_filter) створений для анти-спуфінгу. Він чудовий, поки ви не використовуєте асиметричну маршрутизацію, політичну маршрутизацію або multi-homing. Тоді він стає тихим шредером трафіку.
- Невідповідності MTU рідко ламають маленькі пінги. Вони ламають реальні навантаження: TLS-хендшейки, завантаження образів контейнерів та все, що спричиняє фрагментацію/збої PMTUD.
- Фільтрація VLAN на Linux-бриджі відносно «новіша» порівняно з класичним мостом. Багато команд вмикають її для гігієни, а потім забувають, що нетегований трафік тепер потребує явного PVID.
- Таблиці conntrack — обмежений ресурс. Коли вони переповнюються або таймаути налаштовані невірно, з’являються «випадкові» збої в підключенні контейнерів — особливо під NAT.
Практичні завдання: команди, виводи, рішення (справжній чекліст)
Нижче — практичні завдання. Кожне відповідає на одне питання і примушує до наступної дії. Виконуйте їх в порядку, поки не знайдете першу неправду.
Завдання 1 — Підтвердіть, що контейнер бачить інтерфейс і IP
cr0x@server:~$ pct exec 101 -- ip -br link
lo UNKNOWN 00:00:00:00:00:00 <LOOPBACK,UP,LOWER_UP>
eth0 UP 2a:7d:1c:4f:9b:12 <BROADCAST,MULTICAST,UP,LOWER_UP>
Що це означає: Якщо eth0 відсутній або DOWN — зупиніться. Це не проблема маршрутизації; це проблема сантехніки інтерфейсу або конфігурації контейнера.
Рішення: Якщо eth0 DOWN — перевірте конфіг контейнера і створення veth на хості (Завдання 5–7). Якщо інтерфейс UP — далі перевіряйте IP/маршрути.
cr0x@server:~$ pct exec 101 -- ip -br addr show dev eth0
eth0 UP 192.0.2.50/24 fe80::287d:1cff:fe4f:9b12/64
Рішення: Немає IPv4, коли ви очікуєте? Виправляйте DHCP/статичну конфігурацію всередині CT (або конфіг Proxmox, якщо використовується ip=dhcp).
Завдання 2 — Перевірте маршрут за замовчуванням всередині контейнера
cr0x@server:~$ pct exec 101 -- ip route
default via 192.0.2.1 dev eth0
192.0.2.0/24 dev eth0 proto kernel scope link src 192.0.2.50
Що це означає: Якщо маршрут за замовчуванням відсутній або вказує на неправильний шлюз — контейнер не може вийти за межі підмережі.
Рішення: Виправте шлюз. Не чіпайте бриджі/фаєрволи, поки L3 всередині CT не стане коректним.
Завдання 3 — Швидкий Ladder пінгів (шлюз → бридж хоста → публічний IP)
cr0x@server:~$ pct exec 101 -- ping -c 2 192.0.2.1
PING 192.0.2.1 (192.0.2.1) 56(84) bytes of data.
64 bytes from 192.0.2.1: icmp_seq=1 ttl=64 time=0.512 ms
64 bytes from 192.0.2.1: icmp_seq=2 ttl=64 time=0.487 ms
--- 192.0.2.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
Рішення: Якщо пінг шлюзу не проходить — йдіть прямо до перевірок ARP/neigh та bridge/VLAN (Завдання 4, 8, 10, 11). Якщо пінг шлюзу працює, а публічний IP ні — ймовірно, проблема в маршрутизації/NAT/фаєрволі вище по ланцюгу.
Завдання 4 — Перевірте стан neighbor (ARP) всередині контейнера
cr0x@server:~$ pct exec 101 -- ip neigh show dev eth0
192.0.2.1 lladdr 00:11:22:33:44:55 REACHABLE
Що це означає: REACHABLE/STALE — нормально. INCOMPLETE означає, що ARP-запити не отримують відповіді (невідповідність VLAN, відкид бриджем, upstream-комутатор або неправильний IP шлюзу).
Рішення: Якщо бачите INCOMPLETE — не чіпайте DNS. Виправляйте L2/L3 суміжність.
Завдання 5 — Знайдіть veth на боці хоста для контейнера
cr0x@server:~$ pct config 101 | grep -E '^net'
net0: name=eth0,bridge=vmbr0,firewall=1,hwaddr=2A:7D:1C:4F:9B:12,ip=192.0.2.50/24,gw=192.0.2.1,type=veth
Рішення: Підтвердіть ім’я бриджа. Якщо воно посилається на vmbr1, а ви очікували vmbr0 — ви знайшли баг.
cr0x@server:~$ ip -br link | grep -E 'veth|vmbr0'
vmbr0 UP 3a:ad:be:ef:01:23 <BROADCAST,MULTICAST,UP,LOWER_UP>
veth101i0 UP fe:9a:1c:0f:3b:7a <BROADCAST,MULTICAST,UP,LOWER_UP>
Що це означає: Proxmox зазвичай іменує veth на хості як veth<ctid>i0. Якщо його немає — мережева частина контейнера не піднялася.
Рішення: Якщо відсутній — перевірте логи старту контейнера та повідомлення ядра (Завдання 14).
Завдання 6 — Підтвердіть, що veth приєднаний до бриджа
cr0x@server:~$ ip link show master vmbr0
7: veth101i0@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master vmbr0 state UP mode DEFAULT group default qlen 1000
link/ether fe:9a:1c:0f:3b:7a brd ff:ff:ff:ff:ff:ff
Рішення: Якщо veth не в списку під vmbr0 — контейнер підключений в нікуди. Виправте призначення бриджа або пересоздайте інтерфейс.
Завдання 7 — Перевірте стан порту бриджа і прапори навчання/флудингу
cr0x@server:~$ bridge link show dev veth101i0
7: veth101i0@if6: <BROADCAST,MULTICAST,UP,LOWER_UP> master vmbr0 state forwarding priority 32 cost 2
Що це означає: Якщо порт у стані blocking або не forwarding — STP або неправильна конфігурація бриджа зупиняють трафік.
Рішення: Якщо порт блокується — перевірте STP та запобігання петель на бриджі та вгору по ланцюгу (Завдання 12).
Завдання 8 — Перевірте тегування/фільтрацію VLAN на бриджі
cr0x@server:~$ bridge vlan show dev veth101i0
port vlan-id
veth101i0 1 PVID Egress Untagged
Що це означає: Для VLAN-aware бриджів порт потребує коректного PVID для нетегованого трафіку або явного членства у VLAN для тегованого трафіку.
Рішення: Якщо ви очікуєте VLAN 20, а бачите тільки VLAN 1 — або встановіть tag=20 в конфіг контейнера, або відкоригуйте правила VLAN на бриджі.
Завдання 9 — Підтвердіть, що конфіг мережі контейнера відповідає вашому наміру щодо VLAN
cr0x@server:~$ pct config 101 | grep -E '^net0'
net0: name=eth0,bridge=vmbr0,firewall=1,tag=20,hwaddr=2A:7D:1C:4F:9B:12,ip=192.0.2.50/24,gw=192.0.2.1,type=veth
Рішення: Якщо ваш комутаторпорт — access VLAN 20 (нетегований), не ставте тег в Proxmox; використайте нетегований режим і встановіть PVID бриджа відповідно. Якщо uplink — trunk, тегування може бути коректним. Узгодьте реальність, а не бажання.
Завдання 10 — Перевірте FDB бриджа (навчання MAC)
cr0x@server:~$ bridge fdb show br vmbr0 | grep -i fe:9a:1c:0f:3b:7a
fe:9a:1c:0f:3b:7a dev veth101i0 master vmbr0 permanent
Що це означає: Якщо MAC-и не навчаються динамічно (або з’являються на неправильному порту), можна отримати дивну поведінку «працює для одного контейнера».
Рішення: Немає ознак MAC контейнера взагалі? Трафік може не входити в бридж (контейнер не емить, фаєрвол скидає або veth down).
Завдання 11 — Перевірте стан Proxmox firewall на всіх трьох рівнях
cr0x@server:~$ pve-firewall status
Status: enabled/running
cr0x@server:~$ cat /etc/pve/firewall/cluster.fw | sed -n '1,120p'
[OPTIONS]
enable: 1
[RULES]
cr0x@server:~$ cat /etc/pve/nodes/$(hostname)/host.fw | sed -n '1,160p'
[OPTIONS]
enable: 1
policy_in: DROP
policy_out: ACCEPT
Що це означає: За замовчуванням DROP на фаєрволі хоста може ламати форвардинг контейнера, якщо ви явно не дозволили трафік бриджа.
Рішення: Якщо ви не повністю розумієте свої політики фаєрвола — тимчасово вимкніть фаєрвол CT для контрольного тесту, але не як постійне «виправлення».
Завдання 12 — Перевірте, чи STP/налаштування бриджа тихо не заважають форвардингу
cr0x@server:~$ cat /etc/network/interfaces | sed -n '1,220p'
auto lo
iface lo inet loopback
auto eno1
iface eno1 inet manual
auto vmbr0
iface vmbr0 inet static
address 192.0.2.10/24
gateway 192.0.2.1
bridge-ports eno1
bridge-stp off
bridge-fd 0
bridge-vlan-aware yes
bridge-vids 2-4094
Рішення: Якщо STP увімкнено, а ви цього не чекаєте, ви можете чекати затримок перед форвардингом або стикнутися з заблокованим портом. Якщо VLAN-aware увімкнено, вам потрібно керувати членством у VLAN свідомо.
Завдання 13 — Підтвердіть sysctl хоста, що впливають на форвардинг і асиметрію
cr0x@server:~$ sysctl net.ipv4.ip_forward net.ipv4.conf.all.rp_filter net.ipv4.conf.vmbr0.rp_filter
net.ipv4.ip_forward = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.vmbr0.rp_filter = 1
Що це означає: Якщо ви робите маршрутизацію/NAT на хості і маєте асиметричні шляхи (декілька uplink, policy routing, VRF), rp_filter=1 може скидати валідний трафік.
Рішення: Якщо підозрюєте rp_filter — протестуйте зі значенням rp_filter=2 (loose) на релевантних інтерфейсах, потім закріпіть з правильними маршрутами. Не лишайте «що-заради-працює», не розуміючи наслідків.
Завдання 14 — Пошукайте підказки в логах ядра: veth, bridge, nf_tables, MTU
cr0x@server:~$ dmesg -T | tail -n 30
[Thu Dec 26 09:14:02 2025] device veth101i0 entered promiscuous mode
[Thu Dec 26 09:14:02 2025] vmbr0: port 7(veth101i0) entered blocking state
[Thu Dec 26 09:14:03 2025] vmbr0: port 7(veth101i0) entered forwarding state
Рішення: Якщо бачите помилки на кшталт «failed to create veth», «RTNETLINK answers: File exists» або попередження про MTU — у вас проблема на рівні хоста: колізії імен, виснаження ресурсів або неправильна послідовність конфігурації.
Завдання 15 — Трасуйте пакети з tcpdump з обох боків
cr0x@server:~$ tcpdump -ni veth101i0 arp or icmp
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on veth101i0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
09:18:10.102938 ARP, Request who-has 192.0.2.1 tell 192.0.2.50, length 28
Рішення: Якщо ARP-запити виходять через veth, але ви ніколи не бачите відповідей — перевірте VLAN і upstream-комутатор. Якщо відповіді з’являються на vmbr0, але не на veth101i0 — щось на хості фільтрує між бриджем і портом (bridge VLAN filtering, ebtables/nft bridge rules, Proxmox firewall).
cr0x@server:~$ tcpdump -ni vmbr0 arp or icmp
listening on vmbr0, link-type EN10MB (Ethernet), snapshot length 262144 bytes
09:18:10.102944 ARP, Request who-has 192.0.2.1 tell 192.0.2.50, length 28
Рішення: Побачити той самий запит на vmbr0 — добре: пакет потрапляє в домен бриджа. Тепер знайдіть, де загинається відповідь.
Завдання 16 — Перевірте, чи nftables/iptables політика не вбиває трафік бриджа
cr0x@server:~$ nft list ruleset | sed -n '1,200p'
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
ct state established,related accept
}
chain forward {
type filter hook forward priority 0; policy drop;
}
}
Що це означає: За замовчуванням DROP на forward зламає маршрутизований/NATed трафік контейнера. Бриджований трафік також може зачепитися в залежності від sysctl і налаштувань bridge netfilter.
Рішення: Якщо ви покладаєтесь на маршрутизацію/NAT хоста — додайте явні allow в forward для підмережі контейнера і вихідного інтерфейсу. Якщо ви суто бриджите — перевірте bridge-nf-call-iptables (Завдання 17).
Завдання 17 — Перевірте bridge netfilter sysctl (мовчазний множник політики)
cr0x@server:~$ sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.bridge.bridge-nf-call-arptables
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-arptables = 0
Що це означає: Якщо увімкнено, бриджовані пакети можуть проходити через iptables/nft hooks. Це може бути корисно (безпека) або катастрофічно (неочікувані скидання).
Рішення: Якщо ви не планували фільтрацію бриджованого трафіку — встановіть ці значення в 0 і покладайтеся на коректні L2/L3 межі — або пишіть правила свідомо.
Завдання 18 — Перевірте MTU на контейнері, veth, бриджі й uplink
cr0x@server:~$ ip -br link show dev veth101i0 vmbr0 eno1
veth101i0 UP fe:9a:1c:0f:3b:7a <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500
vmbr0 UP 3a:ad:be:ef:01:23 <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500
eno1 UP 58:11:22:aa:bb:cc <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9000
Що це означає: Uplink на 9000 і бридж на 1500 не завжди помилка, але це поле для PMTUD-крайнощів, якщо є маршрутизація/NAT.
Рішення: Узгодьте MTU від краю до краю для сегмента або доведіть через захоплення, що фрагментація/ICMP «frag needed» працює.
Завдання 19 — Підтвердіть, що DNS контейнера не є козлом відпущення
cr0x@server:~$ pct exec 101 -- getent hosts example.com
2606:2800:220:1:248:1893:25c8:1946 example.com
93.184.216.34 example.com
Рішення: Якщо пінг шлюзу працює, а DNS ні — виправте резолвери (файл /etc/resolv.conf всередині CT або роботу systemd-resolved). Не переписуйте конфіг бриджа через проблему DNS.
Завдання 20 — Тест локального зв’язку хост → контейнер
cr0x@server:~$ ping -c 2 192.0.2.50
PING 192.0.2.50 (192.0.2.50) 56(84) bytes of data.
64 bytes from 192.0.2.50: icmp_seq=1 ttl=64 time=0.221 ms
64 bytes from 192.0.2.50: icmp_seq=2 ttl=64 time=0.213 ms
--- 192.0.2.50 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
Рішення: Якщо хост не може пропінгувати контейнер, але контейнер може пінгувати бридж хоста — підозрюйте політику фаєрвола на хості або ebtables/nft фільтрацію бриджа.
Поширені помилки: симптом → корінна причина → виправлення
1) «Контейнер має IP, але не може пропінгувати шлюз»
Корінна причина: Невідповідність VLAN або VLAN-aware бридж відкидає нетеговані кадри; іноді upstream порт — access VLAN X, а в Proxmox поставили тег VLAN X (подвійне тегування або неправильне тегування).
Виправлення: Зробіть намір щодо VLAN явним. Якщо uplink — trunk і контейнер має бути в VLAN 20, встановіть tag=20 і переконайтеся, що vmbr0 дозволяє VLAN 20. Якщо uplink — access VLAN 20, не тегуйте в Proxmox; переконайтеся, що PVID порту відповідає.
2) «Працює декілька хвилин, потім падає; перезапуск контейнера допомагає»
Корінна причина: Хаос у таблиці neighbor/ARP через дубльований IP, дубльований MAC (клони контейнера) або upstream MAC limit/порт-сек’юріті, що блокує навчання.
Виправлення: Забезпечте унікальний MAC для кожного CT; не клонуйте й не забувайте виправити. Перевірте політику MAC на комутаторі. Переконайтеся, що ніхто не має дубльований IP у сегменті.
3) «Контейнер може пінгувати IP, але не вирішує імена»
Корінна причина: Неправильний DNS, проблеми systemd-resolved або Proxmox, що інжектує неправильні резолвери. Іноді фаєрвол блокує UDP/53, тоді як ICMP проходить.
Виправлення: Перевірте /etc/resolv.conf всередині CT і запустіть getent hosts. Якщо фаєрвол увімкнено — явно дозволіть DNS.
4) «Працюють тільки великі завантаження; пінги працюють»
Корінна причина: Невідповідність MTU + зламаний PMTUD (ICMP «frag needed» блокується) або взаємодія оверлейних мереж з джамбо-фреймами.
Виправлення: Узгодьте MTU; дозвольте ICMP типу 3 код 4 там, де потрібно; перевірте через tcpdump і великий curl або ping -M do -s тест.
5) «Трафік працює до ввімкнення Proxmox firewall»
Корінна причина: За замовчуванням DROP у політиках node/host/CT без потрібних allow-прав для форвардингу бриджа; або sysctl бриджа змушує бриджований трафік потрапляти під L3 правила несподівано.
Виправлення: Аудит політик на datacenter/node/CT. Вирішіть, де має відбуватися фільтрація. Тримайте bridge-nf sysctls під контролем.
6) «Контейнер може дістатися хоста, але не більше; NAT налаштований (ми думаємо)»
Корінна причина: net.ipv4.ip_forward на хості вимкнено, forward-chain DROP або NAT-правила написані в iptables, тоді як система використовує nftables (або навпаки).
Виправлення: Перевірте sysctl форвардингу, упевніться, що forward chain дозволяє трафік, і що ви пишете правила для активного бекенду фаєрвола.
7) «Після міграції CT на інший вузол мережа зламалась»
Корінна причина: На цільовому вузлі інші імена vmbr, налаштування VLAN-aware, MTU або дефолтні фаєрвол-параметри відрізняються.
Виправлення: Трактуйте мережу вузла як контракт API. Стандартизовуйте /etc/network/interfaces по всіх вузлах і перевіряйте перед міграцією.
Жарт №2 (коротко, по суті): баги VLAN — як блискітки: як з’явились, їх знайдете в місцях, яких навіть не чіпали.
Чеклісти / покроковий план
Чекліст A — «Контейнер не може дістатися шлюзу» (найпоширеніше)
- Всередині CT:
ip -br addrтаip route. Спершу виправте відсутній IP/маршрут. - Всередині CT:
ip neigh. Якщо шлюз вINCOMPLETE— це L2/VLAN/bridgе. - На хості: підтвердіть наявність veth і що він на очікуваному бриджі (
ip -br link,ip link show master vmbr0). - На хості: перевірте членство VLAN (
bridge vlan show). Порівняйте з mode switchport (access vs trunk) та Proxmoxtag=. - Захопіть ARP на veth хоста і vmbr. Якщо запит виходить, а відповіді немає — йдіть вгору по ланцюгу (конфіг комутатора, MAC security, кабелі, проблеми LACP hashing).
Чекліст B — «Шлюз працює, інтернет не працює»
- Пінгуйте публічний IP (не ім’я). Якщо не вдається — це маршрутизація/NAT/фаєрвол, не DNS.
- Підтвердіть, що хост має підключення й правильний маршрут за замовчуванням.
- Якщо використовується маршрутизація/NAT на хості: перевірте
net.ipv4.ip_forward=1, політику forward chain і NAT-правила у відповідному бекенді фаєрвола. - Перевірте rp_filter, якщо є декілька шляхів.
- Лише після відновлення IP-доступності: перевірте DNS.
Чекліст C — «Переривчасті або пов’язані з продуктивністю»
- Перевірте MTU по всій ланці: uplink, бридж, veth, контейнер.
- Перевірте тиск на conntrack (симптоми: випадкові втрати під навантаженням).
- Захопіть і шукайте ретрансляції, ICMP frag-needed або аномалії TCP MSS.
- Аудит правил фаєрвола щодо таймаутів stateful-tracking і неочікуваних скидань.
Три міні-історії з корпоративного життя (щоб ви їх не повторили)
Історія 1 — Інцидент через хибне припущення
У них був «простий» план: перемістити набір legacy-сервісів з VM в LXC, щоб зекономити пам’ять. Мережа була «та сама», бо все йшло через vmbr0. Саме це речення і породжує інциденти.
Перший контейнер піднявся з IP і відповідав на пінги з хоста. Ззовні — мертвий. Команда припустила, що upstream-фаєрвол не любить новий MAC, тож відкривали тікети й чекали. Тим часом сервіси лежали, а канал інциденту робив те, що роблять такі канали: генерував жар, а не дані.
Насправді проблема була у невідповідності VLAN, внесеній через «очевидне» припущення: порт комутатора був access VLAN 30, тому вони поставили tag=30 на контейнер. На цьому порту кадри вже були нетегованими VLAN 30. Контейнер фактично відправляв теговані кадри VLAN 30 в access-порт, які відкидалися. ARP ніколи не завершився. Шлюз — недоступний.
Що погіршило ситуацію: сам хост мав IP на цьому access VLAN і міг дістатися шлюзу, тож «хост працює» став доказом, що контейнер теж має працювати. Але хост був нетегований; контейнер — тегований. Різна реальність, той самий кабель.
Фікс був нудний: прибрали тег, залишили контейнер нетегованим і задокументували режим порту комутатора в стандарті мережі кластера. Після цього додали pre-flight тест: виконувати bridge vlan show і порівнювати з конфігом портів перед міграцією.
Історія 2 — Оптимізація, що відбилася боком
Інша організація пишалася своєю безпековою позицією. Вони всюди вмикнули Proxmox firewall, встановили політики за замовчуванням в DROP і розгорнули зміни в вікні змін, яке виглядало щедрим на календарі. Воно не було щедрим у реальному житті.
Збої в підключенні не були тотальними. Деякі контейнери могли спілкуватися з базою; інші — ні. DNS іноді працював. ICMP був непостійним. Це той тип помилки, що змушує людей сумніватися в фізиці.
«Оптимізація» полягала в увімкненні bridge netfilter hooks, бо вони хотіли фільтрувати трафік «навіть якщо він бриджований». Вони вмикнули net.bridge.bridge-nf-call-iptables=1 і застосували набір L3-прав, що припускав маршрутизований трафік. Раптом бриджовані кадри підпали під forward chain із політикою DROP. Деякі потоки виживали через state tracking; нові — ні. Це виглядало випадковим через поєднання стейтфул-політики і топології, для якої вона не була призначена.
Найшвидший шлях назовні був такий: визначитися, де фільтрувати — на L3 або на L2/бриджі — але не випадково обидва одночасно. Вони відключили bridge netfilter на вузлах, де дизайн був чисто бриджевий, залишили Proxmox firewall для management-інтерфейсів і перенесли east-west контроль туди, де топологія була зрозуміла.
Після інциденту найкраща зміна була не технічною. Вона була процедурною: будь-яка зміна фаєрвола вимагала запускати «відомий хороший» контейнер із фіксованим набором тестів (ping шлюзу, resolve DNS, TCP connect) перед розгортанням далі.
Історія 3 — Нудна, але правильна практика, що врятувала день
Фінансова компанія (та, що трактує даунтайм як подію кар’єри) мала стандарт кластера, що дратував інженерів: кожен вузол мав однакові імена бриджів, налаштування VLAN-aware і MTU. Без винятків. Якщо вузлу потрібна була спеціальна обробка — у нього був окремий кластер.
Під час оновлення обладнання вони весь день мігрували контейнери вузол-вузол. Одна міграція провалилася: контейнер втратив зовнішню підключеність негайно після старту на новому вузлі. Інженер на чергуванні не фантазував. Він пройшов стандартний чекліст: підтвердив наявність veth, перевірив членство в бриджі, VLAN-членство, tcpdump ARP з обох боків.
За кілька хвилин вони побачили ARP-запити, що виходять з veth, але ніколи не з’являються на фізичному uplink. Це звузило коло до бридж/uplink сантехніки, а не до контейнера. Далі ip link show master vmbr0 показав, що veth на vmbr0, але vmbr0 не був прикріплений до NIC, який вони очікували. Ім’я інтерфейсу змінилося через оновлення firmware/BIOS і predictable network interface naming, що зробило свою «обіцяну» передбачуваність, тільки не в той бік, який чекали.
Оскільки у них була конфігурація як код, вони перепроєктували мережевий конфіг вузла з правильним ім’ям NIC і все знову запрацювало. Ніяких сніжинок у конфігурації, ніяких «можливо перезавантажити». Практика, що їх врятувала, була нудна: стандартизація і трактування мережевої конфігурації вузла як production-коду.
FAQ
1) Proxmox LXC використовує tap чи veth-пристрої?
Зазвичай veth для LXC. Tap зазвичай для QEMU VM. Схеми усунення несправностей перетинаються: членство в бриджі, VLAN, фаєрвол і MTU.
2) Як знайти, який veth належить якому контейнеру?
Почніть з pct config <ctid> для MAC/бриджа. Потім перелічіть ip -br link | grep veth. Імена зазвичай виглядають як veth<ctid>i0.
3) Мій контейнер може пінгувати хост, але не шлюз. Що це означає?
Ймовірно, у вас локальна бриджова зв’язність, але зламане upstream L2/L3 суміжність: невідповідність VLAN, безпека порту комутатора або неправильне тегування/PVID.
4) Увімкнення Proxmox firewall автоматично блокує контейнери?
Може, залежно від політик за замовчуванням і наборів правил на рівнях datacenter/node/CT. Також слід слідкувати за bridge netfilter sysctl; вони можуть змусити бриджований трафік пройти через L3-правила несподівано.
5) Який найшвидший спосіб довести, що це пов’язано з VLAN?
Перевірте bridge vlan show dev vethXYZ і порівняйте з tag= контейнера та режимом порту upstream-комутатора. Потім захопіть ARP на vmbr і uplink.
6) Чому пінги працюють, а HTTPS — ні?
Класична проблема MTU/PMTUD або TCP MSS. ICMP echo маленький; TLS-хендшейк і передача даних — ні. Перевірте MTU і шукайте ICMP «frag needed».
7) Коли підозрювати rp_filter?
Коли у вас декілька uplink, policy routing, VRF або асиметричні шляхи повернення. Якщо трафік зникає без явного скидання фаєрволом — rp_filter у списку підозрюваних.
8) Чи можу я «виправити» це, переходячи з бриджевого режиму на маршрутизований/NAT?
Можна, але це не виправлення — це зміна дизайну. Якщо ви обираєте маршрутизацію/NAT, ви маєте контролювати sysctl форвардингу, політику forward chain і NAT-правила. Робіть це свідомо.
9) Контейнери втрачають мережу після live migration або відновлення. Чому?
Дріфт конфігів вузлів: різні імена бриджів, VLAN-aware налаштування, дефолтні фаєрвол-параметри або MTU. Стандартизуйте мережу вузлів і перевіряйте перед міграціями.
Наступні кроки (що змінити після виправлення)
Коли ви знайшли причину — не зупиняйтесь на «воно працює». Продакшн-системи деградують, бо фундаментальна невизначеність лишається.
- Стандартизуйте мережу вузлів. Ті самі імена vmbr, ті самі налаштування VLAN-aware, той самий MTU. Трактуйте це як контракт API для навантажень.
- Документуйте намір щодо VLAN в одному місці. Для кожного бриджа/uplink: trunk чи access, дозволені VLAN-и і чи мають контейнери ставити теги.
- Робіть фаєрволінг обдумано. Вирішіть, чи фільтруєте бриджований трафік. Якщо так — пишіть правила з урахуванням топології. Якщо ні — відключіть bridge netfilter hooks.
- Тримайте «відомий хороший» тестовий контейнер. Маленький CT, що може пропінгувати шлюз, вирішувати DNS і конектитися по TCP. Проганяйте його після будь-якої зміни мережі/фаєрвола.
- Культура «capture-first». Коли сумніваєтесь — tcpdump з обох боків veth і на бриджі. Якщо ви не бачите пакет — ви сперечаєтесь з примарою.