Kubernetes.Service—使用源 IP

这篇具有很好参考价值的文章主要介绍了Kubernetes.Service—使用源 IP。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

使用源 IP

运行在 Kubernetes 集群中的应用程序通过 Service 抽象发现彼此并相互通信,它们也用 Service 与外部世界通信。 本文解释了发送到不同类型 Service 的数据包的源 IP 会发生什么情况,以及如何根据需要切换此行为。

准备开始

术语表

本文使用了下列术语:

NAT网络地址转换Source NAT替换数据包上的源 IP;在本页面中,这通常意味着替换为节点的 IP 地址Destination NAT替换数据包上的目标 IP;在本页面中,这通常意味着替换为 Pod 的 IP 地址VIP一个虚拟 IP 地址,例如分配给 Kubernetes 中每个 Service 的 IP 地址Kube-proxy一个网络守护程序,在每个节点上协调 Service VIP 管理

先决条件

你必须拥有一个 Kubernetes 的集群,同时你必须配置 kubectl 命令行工具与你的集群通信。 建议在至少有两个不作为控制平面主机的节点的集群上运行本教程。 如果你还没有集群,你可以通过 Minikube 构建一个你自己的集群,或者你可以使用下面的 Kubernetes 练习环境之一:

  • Killercoda
  • 玩转 Kubernetes

示例使用一个小型 nginx Web 服务器,服务器通过 HTTP 标头返回它接收到的请求的源 IP。 你可以按如下方式创建它:

kubectl create deployment source-ip-app --image=registry.k8s.io/echoserver:1.4

输出为:

deployment.apps/source-ip-app created

教程目标

  • 通过多种类型的 Service 暴露一个简单应用
  • 了解每种 Service 类型如何处理源 IP NAT
  • 了解保留源 IP 所涉及的权衡

Type=ClusterIP类型 Service 的源 IP

如果你在 iptables 模式(默认)下运行 kube-proxy,则从集群内发送到 ClusterIP 的数据包永远不会进行源 NAT。 你可以通过在运行 kube-proxy 的节点上获取 http://localhost:10249/proxyMode 来查询 kube-proxy 模式。

kubectl get nodes

输出类似于:

NAME                           STATUS     ROLES    AGE     VERSION
kubernetes-node-6jst   Ready      <none>   2h      v1.13.0
kubernetes-node-cx31   Ready      <none>   2h      v1.13.0
kubernetes-node-jj1t   Ready      <none>   2h      v1.13.0

在其中一个节点上获取代理模式(kube-proxy 监听 10249 端口):

# 在要查询的节点上的 Shell 中运行
curl http://localhost:10249/proxyMode

输出为:

iptables

你可以通过在源 IP 应用程序上创建 Service 来测试源 IP 保留:

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.0.170.92   <none>        80/TCP    51s

并从同一集群中的 Pod 中访问 ClusterIP:

kubectl run busybox -it --image=busybox:1.28 --restart=Never --rm

输出类似于:

Waiting for pod default/busybox to be running, status is Pending, pod ready: false
If you don't see a command prompt, try pressing enter.

然后,你可以在该 Pod 中运行命令:

# 从 “kubectl run” 的终端中运行
ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1460 qdisc noqueue
    link/ether 0a:58:0a:f4:03:08 brd ff:ff:ff:ff:ff:ff
    inet 10.244.3.8/24 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::188a:84ff:feb0:26a5/64 scope link
       valid_lft forever preferred_lft forever

然后使用 wget 查询本地 Web 服务器:

# 将 “10.0.170.92” 替换为 Service 中名为 “clusterip” 的 IPv4 地址
wget -qO - 10.0.170.92
CLIENT VALUES:
client_address=10.244.3.8
command=GET
...

不管客户端 Pod 和服务器 Pod 位于同一节点还是不同节点,client_address 始终是客户端 Pod 的 IP 地址。

Type=NodePort类型 Service 的源 IP

默认情况下,发送到 Type=NodePort 的 Service 的数据包会经过源 NAT 处理。你可以通过创建一个 NodePort 的 Service 来测试这点:

kubectl expose deployment source-ip-app --name=nodeport --port=80 --target-port=8080 --type=NodePort

输出为:

service/nodeport exposed
NODEPORT=$(kubectl get -o jsonpath="{.spec.ports[0].nodePort}" services nodeport)
NODES=$(kubectl get nodes -o jsonpath='{ $.items[*].status.addresses[?(@.type=="InternalIP")].address }')

如果你在云供应商上运行,你可能需要为上面报告的 nodes:nodeport 打开防火墙规则。 现在你可以尝试通过上面分配的节点端口从集群外部访问 Service。

for node in $NODES; do curl -s $node:$NODEPORT | grep -i client_address; done

输出类似于:

client_address=10.180.1.1
client_address=10.240.0.5
client_address=10.240.0.3

请注意,这些并不是正确的客户端 IP,它们是集群的内部 IP。这是所发生的事情:

  • 客户端发送数据包到 node2:nodePort
  • node2 使用它自己的 IP 地址替换数据包的源 IP 地址(SNAT)
  • node2 将数据包上的目标 IP 替换为 Pod IP
  • 数据包被路由到 node1,然后到端点
  • Pod 的回复被路由回 node2
  • Pod 的回复被发送回给客户端

