微服务-istio

什么是微服务?

定义

微服务是用于构建应用程序的架构风格,一个大的系统可由一个或者多个服务组成,微服务架构可将应用拆分成多个核心功能,每个功能都被称为一项服务,可以单独构建和部署,这意味着各项服务在工作和出现故障的时候不会相互影响。简单来说,微服务架构是把一个大的系统按照不同的业务单元分解成多个职责单一的小系统,并利用简单的方法使多个小系统相互协作,组合成一个大系统,各个小的系统是独立部署的,它们之间是松耦合的。

微服务-istio_第1张图片

优势

  • 1、可以让产品更快的上市
    由于开发周期缩短,微服务架构有助于实现更加敏捷的部署和更新。
  • 2、高度可扩展
    随着某些服务的不断扩展,你可以跨多个服务器和基础架构进行部署,充分满足自身需求。
  • 3、出色的弹性
    只要确保正确构建,这些独立的服务就不会彼此影响。这意味着,一个服务出现故障不会导致整个应用下线
  • 4、易于部署
    相对于传统的单体式应用,基于微服务的应用更加模块化且小巧,所以无需为它们的部署操心。
  • 5、易于访问
    由于大型应用被拆分成了多个小型服务,所以开发人员能够更加轻松地理解、更新和增强这些服务,从而缩短开发周期。
  • 6、更加开放
    由于使用了多语言 API,所以开发人员可以根据需要实现的功能,自由选用最适合的语言和技术。

发展进程

第一代微服务框架-SpringCloud

springCloud 来源于 SpringSource ,具有 Spring 社区的强大背景支持,还有 Netflix强大的后盾与技术输出。
为开发者提供了快速构建分布式系统的通用模型的工具,主要是针对 java 的开发框架。

第二代微服务框架-dubbo

Dubbo 是一个阿里巴巴开源出来的一个分布式服务框架,致力于提供高性能和透明化的 RPC 远程服务调用方案,以及 SOA 服务治理方案。其核心包含:
集群容错: 提供基于接口方法的透明远程过程调用,包括多协议支持,以及软负载均衡,失败容错,地址路由,动态配置等集群支持;
自动发现: 基于注册中心目录服务,使服务消费方能动态的查找服务提供方,使地址透明,使服务提供方可以平滑增加或减少机器。

第三代微服务框架-Service Mesh(服务网格)

istio 是开源的 Service Mesh(服务网格),Service Mesh 翻译成中文就是服务网格。
作为用于微服务服务聚合层管理的新锐项目,是 Google、IBM、Lyft(海外共享出行公司、Uber 劲敌) 首个共同联合开源的项目,提供了统一的连接,安全,管理和监控微服务的方案。

istio

概念

Istio 是一个与 Kubernetes 紧密结合的适用于云原生场景下用于服务治理的开放平台。
服务治理包括:
连接(Connect)、安全(Secure)、策略执行(Control)和可观察性(Observe)。

  • 1)连接:
    Istio 通过集中配置的流量规则控制服务间的流量和调用,实现负载均衡、熔断、故障注入、重试、重定向等服务治理功能。
  • 2)安全:
    Istio 提供透明的认证机制、通道加密、服务访问授权等安全能力,可增强服务访问的安全性。
  • 3)策略执行:
    Istio 通过可动态插拔、可扩展的策略实现访问控制、速率限制、配额管理、服务计费等能力。
  • 4)可观察性
    动态获取服务运行数据和输出,提供强大的调用链、监控和调用日志收集输出的能力。配合可视化工具,可方便运维人员了解服务的运行状态,发现并解决问题。
  • 5)策略与遥测:
    常常需要为服务设置一定的授权策略,比如限制流量的速率、设置黑名单等。另外,遥测(Telemetry)也是一个很重要的功能,可以通过分析收集到的指标(Metric)来监控系统的状态。在Istio 中,策略设定和遥测都是通过 Mixer 组件完成的(mixer 在 1.5+已经被废弃了,整合到 istiod 中了)

知识结构图

微服务-istio_第2张图片

istio架构图

微服务-istio_第3张图片

核心资源解读

1、Gateway

