feat(coderd): add DERP healthcheck (#6936)

This commit is contained in:
Colin Adler
2023-04-03 01:28:42 -05:00
committed by GitHub
parent f4d16a1ae5
commit 7738274b3e
14 changed files with 1925 additions and 5 deletions

View File

@ -33,6 +33,7 @@ import (
"tailscale.com/derp/derphttp"
"tailscale.com/tailcfg"
"tailscale.com/types/key"
"tailscale.com/util/singleflight"
"cdr.dev/slog"
"github.com/coder/coder/buildinfo"
@ -46,6 +47,7 @@ import (
"github.com/coder/coder/coderd/database/dbtype"
"github.com/coder/coder/coderd/gitauth"
"github.com/coder/coder/coderd/gitsshkey"
"github.com/coder/coder/coderd/healthcheck"
"github.com/coder/coder/coderd/httpapi"
"github.com/coder/coder/coderd/httpmw"
"github.com/coder/coder/coderd/metricscache"
@ -123,7 +125,10 @@ type Options struct {
TemplateScheduleStore schedule.TemplateScheduleStore
// AppSigningKey denotes the symmetric key to use for signing app tickets.
// The key must be 64 bytes long.
AppSigningKey []byte
AppSigningKey []byte
HealthcheckFunc func(ctx context.Context) (*healthcheck.Report, error)
HealthcheckTimeout time.Duration
HealthcheckRefresh time.Duration
// APIRateLimit is the minutely throughput rate limit per user or ip.
// Setting a rate limit <0 will disable the rate limiter across the entire
@ -235,6 +240,19 @@ func New(options *Options) *API {
if len(options.AppSigningKey) != 64 {
panic("coderd: AppSigningKey must be 64 bytes long")
}
if options.HealthcheckFunc == nil {
options.HealthcheckFunc = func(ctx context.Context) (*healthcheck.Report, error) {
return healthcheck.Run(ctx, &healthcheck.ReportOptions{
DERPMap: options.DERPMap.Clone(),
})
}
}
if options.HealthcheckTimeout == 0 {
options.HealthcheckTimeout = 30 * time.Second
}
if options.HealthcheckRefresh == 0 {
options.HealthcheckRefresh = 10 * time.Minute
}
siteCacheDir := options.CacheDir
if siteCacheDir != "" {
@ -293,6 +311,7 @@ func New(options *Options) *API {
Auditor: atomic.Pointer[audit.Auditor]{},
TemplateScheduleStore: atomic.Pointer[schedule.TemplateScheduleStore]{},
Experiments: experiments,
healthCheckGroup: &singleflight.Group[string, *healthcheck.Report]{},
}
if options.UpdateCheckOptions != nil {
api.updateChecker = updatecheck.New(
@ -718,6 +737,7 @@ func New(options *Options) *API {
)
r.Get("/coordinator", api.debugCoordinator)
r.Get("/health", api.debugDeploymentHealth)
})
})
@ -773,6 +793,8 @@ type API struct {
// Experiments contains the list of experiments currently enabled.
// This is used to gate features that are not yet ready for production.
Experiments codersdk.Experiments
healthCheckGroup *singleflight.Group[string, *healthcheck.Report]
}
// Close waits for all WebSocket connections to drain before returning.