দুই নেটওয়ার্কের কন্টেইনার ভুল গেটওয়ে বেছে নেয়
দুটি সংযোগ, একটি ডিফল্ট রুট, আর ভুল নেটওয়ার্কই বারবার জিতে থাকে। Compose gw_priority দিয়ে প্রস্থানটি পিন করুন এবং কন্টেইনারের ভেতর থেকেই যাচাই করুন।
আপনার কন্টেইনার এখনও তার কন্ট্রোল ব্রিজে উত্তর দেয়, তবু প্রতিটি আউটবাউন্ড প্যাকেট অফিস macvlan দিয়ে বেরোয়। কিছুই ব্যর্থ হয়নি। দুটি সংযোগের প্রত্যেকটি নিজের গেটওয়ে দেয়, আর একমাত্র ডিফল্ট রুটটি গেছে যে নেটওয়ার্ক আপনি চাননি সেদিকে, তাই সেবা চলতে থাকে অথচ তার ট্রাফিক দীর্ঘ পথ নেয়। কেউ যখন খেয়াল করে, তখন প্রমাণ হয় একটি রাউটিং টেবিল, কোনো ত্রুটি বার্তা নয়।
সাধারণ ব্যাখ্যা হলো Docker নেটওয়ার্কটি দৈবক্রমে বেছেছে। বাস্তবে পুরোনো সিদ্ধান্তটি সংযুক্ত নেটওয়ার্ক নামের বর্ণানুক্রমিক ক্রম অনুসরণ করত, যা রাউটিংকে একটি লেবেলের পার্শ্বপ্রতিক্রিয়ায় পরিণত করত। gw_priority সেটিকে বদলে দেয় আপনার ইচ্ছাকৃতভাবে বাছা একটি সংখ্যা দিয়ে, আর লেআউট লিখে ফেলার পর এটি গ্রহণে প্রায় এক মিনিট লাগে।
কেন ডিফল্ট রুট ভুল নেটওয়ার্কে গিয়ে পড়ে
কোনো সেবা যে নেটওয়ার্কে যোগ দেয়, তার প্রত্যেকটি নিজের গেটওয়ে দিতে পারে, তবু কন্টেইনার ঠিক একটি ডিফল্ট রুট নিয়েই শেষ হয়। Compose 2.33.1-এর আগে সমতা নেটওয়ার্ক নামগুলো সাজিয়ে মেটানো হতো, তাই control-এর মতো একটি লেবেল office-এর আগে এলে সেটাই ঠিক করত ট্রাফিক কোথায় যাবে। কন্টেইনারের ভেতরে কিছুই লিখে রাখে না যে সিদ্ধান্তটি ছিল খেয়ালখুশি, তাই এটি কোড রিভিউ পার হয় এবং পরে একটি অদ্ভুত পথ হিসেবে প্রকাশ পায়। compose ফাইলে নীতি রাখাই এই বেছে নেওয়াকে পরীক্ষাযোগ্য করার একমাত্র উপায়।
সত্যিই দুটি জিনিস ঠিক করে কোন নেটওয়ার্ক জিতবে: আপনি যে gw_priority মান নির্ধারণ করেন, এবং আদৌ কোন নেটওয়ার্কগুলো সংযুক্ত। তৃতীয় একটি নেটওয়ার্ক যোগ করলে প্রার্থীর সংখ্যা বাড়ে; macvlan তুলে নিলে ব্রিজের সঙ্গে প্রতিদ্বন্দ্বিতা করার কিছুই থাকে না। দুটির কোনোটিই অ্যাপ্লিকেশন লগে দেখা যায় না, কারণ ভুল ডিফল্ট রুট খুব কমই সংযোগ সরাসরি ভেঙে দেয়। এটি শুধু প্রতিক্রিয়াগুলো এমন ঠিকানা থেকে আসায় যেটি অপর পক্ষ হয়তো আশা করে না।
gw_priority দিয়ে গেটওয়ে পিন করুন
Compose 2.33.1 সংস্করণ থেকে প্রতিটি সেবা-থেকে-নেটওয়ার্ক সংযোগে gw_priority প্রকাশ করে, আর সবচেয়ে বড় সংখ্যাই জেতে। প্রতি সেবার জন্য আলাদা গেটওয়ে চাবি নেই, তাই মানটি থাকে সেবার networks ব্লকের অধীনে। নিচের উদাহরণটি ডিফল্ট control-কে দেয়, আর office তার সরাসরি সংযুক্ত LAN-এর জন্য পৌঁছানোযোগ্য থাকে।
services:
vpn:
networks:
control:
gw_priority: 1
office:
gw_priority: 0
networks:
control:
driver: bridge
ipam:
config:
- subnet: 172.30.50.0/24
office:
driver: macvlan
driver_opts:
parent: eno1.120
macvlan_mode: bridge
ipam:
config:
- subnet: 192.168.120.0/24
ip_range: 192.168.120.192/27
gateway: 192.168.120.1
ব্লকটিকে দুটি আলাদা নিয়ন্ত্রণ হিসেবে পড়ুন: gw_priority ডিফল্ট রুট ঠিক করে, আর ipam অংশটি অ্যাড্রেসিং ঠিক করে। শুধু subnet বদলালে প্রস্থান নির্বাচন অটুট থাকে, আর এটাই এই সমাধান অর্ধেক প্রয়োগ হওয়ার সবচেয়ে সাধারণ উপায়। প্রায়োরিটিগুলো যে নেটওয়ার্ক তারা নিয়ন্ত্রণ করে তার পাশেই রাখুন, যাতে পরের পাঠককে সিদ্ধান্তটি খুঁজে বেড়াতে না হয়।
gw_priority-কে পাশের সাধারণ priority বৈশিষ্ট্যের সঙ্গে গুলিয়ে ফেলবেন না। সেটি সংযোগ তৈরির ক্রম ঠিক করে এবং রাউটিং নিয়ে কিছুই বলে না, তাই এটি ডিফল্ট গেটওয়ে বাছতে পারে না এবং ইন্টারফেসের নাম ঠিক করে না। কেউ যদি ট্রাফিক ঘোরাতে priority বাড়ানোর পরামর্শ দেন, তবে পরামর্শটি ভুল, এমনকি ফলাফল ক্রমটি দৈবক্রমে ঠিক মনে হলেও।
কোন নেটওয়ার্ক সত্যিই ডিফল্ট রুট বহন করে তা যাচাই করুন
চলমান কন্টেইনারের ভেতরে যাচাই করুন, কারণ হোস্টের রুট টেবিল হোস্টের কথা বলে, সেবাটি যে নেমস্পেস ব্যবহার করে তার নয়। আগে কনফিগ যাচাই চালান যাতে বানান ভুল রিস্টার্টের আগেই ধরা পড়ে, তারপর কন্টেইনার যে রুটটি সত্যিই বসিয়েছে তা পড়ুন।
docker compose config --quiet
docker exec vpn ip -4 route show default
docker exec vpn cat /proc/net/route
সঠিক ফলাফলে ব্রিজ ডিভাইস ও 172.30.50.1-এর নাম থাকে; ভুল ফলাফলে থাকে 192.168.120.1 আর macvlan ডিভাইস। ইমেজে iproute2 প্যাকেজ না থাকলেও /proc ফাইল ডিফল্ট রুট জানায়, গন্তব্য 00000000 এবং গেটওয়ে বাইট উল্টো করে। ডিভাইসের নাম অস্পষ্ট হলে ইন্টারফেস কলামটি docker inspect-এর সঙ্গে মিলিয়ে দেখুন।
Macvlan একটি ভৌত পোর্ট, ব্রিজের ক্লোন নয়
Macvlan কন্টেইনারকে তারে দ্বিতীয় পরিচয় দেয়, আর ঠিক এটাই স্থানীয় ডিভাইসে প্রবেশ কাজ করায়। এর মানে এইও যে সুইচ পোর্ট ও হাইপারভাইজারকে অতিরিক্ত একটি MAC ঠিকানা মেনে নিতে হবে, আর অনেক ক্লাউড নেটওয়ার্ক চুপচাপ তা অস্বীকার করে। ফ্লিট পরিকল্পনার আগে একটি কন্টেইনার পরীক্ষা করুন, কারণ প্রত্যাখ্যাত MAC সাধারণত এমন লিংক হিসেবে দেখা যায় যা আপ আছে কিন্তু কিছুই পার করছে না।
macvlan_mode: bridge সেটিংটি macvlan ড্রাইভারের একটি মোড, Docker-এর সফটওয়্যার ব্রিজ নয়, আর passthru ডিফল্ট নয় বরং আলাদা বিশেষায়িত মোড। Linux আরও বাধা দেয় macvlan কন্টেইনারকে নিজের হোস্টে পৌঁছাতে একই প্যারেন্টের মধ্য দিয়ে, আর এজন্যই কন্ট্রোল ব্রিজটি রাখা হয়, একটি সংযোগ দুটি কাজ করবে বলে আশা না করে।
Compose দেখার আগেই VLAN প্যারেন্টের নাম দিন
Docker eno1.120-এর মতো বিন্দুযুক্ত প্যারেন্টকে 802.1Q সাব-ইন্টারফেস হিসেবে ধরে এবং VLAN ডিভাইসটি নিজেই তৈরি করে। এই সুবিধার সীমা আছে: উদ্ভূত নামটি ভৌত ইন্টারফেসের নামের উপর নির্ভর করে, আর লম্বা নাম ফলাফলকে আশপাশের টুলের প্রত্যাশার বাইরে ঠেলে দিতে পারে। হোস্টের নেটওয়ার্ক কনফিগে নামযুক্ত VLAN ইন্টারফেস তৈরি করে parent-কে তার দিকে দেখালে দুই প্রান্তই পূর্বানুমেয় থাকে।
মনে রাখুন networks-এর অধীনের চাবিটি Compose নাম, Linux ডিভাইস নয়। হোস্টে office নামের ইন্টারফেস খুঁজলে ব্যর্থ হবে, কারণ কার্নেল কেবল প্যারেন্ট ইন্টারফেস আর কন্টেইনারের পেছনের veth জোড়া দেখে।
উপরে VPN-এর জন্য জায়গা করুন
VPN ক্লায়েন্ট এই নেটওয়ার্কগুলো তৈরির পরে সংযুক্ত হয়, তাই gw_priority নির্বিশেষে আরও নির্দিষ্ট রুট, নীতি নিয়ম ও ফিল্টার যোগ করতে পারে। দুই স্থানীয় subnet-এর বিপরীতে দূরবর্তী প্রিফিক্স পরিকল্পনা করুন, কন্ট্রোল পথের প্রয়োজনীয় প্রতিক্রিয়াসহ। দূরবর্তী প্রিফিক্স অফিস LAN-এর সঙ্গে ওভারল্যাপ করলে ঠিকানা পরিকল্পনা ঠিক করুন, টানেল থেকে গোটা প্রাইভেট রেঞ্জ ছিঁড়ে ফেলবেন না।
VPN চালু হওয়ার পরে এবং আবার সংযুক্ত হওয়ার পরেও ঠিকানা, রুট ও সেবার পথ আবার যাচাই করুন, কারণ পুনঃসংযোগেই হাতে যোগ করা রুট হারিয়ে যায়। প্রথম পরীক্ষার আগেই প্রত্যাশিত টেবিলটি লিখে রাখুন, যাতে পরে তুলনাটি স্মৃতিচর্চা নয় বরং একটি diff হয়। কনফিগে নেটওয়ার্কের স্থায়ী মালিকানা রাখুন এবং VPN কনফিগ কেবল নিজের নীতির মালিক থাকুক।