在 Kubernetes 环境中,Ingress controller 用于管理进入集群的流量。在 Istio 服务网格中 Istio Ingress Gateway 承担相应的角色,它使用新的配置模型(Gateway 和VirtualServices)完成流量管理的功能。
通过下图做一个总的描述:
微服务-istio_第4张图片
1、用户向某端口发出请求。
2、负载均衡器监听端口,并将请求转发到集群中的某个节点上。Istio Ingress Gateway Service会监听集群节点端口的请求。
3、Istio Ingress Gateway Service 将请求交给 Istio Ingress Gateway Pod 处理。IngressGateway Pod 通过 Gateway 和 VirtualService 配置规则处理请求。其中,Gateway 用来配置端口、协议和证书;VirtualService 用来配置一些路由信息(找到请求对应处理的服务 AppService)。
4、Istio Ingress Gateway Pod 将请求转给 App Service。
5、最终的请求会交给 App Service 关联的 App Deployment 处理。

2、VirtualService

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

3、DestinationRule

destination rule 是 istio 流量路由功能的重要组成部分。一个 virtual service 可以看作是如何将流量分发给特定的目的地,然后调用 destination rule 来配置分发到该目的地的流量。destinationrule 在 virtual service 的路由规则之后起作用(即在 virtual service 的 math->route-destination 之后起作用,此时流量已经分发到真实的 service 上),应用于真实的目的地。
可以使用 destination rule 来指定命名的服务子集,例如根据版本对服务的实例进行分组,然后通过 virtual service 的路由规则中的服务子集将控制流量分发到不同服务的实例中。

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

在k8s中安装istio

软件包准备

到官方网站下载安装istio的压缩包: https://github.com/istio/istio
将下载的软件包上传到k8s控制节点,手动解压。

tar zxvf istio-1.13.1.tar.gz

将解压包下/bin下的istioctl拷贝到/usr/bin

cd /root/istio-1.13.1/bin/
cp -ar istioctl /usr/bin/

安装istio

用到了如下镜像,可提前到dockerhub拉取

istio/examples-bookinfo-details-v1:1.15.0
istio/examples-bookinfo-productpage-v1:1.16.2
istio/examples-bookinfo-ratings-v1:1.15.0
istio/examples-bookinfo-reviews-v1:1.15.0
istio/examples-bookinfo-reviews-v2:1.15.0
istio/examples-bookinfo-reviews-v3:1.15.0
kennethreitz/httpbin:latest
istio/pilot:1.13.1
istio/proxyv2:1.13.1
 istioctl install --set profile=demo -y

看到如下,说明初始化完成:

✔ Istio core installed
✔ Istiod installed
✔ Egress gateways installed
✔ Ingress gateways installed
✔ Installation complete

验证istio是否部署成功

kubectl get pods -n istio-system

显示如下,说明部署成功
微服务-istio_第5张图片
istio会作为k8s api进行工作,在指定名称空间打上标签istio-injection=enabled后,后续在该名称空间下创建的pod会自动注入sidecar来进行流量控制。

以default名称空间举例:

kubectl label namespace default istio-injection=enabled

通过istio部署在线商店bookinfo

这是在安装istio时自带的一个demo,下面我们通过安装在线书店来理解istio的工作原理。

在线书店功能介绍

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

bookinfo微服务组成

  • 1、productpage 这个微服务会调用 details 和 reviews 两个微服务,用来生成页面;
  • 2、details 这个微服务中包含了书籍的信息;
  • 3、reviews 这个微服务中包含了书籍相关的评论,它还会调用 ratings 微服务;
  • 4、ratings 这个微服务中包含了由书籍评价组成的评级信息。

reviews微服务的三个版本

  • 1、v1 版本不会调用 ratings 服务;
  • 2、v2 版本会调用 ratings 服务,并使用 1 到 5 个黑色星形图标来显示评分信息;
  • 3、v3 版本会调用 ratings 服务,并使用 1 到 5 个红色星形图标来显示评分信息。

整体端到端框架

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

部署应用

要在 Istio 中运行这一应用,无需对应用自身做出任何改变。 只要简单的在 Istio 环境中对服务进行配置和运行,具体一点说就是把 Envoy sidecar 注入到每个 pod 之中。 最终的部署结果将如图所示:
微服务-istio_第7张图片
所有的微服务都和 Envoy sidecar 集成在一起,被集成服务所有的出入流量都被 envoy sidecar 所劫持,这样就为外部控制准备了所需的 Hook,然后就可以利用 Istio 控制平面为应用提供服务路由、遥测数据收集以及策略实施等功能。

