阅读 315

Istio多集群管理方案详解

随着Kubernetes成为云原生领域应用编排的标准,传统企业及新型互联网企业都在逐步将应用容器化及云化。为了实现高并发和高可用,企业通常会将应用部署在多集群甚至多云、混合云等多种环境中,因此,多集群方案逐步成为企业应用部署的最佳选择。很多云厂商都推出了自己的多云、混合云方案,虽然几乎都提供了多集群管理及跨集群的服务访问能力,但是在服务治理方面都有所欠缺。



因此,越来越多的用户对跨集群的服务治理表现出强烈的兴趣和需求。在此背景下,Istio作为Service Mesh领域的事实标准,推出了三种多集群管理方案,这里讲解其中的多控制面管理方案。


多控制面拓扑模型是在Istio 1.1中新增的一种多集群管理模型,如图7-1所示,每个Kubernetes集群都分别部署自己独立的Istio控制面,并且每个集群的控制面部署形态都是相似的,都各自管理自身的Endpoint。

图片

多控制面拓扑模型


多控制面模型还有以下特点。

  • 共享根CA。为了支持安全的跨集群通信mTLS,该模型要求每个集群控制面都使用相同的中间CA证书,供Citadel签发证书使用,以支持跨集群的TLS双向认证。

  • 不要求不同集群之间共享网络,即容器网络不需要打通,跨集群的访问通过Istio Gateway转发。

  • 每个Kubernetes集群的Pod地址范围与服务地址范围都可以与其他集群重叠,双方集群互不干扰,因为每个集群的Istio控制面都只管理自己集群的Endpoint。

  • 该模型依赖于DNS解析,允许服务实例解析本集群或者远端集群的服务名称。它除了使用了Kubernetes默认的cluster.local和<namesapce>.cluster.local后缀,还扩展了Pod的DNS解析,添加了对“.global”后缀的服务支持,以支持remote集群的服务地址解析。


在多控制面Gateway直连模型中,每个工作负载都可以像单集群一样使用典型的Kubernetes服务域名访问同一集群内的服务。然而对于Remote集群的服务访问,Istio扩展了CoreDNS服务器,处理“<name>.<namespace>.global”形式的服务地址解析。


在多控制面Gateway直连模型中,服务间的访问方式分为以下两种。

  • 同一集群内部的服务访问。这种访问方式与单集群模型没有任何区别。

  • 跨集群的服务访问。这种方式需要用户创建ServiceEntry规则,将Remote集群的服务暴露在本集群的服务网格内,并且由于集群之间的网络并不互通,所以这种模型依赖Remote集群的Gateway中转流量。


1

服务DNS解析的原理

在多控制面模型中,每个集群都由独立的Istio控制面管理。我们可以在宏观上认为不同集群的工作负载属于不同的网格。但是在微观上,其实是所有集群联合起来构建了一个大的网格,因为在本地集群中可以以服务域名的形式访问Remote集群的服务。例如,Remote集群的forecast服务在命名空间weather中,那么本地集群在访问forecast服务时使用的是forecast. weather.global域名。这种带“.global”后缀的域名是Istio在多控制面模型中设计的虚假域名。在本地集群中,DNS将这种带“.global”后缀的服务域名解析成一个虚假的在服务网格内没有使用的IP地址。


多控制面DNS的解析原理为:多控制面模型要求Istio能够提供Remote集群的服务地址解析,并且不影响已有的服务。典型的应用期望使用服务DNS名称解析服务地址,并通过地址访问服务。Istio的Sidecar本身在服务之间路由请求时并不使用DNS名称,但是Istio离不开DNS解析,这是因为在一般情况下服务实例是以域名形式访问其他服务的,所以在服务实例发起请求时首先进行DNS解析,才能将请求发送出去。本地集群的服务共享相同的DNS后缀(svc.cluster.local),Kubernetes集群默认的DNS服务器提供对这类服务的域名解析。


对于Remote集群的服务,本地集群的DNS显得束手无策,因为Kubernetes DNS只能通过Kube-apiserver获取本集群的服务及服务实例信息。Istio为支持Remote集群的服务DNS解析,做出了如下要求。


1、在每个Kubernetes集群中都额外部署一个istiocoredns组件

istiocoredns与在集群中默认安装的kube-dns和CoreDNS是级联的关系,协助默认的DNS服务器解析带“.global”后缀的服务,因此需要配置kube-dns和CoreDNS的私有DNS域服务器。如下所示为kube-dns服务器配置私有DNS域(stub domains):

apiVersion: v1

kind: ConfigMap

metadata:  

      name: kube-dns  

      namespace: kube-system  

      data:

stubDomains: |  

      {"global": ["$(kubectl get svc -n istio-system istiocoredns -o jsonpath={.spec.clusterIP})"]}


CoreDNS的私有DNS域设置如下:

apiVersion: v1

kind: ConfigMap

metadata:

  name: coredns

 namespace: kube-system

