Istio三之VirtualService、Gateway、DestinationRule配置使用

前面介绍了Istio如何完成流量劫持,此篇博客将介绍Istio中如何配置VirtualService、Gateway、DestinationRule来完成流量管理。还是先从理论开始,先看看VirtualService、Gateway、DestinationRule的概念。
VirtualService:在Istio服务网格中定义路由规则
DestinationRule:在VirtualService路由生效后,配置应用与请求的策略集
ServiceEntry:通常用于在Istio服务网格之外启用对服务的请求
Gateway:为HTTP/TCP流量配置负载均衡器,最常见的是在网格的边缘的操作,以启用应用程序的入口流量。Istio中gateway分为IngressGateway和EgressGateway,分别管理进来的流量和出去的流量。下面是对上面3个对象配置中的各个字段含义解析。

VirtualService字段名称 字段说明
spec.hosts 定义路由规则关联一组的 hosts,可以是带有通配符的 DNS 名称或者 IP 地址(IP 地址仅能应用于来源流量为边缘代理网关)。该字段能应用于 HTTP 和 TCP 流量。在 Kubernetes 环境中,可以使用 service 的名称作为缩写,Istio 会按照 VirtualService所在 namespace 补齐缩写,例如在 default namespace 的 VirtualService 包含 host 缩写 reviews 会被补齐为 reviews.default.svc.cluster.local。为避免误配置,推荐填写 host 全称
spec.gateways 定义应用路由规则的来源流量,可以是一个或多个网关,或网格内部的 sidecar,指定方式为 /,保留字段 mesh 表示网格内部所有的 sidecar,当该参数缺省时,会默认填写 mesh,即该路由规则的来源流量为网格内部所有 sidecar
spec.http 定义一组有序的(优先匹配靠前的路由规则)应用于 HTTP 流量的路由规则,HTTP 路由规则会应用于网格内部的 service 端口命名为 http-, http2-, grpc- 开头的流量以及来自 gateway 的协议为 HTTP, HTTP2, GRPC, TLS-Terminated-HTTPS 的流量
spec.http.match 定义路由的匹配规则列表,单个匹配规则项内所有条件是且关系,列表中多个匹配规则之间为或关系
spec.http.route 定义路由转发目的地列表,一条 HTTP 路由可以是重定向或转发(默认),转发的目的地可以是一个或多个服务(服务版本)。同时也可以配置权重、header 操作等行为
spec.http.redirect 定义路由重定向,一条 HTTP 路由可以是重定向或转发(默认),如规则中指定了 passthrough 选项,route、redirect 均会被忽略。可将 HTTP 301 重定向到另外的 URL 或 Authority
spec.http.rewrite 定义重写 HTTP URL 或 Authority headers,不能与重定向同时配置,重写操作会在转发前执行
spec.http.timeout 定义 HTTP 请求的超时时间
spec.http.retries 定义 HTTP 请求的重试策略
spec.http.fault 定义 HTTP 流量的故障注入策略,开启时超时和重试策略不会开启
spec.http.mirror 定义将 HTTP 流量复制到另一个指定的目的端,被复制的流量按照“best effort”原则,sidecar/网关不会等待复制流量的响应结果就会从源目的端返回响应。镜像流量的目的服务端会产生监控指标。
spec.http.mirrorPercent 定义流量镜像的复制百分比,缺省时复制100%的流量。最大值为100
spec.http.corsPolicy 定义 CORS 策略(跨域资源共享,Cross-Origin Resource Sharing,CORS),更多关于 CORS 的介绍请参见 CORS,关于 Istio CORS 策略配置语法请参见 CorsPolicy
spec.http.headers 定义 header 操作规则,包括 request 和 response header 的更新,增加,移除操作
spec.tcp 定义一组有序的(优先匹配靠前的路由规则)应用于 TCP 流量的路由规则,该路由规则会应用于任何非 HTTP 和 TLS 的端口
spec.tcp.match 定义 TCP 流量路由的匹配规则列表,单个匹配规则项内所有条件是且关系,列表中多个匹配规则之间为或关系
spec.tcp.route 定义 TCP 连接转发的目的端
spec.tls 定义一组有序的(优先匹配靠前的路由规则)应用于未终止的 TLS 或 HTTPS 流量的路由规则,该路由规则会应用于网格内部的 service 端口命名为 https-,tls- 开头的流量,来自 gateway 的端口协议为 HTTPS, TLS 的未终止加密流量,Service Entry 使用 HTTPS, TLS 协议的端口。当 https-, tls- 端口未关联 VirtualService 规则时将会被视为 TCP 流量
spec.tls.match 定义 TLS 流量路由的匹配规则列表,单个匹配规则项内所有条件是且关系,列表中多个匹配规则之间为或关系
spec.tls.route 定义连接转发的目的端

