दो नेटवर्क वाला कंटेनर गलत गेटवे चुनता है
दो अटैचमेंट, एक डिफ़ॉल्ट रूट, और गलत नेटवर्क हर बार जीतता है। 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 हो। नेटवर्क का स्थायी स्वामित्व Compose में रखें और VPN कॉन्फ़िग को केवल अपनी नीति रखने दें।