Toggle /ping to artificially return unhealthy response on SIGTERM during requestAcceptGraceTimeout interval
This commit is contained in:
parent
9699dc2a85
commit
5792a19b97
5 changed files with 45 additions and 4 deletions
|
@ -85,3 +85,7 @@ Note the dedicated port `:8082` for `/ping`.
|
|||
|
||||
In the above example, it is _very_ important to create a named dedicated entry point, and do **not** include it in `defaultEntryPoints`.
|
||||
Otherwise, you are likely to expose _all_ services via this entry point.
|
||||
|
||||
### Using ping for external Load-balancer rotation health check
|
||||
|
||||
If you are running traefik behind a external Load-balancer, and want to configure rotation health check on the Load-balancer to take a traefik instance out of rotation gracefully, you can configure [lifecycle.requestAcceptGraceTimeout](/configuration/commons.md#life-cycle) and the ping endpoint will return `503` response on traefik server termination, so that the Load-balancer can take the terminating traefik instance out of rotation, before it stops responding.
|
||||
|
|
|
@ -128,6 +128,10 @@ func (s *SimpleSuite) TestRequestAcceptGraceTimeout(c *check.C) {
|
|||
err = try.GetRequest("http://127.0.0.1:8000/service", 3*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// Check that /ping endpoint is responding with 200.
|
||||
err = try.GetRequest("http://127.0.0.1:8001/ping", 3*time.Second, try.StatusCodeIs(http.StatusOK))
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
// Send SIGTERM to Traefik.
|
||||
proc, err := os.FindProcess(cmd.Process.Pid)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
@ -143,6 +147,12 @@ func (s *SimpleSuite) TestRequestAcceptGraceTimeout(c *check.C) {
|
|||
defer resp.Body.Close()
|
||||
c.Assert(resp.StatusCode, checker.Equals, http.StatusOK)
|
||||
|
||||
// ping endpoint should now return a Service Unavailable.
|
||||
resp, err = http.Get("http://127.0.0.1:8001/ping")
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer resp.Body.Close()
|
||||
c.Assert(resp.StatusCode, checker.Equals, http.StatusServiceUnavailable)
|
||||
|
||||
// Expect Traefik to shut down gracefully once the request accepting grace
|
||||
// period has elapsed.
|
||||
waitErr := make(chan error)
|
||||
|
|
|
@ -6,6 +6,9 @@ logLevel = "DEBUG"
|
|||
[entryPoints.http]
|
||||
address = ":8000"
|
||||
|
||||
[entryPoints.traefik]
|
||||
address = ":8001"
|
||||
|
||||
[lifeCycle]
|
||||
requestAcceptGraceTimeout = "10s"
|
||||
|
||||
|
@ -20,3 +23,5 @@ logLevel = "DEBUG"
|
|||
backend = "backend"
|
||||
[frontends.frontend.routes.service]
|
||||
rule = "Path:/service"
|
||||
|
||||
[ping]
|
||||
|
|
27
ping/ping.go
27
ping/ping.go
|
@ -3,19 +3,38 @@ package ping
|
|||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"sync"
|
||||
|
||||
"github.com/containous/mux"
|
||||
)
|
||||
|
||||
//Handler expose ping routes
|
||||
// Handler expose ping routes
|
||||
type Handler struct {
|
||||
EntryPoint string `description:"Ping entryPoint" export:"true"`
|
||||
EntryPoint string `description:"Ping entryPoint" export:"true"`
|
||||
terminating bool
|
||||
lock sync.RWMutex
|
||||
}
|
||||
|
||||
// SetTerminating causes the ping endpoint to serve non 200 responses.
|
||||
func (g *Handler) SetTerminating() {
|
||||
g.lock.Lock()
|
||||
defer g.lock.Unlock()
|
||||
|
||||
g.terminating = true
|
||||
}
|
||||
|
||||
// AddRoutes add ping routes on a router
|
||||
func (g Handler) AddRoutes(router *mux.Router) {
|
||||
func (g *Handler) AddRoutes(router *mux.Router) {
|
||||
router.Methods(http.MethodGet, http.MethodHead).Path("/ping").
|
||||
HandlerFunc(func(response http.ResponseWriter, request *http.Request) {
|
||||
fmt.Fprint(response, "OK")
|
||||
g.lock.RLock()
|
||||
defer g.lock.RUnlock()
|
||||
|
||||
statusCode := http.StatusOK
|
||||
if g.terminating {
|
||||
statusCode = http.StatusServiceUnavailable
|
||||
}
|
||||
response.WriteHeader(statusCode)
|
||||
fmt.Fprint(response, http.StatusText(statusCode))
|
||||
})
|
||||
}
|
||||
|
|
|
@ -212,6 +212,9 @@ func (s *Server) StartWithContext(ctx context.Context) {
|
|||
<-ctx.Done()
|
||||
log.Info("I have to go...")
|
||||
reqAcceptGraceTimeOut := time.Duration(s.globalConfiguration.LifeCycle.RequestAcceptGraceTimeout)
|
||||
if s.globalConfiguration.Ping != nil && reqAcceptGraceTimeOut > 0 {
|
||||
s.globalConfiguration.Ping.SetTerminating()
|
||||
}
|
||||
if reqAcceptGraceTimeOut > 0 {
|
||||
log.Infof("Waiting %s for incoming requests to cease", reqAcceptGraceTimeOut)
|
||||
time.Sleep(reqAcceptGraceTimeOut)
|
||||
|
|
Loading…
Reference in a new issue