istio功能简介

Istio是一个开源的服务网格平台,用于管理和连接容器化应用程序的微服务。它提供了一系列功能,包括:

  1. 流量管理:Istio可以控制和路由应用程序的流量,实现灰度发布、A/B测试、故障恢复等功能。

  2. 安全性:Istio提供了强大的安全功能,包括身份认证、授权、访问控制和加密通信,以保护应用程序的安全性。

  3. 观察性:Istio可以收集和展示应用程序的运行时数据,如请求流量、延迟、错误率等,帮助开发人员进行故障排查和性能优化。

  4. 策略和配额:Istio允许定义和实施各种策略和配额,如限制每秒请求数、设置访问控制规则等。

  5. 故障注入和测试:Istio提供了故障注入的功能,可以模拟网络延迟、错误响应等情况,以测试应用程序的容错能力。

总之,Istio可以帮助开发人员更好地管理和监控微服务架构,提供更好的安全性、可观察性和流量控制能力。

下面使用官方文档的例子做验证,所有资源文件部署在defaultnamespace下

模拟部分流量管理功能

  1. 给命名空间添加标签
# 指示 Istio 在部署应用的时候,自动注入 Envoy 边车代理
$ kubectl label namespace default istio-injection=enabled
  1. 部署istio gateway,作为流量入口,一个k8s集群只需要一个网关

bookinfo-gateway.yaml

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: bookinfo-gateway
spec:
  # The selector matches the ingress gateway pod labels.
  # If you installed Istio using Helm following the standard documentation, this would be "istio=ingress"
  selector:
    istio: ingressgateway # use istio default controller
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    #如果配置具体域名,需要通过域名访问,域名可在本机hosts配置,如果配置*则可用ip或域名访问
    hosts:
    - "*"
---
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
    route:
    - destination:
        host: productpage
        port:
          number: 9080

$ kubectl apply -f bookinfo-gateway.yaml
  1. 部署bookinfo应用

bookinfo.yaml

# Copyright Istio Authors
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.

##################################################################################################
# This file defines the services, service accounts, and deployments for the Bookinfo sample.
#
# To apply all 4 Bookinfo services, their corresponding service accounts, and deployments:
#
#   kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
#
# Alternatively, you can deploy any resource separately:
#
#   kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml -l service=reviews # reviews Service
#   kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml -l account=reviews # reviews ServiceAccount
#   kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml -l app=reviews,version=v3 # reviews-v3 Deployment
##################################################################################################

##################################################################################################
# Details service
##################################################################################################
apiVersion: v1
kind: Service
metadata:
  name: details
  labels:
    app: details
    service: details
spec:
  ports:
  - port: 9080
    name: http
  selector:
    app: details
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: bookinfo-details
  labels:
    account: details
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: details-v1
  labels:
    app: details
    version: v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: details
      version: v1
  template:
    metadata:
      labels:
        app: details
        version: v1
    spec:
      serviceAccountName: bookinfo-details
      containers:
      - name: details
        image: docker.io/istio/examples-bookinfo-details-v1:1.18.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9080
---
##################################################################################################
# Ratings service
##################################################################################################
apiVersion: v1
kind: Service
metadata:
  name: ratings
  labels:
    app: ratings
    service: ratings
spec:
  ports:
  - port: 9080
    name: http
  selector:
    app: ratings
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: bookinfo-ratings
  labels:
    account: ratings
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ratings-v1
  labels:
    app: ratings
    version: v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: ratings
      version: v1
  template:
    metadata:
      labels:
        app: ratings
        version: v1
    spec:
      serviceAccountName: bookinfo-ratings
      containers:
      - name: ratings
        image: docker.io/istio/examples-bookinfo-ratings-v1:1.18.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9080
---
##################################################################################################
# Reviews service
##################################################################################################
apiVersion: v1
kind: Service
metadata:
  name: reviews
  labels:
    app: reviews
    service: reviews
