syntax = "proto3"; package envoy.service.health.v3; import "envoy/config/cluster/v3/cluster.proto"; import "envoy/config/core/v3/address.proto"; import "envoy/config/core/v3/base.proto"; import "envoy/config/core/v3/health_check.proto"; import "envoy/config/endpoint/v3/endpoint_components.proto"; import "google/api/annotations.proto"; import "google/protobuf/duration.proto"; import "envoy/annotations/deprecation.proto"; import "udpa/annotations/status.proto"; import "udpa/annotations/versioning.proto"; option java_package = "io.envoyproxy.envoy.service.health.v3"; option java_outer_classname = "HdsProto"; option java_multiple_files = true; option go_package = "github.com/envoyproxy/go-control-plane/envoy/service/health/v3;healthv3"; option java_generic_services = true; option (udpa.annotations.file_status).package_version_status = ACTIVE; // [#protodoc-title: Health discovery service (HDS)] // HDS is Health Discovery Service. It compliments Envoy’s health checking // service by designating this Envoy to be a healthchecker for a subset of hosts // in the cluster. The status of these health checks will be reported to the // management server, where it can be aggregated etc and redistributed back to // Envoy through EDS. service HealthDiscoveryService { // 1. Envoy starts up and if its can_healthcheck option in the static // bootstrap config is enabled, sends HealthCheckRequest to the management // server. It supplies its capabilities (which protocol it can health check // with, what zone it resides in, etc.). // 2. In response to (1), the management server designates this Envoy as a // healthchecker to health check a subset of all upstream hosts for a given // cluster (for example upstream Host 1 and Host 2). It streams // HealthCheckSpecifier messages with cluster related configuration for all // clusters this Envoy is designated to health check. Subsequent // HealthCheckSpecifier message will be sent on changes to: // a. Endpoints to health checks // b. Per cluster configuration change // 3. Envoy creates a health probe based on the HealthCheck config and sends // it to endpoint(ip:port) of Host 1 and 2. Based on the HealthCheck // configuration Envoy waits upon the arrival of the probe response and // looks at the content of the response to decide whether the endpoint is // healthy or not. If a response hasn't been received within the timeout // interval, the endpoint health status is considered TIMEOUT. // 4. Envoy reports results back in an EndpointHealthResponse message. // Envoy streams responses as often as the interval configured by the // management server in HealthCheckSpecifier. // 5. The management Server collects health statuses for all endpoints in the // cluster (for all clusters) and uses this information to construct // EndpointDiscoveryResponse messages. // 6. Once Envoy has a list of upstream endpoints to send traffic to, it load // balances traffic to them without additional health checking. It may // use inline healthcheck (i.e. consider endpoint UNHEALTHY if connection // failed to a particular endpoint to account for health status propagation // delay between HDS and EDS). // By default, can_healthcheck is true. If can_healthcheck is false, Cluster // configuration may not contain HealthCheck message. // TODO(htuch): How is can_healthcheck communicated to CDS to ensure the above // invariant? // TODO(htuch): Add @amb67's diagram. rpc StreamHealthCheck(stream HealthCheckRequestOrEndpointHealthResponse) returns (stream HealthCheckSpecifier) { } // TODO(htuch): Unlike the gRPC version, there is no stream-based binding of // request/response. Should we add an identifier to the HealthCheckSpecifier // to bind with the response? rpc FetchHealthCheck(HealthCheckRequestOrEndpointHealthResponse) returns (HealthCheckSpecifier) { option (google.api.http).post = "/v3/discovery:health_check"; option (google.api.http).body = "*"; } } // Defines supported protocols etc, so the management server can assign proper // endpoints to healthcheck. message Capability { option (udpa.annotations.versioning).previous_message_type = "envoy.service.discovery.v2.Capability"; // Different Envoy instances may have different capabilities (e.g. Redis) // and/or have ports enabled for different protocols. enum Protocol { HTTP = 0; TCP = 1; REDIS = 2; } repeated Protocol health_check_protocols = 1; } message HealthCheckRequest { option (udpa.annotations.versioning).previous_message_type = "envoy.service.discovery.v2.HealthCheckRequest"; config.core.v3.Node node = 1; Capability capability = 2; } message EndpointHealth { option (udpa.annotations.versioning).previous_message_type = "envoy.service.discovery.v2.EndpointHealth"; config.endpoint.v3.Endpoint endpoint = 1; config.core.v3.HealthStatus health_status = 2; } // Group endpoint health by locality under each cluster. message LocalityEndpointsHealth { config.core.v3.Locality locality = 1; repeated EndpointHealth endpoints_health = 2; } // The health status of endpoints in a cluster. The cluster name and locality // should match the corresponding fields in ClusterHealthCheck message. message ClusterEndpointsHealth { string cluster_name = 1; repeated LocalityEndpointsHealth locality_endpoints_health = 2; } message EndpointHealthResponse { option (udpa.annotations.versioning).previous_message_type = "envoy.service.discovery.v2.EndpointHealthResponse"; // Deprecated - Flat list of endpoint health information. repeated EndpointHealth endpoints_health = 1 [deprecated = true, (envoy.annotations.deprecated_at_minor_version) = "3.0"]; // Organize Endpoint health information by cluster. repeated ClusterEndpointsHealth cluster_endpoints_health = 2; } message HealthCheckRequestOrEndpointHealthResponse { option (udpa.annotations.versioning).previous_message_type = "envoy.service.discovery.v2.HealthCheckRequestOrEndpointHealthResponse"; oneof request_type { HealthCheckRequest health_check_request = 1; EndpointHealthResponse endpoint_health_response = 2; } } message LocalityEndpoints { option (udpa.annotations.versioning).previous_message_type = "envoy.service.discovery.v2.LocalityEndpoints"; config.core.v3.Locality locality = 1; repeated config.endpoint.v3.Endpoint endpoints = 2; } // The cluster name and locality is provided to Envoy for the endpoints that it // health checks to support statistics reporting, logging and debugging by the // Envoy instance (outside of HDS). For maximum usefulness, it should match the // same cluster structure as that provided by EDS. // [#next-free-field: 6] message ClusterHealthCheck { option (udpa.annotations.versioning).previous_message_type = "envoy.service.discovery.v2.ClusterHealthCheck"; string cluster_name = 1; repeated config.core.v3.HealthCheck health_checks = 2; repeated LocalityEndpoints locality_endpoints = 3; // Optional map that gets filtered by :ref:`health_checks.transport_socket_match_criteria ` // on connection when health checking. For more details, see // :ref:`config.cluster.v3.Cluster.transport_socket_matches `. repeated config.cluster.v3.Cluster.TransportSocketMatch transport_socket_matches = 4; // Optional configuration used to bind newly established upstream connections. // If the address and port are empty, no bind will be performed. config.core.v3.BindConfig upstream_bind_config = 5; } message HealthCheckSpecifier { option (udpa.annotations.versioning).previous_message_type = "envoy.service.discovery.v2.HealthCheckSpecifier"; repeated ClusterHealthCheck cluster_health_checks = 1; // The default is 1 second. google.protobuf.Duration interval = 2; } // [#not-implemented-hide:] Not configuration. Workaround c++ protobuf issue with importing // services: https://github.com/google/protobuf/issues/4221 and protoxform to upgrade the file. message HdsDummy { }