Define health checks

This topic describes how to create different types of health checks for your services.

Overview

Health checks are configurations that verifies the health of a service or node. Health checks configurations are nested in the service block. Refer to Define Services for information about specifying other service parameters.

You can define individual health checks for your service in separate check blocks or define multiple checks in a checks block. Refer to Define multiple checks for additional information.

You can create several different kinds of checks:

  • Script checks invoke an external application that performs the health check, exits with an appropriate exit code, and potentially generates output. Script checks are one of the most common types of checks.
  • HTTP checks make an HTTP GET request to the specified URL and wait for the specified amount of time. HTTP checks are one of the most common types of checks.
  • TCP checks attempt to connect to an IP or hostname and port over TCP and wait for the specified amount of time.
  • UDP checks send UDP datagrams to the specified IP or hostname and port and wait for the specified amount of time.
  • Time-to-live (TTL) checks are passive checks that await updates from the service. If the check does not receive a status update before the specified duration, the health check enters a criticalstate.
  • Docker checks are dependent on external applications packaged with a Docker container that are triggered by calls to the Docker exec API endpoint.
  • gRPC checks probe applications that support the standard gRPC health checking protocol.
  • H2ping checks test an endpoint that uses http2. The check connects to the endpoint and sends a ping frame.
  • Alias checks represent the health state of another registered node or service.

If your network runs in a Kubernetes environment, you can sync service health information with Kubernetes health checks. Refer to Configure Health Checks for Consul on Kubernetes for details.

Registration

After defining health checks, you must register the service containing the checks with Consul. Refer to Register Services and Health Checks for additional information. If the service is already registered, you can reload the service configuration file to implement your health check. Refer to Reload for additional information.

Define multiple checks

You can define multiple checks for a service in a single checks block. The checks block contains an array of objects. The objects contain the configuration for each health check you want to implement. The following example includes two script checks named mem and cpu and an HTTP check that calls the /health API endpoint.

Multiple checks example

Multiple checks example

  1. checks = [
  2. {
  3. id = "chk1"
  4. name = "mem"
  5. args = ["/bin/check_mem", "-limit", "256MB"]
  6. interval = "5s"
  7. },
  8. {
  9. id = "chk2"
  10. name = "/health"
  11. http = "http://localhost:5000/health"
  12. interval = "15s"
  13. },
  14. {
  15. id = "chk3"
  16. name = "cpu"
  17. args = ["/bin/check_cpu"]
  18. interval = "10s"
  19. },
  20. ...
  21. ]
  1. {
  2. "checks": [
  3. {
  4. "id": "chk1",
  5. "name": "mem",
  6. "args": ["/bin/check_mem", "-limit", "256MB"],
  7. "interval": "5s"
  8. },
  9. {
  10. "id": "chk2",
  11. "name": "/health",
  12. "http": "http://localhost:5000/health",
  13. "interval": "15s"
  14. },
  15. {
  16. "id": "chk3",
  17. "name": "cpu",
  18. "args": ["/bin/check_cpu"],
  19. "interval": "10s"
  20. },
  21. ...
  22. ]
  23. }

Define initial health check status

When checks are registered against a Consul agent, they are assigned a critical status by default. This prevents services from registering as passing and entering the service pool before their health is verified. You can add the status parameter to the check definition to specify the initial state. In the following example, the check registers in a passing state:

Define initial check status example

Define initial check status example

  1. check = {
  2. id = "mem"
  3. args = ["/bin/check_mem", "-limit", "256MB"]
  4. interval = "10s"
  5. status = "passing"
  6. }
  1. {
  2. "check": [
  3. {
  4. "args": [
  5. "/bin/check_mem",
  6. "-limit",
  7. "256MB"
  8. ],
  9. "id": "mem",
  10. "interval": "10s",
  11. "status": "passing"
  12. }
  13. ]
  14. }

Script checks

Script checks invoke an external application that performs the health check, exits with an appropriate exit code, and potentially generates output data. The output of a script check is limited to 4KB. Outputs that exceed the limit are truncated.

