istio服务网格
服务网格介绍
- 现代应用程序通常被设计成微服务的分布式集合,每个服务执行一些离散的业务功能。服务网格是专门的基础设施层,包含了组成这类体系结构的微服务网络。 服务网格不仅描述了这个网络,而且还描述了分布式应用程序组件之间的交互。所有在服务之间传递的数据都由服务网格控制和路由。
- 随着分布式服务的部署——比如基于 Kubernetes 的系统——规模和复杂性的增长,它可能会变得更加难以理解和管理。需求可以包括发现、负载平衡、故障恢复、度量和监视。微服务体系结构通常还有更复杂的操作需求,比如 A/B 测试、canary 部署、速率限制、访问控制、加密和端到端身份验证。
- 服务到服务的通信使分布式应用成为可能。在应用程序集群内部和跨应用程序集群路由这种通信变得越来越复杂。 Istio 有助于减少这种复杂性,同时减轻开发团队的压力。
什么是istio
- istio 提供一种简单的方式来为已部署的服务建立网络,该网络具有负载均衡、服务间认证、监控等功能,而不需要对服务的代码做任何改动。
- istio 适用于容器或虚拟机环境(特别是 k8s),兼容异构架构。
- istio 使用 sidecar(边车模式)代理服务的网络,不需要对业务代码本身做任何的改动。
- HTTP、gRPC、WebSocket 和 TCP 流量的自动负载均衡。
- istio 通过丰富的路由规则、重试、故障转移和故障注入,可以对流量行为进行细粒度控制;支持访问控制、速率限制和配额。
- istio 对出入集群入口和出口中所有流量的自动度量指标、日志记录和跟踪。
名词解析
- SERVICE MESH:服务网格 (简称 网格 )是一个可管理、可观测以及支持工作负载实例之间进行安全通信的基础设施层。在一个网格中,服务名称与命名空间组合具有唯一性。例如,在一个多集群的网格中,cluster-1 集群的 foo 命名空间中的 bar 服务和 cluster-2 集群的 foo 命名空间中的 bar 服务被认为是同一个服务。由于服务网格会共享这种标识,因此同一服务网格内的工作负载实例可以相互认证通信。
- ENVOY: 是在 Istio 里使用的高性能代理,用于为所有服务网格里的服务调度进出的流量
- MIXER:Mixer 是 Istio 里的一个组件,它负责增强服务网格里的访问控制和使用策略。它还负责收集来自 envoy 和其他服务的遥测数据。
- PILOT:Pilot 是 Istio 里的一个组件,它控制 Envoy 代理,负责服务发现、负载均衡和路由分发。
- POD:Pod 中包含了一个或多个共享存储和网络的容器 (例如 Docker 容器), 以及如何运行容器的规范。 Pod 是 Istio 的 Kubernetes 部署中的一个工作负载实例。
- SERVICE:使用服务名称标识一组具有关联行为的服务服务网格,并使用这些名称应用 Istio 策略(例如负载均衡和路由)。 服务通常由一个或多个服务 Endpoint 实现,并且或许包含多个服务版本。
Sidecar 是什么
- 将本将属于应用程序的功能拆分成单独的进程,这个进程可以被理解为Sidecar。在微服务体系内,将集成在应用内的微服务功能剥离到了sidecar内,sidecar提供了微服务发现、注册,服务调用,应用认证,限速等功能。
- 简单来说,Sidecar 注入会将额外容器的配置添加到 Pod 模板中。
- 特点: 1.sidecar为独立部署的进程。2.sidecar降低应用程序代码和底层代码的耦合度,帮助异构服务通过sidecar快速接入微服务体系。
Envoy 扮演的就是 Sidecar 的角色。
Sidecar 如何工作
- 下图为异构服务通过sidecar接入注册中心。异构服务本身可能为非Java或传统应用,接入困难。
- 异构服务本身不会和注册中心有请求调用,而是通过sidecar代理注册接入注册中心,获得服务注册、发现等功能。
- 从根本上讲,Istio的工作原理是以Sidcar的形式将Envoy的扩展版本作为代理布署到每个微服务中:
istio特点
- 使用 TLS 加密、强身份认证和授权的集群内服务到服务的安全通信
- 自动负载均衡的 HTTP, gRPC, WebSocket,和 TCP 流量
- 通过丰富的路由规则、重试、故障转移和故障注入对流量行为进行细粒度控制
- 一个可插入的策略层和配置 API,支持访问控制、速率限制和配额
- 对集群内的所有流量(包括集群入口和出口)进行自动度量、日志和跟踪
使用场景
Istio 是为可扩展性而设计的,可以处理不同范围的部署需求。Istio 的控制平面运行在 Kubernetes 上,您可以将部署在该集群中的应用程序添加到您的网格中,将网格扩展到其他集群,甚至连接 VM 或运行在 Kubernetes 之外的其他端点。
工作说明
Istio 由两个部分组成:控制平面和数据平面
为什么要使用istio
istio 使用教程
安装istio
- 下载 Istio
curl -L https://istio.io/downloadIstio | sh -
2. 转到 Istio 包目录
cd istio-1.12.1
3.将 istioctl 客户端加入搜索路径
4. 使用istioctl进行安装(采用 demo 配置组合)
$ istioctl install --set profile=demo –y
- 给命名空间添加标签
$ kubectl label namespace default istio-injection=enabled
部署示例应用
$ kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
https://raw.githubusercontent.com/istio/istio/release-1.12/samples/bookinfo/platform/kube/bookinfo.yaml
通过检查返回的页面标题
$ kubectl exec (执行容器)
"$(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}')"
-c ratings (容器名)
-- curl -s productpage:9080/productpage | grep -o “<title>.*</title>”(bash)
用于验证应用是否已在集群中运行,并已提供网页服务
对外开放应用程序
创建 Istio 入站网关(Ingress Gateway), 它会在网格边缘把一个路径映射到路由
- 把应用关联到 Istio 网关:
$ kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml
https://raw.githubusercontent.com/istio/istio/release-1.12/samples/bookinfo/networking/bookinfo-gateway.yaml
- 确保配置文件没有问题:
$ istioctl analyze
确定入站 IP 和端口
- 判断你的 Kubernetes 集群环境是否支持外部负载均衡:
$ kubectl get svc istio-ingressgateway -n istio-system
如果 EXTERNAL-IP 的值为 (或者一直是 状态), 则你的环境则没有提供可作为入站流量网关的外部负载均衡。 在这个情况下,你还可以用服务(Service)的 节点端口( NodePort) 访问网关。
设置入站 IP 地址和端口
$ export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
$ export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].port}')
$ export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].port}')
有些环境需要使用主机名访问
$ export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].hostname}')
其他平台的环境配置
验证外部访问
- 设置环境变量 GATEWAY_URL:
$ export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
- 确保 IP 地址和端口均成功的赋值给了环境变量:
$ echo "$GATEWAY_URL" 192.168.99.100:32194(例子返回的url,具体看本机)
- 获取该应用
$ echo "http://$GATEWAY_URL/productpage"
查看Kiali仪表板
Istio和几个遥测应用做了集成。 遥测能帮你了解服务网格的结构、展示网络的拓扑结构、分析网格的健康状态。
仪表板包括Kiali 、 Prometheus、 Grafana、 还有 Jaeger,例子里使用Kiali
- 安装 Kiali 和其他插件,等待部署完成。
$ kubectl apply -f samples/addons
$ kubectl rollout status deployment/kiali -n istio-system
- 访问 Kiali 仪表板。
$ istioctl dashboard kiali
在左侧的导航菜单,选择 Graph ,然后在 Namespace 下拉列表中,选择 default 。
Kiali 仪表板展示了网格的概览、以及 Bookinfo 示例应用的各个服务之间的关系。 它还提供过滤器来可视化流量的流动。
架构如图
服务构成
网站包括四个微服务:
- productpage :本服务会调用 details 和 reviews 两个微服务,用来生成页面。
- details :这个微服务包含了书籍的信息。
- reviews :这个微服务包含了书籍相关的评论。它还会调用 ratings 微服务。
- ratings :ratings 微服务中包含了由书籍评价组成的评级信息。
reviews 微服务有 3 个版本:
v1 版本不会调用 ratings 服务。
v2 版本会调用 ratings 服务,并使用 1 到 5 个黑色星形图标来显示评分信息。
v3 版本会调用 ratings 服务,并使用 1 到 5 个红色星形图标来显示评分信息。
实现效果
智能路由
- 自定义路由
首先将所有流量导入 v1 版本的 reviews
- 根据 header 内容分发流量
istio 可以基于内容分发流量,在这里我们让普通用户全部访问 v1 版,而特殊用户(jason)访问 v2 版。
监控
在 Istio 中,可以让 Mixer 自动为所有的网格内流量生成和报告新的指标以及新的日志流。
Prometheus(用作指标采集与查询)
分布式追踪
Istio 支持很多追踪系统,包括
Zipkin、Jaeger、LightStep、Datadog。运维人员控制生成追踪的采样率(每个请求生成跟踪数据的速率)。这允许运维人员控制网格生成追踪数据的数量和速率。
虽然 Istio 代理能够自动发送 Span 信息,但还是需要一些辅助手段来把整个跟踪过程统一起来。应用程序应该自行传播跟踪相关的 HTTP
Header,这样在代理发送 Span
信息的时候,才能正确的把同一个跟踪过程统一起来。
jaeger调用链追踪
zipkin
grafana
访问日志
- 访问日志提供了一种从单个工作负载实例的角度监控和理解行为的方法。
- Istio 可以以一组可配置的格式集生成服务流量的访问日志,为运维人员提供日志记录的方式、内容、时间和位置的完全控制。Istio 向访问日志机制暴露了完整的源和目标元数据,允许对网络通信进行详细的审查。
- 访问日志可以在本地生成,或者导出到自定义的后端基础设施,包括 Fluentd。
熔断
- 熔断器基本上是一种软件设计模式,用于检测故障并封装防止故障进一步级联的逻辑。这有助于创建有弹性的微服务应用程序,以限制故障和延迟尖峰的影响。
- 在Istio中,使用DestinationRule中的trafficPolicy配置在调用诸如清单服务之类的服务时应用熔断
- 将DestinationRule配置为maxConnections为1,httpMaxPendingRequests为1,maxRequestsPerConnection为1。这实际上意味着,如果我们将并发请求数超过1,熔断器将开始trap一些请求。
使用JWT进行访问控制
我们可以在Istio中启用授权策略,以允许访问基于JWT的预订服务之类的服务。
在这里,AuthorizationPolicy强制所有请求具有有效的JWT,并将requestPrincipal设置为特定值。 Istio通过组合声明JWT的iss和sub来创建requestPrincipal属性。
我们应该始终使用服务网格吗?
下面列举了一些可能促使我们不使用它的原因:
- 服务网格处理所有服务到服务的通信,而部署和操作服务网格则需要支付额外的费用。对于较简单的应用程序,这可能是不合理的
- 由于我们已经习惯于处理一些此类问题,例如应用程序代码中的熔断,因此可能导致服务网格中的重复处理
- 越来越依赖于诸如服务网格之类的外部系统可能会损害应用程序的可移植性,尤其是因为没有针对服务网格的行业标准
- 由于服务网格通常通过拦截通过代理的网格流量来工作,因此它可能会给请求增加不希望的延迟
服务网格增加了许多其他组件和配置,需要精确处理。这需要专业知识,并增加了学习曲线最后,我们可能最终将操作逻辑(应在服务网格中存在)与业务逻辑(不应在服务网格中)混合在一起