Pola penggunaan beberapa NIC host

Dokumen ini menjelaskan pola konfigurasi dan praktik terbaik untuk menggunakan dua antarmuka jaringan (NIC) LAN host untuk penyimpanan dan pengelolaan di instance Compute Engine.

Ringkasan

Beberapa seri mesin yang dioptimalkan untuk akselerator—termasuk A5X, A4X Max, A4X, A4, dan A3 Ultra—memiliki dua antarmuka jaringan LAN host untuk penyimpanan dan pengelolaan yang terhubung ke jaringan Virtual Private Cloud (VPC) reguler. Mesin ini juga memiliki antarmuka jaringan MRDMA yang harus terpasang ke jaringan VPC Remote Direct Memory Access over Converged Ethernet (RoCE).

Dokumen ini berfokus pada konfigurasi antarmuka LAN host (gVNIC atau IDPF) di jaringan VPC reguler, bukan antarmuka jaringan RDMA. Antarmuka LAN host adalah unit pemrosesan infrastruktur (IPU) Titanium yang terhubung ke soket CPU dan node akses memori tidak seragam (NUMA) yang terpisah. Di dalam instance komputasi, IPU ini muncul sebagai Google Virtual NIC (gVNIC) atau antarmuka jaringan Infrastructure Data Path Function (IDPF). Antarmuka ini menyediakan bandwidth jaringan untuk aktivitas penyimpanan dan pengelolaan, seperti checkpoint, pemuatan data pelatihan, dan pemuatan model. Topologi NUMA mesin, termasuk topologi antarmuka jaringan, dapat dilihat oleh sistem operasi (OS) tamu.

Gunakan konfigurasi berikut, terlepas dari pola yang Anda pilih untuk beberapa NIC host:

  • Setelan jaringan: Konfigurasikan setiap antarmuka gVNIC atau IDPF untuk menggunakan jaringan VPC terpisah. Untuk penyiapan VPC, selesaikan konfigurasi berikut:
    • Konfigurasikan unit transmisi maksimum (MTU) yang besar untuk setiap jaringan VPC, seperti 8896 (MTU maksimum yang didukung).
    • Jika paket data masuk yang dihapus di sisi penerima memperlambat performa ingress untuk workload Anda, periksa paket yang dihapus menggunakan utilitas ethtool. Untuk mengoptimalkan alokasi data dari cache halaman sehingga setiap frame lapisan 2 yang masuk sesuai dengan dua buffer 4 KB, sesuaikan ukuran segmen maksimum (MSS) TCP, MTU antarmuka, atau MTU VPC.
  • Setelan aplikasi:
    • Selaraskan NUMA aplikasi Anda menggunakan core CPU, alokasi memori, dan antarmuka jaringan dari node NUMA yang sama. Jika Anda menjalankan instance khusus aplikasi untuk node NUMA atau antarmuka jaringan tertentu, ikat resource CPU dan memori aplikasi ke node NUMA tersebut menggunakan alat seperti numactl.
  • Setelan sistem operasi:
    • Aktifkan TCP segmentation offload (TSO) dan large receive offload (LRO).
    • Untuk setiap antarmuka gVNIC atau IDPF, konfigurasikan afinitas multipemrosesan simetris (SMP) untuk merutekan permintaan interupsi (IRQ) ke node NUMA yang sama dengan antarmuka dan menyebarkan interupsi ke seluruh core CPU. Jika Anda menggunakan image Linux yang disediakan Google, agen tamu Compute Engine akan menjalankan skrip google_set_multiqueue saat booting untuk menerapkan konfigurasi ini secara otomatis. Jika Anda menggunakan image kustom, instal lingkungan tamu. Jika skrip tidak berjalan secara otomatis, jalankan perintah sudo /usr/bin/google_set_multiqueue.
    • Evaluasi setelan Receive Flow Steering (RFS), Receive Packet Steering (RPS), dan Transmit Packet Steering (XPS) untuk menentukan apakah setelan tersebut bermanfaat bagi workload Anda.
    • Untuk instance A4X Max dan A4X, NVIDIA merekomendasikan agar Anda menonaktifkan penjadwalan NUMA otomatis.
    • Jangan gunakan pengikatan kernel Linux dengan antarmuka gVNIC atau IDPF di mesin ini, karena pengikatan kernel tidak didukung.

