Tema ini menjelaskan cara aplikasi server dapat memperoleh dan mempertahankan alamat IP sumber klien saat mengakses layanan dalam lingkungan Service Mesh.
Prasyarat
Diperlukan instans ASM Edisi Perusahaan atau Edisi Ultimate dengan versi 1.15 atau lebih baru. Untuk informasi lebih lanjut, lihat Buat instans ASM dan Tingkatkan instans ASM.
Kluster ACK yang dikelola telah dibuat. Untuk informasi lebih lanjut, lihat Buat kluster ACK yang dikelola.
Gerbang masuk telah diterapkan. Untuk informasi lebih lanjut, lihat Buat gerbang masuk.
Kluster terhubung melalui kubectl. Untuk informasi lebih lanjut, lihat Dapatkan file KubeConfig kluster dan hubungkan ke kluster menggunakan kubectl.
Informasi latar belakang
Alamat IP asal banyak digunakan dalam berbagai skenario, termasuk kasus penggunaan tipikal berikut:
Kontrol akses aplikasi: Misalnya, banyak aplikasi memberlakukan autentikasi tambahan ketika mendeteksi bahwa pengguna masuk dari wilayah berbeda. Hal ini dapat dicapai dengan memperoleh alamat IP asal.
Persistensi sesi sederhana: Anda dapat melakukan penyeimbangan beban berdasarkan alamat IP sumber sesuai dengan alamat klien. Dengan cara ini, permintaan dari klien yang sama diteruskan ke instans layanan yang sama.
Log akses dan statistik pemantauan: Log akses dan metrik yang berisi alamat IP asal membantu pengembang menganalisis statistik.
Server Load Balancer berbasis cloud juga mendukung pengiriman IP sumber klien ke layanan backend. Istio harus menyediakan kemampuan bagi aplikasi untuk memperoleh alamat IP asal. Namun, saat menggunakan Istio, setelah Sidecar proxy disuntikkan ke pod, semua lalu lintas masuk dialihkan dari Envoy. Saat ini, Envoy mengirimkan lalu lintas ke aplikasi yang terikat pada alamat lokal (127.0.0.1), sehingga aplikasi tidak dapat melihat alamat IP asal sebenarnya.
Terapkan aplikasi contoh
Terapkan aplikasi sleep.
Gunakan konten berikut untuk membuat sleep.yaml.
apiVersion: v1 kind: ServiceAccount metadata: name: sleep --- apiVersion: v1 kind: Service metadata: name: sleep labels: app: sleep service: sleep spec: ports: - port: 80 name: http selector: app: sleep --- apiVersion: apps/v1 kind: Deployment metadata: name: sleep spec: replicas: 1 selector: matchLabels: app: sleep template: metadata: labels: app: sleep spec: terminationGracePeriodSeconds: 0 serviceAccountName: sleep containers: - name: sleep image: curlimages/curl command: ["/bin/sleep", "3650d"] imagePullPolicy: IfNotPresent volumeMounts: - mountPath: /etc/sleep/tls name: secret-volume volumes: - name: secret-volume secret: secretName: sleep-secret optional: trueJalankan perintah berikut untuk menerapkan aplikasi sleep.
kubectl -n default apply -f sleep.yaml
Terapkan aplikasi httpbin.
Gunakan konten berikut untuk membuat httpbin.yaml.
apiVersion: v1 kind: Service metadata: name: httpbin labels: app: httpbin spec: ports: - name: http port: 8000 selector: app: httpbin --- apiVersion: apps/v1 kind: Deployment metadata: name: httpbin spec: replicas: 1 selector: matchLabels: app: httpbin version: v1 template: metadata: labels: app: httpbin version: v1 spec: containers: - image: docker.io/citizenstig/httpbin imagePullPolicy: IfNotPresent name: httpbin ports: - containerPort: 8000Jalankan perintah berikut untuk menerapkan aplikasi httpbin.
kubectl -n default apply -f httpbin.yaml
Skenario 1: Lalu lintas timur-barat
Langkah 1: Verifikasi alamat IP sumber klien yang dilihat oleh server dalam konfigurasi default
Dalam Istio, ketika layanan timur-barat diakses, semua lalu lintas masuk dan keluar dari layanan dicegat dan diproksi oleh Envoy karena injeksi Sidecar. Kemudian, Envoy meneruskan permintaan ke aplikasi. Oleh karena itu, alamat sumber permintaan yang diterima oleh aplikasi adalah alamat akses Envoy 127.0.0.6.
Jalankan perintah berikut untuk memeriksa status pod.
kubectl -n default get pods -o wideHasil yang diharapkan:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES httpbin-c85bdb469-4ll2m 2/2 Berjalan 0 3m22s 172.17.X.XXX cn-hongkong.10.0.0.XX <none> <none> sleep-8f764df66-q7dr2 2/2 Berjalan 0 3m9s 172.17.X.XXX cn-hongkong.10.0.0.XX <none> <none>Dari hasil yang diharapkan, Anda dapat melihat bahwa alamat aplikasi sleep adalah
172.17.X.XXX.Jalankan perintah berikut untuk mengirim permintaan dari kontainer sleep.
kubectl -n default exec -it deploy/sleep -c sleep -- curl http://httpbin:8000/ipHasil yang diharapkan:
{ "origin": "127.0.0.6" }Dari hasil yang diharapkan, Anda dapat melihat bahwa alamat sumber permintaan yang diterima oleh aplikasi httpbin adalah alamat akses Envoy
127.0.0.6, bukan alamat aplikasi sleep.Konfirmasikan apakah alamat IP sumber adalah 127.0.0.6 dari informasi soket.
Masuk ke kontainer httpbin dan jalankan perintah berikut untuk menginstal netstat.
apt update & apt install net-toolsKeluar dari kontainer httpbin dan jalankan perintah berikut untuk melihat informasi berjalan berdasarkan port 80.
kubectl -n default exec -it deploy/httpbin -c httpbin -- netstat -ntp | grep 80Hasil yang diharapkan:
tcp 0 0 172.17.X.XXX:80 127.0.0.6:42691 TIME_WAIT -Dari hasil yang diharapkan, Anda dapat melihat bahwa alamat IP sumber adalah
127.0.0.6.
Lihat isi log proksi dalam pod httpbin.
Contoh log yang diformat adalah sebagai berikut:
{ "trace_id":null, "bytes_received":0, "upstream_host":"172.17.X.XXX:80", "authority":"httpbin:8000", "downstream_remote_address":"172.17.X.XXX:56160", "upstream_service_time":"1", "upstream_transport_failure_reason":null, "istio_policy_status":null, "path":"/ip", "bytes_sent":28, "request_id":"4501a50a-dab0-44c9-b52c-2a4f425a****", "protocol":"HTTP/1.1", "method":"GET", "duration":1, "start_time":"2022-11-22T16:09:30.394Z", "user_agent":"curl/7.86.0-DEV", "upstream_local_address":"127.0.0.6:42169", "response_flags":"-", "route_name":"default", "response_code":200, "upstream_cluster":"inbound|80||", "x_forwarded_for":null, "downstream_local_address":"172.17.X.XXX:80", "requested_server_name":"outbound_.8000_._.httpbin.default.svc.cluster.local" }Dari log, Anda dapat memperoleh informasi berikut:
"downstream_remote_address":"172.17.X.XXX:56160": alamat sleep."downstream_local_address":"172.17.X.XXX:80": alamat tujuan yang diakses oleh sleep."upstream_local_address":"127.0.0.6:42169": alamat lokal Envoy httpbin yang terhubung ke httpbin (alamat IP sumber yang diperoleh saat ini adalah127.0.0.6)."upstream_host":"172.17.X.XXX:80": alamat tujuan yang diakses oleh Envoy httpbin.
Langkah 2: Konfigurasikan service mesh untuk memungkinkan server memperoleh alamat IP sumber klien yang benar
Metode 1: Pertahankan alamat IP sumber klien melalui mode intersepsi transparan TPROXY (berlaku untuk sistem operasi non-CentOS)
Ubah penyebaran aplikasi httpbin untuk menggunakan TPROXY sebagai mode intersepsi lalu lintas masuk.
Jalankan perintah berikut untuk memodifikasi penyebaran aplikasi httpbin.
kubectl patch deployment -n default httpbin -p '{"spec":{"template":{"metadata":{"annotations":{"sidecar.istio.io/interceptionMode":"TPROXY"}}}}}'Jalankan perintah berikut untuk mengirim permintaan dari kontainer sleep.
kubectl -n default exec -it deploy/sleep -c sleep -- curl http://httpbin:8000/ipHasil yang diharapkan:
{ "origin": "172.17.X.XXX" }Dari hasil yang diharapkan, Anda dapat melihat bahwa httpbin dapat memperoleh alamat IP aktual sleep.
Jalankan perintah berikut untuk melihat informasi berjalan berdasarkan port 80.
CatatanSetelah pod di-restart, Anda perlu menginstal ulang netstat.
kubectl -n default exec -it deploy/httpbin -c httpbin -- netstat -ntp | grep 80Hasil yang diharapkan:
tcp 0 0 172.17.X.XXX:80 172.17.X.XXX:36728 ESTABLISHED -Dari hasil yang diharapkan, Anda dapat melihat bahwa alamat IP sumber adalah
172.17.X.XXX.Lihat isi log proksi dalam pod httpbin.
Contoh log yang diformat adalah sebagai berikut:
{ "route_name":"default", "bytes_received":0, "trace_id":null, "request_id":"1ccabe60-63cf-469b-8565-99cac546****", "upstream_cluster":"inbound|80||", "response_flags":"-", "protocol":"HTTP/1.1", "upstream_transport_failure_reason":null, "requested_server_name":"outbound_.8000_._.httpbin.default.svc.cluster.local", "response_code":200, "user_agent":"curl/7.86.0-DEV", "start_time":"2022-11-22T16:03:32.803Z", "path":"/ip", "authority":"httpbin:8000", "bytes_sent":31, "downstream_remote_address":"172.17.X.XXX:39058", "upstream_service_time":"1", "method":"GET", "downstream_local_address":"172.17.X.XXX:80", "duration":1, "upstream_host":"172.17.X.XXX:80", "istio_policy_status":null, "upstream_local_address":"172.17.X.XXX:46129", "x_forwarded_for":null }Dari log, Anda dapat memperoleh informasi berikut:
"downstream_remote_address":"172.17.X.XXX:39058": alamat sleep."downstream_local_address":"172.17.X.XXX:80": alamat tujuan yang diakses oleh sleep."upstream_local_address":"172.17.X.XXX:46129": alamat lokal Envoy httpbin yang terhubung ke httpbin (alamat IP sleep)."upstream_host":"172.17.X.XXX:80": alamat tujuan yang diakses oleh Envoy httpbin.
Metode 2: Peroleh alamat IP sumber klien melalui header permintaan XFF
Anda dapat menggunakan konfigurasi berikut untuk membuat Sidecar proksi mesh server menambahkan header permintaan X-Forwarded-For ke permintaan sebelum meneruskan permintaan masuk ke aplikasi. Nilai header permintaan diatur ke alamat IP klien sebenarnya. Metode ini tidak memiliki batasan pada sistem operasi node, tetapi memerlukan aplikasi untuk dapat mengidentifikasi dan memperoleh alamat IP sumber klien yang dibawa oleh header permintaan XFF.
Rujuk ke Buat filter Envoy menggunakan templat filter Envoy untuk menerapkan EnvoyFilter berikut ke instans ASM melalui templat EnvoyFilter.
apiVersion: networking.istio.io/v1alpha3 kind: EnvoyFilter metadata: name: enable-xff-for-sidecar-inbound namespace: istio-system # Ubah namespace ini ke namespace tempat gateway berada labels: asm-system: "true" provider: "asm" spec: configPatches: - applyTo: NETWORK_FILTER match: proxy: proxyVersion: "^1.*" context: SIDECAR_INBOUND listener: name: "virtualInbound" filterChain: filter: name: "envoy.filters.network.http_connection_manager" patch: operation: MERGE value: typed_config: "@type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager" use_remote_address: trueJalankan perintah berikut untuk mengirim permintaan dari kontainer sleep.
kubectl -n default exec -it deploy/sleep -c sleep -- curl http://httpbin:8000/ipHasil yang diharapkan:
{ "origin": "172.17.X.XXX" }Dari hasil yang diharapkan, Anda dapat melihat bahwa httpbin dapat memperoleh alamat IP aktual sleep. Perhatikan bahwa alamat IP sumber klien diteruskan ke aplikasi httpbin oleh Sidecar melalui header permintaan X-Forwarded-For. Aplikasi httpbin mendukung pemerolehan alamat IP sumber klien dari header permintaan X-Forwarded-For, sehingga dapat membaca alamat IP sumber klien dengan benar. Jika aplikasi tidak memiliki kemampuan untuk memperoleh alamat IP sumber dari header permintaan X-Forwarded-For, metode ini tidak berlaku.
Skenario 2: Lalu lintas utara-selatan
Untuk lalu lintas utara-selatan, klien pertama kali meminta Server Load Balancer, yang kemudian meneruskan permintaan ke Istio ingressgateway, dan kemudian ke layanan backend. Karena adanya ingressgateway tambahan di tengah, memperoleh alamat IP sumber klien menjadi lebih kompleks. Bagian berikut menjelaskan cara mengonfigurasi dan memverifikasi pelestarian alamat IP sumber untuk permintaan protokol HTTP dan HTTPS.
Permintaan protokol HTTP
Without Source IP Preservation
Gunakan konten berikut untuk membuat http-demo.yaml untuk mengakses httpbin menggunakan protokol HTTP.
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: httpbin-gw-httpprotocol namespace: default spec: selector: istio: ingressgateway servers: - hosts: - '*' port: name: http number: 80 protocol: HTTP --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: httpbin namespace: default spec: gateways: - httpbin-gw-httpprotocol hosts: - '*' http: - route: - destination: host: httpbin port: number: 8000Jalankan perintah berikut untuk menerapkan gateway dan layanan virtual.
kubectl -n default apply -f http-demo.yamlJalankan perintah berikut untuk mengakses httpbin melalui ingressgateway.
export GATEWAY_URL=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}') curl http://$GATEWAY_URL:80/ipHasil yang diharapkan:
{ "origin": "10.0.0.93" }Dari hasil yang diharapkan, Anda dapat melihat bahwa alamat IP yang dikembalikan adalah alamat node kluster Kubernetes.
Lihat log akses ingressgateway.
Contoh log:
{ "upstream_service_time":"1", "response_code":200, "protocol":"HTTP/1.1", "bytes_sent":28, "upstream_cluster":"outbound|8000||httpbin.default.svc.cluster.local", "start_time":"2022-11-23T03:29:20.017Z", "istio_policy_status":null, "upstream_transport_failure_reason":null, "trace_id":null, "route_name":null, "request_id":"292903be-a889-4d5d-83a0-ab1f5d1a****", "method":"GET", "upstream_host":"172.17.X.XXX:80", "duration":1, "path":"/ip", "downstream_local_address":"172.17.X.XXX:80", "authority":"47.242.XXX.XX", "user_agent":"curl/7.79.1", "downstream_remote_address":"10.0.0.93:5899", "upstream_local_address":"172.17.X.XXX:54322", "requested_server_name":null, "x_forwarded_for":"10.0.0.93", "response_flags":"-", "bytes_received":0 }Dari log, Anda dapat memperoleh informasi berikut:
"downstream_remote_address":"10.0.0.93:5899": bukan alamat sumber klien sebenarnya."downstream_local_address":"172.17.X.XXX:80": alamat pod ingressgateway."upstream_local_address":"172.17.X.XXX:54322": alamat pod ingressgateway tetap dipertahankan, namun nilai port berubah."upstream_host":"172.17.X.XXX:80": alamat pod httpbin.
With Source IP Preservation
Atur kebijakan lalu lintas eksternal ke Local. (Lewati langkah ini untuk kluster dengan mode jaringan Terway.)
Masuk ke Konsol ASM. Di panel navigasi kiri, pilih .
Di halaman Mesh Management, klik nama instans ASM. Di panel navigasi kiri, pilih .
Di halaman Ingress Gateway, klik View YAML di sebelah kanan gateway target.
Di kotak dialog Edit, di bawah bidang spec, atur bidang externalTrafficPolicy ke Local, lalu klik OK.