data:  Corefile: |

    .:53 {

       errors

        health

        kubernetes cluster.local in-addr.arpa ip6.arpa {

          pods insecure

           upstream

           fallthrough in-addr.arpa ip6.arpa

        }

        prometheus :9153

        proxy . /etc/resolv.conf

        cache 30

        loop

        reload

        loadbalance

    }    global:53 {

        errors

        cache 30

        proxy . $(kubectl get svc -n istio-system istiocoredns -o jsonpath={.spec.clusterIP})  

  }


这两种DNS服务器的私有DNS域服务器都指向了istiocoredns服务,这样“<name>.<namespace>.global”类型的域名解析都会被转发到istiocoredns服务器上。至于istiocoredns服务器为什么可以解析“<name>.<namespace>.global”,请继续阅读下文。


2、为Remote集群服务创建ServiceEntry

我们可以通过创建ServiceEntry将Remote集群的服务暴露到本地集群内,除此之外,在多控制面模型中,ServiceEntry还可以用于带“.global”后缀的服务DNS进行解析。如下所示是remote集群的forecast服务在primary集群中创建的ServiceEntry:

apiVersion: v1

apiVersion: networking.istio.io/v1alpha3

kind: ServiceEntry

metadata:

  name: forecast

spec:

  hosts:

  # 必须是 name.namespace.global 的格式

  - forecast.weather.global

 # 将Remote集群的服务认为是网格内部的服务,因为所有的集群共享相同的根证书

  location: MESH_INTERNAL 

 ports:

  - name: http1

    number: 8000

    protocol: http

 resolution: DNS

  addresses:

  # 虚假的地址,所有发到这个地址的流量都会被Envoy拦截

  # 并转发到${CLUSTER2_GW_ADDR}

  - 127.255.0.2

  endpoints:

  # 集群2的入口网关地址

  - address: ${CLUSTER2_GW_ADDR}

   ports:

      http1: 15443 # Do not change this port value


其中,host名称必须是“<name>.<namespace>.global”形式,address字段必须是在网格中没有使用过的唯一IP地址,“<name>.<namespace>.global”服务的地址将被istiocoredns解析成该IP地址。必须将endpoints设置为Remote集群的Gateway的地址和端口,这里的端口必须是网关服务的TLS端口,默认是15443。

注意:在多控制面的多集群模式下,网关地址必须是从对端集群可以访问的地址,在一般情况下,会通过负载均衡器为网关服务分配一个从集群外部可以访问的虚拟IP地址。


继续回到forecast.weather.global域名解析的主题上来,Kubernetes集群默认部署的DNS服务器根本没有该类型服务的IP信息,但是配置了存根域DNS服务器istiocoredns。istiocoredns是Istio社区为了支持全局的服务DNS解析而专门部署的。Istio社区专门开发了一个CoreDNS插件(https://github.com/istio-ecosystem/istio-coredns-plugin/blob/master/ plugin.go)用于解析ServiceEntry获取全局服务的IP地址,然后与CoreDNS部署在同一个Pod中,通过gRPC协议提供“*.global”类型的服务的DNS解析。


“*.global”类型的服务域名解析流程如下:

  • 为支持Remote集群的forecast服务访问,需要创建ServiceEntry。

  • 在本地集群中访问“forecast.weather.global”服务时首先会进行DNS解析,Kubernetes集群内的DNS解析首先会被发送到kube-dns服务。

  • 默认的kube-dns/coredns根据存根DNS的设置,将“*.global”类型的域名解析请求转发到私有DNS服务器istiocoredns。

  • istiocoredns通过Kube-apiserver获取ServiceEntry进而获取“forecast.weather. global”的IP地址。


*.global类型的服务域名解析流程如下图所示。

图片

*.global类型的服务域名解析流程


2

Gateway连接的原理

在多控制面模型中,Istio对于底层网络连通性没有过多的要求,跨集群的服务访问完全通过Gateway转发,因而只需每个集群的Gateway服务都对外暴露一个虚拟IP地址,供集群外部访问。从网络拓扑来看,多控制面模型部署比较轻量化。


最简单的多控制面跨集群访问模型如图7-3所示,其中,Cluster1中的frontend服务访问Cluster2中的forecast服务,集群1中的工作负载发起到forecast.weather.global的请求,请求首先被Sidecar拦截,Sidecar再根据配置规则将请求转发到Cluster2的Gateway,Gateway再将请求转发到forecast服务实例,基本的流量转发依赖Istio的ServiceEntry、Gateway、VirtualService配置规则。


随着多集群的复杂度提高,例如在级联多集群场景下,相同的应用及服务跨集群部署频见,这对Istio配置规则的设置要求非常高,并且很难自动控制不同集群中服务实例的负载均衡权重。虽然这种多控制面模型基本能够满足跨集群的服务访问,但是需要额外设置很多VirtualService、DestinationRule、Gateway、ServiceEntry等API对象,比较复杂。

图片

最简单的多控制面跨集群访问模型



文章分类
后端
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