Home > Blockchain >  Right namespace for VirtualService and DestinationRule Istio resources
Right namespace for VirtualService and DestinationRule Istio resources

Time:01-03

I am trying to understand the VirtualService and DestinationRule resources in relation with the namespace which should be defined and if they are really namespaced resources or they can be considered as cluster-wide resources also.

I have the following scenario:

  • The frontend service (web-frontend) access the backend service (customers).
  • The frontend service is deployed in the frontend namespace
  • The backend service (customers) is deployed in the backend namespace
  • There are 2 versions of the backend service customers (2 deployments), one related to the version v1 and one related to the version v2.
  • The default behavior for the clusterIP service is to load-balance the request between the 2 deployments (v1 and v2) and my goal is by creating a DestinationRule and a VirtualService to direct the traffic only to the deployment version v1.
  • What I want to understand is which is the appropriate namespace to define such DestinationRule and a VirtualService resources. Should I create the necessary DestinationRule and VirtualService resources in the frontend namespace or in the backend namespace?

In the frontend namespace I have the web-frontend deployment and and the related service as follow:

apiVersion: v1
kind: Namespace
metadata:
  name: frontend
  labels:
    istio-injection: enabled
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-frontend
  namespace: frontend
  labels:
    app: web-frontend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: web-frontend
  template:
    metadata:
      labels:
        app: web-frontend
        version: v1
    spec:
      containers:
        - image: gcr.io/tetratelabs/web-frontend:1.0.0
          imagePullPolicy: Always
          name: web
          ports:
            - containerPort: 8080
          env:
            - name: CUSTOMER_SERVICE_URL
              value: 'http://customers.backend.svc.cluster.local'
---
kind: Service
apiVersion: v1
metadata:
  name: web-frontend
  namespace: frontend
  labels:
    app: web-frontend
spec:
  selector:
    app: web-frontend
  type: NodePort
  ports:
    - port: 80
      name: http
      targetPort: 8080

I have expose the web-frontend service by defining the following Gateway and VirtualService resources as follow:

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: gateway-all-hosts
  # namespace: default # Also working
  namespace: frontend
spec:
  selector:
    istio: ingressgateway
  servers:
    - port:
        number: 80
        name: http
        protocol: HTTP
      hosts:
        - "*"
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: web-frontend
  # namespace: default # Also working
  namespace: frontend
spec:
  hosts:
    - "*"
  gateways:
    - gateway-all-hosts
  http:
    - route:
        - destination:
            host: web-frontend.frontend.svc.cluster.local
            port:
              number: 80

In the backend namespace I have the customers v1 and v2 deployments and related service as follow:

apiVersion: v1
kind: Namespace
metadata:
  name: backend
  labels:
    istio-injection: enabled
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: customers-v1
  namespace: backend
  labels:
    app: customers
    version: v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: customers
      version: v1
  template:
    metadata:
      labels:
        app: customers
        version: v1
    spec:
      containers:
        - image: gcr.io/tetratelabs/customers:1.0.0
          imagePullPolicy: Always
          name: svc
          ports:
            - containerPort: 3000
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: customers-v2
  namespace: backend
  labels:
    app: customers
    version: v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: customers
      version: v2
  template:
    metadata:
      labels:
        app: customers
        version: v2
    spec:
      containers:
        - image: gcr.io/tetratelabs/customers:2.0.0
          imagePullPolicy: Always
          name: svc
          ports:
            - containerPort: 3000
---
kind: Service
apiVersion: v1
metadata:
  name: customers
  namespace: backend
  labels:
    app: customers
spec:
  selector:
    app: customers
  type: NodePort
  ports:
    - port: 80
      name: http
      targetPort: 3000

I have created the following DestinationRule and VirtualService resources to send the traffic only to the v1 deployment.

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: customers
  #namespace: default # Not working
  #namespace: frontend # working
  namespace: backend # working
spec:
  host: customers.backend.svc.cluster.local
  subsets:
    - name: v1
      labels:
        version: v1
    - name: v2
      labels:
        version: v2
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: customers
  #namespace: default # Not working
  #namespace: frontend # working
  namespace: backend # working
spec:
  hosts:
    - "customers.backend.svc.cluster.local"
  http:
  ## route  - subset: v1
  - route:
      - destination:
          host: customers.backend.svc.cluster.local
          port:
            number: 80
          subset: v1
  • The question is which is the appropriate namespace to define the VR and DR resources for the customer service?

  • From my test I see that I can use either the frontend namespace, or the backend namespace. Why the VR,DR can be created to the frontend namespace or in the backend namespaces and in both cases are working? Which is the correct one?

  • Are the DestinationRule and VirtualService resources really namespaced resources or can be considered as cluster-wide resources ? Are the low level routing rules of the proxies propagated to all envoy proxies regardless of the namespace?

CodePudding user response:

A DestinationRule to actually be applied during a request needs to be on the destination rule lookup path:

-> client namespace
-> service namespace
-> the configured meshconfig.rootNamespace namespace (istio-system by default)

In your example, the "web-frontend" client is in the frontend Namespace (web-frontend.frontend.svc.cluster.local), the "customers" service is in the backend Namespace (customers.backend.svc.cluster.local), so the customers DestinationRule should be created in one of the following Namespaces: frontend, backend or istio-system. Additionally, please note that the istio-system Namespace isn't recommended unless the destination rule is really a global configuration that is applicable in all Namespaces.

To make sure that the destination rule will be applied we can use the istioctl proxy-config cluster command for the web-frontend Pod:

$ istioctl proxy-config cluster web-frontend-69d6c79786-vkdv8 -n frontend | grep "customers.backend.svc.cluster.local"
SERVICE FQDN                                            PORT      SUBSET     DESTINATION RULE
customers.backend.svc.cluster.local                     80        -          customers.frontend
customers.backend.svc.cluster.local                     80        v1         customers.frontend
customers.backend.svc.cluster.local                     80        v2         customers.frontend

When the destination rule is created in the default Namespace, it will not be applied during the request:

$ istioctl proxy-config cluster web-frontend-69d6c79786-vkdv8 -n frontend | grep "customers.backend.svc.cluster.local"
SERVICE FQDN                                            PORT      SUBSET    DESTINATION RULE
customers.backend.svc.cluster.local                     80        -        

For more information, see the Control configuration sharing in namespaces documentation.

  • Related