Menyempurnakan perutean untuk MetalLB dalam mode L2

Menyempurnakan perutean untuk MetalLB dalam mode L2
Belum lama ini saya dihadapkan dengan tugas yang sangat tidak biasa dalam menyiapkan perutean untuk MetalLB. Semuanya akan baik-baik saja, karena... Biasanya MetalLB tidak memerlukan tindakan tambahan apa pun, tetapi dalam kasus kami, kami memiliki cluster yang cukup besar dengan konfigurasi jaringan yang sangat sederhana.

Pada artikel ini saya akan memberi tahu Anda cara mengonfigurasi perutean berbasis sumber dan berbasis kebijakan untuk jaringan eksternal cluster Anda.

Saya tidak akan menjelaskan secara detail tentang menginstal dan mengkonfigurasi MetalLB, karena saya berasumsi Anda sudah memiliki pengalaman. Saya sarankan langsung ke intinya yaitu mengatur routing. Jadi kita punya empat kasus:

Kasus 1: Ketika tidak diperlukan konfigurasi

Mari kita lihat kasus sederhana.

Menyempurnakan perutean untuk MetalLB dalam mode L2

Konfigurasi perutean tambahan tidak diperlukan bila alamat yang dikeluarkan oleh MetalLB berada di subnet yang sama dengan alamat node Anda.

Misalnya, Anda memiliki subnet 192.168.1.0/24, ia memiliki router 192.168.1.1, dan node Anda menerima alamat: 192.168.1.10-30, lalu untuk MetalLB Anda dapat menyesuaikan rentangnya 192.168.1.100-120 dan pastikan semuanya akan berfungsi tanpa konfigurasi tambahan apa pun.

Mengapa demikian? Karena node Anda sudah memiliki rute yang dikonfigurasi:

# 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

Dan alamat dari rentang yang sama akan menggunakannya kembali tanpa tindakan tambahan apa pun.

Kasus 2: Ketika penyesuaian tambahan diperlukan

Menyempurnakan perutean untuk MetalLB dalam mode L2

Anda harus mengonfigurasi rute tambahan setiap kali node Anda tidak memiliki alamat IP yang dikonfigurasi atau rute ke subnet yang alamatnya dikeluarkan oleh MetalLB.

Saya akan menjelaskannya sedikit lebih detail. Setiap kali MetalLB mengeluarkan sebuah alamat, itu dapat dibandingkan dengan tugas sederhana seperti:

ip addr add 10.9.8.7/32 dev lo

Perhatikan:

  • a) Alamat diberikan dengan awalan /32 artinya, rute tidak akan secara otomatis ditambahkan ke subnet untuk itu (itu hanya sebuah alamat)
  • b) Alamat tersebut dilampirkan ke antarmuka node mana pun (misalnya loopback). Perlu disebutkan di sini fitur tumpukan jaringan Linux. Tidak peduli antarmuka mana yang Anda tambahkan alamatnya, kernel akan selalu memproses permintaan arp dan mengirimkan respons arp ke salah satu permintaan tersebut, perilaku ini dianggap benar dan, terlebih lagi, cukup banyak digunakan dalam lingkungan dinamis seperti Kubernetes.

Perilaku ini dapat disesuaikan, misalnya dengan mengaktifkan arp ketat:

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

Dalam hal ini, tanggapan arp hanya akan dikirim jika antarmuka secara eksplisit berisi alamat IP tertentu. Pengaturan ini diperlukan jika Anda berencana menggunakan MetalLB dan kube-proxy Anda berjalan dalam mode IPVS.

Namun, MetalLB tidak menggunakan kernel untuk memproses permintaan arp, tetapi melakukannya sendiri di ruang pengguna, jadi opsi ini tidak akan memengaruhi pengoperasian MetalLB.

Mari kita kembali ke tugas kita. Jika rute untuk alamat yang dikeluarkan tidak ada di node Anda, tambahkan terlebih dahulu ke semua node:

ip route add 10.9.8.0/24 dev eth1

Kasus 3: Saat Anda memerlukan perutean berbasis sumber

Anda perlu mengonfigurasi perutean berbasis sumber ketika Anda menerima paket melalui gateway terpisah, bukan yang dikonfigurasi secara default, oleh karena itu paket respons juga harus melalui gateway yang sama.

Misalnya, Anda memiliki subnet yang sama 192.168.1.0/24 didedikasikan untuk node Anda, tetapi Anda ingin mengeluarkan alamat eksternal menggunakan MetalLB. Anggaplah Anda memiliki beberapa alamat dari satu subnet 1.2.3.0/24 terletak di VLAN 100 dan Anda ingin menggunakannya untuk mengakses layanan Kubernetes secara eksternal.