启动应用服务

上面我们已经为 default 命名空间打上标签 istio-injection=enabled ,接下来只需要使用demo自带的yaml文件部署应用即可。

使用 kubectl 部署应用

cd istio-1.13.1
vim samples/bookinfo/platform/kube/bookinfo.yaml

修改名为productpage-v1的deployment用到的镜像为 1.16.2 版 ,如下图所示:
微服务-istio_第8张图片

kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml

上面的命令会启动全部的四个服务,其中也包括了 reviews 服务的三个版本(v1、v2 以及 v3)。

查看服务和pod状态

kubectl get svc

显示如下(nginx服务与本实验无关,可不存在):
微服务-istio_第9张图片

kubectl get pods

微服务-istio_第10张图片

为应用程序定义ingress网关

kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml
kubectl get gateway                                # 查看网关

在这里插入图片描述

访问应用、查看效果

获取端口

kubectl get svc istio-ingressgateway -n istio-system

在这里插入图片描述

如果 EXTERNAL-IP 值已设置,说明环境正在使用外部负载均衡,可以用其为 ingress gateway 提供服务。 如果 EXTERNAL-IP 值为(或持续显示), 说明环境没有提供外部负载均衡,无法使用 ingress gateway。在这种情况下,你可以使用服务的 NodePort(图中32273) 访问网关。

使用浏览器访问

用浏览器打开网址 http://$GATEWAY_URL/productpage,也就是192.168.1.63:32273/productpage 来浏览应用的 Web 页面。如果刷新几次应用的页面,就会看到productpage 页面中会随机展示 reviews 服务的不同版本的效果(红色、黑色的星形或者没有显示)。

删除bookinfo 服务

删除路由规则,并销毁应用的 Pod

sh samples/bookinfo/platform/kube/cleanup.sh

确认应用已经关停

kubectl get virtualservices                        # 无虚拟服务
kubectl get destinationrules                       # 无目标路由
kubectl get gateway                                # 无网关
kubectl get pods                                   # bookinfo相关pod已删

istio核心功能测试

断路器

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

在k8s集群中创建后端服务

[root@s1 ~]# cd istio-1.13.1
[root@s1 istio-1.13.1]# cat 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

上面yaml文件中定义了一个sa、service、deployment。

kubectl apply -f samples/httpbin/httpbin.yaml                      #应用该yaml文件

配置断路器

创建一个destination.yaml文件定义目标规则,内容如下:

apiVersion:  networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: httpbin
spec:
  host: httpbin                                          #定义对应后端服务名称
  trafficPolicy:
    connectionPool:                                      #连接池配置
      tcp:
        maxConnections: 1                                #tcp最大连接数1
      http:
        http1MaxPendingRequests: 1                       #http连接最大等待数1
        maxRequestsPerConnection: 1                      #连接池中每个连接最多处理1个请求后就关闭
    outlierDetection:                                    #异常检测配置
    # 下面配置表示1s内发生1次错误则触发服务熔断,驱逐100%的请求3m。
      consecutiveGatewayErrors: 1                        #连续错误数
      interval: 1s                                       #错误扫描间隔
      baseEjectionTime: 3m                               #基本驱逐时间 3 分钟
      maxEjectionPercent: 100                            #最大驱逐百分比 100%
kubectl apply -f destination.yaml                        #应用定义的规则

添加客户端访问httpbin服务

创建一个客户端以将流量发送给 httpbin 服务。该客户端是一个简单的负载测试客户端,Fortio 可以控制连接数,并发数和 HTTP 调用延迟。使用此客户端来“跳闸”在 DestinationRule 中设置的断路器策略。

[root@s1 istio-1.13.1]# kubectl apply -f samples/httpbin/sampleclient/fortio-deploy.yaml
[root@s1 istio-1.13.1]# kubectl get pods 

微服务-istio_第11张图片
通过 kubectl 执行下面的命令,使用 fortio 客户端工具调用 httpbin做一次请求:

# pod名称写自己实际观察到的
kubectl exec fortio-deploy-5f5f9cd9d8-x4kb9 -c fortio -- /usr/bin/fortio curl  http://httpbin:8000/get   

