浅析ServiceMesh和Istio,你学会了吗?

开发 架构
分布式架构下将单独服务拆分成子服务,结合各种架构设计已经将分布式基石做好了,但是在业务层的架构设计上,还是有很多问题需要解决,比如子服务更新如何不影响全局,功能迭代如何足够快,如何细粒度的监控某些服务状态等。

1、什么是ServiceMesh?

1.1、从单体到分布式

从后台服务发展之初,其实一直面临一个问题,就是如何将多台服务器组成一个整体提供对外服务。毕竟单体服务功能单一,在发展前期已经满足各种需求,但是随着互联网的发展,服务类型越来越多,也越来越复杂,如果用单体架构思考,就会发现越来越难满足需求。为了解决这个问题,于是出现了分布式架构,将单体服务拆分成多个子服务,每个子服务负责不同的功能,然后通过网关组合子服务,对外提供服务。看似这样已经解决了单体服务的问题,但是随着子服务的增多,网关也会越来越复杂,而且每个子服务都需要单独维护,服务治理就变得非常复杂。为了解决这里复杂性,因此引入各种架构概念:

  • 用远程调用代替子服务之间的通信,统一管理通讯协议;
  • 用服务发现代替子服务的注册,统一管理服务地址;
  • 引入服务治理组件,统一管理子服务;
  • 引入旁路负载均衡,统一管理流量管理;...

1.2、微服务架构

分布式架构下将单独服务拆分成子服务,结合各种架构设计已经将分布式基石做好了,但是在业务层的架构设计上,还是有很多问题需要解决,比如子服务更新如何不影响全局,功能迭代如何足够快,如何细粒度的监控某些服务状态等。为了解决这些问题,于是出现了微服务架构,将业务从粒度上变成更加轻量,每个服务负责更小的业务,这样就可以更快的迭代,更细粒度的监控服务状态等。

1.3、ServiceMesh

虽然分布式基石做好了,微服务架构已经能解决业务层发展的一些问题,但是对于工程师来说,关心底层通讯协议,服务发现,负载均衡等这些细节,似乎有些繁琐,就如同使用Linux一样,如果开发者还需要关注什么是文件还是网络(在Linux中,一切皆文件),那对于负担太重了。于是随着Docker和K8S的发展,ServiceMesh 应运而生,作为云原生下的服务间通讯的中间件,屏蔽了底层通讯协议,服务发现,负载均衡等细节,让开发者只需要关注业务逻辑。

ServiceMesh架构图ServiceMesh架构图

发展最早的是Linkerd,通过 Sidecar 模式托管服务间的网络调用和调度,不过由于性能问题被开源社区放弃;第二代是由google发展的 Istio,重新开发了 Envoy 作为网关,将系统定义为数据面和控制面,数据面负责网络通讯和负载均衡,控制面负责服务治理,下面将详细介绍其架构和设计方式。

2、ServiceMesh 的开源实现:Istio

ServiceMesh有一些开源项目,其当前最流行是Google开源实现是 Istio,在2018年10月开源,目前已经发展到了1.2版本,其github地址为:

https://github.com/istio/istio

2.1、Istio架构图

Istio架构图如下:

Istio架构图Istio架构图

提供的功能:

  • 针对HTTP,gRPC,WebSocket和TCP协议提供负载均衡;
  • 精细的流量控制,比如A/B测试,金丝雀部署等;
  • 模块化的插件设计,可以通过API进行访问,频率限制等;
  • 全自动的请求遥测,包括请求的追踪,监控和日志;
  • 强大的安全功能,比如认证,授权,加密等;

2.2、Istio数据面

可以看到架构图上,每个服务都有一个sidecar,也就是 Envoy,这个就是数据面,负责服务间通讯和负载均衡。所有进入服务的请求都经过 Envoy,然后根据路由规则转发到相应的服务,所以 Envoy 被称为服务网格的入口。Envoy 架构图如下:

EnvoyEnvoy

当然,Envoy 并不是唯一的数据面,还有 Linkerd,Kuma 等,但是Envoy 性能比较好,所以目前使用最多。

2.3、Istio控制面

