当前位置: 首页 > news >正文

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

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

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

前文详情:阿里云服务网格ASM架构技术解析

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


集群感知的服务路由


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

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

集群感知的服务路由

如图所示,主集群 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
  1. 然后开始在集群 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 集群中执行成功。

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

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
  1. 将 Istio remote 组件部署到 cluster2,如下所示:

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

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

 

  1. 更新集群 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 将自动读取更新的网络配置。

  1. 创建集群 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
  1. 将集群 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})
  1. 部署版本 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
  1. 登录到命名空间 istio-system 下的 istio-pilot 容器中,运行 curl localhost:8080/v1/registration | grep helloworld -A 11 -B 2 命令,如果得到如下类似的结果就说明版本 v1 与 v2 的 helloworld 服务都已经注册到 Istio 控制平面中了:

 

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

kubectl
exec -it -n app1 $SLEEP_POD sh

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

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

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

www.aliyun.com/product/servicemesh

作者简介

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

 

欢迎大家在留言中讨论交流对阿里云服务网格产品ASM的想法以及对服务网格技术Istio的疑惑,后续我们将邀请王夕宁老师亲自解答。

 

阿里云服务网格产品ASM网址:https://www.aliyun.com/product/servicemesh

《Istio服务网格技术解析与实践》读者可免费体验ASM产品进行学习!

 

后期续更:

如何使用Istio进行多集群部署管理:多控制平面

 

点击链接了解详情并购买

更多精彩回顾

 书单 | 5月书讯 | 华章IT图书上新啦!重磅新书在线投喂...

干货 | 73页PPT,教你从0到1构建用户画像系统(附下载)
榜单 | 423世界读书日 | 华章精品IT书单独家推荐

收藏 | 这10本书助你从容应对数字化转型中可能出现的各种挑战

相关文章:

  • AI直通车 | 阅读理解测试开始!竟然是你VS计算机?
  • #我与虚拟机的故事#连载20:周志明虚拟机第 3 版:到底值不值得买?
  • 大咖发声 | 亲谈Java程序员的职业方向与核心竞争力
  • 世界一流大学的计算机专业,在用哪些书当教材?
  • 用户画像有什么用?怎样用?6个场景案例给你详细解答
  • ​渐进式Web应用PWA的未来
  • G1垃圾回收算法概述
  • 【第7期】云计算监控——Prometheus监控系统
  • 一行简单的管道命令快速创建、原型化复杂的功能
  • 数据分析师的案头工具书都在这了
  • 薅当当羊毛的机会又!双!!叒!!!叕!!!来了
  • 520 情人节 :属于Python 程序员的脱单攻略大合集(视频版)
  • 高端科普系列——领略前沿科学的魅力
  • 周志明虚拟机最新版,大厂面试必备宝典
  • 对话阿里云 MVP:跨界半生,不改赤子之心
  • JavaScript 如何正确处理 Unicode 编码问题!
  • 自己简单写的 事件订阅机制
  • [译]如何构建服务器端web组件,为何要构建?
  • 【刷算法】求1+2+3+...+n
  • 【许晓笛】 EOS 智能合约案例解析(3)
  • 2019.2.20 c++ 知识梳理
  • download使用浅析
  • Java|序列化异常StreamCorruptedException的解决方法
  • js面向对象
  • MD5加密原理解析及OC版原理实现
  • nginx(二):进阶配置介绍--rewrite用法,压缩,https虚拟主机等
  • Phpstorm怎样批量删除空行?
  • Python_网络编程
  • 从零到一:用Phaser.js写意地开发小游戏(Chapter 3 - 加载游戏资源)
  • 飞驰在Mesos的涡轮引擎上
  • 聊聊sentinel的DegradeSlot
  • 码农张的Bug人生 - 初来乍到
  • 判断客户端类型,Android,iOS,PC
  • 嵌入式文件系统
  • 如何正确配置 Ubuntu 14.04 服务器?
  • 什么是Javascript函数节流?
  • 通过几道题目学习二叉搜索树
  • 怎样选择前端框架
  • Python 之网络式编程
  • ​Z时代时尚SUV新宠:起亚赛图斯值不值得年轻人买?
  • ​你们这样子,耽误我的工作进度怎么办?
  • # Maven错误Error executing Maven
  • #gStore-weekly | gStore最新版本1.0之三角形计数函数的使用
  • %@ page import=%的用法
  • (007)XHTML文档之标题——h1~h6
  • (ISPRS,2023)深度语义-视觉对齐用于zero-shot遥感图像场景分类
  • (Java)【深基9.例1】选举学生会
  • (pt可视化)利用torch的make_grid进行张量可视化
  • (附源码)ssm高校实验室 毕业设计 800008
  • (六) ES6 新特性 —— 迭代器(iterator)
  • (转)c++ std::pair 与 std::make
  • .Mobi域名介绍
  • .NET “底层”异步编程模式——异步编程模型(Asynchronous Programming Model,APM)...
  • .NET Core实战项目之CMS 第十二章 开发篇-Dapper封装CURD及仓储代码生成器实现
  • .NET Windows:删除文件夹后立即判断,有可能依然存在