Istio微服务入门---通过istio部署微服务实现灰度发布(15)

目录

一、Istio简介

1.1 Istio介绍

1.1.1 服务注册和发现

1.1.2 负载均衡

1.1.3 故障恢复

1.1.5 灰度发布

1.2 Istio核心特性

1.2.1 断路器

1.2.2 超时

 1.2.3 重试

 1.2.4 多路由规则

二、Istio架构

三、Istio组件详解

3.1 Pilot

3.2 Envoy

 3.3 Citadel组件

 3.4 Galley组件

3.5 Ingressgateway:入口网关

 3.6 Sidecar-injector

3.7 Istio其他组件

四、安装和配置Istio

4.1 准备安装Istio要的压缩包

4.2 安装istio

五、通过Istio部署在线书店bookinfo

5.1 在线书店功能介绍

 5.2 部署应用

5.3 启动应用服务

5.4 卸载bookinfo服务

六、通过Istio实现k8s线上业务灰度发布(金丝雀发布)

6.1 什么是灰度发布?

6.2 使用istio进行金丝雀发布

七、istio核心资源解读

7.1 Gateway资源清单详细解读

 7.2 VirtualService

7.2.1 路由规则优先级

7.2.2 多路由规则解读

7.3 Destination Rule 定义目标规则

八、Istio服务治理----熔断

8.1 断路器

8.2 超时

8.3 故障注入和重试

九、分布式追踪系统---jaeger(暂未部署)

9.1 分布式追踪简介

9.2 Jaeger组件介绍

9.3 使用Jaeger

十、分布式追踪系统-kiali

10.1 kiali简介

 9.2 kiali使用


一、Istio简介
1.1 Istio介绍

官方文档:https://istio.io/docs/concepts/what-is-istio/

中文官方文档:https://istio.io/zh/docs/concepts/what-is-istio/

Github 地址:https://github.com/istio/istio/releases

官当解释: An open platform to connect, secure, control and observe services.

翻译过来,就是”连接、安全加固、控制和观察服务的开放平台“。开放平台就是指它本身是开源 的,服务对应的是微服务,也可以粗略地理解为单个应用。

  1、连接(Connect):智能控制服务之间的调用流量,能够实现灰度升级、AB 测试和蓝绿部署等功能

  2、安全加固(Secure):自动为服务之间的调用提供认证、授权和加密。

  3、控制(Control):应用用户定义的 policy,保证资源在消费者中公平分配。

  4、观察(Observe):查看服务运行期间的各种数据,比如日志、监控和 tracing,了解服务的运行情况。

Istio 是 ServiceMesh 的产品化落地,可以通过在现有的服务器新增部署边车代理(sidecar proxy),应用程序不用改代码,或者只需要改很少的代码,就能实现如下基础功能:

  1、帮助微服务之间建立连接,帮助研发团队更好的管理与监控微服务,并使得系统架构更加安全;

  2、帮助微服务分层解耦,解耦后的 proxy 层能够更加专注于提供基础架构能力,例如:

    (1)服务发现(discovery);

    (2)负载均衡(load balancing);

    (3)故障恢复(failure recovery);

    (4)服务度量(metrics);

    (5)服务监控(monitoring);

    (6)A/B 测试(A/B testing);

    (7)灰度发布(canary rollouts);

    (8)限流限速(rate limiting);

    (9)访问控制(access control);

    (10)身份认证(end-to-end authentication)。

1.1.1 服务注册和发现

 RPC:RPC(Remote Procedure Call)远程过程调用,简单的理解是一个节点请求另一个节点提供的 服务

1.1.2 负载均衡

  把前端的请求分发到后台多个服务器,常见的负载均衡:nginx、haproxy,lvs;F5;Ribbon

1.1.3 故障恢复

  出现故障具备自恢复的能力

1.1.5 灰度发布

  灰度发布也叫金丝雀发布,起源是,矿井工人发现,金丝雀对瓦斯气体很敏感,矿工会在下井之 前,先放一只金丝雀到井中,如果金丝雀不叫了,就代表瓦斯浓度高。

灰度发布步骤

  1.先启动一个新版本应用,但是并不直接将流量切过来,而是测试人员对新版本进行线上测试,这个新版本就是金丝雀

  2.如果测试没问题,将少量用户导入到新版本上,然后对新版本进行运行状态观察,收集各种运行时数据日志,如果此时对新旧版本做各种数据对比,就是所谓的 A/B 测试,

  3.当确认新版本运行没有问题后,在逐步将更多的流量用户导入到新版本上,在此期间,还可以不断地调整新旧两 个版本的运行的服务器副本数量,以使得新版本能够承受越来越大的流量压力

  4.直到将 100%的流量都切换到新版本上,最后关闭剩下的老版本服务,完成灰度发布

  5.如果在灰度发布过程中(灰度期)发现了新版本有问题,就应该立即将流量切回老版本上,这样,就会将负面影响控制在最小范围内。

1.2 Istio核心特性

  1、流控(traffic management):流量控制

    断路器(circuit breakers)、超时、重试、多路由规则、AB 测试、灰度发布、按照百分比分配流量 等。

  2、安全(security)

    加密、身份认证、服务到服务的权限控制、K8S 里容器到容器的权限控制等。

  3、可观察(observability):监控与日志

    追踪、监控、数据收集,通过控制后台全面了解上行下行流量,服务链路情况,服务运行情况,系统性能情况,国内微服务架构体系,这一块做得比较缺乏。

  4、平台无关系(platform support)

    K8s,物理机,自己的虚机都没问题。

  5、集成与定制(integration and customization)

    可定制化扩展功能。

1.2.1 断路器

例1:生活中家用电的保险丝之类跳闸

        断路器也称为服务熔断,在多个服务调用的时候,服务 A 依赖服务 B,服务 B 依赖服务 C,如果服务 C 响应时间过长或者不可用,则会让服务 B 占用太多系统资源,而服务 A 也依赖服 B,同时也在占用大量的系统资源,造成系统雪崩的情况出现。 Istio 断路器通过网格中的边车对流量进行拦截判断处理,避免了在代码中侵入控制逻辑,非常方便的就实服务熔断的能力。

        在微服务架构中,在高并发情况下,如果请求数量达到一定极限(可以自己设置阈值),超出了设置的阈值,断路器会自动开启服务保护功能,然后通过服务降级的方式返回一个友好的提示给客户端。 假设当 10 个请求中,有 10%失败时,熔断器就会打开,此时再调用此服务,将会直接返回失败,不再调远程服务。直到 10s 钟之后,重新检测该触发条件,判断是否把熔断器关闭,或者继续打开。

服务降级(提高用户体验效果)

        比如电商平台,在针对 618、双 11 的时候会有一些秒杀场景,秒杀的时候请求量大,可能会返回报 错标志“当前请求人数多,请稍后重试”等,如果使用服务降级,无法提供服务的时候,消费者会调用降级的操作,返回服务不可用等信息,或者返回提前准备好的静态页面写好的信息。

1.2.2 超时

什么时候需要用到超时:

  在生产环境中经常会碰到由于调用方等待下游的响应过长,堆积大量的请求阻塞了自身服务,造成 雪崩的情况,通过超时处理来避免由于无限期等待造成的故障,进而增强服务的可用性。

举例:nginx 服务设置了超时时间为 3 秒,如果超出这个时间就不在等待,返回超时错误,httpd 服务设置了响应时间延迟 5 秒,任何请求都需要等待 5 秒后才能返回;

  client 通过访问 nginx 服务去反向代理 httpd 服务,由于 httpd 服务需要 5 秒后才能返回,但 nginx 服务只等待 3 秒,所以客户端会提示超时错误。

 1.2.3 重试

  istio 重试机制就是如果调用服务失败,Envoy 代理尝试连接服务的最大次数。而默认情况下, Envoy 代理在失败后并不会尝试重新连接服务。

