healthcheck

package module
v0.0.0-...-64e5089 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 12, 2022 License: Apache-2.0 Imports: 6 Imported by: 1

README

healthcheck

build Quality Gate Status Coverage Code Smells Go Report Card GoDoc

Healthcheck is a library for implementing Kubernetes liveness and readiness probe handlers in your Go application.

Features

  • Integrates easily with Kubernetes. This library explicitly separates liveness vs. readiness checks instead of lumping everything into a single category of check.

  • Supports asynchronous checks, which run in a background goroutine at a fixed interval. These are useful for expensive checks that you don't want to add latency to the liveness and readiness endpoints.

  • Includes a follow useful checks:

    • DNS
    • TCP
    • HTTP
    • database
    • Go runtime.
    • GC max pause
    • MongoDb
    • Redis

Usage

See the GoDoc examples for more detail.

Install dependency

go get -u github.com/gsdenys/healthcheck

Import the package

import "github.com/gsdenys/healthcheck"

Create a healthcheck.Handler:

health := healthcheck.NewHandler()

Configure some application-specific liveness checks (whether the app itself is unhealthy):

// Our app is not happy if we've got more than 100 goroutines running.
health.AddLivenessCheck("goroutine-threshold", goroutine.Count(100))

Configure some application-specific readiness checks (whether the app is ready to serve requests):

// Our app is not ready if we can't resolve our upstream dependency in DNS.
health.AddReadinessCheck("upstream-dep-dns", dns.Resolve("upstream.example.com", 50*time.Millisecond))

// Our app is not ready if we can't connect to our database (`var DB *sql.DB`) in <1s.
health.AddReadinessCheck("database", db.Ping(DB, 1*time.Second))

Expose the /live and /ready endpoints over HTTP (on port 8086):

go func() {
	httpError := http.ListenAndServe("0.0.0.0:8086", health)

	if httpError != nil {
		log.Println("While serving HTTP: ", httpError)
	}
}()

Configure your Kubernetes container with HTTP liveness and readiness probes see the (Kubernetes documentation) for more detail:

# this is a bare bones example
# copy and paste livenessProbe and readinessProbe as appropriate for your app
apiVersion: v1
kind: Pod
metadata:
  name: healthcheck-example
spec:
  containers:
  - name: liveness
    image: your-registry/your-container

    # define a liveness probe that checks every 5 seconds, starting after 5 seconds
    livenessProbe:
      httpGet:
        path: /live
        port: 8086
      initialDelaySeconds: 5
      periodSeconds: 5

    # define a readiness probe that checks every 5 seconds
    readinessProbe:
      httpGet:
        path: /ready
        port: 8086
      periodSeconds: 5

If one of your readiness checks fails, Kubernetes will stop routing traffic to that pod within a few seconds (depending on periodSeconds and other factors).

If one of your liveness checks fails or your app becomes totally unresponsive, Kubernetes will restart your container.

HTTP Endpoints

When you run go http.ListenAndServe("0.0.0.0:8086", health), two HTTP endpoints are exposed:

  • /live: liveness endpoint (HTTP 200 if healthy, HTTP 503 if unhealthy)
  • /ready: readiness endpoint (HTTP 200 if healthy, HTTP 503 if unhealthy)

Pass the ?full=1 query parameter to see the full check results as JSON. These are omitted by default for performance.

Documentation

Overview

Package healthcheck helps you implement Kubernetes liveness and readiness checks for your application. It supports synchronous and asynchronous (background) checks. It can optionally report each check's status as a set of Prometheus gauge metrics for cluster-wide monitoring and alerting.

It also includes a small library of generic checks for DNS, TCP, and HTTP reachability as well as Goroutine usage.

Example
// Create a Handler that we can use to register liveness and readiness checks.
health := NewHandler()

// Add a readiness check to make sure an upstream dependency resolves in DNS.
// If this fails we don't want to receive requests, but we shouldn't be restarted or rescheduled.
upstreamHost := "upstream.example.com"
health.AddReadinessCheck("upstream-dep-dns", dns.Resolve(upstreamHost, 50*time.Millisecond))

// Add a liveness check to detect Goroutine leaks. If this fails we want to be restarted/rescheduled.
health.AddLivenessCheck("goroutine-threshold", goroutine.Count(100))

// Serve http://0.0.0.0:8080/live and http://0.0.0.0:8080/ready endpoints.
go func() {
	httpError := http.ListenAndServe("0.0.0.0:8080", health)

	if httpError != nil {
		log.Println("While serving HTTP: ", httpError)
	}
}()

// Make a request to the readiness endpoint and print the response.
fmt.Print(dumpRequest(health, "GET", "/ready"))
Output:

HTTP/1.1 503 Service Unavailable
Connection: close
Content-Type: application/json; charset=utf-8

{}
Example (Database)
// Connect to a database/sql database
DB := connectToDatabase()

// Create a Handler that we can use to register liveness and readiness checks.
health := NewHandler()

// Add a readiness check to we don't receive requests unless we can reach
// the DB with a ping in <1 second.
health.AddReadinessCheck("database", db.Ping(DB, 1*time.Second))

// Serve http://0.0.0.0:8080/live and http://0.0.0.0:8080/ready endpoints.
go func() {
	httpError := http.ListenAndServe("0.0.0.0:8080", health)

	if httpError != nil {
		log.Println("While serving HTTP: ", httpError)
	}
}()

// Make a request to the readiness endpoint and print the response.
fmt.Print(dumpRequest(health, "GET", "/ready?full=1"))
Output:

HTTP/1.1 200 OK
Connection: close
Content-Type: application/json; charset=utf-8

{
    "database": "OK"
}

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Handler

type Handler interface {
	// The Handler is an http.Handler, so it can be exposed directly and handle
	// /live and /ready endpoints.
	http.Handler

	// AddLivenessCheck adds a check that indicates that this instance of the
	// application should be destroyed or restarted. A failed liveness check
	// indicates that this instance is unhealthy, not some upstream dependency.
	// Every liveness check is also included as a readiness check.
	AddLivenessCheck(name string, check checks.Check)

	// AddReadinessCheck adds a check that indicates that this instance of the
	// application is currently unable to serve requests because of an upstream
	// or some transient failure. If a readiness check fails, this instance
	// should no longer receiver requests, but should not be restarted or
	// destroyed.
	AddReadinessCheck(name string, check checks.Check)

	// LiveEndpoint is the HTTP handler for just the /live endpoint, which is
	// useful if you need to attach it into your own HTTP handler tree.
	LiveEndpoint(http.ResponseWriter, *http.Request)

	// ReadyEndpoint is the HTTP handler for just the /ready endpoint, which is
	// useful if you need to attach it into your own HTTP handler tree.
	ReadyEndpoint(http.ResponseWriter, *http.Request)
}

Handler is an http.Handler with additional methods that register health and readiness checks. It handles handle "/live" and "/ready" HTTP endpoints.

func NewHandler

func NewHandler() Handler

NewHandler creates a new basic Handler

Directories

Path Synopsis
db
dns
gc
tcp

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL