乐趣区

关于云计算:在-Kubernetes-Pod-中如何获取客户端的真实-IP

Kubernetes 依附 kube-proxy 组件实现 Service 的通信与负载平衡。在这个过程中,因为应用了 SNAT 对源地址进行了转换,导致 Pod 中的服务拿不到实在的客户端 IP 地址信息。本篇次要解答了在 Kubernetes 集群中负载如何获取客户端实在 IP 地址这个问题。

创立一个后端服务

服务抉择

这里抉择 containous/whoami 作为后端服务镜像。在 Dockerhub 的介绍页面,能够看到拜访其 80 端口时,会返回客户端的相干信息。在代码中,咱们能够在 Http 头部中拿到这些信息。

Hostname :  6e0030e67d6a
IP :  127.0.0.1
IP :  ::1
IP :  172.17.0.27
IP :  fe80::42:acff:fe11:1b
GET / HTTP/1.1
Host: 0.0.0.0:32769
User-Agent: curl/7.35.0
Accept: */*

集群环境

简略介绍一下集群的情况。集群有三个节点,一个 master,两个 worker 节点。如下图:

创立服务

  • 创立企业空间、我的项目

如下图所示,这里将企业空间和我的项目命名为 realip

  • 创立服务

这里创立无状态服务,抉择 containous/whoami 镜像,应用默认端口。

  • 将服务改为 NodePort 模式

编辑服务的外网拜访形式,批改为 NodePort 模式。

查看拜访服务的 NodePort 端口,发现端口为 31509。

  • 拜访服务

浏览器关上 Master 节点的 EIP + :31509 时,返回如下内容:

Hostname: myservice-fc55d766-9ttxt
IP: 127.0.0.1
IP: 10.233.70.42
RemoteAddr: 192.168.13.4:21708
GET / HTTP/1.1
Host: dev.chenshaowen.com:31509
User-Agent: Chrome/86.0.4240.198 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: lang=zh;
Dnt: 1
Upgrade-Insecure-Requests: 1

能够看到 RemoteAddr 是 Master 节点的 IP,并不是拜访客户端的实在 IP 地址。这里的 Host 指的是拜访入口的地址,为了不便快速访问,我应用的是域名,并不影响测试后果。

间接通过 NortPort 拜访获取实在 IP

在下面的拜访中,获取不到客户端实在 IP 的起因是 SNAT 使得拜访 SVC 的源 IP 产生了变动。将服务的 externalTrafficPolicy 改为 Local 模式能够解决这个问题。

关上服务的配置编辑页面

将服务的 externalTrafficPolicy 设置为 Local 模式。

拜访服务,能够失去如下内容:

Hostname: myservice-fc55d766-9ttxt
IP: 127.0.0.1
IP: 10.233.70.42
RemoteAddr: 139.198.254.11:51326
GET / HTTP/1.1
Host: dev.chenshaowen.com:31509
User-Agent: hrome/86.0.4240.198 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cache-Control: max-age=0
Connection: keep-alive
Cookie: lang=zh;
Dnt: 1
Upgrade-Insecure-Requests: 1

Cluster 暗藏了客户端源 IP,可能导致第二跳到另一个节点,但具备良好的整体负载散布。Local 保留客户端源 IP 并防止 LoadBalancer 和 NodePort 类型服务的第二跳,但存在潜在的不平衡流量流传危险。

上面是比照简图:

当申请落到没有服务 Pod 的节点时,将无法访问。用 curl 拜访时,会始终进展在 TCP_NODELAY , 而后提醒超时:

*   Trying 139.198.112.248...
* TCP_NODELAY set
* Connection failed
* connect to 139.198.112.248 port 31509 failed: Operation timed out
* Failed to connect to 139.198.112.248 port 31509: Operation timed out
* Closing connection 0

通过 LB -> Service 拜访获取实在 IP

在生产环境,通常会有多个节点同时接管客户端的流量,如果仅应用 Local 模式将会导致服务可拜访性变低。引入 LB 的目标是为了利用其探活的特点,仅将流量转发到存在服务 Pod 的节点上。

这里以青云的 LB 为例进行演示。在青云的管制,能够创立 LB,增加监听器,监听 31509 端口,能够参考 LB 的应用文档 (https://docs.qingcloud.com/pr…,在此不再赘述。

如下图能够看到,在服务的 31509 端口仅 master 节点处于沉闷状态,流量也仅会导向 master 节点,合乎预期。

接着持续减少正本数量到 3

遗憾的是,Pod 并没有均匀分布在三个节点,其中有两个处于 master 上。因而 LB 的后端节点也没有齐全点亮。如下图:

这就须要给 deploy 加上反亲和性的形容。有两种抉择。第一种是配置软策略,但不能保障全副 LB 后端点亮,平均调配到流量。

spec:
  template:
    metadata:
      labels:
        app: myservice
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              podAffinityTerm:
                labelSelector:
                  matchExpressions:
                    - key: app
                      operator: In
                      values:
                        - myservice
                topologyKey: kubernetes.io/hostname

另一种是配置硬策略,强制 Pod 调配在不同的节点上,但会限度正本数量,也就是 Pod 总数不能超过 Node 总数。

spec:
  template:
    metadata:
      labels:
        app: myservice
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchExpressions:
                  - key: app
                    operator: In
                    values:
                      - myservice
              topologyKey: kubernetes.io/hostname

采纳硬策略的配置,最终点亮全副后端,如下图:

通过 LB -> Ingress -> Service 拜访获取实在 IP

如果每一个服务都占用一个 LB,老本很高,同时配置不够灵便,每次新增服务时,都须要去 LB 减少新的端口映射。

还有一种计划是 LB 将 80、443 的流量导给 Ingress Controller,而后将流量转发到 Service,接着达到 Pod 中的服务。

此时,须要 LB 能做 TCP 层的透传,或者 HTTP 层的带实在 IP 转发,将 Ingress Controller 的 externalTrafficPolicy 设置为 Local 模式,而 Service 能够不用设置为 Local 模式。

如果想要进步可拜访性,同样能够参考下面配置反亲和性,保障在每个后端节点上都有 Ingress Controller。

流量的转发门路:

LB(80/443) -> Ingress Controller(30000) -> myservice(80) -> myservice-fc55d766-xxxx(80)

首先须要勾选 LB【获取客户端 IP】的配置

接着开启我的项目的外网拜访网关

而后增加服务的路由

最初还须要在【平台治理】->【集群治理】,进入集群,在零碎我的项目 kubesphere-controls-system 中找到 realip 我的项目对应的网关。

编辑服务的配置文件,将 externalTrafficPolicy 改为 Local 模式即可。

拜访服务,能够失去如下内容:

Hostname: myservice-7dcf6b965f-vv6md
IP: 127.0.0.1
IP: 10.233.96.152
RemoteAddr: 10.233.70.68:34334
GET / HTTP/1.1
Host: realip.dev.chenshaowen.com
User-Agent: Chrome/87.0.4280.67 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cache-Control: max-age=0
Cookie: _ga=GA1.2.896113372.1605489938; _gid=GA1.2.863456118.1605830768
Cookie: lang=zh;
Upgrade-Insecure-Requests: 1
X-Forwarded-For: 139.198.113.75
X-Forwarded-Host: realip.dev.chenshaowen.com
X-Forwarded-Port: 443
X-Forwarded-Proto: https
X-Original-Uri: /
X-Real-Ip: 139.198.113.75
X-Request-Id: 999fa36437a1180eda3160a1b9f495a4
X-Scheme: https

总结

本文介绍了三种获取实在 IP 的部署形式:

  • 间接通过 NortPort 拜访获取实在 IP

受制于 Local 模式,可能会导致服务不可拜访。须要保障对外提供入口的节点上,必须具备服务的负载。

  • 通过 LB -> Service 拜访获取实在 IP

利用 LB 的探活能力,可能进步服务的可拜访性。实用于服务较少,或者违心每个服务一个 LB 的场景。

  • 通过 LB -> Ingress -> Service 拜访获取实在 IP

通过 LB 将 80、443 端口的流量转到 Ingress Controller,再进行服务散发。但 Ingress Controller 应用 Local 模式,就要求 LB 的每个后端节点都有 Ingress Controller 正本。实用于对外裸露服务数量较多的场景。

当然也能够组合应用,对于并不需要获取客户端实在 IP 的服务,能够持续应用 Cluster 模式。

参考

  • https://hub.docker.com/r/cont…
  • https://kubernetes.io/zh/docs…
  • https://docs.qingcloud.com/pr…

对于 KubeSphere

KubeSphere(https://kubesphere.io)是在 Kubernetes 之上构建的开源容器混合云,提供全栈的 IT 自动化运维的能力,简化企业的 DevOps 工作流。

KubeSphere 已被 Aqara 智能家居、原本生存、新浪、华夏银行、四川航空、国药团体、微众银行、紫金保险、中通、中国人保寿险、中国太平保险、中移金科、Radore、ZaloPay 等海内外数千家企业采纳。KubeSphere 提供了开发者敌对的向导式操作界面和丰盛的企业级性能,包含多云与多集群治理、Kubernetes 资源管理、DevOps (CI/CD)、利用生命周期治理、微服务治理 (Service Mesh)、多租户治理、监控日志、告警告诉、审计事件、存储与网络管理、GPU support 等性能,帮忙企业疾速构建一个弱小和功能丰富的容器云平台。

GitHub:https://github.com/kubesphere
官网(中国站):https://kubesphere.com.cn
微信群:请搜寻增加群助手微信号 kubesphere

本文由博客一文多发平台 OpenWrite 公布!

退出移动版