Kubernetes canary deployment routing based on geographic location - kubernetes

I have built a simple canary deployment in Kubernetes GCP but I dont have any control of the traffic routing , right now its random.
Ideally I would like to control the routing based on the Geographic location , however browser-agent would also do or any parameter where i can control the routing.
I followed the canary deployment technique using this link
Is there something in-built provided by k8s ?
Any pointers would be great.

Take a look at Canary Deployments using Istio.
For example, the following rule will only apply to an incoming request if it includes a “cookie” header that contains the substring “user=jason”.
apiVersion: config.istio.io/v1alpha2
kind: RouteRule
metadata:
name: ratings-jason
spec:
destination:
name: reviews
match:
request:
headers:
cookie:
regex: "^(.*?;)?(user=jason)(;.*)?$"
...

Related

How to replicate some traffic on Kubernetes and divert it to the Service for investigation

I'm using istio and I know that I can define weights in Virtual Service and divert traffic to different services.
My question is: how to amplify some of the traffic and direct the amplified traffic to the validation service? This amplified traffic will not go back to the original source but will be closed within the cluster. In other words, it does not bother the user.
I'm not even sure if there is an ecosystem, feature or application that provides this kind of mechanism. I don't even know if there is an ecosystem or application that provides such a mechanism and I don't know what it is called, so I'm having trouble finding it.
Thanks.
OP found a soultion by themselves, in the comments, hence the CW.
In this scenario, the best solution is to use Istio Mirroring - also called shadowing.
When traffic gets mirrored, the requests are sent to the mirrored service with their Host/Authority headers appended with -shadow. For example, cluster-1 becomes cluster-1-shadow.
Also, it is important to note that these requests are mirrored as “fire and forget”, which means that the responses are discarded.
To create mirroring rule, you have to create VirtualService with mirror and mirrorPercentage fields.
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: httpbin
spec:
hosts:
- httpbin
http:
- route:
- destination:
host: httpbin
subset: v1
weight: 100
mirror:
host: httpbin
subset: v2
mirrorPercentage:
value: 100.0
This route rule sends 100% of the traffic to v1. The last stanza specifies that you want to mirror (i.e., also send) 100% of the same traffic to the httpbin:v2 service.
[source]

Istio routing unique URL to specific pod

I am interested in using Istio in a use case where I spin up a pod based on some event (user starting a game for example), and allow that user to connect to the specific pod through a unqiue URL. Then when this game is over, I can spin the pod down.
I am trying to configure Istio in such a way that either the subdomain or URL can indicate a specific pod to send that request.
Maybe some way to dynamically control label matching? Like <pod_label>.api.com routes to pod matching label label_name: <pod_label> without having to update VirtualServices and DestinationRoutes every time a pod is created?
Edit:
A psuedo config would look similar to:
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
name: dynamic-route
spec:
hosts:
- r.prod.svc.cluster.local
http:
- match:
uri:
prefix: "/pod/{pod_name}"
ignoreUriCase: true
route:
- destination:
host: {pod_name}.prod.svc.cluster.local
(not sure if this would belong in the virtual service or the destination route)

How to use variables in Istio VirtualService?

I'm currently working on a case when we need to dynamically create services and provide access to them via URI subpaths of the main gateway.
I'm planning to use virtual services for traffic routing for them. Virtual Service for a particular service should look like:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: subpaths-routes
spec:
hosts:
- mainservice.prod.svc.cluster.local
http:
- name: "subpath-redirection"
match:
- uri:
prefix: "/bservices/svc-2345-6789"
route:
- destination:
host: svc-2345-6789.prod.svc.cluster.local
But there may be a huge number of such services (like thousands). All follow the same pattern of routing.
I would like to know if Istio has a mechanism to specify VirtualService with variables/parameters like the following:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: subpaths-routes
spec:
hosts:
- mainservice.prod.svc.cluster.local
http:
- name: "subpath-redirection"
match:
- uri:
prefix: "/bservices/"{{ variable }}
route:
- destination:
host: {{ variable }}.prod.svc.cluster.local
In Nginx, one can do a similar thing by specifying something like this:
location ~ /service/(?<variable>[0-9a-zA-Z\_\-]+)/ {
proxy_pass http://$variable:8080;
}
Is there a way in Istio to accomplish that?
And if there is not, how would thousands of VSs impact the performance of request processing? Is It expensive to keep them in terms of CPU and RAM being consumed?
Thank you in advance!
How to use variables in Istio VirtualService?
As far as I know there is no such option in istio to specify a variable in prefix and host, if it was only a prefix then you could try with regex instead of prefix.
If you would like to automate it in some way, I mean create a variable and put in in both, prefix and host, then you could try do to it with helm.
There are few examples for virtual service in helm.
https://github.com/streamsets/helm-charts/blob/master/incubating/control-hub/templates/istio-gateway-virtualservice.yaml
https://github.com/salesforce/helm-starter-istio/blob/master/templates/virtualService.yaml
how would thousands of VSs impact the performance of request processing?
There is github issue about that, as #lanceliuu mentioned there
When we create ~1k virtualservices in a single cluster, the ingress gateway is picking up new virtualservice slowly.
So that might be one of the issues with thousands of Virtual Services.
Is It expensive to keep them in terms of CPU and RAM being consumed?
I would say it would require testing. I checked in above github issue and they mentioned that there is no mem/cpu pressure for istio components, but I can't say how expensive is that.
In theory you could create 1 big virtual service instead of thousands, but as mentioned in documentation you should rather Split large virtual services into multiple resources.
Additional resources:
https://engineering.hellofresh.com/everything-we-learned-running-istio-in-production-part-2-ff4c26844bfb
https://istio.io/latest/docs/ops/deployment/performance-and-scalability/
https://perf.dashboard.istio.io/

