k8s istio学习

1、istio是什么

连接,安全加固,控制和观察服务的开放平台,本身就是一个开源平台,服务对应的是微服务,也就是单个应用

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

  • 安全加固 自动为服务之间的调用提供认证、授权和加密

  • 控制 应用用户定义的 policy,保证资源在消费者中公平分配

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

  • 降低了部署的复杂性

  1. 微服务分层解耦

    1. 服务发现

      • 服务注册,就是部署了一个tomcat服务,ip和端口都会被注册中心里面所注册

      • 服务发现,就是从注册中心上获取服务的信息

      img

    2. 负载均衡

      • 将前台的请求分发到后台的多个服务器上面,避免都发送到了一个服务器上面,减小压力
    3. 故障恢复

      • 出现故障具备恢复的能力,pod出现了问题,通过控制器,将其创建出来
    4. 服务度量

    5. 灰度发布

      • 也叫做金丝雀发布,就是更新镜像,先升级一个镜像的pod,测试这个pod是否有情况,没有问题的话,就升级其他的pod的镜像
  2. istio的特性

    1. 断路器(服务熔断)

      • 就是a服务一直调用b服务,但是b服务出现了问题的话,就会一直调用,占用资源

      • istio解决了这问题,出现了问题,不会进行调用了

      • 当有10个请求中,有10%失败了,服务熔断就会打开,再次请求的时候,直接返回失败,过了一定的时间后,重新检测该触发条件,判断是否打开熔断器

      • 服务降级

        • 请求量过多的时候,不返回一个错误的页面,返回一个静态页面写好的信息,提升用户体验
    2. 超时

      • 避免调用方等待响应的时间过长,堆积大量的请求阻塞自身服务,通过超时来处理避免由于等待造成的故障
    3. 重试

      • 如果调用服务失败的话,会尝试连接服务的最大次数,默认情况下,失败后并不会尝试连接服务
    4. 多路由规则

2、istio架构

img

  1. 数据平面

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

    • 这个代理就是进来和出去的流量都要经过的

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

  2. 控制平面

    • 负责管理和配置代理来路由流量

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

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

  3. istio工作流程
    img

    1. 自动注入

      • 在创建应用程序时自动注入 Sidecar 代理 Envoy 程序。在 Kubernetes 中创建 Pod 时,Kube-apiserver 调用控制面组件的 Sidecar-Injector 服务,自动修改应用程序的描述信息并注入Sidecar。在真正创建 Pod 时,在创建业务容器的 Pod 中同时创建 Sidecar 容器,也就是创建了2个容器
    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 上执行
  4. istio组件详解

    1. Pilot

      • 是主要的控制组件,下发指令控制客户端,在整个系统中,polit完成一下任务

        • 从kubernetes或者其他注册中心获取服务信息,完成服务发现过程

        • 读取istio各项控制配置,在进行转发之后,并将其发送给数据面进行实施
          img

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

      • Pilot 为 Envoy 提供服务发现

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

      • 生成 envoy 配置

      • 启动 envoy,实际上是piloy-agent启动的

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

    2. envoy
      img

      • 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)

    3. citadel

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

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

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

      img

    4. galley

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

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

    5. Ingressgateway

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

      img

    6. Sidecar-injector

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

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

    7. 其他组件

      • 除了以“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 个红色星形图标来显示评分信息。

img

  • 要在 Istio 中运行这一应用,无需对应用自身做出任何改变。 只要简单的在 Istio 环境中对服务进行配置和运行,具体一点说就是把 Envoy sidecar 注入到每个服务之中

  • 每一个pod里面都有一个sidecar

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

img

# 进入上传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核心资源解读

img

  • 流程解读

    • 用户向某个端口发出请求

    • 负载均衡器监听端口,并将请求转发到集群中的某个节点上面,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资源
[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的流量导入到虚拟服务中, 网关
      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" "-"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值