举例:客户端调用 nginx,nginx 将请求转发给 tomcat。tomcat 通过故障注入而中止对外服务,nginx 设置如果访问 tomcat 失败则会重试 3 次

 1.2.4 多路由规则

  1、HTTP 重定向(HTTPRedirect)

  2、HTTP 重写(HTTPRewrite)

  3、HTTP 重试(HTTPRetry)

  4、HTTP 故障注入(HTTPFaultInjection:

  5、HTTP 跨域资源共享(CorsPolicy)

二、Istio架构

istio 服务网格从逻辑上分为数据平面和控制平面。

 (1)数据平面由一组以 Sidecar 方式部署的智能代理(Envoy+Polit-agent)组成。这些代理承载并控制微服务之间的所有网络通信,管理入口和出口流量,类似于一线员工。 Sidecar 一般和业务容器绑定在一起(在 Kubernets 中以自动注入的方式注入到到业务 pod 中),来劫持业务应用容器的流 量,并接受控制面组件的控制,同时会向控制面输出日志、跟踪及监控数据。

  Envoy 和 pilot-agent 打在同一个镜像中,即 sidecar Proxy。

(2)控制平面负责管理和配置代理来路由流量。

istio1.5+中使用了一个全新的部署模式,重建了控制平面,将原有的多个组件整合为一个单体结构 istiod,这个组件是控制平面的核心,管理 Istio 的所有功能,主要包括 Pilot、Mixer、Citadel 等服务组件。

istiod 是新版本中最大的变化,以一个单体组件替代了原有的架构,降低了复杂度和维护难度,但 原有的多组件并不是被完全移除,而是在重构后以模块的形式整合在一起组成了 istiod。

结合下图我们来理解 Istio 的各组件的功能及相互之间的协作方式:

 (1)自动注入:在创建应用程序时自动注入 Sidecar 代理 Envoy 程序。在 Kubernetes 中创建 Pod 时, Kube-apiserver 调用控制面组件的 Sidecar-Injector 服务,自动修改应用程序的描述信息并注入 Sidecar。在真正创建 Pod 时,在创建业务容器的 Pod 中同时创建 Sidecar 容器。

(2)流量拦截:在 Pod 初始化时设置 iptables 规则,基于配置的 iptables 规则拦截业务容器的 Inbound 流量和 Outbound 流量到 Sidecar 上。而应用程序感知不到 Sidecar 的存在,还以原本的方式 进行互相访问。上图中,流出 frontend 服务的流量会被 frontend 服务侧的 Envoy 拦截,而当流量到达 forecast 容器时,Inbound 流量被 forecast 服务侧的 Envoy 拦截。

(3)服务发现:服务发起方的 Envoy 调用控制面组件 Pilot 的服务发现接口获取目标服务的实例列表。 上图中,frontend 服务侧的 Envoy 通过 Pilot 的服务发现接口得到 forecast 服务各个实例的地址。

(4)负载均衡:服务发起方的 Envoy 根据配置的负载均衡策略选择服务实例,并连接对应的实例地址。上图中,数据面的各个 Envoy 从 Pilot 中获取 forecast 服务的负载均衡配置,并执行负载均衡动作。

(5)流量治理:Envoy 从 Pilot 中获取配置的流量规则,在拦截到 Inbound 流量和 Outbound 流量时执行治理逻辑。上图中, frontend 服务侧的 Envoy 从 Pilot 中获取流量治理规则,并根据该流量治理 规则将不同特征的流量分发到 forecast 服务的 v1 或 v2 版本。

(6)访问安全:在服务间访问时通过双方的 Envoy 进行双向认证和通道加密,并基于服务的身份进行授权管理。上图中,Pilot 下发安全相关配置,在 frontend 服务和 forecast 服务的 Envoy 上自动加载证书和 密钥来实现双向认证,其中的证书和密钥由另一个管理面组件 Citadel 维护。

(7)服务监测:在服务间通信时,通信双方的 Envoy 都会连接管理面组件 Mixer 上报访问数据,并通过 Mixer 将数据转发给对应的监控后端。上图中,frontend 服务对 forecast 服务的访问监控指标、日志和调用链都可以通过这种方式收集到对应的监控后端。

(8)策略执行:在进行服务访问时,通过 Mixer 连接后端服务来控制服务间的访问,判断对访问是放行还是拒绝。上图中,Mixer 后端可以对接一个限流服务对从 frontend 服务到 forecast 服务的访问进行速 率控制等操作。

(9)外部访问:在网格的入口处有一个 Envoy 扮演入口网关的角 色。上图中,外部服务通过 Gateway 访 问入口服务 frontend,对 frontend 服务的负载均衡和一些流量治理策略都在这个 Gateway 上执行。

看了上图就容易懂了,sidecar 和 proxy 相生相伴,就像摩托车(motor)与旁边的车厢(sidecar)。

sidecar 和 proxy 就指微服务进程解耦成两个进程之后,提供基础能力的那个代理进程。

三、Istio组件详解

  Istio 服务组件有很多,从上面的流程中基本能看出每个组件如何协作的,下面具体讲解每个组件的具体用途和功能。

3.1 Pilot

Pilot 是 Istio 的主要控制组件,下发指令控制客户端。在整个系统中,Pilot 完成以下任务:

  1、从 Kubernetes 或者其他平台的注册中心获取服务信息,完成服务发现过程。

  2、读取 Istio 的各项控制配置,在进行转换之后,将其发给数据面进行实施。

 Pilot 将配置内容下发给数据面的 Envoy,Envoy 根据 Pilot 指令,将路由、服务、监听、集群等定义信息转换为本地配置,完成控制行为的落地。

  1)Pilot 为 Envoy 提供服务发现

  2)提供流量管理功能(例如,A/B 测试、金丝雀发布等)以及弹性功能(超时、重试、熔断器 等);

  3)生成 envoy 配置

  4)启动 envoy

  5)监控并管理 envoy 的运行状况,比如 envoy 出错时 pilot-agent 负责重启 envoy,或者 envoy 配 置变更后 reload envoy

3.2 Envoy

Envoy介绍:

  Envoy 是用 C++ 开发的高性能代理,用于协调服务网格中所有服务的入站和出站流量

Envoy 有许多强大的功能,例如: 动态服务发现、负载均衡、TLS 终端、HTTP/2 与 gRPC 代理 断路器、健康检查、流量拆分、灰度发布、故障注入

Istio中Envoy与服务的关系:

  Envoy 和 Service A 同属于一个 Pod,共享网络和命名空间,Envoy 代理进出 Pod A 的流量,并将流 量按照外部请求的规则作用于 Service A 中。

Pilot-agent 是什么?

Envoy 不直接跟 k8s 交互,通过 pilot-agent 管理的

Pilot-agent 进程根据 K8S APIserver 中的配置信息生成 Envoy 的配置文件,并负责启动 Envoy 进 程。

Envoy 由 Pilot-agent 进程启动,启动后,Envoy 读取 Pilot-agent 为它生成的配置文件,然后根据 该文件的配置获取到 Pilot 的地址,通过数据面从 pilot 拉取动态配置信息,包括路由(route), 监听器(listener),服务集群(cluster)和服务端点(endpoint)。

 3.3 Citadel组件

负责处理系统上不同服务之间的 TLS 通信。 Citadel 充当证书颁发机构(CA),并生成证书以允许在数据平面中进行安全的 mTLS 通信。

Citadel 是 Istio 的核心安全组件,提供了自动生成、分发、轮换与撤销密钥和证书功能。

Citadel 一直监听 Kube-apiserver,以 Secret 的形式为每个服务都生成证书密钥,并在 Pod 创建 时挂载到 Pod 上,代理容器使用这些文件来做服务身份认证,进而代理两端服务实现双向 TLS 认证、通道加密、访问授权等安全功能。如图所示,frontend 服务对 forecast 服务的访问用到了 HTTP 方式,通过配置即可对服务增加认证功能,双方的 Envoy 会建立双向认证的 TLS 通道,从而在服务间启用双向认证的 HTTPS。

 3.4 Galley组件

Galley 是 istio 的配置验证、提取、处理和分发的组件。Galley 是提供配置管理的服务。实现原理 是通过 k8s 提供的 ValidatingWebhook 对配置进行验证。