Menyempurnakan perutean untuk MetalLB dalam mode L2

Saat menghubungi 1.2.3.4 Anda akan membuat permintaan dari subnet yang berbeda 1.2.3.0/24 dan menunggu jawabannya. Node yang saat ini menjadi master untuk alamat yang dikeluarkan MetalLB 1.2.3.4, akan menerima paket dari router 1.2.3.1, tapi jawabannya tentu harus melalui jalur yang sama, lewat 1.2.3.1.

Karena node kita sudah memiliki gateway default yang dikonfigurasi 192.168.1.1, maka secara default responsnya akan ditujukan kepadanya, bukan ke sana 1.2.3.1, melalui mana kami menerima paket tersebut.

Bagaimana cara mengatasi situasi ini?

Dalam hal ini, Anda perlu mempersiapkan semua node Anda sedemikian rupa sehingga siap melayani alamat eksternal tanpa konfigurasi tambahan. Artinya, untuk contoh di atas, Anda perlu membuat antarmuka VLAN pada node terlebih dahulu:

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

Dan kemudian tambahkan rute:

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

Harap dicatat bahwa kami menambahkan rute ke tabel perutean terpisah 100 itu hanya akan berisi dua rute yang diperlukan untuk mengirim paket respons melalui gateway 1.2.3.1, terletak di belakang antarmuka eth0.100.

Sekarang kita perlu menambahkan aturan sederhana:

ip rule add from 1.2.3.0/24 lookup 100

yang secara eksplisit mengatakan: jika alamat sumber paket ada di 1.2.3.0/24, maka Anda perlu menggunakan tabel perutean 100. Di dalamnya kami telah menjelaskan rute yang akan dilaluinya 1.2.3.1

Kasus 4: Saat Anda memerlukan perutean berbasis kebijakan

Topologi jaringannya sama seperti pada contoh sebelumnya, tetapi misalkan Anda juga ingin dapat mengakses alamat pool eksternal 1.2.3.0/24 dari pod Anda:

Menyempurnakan perutean untuk MetalLB dalam mode L2

Keunikannya adalah ketika mengakses alamat apa pun di 1.2.3.0/24, paket respons mencapai node dan memiliki alamat sumber dalam jangkauan 1.2.3.0/24 akan dengan patuh dikirim ke eth0.100, tapi kami ingin Kubernetes mengalihkannya ke pod pertama kami, yang menghasilkan permintaan asli.

Menyelesaikan masalah ini ternyata sulit, namun menjadi mungkin berkat perutean berbasis kebijakan:

Untuk pemahaman yang lebih baik tentang prosesnya, berikut adalah diagram blok netfilter:
Menyempurnakan perutean untuk MetalLB dalam mode L2

Pertama, seperti pada contoh sebelumnya, mari buat tabel routing tambahan:

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

Sekarang mari tambahkan beberapa aturan ke 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

Aturan-aturan ini akan menandai koneksi masuk ke antarmuka eth0.100, menandai semua paket dengan tag 0x100, tanggapan dalam koneksi yang sama juga akan ditandai dengan tag yang sama.

Sekarang kita dapat menambahkan aturan perutean:

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

Artinya, semua paket dengan alamat sumber 1.2.3.0/24 dan menandai 0x100 harus dirutekan menggunakan tabel 100.

Dengan demikian, paket lain yang diterima di antarmuka lain tidak tunduk pada aturan ini, yang memungkinkan paket tersebut dirutekan menggunakan alat standar Kubernetes.

Ada satu hal lagi, di Linux ada yang disebut filter jalur terbalik, yang merusak semuanya; ia melakukan pemeriksaan sederhana: untuk semua paket masuk, ia mengubah alamat sumber paket dengan alamat pengirim dan memeriksa apakah paket dapat keluar melalui antarmuka yang sama dengan tempat paket diterima, jika tidak, paket akan menyaringnya.

Masalahnya adalah dalam kasus kami ini tidak berfungsi dengan benar, tetapi kami dapat menonaktifkannya:

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

Harap dicatat bahwa perintah pertama mengontrol perilaku global rp_filter; jika tidak dinonaktifkan, perintah kedua tidak akan berpengaruh. Namun, antarmuka lainnya akan tetap dengan rp_filter diaktifkan.

Agar tidak sepenuhnya membatasi pengoperasian filter, kita dapat menggunakan implementasi rp_filter untuk netfilter. Menggunakan rpfilter sebagai modul iptables, Anda dapat mengonfigurasi aturan yang cukup fleksibel, misalnya:

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

aktifkan rp_filter pada antarmuka eth0.100 untuk semua alamat kecuali 1.2.3.0/24.

Sumber: www.habr.com

Tambah komentar