Skip to content

Commit

Permalink
ready: Add option to enable envoy readiness endpoint from worker
Browse files Browse the repository at this point in the history
/ready endpoint used by emissary is using the admin port (8001 by
default).
This generates a problem during config reloads with large configs as the
admin thread is blocking so the /ready endpoint can be very slow to
answer (in the order of several seconds, even more).

The problem is described in this envoy issue:
envoyproxy/envoy#16425

This change is trying to fix the /ready endpoint problem.
The /ready endpoint can be exposed in the worker pool by adding a
listener+ health check http filter.
This way, the /ready endpoint is fast and it is not blocked by any
config reload or blocking admin operation as it depends on the worker
pool.

Future changes will allow to use this endpoint with diagd and the go
code as well so they get a fast /ready endpoint and they do not use the
admin port.

This listener is disabled by default. the config "read_port" can be used
to set the port and enable this new listener on envoy.
  • Loading branch information
jfrabaute authored and tsuna committed Jun 19, 2022
1 parent 153af3e commit 00aedd8
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 0 deletions.
1 change: 1 addition & 0 deletions cmd/ambex/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ import (
_ "github.com/datawire/ambassador/pkg/api/envoy/config/filter/http/buffer/v2"
_ "github.com/datawire/ambassador/pkg/api/envoy/config/filter/http/ext_authz/v2"
_ "github.com/datawire/ambassador/pkg/api/envoy/config/filter/http/gzip/v2"
_ "github.com/datawire/ambassador/pkg/api/envoy/config/filter/http/health_check/v2"
_ "github.com/datawire/ambassador/pkg/api/envoy/config/filter/http/lua/v2"
_ "github.com/datawire/ambassador/pkg/api/envoy/config/filter/http/rate_limit/v2"
_ "github.com/datawire/ambassador/pkg/api/envoy/config/filter/http/rbac/v2"
Expand Down
1 change: 1 addition & 0 deletions python/ambassador/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ class Constants:
SERVICE_PORT_HTTP = 8080
SERVICE_PORT_HTTPS = 8443
ADMIN_PORT = 8001
READY_PORT = -1
DIAG_PORT = 8877
DIAG_PORT_ALT = 8004
SERVICE_PORT_AGENT = 9900
2 changes: 2 additions & 0 deletions python/ambassador/envoy/v2/v2config.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

from ..common import EnvoyConfig, sanitize_pre_json
from .v2admin import V2Admin
from .v2ready import V2Ready
from .v2bootstrap import V2Bootstrap
from .v2route import V2Route
from .v2listener import V2Listener, V2TCPListener
Expand Down Expand Up @@ -64,6 +65,7 @@ def __init__(self, ir: 'IR', cache: Optional[Cache]=None) -> None:
V2Cluster.generate(self)
V2StaticResources.generate(self)
V2Bootstrap.generate(self)
V2Ready.generate(self)

def as_dict(self) -> Dict[str, Any]:
bootstrap_config, ads_config, clustermap = self.split_config()
Expand Down
86 changes: 86 additions & 0 deletions python/ambassador/envoy/v2/v2ready.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# Copyright 2021 Datawire. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License

from typing import TYPE_CHECKING

from .v2listener import V2Listener

if TYPE_CHECKING:
from . import V2Config # pragma: no cover


class V2Ready(dict):

@classmethod
def generate(cls, config: 'V2Config') -> None:
# Inject the ready listener to the list of listeners if enabled
rport = config.ir.aconf.module_lookup('ambassador', 'ready_port', -1)
if rport <= 0:
return

ready_listener = {
'name': 'ambassador-listener-ready-%s' % rport,
'address': {
'socket_address': {
'address': '0.0.0.0', # Todo: Change this to 127.0.0.1 or make it a parameter
'port_value': rport,
'protocol': 'TCP'
}
},
'filter_chains': [
{
'filters': [
{
'name': 'envoy.filters.network.http_connection_manager',
'typed_config': {
'@type': 'type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager',
"access_log": [
{
"name": "envoy.access_loggers.file",
"typed_config": {
"@type": "type.googleapis.com/envoy.config.accesslog.v2.FileAccessLog",
"format": "ACCESS [%START_TIME%] \"%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%\" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% \"%REQ(X-FORWARDED-FOR)%\" \"%REQ(USER-AGENT)%\" \"%REQ(X-REQUEST-ID)%\" \"%REQ(:AUTHORITY)%\" \"%UPSTREAM_HOST%\"\n",
"path": "/dev/fd/1"
}
}
],
'stat_prefix': 'ready_http',
'route_config': {
'name': 'local_route'
},
'http_filters': [
{
'name': 'envoy.filters.http.health_check',
'typed_config': {
'@type': 'type.googleapis.com/envoy.config.filter.http.health_check.v2.HealthCheck',
'pass_through_mode': False,
'headers': [
{
'name': ':path',
'exact_match': '/ready'
}
]
}
},
{
'name': 'envoy.filters.http.router'
}
]
}
}
]
}
]
}
config.static_resources['listeners'].append(ready_listener)
2 changes: 2 additions & 0 deletions python/ambassador/ir/irambassador.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class IRAmbassador (IRResource):
AModTransparentKeys: ClassVar = [
'add_linkerd_headers',
'admin_port',
'ready_port'
'auth_enabled',
'allow_chunked_length',
'buffer_limit_bytes',
Expand Down Expand Up @@ -120,6 +121,7 @@ def __init__(self, ir: 'IR', aconf: Config,
ir=ir, aconf=aconf, rkey=rkey, kind=kind, name=name,
service_port=Constants.SERVICE_PORT_HTTP,
admin_port=Constants.ADMIN_PORT,
ready_port=Constants.READY_PORT,
auth_enabled=None,
enable_ipv6=False,
envoy_log_type="text",
Expand Down

0 comments on commit 00aedd8

Please sign in to comment.