Traffic Route

Traffic Route is an outbound policy. Dataplanes whose configuration is modified are in the sources matcher.

This policy lets you configure routing rules for the traffic in the mesh. It supports weighted routing and can be used to implement versioning across services or to support deployment strategies such as blue/green or canary.

Note the following:

  • The configuration must specify the data plane proxies for the routing rules.
  • The spec.destinations field supports only kuma.io/service.
  • All available tags are supported for spec.conf.
  • This is an outbound connection policy. Make sure that your data plane proxy configuration includes the appropriate tags.

Kuma also supports locality aware load balancing.

Default TrafficRoute

The control plane creates a default TrafficRoute every time a new Mesh is created. The default TrafficRoute enables the traffic between all the services in the mesh.

  1. apiVersion: kuma.io/v1alpha1
  2. kind: TrafficRoute
  3. mesh: default
  4. metadata:
  5. name: route-all-default
  6. spec:
  7. sources:
  8. - match:
  9. kuma.io/service: '*'
  10. destinations:
  11. - match:
  12. kuma.io/service: '*'
  13. conf:
  14. loadBalancer:
  15. roundRobin: {}
  16. destination:
  17. kuma.io/service: '*'
  1. type: TrafficRoute
  2. name: route-all-default
  3. mesh: default
  4. sources:
  5. - match:
  6. kuma.io/service: '*'
  7. destinations:
  8. - match:
  9. kuma.io/service: '*'
  10. conf:
  11. loadBalancer:
  12. roundRobin: {}
  13. destination:
  14. kuma.io/service: '*'

Usage