DestinationRule字段名称 字段含义
spec.host 关联 DestinationRule 配置的服务名称,可以是自动发现的服务(例如 Kubernetes service name),或通过 ServiceEntry 声明的 hosts。如填写的服务名无法在上述源中找到,则该 DestinationRule 中定义的规则无效
spec.subsets 定义服务的版本(subsets),版本可通过标签键值对匹配匹配服务中的endpoints。可以在 subsets 级覆盖流量策略配置
spec.trafficPolicy 定义流量策略,包括负载均衡、连接池、健康检查、TLS 策略
spec.trafficPolicy.loadBalancer 配置负载均衡算法,可配置:简单负载均衡算法(round robin, least conn, random...),一致性哈希(会话保持,支持按 header name,cookie,IP,query parameter 哈希),地域感知负载均衡算法
spec.trafficPolicy.connectionPool 配置与上游服务的连接量,可设置 TCP/HTTP 的连接池
spec.trafficPolicy.outlierDetection 配置从负载均衡池中驱逐不健康的 hosts
spec.trafficPolicy.tls 连接上游服务的 client 端 TLS 相关配置,与 PeerAuthentication 策略(server 端 TLS 模式配置)配合使用
spec.trafficPolicy.portLevelSettings 配置端口级别的流量策略,端口级别的流量策略会覆盖服务 / subsets 级别的流量策略配置
GateWay字段名称 字段含义
metadata.name Gateway 名称
metadata.namespace Gateway 命名空间
spec.selector Gateway 使用填写的标签键值对匹配配置下发的边缘代理网关实例
spec.servers.port.number 端口
spec.servers.port.protocol 通信协议,支持:HTTP, HTTPS, GRPC, HTTP2, MONGO, TCP, TLS,请注意同一网关同一端口的协议配置需要保持一致。
spec.servers.port.name 端口名称
spec.severs.hosts 域名,支持通配符 *
spec.servers.tls.httpsRedirect 值为 true 时,边缘代理网关会对所有 http 请求返回 301 重定向,要求客户端发起 https 请求
spec.servers.tls.mode 配置当前端口的 TLS 安全认证模式,如需要开启当前端口的安全认证则需要填写。支持:PASSTHROUGH, SIMPLE, MUTUAL, AUTO_PASSTHROUGH, ISTIO_MUTUAL
spec.servers.tls.credentialName 配置发现 TLS 证书密钥的 secret 的名称
spec.servers.tls.serverCertificate 设置端口的 TLS 证书密钥通过 file mount 形式(不推荐,推荐采用填写 credentialName 字段加载证书私钥)挂载时需要填写的证书路径字段,Istio 默认使用网关所在命名空间下 istio-ingressgateway-certs secret 加载证书至路径 /etc/istio/ingressgateway-certs
spec.servers.tls.privateKey 设置端口的 TLS 证书密钥通过 file mount 形式(不推荐,推荐采用填写 credentialName 字段加载证书私钥)挂载时需要填写的私钥路径字段,Istio 默认使用网关所在命名空间下 istio-ingressgateway-certs secret 加载私钥至路径 /etc/istio/ingressgateway-certs
spec.servers.tls.caCertificates 设置端口的 TLS 证书密钥通过 file mount 形式(不推荐,推荐采用填写 credentialName 字段加载证书私钥)挂载时需要填写的跟证书路径字段,Istio 默认使用网关所在命名空间下 istio-ingressgateway-ca-certs 加载根证书至路径 /etc/istio/ingressgateway-ca-certs,双向认证时需要配置根证书

