zoukankan      html  css  js  c++  java
  • 如何使用 Istio 进行多集群部署管理:单控制平面 Gateway 连接拓扑

    头图.png

    作者 | 王夕宁  阿里巴巴高级技术专家

    导读:本文摘自于由阿里云高级技术专家王夕宁撰写的《Istio 服务网格技术解析与实践》一书,讲述了如何使用 Istio 进行多集群部署管理来阐述服务网格对多云环境、多集群即混合部署的支持能力。

    前文详情:
    如何使用 Istio 进行多集群部署管理:单控制平面 VPN 连接拓扑

    单控制平面拓扑下,多个 Kubernetes 集群共同使用在其中一个集群上运行的单个 Istio 控制平面。控制平面的 Pilot 管理本地和远程集群上的服务,并为所有集群配置 Envoy Sidecar 代理。

    集群感知的服务路由

    Istio 1.1 中引入了集群感知的服务路由能力,在单一控制平面拓扑配置下,使用 Istio 的 Split-horizon EDS(水平分割端点发现服务)功能可以通过其入口网关将服务请求路由到其他集群。基于请求源的位置,Istio 能够将请求路由到不同的端点。

    在该配置中,从一个集群中的 Sidecar 代理到同一集群中的服务的请求仍然被转发到本地服务 IP。如果目标工作负载在其他集群中运行,则使用远程集群的网关 IP 来连接到该服务。

    1.png
    (集群感知的服务路由)

    如图所示,主集群 cluster1 运行全套的 Istio 控制平面组件,同时集群 cluster2 仅运行 Istio Citadel、Sidecar Injector 和 Ingress 网关。不需要 VPN 连接,不同集群中的工作负载之间也不需要直接网络访问。

    从共享的根 CA 为每个集群的 Citadel 生成中间 CA 证书,共享的根 CA 启用跨不同集群的双向 TLS 通信。为了便于说明,我们将 samples/certs 目录下 Istio 安装中提供的示例根 CA 证书用于两个集群。在实际部署中,你可能会为每个集群使用不同的 CA 证书,所有 CA 证书都由公共根 CA 签名。

    在每个 Kubernetes 集群中(包括示例中的集群 cluster1 与 cluster2)使用以下命令为生成的 CA 证书创建 Kubernetes 密钥:

    kubectl
    create namespace istio-system
    kubectl
    create secret generic cacerts -n istio-system 
      --from-file=samples/certs/ca-cert.pem 
      --from-file=samples/certs/ca-key.pem 
      --from-file=samples/certs/root-cert.pem 
      --from-file=samples/certs/cert-chain.pem
    

    Istio 控制平面组件

    在部署全套 Istio 控制平面组件的集群 cluster1 中,按照以下步骤执行:

    1.安装 Istio 的 CRD 并等待几秒钟,以便将它们提交给 Kubernetes API 服务器,如下所示:

    for
    i in install/kubernetes/helm/istio-init/files/crd*yaml; do kubectl apply -f $i;
    done
    

    2.然后开始在集群 cluster1 中部署 Istio 控制平面。

    如果 helm 依赖项缺失或者不是最新的,可以通过 helm dep update 来更新这些依赖项。需要注意的是,因为没有使用 istio-cni,可以暂时将其从依赖项 requirements.yaml 中去掉再执行更新操作。具体命令如下所示:

    helm
    template --name=istio --namespace=istio-system 
    --set
    global.mtls.enabled=true 
    --set
    security.selfSigned=false 
    --set
    global.controlPlaneSecurityEnabled=true 
    --set
    global.meshExpansion.enabled=true 
    --set
    global.meshNetworks.network2.endpoints[0].fromRegistry=n2-k8s-config 
    --set
    global.meshNetworks.network2.gateways[0].address=0.0.0.0 
    --set
    global.meshNetworks.network2.gateways[0].port=15443 
    install/kubernetes/helm/istio
    > ./istio-auth.yaml
    

    请注意,网关地址设置为 0.0.0.0。这是一个临时占位符值,在集群 cluster2 部署之后将更新为其网关的公共 IP 值。

    将 Istio 部署到 cluster1,如下所示:

    kubectl
    apply -f ./istio-auth.yaml
    

    确保上述步骤在 Kubernetes 集群中执行成功。

    3. 创建网关以访问远程服务,如下所示:

    kubectl
    create -f - <<EOF
    apiVersion:
    networking.istio.io/v1alpha3
    kind:
    Gateway
    metadata:
      name: cluster-aware-gateway
      namespace: istio-system
    spec:
      selector:
        istio: ingressgateway
      servers:
      - port:
          number: 15443
          name: tls
          protocol: TLS
        tls:
          mode: AUTO_PASSTHROUGH
        hosts:
        - "*"
    EOF
    

    上述网关配置了一个专用端口 15443 用来将传入流量传递到请求的 SNI 标头中指定的目标服务,从源服务到目标服务一直使用双向 TLS 连接。

    请注意虽然该网关定义应用于集群 cluster1,但因为两个集群都与同一个 Pilot 进行通信,此网关实例同样也适用于集群 cluster2。

    istio-remote 组件

    在另一集群 cluster2 中部署 istio-remote 组件,按照以下步骤执行:

    1.首先获取集群 cluster1 的入口网关地址,如下所示:

    export
    LOCAL_GW_ADDR=$(kubectl get svc --selector=app=istio-ingressgateway 
      -n istio-system -o
    jsonpath="{.items[0].status.loadBalancer.ingress[0].ip}")
    

    通过执行以下命令,使用 Helm 创建 Istio remote 部署 YAML 文件:

    helm
    template --name istio-remote --namespace=istio-system 
    --values
    install/kubernetes/helm/istio/values-istio-remote.yaml 
    --set
    global.mtls.enabled=true 
    --set
    gateways.enabled=true 
    --set
    security.selfSigned=false 
    --set
    global.controlPlaneSecurityEnabled=true 
    --set
    global.createRemoteSvcEndpoints=true 
    --set
    global.remotePilotCreateSvcEndpoint=true 
    --set
    global.remotePilotAddress=${LOCAL_GW_ADDR} 
    --set
    global.remotePolicyAddress=${LOCAL_GW_ADDR} 
    --set
    global.remoteTelemetryAddress=${LOCAL_GW_ADDR} 
    --set
    gateways.istio-ingressgateway.env.ISTIO_META_NETWORK="network2" 
    --set
    global.network="network2" 
    install/kubernetes/helm/istio
    > istio-remote-auth.yaml
    

    2. 将 Istio remote 组件部署到 cluster2,如下所示:

    kubectl
    apply -f ./istio-remote-auth.yaml
    

    确保上述步骤在 Kubernetes 集群中执行成功。

    3.更新集群 cluster1 的配置项 istio,获取集群 cluster2 的入口网关地址,如下所示:

    export
    REMOTE_GW_ADDR=$(kubectl get --context=$CTX_REMOTE svc --selector=app=
    istio-ingressgateway
    -n istio-system -o jsonpath="{.items[0].status.loadBalancer.ingress
    [0].ip}")
    

    在集群 cluster1 中编辑命名空间 istio-system 下的配置项 istio,替换 network2 的网关地址,从 0.0.0.0 变成集群 cluster2 的入口网关地址 ${REMOTE_GW_ADDR}。保存后,Pilot 将自动读取更新的网络配置。

    4.创建集群 cluster2 的 Kubeconfig。通过以下命令,在集群 cluster2 上创建服务账号 istio-multi 的 Kubeconfig,并保存为文件 n2-k8s-config:

    CLUSTER_NAME="cluster2"
    SERVER=$(kubectl
    config view --minify=true -o "jsonpath={.clusters[].cluster.server}")
    SECRET_NAME=$(kubectl
    get sa istio-multi -n istio-system -o jsonpath='{.secrets[].name}')
    CA_DATA=$(kubectl
    get secret ${SECRET_NAME} -n istio-system -o
    "jsonpath={.data['ca.crt']}")
    TOKEN=$(kubectl
    get secret ${SECRET_NAME} -n istio-system -o
    "jsonpath={.data['token']}" | base64 --decode)
    cat
    <<EOF > n2-k8s-config
    apiVersion:
    v1
    kind:
    Config
    clusters:
      - cluster:
          certificate-authority-data: ${CA_DATA}
          server: ${SERVER}
        name: ${CLUSTER_NAME}
    contexts:
      - context:
          cluster: ${CLUSTER_NAME}
          user: ${CLUSTER_NAME}
        name: ${CLUSTER_NAME}
    current-context:
    ${CLUSTER_NAME}
    users:
      - name: ${CLUSTER_NAME}
        user:
          token: ${TOKEN}
    EOF
    

    5.将集群 cluster2 加入到 Istio 控制平面。

    在集群 clusterl 执行以下命令,将上述生成的集群 cluster2 的 kubeconfig 添加到集群 cluster1 的 secret 中,执行这些命令后,集群 cluster1 中的 Istio Pilot 将开始监听集群 cluster2 的服务和实例,就像监听集群 cluster1 中的服务与实例一样:

    kubectl
    create secret generic n2-k8s-secret --from-file n2-k8s-config -n istio-system
    kubectl
    label secret n2-k8s-secret istio/multiCluster=true -n istio-system
    

    部署示例应用

    为了演示跨集群访问,在第一个 Kubernetes 集群 cluster1 中部署 sleep 应用服务和版本 v1 的 helloworld 服务,在第二个集群 cluster2 中部署版本 v2 的 helloworld 服务,然后验证 sleep 应用是否可以调用本地或者远程集群的 helloworld 服务。

    1.部署 sleep 和版本 v1 的 helloworld 服务到第一个集群 cluster1 中,执行如下命令:

    kubectl
    create namespace app1
    kubectl
    label namespace app1 istio-injection=enabled
    kubectl
    apply -n app1 -f samples/sleep/sleep.yaml
    kubectl
    apply -n app1 -f samples/helloworld/service.yaml
    kubectl
    apply -n app1 -f samples/helloworld/helloworld.yaml -l version=v1
    export
    SLEEP_POD=$(kubectl get -n app1 pod -l app=sleep -o
    jsonpath={.items..metadata.name})
    

    2.部署版本 v2 的 helloworld 服务到第二个集群 cluster2 中,执行如下命令:

    kubectl
    create namespace app1
    kubectl
    label namespace app1 istio-injection=enabled
    kubectl
    apply -n app1 -f samples/helloworld/service.yaml
    kubectl
    apply -n app1 -f samples/helloworld/helloworld.yaml -l version=v2
    

    3.登录到命名空间 istio-system 下的 istio-pilot 容器中,运行 curl localhost:8080/v1/registration | grep helloworld -A 11 -B 2 命令,如果得到如下类似的结果就说明版本 v1 与 v2 的 helloworld 服务都已经注册到 Istio 控制平面中了:

    微信图片_20200428144254.jpg

    4.验证在集群 cluster1 中的 sleep 服务是否可以正常调用本地或者远程集群的 helloworld 服务,在集群 cluster1 下执行如下命令:

    kubectl
    exec -it -n app1 $SLEEP_POD sh
    

    2.png

    登录到容器中,运行 curl helloworld.app1:5000/hello。

    如果设置正确,则在返回的调用结果中可以看到两个版本的 helloworld 服务,同时可以通过查看 sleep 容器组中的 istio-proxy 容器日志来验证访问的端点 IP 地址,返回结果如下所示:

    3.png

    《Istio服务网格技术解析与实战》读者可免费体验 ASM 产品进行学习!点击了解阿里云服务网格产品 ASM:www.aliyun.com/product/servicemesh

    作者简介

    王夕宁 阿里云高级技术专家,阿里云服务网格产品 ASM 及 Istio on Kubernetes 技术负责人,专注于 Kubernetes、云原生、服务网格等领域。曾在 IBM 中国开发中心工作,担任过专利技术评审委员会主席,拥有 40 多项相关领域的国际技术专利。《Istio 服务网格解析与实战》一书由其撰写,详细介绍了 Istio 的基本原理与开发实战,包含大量精选案例和参考代码可以下载,可快速入门 Istio 开发。Gartner 认为,2020 年服务网格将成为所有领先的容器管理系统的标配技术。本书适合所有对微服务和云原生感兴趣的读者,推荐大家对本书进行深入的阅读。

    课程推荐

    为了更多开发者能够享受到 Serverless 带来的红利,这一次,我们集结了 10+ 位阿里巴巴 Serverless 领域技术专家,打造出最适合开发者入门的 Serverless 公开课,让你即学即用,轻松拥抱云计算的新范式——Serverless。

    点击即可免费观看课程:https://developer.aliyun.com/learning/roadmap/serverless

    阿里巴巴云原生关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的公众号。”

  • 相关阅读:
    SpringMvc执行流程
    Lock wait timeout exceeded; try restarting transaction解决方法
    MySQL删除复杂的重复数据的解决方案(一条数据项中包含多个值的情况)
    数据移植时递归运算查询部门及其下级所有部门的问题
    IDEA常用插件
    mybatis和mybatisPlus中解决实体类字段与数据库关键字冲突问题
    时间日期操作
    spring项目中使用MD5加密方式
    idea如何调出仪表盘
    scanf使用过程中的技巧与坑位
  • 原文地址:https://www.cnblogs.com/alisystemsoftware/p/12836364.html
Copyright © 2011-2022 走看看