外部通信-NodePort_学无止境-CSDN博客_nodeport原理
如何从外部网络访问
Kubernetes的Pod IP和Cluster IP都只能在集群内部访问,而我们通常需要从外部网络上访问集群中的某些服务,Kubernetes提供了下述几种方式来为集群提供外部流量入口。
NodePort
NodePort在集群中的主机节点上为Service提供一个代理端口,以允许从主机网络上对Service进行访问。Kubernetes官网文档只介绍了NodePort的功能,并未对其实现原理进行解释。下面我们通过实验来分析NodePort的实现机制。
www.katacoda.com 这个网站提供了一个交互式的Kubernetes playground,注册即可免费实验kubernetes的相关功能,下面我们就使用Katacoda来分析Nodeport的实现原理。
在浏览器中输入这个网址:https://www.katacoda.com/courses/kubernetes/networking-introduction, 打开后会提供了一个实验用的Kubernetes集群,并可以通过网元模拟Terminal连接到集群的Master节点。
执行下面的命令创建一个nodeport类型的service。
kubectl apply -f nodeport.yaml
查看创建的service,可以看到kubernetes创建了一个名为webapp-nodeport-svc的service,并为该service在主机节点上创建了30080这个Nodeport。
master $ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 36m
webapp1-nodeport-svc NodePort 10.103.188.73 <none> 80:30080/TCP 3m
webapp-nodeport-svc后端对应两个Pod,其Pod的IP分别为10.32.0.3和10.32.0.5。
master $ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IPNODE NOMINATED NODE
webapp1-nodeport-deployment-785989576b-cjc5b 1/1 Running 0 2m 10.32.0.3
webapp1-nodeport-deployment-785989576b-tpfqr 1/1 Running 0 2m 10.32.0.5
通过netstat命令可以看到Kube-proxy在主机网络上创建了30080监听端口,用于接收从主机网络进入的外部流量。
master $ netstat -lnp|grep 30080
tcp6 0 0 :::30080 :::* LISTEN 7427/kube-proxy
下面是Kube-proxy创建的相关iptables规则以及对应的说明。可以看到Kube-proxy为Nodeport创建了相应的IPtable规则,将发向30080这个主机端口上的流量重定向到了后端的两个Pod IP上。
iptables-save > iptables-dump
# Generated by iptables-save v1.6.0 on Thu Mar 28 07:33:57 2019
*nat
# Nodeport规则链
:KUBE-NODEPORTS - [0:0]
# Service规则链
:KUBE-SERVICES - [0:0]
# Nodeport和Service共用的规则链
:KUBE-SVC-J2DWGRZTH4C2LPA4 - [0:0]
:KUBE-SEP-4CGFRVESQ3AECDE7 - [0:0]
:KUBE-SEP-YLXG4RMKAICGY2B3 - [0:0]
# 将host上30080端口的外部tcp流量转到KUBE-SVC-J2DWGRZTH4C2LPA4链
-A KUBE-NODEPORTS -p tcp -m comment --comment "default/webapp1-nodeport-svc:" -m tcp --dport 30080 -j KUBE-SVC-J2DWGRZTH4C2LPA4
#将发送到Cluster IP 10.103.188.73的内部流量转到KUBE-SVC-J2DWGRZTH4C2LPA4链
KUBE-SERVICES -d 10.103.188.73/32 -p tcp -m comment --comment "default/webapp1-nodeport-svc: cluster IP" -m tcp --dport 80 -j KUBE-SVC-J2DWGRZTH4C2LPA4
#将发送到webapp1-nodeport-svc的流量转交到第一个Pod(10.32.0.3)相关的规则链上,比例为50%
-A KUBE-SVC-J2DWGRZTH4C2LPA4 -m comment --comment "default/webapp1-nodeport-svc:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-YLXG4RMKAICGY2B3
#将发送到webapp1-nodeport-svc的流量转交到第二个Pod(10.32.0.5)相关的规则链上
-A KUBE-SVC-J2DWGRZTH4C2LPA4 -m comment --comment "default/webapp1-nodeport-svc:" -j KUBE-SEP-4CGFRVESQ3AECDE7
#将请求重定向到Pod 10.32.0.3
-A KUBE-SEP-YLXG4RMKAICGY2B3 -p tcp -m comment --comment "default/webapp1-nodeport-svc:" -m tcp -j DNAT --to-destination 10.32.0.3:80
#将请求重定向到Pod 10.32.0.5
-A KUBE-SEP-4CGFRVESQ3AECDE7 -p tcp -m comment --comment "default/webapp1-nodeport-svc:" -m tcp -j DNAT --to-destination 10.32.0.5:80
从上面的实验可以看到,通过将一个Service定义为NodePort类型,Kubernetes会通过集群中node上的Kube-proxy为该Service在主机网络上创建一个监听端口。Kube-proxy并不会直接接收该主机端口进入的流量,而是会创建相应的Iptables规则,并通过Iptables将从该端口收到的流量直接转发到后端的Pod中。
NodePort的流量转发机制和Cluster IP的iptables模式类似,唯一不同之处是在主机网络上开了一个“NodePort”来接受外部流量。从上面的规则也可以看出,在创建Nodeport时,Kube-proxy也会同时为Service创建Cluster IP相关的iptables规则。
备注:除采用iptables进行流量转发,NodePort应该也可以提供userspace模式以及ipvs模式,这里未就这两种模式进行实验验证。
从分析得知,在NodePort模式下,集群内外部的通讯如下图所示:
NodePort