Pod OpenVPN dalam Kubernetes tidak memajukan apa-apa? Semak ip_forward
Klien mem-ping pod VPN dan tiada apa di sebaliknya. Namespace mematikan pemajuan, dan pembaikan mesti bertahan melalui admission, permulaan semula dan laluan balik.
Komputer riba anda menunjukkan terowong hijau, log klien melaporkan laluan telah di-push, dan satu-satunya alamat yang menjawab ialah IP terowong pelayan VPN itu sendiri. Ping di sebaliknya mati tidak kira apa yang anda sasarkan, sama ada ClusterIP, alamat pod lain atau nama hos awam. Gabungan itu bersifat diagnostik, bukan kabur: dekapsulasi berfungsi, dan lompatan kedua tidak.
Saya menemui ini pada nod Debian yang menjalankan imej OpenVPN yang dipasang melalui chart, dan terowong itu bahagian yang mudah. Klien mendapat pajakan 10.8.0.x, 10.8.0.1 menjawab, dan 10.96.0.10, perkhidmatan DNS kluster, tamat masa. Tiada apa dalam log pelayan kelihatan tidak sihat, dan itulah sebabnya orang mula menulis semula peraturan iptables yang tidak pernah perlu mereka sentuh.
Pod VPN ialah penghala, dan wajar dikatakan terus. Paket yang disulitkan tiba, dibuka dalam namespace rangkaian pod itu sendiri, dan kemudian mesti keluar melalui antara muka lain. Linux menolak langkah kedua itu melainkan pemajuan didayakan di dalam namespace yang sama.
Apa yang klien boleh dan tidak boleh capai
Alamat yang menjawab milik hujung terowong, dan proses VPN memilikinya secara setempat, jadi pemajuan tidak terlibat sama sekali. Segala-galanya, termasuk pod lain, VIP perkhidmatan atau internet, memerlukan kernel untuk memindahkan paket dari tun0 ke eth0. Apabila pemindahan itu ditolak, gejalanya ialah kesenyapan seragam dan bukan penolakan, kerana tiada apa yang menghasilkan ralat ICMP kembali ke bawah terowong. Anda mendapat tamat masa, bukan mesej tidak dapat dicapai, dan itulah petunjuk bahawa tiada siapa yang menghalakan sama sekali.
Dua minit pengelasan menyempitkan lapisan. Jika nama DNS gagal manakala ping mentah ke IP perkhidmatan berjaya, masalahnya ialah paip DNS, bukan pemajuan. Jika setiap destinasi di sebalik alamat rakan tamat masa, termasuk IP kosong, mulakan dari namespace.
Baca tetapan di dalam namespace
Setiap pod mendapat namespace rangkaiannya sendiri, dan net.ipv4.ip_forward ialah sysctl bagi setiap namespace. Menukarnya pada nod tidak memberitahu apa-apa tentang kontena, dan ia cara yang boleh dipercayai untuk menghabiskan petang pada mesin yang salah.
kubectl exec -it deploy/openvpn -- sysctl net.ipv4.ip_forward
# net.ipv4.ip_forward = 0
Sifar mengesahkan diagnosis. Nilai itu juga tidak diwarisi daripada konfigurasi masa jalan nod: ia bermula dari lalai imej setiap kali kontena dicipta. Pembaikan yang digunakan secara manual dengan kubectl exec ... sysctl -w kerana itu hilang pada permulaan semula seterusnya dan kembali sebagai kerosakan yang kelihatan berselang-seli.
Mendayakannya supaya manifes mengekalkannya
Pilihan yang tahan lama ialah kontena init yang berjalan dalam sandbox pod yang sama dan menulis nilai itu sebelum kontena VPN bermula. Kontena dalam pod berkongsi namespace rangkaian, jadi tetapan itu terbawa ke kontena 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 dibantah oleh penyemak, dan mereka betul. Menulis sysctl memerlukan sama ada keistimewaan atau keupayaan berskup sempit, dan kluster yang menjalankan Pod Security Standard terhad boleh menolak kontena init berkeistimewaan terus. Jika admission menolak pod, anda mengetahuinya semasa penciptaan, yang sekurang-kurangnya jujur dan mudah dibaca.
Alternatif yang lebih bersih ialah senarai securityContext.sysctls pada peringkat pod, yang membolehkan kubelet menggunakan sysctl bernamespace tanpa memberikan keistimewaan kepada mana-mana kontena. Ia hanya meliputi nama dalam senarai benaran kluster. Sama ada net.ipv4.ip_forward ada dalam senarai itu bergantung pada cara kubelet dikonfigurasikan, dan pod yang meminta sysctl di luarnya ditolak semasa admission atau tersangkut dalam CreateContainerConfigError sementara sandbox dicuba semula. Semak senarai benaran sebelum anda menganggap medan itu rosak.
Sebelum membina mana-mana pendekatan secara manual, lihat sama ada chart sudah mendedahkan suis itu, selalunya sebagai sesuatu seperti ipForwardInitContainer: true. Menggunakan nilai chart memastikan fail override anda kecil dan bertahan semasa peningkatan seterusnya, yang tidak dilakukan oleh suntingan Deployment yang ditampal secara manual.
Separuh kedua: laluan balik dan dasar
Pemajuan dihidupkan adalah perlu, bukan memadai. Jika klien menggunakan kumpulan peribadi yang rangkaian kluster tiada laluan ke sana, balasan tidak menemui jalan balik ke dalam terowong, dan pod perlu menyamarkan trafik itu ke arah destinasinya.
Dasar terletak di atasnya. Objek NetworkPolicy dan peraturan tembok api awan dinilai terhadap alamat sumber yang dibawa paket selepas terjemahan, jadi peraturan yang ditulis untuk kumpulan klien boleh berhenti sepadan secara senyap apabila penyamaran didayakan.
Apabila klien hanya perlu mencapai perkhidmatan di dalam kluster, menamatkan VPN pada VIP perkhidmatan ialah reka bentuk yang lebih kecil daripada menghalakan ke rangkaian pod. Ia juga memastikan kumpulan klien di luar jadual penghalaan CNI sepenuhnya.
Mengasingkan lompatan yang gagal daripada klien
Bekerja ke luar dan berhenti pada langkah senyap yang pertama. Mulakan dengan rakan VPN, kemudian cuba alamat mana-mana pod, kemudian VIP perkhidmatan, dan hanya selepas itu destinasi awam. Setiap kejayaan menggerakkan sempadan satu lompatan, dan setiap kegagalan menamakan lapisan yang wajar diperiksa. Selepas mana-mana pelaksanaan, masuk dengan exec dan baca sysctl sekali lagi, kerana pod yang diganti bermula dari lalai imej dan pembaikan yang tidak pernah ada dalam manifes sudah hilang.
Dokumentasi Kubernetes tentang penggunaan sysctl dalam kluster menyenaraikan nama yang boleh ditetapkan melalui konteks keselamatan pod, dan itulah tempat pertama untuk dilihat apabila admission menolak perubahan itu.