Script checks timeout after 30 seconds by default, but you can configure a custom script check timeout value by specifying the timeout field in the check definition. When the timeout is reached on Windows, Consul waits for any child processes spawned by the script to finish. For any other system, Consul attempts to force-kill the script and any child processes it has spawned once the timeout has passed.

Script check configuration

To enable script checks, you must first enable the agent to send external requests, then configure the health check settings in the service definition:

  1. Add one of the following configurations to your agent configuration file to enable a script check:

    Security warning: Enabling non-local script checks in some configurations may introduce a known remote execution vulnerability targeted by malware. We strongly recommend enable_local_script_checks instead.

  2. Specify the script to run in the args of the check block in your service configuration file. In the following example, a check named Memory utilization invokes the check_mem.py script every 10 seconds and times out if a response takes longer than one second:

    Script check configuration

    Script check configuration

    1. service {
    2. ## ...
    3. check = {
    4. id = "mem-util"
    5. name = "Memory utilization"
    6. args = ["/usr/local/bin/check_mem.py", "-limit", "256MB"]
    7. interval = "10s"
    8. timeout = "1s"
    9. }
    10. }
    1. {
    2. "service": [
    3. {
    4. "check": {
    5. "id": "mem-util",
    6. "name": "Memory utilization",
    7. "args": ["/usr/local/bin/check_mem.py", "-limit", "256MB"],
    8. "interval": "10s",
    9. "timeout": "1s"
    10. }
    11. } ]
    12. }

Refer to Health Checks Configuration Reference for information about all health check configurations.

Script check exit codes

The following exit codes returned by the script check determine the health check status:

  • Exit code 0 - Check is passing
  • Exit code 1 - Check is warning
  • Any other code - Check is failing

Any output of the script is captured and made available in the Output field of checks included in HTTP API responses. Refer to the example described in the local service health endpoint.

HTTP checks

HTTP checks send an HTTP request to the specified URL and report the service health based on the HTTP response code. We recommend using HTTP checks over script checks that use cURL or another external process to check an HTTP operation.

HTTP check configuration

Add an http field to the check block in your service definition file and specify the HTTP address, including port number, for the check to call. All other fields are optional. Refer to Health Checks Configuration Reference for information about all health check configurations.

In the following example, an HTTP check named HTTP API on port 5000 sends a POST request to the health endpoint every 10 seconds:

HTTP check configuration

HTTP check configuration

  1. check = {
  2. id = "api"
  3. name = "HTTP API on port 5000"
  4. http = "https://localhost:5000/health"
  5. tls_server_name = ""
  6. tls_skip_verify = false
  7. method = "POST"
  8. header = {
  9. Content-Type = ["application/json"]
  10. }
  11. body = "{\"method\":\"health\"}"
  12. disable_redirects = true
  13. interval = "10s"
  14. timeout = "1s"
  15. }
  1. {
  2. "check": {
  3. "id": "api",
  4. "name": "HTTP API on port 5000",
  5. "http": "https://localhost:5000/health",
  6. "tls_server_name": "",
  7. "tls_skip_verify": false,
  8. "method": "POST",
  9. "header": { "Content-Type": ["application/json"] },
  10. "body": "{\"method\":\"health\"}",
  11. "interval": "10s",
  12. "timeout": "1s"
  13. }
  14. }

HTTP checks send GET requests by default, but you can specify another request method in the method field. You can send additional headers in the header block. The header block contains a key and an array of strings, such as {"x-foo": ["bar", "baz"]}. By default, HTTP checks timeout at 10 seconds, but you can specify a custom timeout value in the timeout field.

HTTP checks expect a valid TLS certificate by default. You can disable certificate verification by setting the tls_skip_verify field to true. When using TLS and a host name is specified in the http field, the check automatically determines the SNI from the URL. If the http field is configured with an IP address or if you want to explicitly set the SNI, specify the name in the tls_server_name field.

