I'm attempting to setup a simple routing example with Istio 1.3.0-rc.0 based upon the Book Info example. I am attempting this in EKS with Kubernetes version 1.13. Here is my configuration.
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: myapp-gateway
spec:
selector:
istio: ingressgateway # use istio default controller
servers:
- port:
number: 80
name: http
protocol: HTTP
hosts:
- "*"
---
apiVersion: v1
kind: Service
metadata:
name: myapp-service
labels:
app: myapp
spec:
ports:
- port: 3001
name: http
selector:
app: myapp
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-v1
spec:
replicas: 1
selector:
matchLabels:
app: myapp
version: v1
template:
metadata:
labels:
app: myapp
version: v1
spec:
containers:
- name: myapp
image: fake-myapp:v1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3001
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-v2
spec:
replicas: 1
selector:
matchLabels:
app: myapp
version: v2
template:
metadata:
labels:
app: myapp
version: v2
spec:
containers:
- name: myapp
image: fake-myapp:v2
imagePullPolicy: IfNotPresent
ports:
- containerPort: 3001
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: myapp-destinationrule
spec:
host: myapp-service
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: app-virtualservice
spec:
hosts:
- "*"
gateways:
- myapp-gateway
http:
- match:
- uri:
exact: /api
route:
- destination:
host: myapp-service
subset: v2
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: myapp-virtualservice
spec:
hosts:
- myapp-service
http:
- route:
- destination:
host: myapp-service
subset: v2
---
I can reach my services from the external load balancer, however, I am attempting to route traffic to only subset v2 as is defined in my VirtualServices.
However, I only get round robin balancing between the two versions of my Deployment.
I've tried the troubleshooting links which suggest adding the subset to the VirtualService that has my gateway attached, but still without any success.
I've also tried setting a host name explicitly without luck.
What am I missing?
Here are my observations particularly on the 2 VirtualService
's.
app-virtualservice
), the match.uri
is exact
with value /api
. Which means request that exactly has path /api
will work i.e. POST GATEWAY_URL/api, GET GATEWAY_URL/api. If you have some more extensions, e.g. POST GATEWAY_URL/api/somethingelse, then it won't fall into this routing. Kindly check on this area. If this is a problem, maybe use prefix
instead of exact
.myapp-virtualservice
), there is no indication of spec.gateways
which would specify the gateway it will apply. Also, in this particular instance, VirtualService
governs the routing for your Gateway
. The DestinationRules apply for the Service
(or the Envoy sidecar proxy).Please check and see if these helps.
This behavior is quite explainable. Once you have created K8s Service pointing to the two different deployments v1
and v2
, K8s runtime composes certain endpoints which are listening on the same port, therefore each time you reach application service throughout Istio mesh traffic objects path (Gateway -> Virtual service -> Destination rule -> K8s service) the request randomly hits myapp-v1
, myapp-v2
nested Pods, as per user space proxy mode, which is enabled using round robin algorithm by default.
You might probably need to compose two separate k8s services for v1
and v2
deployments, targeting appropriate endpoints respectively, in order to avoid sporadic traffic routing between application parties if you are expecting to route traffic between apps, instead of splitting traffic across the service Subsets.
apiVersion: v1
kind: Service
metadata:
name: myapp-v1-service
labels:
version: v1
spec:
ports:
- port: 3001
name: http
selector:
version: v1
apiVersion: v1
kind: Service
metadata:
name: myapp-v2-service
labels:
version: v2
spec:
ports:
- port: 3001
name: http
selector:
version: v2