Here is a full example of TrafficRoute policy

  1. apiVersion: kuma.io/v1alpha1
  2. kind: TrafficRoute
  3. mesh: default
  4. metadata:
  5. name: full-example
  6. spec:
  7. sources:
  8. - match:
  9. kuma.io/service: backend_default_svc_80
  10. destinations:
  11. - match:
  12. kuma.io/service: redis_default_svc_6379
  13. conf:
  14. http:
  15. - match:
  16. method: # one of either "prefix", "exact" or "regex" is allowed
  17. exact: GET
  18. regex: "^POST|PUT$"
  19. path: # one of either "prefix", "exact" or "regex" is allowed
  20. prefix: /users
  21. exact: /users/user-1
  22. regex: "^users$"
  23. headers:
  24. some-header: # one of either "prefix", "exact" or "regex" will be allowed
  25. exact: some-value
  26. prefix: some-
  27. regex: "^users$"
  28. modify: # optional section
  29. path: # one of "rewritePrefix" or "regex" is allowed
  30. rewritePrefix: /not-users # rewrites previously matched prefix
  31. regex: # (example to change the path from "/service/foo/v1/api" to "/v1/api/instance/foo")
  32. pattern: "^/service/([^/]+)(/.*)$"
  33. substitution: '\2/instance/\1'
  34. host: # one of "value" or "fromPath" is allowed
  35. value: "XYZ"
  36. fromPath: # (example to extract "envoyproxy.io" host header from "/envoyproxy.io/some/path" path)
  37. pattern: "^/(.+)/.+$"
  38. substitution: '\1'
  39. requestHeaders:
  40. add:
  41. - name: x-custom-header
  42. value: xyz
  43. append: true # if true then if there is x-custom-header already, it will append xyz to the value
  44. remove:
  45. - name: x-something
  46. responseHeaders:
  47. add:
  48. - name: x-custom-header
  49. value: xyz
  50. append: true
  51. remove:
  52. - name: x-something
  53. destination: # one of "destination", "split" is allowed
  54. kuma.io/service: redis_default_svc_6379
  55. split:
  56. - weight: 100
  57. destination:
  58. kuma.io/service: redis_default_svc_6379
  59. destination: # one of "destination", "split" is allowed
  60. kuma.io/service: redis_default_svc_6379
  61. split:
  62. - weight: 100
  63. destination:
  64. kuma.io/service: redis_default_svc_6379
  65. loadBalancer: # one of "roundRobin", "leastRequest", "ringHash", "random", "maglev" is allowed
  66. roundRobin: {}
  67. leastRequest:
  68. choiceCount: 8
  69. ringHash:
  70. hashFunction: "MURMUR_HASH_2"
  71. minRingSize: 64
  72. maxRingSize: 1024
  73. random: {}
  74. maglev: {}
  1. type: TrafficRoute
  2. name: full-example
  3. mesh: default
  4. sources:
  5. - match:
  6. kuma.io/service: backend
  7. destinations:
  8. - match:
  9. kuma.io/service: redis
  10. conf:
  11. http:
  12. - match:
  13. method: # one of either "prefix", "exact" or "regex" is allowed
  14. exact: GET
  15. regex: "^POST|PUT$"
  16. path: # one of either "prefix", "exact" or "regex" is allowed
  17. prefix: /users
  18. exact: /users/user-1
  19. regex: "^users$"
  20. headers:
  21. some-header: # one of either "prefix", "exact" or "regex" will be allowed
  22. exact: some-value
  23. prefix: some-
  24. regex: "^users$"
  25. modify: # optional section
  26. path: # one of "rewritePrefix" or "regex" is allowed
  27. rewritePrefix: /not-users # rewrites previously matched prefix
  28. regex: # (example to change the path from "/service/foo/v1/api" to "/v1/api/instance/foo")
  29. pattern: "^/service/([^/]+)(/.*)$"
  30. substitution: '\2/instance/\1'
  31. host: # one of "value" or "fromPath" is allowed
  32. value: "XYZ"
  33. fromPath: # (example to extract "envoyproxy.io" host header from "/envoyproxy.io/some/path" path)
  34. pattern: "^/(.+)/.+$"
  35. substitution: '\1'
  36. requestHeaders:
  37. add:
  38. - name: x-custom-header
  39. value: xyz
  40. append: true # if true then if there is x-custom-header already, it will append xyz to the value
  41. remove:
  42. - name: x-something
  43. responseHeaders:
  44. add:
  45. - name: x-custom-header
  46. value: xyz
  47. append: true
  48. remove:
  49. - name: x-something
  50. destination: # one of "destination", "split" is allowed
  51. kuma.io/service: redis
  52. split:
  53. - weight: 100
  54. destination:
  55. kuma.io/service: redis
  56. destination: # one of "destination", "split" is allowed
  57. kuma.io/service: redis
  58. split:
  59. - weight: 100
  60. destination:
  61. kuma.io/service: redis
  62. loadBalancer: # one of "roundRobin", "leastRequest", "ringHash", "random", "maglev" is allowed
  63. roundRobin: {}
  64. leastRequest:
  65. choiceCount: 8
  66. ringHash:
  67. hashFunction: "MURMUR_HASH_2"
  68. minRingSize: 64
  69. maxRingSize: 1024
  70. random: {}
  71. maglev: {}

Kuma utilizes positive weights in the TrafficRoute policy and not percentages, therefore Kuma does not check if the total adds up to 100. If we want to stop sending traffic to a destination service we change the weight for that service to 0.

L4 Traffic Split

We can use TrafficRoute to split a TCP traffic between services with different tags implementing A/B testing or canary deployments.

Here is an example of a TrafficRoute that splits the traffic over the two different versions of the application. 90% of the connections from backend_default_svc_80 service will be initiated to redis_default_svc_6379 with tag version: 1.0 and 10% of the connections will be initiated to version: 2.0

  1. apiVersion: kuma.io/v1alpha1
  2. kind: TrafficRoute
  3. mesh: default
  4. metadata:
  5. name: split-traffic
  6. spec:
  7. sources:
  8. - match:
  9. kuma.io/service: backend_default_svc_80
  10. destinations:
  11. - match:
  12. kuma.io/service: redis_default_svc_6379
  13. conf:
  14. split:
  15. - weight: 90
  16. destination:
  17. kuma.io/service: redis_default_svc_6379
  18. version: '1.0'
  19. - weight: 10
  20. destination:
  21. kuma.io/service: redis_default_svc_6379
  22. version: '2.0'
  1. type: TrafficRoute
  2. name: split-traffic
  3. mesh: default
  4. sources:
  5. - match:
  6. kuma.io/service: backend
  7. destinations:
  8. - match:
  9. kuma.io/service: redis
  10. conf:
  11. split:
  12. - weight: 90
  13. destination:
  14. kuma.io/service: redis
  15. version: '1.0'
  16. - weight: 10
  17. destination:
  18. kuma.io/service: redis
  19. version: '2.0'

