Istio Traffic Shifting not working in Internal communication

11/24/2019

I deployed Istion on my local Kubernetes cluster running in my Mac. I created this VirtualService, DestinationRule and Gateway.

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: code-gateway
  namespace: code
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "gateway.code"

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: codemaster
  namespace: code
spec:
  hosts:
  - master.code
  - codemaster
  gateways:
  - codemaster-gateway
  - code-gateway
  http:
  - route:
    - destination:
        host: codemaster 
        subset: v1 

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: codemaster-gateway
  namespace: code
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "master.code"


apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: codemaster
  namespace: code
spec:
  host: codemaster
  trafficPolicy:
    connectionPool:
      tcp:
        maxConnections: 100
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2


- apiVersion: "v1"
  kind: "Service"
  metadata:
    labels:
      app: "codemaster"
      group: "code"
    name: "codemaster"
    namespace: "code"
  spec:
    ports:
    - name: http-web
      port: 80
      targetPort: 80
    selector:
      app: "codemaster"
      group: "code"
    type: "ClusterIP"

- apiVersion: "apps/v1"
  kind: "Deployment"
  metadata:
    labels:
      app: "codemaster"
      group: "code"
      env: "production"
    name: "codemaster"
    namespace: "code"
  spec:
    replicas: 2
    selector:
      matchLabels:
        app: "codemaster"
        group: "code"
    template:
      metadata:
        labels:
          app: "codemaster"
          version: "v1"
          group: "code"
          env: "production"
      spec:
        containers:
        - env:
          - name: "KUBERNETES_NAMESPACE"
            valueFrom:
              fieldRef:
                fieldPath: "metadata.namespace"
          - name: "SPRING_DATASOURCE_URL"
            value: "jdbc:postgresql://host.docker.internal:5432/code_master"
          - name: "SPRING_DATASOURCE_USERNAME"
            value: "postgres"
          - name: "SPRING_DATASOURCE_PASSWORD"
            value: "postgres"
          image: "kzone/code/codemaster:1.0.0"
          imagePullPolicy: "IfNotPresent"
          name: "codemaster"
          ports:
          - containerPort: 80
            name: "http"
            protocol: "TCP"

apiVersion: "v1"
kind: "List"
items:
- apiVersion: "apps/v1"
  kind: "Deployment"
  metadata:
    labels:
      app: "codemaster"
      group: "code"
      env: "canary"
    name: "codemaster-canary"
    namespace: "code"
  spec:
    replicas: 1
    selector:
      matchLabels:
        app: "codemaster"
        group: "code"
    template:
      metadata:
        labels:
          app: "codemaster"
          version: "v2"
          group: "code"
          env: "canary"
      spec:
        containers:
        - env:
          - name: "KUBERNETES_NAMESPACE"
            valueFrom:
              fieldRef:
                fieldPath: "metadata.namespace"
          - name: "SPRING_DATASOURCE_URL"
            value: "jdbc:postgresql://host.docker.internal:5432/code_master"
          - name: "SPRING_DATASOURCE_USERNAME"
            value: "postgres"
          - name: "SPRING_DATASOURCE_PASSWORD"
            value: "postgres"
          image: "kzone/code/codemaster:1.0.1"
          imagePullPolicy: "IfNotPresent"
          name: "codemaster"
          ports:
          - containerPort: 80
            name: "http"
            protocol: "TCP"

These are the services running in code namespace,

codemaster   ClusterIP   10.103.151.80   <none>        80/TCP    18h
gateway      ClusterIP   10.104.154.57   <none>        80/TCP    18h

I deployed 2 spring-boot microservices in ton k8s. One is a spring-boot gateway. These are the pods running in code namespace,

codemaster-6cb7b8ddf5-mlpzn          2/2     Running   0          7h3m
codemaster-6cb7b8ddf5-sgzt8          2/2     Running   0          7h3m
codemaster-canary-756697d9c8-22qb2   2/2     Running   0          7h3m
gateway-5b5c8697f4-jpb4q             2/2     Running   0          7h3m

When I send a request to http://master.code/version(the gateway created for codemaster service) it always goes to the correct subset. But when I send a request via spring-boot gateway (http://gateway.code/codemaster/version) request doesn't go to subset v1 only, requests go in round-robin to all the 3 pods. This is what I see in Kiali,

Request Routing in Kiali

enter image description here

I want to apply traffic shifting between the gateway and other services.

-- Keaz
docker
istio
kubernetes
spring-boot

2 Answers

11/28/2019

Istio relies on the Host header of a request to apply the traffic rules. Since you are using spring boot gateway to make the request ribbon hits the pod IP directly instead of hitting the service. So to avoid it provide static server list to the

route /version as http://master.code.cluster.local

in your spring boot gateway config -> to avoid ribbon dynamic endpoint discovery. This should fix the problem.

-- Arunagiriswaran Ezhilan
Source: StackOverflow

12/19/2019

After doing some search I found that there is no CNI in Docker for Mac k8s. Because of that traffic shifting doesn't not work on Docker for Mac K8s

-- Keaz
Source: StackOverflow