multiple Gateways on different ports of the same istio-proxy deployment not working as expected

2/11/2019

1. Install Istio (1.0.2)

kubectl apply -f https://raw.githubusercontent.com/knative/serving/master/third_party/istio-1.0.2/istio-crds.yaml
kubectl apply -f https://raw.githubusercontent.com/knative/serving/master/third_party/istio-1.0.2/istio.yaml

2. Create two Deployments and their corresponding Services

# Create Deployments
cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-a
spec:
  selector:
    matchLabels:
      app: a
  replicas: 3
  template:
    metadata:
      labels:
        app: a
    spec:
      containers:
        - name: print
          image: gcr.io/invertible-lens-220304/print
          env:
          - name: TEXT_TO_PRINT
            value: "AAAAAAAAAAAAAAAAAAAA"
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deployment-b
spec:
  selector:
    matchLabels:
      app: b
  replicas: 3
  template:
    metadata:
      labels:
        app: b
    spec:
      containers:
        - name: print
          image: gcr.io/invertible-lens-220304/print
          env:
          - name: TEXT_TO_PRINT
            value: "BBBBBBBBBBBBBBBBBBBB"
EOF

# Create Services
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
  name: service-a
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    app: a
---
apiVersion: v1
kind: Service
metadata:
  name: service-b
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    app: b
EOF

3. Create two Gateways and their corresponding NodePorts

# Create gateways
cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: gateway-a
  namespace: istio-system
spec:
  selector:
    istio: ingressgateway
  servers:
    - port:
        number: 3001
        name: http
        protocol: HTTP
      hosts:
        - "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: gateway-b
  namespace: istio-system
spec:
  selector:
    istio: ingressgateway
  servers:
    - port:
        number: 3002
        name: http
        protocol: HTTP
      hosts:
        - "*"
EOF

# Add ports to the istio-ingressgateway service
kubectl patch service istio-ingressgateway -n istio-system --type json --patch "$(cat <<EOF
  [{
    "op" : "add" ,
    "path" : "/spec/ports/-" ,
    "value" : {
      "name" : "node-port-1",
      "nodePort" : 30001,
      "port": 3001,
      "protocol": "TCP",
      "targetPort": 3001
    }
  }, {
    "op" : "add" ,
    "path" : "/spec/ports/-" ,
    "value" : {
      "name" : "node-port-2",
      "nodePort" : 30002,
      "port": 3002,
      "protocol": "TCP",
      "targetPort": 3002
    }
  }]
EOF)"

4. Create VirtualServices for each Gateway

cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: virtualservice-a
  namespace: istio-system
spec:
  gateways:
    - gateway-a
  hosts:
    - example.com
  http:
    - match:
        - authority:
            exact: example.com
      route:
        - destination:
            host: service-a.default.svc.cluster.local
            port:
              number: 80
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: virtualservice-b
  namespace: istio-system
spec:
  gateways:
    - gateway-b
  hosts:
    - example.com
  http:
    - match:
        - authority:
            exact: example.com
      route:
        - destination:
            host: service-b.default.svc.cluster.local
            port:
              number: 80
EOF

5. Test

NODE_IP=$(kubectl get nodes -o jsonpath="{.items[0].status.addresses[1].address}")

curl $NODE_IP:30001 -H "Host: example.com"
# Result: AAAAAAAAAAAAAAAAAAAA
curl $NODE_IP:30002 -H "Host: example.com"
# Result: AAAAAAAAAAAAAAAAAAAA

kubectl delete virtualservice virtualservice-a -n istio-system

curl $NODE_IP:30001 -H "Host: example.com"
# Result: BBBBBBBBBBBBBBBBBBBB
curl $NODE_IP:30002 -H "Host: example.com"
# Result: BBBBBBBBBBBBBBBBBBBB

Since 30001 is bound to gateway-a which has virtualservice-a pointing to service-a, and 30002 is bound to gateway-b which has virtualservice-b pointing to service-b, I would expected the result to be:

curl $NODE_IP:30001 -H "Host: example.com"
# Result: AAAAAAAAAAAAAAAAAAAA
curl $NODE_IP:30002 -H "Host: example.com"
# Result: BBBBBBBBBBBBBBBBBBBB

What happened and how can I get it to work?

P.S.

  1. I know it's possible with two istio-ingressgateway deployments, but can I achieve the same results with just one?
  2. Another possibility is to use just one VirtualService and one Gateway, and set the port in HTTPMatchRequest, but that still is not what I want.
  3. Yes I want the host names to be the same. Aren't the gateways isolated from each other?

What I want is to have two gateways on different ports of the same istio-proxy (docker.io/istio/proxyv2:1.0.2) deployment, with their own corresponding sets of virtual services, without affecting one another. Is that possible?

-- Kevin
envoyproxy
istio
kubernetes

0 Answers