--- layout: docs page_title: Service Splitter - Configuration Entry Reference description: >- The service splitter configuration entry kind defines how to divide service mesh traffic between service instances. Use the reference guide to learn about `""service-splitter""` config entry parameters and how it can be used for traffic management behaviors like canary rollouts, blue green deployment, and load balancing across environments. --- # Service Splitter Configuration Entry -> **v1.8.4+:** On Kubernetes, the `ServiceSplitter` custom resource is supported in Consul versions 1.8.4+.<br /> **v1.6.0+:** On other platforms, this config entry is supported in Consul versions 1.6.0+. The `service-splitter` config entry kind (`ServiceSplitter` on Kubernetes) controls how to split incoming Connect requests across different subsets of a single service (like during staged canary rollouts), or perhaps across different services (like during a v2 rewrite or other type of codebase migration). If no splitter config is defined for a service it is assumed 100% of traffic flows to a service with the same name and discovery continues on to the resolution stage. ## Interaction with other Config Entries - Service splitter config entries are a component of [L7 Traffic Management](/docs/connect/l7-traffic). - Service splitter config entries are restricted to only services that define their protocol as http-based via a corresponding [`service-defaults`](/docs/connect/config-entries/service-defaults) config entry or globally via [`proxy-defaults`](/docs/connect/config-entries/proxy-defaults) . - Any split destination that specifies a different `Service` field and omits the `ServiceSubset` field is eligible for further splitting should a splitter be configured for that other service, otherwise resolution proceeds according to any configured [`service-resolver`](/docs/connect/config-entries/service-resolver). ## UI Once a `service-splitter` is successfully entered, you can view it in the UI. Service routers, service splitters, and service resolvers can all be viewed by clicking on your service then switching to the _routing_ tab. ![screenshot of service splitter in the UI](/img/l7-routing/Splitter.png) ## Sample Config Entries ### Two subsets of same service Split traffic between two subsets of the same service: <CodeTabs tabs={[ "HCL", "Kubernetes YAML", "JSON" ]}> ```hcl Kind = "service-splitter" Name = "web" Splits = [ { Weight = 90 ServiceSubset = "v1" }, { Weight = 10 ServiceSubset = "v2" }, ] ``` ```yaml apiVersion: consul.hashicorp.com/v1alpha1 kind: ServiceSplitter metadata: name: web spec: splits: - weight: 90 serviceSubset: v1 - weight: 10 serviceSubset: v2 ``` ```json { "Kind": "service-splitter", "Name": "web", "Splits": [ { "Weight": 90, "ServiceSubset": "v1" }, { "Weight": 10, "ServiceSubset": "v2" } ] } ``` </CodeTabs> ### Two different services Split traffic between two services: <CodeTabs tabs={[ "HCL", "Kubernetes YAML", "JSON" ]}> ```hcl Kind = "service-splitter" Name = "web" Splits = [ { Weight = 50 # will default to service with same name as config entry ("web") }, { Weight = 50 Service = "web-rewrite" }, ] ``` ```yaml apiVersion: consul.hashicorp.com/v1alpha1 kind: ServiceSplitter metadata: name: web spec: splits: - weight: 50 # will default to service with same name as config entry ("web") - weight: 50 service: web-rewrite ``` ```json { "Kind": "service-splitter", "Name": "web", "Splits": [ { "Weight": 50 }, { "Weight": 50, "Service": "web-rewrite" } ] } ``` </CodeTabs> ### Set HTTP Headers Split traffic between two subsets with extra headers added so clients can tell which version: <CodeTabs tabs={[ "HCL", "Kubernetes YAML", "JSON" ]}> ```hcl Kind = "service-splitter" Name = "web" Splits = [ { Weight = 90 ServiceSubset = "v1" ResponseHeaders { Set { "X-Web-Version": "v1" } } }, { Weight = 10 ServiceSubset = "v2" ResponseHeaders { Set { "X-Web-Version": "v2" } } }, ] ``` ```yaml apiVersion: consul.hashicorp.com/v1alpha1 kind: ServiceSplitter metadata: name: web spec: splits: - weight: 90 serviceSubset: v1 responseHeaders: set: x-web-version: v1 - weight: 10 serviceSubset: v2 responseHeaders: set: x-web-version: v2 ``` ```json { "Kind": "service-splitter", "Name": "web", "Splits": [ { "Weight": 90, "ServiceSubset": "v1", "ResponseHeaders": { "Set": { "X-Web-Version": "v1" } } }, { "Weight": 10, "ServiceSubset": "v2", "ResponseHeaders": { "Set": { "X-Web-Version": "v2" } } } ] } ``` </CodeTabs> ## Available Fields <ConfigEntryReference keys={[ { name: 'apiVersion', description: 'Must be set to `consul.hashicorp.com/v1alpha1`', hcl: false, }, { name: 'Kind', description: { hcl: 'Must be set to `service-splitter`', yaml: 'Must be set to `ServiceSplitter`', }, }, { name: 'Name', description: 'Set to the name of the service being configured.', type: 'string: <required>', yaml: false, }, { name: 'Namespace', type: `string: "default"`, enterprise: true, description: 'Specifies the namespace to which the configuration entry will apply.', yaml: false, }, { name: 'Partition', type: `string: "default"`, enterprise: true, description: 'Specifies the admin partition to which the configuration entry will apply.', yaml: false, }, { name: 'Meta', type: 'map<string|string>: nil', description: 'Specifies arbitrary KV metadata pairs. Added in Consul 1.8.4.', yaml: false, }, { name: 'metadata', children: [ { name: 'name', description: 'Set to the name of the service being configured.', }, { name: 'namespace', description: 'If running Consul Open Source, the namespace is ignored (see [Kubernetes Namespaces in Consul OSS](/docs/k8s/crds#consul-oss)). If running Consul Enterprise see [Kubernetes Namespaces in Consul Enterprise](/docs/k8s/crds#consul-enterprise) for more details.', }, ], hcl: false, }, { name: 'Splits', type: 'array<ServiceSplit>', description: 'Defines how much traffic to send to which set of service instances during a traffic split. The sum of weights across all splits must add up to 100.', children: [ { name: 'weight', type: 'float32: 0', description: 'A value between 0 and 100 reflecting what portion of traffic should be directed to this split. The smallest representable weight is 1/10000 or .01%', }, { name: 'Service', type: 'string: ""', description: 'The service to resolve instead of the default.', }, { name: 'ServiceSubset', type: 'string: ""', description: { hcl: "A named subset of the given service to resolve instead of one defined as that service's `DefaultSubset`. If empty the default subset is used.", yaml: "A named subset of the given service to resolve instead of one defined as that service's `defaultSubset`. If empty the default subset is used.", }, }, { name: 'Namespace', enterprise: true, type: 'string: ""', description: 'The namespace to resolve the service from instead of the current namespace. If empty, the current namespace is used.', }, { name: 'Partition', enterprise: true, type: 'string: ""', description: 'The admin partition to resolve the service from instead of the current partition. If empty, the current partition is used.', }, { name: 'RequestHeaders', type: 'HTTPHeaderModifiers: <optional>', description: `A set of [HTTP-specific header modification rules](/docs/connect/config-entries/service-router#httpheadermodifiers) that will be applied to requests routed to this split. This cannot be used with a \`tcp\` listener.`, }, { name: 'ResponseHeaders', type: 'HTTPHeaderModifiers: <optional>', description: `A set of [HTTP-specific header modification rules](/docs/connect/config-entries/service-router#httpheadermodifiers) that will be applied to responses from this split. This cannot be used with a \`tcp\` listener.`, }, ], }, ]} /> ## ACLs Configuration entries may be protected by [ACLs](/docs/security/acl). Reading a `service-splitter` config entry requires `service:read` on the resource. Creating, updating, or deleting a `service-splitter` config entry requires `service:write` on the resource and `service:read` on any other service referenced by name in these fields: - [`Splits[].Service`](#service)