Tinh chỉnh định tuyến cho MetalLB ở chế độ L2

Tinh chỉnh định tuyến cho MetalLB ở chế độ L2
Cách đây không lâu, tôi phải đối mặt với một nhiệm vụ rất bất thường là thiết lập định tuyến cho MetalLB. Mọi chuyện sẽ ổn thôi, bởi vì... Thông thường MetalLB không yêu cầu bất kỳ hành động bổ sung nào, nhưng trong trường hợp của chúng tôi, chúng tôi có một cụm khá lớn với cấu hình mạng rất đơn giản.

Trong bài viết này, tôi sẽ cho bạn biết cách định cấu hình định tuyến dựa trên nguồn và dựa trên chính sách cho mạng bên ngoài cụm của bạn.

Tôi sẽ không đi sâu vào chi tiết về việc cài đặt và cấu hình MetalLB vì tôi cho rằng bạn đã có một số kinh nghiệm. Tôi khuyên bạn nên đi thẳng vào vấn đề, cụ thể là thiết lập định tuyến. Vì vậy, chúng tôi có bốn trường hợp:

Trường hợp 1: Khi không cần cấu hình

Hãy xem xét một trường hợp đơn giản.

Tinh chỉnh định tuyến cho MetalLB ở chế độ L2

Không cần cấu hình định tuyến bổ sung khi các địa chỉ do MetalLB cấp nằm trong cùng mạng con với địa chỉ các nút của bạn.

Ví dụ: bạn có một mạng con 192.168.1.0/24, nó có một bộ định tuyến 192.168.1.1và các nút của bạn nhận được địa chỉ: 192.168.1.10-30, thì đối với MetalLB bạn có thể điều chỉnh phạm vi 192.168.1.100-120 và đảm bảo rằng chúng sẽ hoạt động mà không cần bất kỳ cấu hình bổ sung nào.

Tại sao vậy? Bởi vì các nút của bạn đã được định cấu hình các tuyến:

# 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

Và các địa chỉ trong cùng phạm vi sẽ sử dụng lại chúng mà không cần thực hiện thêm bất kỳ hành động nào.

Trường hợp 2: Khi cần tùy chỉnh thêm

Tinh chỉnh định tuyến cho MetalLB ở chế độ L2

Bạn nên định cấu hình các tuyến bổ sung bất cứ khi nào các nút của bạn không có địa chỉ IP được định cấu hình hoặc tuyến đến mạng con mà MetalLB cấp địa chỉ.

Tôi sẽ giải thích chi tiết hơn một chút. Bất cứ khi nào MetalLB xuất ra một địa chỉ, nó có thể được so sánh với một phép gán đơn giản như:

ip addr add 10.9.8.7/32 dev lo

Chú ý đến:

  • a) Địa chỉ được gán với tiền tố /32 nghĩa là một tuyến đường sẽ không được tự động thêm vào mạng con cho nó (nó chỉ là một địa chỉ)
  • b) Địa chỉ được gắn vào bất kỳ giao diện nút nào (ví dụ loopback). Điều đáng nói ở đây là các tính năng của ngăn xếp mạng Linux. Bất kể bạn thêm địa chỉ vào giao diện nào, kernel sẽ luôn xử lý các yêu cầu arp và gửi phản hồi arp tới bất kỳ giao diện nào trong số đó, hành vi này được coi là đúng và hơn nữa, được sử dụng khá rộng rãi trong môi trường động như Kubernetes.

Hành vi này có thể được tùy chỉnh, ví dụ bằng cách bật arp nghiêm ngặt:

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

Trong trường hợp này, phản hồi arp sẽ chỉ được gửi nếu giao diện chứa địa chỉ IP cụ thể một cách rõ ràng. Cài đặt này là bắt buộc nếu bạn định sử dụng MetalLB và kube-proxy của bạn đang chạy ở chế độ IPVS.

Tuy nhiên, MetalLB không sử dụng kernel để xử lý các yêu cầu arp mà tự thực hiện trong không gian người dùng nên tùy chọn này sẽ không ảnh hưởng đến hoạt động của MetalLB.

Hãy quay trở lại nhiệm vụ của chúng ta. Nếu tuyến đường cho các địa chỉ được cấp không tồn tại trên các nút của bạn, hãy thêm tuyến đường đó vào tất cả các nút trước:

ip route add 10.9.8.0/24 dev eth1

Trường hợp 3: Khi bạn cần định tuyến dựa trên nguồn

Bạn sẽ cần định cấu hình định tuyến dựa trên nguồn khi bạn nhận các gói thông qua một cổng riêng biệt, không phải cổng được định cấu hình theo mặc định, do đó các gói phản hồi cũng phải đi qua cùng một cổng.

Ví dụ: bạn có cùng mạng con 192.168.1.0/24 dành riêng cho các nút của bạn, nhưng bạn muốn cấp địa chỉ bên ngoài bằng MetalLB. Giả sử bạn có nhiều địa chỉ từ một mạng con 1.2.3.0/24 nằm trong VLAN 100 và bạn muốn sử dụng chúng để truy cập các dịch vụ Kubernetes từ bên ngoài.

Tinh chỉnh định tuyến cho MetalLB ở chế độ L2

