Ketika sebuah aplikasi melakukan bind ke localhost (127.0.0.1) alih-alih 0.0.0.0, Pod lain dalam kluster tidak dapat mengaksesnya—meskipun Service Kubernetes mengekspos port yang sesuai. Topik ini menjelaskan penyebabnya dan menyediakan dua solusi.
Deskripsi masalah
Sebuah aplikasi dalam kluster mendengarkan pada localhost, sehingga Pod lain tidak dapat mengaksesnya melalui Service Kubernetes.
Pola umum binding ke localhost:
| Bahasa | Kode |
|---|---|
| Go | net.Listen("tcp", "localhost:8080") |
| Node.js | http.createServer().listen(8080, "localhost") |
| Python | socket.socket().bind(("localhost", 8083)) |
Penyebab
Setiap Pod di Kubernetes memiliki alamat IP-nya sendiri. Service mengarahkan lalu lintas ke alamat IP Pod tersebut, bukan ke localhost di dalam Pod. Ketika aplikasi melakukan bind ke localhost, aplikasi hanya menerima koneksi melalui antarmuka loopback (127.0.0.1), yang berada dalam namespace jaringan Pod itu sendiri. Akibatnya, lalu lintas yang tiba melalui alamat IP Pod tidak pernah mencapai aplikasi.
Di kluster yang dikelola ASM, proxy sidecar Istio menambahkan lapisan kompleksitas tambahan: proxy tersebut mencegat lalu lintas masuk melalui aturan iptables dan meneruskannya ke aplikasi. Jika aplikasi hanya mendengarkan pada localhost, proxy sidecar tidak dapat mengirimkan lalu lintas ke aplikasi karena penerusan tersebut ditujukan ke alamat IP Pod, bukan ke alamat loopback.
Solusi
Tersedia dua pendekatan:
| Pendekatan | Kapan digunakan |
|---|---|
| Ubah alamat bind | Anda mengontrol kode sumber aplikasi |
| Konfigurasikan resource Sidecar | Anda tidak dapat memodifikasi kode aplikasi |
Solusi 1: Ubah alamat bind
Perbarui kode aplikasi agar mendengarkan pada 0.0.0.0 alih-alih localhost. Dengan demikian, aplikasi akan menerima koneksi pada semua antarmuka jaringan, termasuk alamat IP Pod.
| Bahasa | Sebelum (localhost) | Sesudah (semua antarmuka) |
|---|---|---|
| Go | net.Listen("tcp", "localhost:8080") | net.Listen("tcp", "0.0.0.0:8080") |
| Node.js | http.createServer().listen(8080, "localhost") | http.createServer().listen(8080, "0.0.0.0") |
| Python | socket.socket().bind(("localhost", 8083)) | socket.socket().bind(("0.0.0.0", 8083)) |
Setelah menerapkan kode yang telah diperbarui, verifikasi bahwa Pod lain dapat mengakses aplikasi melalui Service tersebut.
Solusi 2: Konfigurasikan resource Sidecar
Jika modifikasi kode aplikasi tidak memungkinkan, buat resource Istio Sidecar untuk meneruskan lalu lintas masuk ke alamat localhost. Proxy sidecar menerima lalu lintas pada port Service dan mengalihkannya ke 127.0.0.1:<container-port> di dalam Pod.
Prosedur
-
Masuk ke Konsol ASM. Di panel navigasi sebelah kiri, pilih .
-
Pada halaman Mesh Management, klik nama instans ASM. Di panel navigasi sebelah kiri, pilih . Pada halaman yang muncul, klik Create from YAML.
Klik Create from YAML.
Pada halaman Create, pilih namespace dan templat, tempel konfigurasi YAML berikut, lalu klik Create.
apiVersion: networking.istio.io/v1beta1
kind: Sidecar
metadata:
name: localhost-access
namespace: <namespace>
spec:
ingress:
- defaultEndpoint: '127.0.0.1:<container-port>'
port:
name: tcp
number: <service-port>
protocol: TCP
workloadSelector:
labels:
<label-key>: <label-value>Ganti placeholder berikut dengan nilai aktual Anda:
| Placeholder | Deskripsi | Contoh |
|---|---|---|
<namespace> | Namespace tempat aplikasi dideploy | default |
<container-port> | Port tempat aplikasi mendengarkan di localhost | 8080 |
<service-port> | Port yang diekspos oleh Service Kubernetes | 80 |
<label-key>: <label-value> | Label Pod yang mengidentifikasi beban kerja target | app: my-service |
Bidang defaultEndpoint memberi tahu proxy sidecar ke mana lalu lintas masuk harus diteruskan. Mengaturnya ke 127.0.0.1:<container-port> mengarahkan permintaan ke alamat loopback, sesuai dengan lokasi aplikasi yang sedang mendengarkan.
Verifikasi perbaikan
Setelah menerapkan salah satu solusi, uji konektivitas antar-Pod:
# Dari Pod lain, kirim permintaan ke aplikasi melalui Service-nya
kubectl exec -it <test-pod> -- curl http://<service-name>.<namespace>.svc.cluster.local:<service-port>Tanggapan sukses mengonfirmasi bahwa aplikasi dapat dijangkau dari Pod lain.
Jika permintaan gagal, periksa log proxy sidecar untuk mencari error penerusan:
kubectl logs <pod-name> -c istio-proxy