Bu konu, hizmetlerinize erişim sağlanırken istemci kaynak IP'sinin korunması için Service Mesh yapılandırmasının nasıl yapılacağını açıklar.
Önkoşullar
Sürüm 1,15 veya üzeri bir ASM Enterprise ya da Ultimate Edition örneğiniz bulunmalıdır. Daha fazla bilgi için bkz. ASM örneği oluşturma ve ASM örneğini yükseltme.
Bir ACK yönetilen kümesi oluşturmuş olmalısınız. Daha fazla bilgi için bkz. ACK yönetilen kümesi oluşturma.
Bir giriş ağ geçidi dağıtmış olmalısınız. Daha fazla bilgi için bkz. Giriş ağ geçidi oluşturma.
kubectl kullanarak kümeye bağlı olmalısınız. Daha fazla bilgi için bkz. Kümenin kubeconfig dosyasını alma ve kubectl ile kümeye bağlanma.
Arka plan bilgileri
İstemci kaynak IP'si aşağıdakiler dahil olmak üzere birçok senaryoda kullanılır:
Uygulama erişim kontrolü: Örneğin, birçok uygulama kullanıcı farklı bir bölgeden oturum açtığında ek kimlik doğrulama uygular; bu durum istemcinin orijinal IP'sinin alınmasını gerektirir.
Basit oturum yakınlığı: Aynı istemciden gelen istekleri aynı hizmet örneğine iletmek için kaynak IP tabanlı yük dengeleme yapabilirsiniz.
Erişim günlükleri ve izleme: Gerçek kaynak adresini içeren erişim günlükleri ve izleme ölçümleri, geliştiricilerin trafiği analiz etmesine ve istatistik toplamasına yardımcı olur.
Server Load Balancer (SLB) gibi bulut yük dengeleyiciler, istemci kaynak IP'sini arka uç hizmetlere iletebilir. Istio da bu yeteneği sunmalıdır. Ancak, Istio kullanırken her pod'a bir sidecar proxy enjekte edilir. Bu proxy, tüm gelen trafiği engeller ve yerel bir bağlantı (127.0.0.1) üzerinden uygulamanıza iletir. Sonuç olarak, uygulamanız gerçek istemci kaynak IP'sini göremez.
Örnek uygulamaları dağıtma
-
sleep uygulamasını dağıtın.
-
Aşağıdaki içeriğe sahip sleep.yaml adlı bir dosya oluşturun.
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 -
sleep uygulamasını dağıtmak için aşağıdaki komutu çalıştırın.
kubectl -n default apply -f sleep.yaml
-
-
httpbin uygulamasını dağıtın.
-
Aşağıdaki içeriğe sahip httpbin.yaml adlı bir dosya oluşturun.
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 -
httpbin uygulamasını dağıtmak için aşağıdaki komutu çalıştırın.
kubectl -n default apply -f httpbin.yaml
-
Senaryo 1: Doğu-batı trafiği
1. Adım: Varsayılan istemci kaynak IP davranışını doğrulayın
Istio'da, her hizmetin sidecar proxy'si tüm doğu-batı trafiğini engeller. Bu proxy, istekleri uygulama konteynerine iletir; bu nedenle uygulamanın gördüğü kaynak adresi, proxy'nin loopback adresi olan 127.0.0.6 olur.
-
Pod durumunu kontrol etmek için aşağıdaki komutu çalıştırın.
kubectl -n default get pods -o wideBeklenen çıktı:
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>Çıktı, sleep uygulamasının adresinin
172.17.X.XXXolduğunu gösterir. -
sleep konteynerinden bir istek göndermek için aşağıdaki komutu çalıştırın.
kubectl -n default exec -it deploy/sleep -c sleep -- curl http://httpbin:8000/ipBeklenen çıktı:
{ "origin": "127.0.0.6" }Çıktı, httpbin uygulaması tarafından alınan isteğin kaynak adresinin sleep uygulamasının adresi değil, Envoy proxy adresi olan
127.0.0.6olduğunu gösterir. -
Kaynak IP adresinin 127.0.0.6 olduğunu soket bilgilerini inceleyerek doğrulayın.
-
httpbin konteynerine oturum açın ve netstat yüklemek için aşağıdaki komutu çalıştırın.
apt update & apt install net-tools -
httpbin konteynerinden çıkın ve 8000 bağlantı noktasıyla ilgili bilgileri görüntülemek için aşağıdaki komutu çalıştırın.
kubectl -n default exec -it deploy/httpbin -c httpbin -- netstat -ntp | grep 8000Beklenen çıktı:
tcp 0 0 172.17.X.XXX:8000 127.0.0.6:42691 TIME_WAIT -Çıktı, kaynak IP adresinin
127.0.0.6olduğunu gösterir.
-
-
httpbin pod'undaki erişim günlüğünün içeriğini görüntüleyin.
Aşağıda örnek biçimlendirilmiş bir günlük girişi verilmiştir:
{ "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" }Günlük aşağıdaki bilgileri gösterir:
"downstream_remote_address":"172.17.X.XXX:56160": Sleep uygulamasının adresi."downstream_local_address":"172.17.X.XXX:8000": Sleep uygulamasının eriştiği hedef adres."upstream_local_address":"127.0.0.6:42169": httpbin Envoy proxy'sinin httpbin uygulamasına bağlanmak için kullandığı yerel adres. Bu noktada, uygulamanın gördüğü kaynak IP127.0.0.6olur."upstream_host":"172.17.X.XXX:8000": httpbin Envoy proxy'sinin eriştiği hedef adres.
2. Adım: Kaynak IP korumayı yapılandırın
Yöntem 1: TPROXY modunu kullanma
httpbin dağıtımını TPROXY şeffaf engelleme modunu kullanacak şekilde yapılandırın.
-
httpbin uygulamasının dağıtımını değiştirmek için aşağıdaki komutu çalıştırın.
kubectl patch deployment -n default httpbin -p '{"spec":{"template":{"metadata":{"annotations":{"sidecar.istio.io/interceptionMode":"TPROXY"}}}}}' -
sleep konteynerinden bir istek göndermek için aşağıdaki komutu çalıştırın.
kubectl -n default exec -it deploy/sleep -c sleep -- curl http://httpbin:8000/ipBeklenen çıktı:
{ "origin": "172.17.X.XXX" }Çıktı, httpbin uygulamasının sleep uygulamasının gerçek IP adresini alabildiğini gösterir.
-
8000 bağlantı noktasıyla ilgili bilgileri görüntülemek için aşağıdaki komutu çalıştırın.
NotPod yeniden başlatıldıktan sonra netstat öğesini yeniden yüklemeniz gerekir.
kubectl -n default exec -it deploy/httpbin -c httpbin -- netstat -ntp | grep 8000Beklenen çıktı:
tcp 0 0 172.17.X.XXX:8000 172.17.X.XXX:36728 ESTABLISHED -Çıktı, kaynak IP adresinin
172.17.X.XXXolduğunu gösterir. -
httpbin pod'undaki erişim günlüğünün içeriğini görüntüleyin.
Aşağıda örnek biçimlendirilmiş bir günlük girişi verilmiştir:
{ "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 }Günlük aşağıdaki bilgileri gösterir:
"downstream_remote_address":"172.17.X.XXX:39058": Sleep uygulamasının adresi."downstream_local_address":"172.17.X.XXX:8000": Sleep uygulamasının eriştiği hedef adres."upstream_local_address":"172.17.X.XXX:46129": httpbin Envoy proxy'sinin httpbin uygulamasına bağlanmak için kullandığı yerel adres; bu, sleep uygulamasının IP adresidir."upstream_host":"172.17.X.XXX:8000": httpbin Envoy proxy'sinin eriştiği hedef adres.
Yöntem 2: XFF üst bilgisini kullanma
Aşağıdaki yapılandırma, sunucu tarafındaki sidecar proxy'nin gelen isteklere bir X-Forwarded-For (XFF) üst bilgisi eklemesini sağlar. Proxy, isteği uygulamaya iletmeden önce bu üst bilginin değerini istemcinin gerçek IP adresine ayarlar. Bu yöntemin işletim sistemi sınırlaması yoktur, ancak uygulamanızın istemcinin kaynak IP'sini X-Forwarded-For (XFF) üst bilgisinden okumasını gerektirir.
-
Bir EnvoyFilter şablonu kullanarak aşağıdaki EnvoyFilter'ı ASM örneğine uygulayın. Daha fazla bilgi için bkz. Envoy filter şablonu kullanarak Envoy filter oluşturma.
apiVersion: networking.istio.io/v1alpha3 kind: EnvoyFilter metadata: name: enable-xff-for-sidecar-inbound namespace: istio-system # Change this to the namespace where your gateway is located. 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 -
sleep konteynerinden bir istek göndermek için aşağıdaki komutu çalıştırın.
kubectl -n default exec -it deploy/sleep -c sleep -- curl http://httpbin:8000/ip -
Beklenen çıktı:
{ "origin": "172.17.X.XXX" }Çıktı, httpbin'in sleep uygulamasının gerçek IP adresini aldığını gösterir. httpbin uygulaması bunu, sidecar proxy'nin artık eklediği X-Forwarded-For (XFF) üst bilgisinden kaynak IP'yi okuyacak şekilde tasarlandığı için yapabilir. Uygulamanız XFF üst bilgisini okuyamıyorsa bu yöntem işe yaramaz.
Senaryo 2: Kuzey-güney trafiği
Kuzey-güney trafiğinde istekler bir istemciden yük dengeleyici ve Istio giriş ağ geçidi üzerinden arka uç hizmetine akar. Giriş ağ geçidi üzerinden yapılan bu ekstra atlama, istemci kaynak IP'sinin korunmasını daha karmaşık hale getirir. Aşağıdaki bölümlerde HTTP ve HTTPS istekleri için kaynak IP korumanın nasıl yapılandırılacağı ve doğrulanacağı açıklanmaktadır.
HTTP istekleri
Kaynak IP koruma olmadan
-
httpbin uygulamasına HTTP üzerinden erişmek için aşağıdaki içeriğe sahip http-demo.yaml adlı bir dosya oluşturun.
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 -
Ağ geçidini ve VirtualService'i dağıtmak için aşağıdaki komutu çalıştırın.
kubectl -n default apply -f http-demo.yaml -
Giriş ağ geçidi üzerinden httpbin uygulamasına erişmek için aşağıdaki komutu çalıştırın.
export GATEWAY_URL=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}') curl http://$GATEWAY_URL:80/ipBeklenen çıktı:
{ "origin": "10.0.0.93" }Çıktı, döndürülen IP adresinin bir Kubernetes düğümünün adresi olduğunu gösterir.
-
Giriş ağ geçidinin erişim günlüğünü görüntüleyin.
Aşağıda örnek bir günlük girişi verilmiştir:
{ "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 }Günlük aşağıdaki bilgileri gösterir:
"downstream_remote_address":"10.0.0.93:5899": İstemcinin gerçek kaynak IP'si değildir."downstream_local_address":"172.17.X.XXX:80": Giriş ağ geçidi pod'unun adresi."upstream_local_address":"172.17.X.XXX:54322": Giriş ağ geçidi pod'unun IP adresi korunur ancak bağlantı noktası numarası değiştirilir."upstream_host":"172.17.X.XXX:8000": httpbin pod'unun adresi.
With source IP preservation
-
Harici trafik ilkesini Local olarak ayarlayın. (Terway ağ modunu kullanan kümeler için bu adımı atlayabilirsiniz.)
ASM konsolu üzerinde oturum açın. Sol gezinme bölmesinde seçeneğini belirleyin.
Mesh Management sayfasında ASM örneğinin adını tıklayın. Sol gezinme bölmesinde seçeneğini belirleyin.
Ingress Gateway sayfasında hedef ağ geçidinin sağındaki View YAML seçeneğini tıklayın.
-
Edit iletişim kutusunda spec bölümünü bulun, externalTrafficPolicy alanını Local olarak ayarlayın ve OK seçeneğini tıklayın.
spec: affinity: {} autoCreateGatewayYaml: false clusterIds: - cf0243f2c3009406xxx compression: {} cpu: {} dnsPolicy: ClusterFirst externalTrafficPolicy: Local gatewayType: ingress
-
Giriş ağ geçidi üzerinden httpbin uygulamasına erişmek için aşağıdaki komutu çalıştırın.
curl http://$GATEWAY_URL:80/ipBeklenen çıktı:
{ "origin": "120.244.xxx.xxx" }Çıktı, döndürülen IP adresinin gerçek istemci kaynak IP'si olduğunu gösterir.
-
Giriş ağ geçidinin erişim günlüğünü görüntüleyin.
Aşağıda örnek bir günlük girişi verilmiştir:
{ "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 }Günlük aşağıdaki bilgileri gösterir:
"downstream_remote_address":"120.244.XXX.XXX:28504": Beklendiği gibi istemci kaynak adresi."downstream_local_address":"172.17.X.XXX:80": Giriş ağ geçidi pod'unun adresi."upstream_local_address":"172.17.X.XXX:57498": Giriş ağ geçidi pod'unun adresi korunur ancak bağlantı noktası numarası değiştirilir."upstream_host":"172.17.X.XXX:80": httpbin pod'unun adresi.
HTTPS istekleri
Önceki bölümde HTTP istekleri ayrıntılı olarak açıklandığından, bu bölüm yalnızca HTTPS istekleri için yapılandırma ve doğrulamaya odaklanır.
-
httpbin uygulamasına HTTPS üzerinden erişmek için aşağıdaki içeriğe sahip https-demo.yaml adlı bir dosya oluşturun.
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 -
Ağ geçidini ve VirtualService'i dağıtmak için aşağıdaki komutu çalıştırın.
kubectl -n default apply -f https-demo.yaml -
Giriş ağ geçidi üzerinden httpbin uygulamasına erişmek için aşağıdaki komutu çalıştırın.
export GATEWAY_URL=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}') curl -k https://$GATEWAY_URL:443/ipBeklenen çıktı:
{ "origin": "120.244.XXX.XXX" }Çıktı, döndürülen IP adresinin gerçek istemci kaynak IP'si olduğunu gösterir.