Galley 使 Istio 可以与 Kubernetes 之外的其他环境一起工作,因为它可以将不同的配置数据转换为 Istio 可以理解的通用格式。

3.5 Ingressgateway:入口网关

        Ingressgateway 就是入口处的 Gateway,从网格外访问网格内的服务就是通过这个 Gateway 进行 的。istio-ingressgateway 是一个 Loadbalancer 类型的 Service,不同于其他服务组件只有一两个 端 口,istio-ingressgateway 开放了一组端口,这些就是网格内服务的外部访问端口。如下图所 示,网格入口网关 istio-ingressgateway 的负载和网格内的 Sidecar 是同样的执行流程,也和网格 内的其他 Sidecar 一样从 Pilot 处接收流量规则并执行。

 3.6 Sidecar-injector

Sidecar-injector 是负责自动注入的组件,只要开启了自动注入,在 Pod 创建时就会自动调用 istio-sidecar-injector 向 Pod 中注入 Sidecar 容器。

在 Kubernetes 环境下,根据自动注入配置,Kube-apiserver 在拦截到 Pod 创建的请求时,会调用自动注入服务 istio-sidecar-injector 生成 Sidecar 容器的描述并将其插入原 Pod 的定义中,这样,在创建的 Pod 内除了包括业务容器,还包括 Sidecar 容器,这个注入过程对用户透明。

3.7 Istio其他组件

        除了以“istio”为前缀的 Istio 自有组件,在集群中一般还安装 Jaeger-agent、Jaeger-collector、Jaeger-query、Kiali、Prometheus、Grafana、 Tracing、Zipkin 等组件,这些组件提供了 Istio 的调用链、监控等功能,可以选择安装来完成完整的服务监控管理功能。

四、安装和配置Istio
4.1 准备安装Istio要的压缩包

# 注意不要选择太新的包,1.28.2做bookmark实验时出现问题:ipv6增加了一个地址,导致本机与node节点不通的情况

官网下载地址: https://github.com/istio/istio/

       https://github.com/istio/istio/releases/tag/1.10.3

复制代码

# 1.将压缩包上传到master上解压
tar -xzvf istio-1.10.1-linux-amd64.tar.gz
cd istio-1.10.1
export PATH=$PWD/bin:$PATH
cp -ar bin/istioctl /usr/bin/

# istio安装目录包含以下内容:
samples/目录下,有示例应用程序 
bin/目录下,包含 istioctl 的客户端文件。istioctl 工具用于手动注入 Envoy sidecar 代理。 

复制代码

4.2 安装istio

下载镜像:

安装 istio 需要的镜像默认从官网拉取,上传到自己 k8s 集群的各个节点,但是由于网络不好可以提前先下载准备好

bookinfo所需镜像:

复制代码

[root@node1 bookinfo]# docker load -i httpbin.tar.gz
Loaded image: kennethreitz/httpbin:latest
# 导入顺序
[root@node1 bookinfo]# docker load -i examples-bookinfo-details.tar.gz
Loaded image: istio/examples-bookinfo-details-v1:1.15.0
[root@node1 bookinfo]# docker load -i examples-bookinfo-productpage.tar.gz
Loaded image: istio/examples-bookinfo-productpage-v1:1.16.2
[root@node1 bookinfo]# docker load -i examples-bookinfo-ratings.tar.gz
Loaded image: istio/examples-bookinfo-ratings-v1:1.15.0

[root@node1 bookinfo]# docker load -i examples-bookinfo-reviews-v1.tar.gz
Loaded image: istio/examples-bookinfo-reviews-v1:1.15.0
[root@node1 bookinfo]# docker load -i examples-bookinfo-reviews-v2.tar.gz
Loaded image: istio/examples-bookinfo-reviews-v2:1.15.0
[root@node1 bookinfo]# docker load -i examples-bookinfo-reviews-v3.tar.gz
Loaded image: istio/examples-bookinfo-reviews-v3:1.15.0

复制代码

控制节点安装istio

复制代码

[root@master bookinfo]# istioctl install --set profile=demo -y
✔ Istio core installed
✔ Istiod installed
✔ Egress gateways installed
✔ Ingress gateways installed
✔ Installation complete
Thank you for installing Istio 1.10.  Please take a few minutes to tell us about your install/upgrade experience!  https://forms.gle/KjkrDnMPByq7akrYA

# 验证istio是否部署成功
[root@master bookinfo]# kubectl get pods -n istio-system -o wide
NAME                                    READY   STATUS    RESTARTS   AGE     IP               NODE    NOMINATED NODE   READINESS GATES
istio-egressgateway-659cc7697b-dmx2b    1/1     Running   0          4m50s   10.244.166.130   node1   <none>           <none>
istio-ingressgateway-569f64cdf8-mhp4b   1/1     Running   0          4m50s   10.244.166.131   node1   <none>           <none>
istiod-85c958cd6-854cf                  1/1     Running   0          7m20s   10.244.166.129   node1   <none>           <none>
# 查看3个pod需要拉取的镜像

复制代码

# 下面2个都是使用proxyv2镜像
[root@master ~]# kubectl describe istio-egressgateway-659cc7697b-dmx2b -n istio-system
[root@master ~]# kubectl describe pods istio-ingressgateway-569f64cdf8-mhp4b -n istio-system
Successfully pulled image "docker.io/istio/proxyv2:1.10.1" in 1m10.442079892s

[root@master ~]# kubectl describe pods istiod-85c958cd6-854cf -n istio-system
Successfully pulled image "docker.io/istio/pilot:1.10.1" in 2m23.166032259s

# 下次安装前可以提前将下面2个安装包安装到各个节点
[root@node1 bookinfo]# docker images
istio/proxyv2                                        1.10.1    5c66e8ac89a7   14 months ago   282MB
istio/pilot                                          1.10.1    07d6b563f74b   14 months ago   217MB

复制代码

# 卸载 istio 集群命令(暂时不用执行)
istioctl manifest generate --set profile=demo | kubectl delete -f -

复制代码

五、通过Istio部署在线书店bookinfo
5.1 在线书店功能介绍

在线书店项目-bookinfo介绍:

该应用由四个单独的微服务构成,这个应用模仿在线书店的一个分类,显示一本书的信息,页面上 会显示一本书的描述,书籍的细节(ISBN、页数等),以及关于这本书的一些评论。

Bookinfo 应用分为四个单独的微服务:

  1)productpage 这个微服务会调用 details 和 reviews 两个微服务,用来生成页面;

  2)details 这个微服务中包含了书籍的信息;

  3)reviews 这个微服务中包含了书籍相关的评论,它还会调用 ratings 微服务;

  4)ratings 这个微服务中包含了由书籍评价组成的评级信息。

reviews 微服务有 3 个版本:

  1)v1 版本不会调用 ratings 服务;

  2)v2 版本会调用 ratings 服务,并使用 1 到 5 个黑色星形图标来显示评分信息;

  3)v3 版本会调用 ratings 服务,并使用 1 到 5 个红色星形图标来显示评分信息。

下图展示了bookinfo应用的端到端架构:

Bookinfo 应用中的几个微服务是由不同的语言编写的。这些服务对 istio 并无依赖,但是构成了一 个有代表性的服务网格的例子:它由多个服务、多个语言构成,并且 reviews 服务具有多个版本。

 5.2 部署应用

要在 Istio 中运行这一应用,无需对应用自身做出任何改变。 只要简单的在 Istio 环境中对服务进行配置和运行,具体一点说就是把 Envoy sidecar 注入到每个服务之中。 最终的部署结果将如下图所示:

    所有的微服务都和 Envoy sidecar 集成在一起,被集成服务所有的出入流量都被 envoy sidecar 所劫持,这样就为外部控制准备了所需的 Hook,然后就可以利用 Istio 控制平面为应用提供服务路由、遥测数据收集以及策略实施等功能。

5.3 启动应用服务

https://istio.io/latest/zh/docs/examples/bookinfo/

复制代码

