<p>Let's assume that I have a configuration for istio (I use GCP):</p>

<pre><code>apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: my-route
  namespace: my-service
spec:
  hosts:
  - "service.cluster.local"
  http:
  - match:
    - headers:
        specific-id:
          regex: ^(1|2|3|4|5)$
    route:
    - destination:
        host: "service.cluster.local"
        subset: s-01
  - match:
    - headers:
        specific-id:
          regex: ^(6|7|8|9|10)$
    route:
    - destination:
        host: "service.cluster.local"
        subset: s-02
</code></pre>

<p>My destination rules are based on specific header (int value).</p>

<p>Now I want to change this configuration (because I need to do resharding), and I will have something like this:</p>

<pre><code>apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: my-route
  namespace: my-service
spec:
  hosts:
 - "service.cluster.local"
  http:
 - match:
    - headers:
        specific-id:
          regex: ^(1|2|3|9|10)$
    route:
    - destination:
        host: "service.cluster.local"
        subset: s-03
 - match:
    - headers:
        specific-id:
          regex: ^(4|5|6|7|8|)$
    route:
    - destination:
        host: "service.cluster.local"
        subset: s-04
 - match:
    - headers:
        specific-id:
          regex: ^(1|3|5|7|9|)$
    route:
    - destination:
        host: "service.cluster.local"
        subset: s-05
</code></pre>

<p>My questions are:</p>

<ul>
<li><p>Does istio rules allows to have intersections inside subsets (like to
have for one service regex: <code>^(1|2|3|4|5)$</code> and for another
<code>^(1|3|5|7|9|)$</code>)?</p></li>
<li><p>After deployment of the new schema with new rules, when istio will
apply it? Does istio guarantee that it won't be applied (to not
remove old rules) before all of my new instances will be ready for
traffic? </p></li>
</ul>

<blockquote>
  <p>Does istio rules allows to have intersections inside subsets (like to have for one service regex: <code>^(1|2|3|4|5)$</code> and for another <code>^(1|3|5|7|9|)$</code>)?</p>
</blockquote>

<p>According to <a href="https://istio.io/docs/concepts/traffic-management/#routing-rule-precedence" rel="nofollow noreferrer">istio</a> documentation:</p>

<blockquote>
  <p>Routing rules are  <strong>evaluated in sequential order from top to bottom</strong>, with the first rule in the virtual service definition being given highest priority. In this case you want anything that doesn’t match the first routing rule to go to a default destination, specified in the second rule. Because of this, the second rule has no match conditions and just directs traffic to the v3 subset.</p>
  
  <pre><code>- route:
  - destination:
      host: reviews
      subset: v3
</code></pre>
  
  <p>We recommend providing a default “no condition” or weight-based rule (described below) like this as the last rule in each virtual service to ensure that traffic to the virtual service always has at least one matching route.</p>
</blockquote>

<p>The routing rules are evaluated in order. So the first match will always be selected.</p>

<p><code>regex: ^(1|2|3|9|10)$</code> would end up in <code>subset: s-03</code></p>

<p><code>regex: ^(4|5|6|7|8|)$</code> would end up in <code>subset: s-04</code></p>

<p>No matches would end up in <code>subset: s-05</code> as <code>regex: ^(1|3|5|7|9|)$</code> is already covered by <code>subset: s-03</code> and <code>subset: s-04</code>.</p>

<p>Note that You could set the <code>subset: s-05</code> as default match with “no condition”.</p>

<hr>

<p>However You can use "weight" to distribute traffic between matching rules.</p>

<p>And with little bit of creativity (by splitting intersecting groups into unique subsets) We can get the following configuration:</p>

<pre><code>apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: my-route
  namespace: my-service
spec:
  hosts:
  - "service.cluster.local"
  http:
  - match:
    - headers:
        specific-id:
          regex: ^(1|3|9)$
    route:
    - destination:
        host: "service.cluster.local"
        subset: s-03
      weight: 50
    - destination:
        host: "service.cluster.local"
        subset: s-05
      weight: 50
  - match:
    - headers:
        specific-id:
          regex: ^(2|10)$
    route:
    - destination:
        host: "service.cluster.local"
        subset: s-03
  - match:
    - headers:
        specific-id:
          regex: ^(5|7)$
    route:
    - destination:
        host: "service.cluster.local"
        subset: s-04
      weight: 50
    - destination:
        host: "service.cluster.local"
        subset: s-05
      weight: 50
  - match:
    - headers:
        specific-id:
          regex: ^(4|6|8|)$
    route:
    - destination:
        host: "service.cluster.local"
        subset: s-04

</code></pre>

<p>This way You can have:</p>

<p><code>subset: s-03</code> that matches <code>regex: ^(1|3|9)$ OR ^(2|10)$</code></p>

<p><code>subset: s-04</code> that matches <code>regex: ^(5|7)$ OR ^(4|6|8|)$</code></p>

<p><code>subset: s-05</code> that matches <code>regex: ^(1|3|9)$ OR ^(5|7)$</code></p>

<p>Where traffic for regex: </p>

<p><code>^(1|3|9)$</code> is split evenly between <code>subset: s-03</code> and <code>subset: s-05</code>.</p>

<p><code>^(5|7)$</code> is split evenly between <code>subset: s-04</code> and <code>subset: s-05</code>.</p>

<hr>

<blockquote>
  <p>After deployment of the new schema with new rules, when istio will apply it? Does istio guarantee that it won't be applied (to not remove old rules) before all of my new instances will be ready for traffic?</p>
</blockquote>

<p>Istio uses envoy for routing and <a href="https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/operations/hot_restart" rel="nofollow noreferrer">Envoy</a> documentation has the following statement:</p>

<blockquote>
  <p><strong>Service discovery and dynamic configuration:</strong> Envoy optionally consumes a layered set of <a href="https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/operations/dynamic_configuration#arch-overview-dynamic-config" rel="nofollow noreferrer">dynamic configuration APIs</a> for centralized management. The layers provide an Envoy with dynamic updates about: hosts within a backend cluster, the backend clusters themselves, HTTP routing, listening sockets, and cryptographic material. For a simpler deployment, backend host discovery can be <a href="https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/service_discovery#arch-overview-service-discovery-types-strict-dns" rel="nofollow noreferrer">done through DNS resolution</a> (or even <a href="https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/service_discovery#arch-overview-service-discovery-types-static" rel="nofollow noreferrer">skipped entirely</a>), with the further layers replaced by static config files.</p>
</blockquote>

<p>So as soon as istio object modifies the envoy dynamic configuration, it pushes its changes to envoy proxy. Yes envoy will make sure that new instances will be ready for traffic and drain the old traffic gracefully before shutting down.</p>

<p>More info: <a href="https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/operations/runtime" rel="nofollow noreferrer">Runtime configuration</a>, <a href="https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/operations/hot_restart" rel="nofollow noreferrer">Hot restart</a></p>

<p>Hope this helps.</p>
