乐趣区

关于云计算:开放服务网格-Open-Service-Mesh-如何开放

TL;DR

本文从服务网格倒退现状、到 Open Service Mesh 源码,剖析凋谢服务网格中的凋谢是什么以及如何凋谢。笔者总结其凋谢体现在以下几点:

  1. 资源提供者(Provider)接口和资源的从新封装:通过资源提供者接口形象计算平台的资源,并封装成平台、代理无关的结构化类型,并由对立的接口 MeshCataloger 对外提供拜访。尽管目前只有 Kubernetes 相干资源的 Provider 实现,然而通过形象出的接口,能够兼容其余平台,比方虚拟机、物理机。
  2. 服务网格能力接口:对服务网格能力的形象,定义服务网格的根底功能集。
  3. 代理管制面接口:这一层与反向代理,也就是 sidecar 的实现相干。实际上是反向代理所提供的接口,通过对接口的实现,加上 MeshCataloger 对资源的拜访,生成并下发代理所需的配置。

背景

服务网格是什么

服务网格是在 2017 年由 Buoyant 的 Willian Morgan 在 What’s a service mesh? And why do I need one? 给出了解释。

服务网格是解决服务间网络通信的基础设施组件,旨在从平台层面提供可观性、平安以及可靠性个性,以过程外的形式提供本来由局部应用层逻辑承载的根底能力,真正实现与业务逻辑的拆散。典型的实现是与应用程序一起部署的可扩大网络代理(通常称为 sidecar 模型),来代理服务间的网络通信,也是服务网格个性的接入点。这些代理就组成了服务网格的 数据立体 ,并由 管制立体 进行对立的治理。

图片来自 Pattern: Service Mesh

服务网格现状

过来几年 Istio 有着成为服务网格事实标准的趋势,但时至今日,各种各样的服务网格产品如雨后春笋般层出不穷。CNCF 公布的 2021 Cloud Native survey results 中不难看出,这些网格产品也缓缓被市场所承受,并大有超过 Istio 的态势(局部地区)。

关上 CNCF 的服务网格全景图,会发现有不少服务网格的产品。实际上还有很多产品没有列出,比方 HashiCorp Consul Connect、OpenShift Service Mesh、Nginx Service Mesh、Kong Mesh、SOFAMesh 等等,当然还有我司的 Flomesh。此外还有一些云厂商基于开源的网格产品。

这些产品有些应用雷同的数据立体,也有些不同,但管制立体各不相同。泛滥产品为大家提供了更多抉择的同时,也因为各个产品间有着很强的隔离性,妨碍了生态系统的倒退。这导致很难从一个实现切换到另一个,从管制面到到数据面,以及为其开发的治理后盾都有从新开发的老本。此外,还有用户应用习惯的扭转,无奈做到通明无感知。

针对这种诉求,依照“常规”就是借助规范 接口 来进行形象,提供实现的互通性。比方容器网络、运行时、存储有 CNI、CRI、CSI 接口,服务网格也有其形象接口 Service Mesh Interface(简称 SMI),以及其实现也就是明天的配角 Open Service Mesh(简称 OSM)。

SMI 与 OSM 简介

在 CNCF 的服务网格全景图中能够看到 SMI 和 OSM。

SMI 是什么

SMI 是服务网格的标准,重点关注在 Kubernetes 上运行的服务网格。它定义了一个能够由各种供应商应用的通用规范。容许最终用户的标准化和服务网格技术提供商的翻新。SMI 实现了灵活性和互操作性,并涵盖了最常见的服务网格性能。

SMI 提供了 Kubernetes 服务网格的标准接口、常见服务网格场景的根本功能集、反对服务网格新性能的灵活性,以及服务网格技术生态的翻新空间。

SMI 的指标是将概念与实现隔离开来,像软件开发过来始终做的那样,将简单的货色分层形象。

SMI 标准的最新版本是 0.6.0,笼罩了常见的流量访问控制、遥测、治理等根底服务网格能力。与标准对应的是 API,各个网格供应商基于该 API 进行实现。

OSM 是什么