1.进入 istio 安装目录
2..istio 默认自动注入 sidecar,需要为 default 命名空间打上标签 istio-injection=enabled 
[root@master istio-1.10.1]# kubectl label namespace default istio-injection=enabled
namespace/default labeled

3.使用 kubectl 部署应用
cd istio-1.10.1 
# 查看bookinfo.yaml中image镜像和自己导入的镜像是否相同,如果不同请修改
[root@master istio-1.10.1]# kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
service/details created
serviceaccount/bookinfo-details created
deployment.apps/details-v1 created
service/ratings created
serviceaccount/bookinfo-ratings created
deployment.apps/ratings-v1 created
service/reviews created
serviceaccount/bookinfo-reviews created
deployment.apps/reviews-v1 created
deployment.apps/reviews-v2 created
deployment.apps/reviews-v3 created
service/productpage created
serviceaccount/bookinfo-productpage created
deployment.apps/productpage-v1 created
上面的命令会启动全部的四个服务,其中也包括了 reviews 服务的三个版本(v1、v2 以及 v3)。

4.确认所有的服务和 Pod 都已经正确的定义和启动:
[root@master istio-1.10.1]# kubectl get service
NAME          TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
details       ClusterIP   10.105.175.107   <none>        9080/TCP   31s
kubernetes    ClusterIP   10.96.0.1        <none>        443/TCP    10d
productpage   ClusterIP   10.101.26.228    <none>        9080/TCP   31s
ratings       ClusterIP   10.106.84.226    <none>        9080/TCP   31s
reviews       ClusterIP   10.99.121.53     <none>        9080/TCP   31s

[root@master istio-1.10.1]# kubectl get pods
NAME                              READY   STATUS    RESTARTS   AGE
details-v1-65bbfd4f58-bkjwv       2/2     Running   0          88s
productpage-v1-6b746f74dc-47hrz   2/2     Running   0          88s
ratings-v1-b45758b-zgxld          2/2     Running   0          87s
reviews-v1-74894b48c8-8d89s       2/2     Running   0          87s
reviews-v2-f649764d-r7g45         2/2     Running   0          88s
reviews-v3-6c675c6774-7g6tr       2/2     Running   0          88s

5.确认 Bookinfo 应用是否正在运行,在某个 Pod 中用 curl 命令对应用发送请求,例如 ratings:
[root@master istio-1.10.1]# kubectl exec -it $(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}') -c ratings -- curl productpage:9080/productpage | grep -o "<title>.*</title>" 
<title>Simple Bookstore App</title>

复制代码

复制代码

6.确定Ingress的IP和端口现在 Bookinfo 服务已经启动并运行,你需要使应用程序可以从 Kubernetes 集群外部访问,例如从浏览器访问,那可以用 Istio Gateway 来实现这个目标。
1)为应用程序定义gateway网关:
[root@master istio-1.10.1]# kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml 
gateway.networking.istio.io/bookinfo-gateway created
virtualservice.networking.istio.io/bookinfo created

2)确认网关创建完成
[root@master istio-1.10.1]# kubectl get gateway
NAME               AGE
bookinfo-gateway   41s
[root@master istio-1.10.1]# kubectl get virtualservice
NAME       GATEWAYS               HOSTS   AGE
bookinfo   ["bookinfo-gateway"]   ["*"]   2m49s

3)确定ingress ip和端口
[root@master istio-1.10.1]# kubectl get svc istio-ingressgateway -n istio-system
NAME                   TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                                                                      AGE
istio-ingressgateway   LoadBalancer   10.110.182.125   <pending>     15021:30085/TCP,80:31493/TCP,443:31604/TCP,31400:32087/TCP,15443:30605/TCP   103m
    如果 EXTERNAL-IP 值已设置,说明环境正在使用外部负载均衡,可以用其为 ingress gateway 提供服务。 如果 EXTERNAL-IP 值为<none>(或持续显示<pending>), 说明环境没有提供外部负载均衡,
无法使用 ingress gateway。在这种情况下,你可以使用服务的 NodePort 访问网关。 

若自身环境未使用外部负载均衡器,需要通过 node port 访问。可以通过以下命令获取 Istio Gateway 的地址: 
[root@master istio-1.10.1]# export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
[root@master istio-1.10.1]# echo $INGRESS_PORT
31493
[root@master istio-1.10.1]# export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}') 
[root@master istio-1.10.1]# echo $SECURE_INGRESS_PORT
31604

4.设置GATEWAY_URL
[root@master istio-1.10.1]# INGRESS_HOST=192.168.10.10
# 192.168.10.10是安装istio的机器,控制节点IP也可以是工作节点IP
[root@master istio-1.10.1]# export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
[root@master istio-1.10.1]# echo $GATEWAY_URL
192.168.10.10:31493

确认可以从集群外部访问应用:
可以用 curl 命令来确认是否能够从集群外部访问 Bookinfo 应用程序:
[root@master istio-1.10.1]# curl -s http://${GATEWAY_URL}/productpage | grep -o "<title>.*</title>" 
<title>Simple Bookstore App</title>

复制代码

还可以用浏览器打开网址 http://$GATEWAY_URL/productpage:http://192.168.10.10:31493/productpage来浏览应用的Web页面.

如果刷新几次应用的页面,就会看 到 productpage 页面中会随机展示 reviews 服务的不同版本的效果(红色、黑色的星形或者 没有显示)。

 通过 istio 的 ingressgateway 访问,官网: https://istio.io/docs/examples/bookinfo/#determine-the-ingress-ip-and-port

扩展:添加外部IP-extertal-IP

复制代码

# 编辑,在clusterIPs下面新增externalIPs
[root@master istio-1.10.1]# kubectl edit svc istio-ingressgateway -n istio-system
spec:
  clusterIP: 10.110.182.125
  clusterIPs:
  - 10.110.182.125
  externalIPs:
  - 192.168.10.10

# 查看修改是否有成功
[root@master istio-1.10.1]# kubectl get svc istio-ingressgateway -n istio-system
NAME                   TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)                                                                      AGE
istio-ingressgateway   LoadBalancer   10.110.182.125   192.168.10.10   15021:30085/TCP,80:31493/TCP,443:31604/TCP,31400:32087/TCP,15443:30605/TCP   128m

直接访问IP就可以直接访问到页面:http://192.168.10.10/productpage

复制代码

5.4 卸载bookinfo服务

复制代码

1.删除路由规则并销毁应用的Pod
[root@master istio-1.10.1]# sh samples/bookinfo/platform/kube/cleanup.sh

2. 确认应用已关停
kubectl get virtualservices #-- there should be no virtual services 
kubectl get destinationrules #-- there should be no destination rules 
kubectl get gateway #-- there should be no gateway 
kubectl get pods #-- the Bookinfo pods should be deleted 

复制代码

六、通过Istio实现k8s线上业务灰度发布(金丝雀发布)
6.1 什么是灰度发布?

        灰度发布也叫金丝雀部署 ,是指通过控制流量的比例,实现新老版本的逐步更替。 比如对于服务 A 有 version1、 version2 两个版本 , 当前两个版本同时部署,但是 version1 比例 90% ,version2 比例 10% ,看运行效果,如果效果好逐步调整流量占比 80~20 ,70~ 30 ·····10~90 ,0,100 ,最终 version1 版本下线。

灰度发布的特点:

  1)新老版本共存

  2)可以实时根据反馈动态调整占比

  3)理论上不存在服务完全宕机的情况。

  4)适合于服务的平滑升级与动态更新。

6.2 使用istio进行金丝雀发布

复制代码

# 1.镜像导入节点
[root@node1 istio]# docker load -i canary-v1.tar.gz 
Loaded image: simonxiong/canary:v1
[root@node1 istio]# docker load -i canary-v2.tar.gz 
Loaded image: simonxiong/canary:v2