The check follows HTTP redirects configured in the network by default. Set the disable_redirects field to true to disable redirects.

HTTP check response codes

Responses larger than 4KB are truncated. The HTTP response determines the status of the service:

  • A 200-299 response code is healthy.
  • A 429 response code indicating too many requests is a warning.
  • All other response codes indicate a failure.

TCP checks

TCP checks establish connections to the specified IPs or hosts. If the check successfully establishes a connection, the service status is reported as success. If the IP or host does not accept the connection, the service status is reported as critical. We recommend TCP checks over script checks that use netcat or another external process to check a socket operation.

TCP check configuration

Add a tcp field to the check block in your service definition file and specify the address, including port number, for the check to call. All other fields are optional. Refer to Health Checks Configuration Reference for information about all health check configurations.

In the following example, a TCP check named SSH TCP on port 22 attempts to connect to localhost:22 every 10 seconds:

TCP check configuration

TCP check configuration

  1. check = {
  2. id = "ssh"
  3. name = "SSH TCP on port 22"
  4. tcp = "localhost:22"
  5. interval = "10s"
  6. timeout = "1s"
  7. }
  1. {
  2. "check": {
  3. "id": "ssh",
  4. "name": "SSH TCP on port 22",
  5. "tcp": "localhost:22",
  6. "interval": "10s",
  7. "timeout": "1s"
  8. }
  9. }

If a hostname resolves to an IPv4 and an IPv6 address, Consul attempts to connect to both addresses. The first successful connection attempt results in a successful check.

By default, TCP check requests timeout at 10 seconds, but you can specify a custom timeout in the timeout field.

UDP checks

UDP checks direct the Consul agent to send UDP datagrams to the specified IP or hostname and port. The check status is set to success if any response is received from the targeted UDP server. Any other result sets the status to critical.

UDP check configuration

Add a udp field to the check block in your service definition file and specify the address, including port number, for sending datagrams. All other fields are optional. Refer to Health Checks Configuration Reference for information about all health check configurations.

In the following example, a UDP check named DNS UDP on port 53 sends datagrams to localhost:53 every 10 seconds:

UDP Check

UDP Check

  1. check = {
  2. id = "dns"
  3. name = "DNS UDP on port 53"
  4. udp = "localhost:53"
  5. interval = "10s"
  6. timeout = "1s"
  7. }
  1. {
  2. "check": {
  3. "id": "dns",
  4. "name": "DNS UDP on port 53",
  5. "udp": "localhost:53",
  6. "interval": "10s",
  7. "timeout": "1s"
  8. }
  9. }

By default, UDP checks timeout at 10 seconds, but you can specify a custom timeout in the timeout field. If any timeout on read exists, the check is still considered healthy.

OSService check

OSService checks if an OS service is running on the host. OSService checks support Windows services on Windows hosts or SystemD services on Unix hosts. The check logs the service as healthy if it is running. If the service is not running, the status is logged as critical. All other results are logged with warning. A warning status indicates that the check is not reliable because an issue is preventing it from determining the health of the service.

OSService check configurations

Add an os_service field to the check block in your service definition file and specify the name of the service to check. All other fields are optional. Refer to Health Checks Configuration Reference for information about all health check configurations.

In the following example, an OSService check named svcname-001 Windows Service Health verifies that the myco-svctype-svcname-001 service is running every 10 seconds:

OSService check configuration

OSService check configuration

  1. check = {
  2. id = "myco-svctype-svcname-001"
  3. name = "svcname-001 Windows Service Health"
  4. service_id = "flash_pnl_1"
  5. os_service = "myco-svctype-svcname-001"
  6. interval = "10s"
  7. }
  1. {
  2. "check": {
  3. "id": "myco-svctype-svcname-001",
  4. "name": "svcname-001 Windows Service Health",
  5. "service_id": "flash_pnl_1",
  6. "os_service": "myco-svctype-svcname-001",
  7. "interval": "10s"
  8. }
  9. }

TTL checks

