使用 ingress-nginx、Iptables 和 MetalLb 在 Kubernetes 裸机上保留源 IP
Preserve source IP on Kubernetes bare-metal with ingress-nginx, Iptables and MetalLb
我设置了一个 Kubernetes 集群,其中包含一个主节点和一个工作节点。
正在通过从主机到 LoadBalancer 类型的入口-nginx 服务的 NAT 将流量路由到集群,使用 MetalLb 进行设置:
#!/bin/bash
iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 80 -j DNAT --to-destination "":80
iptables -A FORWARD -p tcp -d "" --dport 80 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
</code>是ingress-nginx的外网IP</p>
<pre><code>apiVersion: v1
kind: Service
metadata:
name: ingress-nginx
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
spec:
type: LoadBalancer
externalTrafficPolicy: Local
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
- name: https
port: 443
targetPort: 443
protocol: TCP
selector:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
此时,如果我查看 ingress-nginx pod 的日志,我可以看到真实的源 IP 地址。
问题是当我检查从入口获取流量的下游应用程序的日志时,源 IP 是入口 pod 的 IP。
kind: Ingress
metadata:
namespace: laurkyt
name: laurkyt-ingress
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
nginx.ingress.kubernetes.io/affinity: cookie
nginx.ingress.kubernetes.io/session-cookie-hash: sha1
nginx.ingress.kubernetes.io/session-cookie-name: REALTIMESERVERID
nginx.ingress.kubernetes.io/proxy-connect-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
nginx.ingress.kubernetes.io/send-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-body-size: 50m
ingress.kubernetes.io/proxy-body-size: 50m
spec:
tls:
- hosts:
- example.com
- '*.example.com'
secretName: wildcard-example-com
rules:
- host: example.com
http:
paths:
- backend:
serviceName: laurkyt
servicePort: 443
apiVersion: v1
kind: Service
metadata:
namespace: laurkyt
name: laurkyt
labels:
app: laurkyt
spec:
externalTrafficPolicy: Local
ports:
- port: 80
targetPort: 80
name: "http"
- port: 443
targetPort: 443
name: "https"
selector:
app: laurkyt
tier: laurkyt
有谁知道我为了在后端 pods 保留源 IP 而遗漏了什么?
因为入口是 above-layer-4 代理。您无法在第 3 层 IP 协议中保留 SRC IP。最好的是,我认为 Nginx Ingress 已经默认设置,他们将“X-Forwarded-For” header 放在任何 HTTP 转发中。
您的应用应该记录 X-Forwarded-For header。
我设置了一个 Kubernetes 集群,其中包含一个主节点和一个工作节点。
正在通过从主机到 LoadBalancer 类型的入口-nginx 服务的 NAT 将流量路由到集群,使用 MetalLb 进行设置:
#!/bin/bash
iptables -t nat -A PREROUTING -p tcp -i eth0 --dport 80 -j DNAT --to-destination "":80
iptables -A FORWARD -p tcp -d "" --dport 80 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
</code>是ingress-nginx的外网IP</p>
<pre><code>apiVersion: v1
kind: Service
metadata:
name: ingress-nginx
namespace: ingress-nginx
labels:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
spec:
type: LoadBalancer
externalTrafficPolicy: Local
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
- name: https
port: 443
targetPort: 443
protocol: TCP
selector:
app.kubernetes.io/name: ingress-nginx
app.kubernetes.io/part-of: ingress-nginx
此时,如果我查看 ingress-nginx pod 的日志,我可以看到真实的源 IP 地址。
问题是当我检查从入口获取流量的下游应用程序的日志时,源 IP 是入口 pod 的 IP。
kind: Ingress
metadata:
namespace: laurkyt
name: laurkyt-ingress
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
nginx.ingress.kubernetes.io/affinity: cookie
nginx.ingress.kubernetes.io/session-cookie-hash: sha1
nginx.ingress.kubernetes.io/session-cookie-name: REALTIMESERVERID
nginx.ingress.kubernetes.io/proxy-connect-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
nginx.ingress.kubernetes.io/send-timeout: "3600"
nginx.ingress.kubernetes.io/proxy-body-size: 50m
ingress.kubernetes.io/proxy-body-size: 50m
spec:
tls:
- hosts:
- example.com
- '*.example.com'
secretName: wildcard-example-com
rules:
- host: example.com
http:
paths:
- backend:
serviceName: laurkyt
servicePort: 443
apiVersion: v1
kind: Service
metadata:
namespace: laurkyt
name: laurkyt
labels:
app: laurkyt
spec:
externalTrafficPolicy: Local
ports:
- port: 80
targetPort: 80
name: "http"
- port: 443
targetPort: 443
name: "https"
selector:
app: laurkyt
tier: laurkyt
有谁知道我为了在后端 pods 保留源 IP 而遗漏了什么?
因为入口是 above-layer-4 代理。您无法在第 3 层 IP 协议中保留 SRC IP。最好的是,我认为 Nginx Ingress 已经默认设置,他们将“X-Forwarded-For” header 放在任何 HTTP 转发中。
您的应用应该记录 X-Forwarded-For header。