# 2.创建金丝雀服务
[root@master istio-canary]# cat deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: appv1
  labels:
    app: v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: v1
      apply: canary
  template:
    metadata:
      labels:
        app: v1
        apply: canary
    spec:
      containers:
      - name: nginx
        image: simonxiong/canary:v1
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: appv2
  labels:
    app: v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: v2
      apply: canary
  template:
    metadata:
      labels:
        app: v2
        apply: canary
    spec:
      containers:
      - name: nginx
        image: simonxiong/canary:v2
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 80

[root@master istio-canary]# kubectl apply -f deployment.yaml 
deployment.apps/appv1 created
deployment.apps/appv2 created
[root@master istio-canary]# kubectl get pods
NAME                     READY   STATUS    RESTARTS   AGE
appv1-6c9cd7bf-pvdt8     2/2     Running   0          4s
appv2-868b45778c-7njvd   1/2     Running   0          4s

# 3.创建service
[root@master istio-canary]# cat service.yaml 
apiVersion: v1
kind: Service
metadata:
  name: canary
  labels:
    apply: canary
spec:
  selector:
    apply: canary
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
[root@master istio-canary]# kubectl apply -f service.yaml 
service/canary created
[root@master istio-canary]# kubectl get svc
NAME         TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)   AGE
canary       ClusterIP   10.96.5.127   <none>        80/TCP    6s

# 4.创建gateway
[root@master istio-canary]# cat gateway.yaml 
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: canary-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"

[root@master istio-canary]# kubectl apply -f gateway.yaml 
gateway.networking.istio.io/canary-gateway created
[root@master istio-canary]# kubectl get gateway
NAME             AGE
canary-gateway   7s

# 5.创建 virtualservice 虚拟服务
# 可以看到v1和v2的weight不同
[root@master istio-canary]# cat virtual.yaml 
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: canary
spec:
  hosts:
  - "*"
  gateways:
  - canary-gateway
  http:
  - route:
    - destination:
        host: canary.default.svc.cluster.local
        subset: v1
      weight: 90
    - destination:
        host: canary.default.svc.cluster.local
        subset: v2
      weight: 10
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: canary
spec:
  host: canary.default.svc.cluster.local
  subsets:
  - name: v1
    labels:
      app: v1
  - name: v2
    labels:
      app: v2
[root@master istio-canary]# kubectl apply -f virtual.yaml 
virtualservice.networking.istio.io/canary created
destinationrule.networking.istio.io/canary created
[root@master istio-canary]# kubectl get virtualservice
NAME     GATEWAYS             HOSTS   AGE
canary   ["canary-gateway"]   ["*"]   30s
[root@master istio-canary]# kubectl get destinationrule
NAME     HOST                               AGE
canary   canary.default.svc.cluster.local   63s

# 6.获取Ingress_port
[root@master istio-canary]# kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}'
31493

# 验证金丝雀发布效果
[root@master istio-canary]# for i in `seq 1 100`;do curl 192.168.10.10:31493;done > 1.txt
[root@master istio-canary]# cat 1.txt | grep v2 | wc -l
10
[root@master istio-canary]# cat 1.txt | grep v1 | wc -l
90
打开 1.txt 可以看到结果有 90 次出现 v1,10 次出现 canary-v2,符合我们预先设计的流量走向。

复制代码

七、istio核心资源解读

官网: https://istio.io/latest/docs/concepts/traffic-management/

7.1 Gateway资源清单详细解读

在 Kubernetes 环境中,Ingress controller 用于管理进入集群的流量。在 Istio 服务网格中 Istio Ingress Gateway 承担相应的角色,它使用新的配置模型(Gateway 和 VirtualServices)完成流量管理 的功能。通过下图做一个总的描述。

  1、用户向某端口发出请求

  2、负载均衡器监听端口,并将请求转发到集群中的某个节点上。Istio Ingress Gateway Service会监听集群节点端口的请求

  3、Istio Ingress Gateway Service 将请求交给 Istio Ingress Gateway Pod 处理。

  IngressGateway Pod 通过 Gateway 和 VirtualService 配置规则处理请求。其中,Gateway 用来配置 端口、协议和证书;VirtualService 用来配置一些路由信息(找到请求对应处理的服务 App Service)

  4、Istio Ingress Gateway Pod 将请求转给 App Service

  5、最终的请求会交给 App Service 关联的 App Deployment 处理

复制代码

[root@master istio-canary]# kubectl explain gateway
KIND:     Gateway
VERSION:  networking.istio.io/v1beta1

DESCRIPTION:
     <empty>

FIELDS:
   apiVersion    <string>
   kind    <string>
   metadata    <Object>
   spec    <Object>
   status    <>

kubectl explain gateway.spec
kubectl explain gateway.spec.servers
kubectl explain gateway.spec.servers.port
kubectl explain gateway.spec.servers.hosts

apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: canary-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"
网关是一个运行在网格边缘的负载均衡器,用于接收传入或传出的 HTTP/TCP 连接。主要工作是接受 外部请求,把请求转发到内部服务。网格边缘的 Ingress 流量,会通过对应的 Istio IngressGateway Controller 进入到集群内部。
在上面这个 yaml 里我们配置了一个监听 80 端口的入口网关,它会将 80 端口的 http 流量导入到集 群内对应的 Virtual Service 上。

复制代码

 7.2 VirtualService

        VirtualService 是 Istio 流量治理的一个核心配置,可以说是 Istio 流量治理中最重要、最复杂 的。VirtualService 在形式上表示一个虚拟服务,将满足条件的流量都转发到对应的服务后端,这个服 务后端可以是一个服务,也可以是在 DestinationRule 中定义的服务的子集。

复制代码

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: canary
spec:
  hosts:
  - "*"
  gateways:
  - canary-gateway
  http:
  - route:
    - destination:
        host: canary.default.svc.cluster.local
        subset: v1
      weight: 90
    - destination:
        host: canary.default.svc.cluster.local
        subset: v2
      weight: 10
这个虚拟服务会收到上一个 gateway 中所有 80 端口来的 http 流量。

复制代码

VirtualService 主要由以下部分组成:

  1、hosts:虚拟主机名称,如果在 Kubernetes 集群中,则这个主机名可以是 service 服务名。

        hosts 字段列出了 virtual service 的虚拟主机。它是客户端向服务发送请求时使用的一个或多个地址,通过该字段提供的地址访问 virtual service,进而访问后端服务。在集群内部(网格内)使用时通常与 kubernetes 的 Service 同名;当需要在集群外部(网格外)访问时,该字段为 gateway 请求的地址,即 与 gateway 的 hosts 字段相同。

hosts:

- reviews

        virtual service 的主机名可以是 IP 地址、DNS 名称,也可以是短名称(例如 Kubernetes 服务短名 称),该名称会被隐式或显式解析为全限定域名(FQDN),具体取决于 istio 依赖的平台。可以使用前缀 通配符(“*”)为所有匹配的服务创建一组路由规则。virtual service 的 hosts 不一定是 Istio 服务 注册表的一部分,它们只是虚拟目的地,允许用户为网格无法路由到的虚拟主机建立流量模型。

  virtual service 的 hosts 短域名在解析为完整的域名时,补齐的 namespace 是 VirtualService 所 在的命名空间,而非 Service 所在的命名空间。如上例的 hosts 会被解析为: reviews.default.svc.cluster.local。

扩展:virtualservice 配置路由规则

        路由规则的功能是:满足 http.match 条件的流量都被路由到 http.route.destination,执行重定向 (HTTPRedirect)、重写(HTTPRewrite)、重试(HTTPRetry)、故障注入(HTTPFaultInjection)、跨站 (CorsPolicy)策略等。HTTPRoute 不仅可以做路由匹配,还可以做一些写操作来修改请求本身。

如下:

复制代码

apiVersion: networking.istio.io/v1alpha3 
kind: VirtualService 
metadata: 
  name: reviews 
spec: 
  hosts: 
  - reviews 
  http: 
  - match: 
    - headers: 
      end-user: 
        exact: jason 
    route: 
    - destination: 
        host: reviews 
        subset: v2 
  - route: 
    - destination: 
        host: reviews 
        subset: v3 