Time-to-live (TTL) checks wait for an external process to report the service’s state to a Consul /agent/check HTTP endpoint. If the check does not receive an update before the specified ttl duration, the check logs the service as critical. For example, if a healthy application is configured to periodically send a PUT request a status update to the HTTP endpoint, then the health check logs a critical state if the application is unable to send the update before the TTL expires. The check uses the following endpoints to update health information:

TTL checks also persist their last known status to disk so that the Consul agent can restore the last known status of the check across restarts. Persisted check status is valid through the end of the TTL from the time of the last check.

You can manually mark a service as unhealthy using the consul maint CLI command or agent/maintenance HTTP API endpoint, rather than waiting for a TTL health check if the ttl duration is high.

TTL check configuration

Add a ttl field to the check block in your service definition file and specify how long to wait for an update from the external process. All other fields are optional. Refer to Health Checks Configuration Reference for information about all health check configurations.

In the following example, a TTL check named Web App Status logs the application as critical if a status update is not received every 30 seconds:

TTL check configuration

TTL check configuration

  1. check = {
  2. id = "web-app"
  3. name = "Web App Status"
  4. notes = "Web app does a curl internally every 10 seconds"
  5. ttl = "30s"
  6. }
  1. {
  2. "check": {
  3. "id": "web-app",
  4. "name": "Web App Status",
  5. "notes": "Web app does a curl internally every 10 seconds",
  6. "ttl": "30s"
  7. }
  8. }

Docker checks

Docker checks invoke an application packaged within a Docker container. The application should perform a health check and exit with an appropriate exit code.

The application is triggered within the running container through the Docker exec API. You should have access to either the Docker HTTP API or the Unix socket. Consul uses the $DOCKER_HOST environment variable to determine the Docker API endpoint.

The output of a Docker check is limited to 4KB. Larger outputs are truncated.

Docker check configuration

To enable Docker checks, you must first enable the agent to send external requests, then configure the health check settings in the service definition:

  1. Add one of the following configurations to your agent configuration file to enable a Docker check:

    Security warning: Enabling non-local script checks in some configurations may introduce a known remote execution vulnerability targeted by malware. We strongly recommend enable_local_script_checks instead.

  2. Configure the following fields in the check block in your service definition file:

    • docker_container_id: The docker ps command is a common way to get the ID.
    • shell: Specifies the shell to use for performing the check. Different containers can run different shells on the same host.
    • args: Specifies the external application to invoke.
    • interval: Specifies the interval for running the check.

In the following example, a Docker check named Memory utilization invokes the check_mem.py application in container f972c95ebf0e every 10 seconds:

Docker check configuration

Docker check configuration

  1. check = {
  2. id = "mem-util"
  3. name = "Memory utilization"
  4. docker_container_id = "f972c95ebf0e"
  5. shell = "/bin/bash"
  6. args = ["/usr/local/bin/check_mem.py"]
  7. interval = "10s"
  8. }
  1. {
  2. "check": {
  3. "id": "mem-util",
  4. "name": "Memory utilization",
  5. "docker_container_id": "f972c95ebf0e",
  6. "shell": "/bin/bash",
  7. "args": ["/usr/local/bin/check_mem.py"],
  8. "interval": "10s"
  9. }
  10. }

gRPC checks

gRPC checks send a request to the specified endpoint. These checks are intended for applications that support the standard gRPC health checking protocol.

gRPC check configuration

Add a grpc field to the check block in your service definition file and specify the endpoint, including port number, for sending requests. All other fields are optional. Refer to Health Checks Configuration Reference for information about all health check configurations.

In the following example, a gRPC check named Service health status probes the entire application by sending requests to 127.0.0.1:12345 every 10 seconds:

gRPC check on entire application

gRPC check on entire application

  1. check = {
  2. id = "mem-util"
  3. name = "Service health status"
  4. grpc = "127.0.0.1:12345"
  5. grpc_use_tls = true
  6. interval = "10s"
  7. }
  1. {
  2. "check": {
  3. "id": "mem-util",
  4. "name": "Service health status",
  5. "grpc": "127.0.0.1:12345",
  6. "grpc_use_tls": true,
  7. "interval": "10s"
  8. }
  9. }