Istio: Can I add randomly generated unique value as a header to every request before it reaches my application

I have a RESTful service within a spring boot application. This spring boot app is deployed inside a kubernetes cluser and we have Istio as a service mesh attached to the sidecar of each container pod in the cluster. Every request to my service first hits the service mesh i.e Istio and then gets routed accordingly.
I need to put a validation for a request header and if that header is not present then randomly generate a unique value and set it as a header to the request. I know that there is Headers.HeaderOperations which i can use in the destination rule but how can i generate a unique value every time the header is missing? I dont want to write the logic inside my application as this is a general rule to apply for all the applications inside the cluster
There is important information that needs to be said in this subject. And it looks to me like You are trying to make a workaround tracing for an applications that does not forward/propagate headers in Your cluster. So I am going to mention few problems that can be encountered with this solution (just in case).
As mentioned in answer from Yuri G. You can configure unique x-request-id headers but they will not be very useful in terms of tracing if the requests are passing trough applications that do not propagate those x-request-id headers.
This is because tracing entire request paths needs to have unique x-request-id though out its entire trace. If the x-request-id value is different in various parts of the path the request takes, how are We going to put together the entire trace path?
In a scenario where two requests are received in application pod at the same time even if they had unique x-request-id headers, only application is able to tell which inbound request matches with which outbound connection. One of the requests could take longer to process and without forwarded trace header we can't tell which one is which.
Anyway for applications that do support forwarding/propagating x-request-id headers I suggest following guide from istio documentation.
Hope it helps.
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: enable-envoy-xrequestid-in-response
namespace: istio-system
spec:
configPatches:
- applyTo: NETWORK_FILTER
match:
context: GATEWAY
listener:
filterChain:
filter:
name: "envoy.http_connection_manager"
patch:
operation: MERGE
value:
typed_config:
"#type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager"
always_set_request_id_in_response: true
From reading the documentation of istio and envoy it seems like this is not supported by istio/envoy out of the box. As a workaround you have 2 options
Option 1: To set the x-envoy-force-trace header in virtual service
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews-route
spec:
hosts:
- reviews.prod.svc.cluster.local
http:
- headers:
request:
set:
x-envoy-force-trace: true
It will generate a header x-request-id if it is missing. But it seems like abuse of tracing mechanism.
Option 2: To use consistentHash balancing based on header, e.g:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: bookinfo-ratings
spec:
host: ratings.prod.svc.cluster.local
trafficPolicy:
loadBalancer:
consistentHash:
httpHeaderName:
name: x-custom-request-id
It will generate the header x-custom-request-id for any request that doesn't have this header. In this case the requests with same x-custom-request-id value will go always to the same pod that can cause uneven balancing.
The answer above works well! I have updated it for the latest istio (filter name is in full):
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
name: enable-envoy-xrequestid-in-response
namespace: istio-system
spec:
configPatches:
- applyTo: NETWORK_FILTER
match:
context: GATEWAY
listener:
filterChain:
filter:
name: "envoy.filters.network.http_connection_manager"
patch:
operation: MERGE
value:
typed_config:
"#type": "type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager"
always_set_request_id_in_response: true

What happens when a destinationrule is pushed in istio

I recently started looking into istio and got confused by the destination rule configuration.
Say I have a service A that have 10 pods running behind it. I pushed a destination rule that has two subsets with label version=v1 and version=v2.
So I'm wondering what will happen to the 10 pods under the hood? Will they be divided into two subsets automatically or just remain unlabeled? Or the subsets will only be valid when the pods themselves are labeled with version=v1 and version=v2?
Thanks a lot!
The general purpose is to set up DestinationRule resource in order to specify how the network traffic will reach your underlying Kubernetes cluster Pods.
Subsets parameter in Istio defines labels that identify version specific instances.
The below example of Istio DestinationRule configuration demonstrates how it works and can potentially reproduce your case:
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
name: reviews
spec:
host: reviews
subsets:
- name: v1
labels:
version: v1
- name: v2
labels:
version: v2
Actually, label version: v1 indicates that only Pods in Kubernetes marked with the same label will receive network traffic; therefore the same approach will work for label version: v2.
There are several resources available in Istio that can expand functionality for network management purposes as described in Official documentation.
A DestinationRule simply "defines" subsets of the underlying pods. Any pod that has the labels specified in a subset are considered part of that subset and can then be routed to in a VirtualService. If your pods don't have labels that correspond to any of the defined subsets, then they will not receive traffic that is routed to a particular subset. For example, if you set a rule in a VirtualService to send 100% of the traffic to subset v1, and you have no pods with the corresponding version=v1 label, then none of your pods will receive the traffic and client calls will fail. Note that you don't have to route traffic to subsets, you can also set rules to just route to any pod implementing the service. Subsets are used to distribute traffic when you have pods implementing more than one version of service running at the same time.