diff --git a/pkg/cmd/infra/router/template.go b/pkg/cmd/infra/router/template.go index 8b7fdabbc..072f6a1f7 100644 --- a/pkg/cmd/infra/router/template.go +++ b/pkg/cmd/infra/router/template.go @@ -563,6 +563,7 @@ func (o *TemplateRouterOptions) Run(stopCh <-chan struct{}) error { var reloadCallbacks []func() + adminSocketURL := &url.URL{Scheme: "unix", Path: "/var/lib/haproxy/run/haproxy.sock"} statsPort := o.StatsPort switch { case o.MetricsType == "haproxy" && statsPort != 0: @@ -607,7 +608,7 @@ func (o *TemplateRouterOptions) Run(stopCh <-chan struct{}) error { collector, err := haproxy.NewPrometheusCollector(haproxy.PrometheusOptions{ // Only template router customizers who alter the image should need this - ScrapeURI: env("ROUTER_METRICS_HAPROXY_SCRAPE_URI", ""), + ScrapeURI: env("ROUTER_METRICS_HAPROXY_SCRAPE_URI", adminSocketURL.String()), // Only template router customizers who alter the image should need this PidFile: env("ROUTER_METRICS_HAPROXY_PID_FILE", ""), Timeout: timeout, @@ -636,9 +637,10 @@ func (o *TemplateRouterOptions) Run(stopCh <-chan struct{}) error { return err } checkController := metrics.ControllerLive() + checkSocket := metrics.AdminSocketAvailable(adminSocketURL) liveChecks := []healthz.HealthChecker{checkController} if !(isTrue(env("ROUTER_BIND_PORTS_BEFORE_SYNC", ""))) { - liveChecks = append(liveChecks, checkBackend) + liveChecks = append(liveChecks, checkSocket) } kubeconfig, _, err := o.Config.KubeConfig() @@ -735,7 +737,7 @@ func (o *TemplateRouterOptions) Run(stopCh <-chan struct{}) error { return err } cmopts := templateplugin.ConfigManagerOptions{ - ConnectionInfo: "unix:///var/lib/haproxy/run/haproxy.sock", + ConnectionInfo: adminSocketURL.String(), CommitInterval: o.CommitInterval, BlueprintRoutes: blueprintRoutes, BlueprintRoutePoolSize: o.BlueprintRoutePoolSize, diff --git a/pkg/router/metrics/haproxy/haproxy.go b/pkg/router/metrics/haproxy/haproxy.go index 22b04ea18..dc753a574 100644 --- a/pkg/router/metrics/haproxy/haproxy.go +++ b/pkg/router/metrics/haproxy/haproxy.go @@ -732,9 +732,6 @@ func NewPrometheusCollector(opts PrometheusOptions) (*Exporter, error) { } func defaultOptions(opts PrometheusOptions) PrometheusOptions { - if len(opts.ScrapeURI) == 0 { - opts.ScrapeURI = "unix:///var/lib/haproxy/run/haproxy.sock" - } if len(opts.PidFile) == 0 { opts.PidFile = "/var/lib/haproxy/run/haproxy.pid" } diff --git a/pkg/router/metrics/health.go b/pkg/router/metrics/health.go index 90e91041b..09ae0ebf5 100644 --- a/pkg/router/metrics/health.go +++ b/pkg/router/metrics/health.go @@ -115,3 +115,34 @@ func ProxyProtocolHTTPBackendAvailable(u *url.URL) healthz.HealthChecker { return nil }) } + +// AdminSocketAvailable returns a healthz check that verifies the +// HAProxy process is alive by sending "show version" to its admin socket and +// expecting a non-empty response. +func AdminSocketAvailable(u *url.URL) healthz.HealthChecker { + return healthz.NamedCheck("admin-socket", func(_ *http.Request) error { + conn, err := net.DialTimeout("unix", u.Path, 2*time.Second) + if err != nil { + return err + } + defer conn.Close() + + conn.SetDeadline(time.Now().Add(2 * time.Second)) + + if _, err := conn.Write([]byte("show version\n")); err != nil { + return err + } + + buf := make([]byte, 10) + n, err := conn.Read(buf) + if err != nil { + return err + } + if n == 0 { + return fmt.Errorf("empty response from admin socket") + } + + log.V(4).Info("probe succeeded", "url", u.String()) + return nil + }) +}