# cluster

## Summary

A `cluster` handles final routing of each request to its intended target. Each `cluster` can have 0 or more instances defined, which are simply the host:port pairs of the targets. Instances within a cluster can be statically configured when the object is created, or dynamically loaded through the [service discovery mechanisms](https://greymatter.gitbook.io/grey-matter-documentation/1.3/usage/discovery)

### Features

* Static or dynamic instances
* Circuit breakers
* Health Checks
* Outlier Detection
* Outgoing SSL configuration
  * Directly via SSL certs on disk
  * Through SPIFFE/SPIRE and Envoy SDS
* Load balancing policy and its configurations

### Example Object

```javascript
{
    "zone_key": "default-zone",
    "cluster_key": "catalog-service",
    "name": "service",
    "instances": [
        {
            "host": "localhost",
            "port": 8080
        }
    ],
    "circuit_breakers": {
      "max_connections": 500,
      "max_requests": 500
    },
    "outlier_detection": null,
    "health_checks": [],
    "lb_policy": "",
    "http2_protocol_options": {},
    "secret": {
        "secret_key": "",
        "secret_name": "",
        "secret_validation_name": "",
        "subject_alt_name": "",
        "ecdh_curves": null,
        "set_current_client_cert_details": {
            "uri": false
        },
        "checksum": ""
    }
}
```

### TLS Configuration

To require TLS on the `cluster` object, an additional field, `require_tls` must be set to true.

There is also an optional `ssl_config` field, which can be set to specify it's configuration. The Cluster SSL Config Object appears as follows:

```javascript
"ssl_config": {
  "cipher_filter": "",
  "protocols": [],
  "cert_key_pairs": null,
  "trust_file": "",
  "crl": null,
  "sni": null
}
```

The Cluster SSL Configuration is used to populate an [UpstreamTlsContext](https://www.envoyproxy.io/docs/envoy/v1.15.0/api-v3/extensions/transport_sockets/tls/v3/tls.proto#extensions-transport-sockets-tls-v3-upstreamtlscontext) for the Envoy Cluster.

The `sni` field for a `cluster` accepts a string that the Envoy cluster uses to specify Server Name Indication when creating TLS backend connections.

To specify a minimum and maximum TLS protocol version, set the `protocols` field to one of the following: `"TLSv1_0"`, `"TLSv1_1"`, `"TLSv1_2"`, `"TLSv1_3"`. If one protocol is specified, it will be set as both the minimum and maximum protocol versions in Envoy. If more than one protocol version is specified in the list, the lowest will set the minimum TLS protocol version and the highest will set the maximum TLS protocol version. If this field is left empty, Envoy will choose the default TLS version.

The `cipher_filter` field takes a colon `:` delimited string to set a specified cipher list for TLS. This populates Envoys `cipher_suites` field.

Specifying the path to a `trust_file` is optional. If a path is specified, it will be added to the UpstreamTlsContext for verifying a presented server certificate. Otherwise, the server certificate will not be verified.

If the Cluster connects to a service that is secured via TLS, the `trust_file` will need to contain the root CA and any intermediate certificates to authenticate the sidecar as a client of the service. If you're unfamiliar with generating certificates, [OpenSSL Certificate Authority](https://jamielinux.com/docs/openssl-certificate-authority/introduction.html) is a great primer. The end result is that you have all trust certificates required by the service in a single file, the `trust_file`.

Specifying a `crl` (a PEM-encoded certificate revocation list) is also optional, and may be added by pointing to a path on disk to a CRL file from the `crl.filename` field or by specifying CRLs directly through the `crl.inline_string` field. More details on CRL configuration can be found in the [Cluster SSL Configuration Guide](https://greymatter.gitbook.io/grey-matter-documentation/1.3/reference/api/fabric-api/cluster-ssl-config#crl).

### Secret Configuration for SPIFFE/SPIRE

To configure the service to use SPIFFE/SPIRE on its egress, you must set a `secret` on the cluster. In the same form as above, `require_tls` **must** be set to true. Note that if both an `ssl_config` and a `secret` are set on a cluster, the secret will override the ssl configuration. An example secret object is as follows:

```javascript
"secret" : {
  "secret_key": "secret-{{.service.serviceName}}-secret",
  "secret_name": "spiffe://{{ .Values.global.spire.trustDomain }}/{{.service.serviceName}}/mTLS",
  "secret_validation_name": "spiffe://{{ .Values.global.spire.trustDomain }}",
  "ecdh_curves": [
    "X25519:P-256:P-521:P-384"
  ]
}
```

This object will configure Envoy to use Secret Discovery Service to fetch SPIFFE certificates from the configured path specified as an environment variable `SPIRE_PATH` in `gm-proxy`. For information on how Envoy's SDS works, see the [docs](https://www.envoyproxy.io/docs/envoy/v1.15.0/configuration/security/secret). The `secret_key` specifies the name of the secret to fetch. `secret_name` should be the [SPIFFE Id](https://github.com/spiffe/spiffe/blob/master/standards/SPIFFE-ID.md#2-spiffe-identity) of your certificate. `secret_validation_name` will set the validation context for the sds secret config.

### Envoy Reference

* [Envoy Cluster Reference](https://www.envoyproxy.io/docs/envoy/v1.15.0/api-v3/config/cluster/v3/cluster.proto#cluster-configuration)

### Fields

#### `cluster_key`

A unique key used to identify this particular cluster configuration. This key is used in [routes](https://greymatter.gitbook.io/grey-matter-documentation/1.3/reference/api/fabric-api/route) or [shared\_rules](https://greymatter.gitbook.io/grey-matter-documentation/1.3/reference/api/fabric-api/shared_rules) to handle routing of traffic to an endpoint.

#### `zone_key`

The zone in which this object will live. It will only be able to be referenced by objects or sent to Sidecars that live in the same zone.

#### `name`

The name of the service that this cluster is addressing. This field has different behavior depending on whether this cluster will be pulling [instances](#instances) from service discovery or wether they will be manually inserted.

To use [service discovery](#../discovery/instances.md), the `name` field should match the announced [`XDS_CLUSTER`](#../discovery/registration#cluster) of another service running in the mesh. If no match is found, from the service not yet being online or a incorrect spelling, the instance array will remain empty. If a match is found, then the discovered instances will be populated in the array. More information can be found in the [service discovery](#../discovery/README.md) pages.

To specify [instances](#instances) manually, with no service discovery, the `name` field must be set to a value that does not match an announced service. If a match is found, the manually inserted `instances` will be overridden.

#### `require_tls`

If `true`, this cluster will only accept HTTPS connections. In this case, one of the [secret](#secret) or [ssl\_config](#sslconfig) fields should be set. If `false`, this cluster will only accept plaintext HTTP connections.

#### `secret`

Configure SSL certificate configuration through Envoy's SDS (Secret Discovery Service)

#### `ssl_config`

[Cluster SSL configuration](https://greymatter.gitbook.io/grey-matter-documentation/1.3/reference/api/fabric-api/cluster/cluster-ssl-config) for this cluster.

#### `instances`

An array of instances that this cluster will use to route requests. Can be either manually inserted, or automatically populated from service discovery.

The order of how instances will handle requests is governed by the [lb\_policy](#lbpolicy) field.

#### `circuit_breakers`

Default and high priority [circuit breakers](https://greymatter.gitbook.io/grey-matter-documentation/1.3/reference/api/fabric-api/cluster/circuit-breakers)

#### `outlier_detection`

[outlier detection](https://greymatter.gitbook.io/grey-matter-documentation/1.3/reference/api/fabric-api/cluster/outlier-detection)

#### `health_checks`

Array of [health checks](https://greymatter.gitbook.io/grey-matter-documentation/1.3/reference/api/fabric-api/cluster/health-check).

#### `lb_policy`

Defaults to `least_request`, supported options are: `round_robin`, `least_request`, `ring_hash`, `random`, `maglev`, and `cluster_provided`. Both the `least_request` and `ring_hash` options require additional configuration in the [`least_request_lb_config` field](#least_request_lb_config) and [`ring_hash_lb_config` field](#ring_hash_lb_config) respectively.

[Envoy Load Balancing Policy](https://www.envoyproxy.io/docs/envoy/v1.15.0/api-v3/config/cluster/v3/cluster.proto#envoy-v3-api-enum-config-cluster-v3-cluster-lbpolicy).

#### `http2_protocol_options`

Options for configuring HTTP/2. Setting this field indicates that the cluster supports HTTP/2, and **must** be set in order to upgrade connections to HTTP/2.

[Envoy HTTP/2 Options](https://www.envoyproxy.io/docs/envoy/v1.15.0/api-v3/config/core/v3/protocol.proto#envoy-v3-api-msg-config-core-v3-http2protocoloptions).

#### `ring_hash_lb_config`

Specific configuration for the [RingHash load balancing policy](https://www.envoyproxy.io/docs/envoy/v1.15.0/intro/arch_overview/upstream/load_balancing/load_balancers#arch-overview-load-balancing-types-ring-hash). Must be set if the `lb_policy` field is set to `ring_hash`.

[Envoy RingHash Load Balancing Policy](https://www.envoyproxy.io/docs/envoy/v1.15.0/api-v3/config/cluster/v3/cluster.proto#envoy-v3-api-msg-config-cluster-v3-cluster-ringhashlbconfig)

#### `original_dst_lb_config`

This is a special purpose load balancer that can only be used with an original destination cluster. No other load balancing policy can be used with original destination clusters.

[Envoy Original Destination Load Balancing Policy](https://www.envoyproxy.io/docs/envoy/v1.15.0/api-v3/config/cluster/v3/cluster.proto#config-cluster-v3-cluster-originaldstlbconfig)

#### `least_request_lb_config`

Specific configuration for the [LeastRequest load balancing policy](https://www.envoyproxy.io/docs/envoy/v1.15.0/intro/arch_overview/upstream/load_balancing/load_balancers#arch-overview-load-balancing-types-least-request). Must be set if the `lb_policy` field is set to `least_request`.

[Envoy LeastRequest Load Balancing Policy](https://www.envoyproxy.io/docs/envoy/v1.15.0/api-v3/config/cluster/v3/cluster.proto#config-cluster-v3-cluster-leastrequestlbconfig)

#### `common_lb_config`

Common configuration for all load balancer implementations.

[Envoy Common Load Balancer Configuration](https://www.envoyproxy.io/docs/envoy/v1.15.0/api-v3/config/cluster/v3/cluster.proto#config-cluster-v3-cluster-commonlbconfig)

#### `checksum`

An API calculated checksum. Can be used to verify that the API contains the expected object before performing a write.
