我创建了一个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入口安装有:CCD_ 1。
我还为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而不是入口吊舱ip?还有没有一种方法可以知道ELB正在向入口发送哪些标头?
一种解决方案是使用externalTrafficPolicy
:Local
(请参阅文档(。
事实上,根据kubernetes documentation
:
由于实现了此功能,在目标容器中看到的源IP不是客户端的原始源IP。。。。service.spec.externalTrafficPolicy-表示此服务是否希望将外部流量路由到节点本地或集群范围的端点。有两个可用选项:群集(默认(和本地。集群模糊了客户端源IP,可能会导致第二次跳到另一个节点,但应该具有良好的整体负载分布。Local保留了客户端源IP,避免了LoadBalancer和NodePort类型服务的第二跳,但存在潜在的不平衡流量扩散风险。
如果要遵循此路线,请更新nginx ingress controller
Service
并添加externalTrafficPolicy
字段:
apiVersion: v1
kind: Service
metadata:
name: nginx-ingress-controller
spec:
...
externalTrafficPolicy: Local
一个可能的替代方案是使用代理协议(见文档(
应该在ConfigMap中为入口控制器和ELB启用代理协议。
L4使用代理协议
对于L7,使用转发头
# 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-协议
只是在@strongjz答案上展开。
默认情况下,将在AWS中为LoadBalancer
类型的服务创建的负载均衡器将是一个经典负载均衡器,在第4层上运行,即在TCP协议级别中代理。
对于这种情况,保留真实ip的最佳方法是使用代理协议,因为它能够在TCP级别上做到这一点。
要做到这一点,您应该在负载均衡器和Nginx入口上启用代理协议。
这些值应该适用于nginxingress的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: "*"
注释将告诉helm install ingress-nginx ingress-nginx/ingress-nginx
0在启用代理协议的情况下创建LoadBalancer。我不确定如果将它添加到预先存在的Ingress nginx中会发生什么,但它也应该工作。
use-proxy-protocol
和real-ip-header
是传递给Nginx的选项,用于在那里启用代理协议。
参考:
- https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.2/guide/service/annotations/#proxy-协议-v2
- https://kubernetes.github.io/ingress-nginx/user-guide/miscellaneous/#proxy-协议
- https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/configmap/#use-代理协议
如果您使用helm安装ingress nginx,则运行以下命令使ingress ngimx转发客户端ip
helm upgrade --install ingress-nginx-chart ingress-nginx/ingress-nginx --set controller.service.externalTrafficPolicy=Local
如果它有效,请投票支持它,不是为了帮助我,而是为了帮助其他面临这个问题的寻求者:(