接着通过实际例子演示如果通过配置VirtualService等完成流量管理。

案例一:部署后端服务simple,配置istio的VirtualService和Gateway,gateway网关添加在istio-ingress pod上,gateway网关expose出80端口。VirtualService将simple网关、80端口发送的,且请求的hosts是“simple.cncamp.io”的请求路由到后端务"simple.simple.svc.cluster.local"上。之前在CoreDNS章节介绍过,这个域名地址实际就是部署的后端simple服务的service地址。

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: simple
spec:
  gateways:
    - simple
  hosts:
    - simple.cncamp.io
  http:
    - match:
        - port: 80
      route:
        - destination:
            host: simple.simple.svc.cluster.local
            port:
              number: 80
---
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: simple
spec:
  selector:
    istio: ingressgateway
  servers:
    - hosts:
        - simple.cncamp.io
      port:
        name: http-simple
        number: 80
        protocol: HTTP
apiVersion: apps/v1
kind: Deployment
metadata:
  name: simple
spec:
  replicas: 1
  selector:
    matchLabels:
      app: simple
  template:
    metadata:
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "80"
      labels:
        app: simple
    spec:
      containers:
        - name: simple
          imagePullPolicy: Always
          image: cncamp/httpserver:v1.0-metrics
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: simple
spec:
  ports:
    - name: http
      port: 80
      protocol: TCP
      targetPort: 80
  selector:
    app: simple

上面的simple 服务的部署配置文件,通过配置文件创建相关对象。

kubectl create ns simple
kubectl create -f simple.yaml -n simple
kubectl create -f istio-specs.yaml -n simple

查看istio-ingress的service的IP地址,通过istio-ingress的IP地址发送请求。

Istio三之VirtualService、Gateway、DestinationRule配置使用_第1张图片 可以看到请求返回了响应,说明整个路由转发成功发送到了后端服务。

Istio三之VirtualService、Gateway、DestinationRule配置使用_第2张图片

案例二:再部署一个服务nginx,配置VirtualService根据不同URL转发到不同的后端服务的路有规则,VirtulaService中还设置了rewrite字段。Gateway与上面相同,还是expose出80端口即可。

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: simple
spec:
  gateways:
    - simple
  hosts:
    - simple.cncamp.io
  http:
  - match:
    - uri:
        exact: "/simple/hello"
    rewrite:
      uri: "/hello"
    route:
      - destination:
          host: simple.simple.svc.cluster.local
          port:
            number: 80
  - match:
    - uri:
        prefix: "/nginx"
    rewrite:
      uri: "/"
    route:
      - destination:
          host: nginx.simple.svc.cluster.local
          port:
            number: 80

 nginx应用部署的yaml文件内容如下所示

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx
---
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  ports:
    - name: http
      port: 80
      protocol: TCP
      targetPort: 80
  selector:
    app: nginx

执行下面的命令启动pod以及访问应用。

kubectl apply -f nginx.yaml -n simple
kubectl apply -f istio-specs.yaml -n simple
curl -H "Host: simple.cncamp.io" $INGRESS_IP/simple/hello
curl -H "Host: simple.cncamp.io" $INGRESS_IP/nginx

可以看到nginx和simple服务都访问成功。

案例三:上面都是http方式访问,如果要通过https访问,配置tls即可,Gateway中expose 443端口,并配置了tls,tls是一个secret,后面会通过命令生成这个secret。

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: httpsserver
spec:
  gateways:
    - httpsserver
  hosts:
    - httpsserver.cncamp.io
  http:
    - match:
        - port: 443
      route:
        - destination:
            host: httpserver.securesvc.svc.cluster.local
            port:
              number: 80