gRPC checks probe the entire gRPC server, but you can check on a specific service by adding the service identifier after the gRPC check’s endpoint using the following format: /:service_identifier.

In the following example, a gRPC check probes my_service in the application at 127.0.0.1:12345 every 10 seconds:

gRPC check for a specific service

gRPC check for a specific service

  1. check = {
  2. id = "mem-util"
  3. name = "Service health status"
  4. grpc = "127.0.0.1:12345/my_service"
  5. grpc_use_tls = true
  6. interval = "10s"
  7. }
  1. {
  2. "check": {
  3. "id": "mem-util",
  4. "name": "Service health status",
  5. "grpc": "127.0.0.1:12345/my_service",
  6. "grpc_use_tls": true,
  7. "interval": "10s"
  8. }
  9. }

TLS is disabled for gRPC checks by default. You can enable TLS by setting grpc_use_tls to true. If TLS is enabled, you must either provide a valid TLS certificate or disable certificate verification by setting the tls_skip_verify field to true.

By default, gRPC checks timeout after 10 seconds, but you can specify a custom duration in the timeout field.

H2ping checks

H2ping checks test an endpoint that uses HTTP2 by connecting to the endpoint and sending a ping frame. If the endpoint sends a response within the specified interval, the check status is set to success.

H2ping check configuration

Add an h2ping field to the check block in your service definition file and specify the HTTP2 endpoint, including port number, for the check to ping. All other fields are optional. Refer to Health Checks Configuration Reference for information about all health check configurations.

In the following example, an H2ping check named h2ping pings the endpoint at localhost:22222 every 10 seconds:

H2ping check configuration

H2ping check configuration

  1. check = {
  2. id = "h2ping-check"
  3. name = "h2ping"
  4. h2ping = "localhost:22222"
  5. interval = "10s"
  6. h2ping_use_tls = false
  7. }
  1. {
  2. "check": {
  3. "id": "h2ping-check",
  4. "name": "h2ping",
  5. "h2ping": "localhost:22222",
  6. "interval": "10s",
  7. "h2ping_use_tls": false
  8. }
  9. }

TLS is enabled by default, but you can disable TLS by setting h2ping_use_tls to false. When TLS is disabled, the Consul sends pings over h2c. When TLS is enabled, a valid certificate is required unless tls_skip_verify is set to true.

By default, H2ping checks timeout at 10 seconds, but you can specify a custom duration in the timeout field.

Alias checks

Alias checks continuously report the health state of another registered node or service. If the alias experiences errors while watching the actual node or service, the check reports acritical state. Consul updates the alias and actual node or service state asynchronously but nearly instantaneously.

For aliased services on the same agent, the check monitors the local state without consuming additional network resources. For services and nodes on different agents, the check maintains a blocking query over the agent’s connection with a current server and allows stale requests.

ACLs

For the blocking query, the alias check presents the ACL token set on the actual service or the token configured in the check definition. If neither are available, the alias check falls back to the default ACL token set for the agent. Refer to acl.tokens.default for additional information about the default ACL token.

Alias checks configuration

Add an alias_service field to the check block in your service definition file and specify the name of the service or node to alias. All other fields are optional. Refer to Health Checks Configuration Reference for information about all health check configurations.

In the following example, an alias check with the ID web-alias reports the health state of the web service:

Alias check configuration

Alias check configuration

  1. check = {
  2. id = "web-alias"
  3. alias_service = "web"
  4. }
  1. {
  2. "check": {
  3. "id": "web-alias",
  4. "alias_service": "web"
  5. }
  6. }

By default, the alias must be registered with the same Consul agent as the alias check. If the service is not registered with the same agent, you must specify "alias_node": "<node_id>" in the check configuration. If no service is specified and the alias_node field is enabled, the check aliases the health of the node. If a service is specified, the check will alias the specified service on this particular node.