spec:
  ports:
  - port: 9080
    name: http
  selector:
    app: reviews
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: bookinfo-reviews
  labels:
    account: reviews
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: reviews-v1
  labels:
    app: reviews
    version: v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: reviews
      version: v1
  template:
    metadata:
      labels:
        app: reviews
        version: v1
    spec:
      serviceAccountName: bookinfo-reviews
      containers:
      - name: reviews
        image: docker.io/istio/examples-bookinfo-reviews-v1:1.18.0
        imagePullPolicy: IfNotPresent
        env:
        - name: LOG_DIR
          value: "/tmp/logs"
        ports:
        - containerPort: 9080
        volumeMounts:
        - name: tmp
          mountPath: /tmp
        - name: wlp-output
          mountPath: /opt/ibm/wlp/output
      volumes:
      - name: wlp-output
        emptyDir: {}
      - name: tmp
        emptyDir: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: reviews-v2
  labels:
    app: reviews
    version: v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: reviews
      version: v2
  template:
    metadata:
      labels:
        app: reviews
        version: v2
    spec:
      serviceAccountName: bookinfo-reviews
      containers:
      - name: reviews
        image: docker.io/istio/examples-bookinfo-reviews-v2:1.18.0
        imagePullPolicy: IfNotPresent
        env:
        - name: LOG_DIR
          value: "/tmp/logs"
        ports:
        - containerPort: 9080
        volumeMounts:
        - name: tmp
          mountPath: /tmp
        - name: wlp-output
          mountPath: /opt/ibm/wlp/output
      volumes:
      - name: wlp-output
        emptyDir: {}
      - name: tmp
        emptyDir: {}
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: reviews-v3
  labels:
    app: reviews
    version: v3
spec:
  replicas: 1
  selector:
    matchLabels:
      app: reviews
      version: v3
  template:
    metadata:
      labels:
        app: reviews
        version: v3
    spec:
      serviceAccountName: bookinfo-reviews
      containers:
      - name: reviews
        image: docker.io/istio/examples-bookinfo-reviews-v3:1.18.0
        imagePullPolicy: IfNotPresent
        env:
        - name: LOG_DIR
          value: "/tmp/logs"
        ports:
        - containerPort: 9080
        volumeMounts:
        - name: tmp
          mountPath: /tmp
        - name: wlp-output
          mountPath: /opt/ibm/wlp/output
      volumes:
      - name: wlp-output
        emptyDir: {}
      - name: tmp
        emptyDir: {}
---
##################################################################################################
# Productpage services
##################################################################################################
apiVersion: v1
kind: Service
metadata:
  name: productpage
  labels:
    app: productpage
    service: productpage
spec:
  ports:
  - port: 9080
    name: http
  selector:
    app: productpage
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: bookinfo-productpage
  labels:
    account: productpage
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: productpage-v1
  labels:
    app: productpage
    version: v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: productpage
      version: v1
  template:
    metadata:
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "9080"
        prometheus.io/path: "/metrics"
      labels:
        app: productpage
        version: v1
    spec:
      serviceAccountName: bookinfo-productpage
      containers:
      - name: productpage
        image: docker.io/istio/examples-bookinfo-productpage-v1:1.18.0
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 9080
        volumeMounts:
        - name: tmp
          mountPath: /tmp
      volumes:
      - name: tmp
        emptyDir: {}
---
$ kubectl apply -f bookinfo.yaml
$ kubectl get pods
iShot_2023-09-14_13.47.39.png

一个productpage前端和detailsratingsreviews后端接口服务,reviews部署了3个版本

我们现在没有创建任何目标规则,一个请求从gateway-->k8s service-->POD,reviews三个版本labels.app相同,
默认每次请求productpage服务会轮训调用三个版本的reviews