用图表示:

Kubernetes.Service—使用源 IP,Kubernetes,kubernetes,tcp/ip,容器

 

如图。使用 SNAT 的源 IP(Type=NodePort)

为避免这种情况,Kubernetes 有一个特性可以保留客户端源 IP。 如果将 service.spec.externalTrafficPolicy 设置为 Local, kube-proxy 只会将代理请求代理到本地端点,而不会将流量转发到其他节点。 这种方法保留了原始源 IP 地址。如果没有本地端点,则发送到该节点的数据包将被丢弃, 因此你可以在任何数据包处理规则中依赖正确的源 IP,你可能会应用一个数据包使其通过该端点。

设置 service.spec.externalTrafficPolicy 字段如下:

kubectl patch svc nodeport -p '{"spec":{"externalTrafficPolicy":"Local"}}'

输出为:

service/nodeport patched

现在,重新运行测试:

for node in $NODES; do curl --connect-timeout 1 -s $node:$NODEPORT | grep -i client_address; done

输出类似于:

client_address=198.51.100.79

请注意,你只从运行端点 Pod 的节点得到了回复,这个回复有正确的客户端 IP。

这是发生的事情:

  • 客户端将数据包发送到没有任何端点的 node2:nodePort
  • 数据包被丢弃
  • 客户端发送数据包到必有端点的 node1:nodePort
  • node1 使用正确的源 IP 地址将数据包路由到端点

用图表示:

Kubernetes.Service—使用源 IP,Kubernetes,kubernetes,tcp/ip,容器

如图。源 IP(Type=NodePort)保存客户端源 IP 地址

Type=LoadBalancer类型 Service 的源 IP

默认情况下,发送到 Type=LoadBalancer 的 Service 的数据包经过源 NAT处理,因为所有处于 Ready 状态的可调度 Kubernetes 节点对于负载均衡的流量都是符合条件的。 因此,如果数据包到达一个没有端点的节点,系统会将其代理到一个带有端点的节点,用该节点的 IP 替换数据包上的源 IP(如上一节所述)。

你可以通过负载均衡器上暴露 source-ip-app 进行测试:

kubectl expose deployment source-ip-app --name=loadbalancer --port=80 --target-port=8080 --type=LoadBalancer

输出为:

service/loadbalancer exposed

打印 Service 的 IP 地址:

kubectl get svc loadbalancer

输出类似于:

NAME           TYPE           CLUSTER-IP    EXTERNAL-IP       PORT(S)   AGE
loadbalancer   LoadBalancer   10.0.65.118   203.0.113.140     80/TCP    5m

接下来,发送请求到 Service 的 的外部 IP(External-IP):

curl 203.0.113.140

输出类似于:

CLIENT VALUES:
client_address=10.240.0.5
...

然而,如果你在 Google Kubernetes Engine/GCE 上运行, 将相同的 service.spec.externalTrafficPolicy 字段设置为 Local, 故意导致健康检查失败,从而强制没有端点的节点把自己从负载均衡流量的可选节点列表中删除。

用图表示:

Kubernetes.Service—使用源 IP,Kubernetes,kubernetes,tcp/ip,容器

 

你可以通过设置注解进行测试:

kubectl patch svc loadbalancer -p '{"spec":{"externalTrafficPolicy":"Local"}}'

你应该能够立即看到 Kubernetes 分配的 service.spec.healthCheckNodePort 字段:

kubectl get svc loadbalancer -o yaml | grep -i healthCheckNodePort

输出类似于:

  healthCheckNodePort: 32122

service.spec.healthCheckNodePort 字段指向每个在 /healthz 路径上提供健康检查的节点的端口。你可以这样测试:

kubectl get pod -o wide -l app=source-ip-app

输出类似于:

NAME                            READY     STATUS    RESTARTS   AGE       IP             NODE
source-ip-app-826191075-qehz4   1/1       Running   0          20h       10.180.1.136   kubernetes-node-6jst

使用 curl 获取各个节点上的 /healthz 端点:

# 在你选择的节点上本地运行
curl localhost:32122/healthz
1 Service Endpoints found

在不同的节点上,你可能会得到不同的结果:

# 在你选择的节点上本地运行
curl localhost:32122/healthz
No Service Endpoints Found

在控制平面上运行的控制器负责分配云负载均衡器。 同一个控制器还在每个节点上分配指向此端口/路径的 HTTP 健康检查。 等待大约 10 秒,让 2 个没有端点的节点健康检查失败,然后使用 curl 查询负载均衡器的 IPv4 地址:

curl 203.0.113.140

输出类似于:

CLIENT VALUES:
client_address=198.51.100.79
...

跨平台支持

只有部分云提供商为 Type=LoadBalancer 的 Service 提供保存源 IP 的支持。 你正在运行的云提供商可能会以几种不同的方式满足对负载均衡器的请求:

  1. 使用终止客户端连接并打开到你的节点/端点的新连接的代理。 在这种情况下,源 IP 将始终是云 LB 的源 IP,而不是客户端的源 IP。
  2. 使用数据包转发器,这样客户端发送到负载均衡器 VIP 的请求最终会到达具有客户端源 IP 的节点,而不是中间代理。

