Pod OpenVPN di Kubernetes tidak meneruskan apa pun? Periksa ip_forward
Klien mem-ping pod VPN dan tidak ada yang lewat. Namespace mematikan penerusan, dan perbaikannya harus bertahan dari admission, restart, dan jalur balik.
Laptop Anda menampilkan terowongan hijau, log klien melaporkan rute telah didorong, dan satu-satunya alamat yang menjawab adalah IP terowongan milik server VPN itu sendiri. Ping ke seberangnya mati apa pun targetnya, entah ClusterIP, alamat pod lain, atau nama host publik. Kombinasi itu diagnostik, bukan kabur: dekapsulasi berfungsi, dan lompatan kedua tidak.
Saya menemui ini pada node Debian yang menjalankan image OpenVPN hasil pemasangan chart, dan terowongannya adalah bagian yang mudah. Klien mendapat sewa 10.8.0.x, 10.8.0.1 menjawab, dan 10.96.0.10, layanan DNS klaster, kehabisan waktu. Tidak ada yang tampak tidak sehat di log server, dan justru itulah sebabnya orang mulai menulis ulang aturan iptables yang tidak pernah perlu mereka sentuh.
Pod VPN adalah router, dan itu layak dikatakan terus terang. Paket terenkripsi datang, dibuka di namespace jaringan milik pod itu sendiri, lalu harus keluar melalui antarmuka lain. Linux menolak langkah kedua itu kecuali penerusan diaktifkan di dalam namespace yang sama.
Apa yang bisa dan tidak bisa dijangkau klien
Alamat yang menjawab milik ujung terowongan, dan proses VPN memilikinya secara lokal, jadi penerusan sama sekali tidak terlibat. Segala hal lain, termasuk pod lain, VIP layanan, atau internet, membutuhkan kernel untuk memindahkan paket dari tun0 ke eth0. Ketika pemindahan itu ditolak, gejalanya adalah kesunyian seragam, bukan penolakan, karena tidak ada yang menghasilkan galat ICMP kembali menuruni terowongan. Anda mendapat timeout, bukan pesan tak terjangkau, dan itulah petunjuk bahwa tidak ada yang merutekan sama sekali.
Dua menit klasifikasi mempersempit lapisannya. Jika nama DNS gagal sementara ping mentah ke IP layanan berhasil, masalahnya ada di perpipaan DNS, bukan penerusan. Jika setiap tujuan di luar alamat peer kehabisan waktu, termasuk IP telanjang, mulailah dari namespace.
Baca pengaturan di dalam namespace
Setiap pod mendapat namespace jaringannya sendiri, dan net.ipv4.ip_forward adalah sysctl per namespace. Mengubahnya di node tidak memberi tahu apa pun tentang kontainer, dan itu cara yang andal menghabiskan sore di mesin yang salah.
kubectl exec -it deploy/openvpn -- sysctl net.ipv4.ip_forward
# net.ipv4.ip_forward = 0
Nol menegaskan diagnosisnya. Nilainya juga tidak diwarisi dari konfigurasi runtime node: ia mulai dari bawaan image setiap kali kontainer dibuat. Perbaikan yang diterapkan dengan tangan memakai kubectl exec ... sysctl -w karena itu lenyap pada restart berikutnya dan kembali sebagai kerusakan yang tampak berkala.
Mengaktifkannya agar manifes mempertahankannya
Pilihan yang tahan lama adalah kontainer init yang berjalan di pod sandbox yang sama dan menulis nilainya sebelum kontainer VPN mulai. Kontainer dalam satu pod berbagi namespace jaringan, jadi pengaturannya ikut ke kontainer utama.
initContainers:
- name: enable-forwarding
image: busybox:1.36
command: ["sysctl", "-w", "net.ipv4.ip_forward=1"]
securityContext:
privileged: true
Baris privileged: true itulah yang dipermasalahkan para peninjau, dan mereka benar. Menulis sysctl memerlukan hak istimewa atau kemampuan yang sempit cakupannya, dan klaster yang menjalankan Pod Security Standard terbatas bisa menolak kontainer init berhak istimewa mentah-mentah. Jika admission menolak pod, Anda mengetahuinya saat pembuatan, yang setidaknya jujur dan mudah dibaca.
Alternatif yang lebih bersih adalah daftar securityContext.sysctls di tingkat pod, yang memungkinkan kubelet menerapkan sysctl bernamespace tanpa memberi hak istimewa ke kontainer mana pun. Ia hanya mencakup nama di daftar izin klaster. Apakah net.ipv4.ip_forward ada di daftar itu bergantung pada cara kubelet dikonfigurasi, dan pod yang meminta sysctl di luarnya ditolak saat admission atau tersangkut di CreateContainerConfigError selagi sandbox dicoba ulang. Periksa daftar izin sebelum menganggap bidang itu rusak.
Sebelum membuat salah satu pendekatan dengan tangan, lihat apakah chart sudah mengekspos sakelarnya, sering kali sebagai sesuatu seperti ipForwardInitContainer: true. Memakai nilai chart menjaga berkas override Anda tetap kecil dan bertahan saat peningkatan berikutnya, yang tidak dilakukan suntingan Deployment yang ditambal tangan.
Paruh kedua: jalur balik dan kebijakan
Penerusan menyala itu perlu, bukan cukup. Jika klien memakai kumpulan privat yang tidak dirutekan oleh jaringan klaster, balasan tidak menemukan jalan kembali ke terowongan, dan pod perlu menyamarkan lalu lintas itu menuju tujuannya.
Kebijakan berada di atasnya. Objek NetworkPolicy dan aturan firewall awan dievaluasi terhadap alamat sumber yang dibawa paket setelah translasi, jadi aturan yang ditulis untuk kumpulan klien bisa diam-diam berhenti cocok begitu penyamaran diaktifkan.
Ketika klien hanya perlu menjangkau layanan di dalam klaster, mengakhiri VPN di VIP layanan adalah rancangan yang lebih kecil daripada merutekan ke jaringan pod. Itu juga menjaga kumpulan klien sepenuhnya di luar tabel perutean CNI.
Mengisolasi lompatan yang gagal dari klien
Bekerjalah ke luar dan berhenti di langkah sunyi pertama. Mulailah dari peer VPN, lalu coba alamat salah satu pod, lalu VIP layanan, dan baru setelah itu tujuan publik. Setiap keberhasilan menggeser batas satu lompatan, dan setiap kegagalan menyebut lapisan yang layak diperiksa. Setelah penerapan apa pun, masuk dengan exec dan baca sysctl lagi, karena pod yang diganti mulai dari bawaan image dan perbaikan yang tidak pernah ada di manifes sudah hilang.
Dokumentasi Kubernetes tentang penggunaan sysctl di klaster mencantumkan nama mana yang dapat disetel melalui konteks keamanan pod, dan itulah tempat pertama yang dilihat ketika admission menolak perubahannya.