Istio微服务入门---通过istio部署微服务实现灰度发布(15)
一、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.4 服务度量
于 HTTP,HTTP/2 和 GRPC 流量,Istio 生成以下指标:
1、请求计数(istio_requests_total):这是一个用于累加每个由 Istio 代理所处理请求的 COUNTER 指标。
2、请求持续时间(istio_request_duration_seconds):这是一个用于测量请求的持续时间的 DISTRIBUTION 指标。
3、请求大小(istio_request_bytes):这是一个用于测量 HTTP 请求 body 大小的 DISTRIBUTION 指标。
4、响应大小(istio_response_bytes):这是一个用于测量 HTTP 响应 body 大小的 DISTRIBUTION 指标。
对于 TCP 流量,Istio 生成以下指标:
1、Tcp 发送字节数(istio_tcp_sent_bytes_total):这是一个用于测量在 TCP 连接下响应期间发 送的总字节数的 COUNTER 指标。
2、Tcp 接收字节数(istio_tcp_received_bytes_total):这是一个用于测量在 TCP 连接下请求期 间接收的总字节数的 COUNTER 指标。
3、Tcp 打开连接数(istio_tcp_connections_opened_total):这是一个用于累加每个打开连接的 COUNTER 指标。
4、Tcp 关闭连接数 (istio_tcp_connections_closed_total) : 这是一个用于累加每个关闭连接的 COUNTER 指标。
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要的压缩包
官网下载地址: 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 启动应用服务
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 秒,所以客户端会提示超时错误。
[root@master timeout]# cat nginx-deployment.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-tomcat
labels:
server: nginx
app: web
spec:
replicas: 1
selector:
matchLabels:
server: nginx
app: web
template:
metadata:
name: nginx
labels:
server: nginx
app: web
spec:
containers:
- name: nginx
image: nginx:latest
imagePullPolicy: IfNotPresent
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: tomcat
labels:
server: tomcat
app: web
spec:
replicas: 1
selector:
matchLabels:
server: tomcat
app: web
template:
metadata:
name: tomcat
labels:
server: tomcat
app: web
spec:
containers:
- name: tomcat
image: docker.io/kubeguide/tomcat-app:v1
imagePullPolicy: IfNotPresent
nginx-deployment.yaml
[root@master timeout]# cat nginx-tomcat-svc.yaml
---
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
spec:
selector:
server: nginx
ports:
- name: http
port: 80
targetPort: 80
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: tomcat-svc
spec:
selector:
server: tomcat
ports:
- name: http
port: 8080
targetPort: 8080
protocol: TCP
nginx-tomcat-svc.yaml
[root@master timeout]# cat virtual-tomcat.yaml
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: nginx-vs
spec:
hosts:
- nginx-svc
http:
- route:
- destination:
host: nginx-svc
timeout: 2s
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: tomcat-vs
spec:
hosts:
- tomcat-svc
http:
- fault:
delay:
percentage:
value: 100
fixedDelay: 10s
route:
- destination:
host: tomcat-svc
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 次
[root@master timeout]# cat virtual-attempt.yaml
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: nginx-vs
spec:
hosts:
- nginx-svc
http:
- route:
- destination:
host: nginx-svc
retries:
attempts: 3
perTryTimeout: 2s
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: tomcat-vs
spec:
hosts:
- tomcat-svc
http:
- fault:
abort:
percentage:
value: 100
httpStatus: 503
route:
- destination:
host: tomcat-svc
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
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:
Kiali 是一个非常强大的可视化工具,可以让用户清晰和直观地了解到 Istio 服务网格中的服务以及服 务之间的关系。除了服务拓扑图外,它还提供了健康检查、指标数据显示和配置验证等功能。强烈推荐把 Kiali 作为必选项添加到服务网格中,来帮助监控和观测网格中服务的工作情况
Istio微服务入门---通过istio部署微服务实现灰度发布(15)的更多相关文章
- Taurus.MVC 微服务框架 入门开发教程:项目部署:1、微服务应用程序常规部署实现多开,节点扩容。
系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 本系列第一篇:Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单 ...
- Taurus.MVC 微服务框架 入门开发教程:项目部署:6、微服务应用程序Docker部署实现多开。
系列目录: 本系列分为项目集成.项目部署.架构演进三个方向,后续会根据情况调整文章目录. 开源地址:https://github.com/cyq1162/Taurus.MVC 本系列第一篇:Tauru ...
- SpringCloud微服务实战——搭建企业级开发框架(三十四):SpringCloud + Docker + k8s实现微服务集群打包部署-Maven打包配置
SpringCloud微服务包含多个SpringBoot可运行的应用程序,在单应用程序下,版本发布时的打包部署还相对简单,当有多个应用程序的微服务发布部署时,原先的单应用程序部署方式就会显得复杂且 ...
- Java生鲜电商平台-微服务入门与服务的拆分架构实战
Java生鲜电商平台-微服务入门与服务的拆分架构实战 刚开始进入软件行业时还是单体应用的时代,前后端分离的概念都还没普及,开发的时候需要花大量的时间在“强大”的JSP上面,那时候SOA已经算是新技术了 ...
- 微服务从设计到部署(二)使用 API 网关
链接:https://github.com/oopsguy/microservices-from-design-to-deployment-chinese 译者:Oopsguy 本书的七个章节是关于设 ...
- .Net Core微服务入门全纪录(七)——IdentityServer4-授权认证
前言 上一篇[.Net Core微服务入门全纪录(六)--EventBus-事件总线]中使用CAP完成了一个简单的Eventbus,实现了服务之间的解耦和异步调用,并且做到数据的最终一致性.这一篇将使 ...
- .Net Core微服务入门全纪录(完结)——Ocelot与Swagger
Tips:本篇已加入系列文章阅读目录,可点击查看更多相关文章. 前言 上一篇[.Net Core微服务入门全纪录(八)--Docker Compose与容器网络]完成了docker-compose.y ...
- 微服务入门三:SpringCloud Alibaba
一.什么是SpringCloud Alibaba 1.简介 1)简介 阿里云未分布式应用开发提供了一站式解决方案.它包含了开发分布式应用程序所需的所有组件,使您可以轻松地使用springcloud开发 ...
- 《Spring Cloud微服务 入门 实战与进阶》
很少在周末发文,还是由于昨晚刚收到实体书,还是耐不住性子马上发文了. 一年前,耗时半年多的时间,写出了我的第一本书<Spring Cloud微服务-全栈技术与案例解析>. 时至今日,一年的 ...
- .Net Core微服务入门全纪录(二)——Consul-服务注册与发现(上)
前言 上一篇[.Net Core微服务入门全纪录(一)--项目搭建]讲到要做到服务的灵活伸缩,那么需要有一种机制来实现它,这个机制就是服务注册与发现.当然这也并不是必要的,如果你的服务实例很少,并且很 ...
随机推荐
- verilog语法基础学习系列
verilog语法 1.学习目标 verilog语法是数字电路的基础.好像大部分的数字电路工程师都需要在面试时回答相关问题,一些甚至需要对该块的知识进行机考.所以,这部分的知识需要明确的概念和结合数字 ...
- KingbaseES数据库配置Hikari数据源
Hikari是一个高性能的数据库连接池,它是Spring Boot 2.x中的默认数据源. 一.下载驱动 打开下面网址:选择对应平台的jdbc驱动程序. 人大金仓-成为世界卓越的数据库产品与服务提供商 ...
- KingbaseES V8R6集群运维案例之---修改ssh端口后脚本创建互信
案例分析: 在KingbaseES V8R6集群部署时,需要建立节点之间ssh互信(或者使用securecmdd工具),在有的生产环境,为了安全起见会修改ssh的默认端口:KingbaseES V8R ...
- KingbaseES 用户密码认证及加密算法
kingbaseES用户的口令被存储在sys_authid系统表中. 口令可以用SQL命令create user 和alter user 管理,例如 :create/alter user u1 wit ...
- springboot3接入nacos
参考:https://blog.csdn.net/qinguan111/article/details/132877842(连接不上nacos) https://verytoolz.com/yaml- ...
- 第十三届蓝桥杯大赛软件赛省赛【Java 大学B 组】试题B: 山
1 public class HelloWorld { 2 public static void main(String args[]) { 3 long count=0; 4 String temp ...
- 采用DevOps的7个主要障碍,你一定不知道!
尽管DevOps已经相对成熟,DevOps哲学仍然在回避甚至是最著名和最有资源的组织.一份令人震惊的Gartner报告显示,75%的DevOps项目未能实现其目标.为什么DevOps的失败率如此之高? ...
- #01背包#洛谷 4161 [SCOI2009]游戏
题目 将 \(n\) 拆成若干个正整数的和, 问这些正整数的LCM有多少种 \(n\leq 10^3\) 分析 考虑这个\(LCM\)一定是1或者由若干个质数的指数幂相乘得到的, 那么可以设\(dp[ ...
- #Tarjan#洛谷 1407 [国家集训队]稳定婚姻
题目 分析 如果婚姻安全那么两个点不在同一个强连通分量, 考虑强制定方向,夫妻女向男连边,情侣男向女连边, 这样就直接用Tarjan有向图缩点就可以了 代码 #include <iostream ...
- [原创工具] 病毒整理器V0.98
最近由于各种需要,所以开发了一个. RT,下载地址: 链接:https://pan.baidu.com/s/1Kxd77-n3fbPZQm_CIH6LTA 提取码:xq8f 很简单的一个小工具,以后还 ...