第一类负载均衡器必须使用负载均衡器和后端之间商定的协议来传达真实的客户端 IP, 例如 HTTP 转发或 X-FORWARDED-FOR 标头,或代理协议。 第二类负载均衡器可以通过创建指向存储在 Service 上的 service.spec.healthCheckNodePort 字段中的端口的 HTTP 健康检查来利用上述功能。

清理现场

删除 Service:

kubectl delete svc -l app=source-ip-app

删除 Deployment、ReplicaSet 和 Pod:文章来源地址https://www.toymoban.com/news/detail-606800.html

kubectl delete deployment source-ip-app

到了这里,关于Kubernetes.Service—使用源 IP的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Spring Cloud Kubernetes】使用k8s原生service实现服务注册和发现

    @TOC 现在微服务开发模式应用的越来越广泛,注册中心 Eureka 也逐渐被其它注册中心产品替代,比如阿里出品的 Nacos 。随着云原生相关技术的普及, k8s 迅猛发展,我们把 K8s 中的 Pod 暴露给外部访问,通过少了 Service ,这也是今天的主角。 有没有发现,其实 Service 已经解决了

    2024年02月12日
    浏览(85)
  • 【云原生 • Kubernetes】kubernetes 核心技术 - Service

    1. Service 的定义 Service 是 Kubernetes 的核心概念之一,创建一个 Service 可以为一组具有相同功能的容器应用提供一个统一的入口地址,并且将请求负载分发到后端的各个容器应用上。 完整 yaml 格式的 Service 定义文件如下: 2. Service 的基本用法 一般情况下,对外部提供服务的应用

    2024年02月01日
    浏览(39)
  • k8s(Kubernetes)设置 pod,Deployment 域名自定义映射ip,hosts 解析 HostAliases

    直接 编辑修改 Deployment 最后内容如下,如需保存 按 esc 键,最后输入 :wq 保存退出,容器会自动重新生成新的

    2024年02月12日
    浏览(47)
  • Kubernetes Service的过程

    在了解Service之前,需要先了解一些额外的知识: 命令: ip route show table all DNAT IPVS和iptables 基础的网络知识(网关,网段或子网,转发) 1. 命令 ip route show table all 这条命令会列出主机内所有的路由.内容展示包含了对应的网段或者IP,要通过那个虚拟设备发送出去.示例: 摘取一条,比如:

    2024年02月16日
    浏览(33)
  • 图解Kubernetes的服务(Service)

    pod 准备: 不要直接使用和管理Pods: 当使用ReplicaSet水平扩展scale时,Pods可能被terminated 当使用Deployment时,去更新Docker Image Version,旧Pods会被terminated,然后创建新Pods Kubernetes 中 Service 是 将运行在一个或一组 [Pod]上的网络应用程序公开为网络服务的方法。 Kubernetes 中 Service 的

    2024年02月03日
    浏览(35)
  • Kubernetes 应用故障排除—调试 Service

    对于新安装的 Kubernetes,经常出现的问题是 Service 无法正常运行。你已经通过 Deployment(或其他工作负载控制器)运行了 Pod,并创建 Service , 但是当你尝试访问它时,没有任何响应。此文档有望对你有所帮助并找出问题所在。 对于这里的许多步骤,你可能希望知道运行在集群

    2024年02月13日
    浏览(41)
  • 【云原生】kubernetes深入理解之Service

    版权声明:本文为CSDN博主「开着拖拉机回家」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 主页地址:开着拖拉机回家的博客_CSDN博客-Linux,Java基础学习,MySql数据库领域博主 目录 一、概述 1.1 Service 1.2 kube-proxy与Service 1.3VIP和Service代理 二、Pod与

    2024年02月08日
    浏览(51)
  • 【Kubernetes 系列】一文学会Kubernetes Service安全的暴露应用_apiversion apps v1

    先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7 深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前! 因此收集整理了一份《2024年最新大数据全套学习资料》,

    2024年04月28日
    浏览(32)
  • Kubernetes(k8s)服务service:service的发现和service的发布

    目录 一.系统环境 二.前言 三.Kubernetes service简介 四.使用hostPort向外界暴露应用程序 4.1 创建deploy 4.2 使用hostPort向外界暴露pod的端口 五.使用service服务向外界暴露应用程序 5.1 使用service服务向外界暴露pod 5.1.1 创建service服务 5.1.2 测试svc的负载均衡 六.service服务的发现 6.1 使用

    2024年02月08日
    浏览(55)
  • 【微服务】 Spring cold、Kubernetes、Service mesh

      目录  Spring Cloud # 什么是微服务?谈谈你对微服务的理解? # 什么是Spring Cloud? # springcloud中的组件有那些? # 具体说说SpringCloud主要项目? # Spring Cloud 和dubbo区别? # 服务注册和发现是什么意思?Spring Cloud 如何实现? # 什么是Eureka? # Eureka怎么实现高可用? # 什么是Eureka的自

    2024年01月15日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包