在 http 字段包含了虚拟服务的路由规则,用来描述匹配条件和路由行为,它们把 HTTP/1.1、HTTP2 和 gRPC 等流量发送到 hosts 字段指定的目标。
示例中的第一个路由规则有一个条件,以 match 字段开始。此路由接收来自 ”jason“ 用户的所有请求,把请求发送到 destination 指定的 v2 子集。 

复制代码

7.2.1 路由规则优先级

  在上面例子中,不满足第一个路由规则的流量均流向一个默认的目标,该目标在第二条规则中指 定。因此,第二条规则没有 match 条件,直接将流量导向 v3 子集。

7.2.2 多路由规则解读

详细配置可参考:https://istio.io/latest/zh/docs/reference/config/networking/virtual-service/#HTTPMatchRequest

复制代码

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: bookinfo
spec:
  hosts:
  - bookinfo.com
  http:
  - match:
    - uri:
        prefix: /reviews
      route:
      - destination: 
        host: reviews
  - match:
    - uri:
        prefix: /ratings
    route:
    - destination:
      host: ratings

复制代码

        路由规则是将特定流量子集路由到指定目标地址的工具。可以在流量端口、header 字段、URI 等内 容上设置匹配条件。例如,上面这个虚拟服务让用户发送请求到两个独立的服务:ratings 和 reviews,相当于访问 http://bookinfo.com/ratings 和 http://bookinfo.com/ reviews,虚拟服务规则根据请求的 URI 把请求路由到特定的目标地址。

2、Gateway:流量来源网关。

3、路由:

        路由的 destination 字段指定了匹配条件的流量的实际地址。与 virtual service 的主机不同,该 host 必须是存在于 istio 的服务注册表(如 kubernetes services,consul services 等)中的真实目的地 或由 ServiceEntries 声明的 hosts,否则 Envoy 不知道应该将流量发送到哪里。它可以是一个带代理的 网格服务或使用 service entry 添加的非网格服务。在 kubernetes 作为平台的情况下,host 表示名为 kubernetes 的 service 名称:

  - destination: 
    host: canary.default.svc.cluster.local 
    subset: v1 
  weight: 90 
7.3 Destination Rule 定义目标规则

        destination rule 是 istio 流量路由功能的重要组成部分。一个 virtual service 可以看作是如何 将流量分发给特定的目的地,然后调用 destination rule 来配置分发到该目的地的流量。destination rule 在 virtual service 的路由规则之后起作用(即在 virtual service 的 math->route-destination 之后起作用,此时流量已经分发到真实的 service 上),应用于真实的目的地。

可以使用 destination rule 来指定命名的服务子集,例如根据版本对服务的实例进行分组,然后通过 virtual service 的路由规则中的服务子集将控制流量分发到不同服务的实例中。

复制代码

cat DestinationRule.yaml 
apiVersion: networking.istio.io/v1beta1 
kind: DestinationRule 
metadata: 
  name: canary 
spec: 
  host: canary.default.svc.cluster.local 
  subsets: 
  - name: v1 
    labels: 
      app: v1 
  - name: v2 
    labels: 
      app: v2
在虚拟服务中使用 Hosts 配置默认绑定的路由地址,用 http.route 字段,设置 http 进入的路由地 址,可以看到,上面导入到了目标规则为 v1 和 v2 的子集。
v1 子集对应的是具有如下标签的 pod: 
selector: 
  matchLabels: 
    app: v1

复制代码

流量控制流程: Gateway->VirtaulService->TCP/HTTP Router->DestinationWeight->Subset:Por

八、Istio服务治理----熔断
8.1 断路器

官网:https://istio.io/latest/zh/docs/tasks/traffic-management/circuit-breaking/

断路器是创建弹性微服务应用程序的重要模式。断路器使应用程序可以适应网络故障和延迟等网络不良影响。

测试断路器

复制代码

# 1.在k8s集群创建后端服务,httpbin 应用程序充当后端服务;httpbin镜像之前已经导入到节点中
[root@master istio]# cat istio-1.10.1/samples/httpbin/httpbin.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: httpbin
---
apiVersion: v1
kind: Service
metadata:
  name: httpbin
  labels:
    app: httpbin
    service: httpbin
spec:
  ports:
  - name: http
    port: 8000
    targetPort: 80
  selector:
    app: httpbin
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin
      version: v1
  template:
    metadata:
      labels:
        app: httpbin
        version: v1
    spec:
      serviceAccountName: httpbin
      containers:
      - image: docker.io/kennethreitz/httpbin
        imagePullPolicy: IfNotPresent
        name: httpbin
        ports:
        - containerPort: 80

[root@master istio]# kubectl apply -f istio-1.10.1/samples/httpbin/httpbin.yaml 
serviceaccount/httpbin created
service/httpbin created
deployment.apps/httpbin created

# 2.配置断路器
# 创建一个目标规则,在调用httpbin服务时应用断路器设置:
[root@master istio-1.10.1]# cat destination.yaml 
apiVersion:  networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: httpbin
spec:
  host: httpbin
  trafficPolicy:
    connectionPool: #连接池(TCP | HTTP)配置,例如:连接数、并发请求等 
      tcp:
        maxConnections: 1  #TCP 连接池中的最大连接请求数,当超过这个值,会返回 503 代码。如两个请求过来,就会有一个请求返回 503。
      http:
        http1MaxPendingRequests: 1  #连接到目标主机的最大挂起请求数,也就是待处理请求数。这里的目标指的是 virtualservice 路由规则中配置的 destination。
        maxRequestsPerConnection: 1  #连接池中每个连接最多处理 1 个请求后就关闭,并根据需要重新创建连接池中的连接
    outlierDetection:  #异常检测配置,传统意义上的熔断配置,即对规定时间内服务错误数的监测 
      consecutiveGatewayErrors: 1  #连续错误数 1,即连续返回 502-504 状态码的 Http 请求错误数 
      interval: 1s  #错误异常的扫描间隔 1s,即在 interval(1s)内连续发生 consecutiveGatewayErrors(1)个错误,则触发服务熔断
      baseEjectionTime: 3m  #基本驱逐时间 3 分钟,实际驱逐时间为 baseEjectionTime*驱逐次数 
      maxEjectionPercent: 100  #最大驱逐百分比 100%

[root@master istio-1.10.1]# kubectl apply -f destination.yaml 
destinationrule.networking.istio.io/httpbin created

复制代码

复制代码

[root@master istio-1.10.1]# kubectl get destinationrule
NAME      HOST                               AGE
canary    canary.default.svc.cluster.local   18h
httpbin   httpbin                            4m14s

# 3.添加客户端访问httpbin服务
创建一个客户端以将流量发送给 httpbin 服务。该客户端是一个简单的负载测试客户端,Fortio 可以控制连接数,并发数和 HTTP 调用延迟。使用此客户端来“跳闸”在 DestinationRule 中设置的断路器策略。
#通过执行下面的命令部署 fortio 客户端:
[root@node1 istio]# docker load -i fortio.tar.gz 
Loaded image: fortio/fortio:latest_release
[root@master istio]# cd istio-1.10.1/samples/httpbin/sample-client
[root@master sample-client]# kubectl apply -f fortio-deploy.yaml 
service/fortio created
deployment.apps/fortio-deploy created

[root@master sample-client]# kubectl get pods
NAME                             READY   STATUS    RESTARTS   AGE
appv1-6c9cd7bf-pvdt8             2/2     Running   0          18h
appv2-868b45778c-7njvd           2/2     Running   0          18h
fortio-deploy-576dbdfbc4-6j8g9   2/2     Running   0          85s
httpbin-74fb669cc6-5g5c9         2/2     Running   0          12m

[root@master sample-client]# kubectl exec fortio-deploy-576dbdfbc4-6j8g9 -c fortio -- /usr/bin/fortio curl http://httpbin:8000/get 
HTTP/1.1 200 OK
server: envoy

复制代码

复制代码