Khi liên hệ 1.2.3.4 bạn sẽ thực hiện yêu cầu từ một mạng con khác với 1.2.3.0/24 và chờ đợi câu trả lời. Nút hiện là nút chính cho địa chỉ do MetalLB cấp 1.2.3.4, sẽ nhận gói tin từ bộ định tuyến 1.2.3.1, nhưng câu trả lời cho anh ta nhất thiết phải đi theo con đường tương tự, thông qua 1.2.3.1.

Vì nút của chúng tôi đã có cổng mặc định được định cấu hình 192.168.1.1, thì theo mặc định, phản hồi sẽ đến với anh ấy chứ không phải đến 1.2.3.1, qua đó chúng tôi đã nhận được gói hàng.

Làm thế nào để đối phó với tình trạng này?

Trong trường hợp này, bạn cần chuẩn bị tất cả các nút của mình theo cách chúng sẵn sàng phục vụ các địa chỉ bên ngoài mà không cần cấu hình bổ sung. Nghĩa là, với ví dụ trên, bạn cần tạo trước giao diện Vlan trên nút:

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

Và sau đó thêm các tuyến đường:

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

Xin lưu ý rằng chúng tôi thêm các tuyến đường vào một bảng định tuyến riêng 100 nó sẽ chỉ chứa hai tuyến cần thiết để gửi gói phản hồi qua cổng 1.2.3.1, nằm phía sau giao diện eth0.100.

Bây giờ chúng ta cần thêm một quy tắc đơn giản:

ip rule add from 1.2.3.0/24 lookup 100

trong đó nói rõ ràng: nếu địa chỉ nguồn của gói nằm ở 1.2.3.0/24, thì bạn cần sử dụng bảng định tuyến 100. Trong đó chúng tôi đã mô tả lộ trình sẽ đưa anh ấy đi qua 1.2.3.1

Trường hợp 4: Khi bạn cần định tuyến dựa trên chính sách

Cấu trúc liên kết mạng giống như trong ví dụ trước, nhưng giả sử bạn cũng muốn có thể truy cập vào các địa chỉ nhóm bên ngoài 1.2.3.0/24 từ nhóm của bạn:

Tinh chỉnh định tuyến cho MetalLB ở chế độ L2

Điều đặc biệt là khi truy cập vào bất kỳ địa chỉ nào trong 1.2.3.0/24, gói phản hồi sẽ chạm tới nút và có địa chỉ nguồn trong phạm vi 1.2.3.0/24 sẽ được ngoan ngoãn gửi đến eth0.100, nhưng chúng tôi muốn Kubernetes chuyển hướng nó đến nhóm đầu tiên của chúng tôi, nhóm đã tạo ra yêu cầu ban đầu.

Việc giải quyết vấn đề này hóa ra rất khó khăn, nhưng nó đã trở nên khả thi nhờ định tuyến dựa trên chính sách:

Để hiểu rõ hơn về quy trình, đây là sơ đồ khối netfilter:
Tinh chỉnh định tuyến cho MetalLB ở chế độ L2

Đầu tiên, như trong ví dụ trước, hãy tạo một bảng định tuyến bổ sung:

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

Bây giờ hãy thêm một vài quy tắc vào 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

Các quy tắc này sẽ đánh dấu các kết nối đến giao diện eth0.100, đánh dấu tất cả các gói bằng thẻ 0x100, các phản hồi trong cùng một kết nối cũng sẽ được đánh dấu bằng cùng một thẻ.

Bây giờ chúng ta có thể thêm quy tắc định tuyến:

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

Nghĩa là, tất cả các gói có địa chỉ nguồn 1.2.3.0/24 và gắn thẻ 0x100 phải được định tuyến bằng bảng 100.

Do đó, các gói khác nhận được trên giao diện khác không tuân theo quy tắc này, điều này sẽ cho phép chúng được định tuyến bằng các công cụ Kubernetes tiêu chuẩn.

Còn một điều nữa, trong Linux có một bộ lọc đường dẫn ngược, làm hỏng toàn bộ sự việc; nó thực hiện một kiểm tra đơn giản: đối với tất cả các gói đến, nó thay đổi địa chỉ nguồn của gói bằng địa chỉ người gửi và kiểm tra xem gói có thể đi qua cùng giao diện mà nó đã được nhận, nếu không, nó sẽ lọc gói đó ra.

Vấn đề là trong trường hợp của chúng tôi, nó sẽ không hoạt động chính xác, nhưng chúng tôi có thể tắt nó:

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

Xin lưu ý rằng lệnh đầu tiên kiểm soát hành vi chung của rp_filter; nếu nó không bị tắt, lệnh thứ hai sẽ không có hiệu lực. Tuy nhiên, các giao diện còn lại sẽ vẫn được bật rp_filter.

Để không hạn chế hoàn toàn hoạt động của bộ lọc, chúng ta có thể sử dụng cách triển khai rp_filter cho netfilter. Sử dụng rpfilter làm mô-đun iptables, bạn có thể định cấu hình các quy tắc khá linh hoạt, ví dụ:

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

kích hoạt rp_filter trên giao diện eth0.100 cho tất cả các địa chỉ ngoại trừ 1.2.3.0/24.

Nguồn: www.habr.com

Thêm một lời nhận xét