L4 Traffic Rerouting

We can use TrafficRoute to fully reroute a TCP traffic to different version of a service or even completely different service.

Here is an example of a TrafficRoute that redirects the traffic to another-redis_default_svc_6379 when backend_default_svc_80 is trying to consume redis_default_svc_6379.

  1. apiVersion: kuma.io/v1alpha1
  2. kind: TrafficRoute
  3. mesh: default
  4. metadata:
  5. name: reroute-traffic
  6. spec:
  7. sources:
  8. - match:
  9. kuma.io/service: backend_default_svc_80
  10. destinations:
  11. - match:
  12. kuma.io/service: redis_default_svc_6379
  13. conf:
  14. destination:
  15. kuma.io/service: another-redis_default_svc_6379
  1. type: TrafficRoute
  2. name: reroute-traffic
  3. mesh: default
  4. sources:
  5. - match:
  6. kuma.io/service: backend_default_svc_80
  7. destinations:
  8. - match:
  9. kuma.io/service: redis_default_svc_6379
  10. conf:
  11. destination:
  12. kuma.io/service: another-redis_default_svc_6379

L7 Traffic Split

We can use TrafficRoute to split an HTTP traffic between services with different tags implementing A/B testing or canary deployments.

Here is an example of a TrafficRoute that splits the traffic from frontend_default_svc_80 to backend_default_svc_80 between versions, but only on endpoints starting with /api. All other endpoints will go to version: 1.0

  1. apiVersion: kuma.io/v1alpha1
  2. kind: TrafficRoute
  3. mesh: default
  4. metadata:
  5. name: api-split
  6. spec:
  7. sources:
  8. - match:
  9. kuma.io/service: frontend_default_svc_80
  10. destinations:
  11. - match:
  12. kuma.io/service: backend_default_svc_80
  13. conf:
  14. http:
  15. - match:
  16. path:
  17. prefix: "/api"
  18. split:
  19. - weight: 90
  20. destination:
  21. kuma.io/service: backend_default_svc_80
  22. version: '1.0'
  23. - weight: 10
  24. destination:
  25. kuma.io/service: backend_default_svc_80
  26. version: '2.0'
  27. destination: # default rule is applied when endpoint does not match any rules in http section
  28. kuma.io/service: backend_default_svc_80
  29. version: '1.0'
  1. type: TrafficRoute
  2. name: api-split
  3. mesh: default
  4. sources:
  5. - match:
  6. kuma.io/service: frontend_default_svc_80
  7. destinations:
  8. - match:
  9. kuma.io/service: backend_default_svc_80
  10. conf:
  11. http:
  12. - match:
  13. path:
  14. prefix: "/api"
  15. split:
  16. - weight: 90
  17. destination:
  18. kuma.io/service: backend_default_svc_80
  19. version: '1.0'
  20. - weight: 10
  21. destination:
  22. kuma.io/service: backend_default_svc_80
  23. version: '2.0'
  24. destination: # default rule is applied when endpoint does not match any rules in http section
  25. kuma.io/service: backend_default_svc_80
  26. version: '1.0'

In order to use L7 Traffic Split, we need to mark the destination service with kuma.io/protocol: http.

L7 Traffic Modification

We can use TrafficRoute to modify outgoing requests, by setting new path or changing request and response headers.

