如何使用Istio 1.6管理多集群中的微服务?
假如你正在一家典型的企业里工作,需要与多个团队一起工作,并为客户提供一个独立的软件,组成一个应用程序。你的团队遵循微服务架构,并拥有由多个Kubernetes集群组成的广泛基础设施。
由于微服务分布在多个集群中,你需要设计一个解决方案来集中管理所有微服务。幸运的是,你正在使用Istio,提供这个解决方案只不过是另一个配置的变化。
像Istio这样的服务网格技术可以帮助你安全地发现和连接分布在多个集群和环境中的微服务。今天我们来讨论一下使用Istio管理托管在多个Kubernetes集群中的微服务。
架构说明
Istio使用以下组件提供跨集群服务发现:
Istio CoreDNS:每个Istio控制平面都有一个CoreDNS。Istio使用它来发现全局范围上定义的服务。例如,如果一个托管在集群1上的微服务需要连接到另一个托管在集群2上的微服务,你需要为运行在集群2上的微服务在Istio CoreDNS上做一个全局条目。
Root CA:由于Istio需要在不同集群上运行的服务之间建立mTLS连接,因此需要使用共享的Root CA为两个集群生成中间CA证书。这就在不同集群上运行的微服务之间建立了信任,因为中间CA共享同一个Root CA。
Istio Ingress网关:集群间的通信通过Ingress网关进行,服务之间没有直接连接。因此,你要确保Ingress网关是可发现的,并且所有集群都可以连接到它。

服务发现
Istio使用以下步骤来促进服务发现:
集群上都有相同的控制平面,以促进高可用性。
Kube DNS与Istio CoreDNS为支点,以提供全局服务发现。
用户通过Istio CoreDNS中的ServiceEntries定义远程服务的路由,格式为name.namespace.global。
源sidecar使用全局CoreDNS条目将流量路由到目标Istio Ingress网关。
目标 Istio Ingress 网关将流量路由到正确的微服务 pod。
前期准备
本文假设你已经对Kubernetes以及Istio的工作原理有一个基本的了解。如果你想了解Istio 1.5和1.6的详细内容,点击此处即可查看相关视频。为了能够跟上我们接下来的演示,请确保:
你有至少两个Kubernetes集群,Kubernetes的版本为1.14、1.15或1.16
你拥有在集群内安装和配置Istio的权限
你在两个Kubernetes集群上都有集群管理权限。
Ingress网关可通过网络负载均衡器或类似配置连接到其他集群。扁平网络是不必要的。
安装Istio
在两个集群上,使用以下命令安装Istio 1.6.1:
curl -L https://istio.io/downloadIstio | ISTIO_VERSION=1.6.1 sh -
cd istio-1.6.1
export PATH=$PWD/bin:$PATH
由于我们需要用共享的根证书生成的中间证书来启动我们的Istio服务网格,所以使用中间证书创建一个secret。
在这个例子中,我们使用提供的样本证书。但是,我不建议你在生产中使用这些证书,因为它们一般都是可轻松获取的,而且是众所周知的。最好是使用你的组织的Root CA来生成中间CA证书。
在两个集群上运行以下命令来使用样本证书。如果你使用的是你的证书,请替换适用的文件路径。
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
secret/cacerts created
由于我们需要安装Istio进行多集群设置,所以在两个集群上使用提供的Istio多集群网关manifest文件。
$ istioctl manifest apply -f install/kubernetes/operator/examples/multicluster/values-istio-multicluster-gateways.yaml
- Applying manifest for component Base...
 Finished applying manifest for component Base.
- Applying manifest for component Pilot...
 Finished applying manifest for component Pilot.
  Waiting for resources to become ready...
- Applying manifest for component AddonComponents...
- Applying manifest for component IngressGateways...
- Applying manifest for component EgressGateways...
 Finished applying manifest for component EgressGateways.
 Finished applying manifest for component IngressGateways.
 Finished applying manifest for component AddonComponents.
 Installation complete
配置KubeDNS
下一步是将DNS解析从Kube DNS联邦到Istio CoreDNS。让我们通过为kube-dns定义一个ConfigMap来配置一个存根域。在两个集群上应用以下manifest:
$ kubectl apply -f - <<EOF
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})"]}
EOF
configmap/kube-dns configured
设置上下文(context)
由于我们需要为不同得活动连接两个集群,因此获取上下文并将其存储在环境变量中会很有意义。有了这些,我们只要在kubectl命令中加入上下文,就可以在我们选择得集群中运行kubectl命令。
获取上下文:
$ kubectl config get-contexts
CURRENT   NAME        CLUSTER     AUTHINFO      NAMESPACE
          cluster-1   cluster-1   cluster-1