Pola penggunaan beberapa NIC host

Tabel berikut menguraikan pola umum untuk menggunakan beberapa NIC host di Google Cloud:

Pola umum untuk menggunakan beberapa NIC host
Pola Tata letak proses yang didukung Jalur deployment: Compute Engine Jalur deployment: Google Kubernetes Engine Jalur deployment: Slurm Catatan
Mengubah aplikasi untuk menggunakan antarmuka tertentu Memproses shard per antarmuka Ya Ya Ya Memerlukan perubahan kode pada aplikasi.
Mengubah aplikasi untuk menggunakan kedua antarmuka Proses antarmuka ganda Ya Ya Ya Memerlukan perubahan kode pada aplikasi.
Menggunakan namespace jaringan khusus untuk aplikasi tertentu Memproses shard per antarmuka Ya Ya (khusus container dengan hak istimewa) Tidak Tidak ada
Memetakan seluruh traffic container ke satu antarmuka Semua traffic container dipetakan ke satu antarmuka Ya Ya Tidak Tidak ada
Menggunakan peering VPC dan mengizinkan sistem melakukan load balancing sesi di seluruh antarmuka Proses antarmuka ganda Ya Ya Ya Sulit atau tidak mungkin untuk menyelaraskan NUMA. Memerlukan kernel Linux 6.16 atau yang lebih baru.
Melakukan sharding traffic di seluruh jaringan
  • Proses antarmuka ganda
  • Memproses shard per antarmuka
Ya Ya Ya Mungkin memerlukan perubahan kode agar selaras dengan NUMA jika Anda menjalankan proses antarmuka ganda.
Menggunakan penafsiran alamat jaringan sumber (SNAT) untuk memilih antarmuka sumber
  • Proses antarmuka ganda
  • Memproses shard per antarmuka
Ya Ya (penyiapan memerlukan hak istimewa administrator) Ya (penyiapan memerlukan hak istimewa administrator) Mungkin sulit dikonfigurasi.

Catatan

Mengubah aplikasi untuk menggunakan antarmuka tertentu

Persyaratan:

  • Memerlukan perubahan kode pada aplikasi Anda.
  • Memerlukan izin untuk satu atau beberapa metode berikut:
    • bind(): memerlukan izin khusus hanya jika Anda menggunakan port sumber dengan hak istimewa.
    • SO_BINDTODEVICE: memerlukan izin CAP_NET_RAW.
  • Mungkin mengharuskan Anda mengubah tabel pemilihan rute kernel untuk membuat rute dan mencegah pemilihan rute asimetris.

Ringkasan umum

Untuk mengonfigurasi aplikasi agar menggunakan antarmuka jaringan tertentu, selesaikan langkah-langkah berikut:

  1. Tambahkan binding untuk antarmuka jaringan ke kode sumber aplikasi Anda menggunakan salah satu opsi berikut:
    • Gunakan panggilan sistem bind() untuk mengikat soket ke alamat IP sumber tertentu.
    • Gunakan opsi soket SO_BINDTODEVICE untuk mengikat soket ke antarmuka jaringan tertentu.
  2. Ubah tabel pemilihan rute kernel sesuai kebutuhan untuk memastikan bahwa ada rute dari antarmuka jaringan sumber ke alamat tujuan. Untuk mencegah perutean asimetris, konfigurasikan perutean kebijakan seperti yang dijelaskan dalam Mengonfigurasi perutean untuk antarmuka jaringan tambahan.
  3. Opsional: Jalankan aplikasi Anda pada memori dan CPU yang menggunakan node NUMA yang sama dengan antarmuka jaringan yang Anda pilih menggunakan perintah numactl.

