【服务网格】最佳实践在哪里-2.5:多集群服务发现

简介: 在《最佳实践在哪里-2:多集群流量管理》中,我们主要探讨了同一套微服务在多集群环境下的冗余部署以及集群内流量保持实现。不过,多集群部署的使用方式也并非只有这一种;根据实际情况,我们也有可能以其它的方式在多集群中部署服务。比如,我们选择多集群部署可能并非是需要它的故障隔离和故障转移能力,而只是希望服务和其依赖的数据库等外部资源部署在同一地域,以缩短调用时延;在这种情况下,我们可能会将包含多个微服务的

在《最佳实践在哪里-2:多集群流量管理》中,我们主要探讨了同一套微服务在多集群环境下的冗余部署以及集群内流量保持实现。不过,多集群部署的使用方式也并非只有这一种;根据实际情况,我们也有可能以其它的方式在多集群中部署服务。比如,我们选择多集群部署可能并非是需要它的故障隔离和故障转移能力,而只是希望服务和其依赖的数据库等外部资源部署在同一地域,以缩短调用时延;在这种情况下,我们可能会将包含多个微服务的一套应用程序部署在多个集群中,而非进行冗余部署。

我们以sleep服务和httpbin服务为例,演示上述的这种场景:

在这个例子中,由统一的服务网格控制面对集群1和集群2中的所有网格代理进行管理。服务之间的调用链为sleep -> httpbin;同时,只有集群1中部署了sleep Service、只有集群2中部署了httpbin Service。集群之间已经配置好了互访连通性(可以参考https://help.aliyun.com/document_detail/149550.html,进行多集群下互访连通性配置)。

应用部署

首先,我们准备两个集群,并参考https://help.aliyun.com/document_detail/150509.html,将两个集群都添加到同一个ASM实例中,这样我们就实现了使用同一个服务网格实例管理多个集群中的应用(多集群之间需要进行网络规划,参考https://help.aliyun.com/document_detail/424941.html)。

接下来,我们为两个集群的default命名空间打上istio-injection: enabled的标签,开启自动注入,并分别部署sleep和httpbin引用。

用kubectl连接到集群1,部署sleep应用:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: sleep
---
apiVersion: v1
kind: Service
metadata:
  name: sleep
  labels:
    app: sleep
    service: sleep
spec:
  ports:
  - port: 80
    name: http
  selector:
    app: sleep
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sleep
spec:
  replicas: 1
  selector:
    matchLabels:
      app: sleep
  template:
    metadata:
      labels:
        app: sleep
    spec:
      terminationGracePeriodSeconds: 0
      serviceAccountName: sleep
      containers:
      - name: sleep
        image: curl:8.1.2
        command: ["/bin/sleep", "infinity"]
        imagePullPolicy: IfNotPresent
        volumeMounts:
        - mountPath: /etc/sleep/tls
          name: secret-volume
      volumes:
      - name: secret-volume
        secret:
          secretName: sleep-secret
          optional: true
---

sleep内部是一个curl容器,可以很方便地利用curl实现作为客户端pod的功能。

接下来用kubectl连接集群2,部署httpbin应用:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: httpbin
---
apiVersion: v1
kind: Service
metadata:
  name: httpbin
  labels:
    app: httpbin
    service: httpbin
spec:
  ports:
  - name: http
    port: 8000
    targetPort: 80
  selector:
    app: httpbin
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin
      version: v1
  template:
    metadata:
      labels:
        app: httpbin
        version: v1
    spec:
      serviceAccountName: httpbin
      containers:
      - image: docker.io/kennethreitz/httpbin
        imagePullPolicy: IfNotPresent
        name: httpbin
        ports:
        - containerPort: 80

集群2内部署的httpbin应用是一个http Server工具箱,提供了多种测试http协议的工具箱接口,可以用作服务端pod使用。

通过分别部署在两个集群中的sleep和httpbin,我们目前理论上已经实现了上图的效果,那么现在就试试看吧!

多集群服务发现

我们直接执行进入集群1的sleep pod,尝试用curl调用httpbin服务。

$ kubectl exec -it sleep-86xxxxxxxx-xxxxx -c sleep -- sh
~ $ curl httpbin:8000
curl: (6) Could not resolve host: httpbin

遗憾的是,我们发现我们的设想似乎并不能work:此时跨集群调用并没能调通,显示的则是Could not resolve host: httpbin。这似乎与我们的设想不太一致,根据我们所知的信息,sleep容器发出的调用请求会被网格代理拦截,而网格代理是由多集群统一的服务网格控制面管理的,控制面应该已经为其下发了集群2中httpbin服务的端点信息,那么为什么会出现调用失败的情况呢?

其实非常简单,我们需要简单理解下网格代理拦截请求究竟拦截了个啥。

如果你学习过计算网络、或是刷过诸如“浏览器从敲下回车到显示网页都发生了啥”这种面试题,那么应该会知道:客户端在请求服务端时,若使用服务域名,则需要先向DNS服务器发送DNS请求,将域名解析为服务ip地址,再通过ip地址与服务端建立连接。

由于这层原因,网格代理拦截到客户端发送的请求时,实际得到的信息是请求目标的服务ip地址、而不是服务域名。而从域名到ip地址的解析,则仍然需要交给Kubentes集群的DNS服务去处理。在本例中,由于集群1中并没有部署名为httpbin的Service,自然也就无法解析httpbin这个域名,从而请求在DNS解析阶段就出错了,无法实际将请求发出。

如何解决这个问题呢?一种比较直观的思路是:既然问题在于集群1的DNS解析服务无法解析httpbin这个域名,让它能够解析就可以了;为此,我们需要在集群1中部署一个完全相同的httpbin Service,不需要为其部署工作负载,因为其存在意义仅仅是让集群1的域名解析可以正常工作。顺着这个思路,我们需要在两个集群中为所有服务都部署一个一模一样的Service,尽管有些Service可能在本集群内可能不存在对应的工作负载。

有没有更加简化的方法呢?我们知道,服务网格通过对接多个集群中的服务注册中心,其控制面也同样保存着服务ip地址到服务域名的映射、并且这些映射关系也都会被下发到多集群中每个网格代理之中。因此,使用网格代理代为响应DNS解析请求在理论上是完全可行的。

我们可以选择为网格代理启用“DNS代理功能”,启用DNS代理功能后,网格代理容器将拦截工作负载的DNS请求,以提高服务网格的性能和可用性。来自工作负载的所有请求将被重定向至网格代理容器。由于Sidecar代理容器在本地存储IP地址到本地域名的映射,网格代理容器将可以直接返回DNS响应给工作负载,避免再向远端的DNS服务发送请求。若DNS请求无法被网格代理容器处理,网格代理将会直接向集群的DNS服务转发DNS请求。

进入服务网格ASM的实例管理页面,选择Sidecar管理(数据面)> Sidecar代理配置,将启用DNS代理功能 开关打开。

由于Sidecar代理配置生效于Pod yaml,我们需要连接到集群1,然后重新部署Sleep应用,以令新的Sidecar代理配置生效,参考https://help.aliyun.com/document_detail/610989.html?spm=a2c4g.205486.0.0.7c31352akhtjko#p-4q2-0z4-6u6

此时我们重新尝试执行进入集群1的sleep pod,用curl调用httpbin服务。

$ kubectl exec -it sleep-bfxxxxxx-xxxxx -c sleep -- sh
~ $ curl httpbin:8000
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>httpbin.org</title>
...

请求成功了!证明DNS代理功能已经在正常工作~

小结

本文作为《最佳实践在哪里-2:多集群流量管理》的扩充,本文探讨了多集群环境下服务发现的基本问题,并探索了服务网格的DNS代理功能之最佳实践方式,我们发现DNS代理可以为我们带来以下好处:

  1. DNS代理功能可以在多集群部署环境下大显身手,只用一个开关,我们在任意一个集群中部署的服务,都可以被其他集群中的工作负载以域名的形式访问,无需多余配置。
  2. DNS代理功能还可以提高集群的性能与可用性。由于Pod发出的DNS解析请求都被位于Pod本地的网格代理容器所代理,DNS解析的响应效率将得到提高。同时,当集群中的DNS解析服务不可用时,DNS代理功能仍然可以保证服务之间通过域名的访问正常工作。

老子差点就没法调用我的意大利炮了,多亏有DNS代理功能!—— 李云龙

https://www.aliyun.com/product/servicemesh

相关文章
|
2天前
|
负载均衡 安全 网络协议
如何通过计算巢在ACK集群上使用Istio服务网格
本文主要介绍怎么通过计算巢部署Isito服务网格,并介绍了使用示例。
35 0
|
6月前
|
负载均衡 安全 Cloud Native
[大厂实践] 零配置服务网格与按需集群发现
[大厂实践] 零配置服务网格与按需集群发现
59 0
|
7月前
|
监控 安全 Cloud Native
构建无缝的服务网格体验:分享在生产环境中构建和管理服务网格的最佳实践
构建无缝的服务网格体验:分享在生产环境中构建和管理服务网格的最佳实践
29 0
|
7月前
|
Kubernetes 监控 Go
在Kubernetes上安装和配置Istio:逐步指南,展示如何在Kubernetes集群中安装和配置Istio服务网格
在Kubernetes上安装和配置Istio:逐步指南,展示如何在Kubernetes集群中安装和配置Istio服务网格
90 0
|
10月前
|
存储 Kubernetes 负载均衡
【服务网格】最佳实践在哪里-2:多集群流量管理
各位,多集群这个场景在服务网格这一块也算是越来越热了。早在1.4版本,istio社区就已经提出了多集群环境下istio的部署模型,提供统一的控制面管理多集群中服务的能力。而最近随着服务网格的配套可观测项目kiali推出v1.69版本,我们更是可以在一个kiali实例中就纵览多集群中的流量规则、流量拓扑与服务详情,多集群的使用体验逐渐完善,利用这个场景玩法的用户也是越来越多了。不过,任何新事物的引入
|
10月前
|
Kubernetes 负载均衡 安全
【服务网格】最佳实践在哪里-1:全链路灰度
作为完全兼容社区Istio的服务网格产品,服务网格ASM针对全链路灰度场景提出了自己的思考,并针对性地设计了对应的流量标签方案,来解决上述全链路灰度实现方案中的痛点问题。
|
Prometheus 监控 Kubernetes
使用ASM网格拓扑观测多集群的流量控制与容灾场景
作为业内首个全托管Istio兼容的阿里云服务网格产品ASM,一开始从架构上就保持了与社区、业界趋势的一致性,控制平面的组件托管在阿里云侧,与数据面侧的用户集群独立。ASM产品是基于社区Istio定制实现的,在托管的控制面侧提供了用于支撑精细化的流量管理和安全管理的组件能力。通过托管模式,解耦了Istio组件与所管理的K8s集群的生命周期管理,使得架构更加灵活,提升了系统的可伸缩性。从2022年4月
|
数据采集 存储 算法
服务网格ASM使用FAQ之(4):如何基于集群内服务层和网格层跨集群使用流量镜像
流量镜像主要用于能够在不以任何方式影响最终客户端的情况下测试具有实际生产流量的服务。 在实践中,无论是在生产环境还是非生产环境中,将生产流量镜像到测试集群,是降低新部署风险的一种非常有效的方法。像大型互联网企业,多年来也一直在坚持这么做。 服务网格技术提供了流量镜像(Traffic Mirroring)的功能,也称为影子流量(Traffic shadowing),会将实时流量的副本发送到镜像服务, 镜像流量发生在主服务的关键请求路径之外。
340 0
服务网格ASM使用FAQ之(4):如何基于集群内服务层和网格层跨集群使用流量镜像
|
Kubernetes 安全 网络协议
如何利用服务网格ASM让集群中监听localhost的应用能够被其它Pod访问
作为业内首个全托管Istio兼容的阿里云服务网格产品ASM,一开始从架构上就保持了与社区、业界趋势的一致性,控制平面的组件托管在阿里云侧,与数据面侧的用户集群独立。ASM产品是基于社区Istio定制实现的,在托管的控制面侧提供了用于支撑精细化的流量管理和安全管理的组件能力。通过托管模式,解耦了Istio组件与所管理的K8s集群的生命周期管理,使得架构更加灵活,提升了系统的可伸缩性。本文介绍如何在应
|
Kubernetes Cloud Native Java
服务网格的最佳实践
服务网格是用于处理服务间通信的专用基础设施层。它负责通过包含现代云原生应用程序的复杂服务拓扑来可靠地传递请求。
18270 1
服务网格的最佳实践