*         cluster-2   cluster-2   cluster-2
设置环境变量以使用上下文:
$ export CTX_CLUSTER1=$(kubectl config view -o jsonpath='{.contexts[0].name}')
$ export CTX_CLUSTER2=$(kubectl config view -o jsonpath='{.contexts[1].name}')
$ echo CTX_CLUSTER1 = ${CTX_CLUSTER1}, CTX_CLUSTER2 = ${CTX_CLUSTER2}
CTX_CLUSTER1 = cluster-1, CTX_CLUSTER2 = cluster-2
部署示例微服务
我们先在集群1的foo命名空间上部署sleep微服务。
$ kubectl create --context=$CTX_CLUSTER1 namespace foo
namespace/foo created
$ kubectl label --context=$CTX_CLUSTER1 namespace foo istio-injection=enabled
namespace/foo labeled
$ kubectl apply --context=$CTX_CLUSTER1 -n foo -f samples/sleep/sleep.yaml
serviceaccount/sleep created
service/sleep created
deployment.apps/sleep created
$ export SLEEP_POD=$(kubectl get --context=$CTX_CLUSTER1 -n foo pod -l app=sleep -o jsonpath={.items..metadata.name})
现在我们在集群2的bar命名空间上部署httpbin微服务:
$ kubectl create --context=$CTX_CLUSTER2 namespace bar
namespace/bar created
$ kubectl label --context=$CTX_CLUSTER2 namespace bar istio-injection=enabled
namespace/bar labeled
$ kubectl apply --context=$CTX_CLUSTER2 -n bar -f samples/httpbin/httpbin.yaml
serviceaccount/httpbin created
service/httpbin created
deployment.apps/httpbin created
创建服务条目
现在我们需要在Istio CoreDNS上创建一个服务条目以便于我们可以从集群1中发现集群2上的服务。由于所有的通信都会通过Ingress 网关,导出集群2 Ingress网关地址。
export CLUSTER2_GW_ADDR=$(kubectl get --context=$CTX_CLUSTER2 svc --selector=app=istio-ingressgateway \
    -n istio-system -o jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}')
为了让集群1上的服务能够发现集群2上的httpbin,我们需要在集群1上为httpbin.bar.global创建一个ServiceEntry。这样可以保证集群1上的Istio Core DNS在集群1上的服务到达httpbin.bar.global这个端点时,可以到达集群2的Ingress网关。下面的yaml:
在hosts部分定义服务域名
位置是
mesh_INTERNAL,因为我们需要把其他服务当作同一个服务网格的一部分将服务暴露在8000端口上
我们需要给该服务提供一个独特的IP地址。该IP地址不需要可路由,并且你可以使用240.0.0.0/16范围内的任意地址
我们在端点地址部分上定义集群2 ingress网关地址,以便于请求可以路由给它。端口15443是Ingress网关的SNI识别的Envoy代理端口,用于在目标群集服务的Pod之间路由流量。
应用yaml文件:
$ kubectl apply --context=$CTX_CLUSTER1 -n foo -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: httpbin-bar
spec:
  hosts:
  - httpbin.bar.global
  location: MESH_INTERNAL
  ports:
  - name: http1
    number: 8000
    protocol: http
  resolution: DNS
  addresses:
  - 240.0.0.2
  endpoints:
  - address: ${CLUSTER2_GW_ADDR}
    ports:
      http1: 15443 # Do not change this port value
EOF
serviceentry.networking.istio.io/httpbin-bar created
测试服务
现在让我们从sleep微服务中产生一些流量,看看它是否能到达集群2上运行的httpbin微服务。
$ kubectl exec --context=$CTX_CLUSTER1 $SLEEP_POD -n foo -c sleep -- curl -I httpbin.bar.global:8000/headers
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0HTTP/1.1 200 OK
  0   519    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
server: envoy
date: Sat, 16 May 2020 23:03:22 GMT
content-type: application/json
content-length: 519
access-control-allow-origin: *
access-control-allow-credentials: true
x-envoy-upstream-service-time: 37
我们得到一个成功的响应!恭喜你,我们已经成功地使用Istio在多个Kubernetes集群之间配置了服务发现。
结 论
感谢你的阅读,希望你能喜欢这篇文章。
这是一个在多个集群上运行的高可用Istio服务网格配置的演示。你也可以有一个共享的控制平面配置,但这并不推荐用于生产——如果你因为中断而失去一个集群,你也会失去对正在运行的集群的控制。
如何使用Istio 1.6管理多集群中的微服务?的更多相关文章
- Blazor+Dapr+K8s微服务之基于WSL安装K8s集群并部署微服务
		
前面文章已经演示过,将我们的示例微服务程序DaprTest1部署到k8s上并运行.当时用的k8s是Docker for desktop 自带的k8s,只要在Docker for deskto ...
 - Java高可用集群架构与微服务架构简单分析
		
序 可能大部分读者都在想,为什么在这以 dubbo.spring cloud 为代表的微服务时代,我要还要整理这种已经"过时"高可用集群架构? 本人工作上大部分团队都是7-15人编 ...
 - CentOS7 使用chrony搭建集群中的时间同步服务
		
