Dokumen ini menjelaskan cara mengonfigurasi Service Mesh agar mempertahankan IP sumber client saat layanan Anda diakses.
Prasyarat
-
Anda memiliki instans ASM Edisi Enterprise atau Ultimate versi 1.15 atau yang lebih baru. Untuk informasi selengkapnya, lihat Create an ASM instance dan Upgrade an ASM instance.
Kluster ACK yang dikelola telah dibuat. Untuk informasi selengkapnya, lihat Create an ACK managed cluster.
Gerbang masuk telah diterapkan. Untuk informasi selengkapnya, lihat Create an ingress gateway.
-
Anda terhubung ke kluster menggunakan kubectl. Untuk informasi selengkapnya, lihat Memperoleh file kubeconfig kluster dan menggunakan kubectl untuk terhubung ke kluster.
Informasi latar belakang
IP sumber client digunakan dalam berbagai skenario, termasuk:
-
Kontrol akses aplikasi: Misalnya, banyak aplikasi menerapkan otentikasi tambahan ketika pengguna masuk dari wilayah yang berbeda, yang memerlukan informasi IP asli client.
-
Afinitas sesi sederhana: Anda dapat melakukan load balancing berbasis IP sumber untuk meneruskan permintaan dari client yang sama ke instans layanan yang sama.
-
Pencatatan log akses dan pemantauan: Log akses dan metrik pemantauan yang mencantumkan alamat sumber sebenarnya membantu developer menganalisis traffic dan mengumpulkan statistik.
Load balancer cloud seperti Server Load Balancer (SLB) dapat meneruskan IP sumber client ke layanan backend. Istio juga seharusnya menyediakan kemampuan ini. Namun, saat Anda menggunakan Istio, proxy sidecar disuntikkan ke setiap Pod. Proxy ini mengintersepsi semua traffic inbound dan meneruskannya ke aplikasi Anda melalui koneksi lokal (127.0.0.1). Akibatnya, aplikasi Anda tidak dapat melihat IP sumber client yang sebenarnya.
Terapkan aplikasi contoh
-
Terapkan aplikasi sleep.
-
Buat file bernama sleep.yaml dengan konten berikut.
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: true -
Jalankan perintah berikut untuk menerapkan aplikasi sleep.
kubectl -n default apply -f sleep.yaml
-
-
Terapkan aplikasi httpbin.
-
Buat file bernama httpbin.yaml dengan konten berikut.
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: 8000 -
Jalankan perintah berikut untuk menerapkan aplikasi httpbin.
kubectl -n default apply -f httpbin.yaml
-
Skema 1: Traffic timur-barat
Langkah 1: Verifikasi perilaku default IP sumber client
Di Istio, proxy sidecar untuk setiap layanan mengintersepsi semua traffic timur-barat. Proxy ini kemudian meneruskan permintaan ke kontainer aplikasi, sehingga alamat sumber yang dilihat aplikasi adalah alamat loopback proxy tersebut, yaitu 127.0.0.6.
-
Jalankan perintah berikut untuk memeriksa status Pod.
kubectl -n default get pods -o wideOutput yang diharapkan:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES httpbin-c85bdb469-4ll2m 2/2 Running 0 3m22s 172.17.X.XXX cn-hongkong.10.0.0.XX <none> <none> sleep-8f764df66-q7dr2 2/2 Running 0 3m9s 172.17.X.XXX cn-hongkong.10.0.0.XX <none> <none>Output menunjukkan 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/ipOutput yang diharapkan:
{ "origin": "127.0.0.6" }Output menunjukkan bahwa alamat sumber permintaan yang diterima oleh aplikasi httpbin adalah alamat proxy Envoy
127.0.0.6, bukan alamat aplikasi sleep. -
Konfirmasi bahwa alamat IP sumber adalah 127.0.0.6 dengan memeriksa informasi socket.
-
Masuk ke kontainer httpbin dan jalankan perintah berikut untuk menginstal netstat.
apt update & apt install net-tools -
Keluar dari kontainer httpbin dan jalankan perintah berikut untuk melihat informasi tentang port 8000.
kubectl -n default exec -it deploy/httpbin -c httpbin -- netstat -ntp | grep 8000Output yang diharapkan:
tcp 0 0 172.17.X.XXX:8000 127.0.0.6:42691 TIME_WAIT -Output menunjukkan bahwa alamat IP sumber adalah
127.0.0.6.
-
-
Lihat isi log akses di Pod httpbin.
Berikut adalah contoh entri log terformat:
{ "trace_id":null, "bytes_received":0, "upstream_host":"172.17.X.XXX:8000", "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:8000", "requested_server_name":"outbound_.8000_._.httpbin.default.svc.cluster.local" }Log tersebut menunjukkan informasi berikut:
-
"downstream_remote_address":"172.17.X.XXX:56160": Alamat aplikasi sleep. -
"downstream_local_address":"172.17.X.XXX:8000": Alamat tujuan yang diakses oleh aplikasi sleep. -
"upstream_local_address":"127.0.0.6:42169": Alamat lokal yang digunakan proxy Envoy httpbin untuk terhubung ke aplikasi httpbin. Pada titik ini, IP sumber yang dilihat aplikasi adalah127.0.0.6. -
"upstream_host":"172.17.X.XXX:8000": Alamat tujuan yang diakses oleh proxy Envoy httpbin.
-
Langkah 2: Konfigurasi pelestarian IP sumber
Metode 1: Gunakan mode TPROXY
Konfigurasikan penerapan httpbin untuk menggunakan mode intersepsi transparan TPROXY.
-
Jalankan perintah berikut untuk memodifikasi penerapan 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/ipOutput yang diharapkan:
{ "origin": "172.17.X.XXX" }Output menunjukkan bahwa aplikasi httpbin dapat memperoleh alamat IP sebenarnya dari aplikasi sleep.
-
Jalankan perintah berikut untuk melihat informasi tentang port 8000.
CatatanSetelah Pod direstart, Anda harus menginstal ulang netstat.
kubectl -n default exec -it deploy/httpbin -c httpbin -- netstat -ntp | grep 8000Output yang diharapkan:
tcp 0 0 172.17.X.XXX:8000 172.17.X.XXX:36728 ESTABLISHED -Output menunjukkan bahwa alamat IP sumber adalah
172.17.X.XXX. -
Lihat isi log akses di Pod httpbin.
Berikut adalah contoh entri log terformat:
{ "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:8000", "duration":1, "upstream_host":"172.17.X.XXX:8000", "istio_policy_status":null, "upstream_local_address":"172.17.X.XXX:46129", "x_forwarded_for":null }Log tersebut menunjukkan informasi berikut:
-
"downstream_remote_address":"172.17.X.XXX:39058": Alamat aplikasi sleep. -
"downstream_local_address":"172.17.X.XXX:8000": Alamat tujuan yang diakses oleh aplikasi sleep. -
"upstream_local_address":"172.17.X.XXX:46129": Alamat lokal yang digunakan proxy Envoy httpbin untuk terhubung ke aplikasi httpbin, yaitu alamat IP aplikasi sleep. -
"upstream_host":"172.17.X.XXX:8000": Alamat tujuan yang diakses oleh proxy Envoy httpbin.
-
Metode 2: Gunakan header XFF
Konfigurasi berikut membuat proxy sidecar di sisi server menambahkan header X-Forwarded-For (XFF) ke permintaan inbound. Proxy mengatur nilai header ini ke alamat IP asli client sebelum meneruskan permintaan ke aplikasi. Metode ini tidak memiliki batasan sistem operasi, tetapi memerlukan aplikasi Anda untuk membaca IP sumber client dari header X-Forwarded-For (XFF).
-
Terapkan FilterEnvoy berikut ke instans ASM menggunakan templat FilterEnvoy. Untuk informasi selengkapnya, lihat Create an Envoy filter by using an Envoy filter template.
apiVersion: networking.istio.io/v1alpha3 kind: EnvoyFilter metadata: name: enable-xff-for-sidecar-inbound namespace: istio-system # Ubah ini ke namespace tempat gerbang Anda 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: true -
Jalankan perintah berikut untuk mengirim permintaan dari kontainer sleep.
kubectl -n default exec -it deploy/sleep -c sleep -- curl http://httpbin:8000/ip -
Output yang diharapkan:
{ "origin": "172.17.X.XXX" }Output menunjukkan bahwa httpbin menerima alamat IP sebenarnya dari aplikasi sleep. Aplikasi httpbin dapat melakukan hal ini karena dirancang untuk membaca IP sumber dari header X-Forwarded-For (XFF), yang kini ditambahkan oleh proxy sidecar. Metode ini tidak akan berfungsi jika aplikasi Anda tidak dapat membaca header XFF.
Skema 2: Traffic utara-selatan
Untuk traffic utara-selatan, permintaan mengalir dari client, melalui load balancer dan gerbang masuk Istio, menuju layanan backend. Hop tambahan melalui gerbang masuk ini membuat pelestarian IP sumber client menjadi lebih kompleks. Bagian berikut menjelaskan cara mengonfigurasi dan memverifikasi pelestarian IP sumber untuk permintaan HTTP dan HTTPS.
Permintaan HTTP
Tanpa pelestarian IP sumber
-
Buat file bernama http-demo.yaml dengan konten berikut untuk mengakses aplikasi httpbin melalui 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: 8000 -
Jalankan perintah berikut untuk menerapkan gerbang dan VirtualService.
kubectl -n default apply -f http-demo.yaml -
Jalankan perintah berikut untuk mengakses aplikasi httpbin melalui gerbang masuk.
export GATEWAY_URL=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}') curl http://$GATEWAY_URL:80/ipOutput yang diharapkan:
{ "origin": "10.0.0.93" }Output menunjukkan bahwa alamat IP yang dikembalikan adalah alamat node Kubernetes.
-
Lihat log akses gerbang masuk.
Berikut adalah contoh entri 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:8000", "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 }Log tersebut menunjukkan informasi berikut:
-
"downstream_remote_address":"10.0.0.93:5899": Bukan IP sumber asli client. -
"downstream_local_address":"172.17.X.XXX:80": Alamat Pod gerbang masuk. -
"upstream_local_address":"172.17.X.XXX:54322": Alamat IP Pod gerbang masuk dipertahankan, tetapi nomor port diubah. -
"upstream_host":"172.17.X.XXX:8000": Alamat Pod httpbin.
-
With source IP preservation
-
Atur kebijakan traffic eksternal ke Local. (Anda dapat melewati langkah ini untuk kluster yang menggunakan mode jaringan Terway.)
-
Masuk ke Konsol ASM. Di panel navigasi kiri, pilih .
-
Pada halaman Mesh Management, klik nama instans ASM. Di panel navigasi kiri, pilih .
-
Pada halaman Ingress Gateway, klik View YAML di sebelah kanan gerbang yang dituju.
-
Di kotak dialog Edit, temukan bagian spec, atur bidang externalTrafficPolicy ke Local, lalu klik OK.
spec: affinity: {} autoCreateGatewayYaml: false clusterIds: - cf0243f2c3009406xxx compression: {} cpu: {} dnsPolicy: ClusterFirst externalTrafficPolicy: Local gatewayType: ingress
-
-
Jalankan perintah berikut untuk mengakses aplikasi httpbin melalui gerbang masuk.
curl http://$GATEWAY_URL:80/ipOutput yang diharapkan:
{ "origin": "120.244.xxx.xxx" }Output menunjukkan bahwa alamat IP yang dikembalikan adalah IP sumber client yang sebenarnya.
-
Lihat log akses gerbang masuk.
Berikut adalah contoh entri 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 }Log tersebut menunjukkan informasi berikut:
-
"downstream_remote_address":"120.244.XXX.XXX:28504": Alamat sumber client, sesuai harapan. -
"downstream_local_address":"172.17.X.XXX:80": Alamat Pod gerbang masuk. -
"upstream_local_address":"172.17.X.XXX:57498": Alamat Pod gerbang masuk dipertahankan, tetapi nomor port diubah. -
"upstream_host":"172.17.X.XXX:80": Alamat Pod httpbin.
-
Permintaan HTTPS
Karena bagian sebelumnya telah menjelaskan permintaan HTTP, bagian ini hanya fokus pada konfigurasi dan verifikasi untuk permintaan HTTPS.
-
Buat file bernama https-demo.yaml dengan konten berikut untuk mengakses aplikasi httpbin melalui 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: 8000 -
Jalankan perintah berikut untuk menerapkan gerbang dan VirtualService.
kubectl -n default apply -f https-demo.yaml -
Jalankan perintah berikut untuk mengakses aplikasi httpbin melalui gerbang masuk.
export GATEWAY_URL=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}') curl -k https://$GATEWAY_URL:443/ipOutput yang diharapkan:
{ "origin": "120.244.XXX.XXX" }Output menunjukkan bahwa alamat IP yang dikembalikan adalah IP sumber client yang sebenarnya.