【问题标题】:Kubernetes + metallb + traefik: how to get real client ip?Kubernetes + metallb + traefik:如何获取真实的客户端 ip?
【发布时间】:2018-05-29 13:27:32
【问题描述】:

traefik.toml:

defaultEntryPoints = ["http", "https"]

[entryPoints]
  [entryPoints.http]
  address = ":80"
    [entryPoints.http.forwardedHeaders]
      trustedIPs = ["0.0.0.0/0"]
    [entryPoints.http.redirect]
      entryPoint = "https"
  [entryPoints.https]
  address = ":443"
    [entryPoints.https.tls]
    [entryPoints.https.forwardedHeaders]
      trustedIPs = ["0.0.0.0/0"]
[api]

traefik 服务:

kind: Service
apiVersion: v1
metadata:
  name: traefik-ingress-service
  namespace: kube-system
spec:
  selector:
    k8s-app: traefik-ingress-lb
  ports:
    - protocol: TCP
      port: 80
      name: http
    - protocol: TCP
      port: 443
      name: https
  type: LoadBalancer

那么:

kubectl run source-ip-app --image=k8s.gcr.io/echoserver:1.4
deployment "source-ip-app" created

kubectl expose deployment source-ip-app --name=clusterip --port=80 --target-port=8080
service "clusterip" exposed

kubectl get svc clusterip
NAME        TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
clusterip   ClusterIP   10.5.55.102   <none>        80/TCP    2h

为集群创建入口:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: clusterip-ingress
  namespace: default
  annotations:
    kubernetes.io/ingress.class: traefik
spec:
  rules:
  - host: clusterip.staging
    http:
      paths:
      - backend:
          serviceName: clusterip
          servicePort: 80

clusterip.staging ip:192.168.0.69

来自其他 ip:192.168.0.100 的电脑:

wget -qO - clusterip.staging

并获得结果:

CLIENT VALUES:
client_address=10.5.65.74
command=GET
real path=/
query=nil
request_version=1.1
request_uri=http://clusterip.staging:8080/

SERVER VALUES:
server_version=nginx: 1.10.0 - lua: 10001

HEADERS RECEIVED:
accept=text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
accept-encoding=gzip, deflate, br
accept-language=ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
cache-control=max-age=0
host=clusterip.staging
upgrade-insecure-requests=1
x-forwarded-for=10.5.64.0
x-forwarded-host=clusterip.staging
x-forwarded-port=443
x-forwarded-proto=https
x-forwarded-server=traefik-ingress-controller-755cc56458-t8q9k
x-real-ip=10.5.64.0
BODY:
-no body in request-

kubectl 获取 svc --all-namespaces

NAMESPACE     NAME                      TYPE           CLUSTER-IP    EXTERNAL-IP    PORT(S)                                                 AGE
default       clusterip                 NodePort       10.5.55.102   <none>         80:31169/TCP                                            19h
default       kubernetes                ClusterIP      10.5.0.1      <none>         443/TCP                                                 22d
kube-system   kube-dns                  ClusterIP      10.5.0.3      <none>         53/UDP,53/TCP                                           22d
kube-system   kubernetes-dashboard      ClusterIP      10.5.5.51     <none>         443/TCP                                                 22d
kube-system   traefik-ingress-service   LoadBalancer   10.5.2.37     192.168.0.69   80:32745/TCP,443:30219/TCP                              1d
kube-system   traefik-web-ui            NodePort       10.5.60.5     <none>         80:30487/TCP                                            7d

如何在我的安装中获取真实 ip (192.168.0.100)?为什么是 x-real-ip 10.5.64.0? 我在文档中找不到答案。

【问题讨论】:

    标签: kubernetes traefik


    【解决方案1】:

    kube-proxy 使用iptables 模式时,它使用 NAT 将数据发送到有效负载工作的节点,在这种情况下您会丢失原始的SourceIP 地址。

    据我了解,您在Traefik Ingress Service 后面使用Matallb(因为它的类型是LoadBalancer)。这意味着从客户端到后端的流量是这样的:

    Client -&gt; Metallb -&gt; Traefik LB -&gt; Traefik Service -&gt; Backend pod.

    Traefik 可以正常工作并添加标头 x-*,包括包含虚假地址的 x-forwarded-for 和 x-real-ip,这就是原因:

    来自Metallbdocumentation:

    MetalLB 了解服务的externalTrafficPolicy 选项,并根据您选择的策略和公告协议实现不同的公告模式。

    • 第二层

      此策略导致服务中所有 Pod 的流量分布均匀。但是,kube-proxy 在进行负载平衡时会隐藏连接的源 IP 地址,因此您的 pod 日志将显示外部流量似乎来自集群的领导节点。

    • BGP

      • “集群”流量政策

        使用默认的集群流量策略,集群中的每个节点都会吸引服务 IP 的流量。在每个节点上,流量都经过第二层负载均衡(由 kube-proxy 提供),将流量导向各个 pod。

        ......

        “集群”策略的另一个缺点是 kube-proxy 在进行负载平衡时会隐藏连接的源 IP 地址,因此您的 pod 日志将显示外部流量似乎来自您的集群节点。

      • “本地”流量政策

        使用本地流量策略,节点只有在本地运行一个或多个服务的 Pod 时才会吸引流量。 BGP 路由器将仅在当前托管服务的那些节点之间对传入流量进行负载平衡。在每个节点上,流量仅通过 kube-proxy 转发到本地 Pod,节点之间没有“水平”流量。

        此政策为您的服务提供最有效的流量。此外,由于kube-proxy 不需要在集群节点之间发送流量,您的 pod 可以看到传入连接的真实源 IP 地址。

    最后,获取真实源IP地址的唯一方法是使用TrafficPolicy的“本地”模式。

    如果你设置它,你会得到你想要的。

    【讨论】:

    • 非常感谢。我还在 metallb 的文档中找到。第一次看的时候错过了:)
    • 有一个关于此的 k8s 文档:kubernetes.io/docs/tasks/access-application-cluster/…
    • k8s 文档中提到的这种潜在缺点的含义是什么:“本地保留客户端源 IP 并避免 LoadBalancer 和 NodePort 类型服务的第二个跃点,但存在潜在的不平衡流量传播风险。”?只有运行服务的节点才能获得流量,这听起来不错。那么什么是不平衡的呢?
    猜你喜欢
    • 2021-06-16
    • 2020-05-22
    • 2020-10-01
    • 2012-08-04
    • 2021-09-15
    • 2012-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多