From 884135eae5a655c69891eedfaa0290e1b381d4fd Mon Sep 17 00:00:00 2001 From: Mark Anderson Date: Fri, 4 Jun 2021 18:54:31 -0700 Subject: [PATCH] Docs for Unix Domain Sockets (#10252) * Docs for Unix Domain Sockets There are a number of cases where a user might wish to either 1) expose a service through a Unix Domain Socket in the filesystem ('downstream') or 2) connect to an upstream service by a local unix domain socket (upstream). As of Consul (1.10-beta2) we've added new syntax and support to configure the Envoy proxy to support this To connect to a service via local Unix Domain Socket instead of a port, add local_bind_socket_path and optionally local_bind_socket_mode to the upstream config for a service: upstreams = [ { destination_name = "service-1" local_bind_socket_path = "/tmp/socket_service_1" local_bind_socket_mode = "0700" ... } ... ] This will cause Envoy to create a socket with the path and mode provided, and connect that to service-1 The mode field is optional, and if omitted will use the default mode for Envoy. This is not applicable for abstract sockets. See https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/address.proto#envoy-v3-api-msg-config-core-v3-pipe for details NOTE: These options conflict the local_bind_socket_port and local_bind_socket_address options. We can bind to an port or we can bind to a socket, but not both. To expose a service listening on a Unix Domain socket to the service mesh use either the 'socket_path' field in the service definition or the 'local_service_socket_path' field in the proxy definition. These fields are analogous to the 'port' and 'service_port' fields in their respective locations. services { name = "service-2" socket_path = "/tmp/socket_service_2" ... } OR proxy { local_service_socket_path = "/tmp/socket_service_2" ... } There is no mode field since the service is expected to create the socket it is listening on, not the Envoy proxy. Again, the socket_path and local_service_socket_path fields conflict with address/port and local_service_address/local_service_port configuration entries. Set up a simple service mesh with dummy services: socat -d UNIX-LISTEN:/tmp/downstream.sock,fork UNIX-CONNECT:/tmp/upstream.sock socat -v tcp-l:4444,fork exec:/bin/cat services { name = "sock_forwarder" id = "sock_forwarder.1" socket_path = "/tmp/downstream.sock" connect { sidecar_service { proxy { upstreams = [ { destination_name = "echo-service" local_bind_socket_path = "/tmp/upstream.sock" config { passive_health_check { interval = "10s" max_failures = 42 } } } ] } } } } services { name = "echo-service" port = 4444 connect = { sidecar_service {} } Kind = "ingress-gateway" Name = "ingress-service" Listeners = [ { Port = 8080 Protocol = "tcp" Services = [ { Name = "sock_forwarder" } ] } ] consul agent -dev -enable-script-checks -config-dir=./consul.d consul connect envoy -sidecar-for sock_forwarder.1 consul connect envoy -sidecar-for echo-service -admin-bind localhost:19001 consul config write ingress-gateway.hcl consul connect envoy -gateway=ingress -register -service ingress-service -address '{{ GetInterfaceIP "eth0" }}:8888' -admin-bind localhost:19002 netcat 127.0.0.1 4444 netcat 127.0.0.1 8080 Signed-off-by: Mark Anderson * fixup Unix capitalization Signed-off-by: Mark Anderson * Update website/content/docs/connect/registration/service-registration.mdx Co-authored-by: Blake Covarrubias * Provide examples in hcl and json Signed-off-by: Mark Anderson * Apply suggestions from code review Co-authored-by: Blake Covarrubias * One more fixup for docs Signed-off-by: Mark Anderson Co-authored-by: Blake Covarrubias --- .../registration/service-registration.mdx | 139 +++++++++++++++++- website/content/docs/discovery/services.mdx | 2 + 2 files changed, 140 insertions(+), 1 deletion(-) diff --git a/website/content/docs/connect/registration/service-registration.mdx b/website/content/docs/connect/registration/service-registration.mdx index 496387b6fe..cf88ceb94e 100644 --- a/website/content/docs/connect/registration/service-registration.mdx +++ b/website/content/docs/connect/registration/service-registration.mdx @@ -81,6 +81,7 @@ registering a proxy instance. "destination_service_id": "redis1", "local_service_address": "127.0.0.1", "local_service_port": 9090, + "local_service_socket_path": "/tmp/redis.sock", "mode": "transparent", "transparent_proxy": {}, "config": {}, @@ -117,11 +118,15 @@ registering a proxy instance. Defaults to the port advertised by the service instance identified by `destination_service_id` if it exists otherwise it may be empty in responses. +- `local_service_socket_path` - The path of a Unix domain socket to connect to the local application + instance. This is created by the application. This conflicts with `local_service_address` + and `local_service_port`. This is only supported when using Envoy for the proxy. + - `mode` `(string: "")` Beta - One of \`direct\` or \`transparent\`. Added in v1.10.0. - `"transparent"` - represents that inbound and outbound application traffic is being captured and redirected through the proxy. This mode does not enable the traffic redirection itself. Instead it signals Consul to configure Envoy as if traffic is already being redirected. - - `"direct"` - represents that the proxy's listeners must be dialed directly by the local + - `"direct"` - represents that the proxy's listeners must be dialed directly by the local application and other proxies. - `""` - Default mode. The default mode will be `"direct"` if no other configuration applies. The order of precedence for setting the mode is @@ -166,6 +171,8 @@ followed by documentation for each attribute. "datacenter": "dc1", "local_bind_address": "127.0.0.1", "local_bind_port": 1234, + "local_bind_socket_path": "/tmp/redis_5678.sock", + "local_bind_socket_mode": "0700", "config": {}, "mesh_gateway": { "mode": "local" @@ -195,6 +202,12 @@ followed by documentation for each attribute. - `local_bind_address` `(string: "")` - Specifies the address to bind a local listener to for the application to make outbound connections to this upstream. Defaults to `127.0.0.1`. +- `local_bind_socket_path` `(string: "")` - Specifies the path at which to bind a Unix + domain socket listener for the application to make outbound connections to + this upstream. This conflicts with specifying the local_bind_port + or local_bind_address. This is only supported when using Envoy as a proxy. +- `local_bind_socket_mode` `(string: "")` - Specifies the (optional) Unix octal + file permissions to use for the socket. - `destination_type` `(string: "")` - Specifies the type of discovery query to use to find an instance to connect to. Valid values are `service` or `prepared_query`. Defaults to `service`. @@ -353,3 +366,127 @@ registrations](/docs/agent/services#service-definition-parameter-case). the listener to be set up. If the port is not free then Envoy will not expose a listener for the path, but the proxy registration will not fail. - `protocol` `(string: "http")` - Sets the protocol of the listener. One of `http` or `http2`. For gRPC use `http2`. + +### Unix Domain Sockets Beta + +The following examples show additional configuration for Unix domain sockets. + +Added in v1.10.0. + +To connect to a service via local Unix Domain Socket instead of a +port, add `local_bind_socket_path` and optionally `local_bind_socket_mode` +to the upstream config for a service: + + + + +```hcl +upstreams = [ + { + destination_name = "service-1" + local_bind_socket_path = "/tmp/socket_service_1" + local_bind_socket_mode = "0700" + } +] +``` + + + + +```json +"upstreams": [ + { + "destination_name": "service-1", + "local_bind_socket_path": "/tmp/socket_service_1", + "local_bind_socket_mode": "0700" + } +] +``` + + + + +This will cause Envoy to create a socket with the path and mode +provided, and connect that to service-1. + +The mode field is optional, and if omitted will use the default mode +for Envoy. This is not applicable for abstract sockets. See the +[Envoy documentation](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/core/v3/address.proto#envoy-v3-api-msg-config-core-v3-pipe) +for details. + +-> These options conflict with the `local_bind_socket_port` and +`local_bind_socket_address` options. For a given upstream the proxy can bind either to an IP port or +a Unix socket, but not both. + +Similarly to expose a service listening on a Unix Domain socket to the service +mesh, use either the `socket_path` field in the service definition or the +`local_service_socket_path` field in the proxy definition. These +fields are analogous to the `port` and `service_port` fields in their +respective locations. + + + +```hcl +services { + name = "service-2" + socket_path = "/tmp/socket_service_2" +} +``` + + + + +```json +"services": { + "name": "service-2", + "socket_path": "/tmp/socket_service_2" +} +``` + + + +Or in the proxy definition: + + + +```hcl +services { + name = "socket_service_2" + connect { + sidecar_service { + proxy { + name = "service-2" + local_service_socket_path = "/tmp/socket_service_2" + ... + } + } + } +} +``` + + + + +```json +"services": { + "name": "socket_service_2", + "connect": { + "sidecar_service": { + "proxy": { + "name": "service-2", + "local_service_socket_path": "/tmp/socket_service_2" + ... + } + } + } +} +``` + + + + +There is no mode field since the service is expected to create the +socket it is listening on, not the Envoy proxy. +Again, the `socket_path` and `local_service_socket_path` fields conflict +with `address`/`port` and `local_service_address`/`local_service_port` +configuration options. diff --git a/website/content/docs/discovery/services.mdx b/website/content/docs/discovery/services.mdx index 3485c852b2..c5ea29708c 100644 --- a/website/content/docs/discovery/services.mdx +++ b/website/content/docs/discovery/services.mdx @@ -54,6 +54,7 @@ example shows all possible fields, but note that only a few are required. } }, "port": 8000, + "socket_path: "/tmp/redis.sock", "enable_tag_override": false, "checks": [ { @@ -68,6 +69,7 @@ example shows all possible fields, but note that only a few are required. "destination_service_id": "redis1", "local_service_address": "127.0.0.1", "local_service_port": 9090, + "local_service_socket_path": "/tmp/redis.sock", "mode": "transparent", "transparent_proxy": { "outbound_listener_port": 22500