社区容器服务发现及负载均衡

技术
前言

得物社区云原生这方面走得比较快,所有 Go 服务都运行在 K8S 集群,已用上 Istio。后面进行了 Dubbo-go 改造,实现了传统微服务和新兴 ServiceMesh 一键切换。

K8S虽好,但也会带来额外的复杂度,特别是两套一起使用时。

让我们通过今天的文章深入其中,了解技术细节,直击问题本源 。

一、K8S 原生流量

讲 Istio 前,需先了解一下原生 K8S 技术细节。

服务发现

picture.image

K8S 的服务发现是通过 CoreDNS 和 Etcd

每个 ClusterIP 类型的 Service 资源会分配一个 VIP,并在 DNS 服务器中创建一条 A 记录,将域名<name>.<namespace>.svc指向其 VIP。

Etcd就是 K8S 的数据库,保存了所有资源的信息。

每个 Pod 会被分配一个 IP,并写入 Pod 资源中。每个 Service 对应一个 Endpoint 资源,Endpoint 中维护 Service 后端 Pod 的 IP 列表。

通过Etcd 的 watch 机制,监听 Endpoint 资源即可实现服务发现。

负载均衡

picture.image

K8S 原生服务负载均衡是通过 iptables 或 IPVS 实现。每台 Node 上的 kube-proxy 监听 Etcd 的 Endpoint,将SVC clusterIP 和PodIP 更新至 iptables,实现四层负载均衡。

既然 K8S 自带负载均衡,为啥还需要引入ServiceMesh?

因为这套负载均衡存在缺陷,不支持长连接。如 GRPC 使用原生 SVC 会有流量不均衡的问题。要向更精细的流量控制,需要七层负载均衡。

二、Istio 流量

服务发现

picture.image

Istio 的架构分为数据平面和控制平面。数据平面即 Sidecar 中的 Envoy,代理业务容器流量进出。控制平面 即 Istiod,监听 K8S Etcd 将 SVC clusterIP 和 PodIP 通过 XDS 协议下发至 Envoy,实现服务发现。

负载均衡

Istio 的负载均衡通过Sidecar实现,绕过了 K8S iptables 那套。业务容器访问某个 SVC 时,Envoy 中已配置 SVC name(domain) 到 PodIP 的路由规则,目标地址直接变成 PodIP,不需要经过 iptables VIP 到 PodIP 的负载。

Envoy 之所以能处理诸如 GRPC 之类的长连接,是因为其内置的 GRPC 模块。业务容器与 Envoy 之间建立一条长连接,Envoy 与后端多个 Pod 一一建立长连接,解析业务容器连接发过来的 Stream,将其负载到多个 Pod 上。

picture.image

流量劫持

picture.image

最后说说 Istio 最核心的流量劫持实现原理。上图是 K8S Pod 的网络模型,Pod 中多个容器共享 Net Namespace。

Pod 创建时,Istio 通过 webhook 给 Pod 注入 Init container,执行 init 命令istio-iptables -p 15001 -z 15006 -u 1337 -m REDIRECT -i '' -x "" -b '' -d 15090,15020

由于共享网络命令空间的缘故,此项配置在所有容器中生效。 这条命令的效果是劫持所有入站流量(inbound)重定向至 15006 端口,再劫持所有出站流量(outbound)重定向至 15001 端口。排除监控和健康检查使用的 15090、15020 端口。

三、Dubbo-go 流量

Istio 这套 ServiceMesh 方案服务,使用起来是很爽,无需很重的框架层即可接入微服务体系。但在这方面技术积累不够,遇到问题无人支持,Istio 相关配置不敢动,非常尴尬。ServiceMesh 的很多高级功能也没有使用起来。并且流量日益增长,Mesh 存在性能隐患,优化 Mesh 的技术难度和成本都非常高,轻则网络层,重则内核层。

另外,现在技术部对服务稳定性和可靠性也有更高的要求。在此背景下,社区进行了 Dubbo-go 服务改造,退回到传统微服务架构

Dubbo 这套架构比较简单,但简单的东西反而更可靠,并且性能也更好。Nacos 作为注册中心,应用集成侵入式框架,Provider 启动后将自己的容器 IP 上报至注册中心,Consumer 订阅获取 Provider IP 列表,在客户端通过轮询等算法实现负载均衡。

看到这里,大家也许会察觉 K8S、Istio 和传统微服务的服务发现原理都是相通,本质上都是 IP 地址的发布订阅

picture.image

四、网关流量

最后说说流量入口 —— 网关。社区的流量会经过两层网关,外层是 Java 网关,在此处理 JWT 鉴权,通过精确路由配置。

内层网关是 K8S Ingress,使用阿里云 SLB 将流量转发至 K8S 内部,具体使用的是 Istio Ingress Gateway,Istio gateway 同样是使用 Envoy。

picture.image

Istio 网关通过 Istio 的 CRD 资源 VirtualService 来配置,以下实例将 uri 以 /sns-event/ 开头的转发至 sns-event 这个 SVC 的 80 HTTP 端口;将 15029 端口转发至sns-event 这个 SVC 的 80 GRPC 端。

picture.image

*文/无风

0
0
0
0
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论