Setelah Anda menyelesaikan langkah-langkah ini, aplikasi Anda akan menggunakan antarmuka jaringan yang ditentukan.

Mengubah aplikasi untuk menggunakan kedua antarmuka

Persyaratan:

  • Memerlukan perubahan kode pada aplikasi Anda.
  • Memerlukan izin untuk satu atau beberapa metode berikut:
    • bind(): memerlukan izin khusus hanya jika Anda menggunakan port sumber dengan hak istimewa.
    • SO_BINDTODEVICE: memerlukan izin CAP_NET_RAW.
  • Mungkin mengharuskan Anda mengubah tabel pemilihan rute kernel untuk membuat rute dan mencegah pemilihan rute asimetris.

Ringkasan umum

Untuk mengonfigurasi aplikasi agar menggunakan kedua antarmuka jaringan, selesaikan langkah-langkah berikut:

  1. Tambahkan binding untuk setiap antarmuka jaringan ke kode sumber aplikasi Anda menggunakan salah satu opsi berikut:
    • Gunakan panggilan sistem bind() untuk mengikat setiap soket ke alamat IP sumber antarmuka jaringan yang sesuai.
    • Gunakan opsi soket SO_BINDTODEVICE untuk mengikat setiap soket ke antarmuka jaringan tertentu.
  2. Jika aplikasi Anda bertindak sebagai klien, buat soket klien terpisah untuk setiap antarmuka jaringan sumber.
  3. Ubah tabel perutean kernel sesuai kebutuhan untuk memastikan bahwa ada rute dari setiap antarmuka jaringan sumber ke alamat tujuan. Untuk mencegah perutean asimetris, konfigurasikan perutean kebijakan seperti yang dijelaskan dalam Mengonfigurasi perutean untuk antarmuka jaringan tambahan.
  4. Partisi aktivitas jaringan menjadi thread yang berjalan pada node NUMA yang sama dengan antarmuka gVNIC atau IDPF yang sesuai—misalnya, dengan memanggil pthread_setaffinity_np. Karena aplikasi menggunakan resource di beberapa node NUMA, hindari penggunaan numactl, atau pastikan perintah numactl Anda menyertakan node NUMA dari semua antarmuka jaringan yang digunakan aplikasi Anda.

Menggunakan namespace jaringan khusus untuk aplikasi tertentu

Persyaratan:

  • Memerlukan kemampuan CAP_SYS_ADMIN.
  • Tidak kompatibel dengan GKE Autopilot.
  • Jika menggunakan GKE, Anda harus menggunakan container dengan hak istimewa.

Bagian ini menjelaskan pola yang dapat Anda gunakan untuk membuat namespace jaringan untuk antarmuka jaringan sekunder. Pola terbaik untuk workload Anda bergantung pada skenario Anda. Pendekatan yang menggunakan tombol virtual atau IPvlan berfungsi paling baik saat beberapa aplikasi perlu berbagi antarmuka sekunder dari namespace jaringan yang berbeda.

Memindahkan antarmuka sekunder ke namespace jaringan khusus

Dengan pola ini, Anda membuat namespace jaringan, memindahkan antarmuka gVNIC atau IDPF sekunder ke namespace baru, lalu menjalankan aplikasi dari namespace tersebut. Pola ini lebih mudah disiapkan dan disesuaikan dibandingkan dengan tombol virtual, tetapi aplikasi di luar namespace jaringan baru tidak dapat mengakses antarmuka jaringan sekunder.

Untuk memindahkan antarmuka eth1 ke namespace jaringan bernama app-net dan menjalankan perintah di namespace tersebut, jalankan perintah berikut:

ip netns add app-net
ip link set eth1 netns app-net
ip netns exec app-net ip addr add ETH1_IP/PREFIX dev eth1
ip netns exec app-net ip link set dev eth1 up
ip netns exec app-net ip route add default via GATEWAY_IP dev eth1
ip netns exec app-net COMMAND

Ganti kode berikut:

  • ETH1_IP: alamat IP internal antarmuka eth1.
  • PREFIX: panjang awalan subnet untuk antarmuka eth1.
  • GATEWAY_IP: alamat IP gateway default untuk subnet eth1.
  • COMMAND: perintah yang akan dijalankan di dalam namespace jaringan app-net.

Saat Anda menjalankan perintah ini, COMMAND akan berjalan di dalam namespace jaringan app-net dan menggunakan antarmuka eth1.

Aplikasi yang berjalan di dalam namespace jaringan baru menggunakan antarmuka gVNIC atau IDPF sekunder. Anda juga dapat menggunakan perintah numactl untuk menjalankan aplikasi menggunakan memori dan CPU pada node NUMA yang sama dengan antarmuka jaringan yang Anda pilih.

Menggunakan switch virtual dan namespace jaringan untuk antarmuka sekunder

Dengan pola ini, Anda mengonfigurasi tombol virtual untuk mengakses antarmuka gVNIC atau IDPF sekunder dari namespace jaringan:

  1. Buka koneksi SSH ke instance komputasi. Untuk mengetahui informasi selengkapnya, lihat Menghubungkan ke VM Linux.
  2. Buat pasangan perangkat Virtual Ethernet (veth) menggunakan perintah ip link add—misalnya, ip link add veth0 type veth peer name veth1.
  3. Sesuaikan MTU di setiap perangkat agar sesuai dengan MTU antarmuka sekunder menggunakan perintah ip link set:

    ip link set dev veth0 mtu MTU
    ip link set dev veth1 mtu MTU
    

    Ganti MTU dengan MTU antarmuka sekunder—misalnya, 8896.

  4. Aktifkan penerusan paket IPv4:

    sysctl -w net.ipv4.ip_forward=1
    
  5. Pindahkan salah satu ujung pasangan veth ke namespace jaringan baru, dan biarkan ujung lainnya di namespace root.

  6. Petakan traffic dari perangkat veth ke antarmuka sekunder. Untuk mengonfigurasi pemetaan ini, buat rentang IP alias untuk antarmuka sekunder instance komputasi dan tetapkan alamat IP dari rentang ini ke antarmuka turunan di namespace.

  7. Jalankan aplikasi dari namespace jaringan baru. Anda dapat menggunakan perintah numactl untuk menjalankan aplikasi menggunakan memori dan CPU pada node NUMA yang sama dengan antarmuka jaringan yang dipilih.

Atau, bergantung pada OS tamu dan penyiapan workload, Anda dapat menautkan antarmuka IPvlan ke antarmuka gVNIC atau IDPF sekunder, bukan membuat perangkat veth.

Memetakan traffic seluruh container ke satu antarmuka

Persyaratan:

  • Aplikasi Anda harus berjalan di dalam container yang menggunakan namespace jaringan untuk jaringan container, seperti GKE, Docker, atau Podman. Anda tidak dapat menggunakan jaringan host.

Runtime container seperti GKE, Docker, dan Podman menggunakan namespace jaringan khusus untuk setiap container guna mengisolasi traffic-nya. Anda dapat mengubah namespace jaringan ini—baik secara langsung maupun menggunakan alat runtime container—untuk memetakan traffic ke antarmuka jaringan yang berbeda.

GKE memerlukan antarmuka utama untuk komunikasi Kubernetes internal. Namun, Anda dapat mengubah rute default di Pod untuk menggunakan antarmuka sekunder, seperti yang ditunjukkan dalam manifes Pod GKE berikut:

metadata:
  # ...
  annotations:
    networking.gke.io/default-interface: 'eth1'
    networking.gke.io/interfaces: |
      [
        {"interfaceName":"eth0","network":"default"},
        {"interfaceName":"eth1","network":"secondary-network"}
      ]

