การปรับแต่งเส้นทางอย่างละเอียดสำหรับ MetalLB ในโหมด L2

การปรับแต่งเส้นทางอย่างละเอียดสำหรับ MetalLB ในโหมด L2
ไม่นานมานี้ ฉันต้องเผชิญกับงานที่ผิดปกติอย่างมากในการตั้งค่าการกำหนดเส้นทางสำหรับ MetalLB ทุกอย่างคงจะดีเพราะ... โดยปกติแล้ว MetalLB ไม่ต้องการการดำเนินการใดๆ เพิ่มเติม แต่ในกรณีของเรา เรามีคลัสเตอร์ที่ค่อนข้างใหญ่และมีการกำหนดค่าเครือข่ายที่ง่ายมาก

ในบทความนี้ ฉันจะบอกวิธีกำหนดค่าการกำหนดเส้นทางตามแหล่งที่มาและตามนโยบายสำหรับเครือข่ายภายนอกของคลัสเตอร์ของคุณ

ฉันจะไม่ลงรายละเอียดเกี่ยวกับการติดตั้งและกำหนดค่า MetalLB เนื่องจากฉันคิดว่าคุณมีประสบการณ์มาบ้างแล้ว ฉันแนะนำให้ตรงไปตรงประเด็นคือการตั้งค่าเส้นทาง ดังนั้นเราจึงมีสี่กรณี:

กรณีที่ 1: เมื่อไม่จำเป็นต้องกำหนดค่าใดๆ

ลองดูกรณีง่ายๆ

การปรับแต่งเส้นทางอย่างละเอียดสำหรับ MetalLB ในโหมด L2

ไม่จำเป็นต้องมีการกำหนดค่าการกำหนดเส้นทางเพิ่มเติมเมื่อที่อยู่ที่ออกโดย MetalLB อยู่ในเครือข่ายย่อยเดียวกันกับที่อยู่ของโหนดของคุณ

ตัวอย่างเช่น คุณมีซับเน็ต 192.168.1.0/24มันมีเราเตอร์ 192.168.1.1และโหนดของคุณได้รับที่อยู่: 192.168.1.10-30จากนั้นสำหรับ MetalLB คุณสามารถปรับช่วงได้ 192.168.1.100-120 และตรวจสอบให้แน่ใจว่าจะทำงานโดยไม่มีการกำหนดค่าเพิ่มเติม

ทำไมเป็นอย่างนั้น? เนื่องจากโหนดของคุณมีเส้นทางที่กำหนดค่าไว้แล้ว:

# ip route
default via 192.168.1.1 dev eth0 onlink 
192.168.1.0/24 dev eth0 proto kernel scope link src 192.168.1.10

และที่อยู่จากช่วงเดียวกันจะถูกนำมาใช้ซ้ำโดยไม่ต้องดำเนินการใดๆ เพิ่มเติม

กรณีที่ 2: เมื่อจำเป็นต้องปรับแต่งเพิ่มเติม

การปรับแต่งเส้นทางอย่างละเอียดสำหรับ MetalLB ในโหมด L2

คุณควรกำหนดค่าเส้นทางเพิ่มเติมทุกครั้งที่โหนดของคุณไม่มีที่อยู่ IP ที่กำหนดค่าไว้ หรือกำหนดเส้นทางไปยังเครือข่ายย่อยที่ MetalLB ออกที่อยู่

ฉันจะอธิบายรายละเอียดเพิ่มเติมเล็กน้อย เมื่อใดก็ตามที่ MetalLB ส่งออกที่อยู่ ก็สามารถเปรียบเทียบได้กับการมอบหมายง่ายๆ เช่น:

ip addr add 10.9.8.7/32 dev lo

ให้ความสนใจกับ:

  • a) ที่อยู่ถูกกำหนดด้วยคำนำหน้า /32 นั่นคือเส้นทางจะไม่ถูกเพิ่มลงในเครือข่ายย่อยโดยอัตโนมัติ (เป็นเพียงที่อยู่)
  • b) ที่อยู่จะแนบไปกับอินเทอร์เฟซของโหนดใดๆ (เช่น ลูปแบ็ค) เป็นมูลค่าการกล่าวขวัญถึงคุณสมบัติของสแต็กเครือข่าย Linux ที่นี่ ไม่ว่าคุณจะเพิ่มที่อยู่ให้กับอินเทอร์เฟซใด เคอร์เนลจะประมวลผลคำขอ arp และส่งการตอบสนอง arp ไปยังคำขอใด ๆ เสมอ ลักษณะการทำงานนี้ถือว่าถูกต้องและยิ่งไปกว่านั้นยังใช้กันอย่างแพร่หลายในสภาพแวดล้อมแบบไดนามิกเช่น Kubernetes

พฤติกรรมนี้สามารถปรับแต่งได้ เช่น โดยการเปิดใช้งาน arp แบบเข้มงวด:

echo 1 > /proc/sys/net/ipv4/conf/all/arp_ignore
echo 2 > /proc/sys/net/ipv4/conf/all/arp_announce