Here is an example of a TrafficRoute that adds x-custom-header with value xyz when frontend_default_svc_80 tries to consume backend_default_svc_80.

  1. apiVersion: kuma.io/v1alpha1
  2. kind: TrafficRoute
  3. mesh: default
  4. metadata:
  5. name: add-header
  6. spec:
  7. sources:
  8. - match:
  9. kuma.io/service: frontend_default_svc_80
  10. destinations:
  11. - match:
  12. kuma.io/service: backend_default_svc_80
  13. conf:
  14. http:
  15. - match:
  16. path:
  17. prefix: "/"
  18. modify:
  19. requestHeader:
  20. add:
  21. - name: x-custom-header
  22. value: xyz
  23. destination:
  24. kuma.io/service: backend_default_svc_80
  25. destination:
  26. kuma.io/service: backend_default_svc_80
  1. type: TrafficRoute
  2. name: add-header
  3. mesh: default
  4. sources:
  5. - match:
  6. kuma.io/service: frontend_default_svc_80
  7. destinations:
  8. - match:
  9. kuma.io/service: backend_default_svc_80
  10. conf:
  11. http:
  12. - match:
  13. path:
  14. prefix: "/"
  15. modify:
  16. requestHeader:
  17. add:
  18. - name: x-custom-header
  19. value: xyz
  20. destination:
  21. kuma.io/service: backend_default_svc_80
  22. destination:
  23. kuma.io/service: backend_default_svc_80

In order to use L7 Traffic Modification, we need to mark the destination service with kuma.io/protocol: http.

L7 Traffic Rerouting

We can use TrafficRoute to modify outgoing requests, by setting new path or changing request and response headers.

Here is an example of a TrafficRoute that redirect traffic to offers_default_svc_80 when frontend_default_svc_80 is trying to consume backend_default_svc_80 on /offers endpoint.

  1. apiVersion: kuma.io/v1alpha1
  2. kind: TrafficRoute
  3. mesh: default
  4. metadata:
  5. name: http-reroute
  6. spec:
  7. sources:
  8. - match:
  9. kuma.io/service: frontend_default_svc_80
  10. destinations:
  11. - match:
  12. kuma.io/service: backend_default_svc_80
  13. conf:
  14. http:
  15. - match:
  16. path:
  17. prefix: "/offers"
  18. destination:
  19. kuma.io/service: offers_default_svc_80
  20. destination:
  21. kuma.io/service: backend_default_svc_80
  1. type: TrafficRoute
  2. name: http-reroute
  3. mesh: default
  4. sources:
  5. - match:
  6. kuma.io/service: frontend_default_svc_80
  7. destinations:
  8. - match:
  9. kuma.io/service: backend_default_svc_80
  10. conf:
  11. http:
  12. - match:
  13. path:
  14. prefix: "/offers"
  15. destination:
  16. kuma.io/service: offers_default_svc_80
  17. destination:
  18. kuma.io/service: backend_default_svc_80

In order to use L7 Traffic Rerouting, we need to mark the destination service with kuma.io/protocol: http.

Load balancer types

There are different load balancing algorithms that can be used to determine how traffic is routed to the destinations. By default TrafficRoute uses the roundRobin load balancer, but more options are available:

  • roundRobin is a simple algorithm in which each available upstream host is selected in round robin order.

    Example:

    1. loadBalancer:
    2. roundRobin: {}
  • leastRequest uses different algorithms depending on whether the hosts have the same or different weights. It has a single configuration field choiceCount, which denotes the number of random healthy hosts from which the host with the fewer active requests will be chosen.

    Example:

    1. loadBalancer:
    2. leastRequest:
    3. choiceCount: 8
  • ringHash implements consistent hashing to the upstream hosts. It has the following fields:

    • hashFunction the hash function used to hash the hosts onto the ketama ring. Can be XX_HASH or MURMUR_HASH_2.
    • minRingSize minimum hash ring size.
    • maxRingSize maximum hash ring size.

    Example:

    1. loadBalancer:
    2. ringHash:
    3. hashFunction: "MURMUR_HASH_2"
    4. minRingSize: 64
    5. maxRingSize: 1024
  • random selects a random available host.

    Example:

    1. loadBalancer:
    2. random: {}
  • maglev implements consistent hashing to upstream hosts

    Example:

    1. loadBalancer:
    2. maglev: {}