使用 IngressGateway 和 ServiceRoute 基于子集的流量路由

查看本文大纲

在本操作指南中,你将了解如何通过基于 URI 端点、标头和端口匹配流量并将其路由到目标服务的主机:端口来设置基于子集的流量路由。

先决条件

在继续之前,请确保你已完成以下任务:

创建工作区和配置组

首先,使用以下 YAML 配置创建工作区和配置组:

helloworld-ws-groups.yaml
apiversion: api.tsb.tetrate.io/v2
kind: Workspace
metadata:
  organization: tetrate
  tenant: tetrate
  name: helloworld-ws
spec:
  namespaceSelector:
    names:
      - '*/helloworld'
---
apiVersion: gateway.tsb.tetrate.io/v2
kind: Group
metadata:
  organization: tetrate
  tenant: tetrate
  workspace: helloworld-ws
  name: helloworld-gw
spec:
  namespaceSelector:
    names:
      - '*/helloworld'
  configMode: BRIDGED
---
apiVersion: traffic.tsb.tetrate.io/v2
kind: Group
metadata:
  organization: tetrate
  tenant: tetrate
  workspace: helloworld-ws
  name: helloworld-trf
spec:
  namespaceSelector:
    names:
      - '*/helloworld'
  configMode: BRIDGED

将其保存为 helloworld-ws-groups.yaml ,并将其与 tctl 一起应用:

tctl apply -f helloworld-ws-groups.yaml

部署你的应用程序

首先创建命名空间并启用 Istio sidecar 注入:

kubectl create namespace helloworld
kubectl label namespace helloworld istio-injection=enabled

接下来,使用以下 YAML 配置部署你的应用程序:

helloworld-2-subsets.yaml
apiVersion: v1
kind: Service
metadata:
  name: helloworld
  labels:
    app: helloworld
    service: helloworld
spec:
  ports:
    - port: 5000
      name: http
  selector:
    app: helloworld
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: helloworld-v1
  labels:
    app: helloworld
    version: v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: helloworld
      version: v1
  template:
    metadata:
      labels:
        app: helloworld
        version: v1
    spec:
      containers:
        - name: helloworld
          image: docker.io/istio/examples-helloworld-v1
          resources:
            requests:
              cpu: '100m'
          imagePullPolicy: IfNotPresent #Always
          ports:
            - containerPort: 5000
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: helloworld-v2
  labels:
    app: helloworld
    version: v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: helloworld
      version: v2
  template:
    metadata:
      labels:
        app: helloworld
        version: v2
    spec:
      containers:
        - name: helloworld
          image: docker.io/istio/examples-helloworld-v2
          resources:
            requests:
              cpu: '100m'
          imagePullPolicy: IfNotPresent #Always
          ports:
            - containerPort: 5000

将其保存为 helloworld-2-subsets.yaml ,并将其与 kubectl 一起应用:

kubectl apply -f helloworld-2-subsets.yaml -n helloworld

部署应用程序 IngressGateway

使用以下 YAML 配置部署应用程序 IngressGateway:

apiVersion: install.tetrate.io/v1alpha1
kind: IngressGateway
metadata:
  name: tsb-helloworld-gateway
  namespace: helloworld
spec:
  kubeSpec:
    service:
      type: LoadBalancer

将其保存为 helloworld-ingress.yaml ,并将其与 kubectl 一起应用:

kubectl apply -f helloworld-ingress.yaml

获取网关 IP:

export GATEWAY_IP=$(kubectl -n helloworld get service tsb-helloworld-gateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
echo $GATEWAY_IP

网关证书

在本例中,你将在网关处使用简单的 TLS 公开应用程序。你需要为它提供一个存储在 Kubernetes 密钥中的 TLS 证书:

kubectl create secret tls -n helloworld helloworld-cert \
    --cert /path/to/some/helloworld-cert.pem \
    --key /path/to/some/helloworld-key.pem

部署 IngressGateway 和 ServiceRoute

使用以下 YAML 配置创建 IngressGateway:

helloworld-gw.yaml
apiVersion: gateway.tsb.tetrate.io/v2
kind: IngressGateway
metadata:
  name: helloworld-gateway
  group: helloworld-gw
  workspace: helloworld-ws
  tenant: tetrate
  organization: tetrate
spec:
  workloadSelector:
    namespace: helloworld
    labels:
      app: tsb-helloworld-gateway
  http:
    - name: helloworld
      port: 443
      hostname: helloworld.tetrate.com
      tls:
        mode: SIMPLE
        secretName: helloworld-cert
      routing:
        rules:
          - route:
              host: helloworld/helloworld.helloworld.svc.cluster.local
              port: 5000

将其保存为 helloworld-gw.yaml ,并将其与 tctl 一起应用:

tctl apply -f helloworld-gw.yaml

创建一个 ServiceRoute,根据标头匹配流量并将其路由到不同的子集:

helloworld-header-based-routing-service-route.yaml
apiVersion: traffic.tsb.tetrate.io/v2
kind: ServiceRoute
metadata:
  name: helloworld-service-route
  group: helloworld-trf
  workspace: helloworld-ws
  tenant: tetrate
  organization: tetrate
spec:
  service: helloworld/helloworld.helloworld.svc.cluster.local
  portLevelSettings:
    - port: 5000
      trafficType: HTTP
  subsets:
    - name: v1
      labels:
        version: v1
      weight: 50
    - name: v2
      labels:
        version: v2
      weight: 50
  httpRoutes:
    - name: http-route-match-header-and-port
      match:
        - name: match-header-and-port
          headers:
            end-user:
              exact: jason
          port: 5000
      destination:
        - subset: v1
          weight: 80
          port: 5000
        - subset: v2
          weight: 20
          port: 5000
    - name: http-route-match-port
      match:
        - name: match-port
          port: 5000
      destination:
        - subset: v1
          weight: 100
          port: 5000

将其保存为 helloworld-header-based-routing-service-route.yaml ,并将其与 tctl 一起应用:

tctl apply -f helloworld-header-based-routing-service-route.yaml

验证

带标头的请求

发送带有标头 end-user: jason 的连续 curl 请求。流量将以 80:20 的比例在 v1v2 之间路由。

for i in {1..20}; do curl -k "https://helloworld.tetrate.com/hello" \
--resolve "helloworld.tetrate.com:443:$GATEWAY_IP" \
-H "end-user: jason" 2>&1; done

无标头请求

发送不带任何标头的连续卷曲请求。所有流量都将路由到 v1

for i in {1..20}; do curl -k "https://helloworld.tetrate.com/hello" \
--resolve "helloworld.tetrate.com:443:$GATEWAY_IP" 2>&1; done

通过执行这些步骤,你已使用 IngressGateway 和 ServiceRoute 成功设置基于子集的流量路由。