# 设置 EXTERNAL-IP 的值之后, 您的环境就有了一个外部的负载均衡器,
# 可以将其用作入站网关。 但如果 EXTERNAL-IP 的值为 <none> (或者一直是 <pending> 状态), 
# 则您的环境则没有提供可作为入站流量网关的外部负载均衡器。 
# 在这个情况下,您还可以用服务(Service)的节点端口访问网关。
$ kubectl get svc istio-ingressgateway -n istio-system
# 查看Service IP和应用端口
$ kubectl get svc

我这里有EXTERNAL-IP我就用http://${EXTERNAL-IP}/productpage在浏览器访问,
否则就用http://${CLUSTER-IP}:9080/productpage (需要再集群任意一台机器上访问)

iShot_2023-09-14_14.11.03.png

红色框显示当前提供服务的是哪个版本的reviews,多次刷新发现会在 v1 v2 v3之间变化

  1. 设置每个版本的子集subsets,可以为不同版本指定不同的负载均衡算法

distination-rule-reviews.yaml

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: reviews
spec:
  host: reviews
  trafficPolicy:
    loadBalancer:
      simple: RANDOM
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
#    trafficPolicy:
#      loadBalancer:
#        simple: ROUND_ROBIN  
  - name: v3
    labels:
      version: v3
$ kubectl apply -f distination-rule-reviews.yaml
  1. 测试-reviews v2和v3版本各50%权重

virtual-service-reviews-v2-v3.yaml

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
    - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v2
      weight: 50
    - destination:
        host: reviews
        subset: v3
      weight: 50
$ kubectl apply -f virtual-service-reviews-v2-v3.yaml

浏览器多次刷新,发现右下角reviews版本在v2 v3之间切换,总体上权重维持1:1

  1. 测试-reviews v1和v2版本各权重90:10权重

virtual-service-reviews-90-10.yaml

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
    - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v1
      weight: 90
    - destination:
        host: reviews
        subset: v2
      weight: 10
$ kubectl apply -f virtual-service-reviews-90-10.yaml

浏览器多次刷新,发现右下角reviews版本在v1 v2之间切换,总体上权重维持9:1

  1. 测试-把权重全部给到v3

virtual-service-reviews-v3.yaml

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
    - reviews
  http:
  - route:
    - destination:
        host: reviews
        subset: v3
$ kubectl apply -f virtual-service-reviews-v3.yaml

浏览器多次刷新,发现右下角reviews版本保持v3;经过上面5、6、7三个步骤我们就明白了如何控制灰度发布

  1. 测试-带有特征的流量转发

有时为了验证新版本需要把带有指定特征的流量导入到新版本,无特征的流量继续访问老版本

virtual-service-reviews-jason-v2-v3.yaml

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
$ kubectl apply -f virtual-service-reviews-jason-v2-v3.yaml

如果请求头带有end-user:jason,就把流量转到v2版本,否则流量转到v3,这里的exact代表全匹配模式,
还可以指定prefix、正则表达式等支持的匹配模式;此时我们多次刷新页面发现都是v3版本,我们在右上角登录
jason用户(密码可不填),再次刷新页面发现都是v2版本;通过查看productpage服务日志发现请求reviews
接口带了end-user:jason请求头

iShot_2023-09-14_14.48.02.png

Istio中的"match"用于定义流量管理规则,以便对特定的请求进行匹配和操作。以下是一些常见的匹配模式:

  1. URI匹配:可以基于请求的URI路径进行匹配,例如/api/v1/users/*

  2. 方法匹配:可以基于HTTP方法(GET、POST等)进行匹配。

  3. 主机匹配:可以基于请求的主机名进行匹配,例如example.com

  4. 标头匹配:可以基于请求的标头进行匹配,例如x-request-id=123456

  5. 标签匹配:可以基于Kubernetes标签进行匹配,例如version=v1

  6. 端口匹配:可以基于请求的端口号进行匹配。

这些匹配模式可以组合使用,以创建更复杂的匹配规则。例如,可以使用URI匹配和方法匹配来仅匹配特定路径和HTTP方法的请求。Istio的匹配规则非常灵活,可以根据具体的需求进行定制。

应用部署方案