显示如下(状态码为200):
微服务-istio_第12张图片

触发断路器

我们刚才在 DestinationRule 设置中,指定了 maxConnections: 1 和 http1MaxPendingRequests: 1。这些规则表明,如果超过一个以上的连接并发请求,则 istio-proxy 在为进一步的请求和连接打开路由时,会触发断路器。
现以两个并发连接(-c 2)和发送 20 个请求(-n 20)调用服务,观察情况:

kubectl exec fortio-deploy-5f5f9cd9d8-x4kb9 -c fortio -- /usr/bin/fortio load -c 2 -qps 0 -n 20 -loglevel Warning  http://httpbin:8000/get

微服务-istio_第13张图片
可以看到部分请求被拦截,返回503。

超时

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

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

使用deployment部署tomcat、nginx

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
kubectl apply -f nginx-deployment.yaml
kubectl get pods

微服务-istio_第14张图片

部署nginx、tomcat的前端service

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
kubectl apply -f nginx-tomcat-svc.yaml  
kubectl get svc

微服务-istio_第15张图片

部署虚拟服务

yaml文件内容如下:

---
# nginx的虚拟服务
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: nginx-vs                                                      #虚拟服务名称
spec:
  hosts:
  - nginx-svc                                                         #虚拟主机名称
  http:
  - route:                                                            #定义路由规则                                          
    - destination: 
        host: nginx-svc                                               #指向nginx service                                        
    timeout: 2s                                                       #调用超时时间2s
---
# tomcat的虚拟服务
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: tomcat-vs
spec:
  hosts:
  - tomcat-svc
  http:
  - fault:                                                             #定义故障注入策略
      delay:
        percentage:
          value: 100
        fixedDelay: 10s                                                #延时10s响应
    route:
    - destination:
        host: tomcat-svc 

修改nginx配置,使其反向代理到tomcat

进入nginx容器

kubectl exec -it nginx-tomcat-7649c6ff85-bw6st -- sh

修改nginx配置

vi /etc/nginx/conf.d/default.conf

修改完成后如下图所示:
微服务-istio_第16张图片
检查配置文件是否有语法错误,如没有则重载nginx。

nginx -t
nginx -s reload

验证超时

运行一个busybox,访问nginx服务。

 kubectl run busybox --image busybox:1.28 --restart=Never --rm -it busybox -- sh
 time wget -q -O - http://nginx-svc

微服务-istio_第17张图片
每隔 2 秒,由于 nginx 服务的超时时间到了而 tomcat 未有响应,则提示返回超时错误。

再访问tomcat服务,验证故障注入效果。

time wget -q -O - http://tomcat-svc

微服务-istio_第18张图片
执行10s后返回结果。

故障注入和重试

Istio 重试机制就是如果调用服务失败,Envoy 代理尝试连接服务的最大次数。而默认情况下,Envoy 代理在失败后并不会尝试重新连接服务,除非我们启动 Istio 重试机制。
下面例子模拟客户端调用 nginx,nginx 将请求转发给 tomcat。tomcat 通过故障注入而中止对外服务,nginx 设置如果访问 tomcat 失败则会重试 3 次。

重新定义虚拟服务

删除原定义的nginx、tomcat的虚拟服务

kubectl delete -f virtual-tomcat.yaml

重新定义虚拟服务,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                                                #每个重试的超时时间
     #该设置说明调用 nginx-svc 的 k8s service,在初始调用失败后最多重试 3 次来连接到服务子集,每个重试都有 2 秒的超时。
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: tomcat-vs
spec:
  hosts:
  - tomcat-svc
  http:
  - fault:
      abort:                                                            #模拟服务不可用
        percentage:                             
          value: 100                      
        httpStatus: 503                                                 #100%返回503
    route:
    - destination:
        host: tomcat-svc
kubectl apply -f virtual-attempt.yaml                                   #应用虚拟服务

验证重试效果

运行一个busybox对nginx服务做请求

kubectl run -it busybox --image busybox:1.28 --restart=Never --rm -- sh 
wget -q -O - http://nginx-svc

查看nginx pod里istio-proxy的日志信息

kubectl logs nginx-tomcat-7649c6ff85-bw6st -c istio-proxy

微服务-istio_第19张图片
由上图可知,重试设置生效。

你可能感兴趣的:(isito)