جنبه های شبکه سازی اجرای ماشین های مجازی در کانتینرها « وبلاگ ipSpace.net

را vrnetlab پروژه و او آزمایشگاه کانتینری فورک ایده فوقالعادهای را پیادهسازی میکند: بیایید ماشینهای مجازی (عموماً دستگاههای شبکهای که نمیتوانند کانتینری شوند) را بهعنوان کانتینر بستهبندی کنیم تا از ابزارهای ارکستراسیون قابل اعتماد استفاده کنیم. آزمایشگاه کانتینری برای ارائه توپولوژی های شبکه
این رویکرد می تواند چندین اشکال داشته باشد (بسته به نحوه ساخت تصاویر کانتینر)، اما فیل آشکار در اتاق این است: چگونه شبکه مجازی را فعال کنیم?
اگر می خواهید ماشین های مجازی را در کانتینرها اجرا کنید، به نرم افزار مجازی سازی (QEMU) نیاز دارید که در داخل کانتینر اجرا شود، و این vrnetlabظروف مبتنی بر دارند. همانطور که ممکن است از پست های وبلاگ در مورد اتصالات آزمایشگاه مجازی و اتصالات نقطه به نقطه آزمایشگاه مجازی به خاطر بیاورید، QEMU ارائه می دهد شبیه سازی کارت رابط شبکه مجازی و فریم های اترنت را بین بافرهای ورودی/خروجی این کارت شبکه مجازی (که در نمودار N مشخص شده است) و لینوکس “خارجی” به هم می زند. لمس کنید رابطی که می تواند به هر رابط دیگری (معمولاً یک پل لینوکس) متصل شود:
دستگاه های شبکه ای که در آزمایشگاه های مجازی کار می کنند معمولا دارای یک مدیریت رابط (امیدوارم در یک VRF مدیریتی) و رابط های صفحه داده صفر یا بیشتر. فرض کنید یک ماشین مجازی با یک رابط مدیریت (نارنجی) و یک رابط صفحه داده واحد (قهوه ای) داریم:

از سوی دیگر، ما (از همان پستهای وبلاگ) میدانیم که کانتینرهای شبکه از جفتهای vEth (کابلهای مجازی برای اتصال فرستندهها و NICهای متصل به آنها) برای برقراری ارتباط بین دو فضای نام شبکه استفاده میکنند. یک کانتینر با یک رابط صفحه مدیریت و داده، بخش “داخلی” دو جفت vEth متصل به پشته شبکه خواهد داشت:

حال برای اصل پست وبلاگ امروز: چگونه این دو را به هم متصل می کنید؟ رابط کانتینر صفحه داده یک رابط لایه 2 (بدون آدرس IP) است، بنابراین می توانید فقط (با استفاده از tc) در لمس کنید رابط و قسمت داخلی جفت vEth و شما فریم هایی را دریافت خواهید کرد که بین انتهای خارجی جفت vEth از انتهای داخلی جفت vEth، رابط tap و شبیه سازی QEMU vNIC به بافرهای VM vNIC I/O عبور می کنند. سپس VM میتواند هر آدرس IP را که میخواهد به vNIC خود اختصاص دهد و اتصال مستقیم به سایر اشیاء متصل به همان میزبان پل لینوکس (یا هر انتهای خارجی جفت vEth که به آن متصل است) را تجربه میکند.

ما نمی توانیم از همان ترفند با رابط کنترل استفاده کنیم. در زمان شروع کانتینر، سیستم ارکستراسیون (آزمایشگاه کانتینری یا داکر/تقلب) قبلاً آدرس IP خود را پیکربندی کرده است (جزئیات بیشتر در یک پست وبلاگ دیگر). اصل vrnetlab کد (از 2018) یک آدرس IP ثابت (10.0.0.15) را در رابط مدیریت VM پیکربندی کنید و از آن استفاده کنید. اجتماعی به عنوان یک پروکسی TCP برای ارسال ترافیک SSH (و دوستانش) بین IP مدیریت کانتینر و IP مدیریت VM.

