Pepper Metrics是我与同事开发的一个开源工具(github.com/zrbcool/pep…),其经过收集jedis/mybatis/httpservlet/dubbo/motan的运行性能统计,并暴露成prometheus等主流时序数据库兼容数据,经过grafana展现趋势。其插件化的架构也很是方便使用者扩展并集成其余开源组件。
请你们给个star,同时欢迎你们成为开发者提交PR一块儿完善项目。node
随着Service Mesh的概念逐渐被你们所接受,以及K8S做为一个容器管理平台已经成为事实标准,你们对于K8S下的服务治理及流量管理的需求也是日渐强烈,在Google,IBM,Lyft几个大厂的推进下,Istio + Envoy的Service Mesh及流量管理的解决方案补齐了K8S在服务治理,精细化的流量管理,灰度发布等高级特性上的不足,因为其Go加C++语言栈的优点,相比Linked的scala更节省资源,目前已经基本能够肯定是Service Mesh领域的事实标准。
本篇文章,我以在阿里云建立的K8S加Istio的集群环境为例,来说一下一个请求到底在K8S以及Istio、Envoy和微服务的Pod之间网络上是如何流转的。linux
本文中忽略了大量网络及Kubernates中的概念及网络实现原理的说明,若是读者在阅读中遇到困难,请参考下面列出的几篇文章git
新建立集群名为test,下面有两个node节点,主机名分别为work001,和work002,(经过阿里云容器服务Kubernetes版的应用市场)部署istio-ingressgateway并建立type为LoadBalancer的Service,以及部署replics为2的istio-ingressgateway POD实例,完成后可见两个POD实例分别在work001及work002上启动。
建立成功后,会在阿里云控制台上发现,LoadBalancer类型的Service会自动为咱们建立好一个阿里云负载均衡(182.92.251.227)实例并将咱们的两个node节点的31061端口做为阿里云负载均衡实例的后端服务,以下图所示:
github
从work001(上图中的192.168.0.17)这台机器查看iptables规则能够看到:docker
➜ ~ iptables -L -t nat
Chain PREROUTING (policy ACCEPT 244 packets, 14640 bytes)
pkts bytes target prot opt in out source destination
32M 2003M KUBE-SERVICES all -- * * 0.0.0.0/0 0.0.0.0/0 /* kubernetes service portals */
复制代码
上面是一段nat表的规则,它的意思是,接受全部到来的数据,并交给KUBE-SERVICES这个规则链处理,下面咱们看下KUBE-SERVICES这个规则链:数据库
Chain KUBE-SERVICES (2 references)
pkts bytes target prot opt in out source destination
0 0 KUBE-FW-HBO2MBMQRZFAHKF2 tcp -- * * 0.0.0.0/0 182.92.251.227 /* default/istio-ingressgateway:http2 loadbalancer IP */ tcp dpt:80
562 33720 KUBE-NODEPORTS all -- * * 0.0.0.0/0 0.0.0.0/0 /* kubernetes service nodeports; NOTE: this must be the last rule in this chain */ ADDRTYPE match dst-type LOCAL
复制代码
能够看到目标是182.92.251.227:80的请求表要被转发给KUBE-FW-HBO2MBMQRZFAHKF2这个规则链,继续看KUBE-FW-HBO2MBMQRZFAHKF2:后端
Chain KUBE-FW-HBO2MBMQRZFAHKF2 (1 references)
pkts bytes target prot opt in out source destination
0 0 KUBE-XLB-HBO2MBMQRZFAHKF2 all -- * * 0.0.0.0/0 0.0.0.0/0 /* default/istio-ingressgateway:http2 loadbalancer IP */
0 0 KUBE-MARK-DROP all -- * * 0.0.0.0/0 0.0.0.0/0 /* default/istio-ingressgateway:http2 loadbalancer IP */
Chain KUBE-MARK-DROP (7 references)
pkts bytes target prot opt in out source destination
0 0 MARK all -- * * 0.0.0.0/0 0.0.0.0/0 MARK or 0x8000
复制代码
上面规则表示请求包转交给规则链KUBE-XLB-HBO2MBMQRZFAHKF2处理,若是不能匹配则丢弃(KUBE-MARK-DROP)tomcat
Chain KUBE-XLB-HBO2MBMQRZFAHKF2 (2 references)
pkts bytes target prot opt in out source destination
0 0 KUBE-SVC-HBO2MBMQRZFAHKF2 all -- * * 172.20.0.0/16 0.0.0.0/0 /* Redirect pods trying to reach external loadbalancer VIP to clusterIP */
80 4800 KUBE-SEP-EW7YLHH65NRUVIFQ all -- * * 0.0.0.0/0 0.0.0.0/0 /* Balancing rule 0 for default/istio-ingressgateway:http2 */
复制代码
能够看到该规则链有两条规则,因为咱们的请求来自于集群外,经过SLB(182.92.251.227:80)进入集群,因此匹配第二条规则KUBE-SEP-EW7YLHH65NRUVIFQbash
Chain KUBE-SEP-EW7YLHH65NRUVIFQ (2 references)
pkts bytes target prot opt in out source destination
0 0 KUBE-MARK-MASQ all -- * * 172.20.1.157 0.0.0.0/0 /* default/istio-ingressgateway:http2 */
80 4800 DNAT tcp -- * * 0.0.0.0/0 0.0.0.0/0 /* default/istio-ingressgateway:http2 */ tcp to:172.20.1.157:80
Chain KUBE-MARK-MASQ (102 references)
pkts bytes target prot opt in out source destination
241 14460 MARK all -- * * 0.0.0.0/0 0.0.0.0/0 MARK or 0x4000
复制代码
咱们的请求包匹配DNAT这条,DNAT将咱们的请求目标地址转换为172.20.1.157:80,并交给上层协议栈处理,这样请求会走到routing decision(下面截图来自于维基百科中大牛整理的Iptables/Netfilter的流转图) 网络
# work001
➜ ~ ip route
default via 192.168.0.253 dev eth0
169.254.0.0/16 dev eth0 scope link metric 1002
169.254.123.0/24 dev docker0 proto kernel scope link src 169.254.123.1
172.20.1.128/25 dev cni0 proto kernel scope link src 172.20.1.129
192.168.0.0/24 dev eth0 proto kernel scope link src 192.168.0.17
复制代码
因为172.20.1.157:80知足第三条172.20.1.128/25 dev cni0 proto kernel scope link src 172.20.1.129,该请求将直接交给网桥设备cni0(ip是172.20.1.129)处理
这样请求就来到了cni0网桥
➜ ~ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE
caf-sample-mesh-tomcat-77ff76b78f-fhgcl 2/2 Running 0 7d 172.20.1.167 cn-beijing.i-2zef83gtte2gddxlpy3q <none>
istio-ingressgateway-84b4868f6b-9xnts 1/1 Running 0 15d 172.20.1.157 cn-beijing.i-2zef83gtte2gddxlpy3q <none>
istio-ingressgateway-84b4868f6b-qxz5t 1/1 Running 0 22h 172.20.2.7 cn-beijing.i-2zeg4wnagly6jvlcz5kr <none>
zookeeper-854f49888f-4zhhk 2/2 Running 0 8d 172.20.1.165 cn-beijing.i-2zef83gtte2gddxlpy3q <none>
复制代码
可以看到172.20.1.157这个IP由这个istio-ingressgateway-84b4868f6b-9xnts POD持有,进入这个POD,
➜ ~ kubectl exec -it istio-ingressgateway-84b4868f6b-9xnts bash
root@istio-ingressgateway-84b4868f6b-9xnts:/# ip route
default via 172.20.1.129 dev eth0
172.20.0.0/16 via 172.20.1.129 dev eth0
172.20.1.128/25 dev eth0 proto kernel scope link src 172.20.1.157
复制代码
咱们知道K8S内的eth0网卡实际上是veth设备对的一边放在了POD的网络namespace内,而且重命名成eth0,另外一端在宿主机上插在网桥cni0上,从宿主机上能够查看
➜ ~ brctl show
bridge name bridge id STP enabled interfaces
cni0 8000.0a58ac140181 no veth0982819b
veth21f3386e
veth295aca54
veth29c64f6d
veth2fc83624
veth5413f391
veth55b5c32f
veth5d630032
veth5f4b9957
veth67b85819
veth6e5e5662
veth6efeda57
veth7413a550
veth831d20f5
veth849fecd0
veth8dbe1d2c
vetha7ec9173
vetha83f9559
vethcc9d3b42
vethd967d407
vethec751a37
vethf69ed27b
复制代码
这时网桥cni0其实充当了二层交换机设备,全部发往cni0的数据包会路由给相应的veth对的另外一边,也就是在容器POD的网络namespace内的eth0网卡,咱们的示例中是:POD istio-ingressgateway-84b4868f6b-9xnts(IP为172.20.1.157)
历经重重关卡,咱们的请求包终于到达istio-ingressgateway容器内部,下面来总结下:
本讲咱们主要介绍了,外网(集群外)请求包如何经过阿里云的四层负载均衡设备SLB转发到咱们集群内的POD(实际上是istio-ingressgateway)中,也就是咱们Service Mesh理念中常说的南北向流量,其实这块的网络转发所有是由阿里云的LoadBalancer(K8s的一种Service类型,由各个云提供商来实现)以及K8s的cni网络插件来实现的,目前还没Istio什么事
下一讲咱们就来介绍下这个请求包在istio-ingressgateway中是如何流转,及istio如何控制这个南北向流量的,敬请期待吧