基于开源istio治理CCE多集群--扁平网络场景

举报
可以交个朋友 发表于 2024/07/25 16:46:38 2024/07/25
【摘要】 基于开源istio实现容器网络扁平场景下CCE多集群流量治理

一 背景

创建2个CCE turbo集群,扁平网络模式,每个集群pod网段 service网段不重合。现在需要业务容灾部署、主备形式运行。
image.png
image.png
正常情况下,如果不借助istio的能力,没办法实现通过service访问远端集群的业务。
image.png
只会将流量路由到本集群的业务中。
如果此时将本集群业务不可用,则会出现访问失败的情况
image.png


二 方案简介

针对上述网络环境,本文档将以多集群容器扁平网络多控制面架构进行istio的安装
image.png
若需实现该方案,需要回答如下关键问题:

  • 问题一、A、B集群的istiod如何获取到A、B集群的域名、clusterip、podip信息?
    答:获取A、B集群的kubeconfig凭证(注意凭证的权限和有效期),基于istioctl的remotesecret命令生成对端集群的访问凭证,使得本端集群istiod可同时连接本端集群(通过serviceaccount方式)、对端集群(通过remotesecret)的kube-apiserver。通过这种方式,A集群的istiod可以获取A、B集群的域名、clusterip、podip等全量信息。

  • 问题二、在A、B集群均部署相同业务前提下,某集群的istio-proxy如何将指定域名流量转发给两个集群的后端实例?
    答:在问题一的回复基础上,A集群istiod获取A、B集群的全量域名、clusterip、podip,将对应信息通过xDS协议下发给本集群各个Pod的istio-proxy组件。当业务容器访问某容灾业务域名时(A、B均部署相同业务,域名相同),istio-proxy拦截流量后获取到与该域名关联的A、B集群中的podip信息,由于本模拟场景A、B集群容器网络扁平和互通,所以该流量直接可转发给A、B集群的相关业务后端,实现多集群容灾。

  • 问题三、在A、B集群部署不同业务前提下,A集群如何通过B集群业务域名访问B集群后端实例,实现双集群东西向互访
    答:在问题一的回复基础上,A集群istiod获取A、B集群的全量域名、clusterip、podip,将对应信息通过xDS协议下发给本集群各个Pod的istio-proxy组件。当业务容器通过servicename.cluster访问B集群业务时(A集群无对应业务,该集群在B集群部署),需要先通过影子service或者开启istio智能dns代理能力,使得域名可以解析组成TCP包发送。istio-proxy拦截流量后获取到与该域名关联的A、B集群中的podip信息,由于本模拟场景A、B集群容器网络扁平和互通,所以该流量直接可转发给B集群的相关业务后端,实现多集群业务东西向互访。

  • 问题四、istio-proxy默认加密流量转发,为什么A、B集群isto-proxy可双向认证?
    答:A、B集群的istio-proxy要基于同一根证书签发证书,使得A、B集群istio-proxy证书互信。


三 多集群网格环境搭建

3.1 创建CA证书

  • 在istio多集群通信中,每个集群都会有一个istio控制面,其中包含一个CA服务,该CA服务会自动为每个集群中的Istio Sidecar 生成证书和密钥,并用于为Pod之间的mTLS加密认证提供证书签名。

  • 这些证书和密钥是由Istio CA服务签发的,以确保通信的安全性和可靠性。多集群服务网格部署要求网格中的所有集群之间建立信任关系,所以需要使用同一个根证书Root CA来签发中间态证书
    image.png


  1. 下载istio安装包
    wget https://github.com/istio/istio/releases/download/1.22.3/istio-1.22.3-linux-amd64.tar.gz
    CCE 集群的kubernetes 版本为1.28,可使用1.22版本的istio,kubernetes 和istio的对应关系 可参照:https://istio.io/latest/zh/docs/releases/supported-releases/#support-status-of-istio-releases

  2. 在 Istio 安装包的顶层目录下,创建一个目录来存放证书和密钥
    mkdir -p certs
    pushd certs
    image.png

  3. 生成根证书和密钥
    make -f ../tools/certs/Makefile.selfsigned.mk root-ca
    image.png
    将会生成以下文件:
    ○ root-cert.pem:生成的根证书
    ○ root-key.pem:生成的根密钥
    ○ root-ca.conf:生成根证书的 openssl 配置
    ○ root-cert.csr:为根证书生成的 CSR
    image.png

  4. 对于每个集群,为 Istio CA 生成一个中间证书和密钥
    make -f ../tools/certs/Makefile.selfsigned.mk cluster1-cacerts
    make -f ../tools/certs/Makefile.selfsigned.mk cluster2-cacerts
    image.png
    image.png
    运行以上命令,将会在名为 cluster1、cluster2 的目录下生成以下文件:
    ○ ca-cert.pem:生成的中间证书
    ○ ca-key.pem:生成的中间密钥
    ○ cert-chain.pem:istiod 使用的生成的证书链
    ○ root-cert.pem:根证书
    image.png

  5. 在每个集群中,创建一个私密 cacerts,包括所有输入文件 ca-cert.pem, ca-key.pem,root-cert.pem 和 cert-chain.pem

    kubectl create namespace istio-system
    kubectl create secret generic cacerts -n istio-system \
          --from-file=cluster1/ca-cert.pem \
          --from-file=cluster1/ca-key.pem \
          --from-file=cluster1/root-cert.pem \
          --from-file=cluster1/cert-chain.pem
    
    kubectl create namespace istio-system --context=cluster2
    kubectl create secret generic cacerts -n istio-system \
          --from-file=cluster2/ca-cert.pem \
          --from-file=cluster2/ca-key.pem \
          --from-file=cluster2/root-cert.pem \
          --from-file=cluster2/cert-chain.pem  --context=cluster2
    

    image.png

  6. 证书创建完毕,返回istio 安装目录
    popd
    image.png

  7. 备注:以上证书内容仅用于演示。对于生产型集群的设置,强烈建议使用生产型 CA,如 Hashicorp Vault。 在具有强大安全保护功能的离线机器上管理根 CA 是一个很好的做法。

  8. 在扁平网络模式下,跨集群通信是Pod与Pod直连,不需要经过Istio Gateway,因此不需要强制使用mTLS,可以不用配置mTLS证书。istio默认sidecar之间使用加密流量通信,取消mtls方式可参考如下:

    apiVersion: security.istio.io/v1beta1
    kind: PeerAuthentication
    metadata:
      name: "default"
      namespace: "istio-system" #网格范围:为根命名空间指定的策略
    spec:
      mtls:
        mode: DISABLE  #禁用双向 TLS,从安全角度来看,除非您提供自己的安全解决方案,否则请勿使用此模式。
    
    