OSM 是一个轻量级可扩大的云原生服务网格,是简略、残缺且独立的服务网格解决方案,它容许用户对立治理、爱护并取得针对高度动静微服务环境的开箱即用的可察看性功能。OSM 运行在 Kubernetes 之上管制立体实现了 xDS API 并配置了 SMI API,为应用程序注入 Envoy sidecar 容器作为代理,通过 SMI Spec 来援用网格中的服务。

尽管默认状况下应用 Envoy 作为数据立体,然而设计上提供接口的形象,反对兼容 xDS 的代理,甚至其余的代理。

SMI 标准

SMI 标准为常见服务网格能力提供了一套标准:

  • 流量策略:跨服务利用身份和传输加密等策略。
  • 流量遥测:捕捉要害指标,如错误率和提早。
  • 流量治理:在不同服务之前转移流量。

流量策略

这个标准是用来指定利用的流量表现形式,并与拜访控制策略联合来定义特定流量在服务网格中的行为。

比方上面的定义中,/metrics 端点仅对外提供 GET 形式拜访,比方 Prometheus。而其余端点,反对所有形式。

kind: TCPRoute
metadata:
  name: the-routes
spec:
  matches:
    ports:
    - 8080
---
kind: HTTPRouteGroup
metadata:
  name: the-routes
spec:
  matches:
  - name: metrics
    pathRegex: "/metrics"
    methods:
    - GET
  - name: everything
    pathRegex: ".*"
    methods: ["*"]

上面的定义,则在后面的根底上,容许 Prometheus(应用 prometheus ServiceAccount 部署)拜访所有 service-a ServiceAccount 的利用的 /metrics 端点。

kind: TrafficTarget
metadata:
  name: path-specific
  namespace: default
spec:
  destination:
    kind: ServiceAccount
    name: service-a
    namespace: default
  rules:
  - kind: TCPRoute
    name: the-routes
  - kind: HTTPRouteGroup
    name: the-routes
    matches:
    - metrics
  sources:
  - kind: ServiceAccount
    name: prometheus
    namespace: default

流量治理

访问控制以外的流量治理,更多是体现在流量的拆分上。流量拆分 TrafficSplit 用于实现将流量按百分比拆分到同一应用程序的不同版本。

上面的定义中,将来自 Firefox 申请全都路由到 website 的 v2 版本,实现金丝雀公布。在理论场景中的操作流程,参考 SMI 的示例。

kind: TrafficSplit
metadata:
  name: ab-test
spec:
  service: website
  matches:
  - kind: HTTPRouteGroup
    name: ab-test
  backends:
  - service: website-v1
    weight: 0
  - service: website-v2
    weight: 100
---
kind: HTTPRouteGroup
metadata:
  name: ab-test
matches:
- name: firefox-users
  headers:
    user-agent: ".*Firefox.*"

流量遥测

流量遥测还是处于很晚期的版本 v1alpha1

该标准形容了一种资源,该资源为工具提供了一个通用集成点,这些工具能够通过应用与 HTTP 流量相干的指标而受害。对于即时指标它遵循 metrics.k8s.io 的模式,这些指标可被 CLI 工具、HPA 扩大或自动化金丝雀更新应用。

比方上面定义了从 Pod foo-775b9cbd88-ntxsl 到 Pod baz-577db7d977-lsk2q 的提早以及成功率指标。

kind: TrafficMetrics
# See ObjectReference v1 core for full spec
resource:
  name: foo-775b9cbd88-ntxsl
  namespace: foobar
  kind: Pod
edge:
  direction: to
  side: client
  resource:
    name: baz-577db7d977-lsk2q
    namespace: foobar
    kind: Pod
timestamp: 2019-04-08T22:25:55Z
window: 30s
metrics:
- name: p99_response_latency
  unit: seconds
  value: 10m
- name: p90_response_latency
  unit: seconds
  value: 10m
- name: p50_response_latency
  unit: seconds
  value: 10m
- name: success_count
  value: 100
- name: failure_count
  value: 100

OSM 的设计