一.集群环境: 系统:CentOS7-minimal 集群中的两台主机ip:10.132.226.103/24 10.132.226.104/24 二.CentOS7中时间相关命令timedatec ...
 - shipyard 管理swarm集群(附etcd发现服务方法)
		
docker swarm集群 第一步:安装swarm集群 192.168.132.131----->(manger1,node) 192.168.132.132----->(manger2 ...
 - 8分钟学会Consul集群搭建及微服务概念
		
Consul介绍: Consul 是由 HashiCorp 公司推出的开源软件,用于实现分布式系统的服务发现与配置.与其他分布式服务注册与发现的方案,Consul 的方案更“一站式”,内置了服务注册与 ...
 - 在Kubernetes集群里安装微服务DevOps平台fabric8
		
转载于https://blog.csdn.net/wzp1986/article/details/72128063?utm_source=itdadao&utm_medium=referral ...
 - 使用Cloudrea Manager在CDH集群中添加kafka服务节点,更改borker.id配置后无法启动
		
需要保证meta.properties文件中的broker.id和cloudrea manager的web页面上kafka配置的broker.id一致,最好让server.properties中的br ...
 - 在 Minecraft 中管理 Kubernetes 集群
		
原文链接:在 Minecraft 中管理 Kubernetes 集群 微软 2015 年收购 Minecraft 之后不久开源了一个项目叫 Dockercraft,这个项目当时看起来非常有趣,通过 D ...
 - 实操教程丨如何在K8S集群中部署Traefik Ingress Controller
		
注:本文使用的Traefik为1.x的版本 在生产环境中,我们常常需要控制来自互联网的外部进入集群中,而这恰巧是Ingress的职责. Ingress的主要目的是将HTTP和HTTPS从集群外部暴露给 ...
 
随机推荐
- offer到手!美团Java岗四面(多线程+redis+JVM+数据库)
			
美团Java岗四面,已拿offer,前三面都是技术面,第四面是HR面,下面是面试题! 美团Java岗一面(技术,电话面,约40分钟) 自我介绍. 项目介绍. 了解过redis源码及redis集群么? ...
 - 图解resilience4j容错机制
			
Resilience4j是一个轻量级.易于使用的容错库,其灵感来自Netflix Hystrix,但专为Java 8和函数式编程设计.轻量级,因为库只使用Vavr,它没有任何其他外部库依赖项.相比之下 ...
 - 4 个好用的 Linux 监控工具
			
下面是 Linux 下 4 个日常使用率非常高的监控工具,可以帮助我们准确快速的诊断系统问题. 1. iotop 如果你想知道某些进程使用了多少你宝贵的 I/O 资源,那么就使用 iotop 吧. i ...
 - pycharm中连接MySql出现  Exception in thread "main" java.lang.ClassNotFoundException: com.mysql.jdbc.的错误解决
			
具体异常如下: 这个异常特别烦人,是mysql连接驱动的问题,可以用二步解决: 第一步 从网上下载驱动,从mysql-connector-java_8.0.16-1ubuntu16.04_all.de ...
 - 机器学习入门:极度舒适的GBDT原理拆解
			
机器学习入门:极度舒适的GBDT拆解 本文旨用小例子+可视化的方式拆解GBDT原理中的每个步骤,使大家可以彻底理解GBDT Boosting→Gradient Boosting Boosting是集成 ...
 - 用Python语言绘制股市OBV指标效果
			
我的新书<基于股票大数据分析的Python入门实战>于近日上架,在这篇博文向大家介绍我的新书:<基于股票大数据分析的Python入门实战>里,介绍了这本书的内容.这里将摘录出部 ...
 - [SpringBoot]SpringBoot中使用redis事务
			
本文基于SpringBoot 2.X 事务在关系型数据库的开发中经常用到,其实非关系型数据库,比如redis也有对事务的支持,本文主要探讨在SpringBoot中如何使用redis事务. 事务的相关介 ...
 - uniapp,微信小程序中使用 MQTT
			
最近在uniapp打包成微信小程序的项目中第一次用到了MQTT.使用比较简单,但是还是遇到了一些问题.在此记录一下. 官方文档:MQTT Github 官方MQTT测试工具:MQTTX.测试工具使用说 ...
 - java 面向对象(十二):面向对象的特征二:继承性 (一) 前言
			
1.为什么要有类的继承性?(继承性的好处) * ① 减少了代码的冗余,提高了代码的复用性 * ② 便于功能的扩展 * ③ 为之后多态性的使用,提供了前提图示: 2.继承性的格式:class A ext ...
 - 数据可视化之PowerQuery篇(四)二维表转一维表,看这篇文章就够了
			
https://zhuanlan.zhihu.com/p/69187094 数据分析的源数据应该是规范的,而规范的其中一个标准就是数据源应该是一维表,它会让之后的数据分析工作变得简单高效. 在之前的文 ...