3.2 将istio分别安装在各个集群中

因为是多istio控制面部署,所以每个集群都需要安装istio。本文档采用istioctl方式进行安装,安装API参数配置参考: https://istio.io/latest/zh/docs/reference/config/istio.operator.v1alpha1/

  1. cluster1集群istio安装配置

    apiVersion: install.istio.io/v1alpha1
    kind: IstioOperator
    spec:
      hub: swr.cn-north-4.myhuaweicloud.com/hjmtest #配置istio安装的镜像仓库
      meshConfig: 
        accessLogFile: /dev/stdout #开启访问日志
      values:
        global:
          meshID: mesh1
          multiCluster:
            clusterName: cluster1 
          network: network1  # 集群的网络标识
    

    istioctl install --context=cluster1 -f cluster1.yaml
    image.png

  2. cluster2 集群istio 安装配置

    apiVersion: install.istio.io/v1alpha1
    kind: IstioOperator
    spec:
      hub: swr.cn-north-4.myhuaweicloud.com/hjmtest #配置istio安装的镜像仓库
      meshConfig: 
        accessLogFile: /dev/stdout #开启访问日志
      values:
        global:
          meshID: mesh1 #和cluster1 同属于一个mesh
          multiCluster:
            clusterName: cluster2 #需要区别cluster1 
          network: network1  # 集群的网络标识,扁平网络,和cluster1 在同一个网络下
    
    

    istioctl install --context=cluster2 -f cluster2.yaml
    image.png


3.3 istio控制面访问remote kubernetes集群配置

istiod 需要负责连接所有集群的kube-apiserver,并且List-Watch 获取每个集群的Service、Endpoint、Pod等。

  • istiod 以RBAC的方式通过serviceaccount 绑定clusterrole 获取本集群的各种k8s资源信息,即通过Pod内置的token连接所在集群的Kube-apiserver。
  • 至于如何获取remote集群中的k8s资源,则需要通过Secret为istiod提供访问凭据,这种特殊的Secret,其标签为istio/multiCluster: true,并包含集群的ID 及remote集群访问的凭据 KubeConfig,istiod可以通过该secret提供的访问凭据与remote集群建立连接,监听remote集群的所有服务和相关资源的变化。

  1. 在 cluster1 中安装remote集群的 secret,该 secret 提供 cluster2 的 kube-apiserver的访问权限。

    istioctl create-remote-secret \
      --context=cluster2 \
      --name=cluster2 | \
    kubectl apply -f - --context=cluster1
    
    

    image.png
    secret 大致内容如下
    image.png
    secret中的cluster2对应value值为:
    image.png

  2. 在 cluster2 中安装remote集群的 secret,该 secret 提供 cluster1 的 kube-apiserver的访问权限。

    istioctl create-remote-secret \
        --context=cluster1 \
        --name=cluster1 | \
        kubectl apply -f - --context=cluster2
    

    image.png

  3. 查看istiod 日志 。确认istio是否与remote集群建立连接
    image.png

    image.png

  4. 注意: istioctl create-remote-secret --context=xxx,采用对应的kubeconfig配置文件,需要kubeconfig能保证访问集群各项资源权限 同时还需要保证证书时间在网格使用期间不过期。
    可参考istio源码:https://github.com/istio/istio/blob/master/istioctl/pkg/multicluster/remote_secret.go