ในกรณีนี้ การตอบสนอง arp จะถูกส่งก็ต่อเมื่ออินเทอร์เฟซมีที่อยู่ IP ที่ระบุอย่างชัดเจนเท่านั้น จำเป็นต้องมีการตั้งค่านี้หากคุณวางแผนที่จะใช้ MetalLB และ kube-proxy ของคุณทำงานในโหมด IPVS

อย่างไรก็ตาม MetalLB ไม่ได้ใช้เคอร์เนลเพื่อประมวลผลคำขอ arp แต่ใช้เคอร์เนลเองในพื้นที่ผู้ใช้ ดังนั้นตัวเลือกนี้จะไม่ส่งผลต่อการทำงานของ MetalLB

กลับมาที่งานของเรากันดีกว่า หากไม่มีเส้นทางสำหรับที่อยู่ที่ออกไว้บนโหนดของคุณ ให้เพิ่มเส้นทางล่วงหน้าให้กับโหนดทั้งหมด:

ip route add 10.9.8.0/24 dev eth1

กรณีที่ 3: เมื่อคุณต้องการการกำหนดเส้นทางตามแหล่งที่มา

คุณจะต้องกำหนดค่าการกำหนดเส้นทางตามแหล่งที่มาเมื่อคุณได้รับแพ็กเก็ตผ่านเกตเวย์ที่แยกต่างหาก ไม่ใช่ที่กำหนดค่าไว้ตามค่าเริ่มต้น ดังนั้นแพ็กเก็ตการตอบกลับควรผ่านเกตเวย์เดียวกันด้วย

ตัวอย่างเช่น คุณมีเครือข่ายย่อยเดียวกัน 192.168.1.0/24 เฉพาะสำหรับโหนดของคุณ แต่คุณต้องการออกที่อยู่ภายนอกโดยใช้ MetalLB สมมติว่าคุณมีที่อยู่หลายแห่งจากเครือข่ายย่อย 1.2.3.0/24 ตั้งอยู่ใน VLAN 100 และคุณต้องการใช้เพื่อเข้าถึงบริการ Kubernetes จากภายนอก

การปรับแต่งเส้นทางอย่างละเอียดสำหรับ MetalLB ในโหมด L2

เมื่อติดต่อ 1.2.3.4 คุณจะทำการร้องขอจากซับเน็ตอื่นที่ไม่ใช่ 1.2.3.0/24 และรอคำตอบ โหนดที่เป็นโหนดหลักในปัจจุบันสำหรับที่อยู่ที่ออกโดย MetalLB 1.2.3.4จะได้รับแพ็กเก็ตจากเราเตอร์ 1.2.3.1แต่คำตอบสำหรับเขาจะต้องไปในเส้นทางเดียวกันโดยผ่าน 1.2.3.1.

เนื่องจากโหนดของเรามีเกตเวย์เริ่มต้นที่กำหนดค่าไว้แล้ว 192.168.1.1จากนั้นตามค่าเริ่มต้นการตอบกลับจะไปหาเขา ไม่ใช่ไปที่ 1.2.3.1ซึ่งเราได้รับพัสดุผ่านทางนั้น

จะรับมือกับสถานการณ์นี้ได้อย่างไร?

ในกรณีนี้ คุณต้องเตรียมโหนดทั้งหมดของคุณในลักษณะที่พร้อมให้บริการที่อยู่ภายนอกโดยไม่ต้องกำหนดค่าเพิ่มเติม นั่นคือ สำหรับตัวอย่างข้างต้น คุณต้องสร้างอินเทอร์เฟซ VLAN บนโหนดล่วงหน้า:

ip link add link eth0 name eth0.100 type vlan id 100
ip link set eth0.100 up

จากนั้นเพิ่มเส้นทาง:

ip route add 1.2.3.0/24 dev eth0.100 table 100
ip route add default via 1.2.3.1 table 100

โปรดทราบว่าเราได้เพิ่มเส้นทางลงในตารางเส้นทางแยกต่างหาก 100 จะมีเพียงสองเส้นทางที่จำเป็นในการส่งแพ็กเก็ตตอบกลับผ่านเกตเวย์ 1.2.3.1ซึ่งอยู่ด้านหลังอินเทอร์เฟซ eth0.100.

ตอนนี้เราต้องเพิ่มกฎง่ายๆ:

ip rule add from 1.2.3.0/24 lookup 100

ซึ่งระบุอย่างชัดเจนว่า: หากที่อยู่ต้นทางของแพ็กเก็ตอยู่ 1.2.3.0/24จากนั้นคุณจะต้องใช้ตารางเส้นทาง 100. ในนั้นเราได้บรรยายถึงเส้นทางที่จะส่งพระองค์ผ่านไปแล้ว 1.2.3.1

กรณีที่ 4: เมื่อคุณต้องการการกำหนดเส้นทางตามนโยบาย

โทโพโลยีเครือข่ายเหมือนกับในตัวอย่างก่อนหน้านี้ แต่สมมติว่าคุณต้องการเข้าถึงที่อยู่พูลภายนอกด้วย 1.2.3.0/24 จากพ็อดของคุณ:

การปรับแต่งเส้นทางอย่างละเอียดสำหรับ MetalLB ในโหมด L2

ลักษณะเฉพาะคือเมื่อเข้าถึงที่อยู่ใด ๆ 1.2.3.0/24แพ็กเก็ตตอบกลับจะไปถึงโหนดและมีที่อยู่ต้นทางในช่วง 1.2.3.0/24 จะถูกส่งไปอย่างเชื่อฟัง eth0.100แต่เราต้องการให้ Kubernetes เปลี่ยนเส้นทางไปยังพ็อดแรกของเรา ซึ่งสร้างคำขอดั้งเดิม

การแก้ปัญหานี้กลายเป็นเรื่องยาก แต่ก็เป็นไปได้ด้วยการกำหนดเส้นทางตามนโยบาย:

เพื่อความเข้าใจที่ดีขึ้นของกระบวนการ นี่คือแผนภาพบล็อก netfilter:
การปรับแต่งเส้นทางอย่างละเอียดสำหรับ MetalLB ในโหมด L2

ขั้นแรก ดังตัวอย่างก่อนหน้านี้ เรามาสร้างตารางเส้นทางเพิ่มเติมกัน:

ip route add 1.2.3.0/24 dev eth0.100 table 100
ip route add default via 1.2.3.1 table 100

ตอนนี้เรามาเพิ่มกฎสองสามข้อใน iptables:

iptables -t mangle -A PREROUTING -i eth0.100 -j CONNMARK --set-mark 0x100
iptables -t mangle -A PREROUTING  -j CONNMARK --restore-mark
iptables -t mangle -A PREROUTING -m mark ! --mark 0 -j RETURN
iptables -t mangle -A POSTROUTING -j CONNMARK --save-mark

กฎเหล่านี้จะทำเครื่องหมายการเชื่อมต่อขาเข้าไปยังอินเทอร์เฟซ eth0.100โดยทำเครื่องหมายแพ็กเก็ตทั้งหมดด้วยแท็ก 0x100การตอบสนองภายในการเชื่อมต่อเดียวกันจะถูกทำเครื่องหมายด้วยแท็กเดียวกันด้วย

ตอนนี้เราสามารถเพิ่มกฎการกำหนดเส้นทางได้:

ip rule add from 1.2.3.0/24 fwmark 0x100 lookup 100

นั่นคือแพ็กเก็ตทั้งหมดที่มีที่อยู่ต้นทาง 1.2.3.0/24 และแท็ก 0x100 จะต้องกำหนดเส้นทางโดยใช้ตาราง 100.

ดังนั้นแพ็กเก็ตอื่นๆ ที่ได้รับบนอินเทอร์เฟซอื่นจึงไม่อยู่ภายใต้กฎนี้ ซึ่งจะช่วยให้สามารถกำหนดเส้นทางโดยใช้เครื่องมือ Kubernetes มาตรฐานได้

มีอีกอย่างหนึ่ง ใน Linux มีสิ่งที่เรียกว่าตัวกรองเส้นทางย้อนกลับ ซึ่งทำให้เสียสิ่งทั้งหมด โดยทำการตรวจสอบง่ายๆ: สำหรับแพ็กเก็ตที่เข้ามาทั้งหมด มันจะเปลี่ยนที่อยู่ต้นทางของแพ็กเก็ตด้วยที่อยู่ผู้ส่งและตรวจสอบว่า แพ็กเก็ตสามารถออกจากอินเทอร์เฟซเดียวกันกับที่ได้รับ หากไม่เป็นเช่นนั้นก็จะกรองออก

ปัญหาคือในกรณีของเรามันจะทำงานไม่ถูกต้อง แต่เราสามารถปิดการใช้งานได้:

echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter
echo 0 > /proc/sys/net/ipv4/conf/eth0.100/rp_filter

โปรดทราบว่าคำสั่งแรกควบคุมลักษณะการทำงานทั่วโลกของ rp_filter หากไม่ได้ปิดใช้งาน คำสั่งที่สองจะไม่มีผลใดๆ อย่างไรก็ตาม อินเทอร์เฟซที่เหลือจะยังคงอยู่โดยเปิดใช้งาน rp_filter

เพื่อไม่ให้จำกัดการทำงานของตัวกรองอย่างสมบูรณ์ เราสามารถใช้ rp_filter การใช้งานสำหรับ netfilter การใช้ rpfilter เป็นโมดูล iptables คุณสามารถกำหนดค่ากฎที่ค่อนข้างยืดหยุ่นได้ เช่น:

iptables -t raw -A PREROUTING -i eth0.100 -d 1.2.3.0/24 -j RETURN
iptables -t raw -A PREROUTING -i eth0.100 -m rpfilter --invert -j DROP

เปิดใช้งาน rp_filter บนอินเทอร์เฟซ eth0.100 สำหรับที่อยู่ทั้งหมดยกเว้น 1.2.3.0/24.

ที่มา: will.com

เพิ่มความคิดเห็น