در سال 2024، پراکسی اختصاصی TCP با حمل و نقل پورت QEMU داخلی (که از سال 2007 در اطراف معلق بود و بی سر و صدا نادیده گرفته شده بود) و در دسامبر 2024 جایگزین شد. آزمایشگاه کانتینری vrnetlab فورک یک رابط مدیریت شفاف با آزمایشگاه کانتینری پشتیبانی در نسخه 0.62 (ژانویه 2025) ارائه می شود. این تابع آدرس IP را که Docker به اولین رابط کانتینر اختصاص می دهد کپی می کند (eth0) به اولین رابط VM (رابط مدیریت). از آنجایی که هر دو رابط (کانتینر و رابط مدیریت VM) آدرس IP یکسانی دارند، ما به هک های اضافی (قوی تر) نیاز داریم tc چسب) تا کار کند.
بیش از یک سال طول کشید تا متوجه این تغییر شویم (ما خیلی خوب بودیم vrnetlab ماشین های مجازی که دارای هر آدرس IP مدیریتی هستند تا زمانی که در یک VRF مدیریتی ایزوله شده باشند. netlab شروع به استفاده از رابط مدیریت شفاف در نسخه 26.08 کرد.
مشتاق جزئیات بیشتر هستید؟
آنجاست اتصال ip از ظرفی که دارای یک OpenBSD VM است تخلیه کنید. می توانید دو نقطه پایانی جفت های vEth را ببینید (eth0@if91، کجا if91 سر دیگر «کابل» است و eth1@if93) و آویزان کردن tap1 رابط کاربری
root@dut:/# ip link
1: lo: mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: tap1: mtu 65000 qdisc fq_codel state UNKNOWN mode DEFAULT group default qlen 1000
link/ether a2:9f:be:ff:9f:0a brd ff:ff:ff:ff:ff:ff
90: eth0@if91: mtu 1500 qdisc noqueue state UP mode DEFAULT group default
link/ether 02:42:c0:a8:79:65 brd ff:ff:ff:ff:ff:ff link-netnsid 0
92: eth1@if93: mtu 9500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
link/ether aa:c1:ab:dd:e1:e6 brd ff:ff:ff:ff:ff:ff link-netnsid 1
altname clab-o-dcb4597617d6fdf9
اینها فرآیندهایی هستند که در این ظرف اجرا می شوند. یک اسکریپت پایتون وجود دارد که کد را برای شروع کانتینر اجرا می کند (the اولیه پردازش بنابراین نمی تواند خارج شود)، و قوم فرآیند اجرای شبیه سازی VM:
root@dut:/# ps -ef
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 09:04 pts/0 00:00:00 python3 /launch.py --username admin --password admin --hostname dut --connection
root 14 1 53 09:04 pts/0 00:01:20 qemu-system-x86_64 -enable-kvm -display none -machine pc -monitor tcp:0.0.0.0:40
root 47 0 0 09:05 pts/1 00:00:00 bash
root 67 47 0 09:06 pts/1 00:00:00 ps -ef
شما می خواهید کل خط فرمان را ببینید قوم فرآیند؟ آنجاست؛ میتوانید تنظیمات ارسال میزبان برای دستهای از پورتها را در اولین NIC ببینید (برای جزئیات به سمت راست بروید) و نگاشت شیر آب 1 دستگاه در VM NIC.
root@dut:/# ps -p 14 -o args|cat
COMMAND
qemu-system-x86_64 -enable-kvm -display none -machine pc
-monitor tcp:0.0.0.0:4000,server,nowait
-serial telnet:0.0.0.0:5000,server,nowait -m 512
-cpu host -smp 1
-drive if=ide,file=/openbsd-min_v7.7_2025-04-28-11-38-overlay.qcow2
-cdrom /cloud_init.iso
-device pci-bridge,chassis_nr=1,id=pci.1
-device virtio-net-pci,netdev=p00,mac=0C:00:fe:e9:cf:00,bus=pci.1
-netdev user,id=p00,net=10.0.0.0/24,host=10.0.0.2,dns=10.0.0.3,dhcpstart=10.0.0.15,hostfwd=tcp:0.0.0.0:22-10.0.0.15:22,hostfwd=udp:0.0.0.0:161-10.0.0.15:161,hostfwd=tcp:0.0.0.0:80-10.0.0.15:80,hostfwd=tcp:0.0.0.0:443-10.0.0.15:443,hostfwd=tcp:0.0.0.0:830-10.0.0.15:830,hostfwd=tcp:0.0.0.0:6030-10.0.0.15:6030,hostfwd=tcp:0.0.0.0:8080-10.0.0.15:8080,hostfwd=tcp:0.0.0.0:9339-10.0.0.15:9339,hostfwd=tcp:0.0.0.0:32767-10.0.0.15:32767,hostfwd=tcp:0.0.0.0:50051-10.0.0.15:50051,hostfwd=tcp:0.0.0.0:57400-10.0.0.15:57400,tftp=/tftpboot -device virtio-net-pci,netdev=p01,mac=0C:00:e8:0e:01:01,bus=pci.1,addr=0x2
-netdev tap,id=p01,ifname=tap1,script=/etc/tc-tap-ifup,downscript=no
چطور؟ tc چسب بین eth1 و tap1? اینجاست:
root@dut:/# tc filter show dev eth1 ingress
filter protocol all pref 49152 flower chain 0
filter protocol all pref 49152 flower chain 0 handle 0x1
not_in_hw
action order 1: mirred (Egress Redirect to device tap1) stolen
index 1 ref 1 bind 1
root@dut:/# tc filter show dev tap1 ingress
filter protocol all pref 49152 flower chain 0
filter protocol all pref 49152 flower chain 0 handle 0x1
not_in_hw
action order 1: mirred (Egress Redirect to device eth1) stolen
index 2 ref 1 bind 1
هک مدیریت گذر
و بالاخره چطوره انتقال مدیریت برآورده شد؟ آنجاست vrnetlab اسکریپت کانتینری که راه اندازی می شود tc قوانین بین eth0 (رابط مدیریت کانتینر) و شیر آب 0 (که به NIC مدیریت VM متصل می شود):
#!/bin/bash
ip link set tap0 up
ip link set tap0 mtu 65000
# disable IPv6 to avoid sending periodic traffic like router solicitations from the vrnetlab container
ip -6 addr flush $TAP_IF
# create tc ethtap redirect rules
tc qdisc add dev eth0 clsact
# exception for TCP ports 5000-5007
tc filter add dev eth0 ingress prio 1 protocol ip flower ip_proto tcp dst_port 5000-5007 action pass
# mirror ARP traffic to container
tc filter add dev eth0 ingress prio 2 protocol arp flower action mirred egress mirror dev tap0
# redirect rest of ingress traffic of eth0 to egress of tap0
tc filter add dev eth0 ingress prio 3 flower action mirred egress redirect dev tap0
tc qdisc add dev tap0 clsact
# redirect all ingress traffic of tap0 to egress of eth0
tc filter add dev tap0 ingress flower action mirred egress redirect dev eth0
# clone management MAC of the VM
ip link set dev eth0 address 0C:00:5d:18:38:00
این کاملا واضح است:
- IPv6 در رابط کانتینر غیرفعال است تا از تداخل پشته IPv6 کانتینر جلوگیری شود (پشته IPv4 تا زمانی که از شما خواسته نشود بی صدا است).
- پورت های TCP 5000-5007 توسط پشته TCP کانتینر پذیرفته می شوند.
- تمام ترافیک های دیگر (به ویژه ARP) توسط منعکس می شود
eth0بهtap0. همه چیز منعکس شده استtap0بهeth0. - در نهایت، فقط برای اینکه مطمئن شویم ورودیهای ARP تکراری یا آدرسهای MAC دریافت نمیکنیم، و برای اینکه پشته IP کانتینر روی پورتهای TCP 5000-5007 در حال اجرا باشد، زمانی که ماشین مجازی شروع به ارسال ARPهای رایگان کرد، آدرس MAC ماشین مجازی (همانطور که توسط فرآیند راهاندازی پایتون تنظیم شده و به پارامتر QEMU به عنوان یک Copi ارسال میشود) است.
eth0آدرس