Pendekatan ini tidak menjamin penyelarasan NUMA antara antarmuka jaringan default dan CPU atau memori yang ditetapkan.

Menggunakan peering VPC dan mengizinkan sistem melakukan load balancing sesi di seluruh antarmuka

Persyaratan:

  • Anda harus membuat Peering Jaringan VPC antara jaringan VPC NIC host utama dan sekunder.
  • Anda harus menggunakan Linux kernel versi 6.16 atau yang lebih baru untuk menyeimbangkan beban sesi TCP di seluruh antarmuka sumber saat mengirim traffic ke satu alamat IP dan port tujuan.
  • Workload Anda harus menoleransi transfer memori lintas soket tanpa mengabaikan target performanya.

Ringkasan umum

Jika Anda tidak dapat dengan mudah melakukan sharding koneksi jaringan dalam aplikasi atau di seluruh instance aplikasi, dan workload Anda berjalan pada instance komputasi A4 atau A3 Ultra yang tidak sensitif terhadap transfer lintas NUMA atau lintas soket, Anda dapat memperlakukan kedua antarmuka tersebut sebagai sepadan.

Untuk mengonfigurasi perilaku ini, aktifkan parameter sysctl fib_multipath_hash_policy dan tambahkan rute multipath:

PRIMARY_GW=192.168.1.1  # Gateway of nic0
SECONDARY_GW=192.168.2.1  # Gateway of nic1
PRIMARY_IP=192.168.1.15  # Internal IP address for nic0
SECONDARY_IP=192.168.2.27  # Internal IP address for nic1

# Enable L4 5-tuple equal-cost multipath (ECMP) hashing
sysctl -w net.ipv4.fib_multipath_hash_policy=1
ip route add DESTINATION_NETWORK/SUBNET_MASK \
    nexthop via ${PRIMARY_GW} \
    nexthop via ${SECONDARY_GW}

Ganti kode berikut:

  • DESTINATION_NETWORK: rentang alamat IP internal tujuan.
  • SUBNET_MASK: panjang awalan subnet untuk jaringan tujuan.

Membagi traffic di seluruh jaringan

Persyaratan:

  • nic0 dan nic1 pada instance komputasi harus terhubung ke jaringan VPC dan subnet yang terpisah, dan alamat IP tujuan harus di-sharding di dua jaringan VPC.

Ringkasan umum

Secara default, kernel Linux membuat rute untuk subnet nic0 dan subnet nic1 yang merutekan traffic berdasarkan alamat IP tujuan melalui antarmuka jaringan yang sesuai.

Misalnya, anggaplah nic0 menggunakan jaringan VPC net1 dengan subnet subnet-a, dan nic1 menggunakan jaringan VPC net2 dengan subnet subnet-b. Secara default, traffic ke alamat IP peer di subnet-a menggunakan nic0, dan traffic ke alamat IP peer di subnet-b menggunakan nic1. Konfigurasi ini biasanya berlaku saat sekumpulan instance komputasi single-NIC peer terhubung ke net1 dan sekumpulan kedua terhubung ke net2.

Menggunakan SNAT untuk memilih antarmuka sumber

Persyaratan:

  • Memerlukan kemampuan CAP_NET_ADMIN untuk menyiapkan aturan iptables awal, meskipun tidak untuk menjalankan aplikasi.
  • Memerlukan evaluasi yang cermat jika digabungkan dengan aturan iptables atau konfigurasi perutean nontrivial lainnya.

Ringkasan umum

Jika Anda tidak dapat menggunakan namespace jaringan atau mengubah aplikasi, Anda dapat menggunakan SNAT untuk memilih antarmuka sumber. Dengan menggunakan alat seperti iptables, Anda dapat menulis ulang alamat IP sumber flow agar cocok dengan alamat IP antarmuka tertentu berdasarkan properti aplikasi pengirim, seperti cgroup, pengguna, atau CPU-nya.

