Kubernetes'teki OpenVPN pod'u hiçbir şey iletmiyor mu? ip_forward'ı kontrol edin
İstemciler VPN pod'una ping atıyor ve ötesine hiçbir şey geçmiyor. Namespace'te iletim kapalı ve düzeltme admission, yeniden başlatmalar ve dönüş yolu boyunca ayakta kalmalı.
Dizüstü bilgisayarınız yeşil bir tünel gösteriyor, istemci günlüğü rotaların gönderildiğini bildiriyor ve yanıt veren tek adres VPN sunucusunun kendi tünel IP'si. Ötesine giden ping'ler neyi hedeflerseniz hedefleyin ölüyor; ister ClusterIP, ister başka bir pod'un adresi, ister genel bir ana bilgisayar adı olsun. Bu kombinasyon belirsiz değil, tanılayıcı: kapsül açma çalışıyor ve ikinci atlama çalışmıyor.
Buna chart ile kurulmuş bir OpenVPN imajı çalıştıran Debian düğümünde rastladım ve tünel işin kolay kısmıydı. İstemci 10.8.0.x kiralaması aldı, 10.8.0.1 yanıt verdi ve 10.96.0.10, yani küme DNS hizmeti, zaman aşımına uğradı. Sunucu günlüğünde hiçbir şey hasta görünmüyordu ve insanların hiç dokunmaları gerekmeyen iptables kurallarını yeniden yazmaya başlamasının nedeni tam olarak bu.
VPN pod'u bir yönlendiricidir ve bunu açıkça söylemek gerekir. Şifreli paketler gelir, pod'un kendi ağ namespace'inde açılır ve sonra başka bir arayüzden çıkmalıdır. Linux, iletim tam o namespace içinde etkin değilse bu ikinci adımı reddeder.
İstemcinin ulaşabildiği ve ulaşamadığı şeyler
Yanıt veren adres tünelin uç noktasına aittir ve VPN süreci ona yerel olarak sahiptir, bu yüzden iletim hiç devrede değildir. Geri kalan her şey, başka bir pod, bir hizmet VIP'si veya internet dahil, çekirdeğin paketi tun0 adresinden eth0 adresine taşımasını gerektirir. Bu taşıma reddedildiğinde belirti bir ret değil, tekdüze sessizliktir, çünkü tünelin aşağısına geri hiçbir ICMP hatası üretilmez. Zaman aşımı alırsınız, ulaşılamaz mesajları değil, ve bu kimsenin hiç yönlendirme yapmadığının ipucudur.
İki dakikalık sınıflandırma katmanı daraltır. DNS adları başarısız olurken bir hizmet IP'sine ham ping'ler başarılıysa, sorun iletimde değil, DNS tesisatındadır. Eş adresinin ötesindeki her hedef zaman aşımına uğrarsa, çıplak bir IP dahil, namespace'ten başlayın.
Ayarı namespace'in içinde okuyun
Her pod kendi ağ namespace'ini alır ve net.ipv4.ip_forward her namespace için bir sysctl'dir. Bunu düğümde değiştirmek konteyner hakkında hiçbir şey söylemez ve yanlış makinede bir öğleden sonra geçirmenin güvenilir bir yoludur.
kubectl exec -it deploy/openvpn -- sysctl net.ipv4.ip_forward
# net.ipv4.ip_forward = 0
Sıfır tanıyı doğrular. Değer düğümün çalışma zamanı yapılandırmasından da miras alınmaz: her konteyner oluşturulduğunda imajın varsayılanından başlar. Bu nedenle kubectl exec ... sysctl -w ile elle uygulanan bir düzeltme sonraki yeniden başlatmada kaybolur ve aralıklı görünen bir arıza olarak geri döner.
Manifest'in saklaması için etkinleştirmek
Kalıcı seçenek, aynı pod sandbox içinde çalışan ve değeri VPN konteyneri başlamadan önce yazan bir init konteyneridir. Bir pod'daki konteynerler ağ namespace'ini paylaşır, bu yüzden ayar ana konteynere geçer.
initContainers:
- name: enable-forwarding
image: busybox:1.36
command: ["sysctl", "-w", "net.ipv4.ip_forward=1"]
securityContext:
privileged: true
Tam da privileged: true gözden geçirenlerin karşı çıktığı satırdır ve haklılar. Bir sysctl yazmak ya ayrıcalık ya da dar kapsamlı bir yetenek gerektirir ve kısıtlı Pod Security Standard çalıştıran bir küme ayrıcalıklı bir init konteynerini tümüyle reddedebilir. admission pod'u reddederse bunu oluşturma anında öğrenirsiniz, bu en azından dürüst ve okunması kolaydır.
Daha temiz alternatif, kubelet'in hiçbir konteynere ayrıcalık vermeden namespace'li sysctl uygulamasına izin veren pod düzeyindeki securityContext.sysctls listesidir. Yalnızca kümenin izin listesindeki adları kapsar. net.ipv4.ip_forward bu listede mi, kubelet'in nasıl yapılandırıldığına bağlıdır ve listenin dışında sysctl isteyen bir pod admission'da reddedilir ya da sandbox yeniden denenirken CreateContainerConfigError içinde takılır. Alanın bozuk olduğunu varsaymadan önce izin listesini kontrol edin.
İki yaklaşımdan birini elle kurmadan önce, chart'ın anahtarı zaten sunup sunmadığına bakın, çoğu zaman ipForwardInitContainer: true gibi bir şey olarak. Chart değerini kullanmak override dosyanızı küçük tutar ve sonraki yükseltmeyi atlatır; elle yamalanan Deployment düzenlemeleri bunu yapmaz.
İkinci yarı: dönüş yolu ve politika
İletimin açık olması gereklidir, yeterli değildir. İstemciler küme ağının rotası olmadığı özel bir havuz kullanıyorsa yanıtlar tünele geri yol bulamaz ve pod bu trafiği hedefine doğru maskelemedir.
Politika bunun üzerinde oturur. NetworkPolicy nesneleri ve bulut güvenlik duvarı kuralları, paketin çeviriden sonra taşıdığı kaynak adrese göre değerlendirilir, bu yüzden istemci havuzu için yazılmış bir kural maskeleme etkinleştiğinde sessizce eşleşmeyi bırakabilir.
İstemciler yalnızca küme içindeki hizmetlere ulaşmalıysa, VPN'i hizmetin VIP'sinde sonlandırmak pod ağına yönlendirmekten daha küçük bir tasarımdır. İstemci havuzunu CNI'nin yönlendirme tablosunun tamamen dışında tutar.
Başarısız atlamayı istemciden yalıtmak
Dışa doğru çalışın ve ilk sessiz adımda durun. VPN eşiyle başlayın, sonra bir pod'un adresini deneyin, sonra bir hizmet VIP'sini ve ancak ondan sonra genel bir hedefi. Her başarı sınırı bir atlama kaydırır ve her başarısızlık incelenmeye değer katmanı adlandırır. Herhangi bir dağıtımdan sonra exec ile içeri girin ve sysctl'i yeniden okuyun, çünkü değiştirilen pod imajın varsayılanından başlar ve manifestte hiç bulunmamış bir düzeltme çoktan gitmiştir.
Kubernetes belgeleri bir kümede sysctl kullanımı konusunda hangi adların pod güvenlik bağlamıyla ayarlanabileceğini listeler ve admission değişikliği reddettiğinde ilk bakılacak yer orasıdır.