控制面负责服务治理,比如路由规则,安全策略等,是服务网格的控制核心,通过控制面,可以配置服务网格中各个组件的行为。为了结构化控制面的功能,Istio 将其分为Pilot,Mixer,Citadel组件,其各个部分对应的功能:

  • Pilot:负责服务发现,负载均衡,路由规则等,不过Pilot不提供服务注册,只提供标准化的接口,可以方便的对接到各个服务注册中心,比如Eureka,Etcd等,然后通过服务发现控制Envoy的动态转发能力;
  • Mixer:负责访问控制,策略执行等,在最初的Istio的架构设计中,Mixer是中心化的组件,由于Mixer提供了各种访问控制策略,所以Mixer的负载压力比较大,发起请求之前做一次逻辑检查,请求结束后还需要上报处理,Mixer接收的请求至少涨了原始请求的2倍。为了解决这个问题,Mixer增加了缓存的功能,逻辑处理和上报都由Mixer缓存完成,这样Mixer的负载压力就能缓解;
  • Citadel:负责安全功能,比如认证授权等,比如那些服务安全级别比较高,需要对请求做单独的加密处理或者角色控制,Istio 通过引入Citadel组件,将安全能力透明化;

2.4、详解 Envoy

Envoy是专为大型现代SOA(面向服务架构)设计的、用C++11开发的代理和通信总线,作为服务网格中的数据面,负责服务间通讯和负载均衡。开源地址:https://github.com/envoyproxy/envoy.git

(1)编译编译依赖:

  • C++11
  • bazel
git clone https://github.com/envoyproxy/envoy.git
cd envoy
bazel build //source/exe:envoy-static

(2)配置Envoy的配置文件为 yaml 格式,其配置文件分为两部分:

  • 静态配置:在启动时加载,后续不会变化;
  • 动态配置:在运行时加载,可以调用API动态修改;
  • 样例配置文件:
admin:                  # 监控配置
  address:
    socket_address:
      protocol: TCP
      address: 0.0.0.0
      port_value: 9901  # 监听的端口
static_resources:
  listeners:
  - name: listener_0
    address:
      socket_address:
        protocol: TCP
        address: 0.0.0.0
        port_value: 10000 # 监听的端口
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager # 过滤器名称
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          stat_prefix: ingress_http
          access_log:
          - name: envoy.access_loggers.stdout
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
          route_config:
            name: local_route
            virtual_hosts:
            - name: local_service
              domains: ["*"]
              routes:
              - match:
                  prefix: "/"
                route:
                  host_rewrite_literal: www.envoyproxy.io
                  cluster: service_envoyproxy_io
          http_filters:
          - name: envoy.filters.http.router
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
  clusters:
  - name: service_envoyproxy_io
    type: LOGICAL_DNS
    # Comment out the following line to test on v6 networks
    dns_lookup_family: V4_ONLY
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: service_envoyproxy_io
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: www.envoyproxy.io
                port_value: 443
    transport_socket:
      name: envoy.transport_sockets.tls
      typed_config:
        "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
        sni: www.envoyproxy.io

(3)服务启动和测试

./envoy -c envoy.yaml
curl -v localhost:10000

# 返回数据
TODO:

(4)Envoy架构

图片图片

Envoy包括几个部分:

  • listeners:监听器,负责监听端口,接收请求,比如上述的配置文件中监听10000端口;
  • filter Chains:过滤器链,可以在配置文件配置对于请求的处理链路,可以在任何一个套接字上,按我们的需要去拼接多个过滤器,来实现对流量的、不同功能的处理,比如上述的配置文件中的过滤器链,在监听器上添加了 HttpConnectionManager 过滤器,这个过滤器负责解析HTTP协议;
  • cluster defintios:设置转发到下游的upsteam server,比如上述配置文件中的cluster defintios,设置转发到www.envoyproxy.io这个域名;

Envoy提供了xDS API标准,什么是xDS?xDS是x-discovery service,也就是服务发现服务,Envoy通过xDS API获取配置信息,然后根据配置信息进行转发,包括几个类型,分别是:EDS(endpoint discovery service),LDS(listener discovery service)和CDS(cluster discovery service),对应实现节点服务发现,监听器服务发现和集群服务发现。

EnvoyEnvoy

Envoy支持L3/L4 filter架构,提供了对L3/L4网络代理功能,这是Envoy的核心功能,还支持TCP、UDP、HTTP、TLS证书认证、Redis、Postgres、MongoDb等诸多协议的filter;Envoy支持HTTP L7架构,提供了对HTTP协议的filter,支持HTTP1.1、HTTP2、HTTP3,gRPC等协议;Envoy还提供了健康检查,负载均衡,熔断,限流等功能,并且有强大的可观测性,包括metrics、tracing等;

