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

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器镜像服务 ACR,镜像仓库100个 不限时长
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: 主要描述服务网格中DNS代理功能在多集群服务发现之中的妙用

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

image.png


在这个例子中,由统一的服务网格控制面对集群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代理功能 开关打开。

image.png

由于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服务。

$ kc 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👈👈👈

相关文章
|
16天前
|
Kubernetes 安全 Serverless
基于Service Mesh管理Knative流量最佳实践
Istio扩展了Kubernetes,以建立可编程、应用程序感知的服务网格(Service Mesh)。Istio与Knative结合使用,可以为Serverless应用工作负载带来标准、通用的流量管理、可观测和安全性能力。
基于Service Mesh管理Knative流量最佳实践
|
10月前
|
Kubernetes 安全 Cloud Native
Service Mesh和Kubernetes:加强微服务的通信与安全性
Kubernetes已经成为云原生应用程序的事实标准,它为容器编排和管理提供了出色的解决方案。然而,微服务架构的广泛采用使得服务之间的通信变得复杂,同时安全性和可观测性需求也在不断增加。这正是Service Mesh技术的用武之地。本文将深入探讨Service Mesh如Istio和Linkerd如何增强Kubernetes集群中微服务的通信和安全性。
155 0
|
11月前
|
存储 Kubernetes 调度
【云原生】k8s核心概念—Pod & Controller & Service & Serect & ConfigMap介绍——20230213
【云原生】k8s核心概念—Pod & Controller & Service & Serect & ConfigMap介绍——20230213
219 0
|
存储 Kubernetes 负载均衡
【Service Mesh】最佳实践在哪里-2:多集群流量管理
服务网格 - 多集群流量管理最佳实践相关思考
|
负载均衡 Kubernetes 监控
微服务之Service Mesh浅析
随着技术体系的不断革新,基于原有的模式或思路使得软件的架构越来越难以维护,无论是国外还是国内的软件行业,都得到进一步的证实。依据各大主流技术论坛或者商业网站,目测,全球大约有85%以上的企业计划使用或者正在使用微服务体系生态。毕竟,原有的单一架构体系难以继续开发和持续维护,而基于微服务生态则允许使用较小的目标服务来实现更大的敏捷性收益。
350 0
|
JSON Kubernetes Cloud Native
【云原生|K8s系列第5篇】:实战使用Service暴露应用
本期文章是K8s系列第5篇,主要是实战使用Service暴露应用。通过本期文章:我们将学习了解 Kubernetes 中的 Service,学习标签(Label) 和 标签选择器(Label Selector) 对象如何与 Service 关联,最后在 Kubernetes 集群外用 Service 暴露应用。 ———————————————— 版权声明:本文为CSDN博主「程序员洲洲」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/weixin_51484460/article/details/1260
【云原生|K8s系列第5篇】:实战使用Service暴露应用
|
负载均衡 监控 网络协议
Service Mesh之Sidecar
时间总是给你意外,在使用微服务架构吗?还在考虑使用哪种微服务架构呢?要准备大干一场,学习spring cloud吗? 还在纠结这些问题时,这些技术都将要被淘汰了,下一代微服务Service Mesh出现了
272 0
Service Mesh之Sidecar
|
Prometheus Kubernetes Cloud Native
腾讯云 K8S 集群实战 Service Mesh—Linkerd2 & Traefik2 部署 emojivoto 应用
腾讯云 K8S 集群实战 Service Mesh—Linkerd2 & Traefik2 部署 emojivoto 应用
355 0
腾讯云 K8S 集群实战 Service Mesh—Linkerd2 & Traefik2 部署 emojivoto 应用
|
域名解析 Kubernetes 网络协议
Kubernetes-Service介绍(二)-服务发现
Kubernetes提供两种客户端以固定方式获取后端访问地址的方式:环境变量和DNS方式。
|
Rust Prometheus Kubernetes
了解 Linkerd Service Mesh 架构
了解 Linkerd Service Mesh 架构
161 0