2

Scenario-

I have 2 deployments deployment-1 with label- version:v1 and deployment-2 with label- version:v2 both are hosted under a nodeport service- test-1. I have created a virtual service with two match conditions as follows

  - match:
    - uri:
        exact: /v1
    rewrite:
      uri: /
    route:
      - destination:
          host: test-1
          port:
            number: 80
          subset: v1
  - match:
    - uri:
        exact: /v2
    rewrite:
      uri: /
    route:
      - destination:
          host: test-1
          port:
            number: 80
          subset: v2

The code file can be found here

Problem-

When I try to visit this Ingress Gateway IP at http://ingress-gateway-ip/v1/favicon.ico, I encounter a 404 error in the console saying http://ingress-gateway-ip/favicon.ico not found (because this has been re-written to "/") also the stylings and js are absent at this route. But when I try to visit http://ingress-gateway-ip/v1/favicon.ico I can see the favicon icon along with all the js and stylings.

Please find the screenshots of the problem here

Expectation-

How can I access these two services using a prefix routing in the url, meaning when I navigate to /v1, only the V1 version should come up without 404, and when I navigate to /v2, only the V2 version should come up?

EDIT-1:

  1. Added code snippet from the original code
  2. Added code file link

EDIT-2:

  1. Added screenshot of the problem
  2. Modified problem statement for clear understanding
john mich
  • 2,477
  • 3
  • 17
  • 32
  • 1
    You have specified 2 matches, /v1 and v2, so if you go with http://ingress-gateway-ip/ there is no match for that, if you have only test-1 service then v2 shouldn't work either, so only v1 will work for now. As far as I understand you're missing a subset in virtual service and appropriate destination rule like in below example. If they're both under test-1 then destination host for /v2 should be test-1, and then it should match the deployment based on subset's. Take a look at canary examples [here](https://www.istiobyexample.dev/canary) and [here](https://istio.io/latest/blog/2017/0.1-canary/) – Jakub Aug 13 '20 at 11:52
  • I am sorry for creating confusion there, I do have the subsets in the original file, it's just that I wanted to highlight the match rules and hence I represented it in an incomplete manner. I have edited the question and here [https://gist.github.com/directlinks/9a019d940caa4516bcff3ff1358e06a0] is my complete code – john mich Aug 13 '20 at 19:30

1 Answers1

1

How can I access these two services using a prefix routing in the url, meaning when I navigate to /v1, only the V1 version should come up without 404, and when I navigate to /v2, only the V2 version should come up

I assume your issue is your DestinationRule, in the v2 name your label is version: v1 and it should be version: v2, that's why your requests from /v1 and /v2 went only to v1 version of your pod.

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: test-destinationrule
spec:
  host: test-1
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v1 <--- 

It should be

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: test-destinationrule
spec:
  host: test-1
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2

When I try to visit this Ingress Gateway IP, I encounter a 404 error in the console saying http://ingress-gateway-ip/favicon.ico

It's working as designed, you haven't specified path for /, just for /v1 and /v2.

If you want to be able to access then you would have to add another match for /

- match:
  - uri:
      prefix: /
  route:
    - destination:
        host: test-1

There is working example with 2 nginx pods, take a look.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-v1
spec:
  selector:
    matchLabels:
      version: v1
  replicas: 1
  template:
    metadata:
      labels:
        app: frontend
        version: v1
    spec:
      containers:
      - name: nginx1
        image: nginx
        ports:
        - containerPort: 80
        lifecycle:
          postStart:
            exec:
              command: ["/bin/sh", "-c", "echo Hello nginx1 > /usr/share/nginx/html/index.html"]

---


apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-v2
spec:
  selector:
    matchLabels:
      version: v2
  replicas: 1
  template:
    metadata:
      labels:
        app: frontend
        version: v2
    spec:
      containers:
      - name: nginx2
        image: nginx
        ports:
        - containerPort: 80
        lifecycle:
          postStart:
            exec:
              command: ["/bin/sh", "-c", "echo Hello nginx2 > /usr/share/nginx/html/index.html"]

---

apiVersion: v1
kind: Service
metadata:
  name: test-1
  labels:
    app: frontend
spec:
  ports:
  - name: http-front
    port: 80
    protocol: TCP
  selector:
    app: frontend

---

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: simpleexample
spec:
  selector:
    istio: ingressgateway
  servers:
  - hosts:
    - '*'
    port:
      name: http
      number: 80
      protocol: HTTP

---

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: test-virtualservice
spec:
  gateways:
  - simpleexample
  hosts:
  - '*' 
  http:
  - match:
    - uri:
        prefix: /v1
    rewrite:
      uri: /
    route:
      - destination:
          host: test-1
          port:
            number: 80
          subset: v1
  - match:
    - uri:
        prefix: /v2
    rewrite:
      uri: /
    route:
      - destination:
          host: test-1
          port:
            number: 80
          subset: v2

  
---

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: test-destinationrule
spec:
  host: test-1
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2

Results from curl:

curl -v ingress-gateway-ip/  
404 Not Found 
there is no path specified for that in virtual service 

curl -v ingress-gateway-ip/v1  
HTTP/1.1 200 OK 
Hello nginx1

curl -v ingress-gateway-ip/v2 
HTTP/1.1 200 OK 
Hello nginx2

EDIT

the problem is that all the stylings and js are not readable by the browser at "/" when they are being re-written

It was already explained by @Rinor here

I would add this Istio in practise tutorial here, it explains well a way of dealing with that problem, which is to add more paths for your dependencies(js,css,etc).

Let’s break down the requests that should be routed to Frontend:

Exact path / should be routed to Frontend to get the Index.html

Prefix path /static/* should be routed to Frontend to get any static files needed by the frontend, like Cascading Style Sheets and JavaScript files.

Paths matching the regex ^.*.(ico|png|jpg)$ should be routed to Frontend as it is an image, that the page needs to show.

http:
  - match:
    - uri:
        exact: /
    - uri:
        exact: /callback
    - uri:
        prefix: /static
    - uri:
        regex: '^.*\.(ico|png|jpg)$'
    route:
    - destination:
        host: frontend             
        port:
          number: 80

Let me know if you have any more questions.

Jakub
  • 8,189
  • 1
  • 17
  • 31
  • Thank you for your time and pointing out that destination rule mistake, I'll fix that for V2. Let's focus on version V1. Say I have a rule saying if the URL has "v1" as a prefix then rewrite it as "/", during this process it does exactly that has been specified in the rules but the problem is that all the stylings and js are not readable by the browser at "/" when they are being re-written because they are actually present at "V1". Check out this screenshot-> https://imgur.com/a/Rl4xAFu – john mich Aug 17 '20 at 13:21
  • 1
    Hi @johnmich, I have edited my answer to answer your question, take a look. If it helped consider upvoting/accepting the answer If not please let me know about your results/further issues. – Jakub Aug 18 '20 at 06:14
  • 1
    Thank you, I will check this soon and give an update on this. – john mich Aug 18 '20 at 10:52