OSM 的管制层面蕴含了五个外围组件:

  • Proxy Control Plane:代理管制面在操作服务网格中起着关键作用,所有以 sidecar 形式运行的代理,都会与其建设连贯,并一直地承受配置的更新。这个组件实现反向代理所需的接口。目前 OSM 应用 Envoy 作为其默认的代理实现,因而这个组件实现了 Envoy 的 xDS API。
  • Certificate Manger:证书管理器组件为网格中的服务提供 TLS 证书,这些证书用于应用 mTLS 建设和加密服务之间的连贯。
  • Endpoints Providers:端点提供者是与计算平台(Kubernetes 集群、云主机、本地机器)交互的一系列组件的统称。端点提供者将服务名解析为 IP 地址。
  • Mesh Specification:网格标准是现有 SMI 标准组件的封装。该组件形象了为 YAML 定义的特定存储。这个模块实际上是 SMI Spec 的 Kubernetes informers 的封装。
  • Mesh Catalog:是 OSM 的外围组件,它将其余组件的输入组装成新的构造。新的构造能够转换为代理配置并通过代理管制面分发给所有的代理。

这几个形象的组件,都有接口与其一一对应,

  • Proxy Control Plane:Envoy AggregatedDiscoveryServiceServer
  • Certificate Manger:certificate.Manager
  • Endpoints Providers:endpoint.Provider
  • Mesh Specification:smi.MeshSpec
  • Mesh Catalog:catalog.MeshCataloger

源码剖析

代理管制立体接口

基于 Evnoy 代理的服务网格实现,代理管制面都要实现 AggregatedDiscoveryServiceServer 接口。目前 OSM 实现的是 V3 版本的接口。深刻到代码中,OSM 的 ads.Server 实现了 AggregatedDiscoveryServiceServer 接口。

ads.Server 的定义中能够看到其余组件接口 catalog.MeshCatalogercertificate.Manager 的身影。

// Server implements the Envoy xDS Aggregate Discovery Services
type Server struct {
    catalog        catalog.MeshCataloger
    proxyRegistry  *registry.ProxyRegistry
    xdsHandlers    map[envoy.TypeURI]func(catalog.MeshCataloger, *envoy.Proxy, *xds_discovery.DiscoveryRequest, configurator.Configurator, certificate.Manager, *registry.ProxyRegistry) ([]types.Resource, error)
    xdsLog         map[certificate.CommonName]map[envoy.TypeURI][]time.Time
    xdsMapLogMutex sync.Mutex
    osmNamespace   string
    cfg            configurator.Configurator
    certManager    certificate.Manager
    ready          bool
    workqueues     *workerpool.WorkerPool
    kubecontroller k8s.Controller

    // ---
    // SnapshotCache implementation structrues below
    cacheEnabled bool
    ch           cachev3.SnapshotCache
    srv          serverv3.Server
    // When snapshot cache is enabled, we (currently) don't keep track of proxy information, however different
    // config versions have to be provided to the cache as we keep adding snapshots. The following map
    // tracks at which version we are at given a proxy UUID
    configVerMutex sync.Mutex
    configVersion  map[string]uint64

    msgBroker *messaging.Broker
}

此处,不得不提一下 messaging.Broker,OSM 管制立体的“音讯总线”。集群中,任何资源(K8s 原生资源、OSM 定义资源、SMI 资源)的变更,都会以事件的形式公布到音讯总线。

特定事件音讯的订阅方在接管到事件后就会执行特定的逻辑。

这里 ads.Server 在启动 grpc 服务后,便会订阅 ProxyUpdate 事件,收到事件会触发对应的逻辑:通过 catalog.MeshCataloger 的实现获取结构化的数据,进而转换成代理的配置并发送给代理。

在 OSM 中 ProxyUpdate 事件是一些事件的汇合,这些事件最终都会被“当作” ProxyUpdate 事件进行解决。

网格目录接口

Mesh Catalog 的接口 catalog.MeshCataloger,定义了一些用于生成结构化数据的办法。这些结构化的数据,是在 K8s 原生资源、SMI 自定义资源的根底上的封装。作为底层资源和代理管制面的中间层,对上隔离了底层资源的实现,对下对立了资源的对外裸露模式。