(5)Envoy处理请求流程

  • 某请求经过TCP链接被处于某个worker线程的listener接受;
  • listener filter链被创建,一个listener可以有多个filter链,主要用于SNI、相关等处理,一旦处理完成,listener将匹配一个network filter链,如HTTP connection manager;
  • listener filter链可以与TLS关联,以解密被加密的数据,network filter链被创建,如HTTP connection manager;
  • HTTP/2编解码器将TCP流解帧为独立的stream,每个stream处理一对request/response;
  • 对于每个HTTP stream,一个下游http filter被创建,其中最重要的是route filter,它必须位于HTTP filter链的末端;
  • route filter根据配置来选定请求要被路由到哪个cluster(route filter将从cluster获取HTTP connection pool);
  • cluster通过负载均衡策略选定最终的上游节点,其中还涉及到了断路器与健康检查等机制,若HTTP connection pool不存在存活的链接,则一个与上游节点的新链接将被建立;
  • 对于每个stream,一个上游HTTP filter链将被创建,默认情况下只有codec filter,它主要负责将请求编码给上游节点,并将上游节点的回包解码;
  • 处理与上游节点相关的TLS,而后将请求发送到上游节点;
  • 收到上游节点的回包后,回包以相反顺序依次经过HTTP filter,包括上游codec filter,route filter等filter,最终被发送到下游;
  • 最后stream被销毁,更新整个过程中产生的统计数据与日志;

3、Istio实践

Istio 是基于K8S编排服务,而K8S网络相关的知识点,在《Kubernetes核心原理》做过一些介绍,这里再回顾一下:

  • K8S的物理资源是Node,每个Node上运行一个Kubelet进程,而Node上运行的Pod,就是K8S的逻辑资源;
  • 每个Pod都有一个IP地址,通过该IP地址可以访问到Pod;
  • 如果声明Deploymnet,则K8S会为该Deployment创建一组Pod,每个Pod的IP地址是不同的,为了这些Pod实现负载均衡,K8S会为每个Pod创建一个Service,Service的IP地址是固定的,通过该IP地址可以访问到一组Pod;
  • Service的IP地址是虚拟IP,K8S通过iptables规则将Service的IP地址映射到Pod的IP地址;
  • 在K8S中服务发现,是通过CoreDNS实现的DNS服务来找到对应的Service的IP;

而在Istio中,每个Pod都有一个对应的Sidecar,Sidecar负责与K8S进行通信,可以登陆到业务的Pod中执行ps aux,会看到proxy的进程,具体istio的pods详细如下图:

详情详情

如果你想继续探究内部实现,可以尝试自己安装Istio,如果你没有自己的可用集群,可以使用Kubernetes Playground,打开链接:https://labs.play-with-k8s.com/具体可以参考这篇文章:https://www.knowledgehut.com/blog/cloud-computing/test-drive-your-first-istio-deployment-using-play-with-kubernetes-platform-cloud-computing

对应的脚本已经准备好了,可以先执行istio-preinstall.sh:

#!/bin/bash
kubeadm init --apiserver-advertise-address $(hostname -i)
mkdir -p $HOME/.kube
chown $(id -u):$(id -g) $HOME/.kube/config
kubectl apply -n kube-system -f "https://cloud.weave.works/k8s/net?k8s-versinotallow=$(kubectl version | base64 | tr -d '\n')"

然后执行istio-install.sh:

#!/bin/bash
curl -L https://git.io/getLatestIstio | sh -
export PATH=$PWD/bin:$PATH
cd istio-1.21.2
istioctl manifest apply --set profile=demo --set values.gateways.istio-ingressgateway.type=ClusterIP

最后执行:kubectl -n istio-system get pod 可以看到isito-ingressgateway和istio-pilot的pod状态都是running。

参考

(1)https://cloud.tencent.com/developer/article/1351311

(2)https://labs.play-with-k8s.com/

(3)https://blog.csdn.net/KeyarchOS/article/details/135782578

责任编辑:武晓燕 来源: 周末程序猿
相关推荐

2024-01-08 07:29:57

多集群模型Istio网络拓扑

2024-07-17 09:23:58

Vite插件机制

2024-01-18 09:38:00

Java注解JDK5

2023-07-10 08:36:21

工具pptword

2023-07-26 13:11:21

ChatGPT平台工具

2024-02-04 00:00:00

Effect数据组件

2024-01-19 08:25:38

死锁Java通信

2023-01-10 08:43:15

定义DDD架构

2023-08-01 12:51:18

WebGPT机器学习模型

2024-01-02 12:05:26

Java并发编程

2024-11-08 08:56:01

2022-11-21 16:57:20

2024-07-31 08:39:45

Git命令暂存区

2022-07-08 09:27:48

CSSIFC模型

2024-08-06 09:47:57

2023-01-30 09:01:54

图表指南图形化

2024-05-06 00:00:00

InnoDBView隔离

2023-10-10 11:04:11

Rust难点内存

2023-12-12 08:02:10

2022-06-16 07:50:35

数据结构链表
点赞
收藏

51CTO技术栈公众号