kubernetes Nginx ingress向服务发送X-Real-IP的私有IP

jmp7cifd  于 2023-04-20  发布在  Kubernetes
关注(0)|答案(4)|浏览(326)

我创建了一个Nginx入口和服务,代码如下:

apiVersion: v1
kind: Service
metadata:
  name: myservice
spec:
  type: ClusterIP
  selector:
    name: my-app
  ports:
    - port: 8000
      targetPort: 8000
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myingress
  annotations:
    kubernetes.io/ingress.class: nginx
  labels:
    name: myingress
spec:
  rules:
  - host: mydomain.com
    http:
      paths:
      - pathType: Prefix
        path: "/"
        backend:
          service:
            name: my-service
            port: 
              number: 8000

Nginx ingress安装:helm install ingress-nginx ingress-nginx/ingress-nginx .
我还为ELB启用了代理协议。但在nginx日志中,我看不到X-Forwarded-For和X-Real-IP头的真实的客户端IP。这是我在应用日志中看到的最后一个头:

X-Forwarded-For:[192.168.21.145] X-Forwarded-Port:[80] X-Forwarded-Proto:[http] X-Forwarded-Scheme:[http] X-Real-Ip:[192.168.21.145] X-Request-Id:[1bc14871ebc2bfbd9b2b6f31] X-Scheme:[http]

我如何获得真实的的客户端IP而不是ingress Pod IP?是否有方法知道ELB正在向ingress发送哪些报头?

qncylg1j

qncylg1j1#

一个解决方案是使用externalTrafficPolicyLocal(参见文档)。
事实上,根据kubernetes documentation
由于此功能的实现,在目标容器中看到的源IP不是客户端的原始源IP。.... service.spec.externalTrafficPolicy -表示此Service是否希望将外部流量路由到节点本地或群集范围的端点。有两个可用选项:群集(默认)和本地。群集会隐藏客户端源IP,并可能导致到另一个节点的第二跳,但应具有良好的总体负载分布。本地会保留客户端源IP,并避免LoadBalancer和NodePort类型服务的第二跳,但存在潜在的不平衡流量分布风险。
如果你想遵循这个路线,更新你的nginx ingress controllerService并添加externalTrafficPolicy字段:

apiVersion: v1
kind: Service
metadata:
  name: nginx-ingress-controller
spec:
  ...
  externalTrafficPolicy: Local

一种可能的替代方法是使用Proxy protocol(参见文档)。

6qftjkof

6qftjkof2#

应在ConfigMap中为入口控制器和ELB启用代理协议。
L4使用代理协议
对于L7使用use-forwarded-header

# configmap.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-configuration
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
data:
  use-forwarded-headers: "true"
  use-proxy-protocol: "true"

https://kubernetes.github.io/ingress-nginx/user-guide/miscellaneous/#proxy-protocol

ngynwnxp

ngynwnxp3#

只是在@strongjz上扩展答案。
默认情况下,将在AWS中为LoadBalancer类型的服务创建的负载均衡器将是经典负载均衡器,在第4层上运行,即在TCP协议级别代理。
对于这种情况,保留真实的IP的最佳方法是使用代理协议,因为它能够在TCP级别执行此操作。
为此,您应该在负载均衡器和Nginx-ingress上启用代理协议。
对于nginx-ingress的Helm安装,这些值应该可以做到:

controller:
    service:
      annotations:
        service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*"
    config:
      use-proxy-protocol: "true"
      real-ip-header: "proxy_protocol"

service.beta.kubernetes.io/aws-load-balancer-proxy-protocol: "*" annotation将告诉aws-load-balancer-controller创建启用代理协议的LoadBalancer。我不确定如果将其添加到预先存在的Ingress-nginx会发生什么,但它应该也可以工作。
use-proxy-protocolreal-ip-header是传递给Nginx的选项,也可以在那里启用代理协议。
参考文献:

  • https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.2/guide/service/annotations/#proxy-protocol-v2
  • https://kubernetes.github.io/ingress-nginx/user-guide/miscellaneous/#proxy-protocol
  • https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#use-proxy-protocol
deyfvvtc

deyfvvtc4#

如果您使用helm安装ingress-nginx,请运行以下命令使ingress-nginx转发客户端IP

helm upgrade --install ingress-nginx-chart ingress-nginx/ingress-nginx --set controller.service.externalTrafficPolicy=Local

如果它起作用了,就投赞成票吧,不是为了帮助我,而是为了帮助其他面临这个问题的求职者:)

相关问题