# 4.触发断路器
在 DestinationRule 设置中,指定了 maxConnections: 1 和http1MaxPendingRequests: 1。这些规则表明,如果超过一个以上的连接并发请求,则 istio-proxy 在为进一步的请求和连接打开路由时,应该会看到下面的情况 。 
以两个并发连接(-c 2)和发送 20 个请求(-n 20)调用服务: 
[root@master sample-client]# kubectl exec -it fortio-deploy-576dbdfbc4-6j8g9 -c fortio -- /usr/bin/fortio load -c 2 -qps 0 -n 20 -loglevel Warning http://httpbin:8000/get
03:17:08 I logger.go:127> Log level is now 3 Warning (was 2 Info)
Fortio 1.17.1 running at 0 queries per second, 6->6 procs, for 20 calls: http://httpbin:8000/get
Starting at max qps with 2 thread(s) [gomax 6] for exactly 20 calls (10 per thread + 0)
03:17:08 W http_client.go:806> [0] Non ok http code 503 (HTTP/1.1 503)
03:17:08 W http_client.go:806> [0] Non ok http code 503 (HTTP/1.1 503)
03:17:08 W http_client.go:806> [0] Non ok http code 503 (HTTP/1.1 503)
03:17:08 W http_client.go:806> [0] Non ok http code 503 (HTTP/1.1 503)
03:17:08 W http_client.go:806> [1] Non ok http code 503 (HTTP/1.1 503)
03:17:08 W http_client.go:806> [0] Non ok http code 503 (HTTP/1.1 503)
03:17:08 W http_client.go:806> [1] Non ok http code 503 (HTTP/1.1 503)
03:17:08 W http_client.go:806> [1] Non ok http code 503 (HTTP/1.1 503)
03:17:08 W http_client.go:806> [1] Non ok http code 503 (HTTP/1.1 503)
03:17:08 W http_client.go:806> [1] Non ok http code 503 (HTTP/1.1 503)
03:17:08 W http_client.go:806> [0] Non ok http code 503 (HTTP/1.1 503)
03:17:08 W http_client.go:806> [1] Non ok http code 503 (HTTP/1.1 503)
03:17:08 W http_client.go:806> [0] Non ok http code 503 (HTTP/1.1 503)
03:17:08 W http_client.go:806> [1] Non ok http code 503 (HTTP/1.1 503)
03:17:08 W http_client.go:806> [0] Non ok http code 503 (HTTP/1.1 503)
03:17:08 W http_client.go:806> [0] Non ok http code 503 (HTTP/1.1 503)
03:17:08 W http_client.go:806> [1] Non ok http code 503 (HTTP/1.1 503)
03:17:08 W http_client.go:806> [1] Non ok http code 503 (HTTP/1.1 503)
03:17:08 W http_client.go:806> [1] Non ok http code 503 (HTTP/1.1 503)
Ended after 56.515285ms : 20 calls. qps=353.89
Aggregated Function Time : count 20 avg 0.0055688861 +/- 0.01001 min 0.000558887 max 0.042719936 sum 0.111377723
# range, mid point, percentile, count
>= 0.000558887 <= 0.001 , 0.000779444 , 35.00, 7
> 0.001 <= 0.002 , 0.0015 , 50.00, 3
> 0.002 <= 0.003 , 0.0025 , 75.00, 5
> 0.004 <= 0.005 , 0.0045 , 80.00, 1
> 0.006 <= 0.007 , 0.0065 , 85.00, 1
> 0.012 <= 0.014 , 0.013 , 90.00, 1
> 0.02 <= 0.025 , 0.0225 , 95.00, 1
> 0.04 <= 0.0427199 , 0.04136 , 100.00, 1
# target 50% 0.002
# target 75% 0.003
# target 90% 0.014
# target 99% 0.0421759
# target 99.9% 0.0426655
Sockets used: 19 (for perfect keepalive, would be 2)
Jitter: false
Code 200 : 1 (5.0 %)
Code 503 : 19 (95.0 %)
# 只有5%成功,其余都断开了
Response Header Sizes : count 20 avg 11.55 +/- 50.35 min 0 max 231 sum 231
Response Body/Total Sizes : count 20 avg 186.6 +/- 146.5 min 153 max 825 sum 3732
All done 20 calls (plus 0 warmup) 5.569 ms avg, 353.9 qps

复制代码

8.2 超时

        在生产环境中经常会碰到由于调用方等待下游的响应过长,堆积大量的请求阻塞了自身服务,造成雪崩的情况,通过超时处理来避免由于无限期等待造成的故障,进而增强服务的可用性,Istio 使用虚拟服务来优雅实现超时处理.

        下面例子模拟客户端调用 nginx,nginx 将请求转发给 tomcat。nginx 服务设置了超时时间为 2 秒,如果超出这个时间就不在等待,返回超时错误。tomcat 服务设置了响应时间延迟 10 秒,任何请求都 需要等待 10 秒后才能返回。client 通过访问 nginx 服务去反向代理 tomcat 服务,由于 tomcat 服务 需要10 秒后才能返回,但 nginx 服务只等待 2 秒,所以客户端会提示超时错误。

 nginx-deployment.yaml

 nginx-tomcat-svc.yaml

 cat virtual-tomcat.yaml

复制代码

#virtual-tomcat.yaml 资源清单重点知识讲解 
第一:故障注入: 
  http:
  - fault:
      delay:
        percentage:
          value: 100
        fixedDelay: 10s
该设置说明每次调用 tomcat-svc 的 k8s service,都会延迟 10s 才会调用。

  hosts:
  - nginx-svc
  http:
  - route:
    - destination: 
        host: nginx-svc
    timeout: 2s
该设置说明调用 nginx-svc 的 k8s service,请求超时时间是 2s。 

复制代码

复制代码

# 搭建环境
# 把 busybox.tar.gz、 nginx.tar.gz、 tomcat-app.tar.gz 上传到node节点中,并导入
docker load -i nginx.tar.gz
docker load -i tomcat-app.tar.gz
docker load -i busybox.tar.gz

[root@master timeout]# kubectl apply -f nginx-deployment.yaml 
deployment.apps/nginx-tomcat created
deployment.apps/tomcat created

[root@master timeout]# kubectl get pods
NAME                             READY   STATUS    RESTARTS   AGE
nginx-tomcat-7dd6f74846-w2r8l    2/2     Running   0          2m43s
tomcat-86ddb8f5c9-pgt8m          2/2     Running   0          2m43s

# service svc
[root@master timeout]# kubectl get svc
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
nginx-svc    ClusterIP   10.111.225.41    <none>        80/TCP     20s
tomcat-svc   ClusterIP   10.100.251.247   <none>        8080/TCP   20s

[root@master timeout]# kubectl apply -f virtual-tomcat.yaml 
virtualservice.networking.istio.io/nginx-vs created
virtualservice.networking.istio.io/tomcat-vs created
[root@master timeout]# kubectl get VirtualService
NAME        GATEWAYS             HOSTS            AGE
canary      ["canary-gateway"]   ["*"]            20h
nginx-vs                         ["nginx-svc"]    23s
tomcat-vs                        ["tomcat-svc"]   23s

[root@master timeout]# kubectl exec -it nginx-tomcat-7dd6f74846-w2r8l -- /bin/sh
# 修改nginx配置文件
# apt-get update
# apt-get install vim -y
# cat /etc/nginx/conf.d/default.conf
server {
    listen       80;
    listen  [::]:80;
    server_name  localhost;

    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        #root   /usr/share/nginx/html;
        #index  index.html index.htm;
        proxy_pass http://tomcat-svc:8080;
        proxy_http_version 1.1; 
    }
# nginx -t
# nginx -s reload

复制代码

复制代码

# 验证超时
[root@master timeout]# kubectl run busybox --image busybox:1.28 --restart=Never --rm -it busybox -- sh
/ # time wget -q -O - http://nginx-svc
wget: server returned error: HTTP/1.1 504 Gateway Timeout
Command exited with non-zero status 1
real    0m 2.01s
user    0m 0.00s
sys    0m 0.00s