Contoh berikut menggunakan aturan berbasis CPU sehingga setiap alur yang berasal dari thread pada CPU tertentu keluar melalui antarmuka gVNIC atau IDPF yang terpasang ke node NUMA CPU tersebut:

# --- Begin Configuration ---
OUTPUT_INTERFACE_0="enp0s19"        # CHANGEME: NIC0
OUTPUT_INTERFACE_1="enp192s20"      # CHANGEME: NIC1

CPUS_0=($(seq 0 55; seq 112 167))   # CHANGEME: CPU IDs for NIC0
GATEWAY_0="10.0.0.1"                # CHANGEME: Gateway for NIC0
SNAT_IP_0="10.0.0.2"                # CHANGEME: SNAT IP for NIC0
CONNMARK_0="0x1"
RT_TABLE_0="100"

CPUS_1=($(seq 56 111; seq 168 223)) # CHANGEME: CPU IDs for NIC1
GATEWAY_1="10.0.1.1"                # CHANGEME: Gateway for NIC1
SNAT_IP_1="10.0.1.2"                # CHANGEME: SNAT IP for NIC1
CONNMARK_1="0x2"
RT_TABLE_1="101"
# --- End Configuration ---

# Specify which interface to use for packets in each routing table.
ip route add default via "$GATEWAY_0" dev "$OUTPUT_INTERFACE_0" table "$RT_TABLE_0"
ip route add default via "$GATEWAY_1" dev "$OUTPUT_INTERFACE_1" table "$RT_TABLE_1"

# Route replies to connections from peers through the matching egress interface.
# Add these rules before the fwmark rules so that fwmark takes precedence.
ip rule add from "$SNAT_IP_0" table "$RT_TABLE_0"
ip rule add from "$SNAT_IP_1" table "$RT_TABLE_1"

# Select the routing table based on the packet mark set in OUTPUT.
ip rule add fwmark "$CONNMARK_0" table "$RT_TABLE_0"
ip rule add fwmark "$CONNMARK_1" table "$RT_TABLE_1"

# Relax reverse path filtering so that the kernel doesn't drop legitimate
# replies to the SNAT IP addresses.
sysctl -w net.ipv4.conf."$OUTPUT_INTERFACE_0".rp_filter=2
sysctl -w net.ipv4.conf."$OUTPUT_INTERFACE_1".rp_filter=2

# Mark packets and connections with a per-NIC mark based on the source CPU.
# The fwmark rules then select the corresponding routing table for this traffic.
for cpu_id in "${CPUS_0[@]}"; do
    iptables -t mangle -A OUTPUT -m state --state NEW -m cpu --cpu "$cpu_id" -j CONNMARK --set-mark "$CONNMARK_0"
    iptables -t mangle -A OUTPUT -m state --state NEW -m cpu --cpu "$cpu_id" -j MARK --set-mark "$CONNMARK_0"
done
for cpu_id in "${CPUS_1[@]}"; do
    iptables -t mangle -A OUTPUT -m state --state NEW -m cpu --cpu "$cpu_id" -j CONNMARK --set-mark "$CONNMARK_1"
    iptables -t mangle -A OUTPUT -m state --state NEW -m cpu --cpu "$cpu_id" -j MARK --set-mark "$CONNMARK_1"
done

# Restore the connection mark for established connections so that packets use
# the same NIC regardless of other routing rules.
iptables -t mangle -A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j CONNMARK --restore-mark

# Rewrite the source address after the packet is routed to the target interface
# so that replies return to the same NIC and pass VPC network validation.
iptables -t nat -A POSTROUTING -m mark --mark "$CONNMARK_0" -j SNAT --to-source "$SNAT_IP_0"
iptables -t nat -A POSTROUTING -m mark --mark "$CONNMARK_1" -j SNAT --to-source "$SNAT_IP_1"

Langkah berikutnya