四 验证多集群流量治理

4.1 验证istio跨集群流量

在两个集群中分别部署不同版本的服务

kubectl apply --context=cluster1     -f samples/helloworld/helloworld.yaml     -l version=v1 -n sample
kubectl apply --context=cluster1     -f samples/helloworld/helloworld.yaml     -l service=helloworld -n sample

kubectl apply --context=cluster2     -f samples/helloworld/helloworld.yaml     -l version=v2 -n sample
kubectl apply --context=cluster2     -f samples/helloworld/helloworld.yaml     -l service=helloworld -n sample

  1. 进行访问测试
    image.png

  2. 查看 客户端的istio-proxy访问日志
    image.png
    访问日志记录了outbound流量相关信息。


4.2 验证多集群流量灰度发布

在istio多控制面模型中,Istio控制面目前只监听主集群(也就是istio所在集群)的 VirtualService、DestinationRule、Gateway等Istio API对象,因此 对于多控制面模型来说,相同的Istio配置需要被复制下发到多个集群中,否则不同集群的Sidecar订阅到的xDS配置可能会存在严重的不一致,导致不同集群的服务访问行为不一致。

  1. 针对需要灰度的服务配置VirtualService路由规则

    apiVersion: networking.istio.io/v1beta1
    kind: VirtualService
    metadata:
      name: helloworld
      namespace: sample
    spec:
      hosts:
        - helloworld
      http:
        - route:
          - destination:
              host: helloworld
              subset: v2
            weight: 30
          - destination:
              host: helloworld
              subset: v1
            weight: 70
    
    

    以上规则表示,当有流量访问域名为helloworld的服务时,客户端服务的sidecar容器istio-proxy会将30%的流量路由到v2版本的helloworld负载上,将70%的流量路由到v1版本的helloworld负载上。

  2. 针对需要灰度的服务配置DestinationRule目标规则

    apiVersion: networking.istio.io/v1beta1
    kind: DestinationRule
    metadata:
      name: helloworld
      namespace: sample
    spec:
      host: helloworld
      subsets:
        - name: v2
          labels:
            version: v2
        - name: v1
          labels:
            version: v1
    
    

    以上规则表示,将域名为helloworld的服务创建两个subset子集。负载实例满足标签为version: v2 将被定义到subset v2中,负载实例满足标签为version: v1将被定义到subset v1中,一般和virtualservice结合使用。

  3. 于cluster1中创建上述两条istio crd资源
    image.png

  4. 访问测试,以cluster1集群中的sleep服务作为客户端访问helloworld服务端
    image.png

  5. 如果以cluster2集群中的客户端sleep服务进行访问,将会出现什么情况呢?还是否能够进行跨集群流量灰度发布
    image.png
    可以发现之前在cluster1中创建的流量治理规则,不会在cluster2中的数据面istio-proxy生效。

  6. 此时在cluster2中创建上述virtualservice、destinationrule资源,然后再进行访问测试。
    image.png
    可以发现流量比例不再是1:1,而是以设定的7:3的路由规则进行流量分发。
    image.png


4.3 验证istio 智能DNS代理

我们可能会有疑问,在kubernetes集群中,coreDNS只负责集群内的服务域名解析,对其他集群的域名解析束手无策。

  • 关于istio如何解析remote集群的service 域名,通常的做法是在每个集群中都创建相同的Service对象,可以没有pod实例 ,这种影子service作为占位符,仅供每个Kubernetes集群的coredns服务提供对服务网格的域名解析。
  • 在 istio 1.8以后,istio 提供了智能的DNS代理,原生支持对Remote集群的service域名解析,不过该配置默认是关闭的,需要手动开启,开启方式分为全局开启和局部开启。详情可参考:https://istio.io/latest/zh/docs/ops/configuration/traffic-management/dns-proxy/

image.png

proxy.istio.io/config: |
          proxyMetadata:
            ISTIO_META_DNS_CAPTURE: "true"
            ISTIO_META_DNS_AUTO_ALLOCATE: "true"

  1. 将cluster1 中helloword服务的实例缩容到0,然后发起访问
    image.png
    流量直接路由到cluster2中的helloworld实例上,访问还是成功的
    image.png

  2. 如果将cluster1集群中helloworld service去除,将导致访问失败,即使cluster2中存在helloworld服务
    image.png

  3. 于cluster1中发起对helloworld的访问
    因为缺少影子service导致访问失败
    image.png

  4. 此时给客户端添加配置

    proxy.istio.io/config: |
              proxyMetadata:
                ISTIO_META_DNS_CAPTURE: "true"
                ISTIO_META_DNS_AUTO_ALLOCATE: "true"
    
    

    image.png

  5. 再次进行访问测试
    image.png

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。