/ # while true; do wget -q -O - http://nginx-svc; done
wget: server returned error: HTTP/1.1 504 Gateway Timeout
wget: server returned error: HTTP/1.1 504 Gateway Timeout
每隔 2 秒,由于 nginx 服务的超时时间到了而 tomcat 未有响应,则提示返回超时错误。
/ # time wget -q -O - http://tomcat-svc
wget: server returned error: HTTP/1.1 503 Service Unavailable
Command exited with non-zero status 1
real    0m 10.01s
user    0m 0.00s
sys    0m 0.00s
执行之后 10s 才会有结果

复制代码

8.3 故障注入和重试

Istio 重试机制就是如果调用服务失败,Envoy 代理尝试连接服务的最大次数。而默认情况下, Envoy 代理在失败后并不会尝试重新连接服务,除非我们启动 Istio 重试机制。

下面例子模拟客户端调用 nginx,nginx 将请求转发给 tomcat,tomcat 通过故障注入而中止对外服务,nginx 设置如果访问 tomcat 失败则会重试 3 次

 virtual-attempt.yaml

复制代码

虚拟服务资源清单解读: 
第一:故障注入。该虚拟服务的作用对象就是 tomcat-svc。使用此故障注入后,在网格中该 tomcat 就是不可用的。 
      abort:
        percentage:
          value: 100
        httpStatus: 503
abort 是模拟 tomcat 服务始终不可用,该设置说明每次调用 tomcat-svc 的 k8s service,100%都会返回错误状态码 503。 

第二:调用超时:
  hosts:
  - nginx-svc
  http:
  - route:
    - destination: 
        host: nginx-svc
    retries:
      attempts: 3
      perTryTimeout: 2s
该设置说明调用 nginx-svc 的 k8s service,在初始调用失败后最多重试 3 次来连接到服务子集,每个重试都有 2 秒的超时。 

复制代码

复制代码

# 将超时测试生成的pod、svc、virtual都删除,重新生成
[root@master timeout]# kubectl apply -f nginx-deployment.yaml 
deployment.apps/nginx-tomcat created
deployment.apps/tomcat created
[root@master timeout]# kubectl apply -f nginx-tomcat-svc.yaml 
service/nginx-svc created
service/tomcat-svc created
[root@master timeout]# kubectl apply -f virtual-attempt.yaml 
virtualservice.networking.istio.io/nginx-vs created
virtualservice.networking.istio.io/tomcat-vs created
[root@master timeout]# kubectl get VirtualService
NAME        GATEWAYS             HOSTS            AGE
canary      ["canary-gateway"]   ["*"]            20h
nginx-vs                         ["nginx-svc"]    2m43s
tomcat-vs                        ["tomcat-svc"]   2m43s

#登录进入nginx-tomcat-7dd6f74846-gcrh2,修改/etc/nginx/confd./default.conf,与超时设置一样修改


#验证重试是否生效 
kubectl run busybox --image busybox:1.28 --restart=Never --rm -it busybox -- sh 
# wget -q -O - http://nginx-svc 
# 查看日志
 kubectl logs -f nginx-tomcat-7dd6f74846-gcrh2 -c istio-proxy

复制代码

九、分布式追踪系统---jaeger(暂未部署)
9.1 分布式追踪简介

(1)什么是分布式追踪?

分布式追踪最早由谷歌的 Dapper 普及开来,它本质上是具有在微服务的整个生命周期中追踪请求 的能力。分布式追踪(Distributed Tracing)主要用于记录整个请求链的信息

(2) 为什么要分布式追踪

        当业务微服务化后,一次业务请求,可能会涉及到多个微服务,分布式跟踪可以对跨多个分布式服务 网格的 1 个请求进行追踪分析,并通过可视化的方式深入地了解请求的延迟,序列化和并发,充分地了解 服务流量实况,从而快速地排查和定位问题。在微服务应用中,一个完整的业务往往需要调用多个服务才能完成,服务之间就产生了交互。当出现故障时,如何找到问题的根源非常重要。追踪系统可以清晰地展 示出请求的整个调用链以及每一步的耗时,方便查找问题所在。

(3)分布式追踪系统-jaeger

Jaeger 是一个开源的分布式追踪系统,它可以在复杂的分布式系统中进行监控和故障排查。Jaeger 的主要功能包括分布式请求监控、性能调优、故障分析和服务依赖分析等。

9.2 Jaeger组件介绍

jaeger-agent: 负责发送的进程,对 spans 进行处理并发送给 collector,监听 spans 的 UDP 发送。这层作为基 础组件部署在主机上,Agent 将 Client Library 和 Collector 解耦,为 ClientLibrary 屏蔽了路由和发现 Collector 的细节。

jaeger-collector: 收集追踪 spans,并通过管道对追踪数据进行处理。当前的管道支持追踪的验证、索引、转换,最 后存储数据

jaeger-query: 从存储中检索追踪信息并通过 UI 展示

data store: 追踪信息的存储

9.3 使用Jaeger

复制代码

cd iso-1.10.1 && kubectl apply -f sample/addos
kubectl get svc -n istio-system | grep jaeger

修改 jaeger-query 的 type 类型为 nodePort
kubectl edit svc jaeger-query -n istio-system
把 type: ClusterIP 变成 type: NodePort

浏览器访问:http://192.168.10.10:

复制代码

查看追踪数据:
在 Jaeger 左侧版面的 Service 下拉列表中选择 v1.default,单击 Find Traces 按钮,会看到如下图所示:

追踪上下文传递:

        Istio 利用 Envoy 的分布式追踪功能提供了开箱即用的追踪集成。确切地说,Istio 提供了安装各 种追踪后端服务的选项,并且通过配置代理来自动发送追踪 span 到追踪后端服务。尽管 Istio 代理能 够自动发送 span,但是他们需要一些附加线索才能将整个追踪链路关联到一起。所以当代理发送 span 信息的时候,应用需要附加适当的 HTTP 请求头信息,这样才能够把多个 span 正确的关联到同一个追 踪上。

要做到这一点,应用程序从传入请求到任何传出的请求中需要包含以下请求头参数:

x-request-id

x-b3-traceid

x-b3-spanid

x-b3-parentspanid

x-b3-sampled

x-b3-flags

x-ot-span-context

十、分布式追踪系统-kiali
10.1 kiali简介

Kiali 是 Istio 服务网格的可视化工具,它主要的功能是用可视化的界面来观察微服务系统以及服务之 间的关系。Kiali 功能如下。

  1)服务拓扑图:这是 Kiali 最主要的功能,提供了一个总的服务视图,可以实时地显示命名空间下 服务之间的调用和层级关系,以及负载情况。

  2)服务列表视图:展示了系统中所有的服务,以及它们的健康状况和出错率。· 工作负载视图:展 示服务的负载情况。

  3)Istio 配置视图:展示了所有的 Istio 配置对象。

Kiali 的架构比较简单,如下图,它分为前端和后端两部分。后端以容器的方式运行在应用平台,负 责获取和处理数据,并发送给前端;前端是一个典型的 Web 应用,由 React 和 TypeScript 实现,负责 展示后端发送过来的数据。对 Kiali 来说 Istio 是必须存在的系统,它类似于 Kiali 的宿主。虽然它们可以 分开部署,但没有了 Istio,Kiali 是不能工作的

 9.2 kiali使用

复制代码

kubectl get svc -n istio-system | grep kiali

修改 kiali 的 type 类型为 nodePort
kubectl edit svc kiali -n istio-system
把 type: ClusterIP 变成 type: NodePort

kubectl get svc -n istio-system | grep kiali

在浏览器访问:192.168.10.10:30172

 查看graph,上面可以查看访问deployment的步骤线路图

需要先访问下才能生成

for i in `seq 1 100`;do curl 192.168.10.10:32412;done > 1.txt

复制代码

Kiali 是一个非常强大的可视化工具,可以让用户清晰和直观地了解到 Istio 服务网格中的服务以及服 务之间的关系。除了服务拓扑图外,它还提供了健康检查、指标数据显示和配置验证等功能。强烈推荐把 Kiali 作为必选项添加到服务网格中,来帮助监控和观测网格中服务的工作情况

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值