---
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: httpsserver
spec:
  selector:
    istio: ingressgateway
  servers:
    - hosts:
        - httpsserver.cncamp.io
      port:
        name: https-default
        number: 443
        protocol: HTTPS
      tls:
        mode: SIMPLE
        credentialName: cncamp-credential

后端服务httpserver的部署yaml文件内容如下所示。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpserver
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpserver
  template:
    metadata:
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "80"
      labels:
        app: httpserver
    spec:
      containers:
        - name: httpserver
          imagePullPolicy: Always
          image: cncamp/httpserver:v1.0-metrics
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: httpserver
spec:
  ports:
    - name: http
      port: 80
      protocol: TCP
      targetPort: 80
  selector:
    app: httpserver
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=cncamp Inc./CN=*.cncamp.io' -keyout cncamp.io.key -out cncamp.io.crt
kubectl create -n istio-system secret tls cncamp-credential --key=cncamp.io.key --cert=cncamp.io.crt
kubectl apply -f istio-specs.yaml -n securesvc

通过openssl命令生成key和cert,通过kubectl create secret tls命令生成secret对象,通过https访问访问服务。

curl --resolve httpsserver.cncamp.io:443:$INGRESS_IP https://httpsserver.cncamp.io/healthz -v -k

可以看到访问成功,因为是https方式访问,故可以看到有TLS握手的过程。

Istio三之VirtualService、Gateway、DestinationRule配置使用_第3张图片 案例四:模拟金丝雀部署,将应用的两个版本同时部署上,配置路由到V1和V2的规则。 如果请求的header中包含jesse,则路有到V2版本,否则路有到V1版本。Destination中定义V1和V2.

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: canary
spec:
  hosts:
    - canary
  http:
    - match:
        - headers:
            user:
              exact: jesse
      route:
        - destination:
            host: canary
            subset: v2
    - route:
      - destination:
          host: canary
          subset: v1
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: canary
spec:
  host: canary
  trafficPolicy:
    loadBalancer:
      simple: RANDOM
  subsets:
    - name: v1
      labels:
        version: v1
    - name: v2
      labels:
        version: v2
      trafficPolicy:
        loadBalancer:
          simple: ROUND_ROBIN

模拟的后端服务V1和V2版本,区分V1和V2应用主要是通过lables version进行区分的。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: canary
spec:
  replicas: 1
  selector:
    matchLabels:
      app: canary
  template:
    metadata:
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "80"
      labels:
        app: canary
        version: v1
    spec:
      containers:
        - name: canary
          imagePullPolicy: Always
          image: cncamp/httpserver:v1.0-metrics
          ports:
            - containerPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: canary-v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: canary
  template:
    metadata:
      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "80"
      labels:
        app: canary
        version: v2
    spec:
      containers:
        - name: canary
          imagePullPolicy: Always
          image: cncamp/httpserver:v2.0-metrics
          ports:
            - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: canary
spec:
  ports:
    - name: http
      port: 80
      protocol: TCP
      targetPort: 80
  selector:
    app: canary

启动后端服务和生产VirtualService和DestinationRule。

kubectl apply -f canary.yaml -n canary
kubectl apply -f istio-specs.yaml -n canary

为了访问canary,这里再启动一个能执行linux命令的pod,toolbox。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: toolbox
spec:
  replicas: 1
  selector:
    matchLabels:
      app: toolbox
  template:
    metadata:
      labels:
        app: toolbox
        access: "true"
    spec:
      containers:
        - name: toolbox
          image: centos
          command:
            - tail
            - -f
            - /dev/null

登录到toolbox中,通过curl命令(curl canary/hello -H "user: jesse")访问后端服务,如果header中有jesse字段值,那么就会访问到V2版本的服务,否则会访问V1版本的服务。执行结果如下所示

Istio三之VirtualService、Gateway、DestinationRule配置使用_第4张图片

以上就是通过例子演示Istio中VirtualService、Gateway、DestinationRule的配置,从而完成流量管理。

你可能感兴趣的:(云原生,Istio,kubernetes)