
k8s istio学习
Bookinfo 应用分为四个单独的微服务1)productpage 这个微服务会调用 details 和 reviews 两个微服务,用来生成页面2)details 这个微服务中包含了书籍的信息;3)reviews 这个微服务中包含了书籍相关的评论,它还会调用 ratings 微服务;4)ratings 这个微服务中包含了由书籍评价组成的评级信息。reviews 微服务有 3 个版本1)v1 版
文章目录
1、istio是什么
连接,安全加固,控制和观察服务的开放平台,本身就是一个开源平台,服务对应的是微服务,也就是单个应用
-
连接 智能控制服务之间的调用流量,能够实现灰度升级、AB 测试和蓝绿部署等功
能 -
安全加固 自动为服务之间的调用提供认证、授权和加密
-
控制 应用用户定义的 policy,保证资源在消费者中公平分配
-
观察 查看服务运行期间的各种数据,比如日志、监控和 tracing,了解服务的运行
情况 -
降低了部署的复杂性
-
微服务分层解耦
-
服务发现
-
服务注册,就是部署了一个tomcat服务,ip和端口都会被注册中心里面所注册
-
服务发现,就是从注册中心上获取服务的信息
-
-
负载均衡
- 将前台的请求分发到后台的多个服务器上面,避免都发送到了一个服务器上面,减小压力
-
故障恢复
- 出现故障具备恢复的能力,pod出现了问题,通过控制器,将其创建出来
-
服务度量
-
灰度发布
- 也叫做金丝雀发布,就是更新镜像,先升级一个镜像的pod,测试这个pod是否有情况,没有问题的话,就升级其他的pod的镜像
-
-
istio的特性
-
断路器(服务熔断)
-
就是a服务一直调用b服务,但是b服务出现了问题的话,就会一直调用,占用资源
-
istio解决了这问题,出现了问题,不会进行调用了
-
当有10个请求中,有10%失败了,服务熔断就会打开,再次请求的时候,直接返回失败,过了一定的时间后,重新检测该触发条件,判断是否打开熔断器
-
服务降级
- 请求量过多的时候,不返回一个错误的页面,返回一个静态页面写好的信息,提升用户体验
-
-
超时
- 避免调用方等待响应的时间过长,堆积大量的请求阻塞自身服务,通过超时来处理避免由于等待造成的故障
-
重试
- 如果调用服务失败的话,会尝试连接服务的最大次数,默认情况下,失败后并不会尝试连接服务
-
多路由规则
-
2、istio架构
-
数据平面
-
数据平面由一组以 Sidecar 方式部署的智能代理(Envoy+Polit-agent)组成。这些代理承载并控制微服务之间的所有网络通信,管理入口和出口流量,类似于一线员工。 Sidecar 一般和业务容器绑定在一起(在 Kubernets 中以自动注入的方式注入到到业务 pod 中),来劫持业务应用容器的流量,并接受控制面组件的控制,同时会向控制面输出日志、跟踪及监控数据
-
这个代理就是进来和出去的流量都要经过的
-
Envoy 和 pilot-agent 打在同一个镜像中,即 sidecar Proxy
-
-
控制平面
-
负责管理和配置代理来路由流量
-
istio1.5+中使用了一个全新的部署模式,重建了控制平面,将原有的多个组件整合为一个单体结构istiod,这个组件是控制平面的核心,管理 Istio 的所有功能,主要包括 Pilot、Mixer、Citadel等服务组件
-
istiod 是新版本中最大的变化,以一个单体组件替代了原有的架构,降低了复杂度和维护难度,但原有的多组件并不是被完全移除,而是在重构后以模块的形式整合在一起组成了 istiod
-
-
istio工作流程
-
自动注入
- 在创建应用程序时自动注入 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 拦截
-
服务发现
- 服务发起方的 Envoy 调用控制面组件 Pilot 的服务发现接口获取目标服务的实例列表。上图中,frontend 服务侧的 Envoy 通过 Pilot 的服务发现接口得到 forecast 服务各个实例的地址
-
负载均衡
- 服务发起方的 Envoy 根据配置的负载均衡策略选择服务实例,并连接对应的实例地址。上图中,数据面的各个 Envoy 从 Pilot 中获取 forecast 服务的负载均衡配置,并执行负载均衡动作
-
流量治理
- Envoy 从 Pilot 中获取配置的流量规则,在拦截到 Inbound 流量和 Outbound 流量时执行治理逻辑。上图中, frontend 服务侧的 Envoy 从 Pilot 中获取流量治理规则,并根据该流量治理规则将不同特征的流量分发到 forecast 服务的 v1 或 v2 版本
-
访问安全
- 在服务间访问时通过双方的 Envoy 进行双向认证和通道加密,并基于服务的身份进行授权管理。上图中,Pilot 下发安全相关配置,在 frontend 服务和 forecast 服务的 Envoy 上自动加载证书和密钥来实现双向认证,其中的证书和密钥由另一个管理面组件 Citadel 维护
-
服务检测
- 在服务间通信时,通信双方的 Envoy 都会连接管理面组件 Mixer 上报访问数据,并通过Mixer 将数据转发给对应的监控后端。上图中,frontend 服务对 forecast 服务的访问监控指标、日志和调用链都可以通过这种方式收集到对应的监控后端
-
策略执行
- 在进行服务访问时,通过 Mixer 连接后端服务来控制服务间的访问,判断对访问是放行还是拒绝。上图中,Mixer 后端可以对接一个限流服务对从 frontend 服务到 forecast 服务的访问进行速率控制等操作
-
外部访问
- 在网格的入口处有一个 Envoy 扮演入口网关的角 色。上图中,外部服务通过 Gateway 访问入口服务 frontend,对 frontend 服务的负载均衡和一些流量治理策略都在这个 Gateway 上执行
-
-
istio组件详解
-
Pilot
-
是主要的控制组件,下发指令控制客户端,在整个系统中,polit完成一下任务
-
从kubernetes或者其他注册中心获取服务信息,完成服务发现过程
-
读取istio各项控制配置,在进行转发之后,并将其发送给数据面进行实施
-
-
Pilot 将配置内容下发给数据面的 Envoy,Envoy 根据 Pilot 指令,将路由、服务、监听、集群等定义信息转换为本地配置,完成控制行为的落地
-
Pilot 为 Envoy 提供服务发现
-
提供流量管理功能(例如,A/B 测试、金丝雀发布等)以及弹性功能(超时、重试、熔断器等)
-
生成 envoy 配置
-
启动 envoy,实际上是piloy-agent启动的
-
监控并管理 envoy 的运行状况,比如 envoy 出错时 pilot-agent 负责重启 envoy,或者 envoy 配置变更后 reload envoy
-
-
envoy
-
Envoy 是用 C++ 开发的高性能代理,用于协调服务网格中所有服务的入站和出站流量
-
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)
-
-
-
citadel
-
负责处理系统上不同服务之间的 TLS 通信。 Citadel 充当证书颁发机构(CA),并生成证书以允许在数据平面中进行安全的 mTLS 通信
-
Citadel 是 Istio 的核心安全组件,提供了自动生 成、分发、轮换与撤销密钥和证书功能
-
Citadel 一直监听 Kube- apiserver,以 Secret 的形式为每个服务都生成证书密钥,并在 Pod 创建时挂载到 Pod 上,代理容器使用这些文件来做服务身份认证,进而代 理两端服务实现双向 TLS 认证、通道加密、访问授权等安全功能。如图 所示,frontend 服 务对 forecast 服务的访问用到了HTTP 方式,通过配置即可对服务增加认证功能,双方的 Envoy 会建立双向认证的 TLS 通道,从而在服务间启用双向认证的 HTTPS
-
-
galley
-
Galley 是 istio 的配置验证、提取、处理和分发的组件。Galley 是提供配置管理的服务。实现原理是通过 k8s 提供的 ValidatingWebhook 对配置进行验证
-
Galley 使 Istio 可以与 Kubernetes 之外的其他环境一起工作,因为它可以将不同的配置数据转换为Istio 可以理解的通用格式
-
-
Ingressgateway
- Ingressgateway 就是入口处的 Gateway,从网格外访问网格内的服务就是通过这个 Gateway 进行的。istio-ingressgateway 是一个 Loadbalancer 类型的 Service,不同于其他服务组件只有一两个端 口,istio-ingressgateway 开放了一组端口,这些就是网格内服务的外部访问端口。如下图所示,网格入口网关 istio-ingressgateway 的负载和网格内的 Sidecar 是同样的执行流程,也和网格内的其他 Sidecar 一样从 Pilot 处接收流量规则并执行
-
Sidecar-injector
-
Sidecar-injector 是负责自动注入的组件,只要开启了自动注 入,在 Pod 创建时就会自动调用istio-sidecar-injector 向 Pod 中注入 Sidecar 容器
-
在 Kubernetes 环境下,根据自动注入配置,Kube-apiserver 在拦截到 Pod 创建的请求时,会调用自动注入服务 istio-sidecar-injector 生成 Sidecar 容器的描述并将其插入原 Pod 的定义中,这样,在创建的 Pod 内除了包括业务容器,还包括 Sidecar 容器,这个注入过程对用户透明
-
-
其他组件
- 除了以“istio”为前缀的 Istio 自有组件,在集群中一般还安装 Jaeger-agent、Jaegercollector、Jaeger-query、Kiali、Prometheus、Grafana、Tracing、Zipkin 等组件,这些组件提供了 Istio 的调用链、监控等功能,可以选择安装来完成完整的服务监控管理功能
-
3、安装istio
#官网下载地址
github.com/istio/istio/release/download
# 上传镜像并进行解压
[root@master istio]# ls
istio-1.10.1 istio-1.10.1-linux-amd64.tar.gz
[root@master istio-1.10.1]# export PATH=$PWD/bin:$PATH
# 上传istio需要的镜像到各个节点上面
[root@node1 istio]# ls
engress-proxyv2-1-10-1.tar.gz examples-bookinfo-ratings.tar.gz examples-bookinfo-reviews-v3.tar.gz
examples-bookinfo-details.tar.gz examples-bookinfo-reviews-v1.tar.gz httpbin.tar.gz
examples-bookinfo-productpage.tar.gz examples-bookinfo-reviews-v2.tar.gz istio-1-10-1.tar.gz
# docker load -i 一下
# istioctl install --set profile=demo -y
# 根据demo这个预配置进行安装,里面包含了istio所有核心组件
# 出现这个安装成功
[root@master /]# kubectl get pod -n istio-system
NAME READY STATUS RESTARTS AGE
istio-egressgateway-659cc7697b-qnqgm 1/1 Running 0 3m42s
istio-ingressgateway-569f64cdf8-7mfd6 1/1 Running 0 3m43s
istiod-85c958cd6-2zvmt 1/1 Running 0 3m49s
# istio空间下面的所有资源
[root@master networking]# kubectl get all -n istio-system
NAME READY STATUS RESTARTS AGE
pod/istio-egressgateway-659cc7697b-qnqgm 1/1 Running 1 6h49m
pod/istio-ingressgateway-569f64cdf8-7mfd6 1/1 Running 1 6h49m
pod/istiod-85c958cd6-2zvmt 1/1 Running 1 6h49m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/istio-egressgateway ClusterIP 10.100.54.125 <none> 80/TCP,443/TCP 6h49m
service/istio-ingressgateway LoadBalancer 10.97.188.208 <pending> 15021:31634/TCP,80:31223/TCP,443:31841/TCP,31400:31623/TCP,15443:31132/TCP 6h49m
service/istiod ClusterIP 10.97.147.13 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 6h49m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/istio-egressgateway 1/1 1 1 6h49m
deployment.apps/istio-ingressgateway 1/1 1 1 6h49m
deployment.apps/istiod 1/1 1 1 6h49m
NAME DESIRED CURRENT READY AGE
replicaset.apps/istio-egressgateway-659cc7697b 1 1 1 6h49m
replicaset.apps/istio-ingressgateway-569f64cdf8 1 1 1 6h49m
replicaset.apps/istiod-85c958cd6 1 1 1 6h49m
# 卸载istio集群
4、通过istio部署在线书店bookinfo
1、bookinfo介绍
-
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 个红色星形图标来显示评分信息。
-
-
要在 Istio 中运行这一应用,无需对应用自身做出任何改变。 只要简单的在 Istio 环境中对服务进行配置和运行,具体一点说就是把 Envoy sidecar 注入到每个服务之中
-
每一个pod里面都有一个sidecar
-
所有的微服务都和 Envoy sidecar 集成在一起,被集成服务所有的出入流量都被 envoy sidecar 所劫持,这样就为外部控制准备了所需的 Hook,然后就可以利用 Istio 控制平面为应用提供服务路由、遥测数据收集以及策略实施等功能
# 进入上传istio压缩包目录里面,里面有bookinfo的yaml文件
[root@master kube]# pwd
/root/istio/istio-1.10.1/samples/bookinfo/platform/kube
# istio默认自动注入sidecar,需要给名称空间打上一个标签
# 这样的话,创建一个pod的时候,就会多出一个sidecar的容器,用于istio管理的
kubectl label namespace default istio-injection=enabled
[root@master kube]# kubectl apply -f bookinfo.yaml
[root@master kube]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
details ClusterIP 10.96.58.191 <none> 9080/TCP 21m
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 6h25m
productpage ClusterIP 10.99.130.10 <none> 9080/TCP 21m
ratings ClusterIP 10.96.246.202 <none> 9080/TCP 21m
reviews ClusterIP 10.110.195.12 <none> 9080/TCP 21m
[root@master kube]# kubectl get pod
NAME READY STATUS RESTARTS AGE
busybox 1/1 Running 1 6h17m
details-v1-778b44bf55-9ljwh 2/2 Running 0 21m
productpage-v1-7897c765c8-g49z9 2/2 Running 0 21m
ratings-v1-669d4fc759-hkldb 2/2 Running 0 21m
reviews-v1-6b74b64f49-zbj5h 2/2 Running 0 21m
reviews-v2-6b86dcd4dc-hc4g7 2/2 Running 0 21m
reviews-v3-5fb4b7f649-69fh9 2/2 Running 0 21m
# 确认bookinfo是否在在运行
[root@master kube]# 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> 代表运行成功
# 为应用程序定义网关,
[root@master networking]# kubectl apply -f bookinfo-gateway.yaml
gateway.networking.istio.io/bookinfo-gateway created
virtualservice.networking.istio.io/bookinfo created
# 这个bookinfo的网关选择控制器就是istio名称空间下面的gateway
[root@master networking]# kubectl get gateways.networking.istio.io
NAME AGE
bookinfo-gateway 3s
# 查看虚拟服务,绑定了网关
[root@master networking]# kubectl get virtualservices.networking.istio.io
NAME GATEWAYS HOSTS AGE
bookinfo ["bookinfo-gateway"] ["*"] 17s
# 确定ingress ip和端口
[root@master networking]# kubectl get svc -n istio-system istio-ingressgateway
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway LoadBalancer 10.97.188.208 <pending> 15021:31634/TCP,80:31223/TCP,443:31841/TCP,31400:31623/TCP,15443:31132/TCP 12h
# pending状态,没有公网ip提供,所以的话,需要nodeport来进行访问网关
# 获取istio gateway地址和映射到主机的端口
[root@master networking]# kubectl get svc -n istio-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-egressgateway ClusterIP 10.100.54.125 <none> 80/TCP,443/TCP 12h
istio-ingressgateway LoadBalancer 10.97.188.208 <pending> 15021:31634/TCP,80:31223/TCP,443:31841/TCP,31400:31623/TCP,15443:31132/TCP 12h
istiod ClusterIP 10.97.147.13 <none> 15010/TCP,15012/TCP,443/TCP,15014/TCP 12h
[root@master networking]# export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
[root@master networking]# echo $INGRESS_PORT
31223
# 设置gateway url
[root@master networking]# INGRESS_HOST=192.168.200.10
[root@master networking]# export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
# 这样的话就设置成功了
[root@master networking]# echo $GATEWAY_URL
192.168.200.10:31223
# 可以通过这个来进行访问了
[root@master networking]# curl -s http://${GATEWAY_URL}/productpage | grep -o "<title>.*</title>"
<title>Simple Bookstore App</title>
# 浏览器也可以进行访问
http://192.168.200.10:31223/productpage
# 刷新可以,调用
# 访问的话,进行主机映射和添加一个externalip就能直接进行访问了
# master充当web提供的ip
# 添加一个externalIPs
[root@master networking]# kubectl edit svc -n istio-system istio-ingressgateway
[root@master networking]# kubectl get svc -n istio-system istio-ingressgateway
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway LoadBalancer 10.97.188.208 192.168.200.10 15021:31634/TCP,80:31223/TCP,443:31841/TCP,31400:31623/TCP,15443:31132/TCP 12h
# 修改windows的hosts文件
192.168.200.10 bookinfo
# 通过域名来进行访问
http://bookinfo/productpage
# 卸载bookinfo
[root@master kube]# sh cleanup.sh
namespace ? [default] y
NAMESPACE y not found.
using NAMESPACE=default
virtualservice.networking.istio.io "bookinfo" deleted
gateway.networking.istio.io "bookinfo-gateway" deleted
Application cleanup may take up to one minute
service "details" deleted
serviceaccount "bookinfo-details" deleted
deployment.apps "details-v1" deleted
service "ratings" deleted
serviceaccount "bookinfo-ratings" deleted
deployment.apps "ratings-v1" deleted
service "reviews" deleted
serviceaccount "bookinfo-reviews" deleted
deployment.apps "reviews-v1" deleted
deployment.apps "reviews-v2" deleted
deployment.apps "reviews-v3" deleted
service "productpage" deleted
serviceaccount "bookinfo-productpage" deleted
deployment.apps "productpage-v1" deleted
Application cleanup successful
# 这样的话,bookinfo的pod,svc,gateway全部都删除干净了
-
访问的流程
-
外部的请求到istio中的svc的ingress到istio中的pod
-
再到对应的gateway再到virtualservice中再到svc中的prod到对应的pod里面即可访问到
-
5、通过istio实现灰度发布(金丝雀发布)
1、什么是灰度发布
-
之前的deployment也实现了灰度发布,就是镜像的升级等操作
-
是指通过流量的比例,实现新老版本的逐步更替,比如服务a有2个版本的话,v1占比90,v2占比10,同时进行部署,最后将v1的占比逐渐减少,最后v1版本下线
-
就是控制访问的相同pod不同功能之间流量怎们进行访问,谁占比多谁占比少
-
特点
-
新老版本共存
-
可以实时根据反馈动态调整占比
-
理论上不存在服务宕机的情况
-
适合服务的平滑升级与动态更新
-
2、通过istio实现灰度发布
# 将需要的镜像进行上传到工作节点上面
# 注意这个是在默认的名称空间下面,所以的话,在其他的名称空间下面的话,需要设置自动注入,sidecar容器
# 编写deployment和svc
[root@master istio]# kubectl apply -f deployment.yaml
deployment.apps/appv1 created
deployment.apps/appv2 created
[root@master istio]# kubectl apply -f service.yaml
service/canary created
[root@master istio]# kubectl get pod
NAME READY STATUS RESTARTS AGE
appv1-6f7b58fd99-p6f6d 2/2 Running 0 11s
appv2-f78cb577-4bz7w 2/2 Running 0 11s
busybox 1/1 Running 3 23h
# svc代理的这个2个pod
[root@master istio]# kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
canary ClusterIP 10.109.124.165 <none> 80/TCP 8s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 23h
# 创建一个网关
[root@master istio]# 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]# cat virtual.yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: canary
spec:
hosts: # 主机列表
- "*"
gateways:
- canary-gateway # 访问网关的时候,会将请求发送到虚拟服务这里来
http:
- route:
- destination: # 找后端所对应的pod,权重不一样
host: canary.default.svc.cluster.local
subset: v1 # 这个v1就是后面的目标规则所对应的
weight: 90
- destination: # 2个虚拟服务
host: canary.default.svc.cluster.local
subset: v2
weight: 10
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule # 目标规则
metadata:
name: canary
spec: # 找的canary这个svc,请求转发到代理的2个pod上
host: canary.default.svc.cluster.local
subsets:
- name: v1
labels: # 对应的pod的标签
app: v1
- name: v2
labels:
app: v2
# 查看网关,虚拟服务,到目标规则
[root@master istio]# kubectl get gateways.networking.istio.io
NAME AGE
canary-gateway 14m
[root@master istio]# kubectl get virtualservices.networking.istio.io
NAME GATEWAYS HOSTS AGE
canary ["canary-gateway"] ["*"] 7m57s
# 关联的就是这个canary的完整的FQDN
[root@master istio]# kubectl get destinationrules.networking.istio.io
NAME HOST AGE
canary canary.default.svc.cluster.local 8m
# 进行访问,就是将流量进行占比分配
[root@master istio]# for i in `seq 1 100`; do curl 192.168.200.10:31223;done > 1.txt
# 内容的话就是10次出现v2,90次出现v1,当然有少许的误差,正常现象
6、istio核心资源解读
-
流程解读
-
用户向某个端口发出请求
-
负载均衡器监听端口,并将请求转发到集群中的某个节点上面,istio ingress gateway service会监听集群节点端口的请求
-
istio ingress gateway service 会将请求转发到istio ingress gateway pod 处理,IngresGateway pod通过gateway和virtualserivce 配置规则处理请求,其中gateway配置端口,协议,证书,virtualservice用来配置一些路由信息,找到请求对应处理的服务的app service
-
istio ingress gateway pod 将请求转发给app service
-
最后请求转发给所代理的deployment进行处理
-
非常的透彻
-
1、gateway资源
- 描述负载均衡器暴露的端口,协议,控制着Envoy代理在网络接口上的监听的方式
[root@master istio]# cat gateway.yaml
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
name: canary-gateway
spec:
selector:
istio: ingressgateway
servers:
- port:
number: 80 # 这个端口是ingress gateway svc监听的端口,将访问80的流量导入到虚拟服务中, 网关,为入口暴露80端口,入口网关代理
name: http
protocol: HTTP
hosts: # 配置的任何域名都可以进行访问
- "*"
# 就是访问域名的时候,将请求转发到这个负载均衡器上面了,然后转发到ingress pod 从而根据gateway和virtual service找到后端的svc,最后找到对应的pod
[root@master istio]# kubectl get svc -n istio-system istio-ingressgateway
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
istio-ingressgateway LoadBalancer 10.97.188.208 192.168.200.10 15021:31634/TCP,80:31223/TCP,443:31841/TCP,31400:31623/TCP,15443:31132/TCP 24h
2、virtualservice
- 是istio中核心的配置,表现为一个虚拟服务,将满足条件的流量转发到对应的服务后端,这个服务后端可以是一个服务,也可以是一个destionrule中定义的服务的子集,也就是一个svc关联了多个pod,可以这样编写
[root@master istio]# cat virtual.yaml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: canary
spec:
hosts: # 虚拟主机的名称,与gateway中的Host保持一致,如果是具体的话example.com,那么virtual service只会处理法子example的请求,* 表示可以处理发往任何主机的请求的
- "*"
gateways:
- canary-gateway # 选择的网关
http:
- route: # 路由规则
- destination: # 到的是canary服务的子集,也可以直接是后端服务
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
# 如果不是*的话,app1和app2的话,需要做域名解析
# 通过域名来进行访问
-
virtual service配置路由规则
- 路由规则的功能是:满足 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 # 带有jason的请求转发到v2自己
route:
- destination:
host: reviews
subset: v2
- route:
- destination:
host: reviews
subset: v3
1、多路由规则
-
路由规则是将特定流量子集路由到指定目标地址的工具。可以在流量端口、header 字段、URI 等内
容上设置匹配条件 -
路由的 destination 字段指定了匹配条件的流量的实际地址。与 virtual service 的主机不同,该
host 必须是存在于 istio 的服务注册表(如 kubernetes services,consul services 等)中的真实目的地或由 ServiceEntries 声明的 hosts,否则 Envoy 不知道应该将流量发送到哪里。它可以是一个带代理的网格服务或使用 service entry 添加的非网格服务。在 kubernetes 作为平台的情况下,host 表示名为kubernetes 的 service 名称 -
就是host使用的svc
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: bookinfo
spec:
hosts:
- "*" # 这个随便写,就是一个虚拟主机列表
gateways:
- bookinfo-gateway
http:
- match:
- uri:
exact: /productpage
- uri:
prefix: /static
- uri:
exact: /login
- uri:
exact: /logout
- uri:
prefix: /api/v1/products # 匹配到这些的话,就是转发到destions中
route:
- destination:
host: productpage # 短svc,必须是真实存在的
port:
number: 9080
# http://localhost/static
3、destinationrule
-
destination rule 是 istio 流量路由功能的重要组成部分。一个 virtual service 可以看作是如何将流量分发给特定的目的地,然后调用 destination rule 来配置分发到该目的地的流量。destination rule 在 virtual service 的路由规则之后起作用(即在 virtual service 的 math->route-destination 之后起作用,此时流量已经分发到真实的 service 上),应用于真实的目的地
-
可以使用 destination rule 来指定命名的服务子集,例如根据版本对服务的实例进行分组,然后通
过 virtual service 的路由规则中的服务子集将控制流量分发到不同服务的实例中 -
流量控制的流程
- Gateway->VirtaulService->TCP/HTTP Router->DestinationWeight->Subset:Port
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: canary
spec:
host: canary.default.svc.cluster.local # 访问的svc
subsets:
- name: v1
labels:
app: v1
- name: v2
labels:
app: v2
7、核心功能演示
1、断路器
-
创建弹性微服务应用程序的重要模式,断路器使用应用程序适应网络故障和延迟等
-
就是发送了一个请求一直进行了占用,这个时候直接返回一个失败的页面
-
k8s本身没有的,
[root@master httpbin]# kubectl apply -f httpbin.yaml
serviceaccount/httpbin created
service/httpbin created
deployment.apps/httpbin created
# 配置断路器
[root@master istio]# cat destination.yaml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: httpbin
spec:
host: httpbin
trafficPolicy:
connectionPool: # 连接池(TCP | HTTP)配置,例如:连接数、并发请求等
tcp:
maxConnections: 1 # 最大请求数,否则返回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%
# 创建一个客户端以将流量发送给 httpbin 服务。该客户端是一个简单的负载测试客户端,Fortio 可以控制连接数,并发数和 HTTP 调用延迟。使用此客户端来“跳闸”在 DestinationRule 中设置的断路器策略
# 上传镜像到node1上面
[root@master sample-client]# kubectl apply -f fortio-deploy.yaml
service/fortio created
deployment.apps/fortio-deploy created
[root@master sample-client]# kubectl get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
appv1 1/1 1 1 111m
appv2 1/1 1 1 111m
fortio-deploy 1/1 1 1 6s
httpbin 1/1 1 1 13m
[root@master sample-client]# kubectl get pod
NAME READY STATUS RESTARTS AGE
appv1-6f7b58fd99-p6f6d 2/2 Running 0 111m
appv2-f78cb577-4bz7w 2/2 Running 0 111m
busybox 1/1 Running 3 25h
fortio-deploy-648f745b7b-gqzz4 2/2 Running 0 10s
httpbin-74fb669cc6-8nkhd 2/2 Running 0 13m
# 发出请求
[root@master sample-client]# kubectl exec fortio-deploy-648f745b7b-gqzz4 -c fortio -- /usr/bin/fortio curl http://httpbin:8000/get
HTTP/1.1 200 OK
server: envoy
date: Mon, 07 Oct 2024 03:39:53 GMT
content-type: application/json
content-length: 594
access-control-allow-origin: *
access-control-allow-credentials: true
x-envoy-upstream-service-time: 24
{
"args": {},
"headers": {
"Host": "httpbin:8000",
"User-Agent": "fortio.org/fortio-1.11.3",
"X-B3-Parentspanid": "f44cbb0f0bb9e82f",
"X-B3-Sampled": "1",
"X-B3-Spanid": "8d69c22623b5b8d2",
"X-B3-Traceid": "135e947066e606baf44cbb0f0bb9e82f",
"X-Envoy-Attempt-Count": "1",
"X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/default/sa/httpbin;Hash=be7e5fe5cdd5ee45f88f698dadb31543edb6a858cf4aacb128c0b8364ed74500;Subject=\"\";URI=spiffe://cluster.local/ns/default/sa/default"
},
"origin": "127.0.0.6",
"url": "http://httpbin:8000/get"
}
# 在 DestinationRule 设置中,指定了 maxConnections: 1 和 http1MaxPendingRequests: 1。这些规则表明,如果超过一个以上的连接并发请求,则 istio-proxy 在为进一步的请求和连接打开路由时,应该会看到下面的情况 。 以两个并发连接(-c 2)和发送 20 个请求(-n 20)调用服务
# 触发断路器
# 2个并发连接
[root@master sample-client]# kubectl exec fortio-deploy-648f745b7b-gqzz4 -c fortio -- /usr/bin/fortio load -c 2 -qps 0 -n 20 -loglevel Warning http://httpbin:8000/get
# 全部都是错误的,每一次都是不一样的
Code 503 : 20 (100.0 %)
2、超时
-
在生产环境中经常会碰到由于调用方等待下游的响应过长,堆积大量的请求阻塞了自身服务,造成
雪崩的情况,通过通过超时处理来避免由于无限期等待造成的故障,进而增强服务的可用性,Istio 使用虚拟服务来优雅实现超时处理 -
下面例子模拟客户端调用 nginx,nginx 将请求转发给 tomcat。nginx 服务设置了超时时间为 2
秒,如果超出这个时间就不在等待,返回超时错误。tomcat 服务设置了响应时间延迟 10 秒,任何请求都需要等待 10 秒后才能返回。client 通过访问 nginx 服务去反向代理 tomcat 服务,由于 tomcat 服务需要 10 秒后才能返回,但 nginx 服务只等待 2 秒,所以客户端会提示超时错误
# 将busybox,nginx,tomcat上传到node1上面
#
[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:1.14-alpine
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
[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
# 设置虚拟服务
[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 #该设置说明每次调用 tomcat-svc 的 k8s service,都会延迟 10s 才会调用
route:
- destination:
host: tomcat-svc
# 查看虚拟服务
[root@master timeout]# kubectl get virtualservices.networking.istio.io
NAME GATEWAYS HOSTS AGE
canary ["canary-gateway"] ["*"] 3h20m
nginx-vs ["nginx-svc"] 3m43s
tomcat-vs ["tomcat-svc"] 3m43s
# 设置超时时间
# 进入到nginxpod里面去
/ # vi /etc/nginx/conf.d/default.conf
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: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
# 重启nginx
/ # nginx -s reload
2024/10/07 05:24:13 [notice] 16#16: signal process started
# 启动一个busybox,
/ # 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.02s # 2秒就超时
user 0m 0.00s
sys 0m 0.00s
# 流程应该是访问的时候,先从virtual service中到service再到后端对应的pod上面的
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 是模拟 tomcat 服务始终不可用,该设置说明每次调用 tomcat-svc 的 k8s service,100%都会返回错误状态码 503
abort:
percentage:
value: 100
httpStatus: 503
route:
- destination:
host: tomcat-svc
# 修改超时时间
[root@master timeout]# kubectl exec -ti nginx-tomcat-7f6496574c-tkg5m -- sh
Defaulting container name to nginx.
Use 'kubectl describe pod/nginx-tomcat-7f6496574c-tkg5m -n default' to see all of the containers in this pod.
/ # vi /etc/nginx/conf.d/default.conf
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: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
/ # nginx -s reload
2024/10/07 05:38:47 [notice] 17#17: signal process started
# busybox测试
[root@master timeout]# kubectl exec -ti busybox -- sh
Defaulting container name to busybox.
Use 'kubectl describe pod/busybox -n default' to see all of the containers in this pod.
/ # wget -q -O - http://nginx-svc
wget: server returned error: HTTP/1.1 503 Service Unavailable
# 查看日志
# 第一次请求失败,就会重试三次
[root@master ~]# kubectl logs -f nginx-tomcat-7f6496574c-tkg5m
127.0.0.6 - - [07/Oct/2024:05:39:22 +0000] "GET / HTTP/1.1" 503 18 "-" "Wget" "-"
127.0.0.6 - - [07/Oct/2024:05:39:22 +0000] "GET / HTTP/1.1" 503 18 "-" "Wget" "-"
127.0.0.6 - - [07/Oct/2024:05:39:22 +0000] "GET / HTTP/1.1" 503 18 "-" "Wget" "-"
127.0.0.6 - - [07/Oct/2024:05:39:23 +0000] "GET / HTTP/1.1" 503 18 "-" "Wget" "-"
127.0.0.6 - - [07/Oct/2024:05:40:38 +0000] "GET / HTTP/1.1" 503 18 "-" "Wget" "-"
127.0.0.6 - - [07/Oct/2024:05:40:38 +0000] "GET / HTTP/1.1" 503 18 "-" "Wget" "-"
127.0.0.6 - - [07/Oct/2024:05:40:38 +0000] "GET / HTTP/1.1" 503 18 "-" "Wget" "-"
127.0.0.6 - - [07/Oct/2024:05:40:38 +0000] "GET / HTTP/1.1" 503 18 "-" "Wget" "-"
8、图片理解和总结
-
ingress-gateway是入口网关
-
egress-gateway是出口网关
-
gateway中的host和vistual serviec中的hosts
-
gw是*的话,允许所有主机
-
以gw的hosts为主
-
1、简单的路由
2、高级路由
-
有的时候需要更加精细化的控制
-
istio允许我们使用传入的请求的一部分,并将其与定义的值相匹配,匹配传入的url前缀,从而实现访问
属性 | 描述 |
---|---|
uri | 将请求url与指定值相匹配 |
schema | 匹配请求的scema,http或者https |
method | 匹配请求的method,get,post |
authority | 匹配请求的authority头 |
headers | 匹配请求头,头信息必须是小写的,使用这个的话,其他属性将被忽略(上面的) |
上面的每个属性都可以使用这些方法进行匹配
-
精确匹配,exact: “value” 匹配精确的字符串
-
前缀匹配,prefix: “value” 只匹配前缀
-
正则匹配,regex: “value” 正则进行匹配
[root@k8s-master-node1 gaojiroute]# cat vs-dr.yml
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: test-vs
namespace: test-istio
spec:
gateways:
- gw
hosts:
- "*"
http:
- match:
- uri:
prefix: /v2 # 前缀是v2,就能被匹配到
route:
- destination:
host: "svc-test"
port:
number: 80
subset: v2
- route:
- destination:
host: "svc-test"
port:
number: 80
subset: v1
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
name: test-dr
namespace: test-istio
spec:
host: svc-test
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
3、基本命令
# 查看ingress pod中的规则
[root@k8s-master-node1 gaojiroute]# istioctl proxy-config -n istio-system route istio-ingressgateway-55d9fb9f-5q44k
NAME DOMAINS MATCH VIRTUAL SERVICE
http.8080 * /v2* test-vs.test-istio
http.8080 * /* test-vs.test-istio
* /stats/prometheus*
* /healthz/ready*
更多推荐





所有评论(0)