// MeshCataloger is the mechanism by which the Service Mesh controller discovers all Envoy proxies connected to the catalog.
type MeshCataloger interface {
    // ListOutboundServicesForIdentity list the services the given service identity is allowed to initiate outbound connections to
    ListOutboundServicesForIdentity(identity.ServiceIdentity) []service.MeshService

    // ListOutboundServicesForMulticlusterGateway  lists the upstream services for the multicluster gateway
    ListOutboundServicesForMulticlusterGateway() []service.MeshService

    // ListInboundServiceIdentities lists the downstream service identities that are allowed to connect to the given service identity
    ListInboundServiceIdentities(identity.ServiceIdentity) []identity.ServiceIdentity

    // ListOutboundServiceIdentities lists the upstream service identities the given service identity are allowed to connect to
    ListOutboundServiceIdentities(identity.ServiceIdentity) []identity.ServiceIdentity

    // ListServiceIdentitiesForService lists the service identities associated with the given service
    ListServiceIdentitiesForService(service.MeshService) []identity.ServiceIdentity

    // ListAllowedUpstreamEndpointsForService returns the list of endpoints over which the downstream client identity
    // is allowed access the upstream service
    ListAllowedUpstreamEndpointsForService(identity.ServiceIdentity, service.MeshService) []endpoint.Endpoint

    // GetIngressTrafficPolicy returns the ingress traffic policy for the given mesh service
    GetIngressTrafficPolicy(service.MeshService) (*trafficpolicy.IngressTrafficPolicy, error)

    // ListInboundTrafficTargetsWithRoutes returns a list traffic target objects composed of its routes for the given destination service identity
    ListInboundTrafficTargetsWithRoutes(identity.ServiceIdentity) ([]trafficpolicy.TrafficTargetWithRoutes, error)

    // GetEgressTrafficPolicy returns the Egress traffic policy associated with the given service identity.
    GetEgressTrafficPolicy(identity.ServiceIdentity) (*trafficpolicy.EgressTrafficPolicy, error)

    // GetKubeController returns the kube controller instance handling the current cluster
    GetKubeController() k8s.Controller

    // GetOutboundMeshTrafficPolicy returns the outbound mesh traffic policy for the given downstream identity
    GetOutboundMeshTrafficPolicy(identity.ServiceIdentity) *trafficpolicy.OutboundMeshTrafficPolicy

    // GetInboundMeshTrafficPolicy returns the inbound mesh traffic policy for the given upstream identity and services
    GetInboundMeshTrafficPolicy(identity.ServiceIdentity, []service.MeshService) *trafficpolicy.InboundMeshTrafficPolicy
}

接口的实现 catalog.MeshCatalog,也是通过几个接口获取底层的资源:

  • endpoint.Providerendpoint.Endpoint 形象资源的提供者,在目前 OSM 版本中提供获取 Kubernetes Endpoint 的实现。
  • service.Providerservice.MeshService 形象资源的提供者,目前同样是提供获取 Kubernetes Service 的实现。
  • smi.MeshSpec:故名思义针对是 SMI 自定义资源,间接应用 SMI 的定义,并没有从新形象封装。
  • k8s.Controller:用于获取 Kubernetes 原生资源,比方 ServiceAcount、Namespace、Pods 等。
  • policy.Controller:用于获取 OSM 的 EgressIngressBackend 资源。
// MeshCatalog is the struct for the service catalog
type MeshCatalog struct {endpointsProviders []endpoint.Provider
    serviceProviders   []service.Provider
    meshSpec           smi.MeshSpec
    certManager        certificate.Manager
    configurator       configurator.Configurator

    // This is the kubernetes client that operates async caches to avoid issuing synchronous
    // calls through kubeClient and instead relies on background cache synchronization and local
    // lookups
    kubeController k8s.Controller

    // policyController implements the functionality related to the resources part of the policy.openrservicemesh.io
    // API group, such as egress.
    policyController policy.Controller
}

文章对立公布在公众号 云原生指北

退出移动版