Jalankan perintah berikut untuk mengakses httpbin melalui ingressgateway.
curl http://$GATEWAY_URL:80/ipHasil yang diharapkan:
{ "origin": "120.244.xxx.xxx" }Dari hasil yang diharapkan, Anda dapat melihat bahwa alamat IP yang dikembalikan adalah alamat IP sumber klien sebenarnya.
Lihat log akses ingressgateway.
Contoh log:
{ "istio_policy_status":null, "upstream_transport_failure_reason":null, "path":"/ip", "x_forwarded_for":"120.244.XXX.XXX", "route_name":null, "method":"GET", "duration":2, "downstream_remote_address":"120.244.XXX.XXX:28504", "bytes_received":0, "upstream_cluster":"outbound|8000||httpbin.default.svc.cluster.local", "bytes_sent":34, "protocol":"HTTP/1.1", "response_flags":"-", "upstream_local_address":"172.17.X.XXX:57498", "upstream_service_time":"2", "request_id":"9c0295d4-e77f-4a3a-b292-e5c58d92****", "start_time":"2022-11-23T03:24:04.413Z", "response_code":200, "trace_id":null, "authority":"47.242.XXX.XX", "user_agent":"curl/7.79.1", "downstream_local_address":"172.17.X.XXX:80", "upstream_host":"172.17.X.XXX:80", "requested_server_name":null }Dari log, Anda dapat memperoleh informasi berikut:
"downstream_remote_address":"120.244.XXX.XXX:28504": alamat sumber klien, sesuai harapan."downstream_local_address":"172.17.X.XXX:80": alamat pod ingressgateway."upstream_local_address":"172.17.X.XXX:57498": alamat pod ingressgateway tetap dipertahankan, namun nilai port berubah."upstream_host":"172.17.X.XXX:80": alamat pod httpbin.
Permintaan protokol HTTPS
Bagian sebelumnya telah menjelaskan secara rinci perbandingan sebelum dan sesudah pengaturan pelestarian IP sumber untuk permintaan protokol HTTP. Oleh karena itu, bagian ini hanya menjelaskan cara mengonfigurasi dan memverifikasi pelestarian IP sumber untuk permintaan protokol HTTPS.
Gunakan konten berikut untuk membuat https-demo untuk mengakses httpbin menggunakan protokol HTTPS.
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: httpbin-gw-https namespace: default spec: selector: istio: ingressgateway servers: - hosts: - '*' port: name: https number: 443 protocol: HTTPS tls: credentialName: myexample-credential mode: SIMPLE --- apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: httpbin-https namespace: default spec: gateways: - httpbin-gw-https hosts: - '*' http: - route: - destination: host: httpbin port: number: 8000Jalankan perintah berikut untuk menerapkan gateway dan layanan virtual.
kubectl -n default apply -f https-demo.yamlJalankan perintah berikut untuk mengakses httpbin melalui ingressgateway.
export GATEWAY_URL=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}') curl -k https://$GATEWAY_URL:443/ipHasil yang diharapkan:
{ "origin": "120.244.XXX.XXX" }Dari hasil yang diharapkan, Anda dapat melihat bahwa alamat IP yang dikembalikan adalah alamat IP sumber klien sebenarnya.