内容简介:[TOC]本文主要内容翻译自:您必须具有可用的
目录
[TOC]
1、先决条件 2、具有 Type = ClusterIP 服务的客户端IP 3、通过 Type=NodePort 获取客户端IP 4、通过 Type = LoadBalancer 获取客户端IP 5、删除服务 6、参考文章
本文主要内容翻译自: source-ip
1、先决条件
您必须具有可用的 Kubernetes 1.5
集群才能运行本文档中的示例。这些示例使用一个小的 Nginx Web
服务器,它会显示通过HTTP头接收的请求的一切信息,包括客户端IP。您可以按如下方式创建它:
$ kubectl create deployment source-ip-app --image=idoall/echoserver:1.10 deployment.apps/source-ip-app created
2、具有 Type = ClusterIP 服务的客户端IP
如果您在 iptables
模式下运行 kube-proxy
,则从群集内发送到 ClusterIP
的数据包永远不会来自 DNAT
,这是 Kubernetes 1.2
以来的默认设置。 Kube-proxy
通过访问proxyMode endpoint 可以查看公开模式:
$ curl localhost:10249/proxyMode iptables
接下来我们创建一个服务来测试客户端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.245.180.210 <none> 80/TCP 8s
刚才我们只是部署了一个名为 source-ip-app
的Pod ,通过 kubectl expose
将资源暴露为新的 Kubernetes Service
,名称为 clusterip
。
接下来创建一个 pod
尝试获取 clusterip
测试
$ kubectl run busybox -it --image=busybox --restart=Never --rm If you don't see a command prompt, try pressing enter. / # ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1 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 3: eth0@if31: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1450 qdisc noqueue link/ether 5e:69:18:64:dd:94 brd ff:ff:ff:ff:ff:ff inet 10.244.5.27/24 scope global eth0 valid_lft forever preferred_lft forever / # wget -qO - 10.245.180.210 Hostname: source-ip-app Pod Information: -no pod information available- Server values: server_version=nginx: 1.13.3 - lua: 10008 Request Information: client_address=10.244.5.27 method=GET real path=/ query= request_version=1.1 request_scheme=http request_uri=http://10.245.180.210:8080/ Request Headers: connection=close host=10.245.180.210 user-agent=Wget Request Body: -no body in request- / #
无论何种访问方式,可以发现获取到的 client_address
地址,永远都是客户端所在容器的IP 10.244.5.27
。
3、通过 Type=NodePort 获取客户端IP
从 Kubernetes 1.5
开始, 默认情况下,发送到 Type = NodePort
的服务数据包是来自 DNAT
。接下来我们再创建一个类型是 NodePort
的服务,来对应刚才创建的部署 source-ip-app
:
$ 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}') $ for node in $NODES; do curl -s $node:$NODEPORT | grep -i client_address; done client_address=10.244.3.0 client_address=10.244.4.0 client_address=10.244.5.1 client_address=10.244.0.0 client_address=10.244.1.0 client_address=10.244.2.0
通过上面的方法能够看到,我们从不同节点去访问 NodePort
,得到的也并不是真正的客户端IP,而是集群IP
处理流程如下:
* 客户端发送数据包node2:nodePort
* node2
用自己的IP地址替换数据包中的源IP地址(SNAT)
* node2
使用 pod IP 替换数据包上的目标 IP
node1
,然后路由到 endpoint
* pod的回复被路由回
node2
* pod的回复被发送回客户端
client \ ^ \ \ v \ node 1 <--- node 2 | ^ SNAT | | ---> v | endpoint
为避免这种情况, Kubernetes
具有保留客户端IP 的功能。设置 service.spec.externalTrafficPolicy
为 Local
会将请求代理到本地端点,不将流量转发到其他节点,从而保留原始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=10.0.0.100 client_address=10.0.0.100
这时获取到的正确IP地址,只能是在当前节点的IP地址。
处理流程如下:
* 客户端发送数据包node2:nodePort
,没有任何 endpoint
* 数据包被丢
* 客户端发送数据包node1:nodePort
,存在 endpoint
* node1
使用正确的源IP将数据包路由到 endpoint
client ^ / \ / / \ / v X node 1 node 2 ^ | | | | v endpoint
4、通过 Type = LoadBalancer 获取客户端IP
从 Kubernetes 1.5
开始,默认情况下,发送到具有 Type = LoadBalancer
的服务的数据包来源是 DNAT,因为该 Ready
状态中的所有可调度 Kubernetes
节点都能获得负载平衡流量。因此,如果数据包到达没有 endpoint
的 Node
,系统会将其代理到具有 endpoint
的 Node
,用这个 Node
的IP替换数据包上的源IP(如上一节所述)。
您可以通过负载均衡器公开 source-ip-app
来测试这一点
$ kubectl expose deployment source-ip-app --name=loadbalancer --port=80 --target-port=8080 --type=LoadBalancer service/loadbalancer exposed $ kubectl get svc loadbalancer NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE loadbalancer LoadBalancer 10.245.176.219 192.168.11.221 80:30821/TCP 57s $ curl -s 192.168.11.221 | grep -i client_address client_address=10.244.0.0
通过上面的实例可以看到,获取到的 client_address
还是集群内的IP。
通过设置相同的 service.spec.externalTrafficPolicy
字段以 Local
强制没有服务端点的节点通过故意失败的运行状况检查将自己从符合加载平衡流量的节点列表中删除。
client | lb VIP / ^ v / health check ---> node 1 node 2 <--- health check 200 <--- ^ | ---> 500 | V endpoint
您可以通过下面的代码来测试:
$ kubectl patch svc loadbalancer -p '{"spec":{"externalTrafficPolicy":"Local"}}' service/loadbalancer patched
你应该立即看到 service.spec.healthCheckNodePortKubernetes
分配的字段
$ kubectl get svc loadbalancer -o yaml | grep -i healthCheckNodePort healthCheckNodePort: 32131
该 service.spec.healthCheckNodePort
字段指向服务于运行状况检查的每个节点上的端口 /healthz
。可以通过以下字段测试:
$ kubectl get pod -o wide -l run=source-ip-app NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES source-ip-app 1/1 Running 0 47m 10.244.4.179 k8s-dev-datanode-02 <none> <none> source-ip-app-784589f58-rk95c 1/1 Running 0 47m 10.244.5.26 k8s-dev-datanode-03 <none> <none> [root@k8s-dev-datanode-01 ~]# curl localhost:32131 { "service": { "namespace": "default", "name": "loadbalancer" }, "localEndpoints": 0 [root@k8s-dev-datanode-02 ~]# curl localhost:32131 { "service": { "namespace": "default", "name": "loadbalancer" }, "localEndpoints": 1
在 master
服务器上会进行负载均衡分配 ,当执行此操作时,它会分配指向每个节点上的端口/路径的HTTP运行状况检查。对于没有端点的2个节点等待大约10秒钟的健康检查失败,然后会指向正确的IP地址:
$ curl -s 192.168.11.221 | grep -i client_address client_address=192.168.11.175
只有在所在节点 datanode-02 上运行,才可以访问
5、删除服务
$ kubectl delete svc -l app=source-ip-app
删除标签是 app: source-ip-app
的服务
删除 Deployment
, ReplicaSet
和 Pod
:
$ kubectl delete deployment source-ip-app
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
HTML 压缩/解压工具
在线压缩/解压 HTML 代码
在线进制转换器
各进制数互转换器