Initial revisin of healthchecker, inspired by HAProxy
This commit is contained in:
76
internal/prober/tcp.go
Normal file
76
internal/prober/tcp.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package prober
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"net"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"git.ipng.ch/ipng/vpp-maglev/internal/health"
|
||||
)
|
||||
|
||||
// TCPProbe performs a TCP connect to cfg.Target:cfg.Port inside the healthcheck
|
||||
// netns. If cfg.TCP.SSL is true a TLS handshake is performed after connect,
|
||||
// making this an L6 check (useful for smtps, imaps, etc.).
|
||||
// Plain connect returns L4OK/L4TOUT/L4CON.
|
||||
// TLS handshake returns L6OK/L6TOUT/L6RSP (on top of an L4OK connect).
|
||||
func TCPProbe(ctx context.Context, cfg ProbeConfig) health.ProbeResult {
|
||||
port := cfg.Port
|
||||
if port == 0 {
|
||||
port = 80
|
||||
}
|
||||
addr := net.JoinHostPort(cfg.Target.String(), strconv.Itoa(int(port)))
|
||||
|
||||
doTLS := cfg.TCP != nil && cfg.TCP.SSL
|
||||
var serverName string
|
||||
var insecureSkipVerify bool
|
||||
if cfg.TCP != nil {
|
||||
serverName = cfg.TCP.ServerName
|
||||
insecureSkipVerify = cfg.TCP.InsecureSkipVerify
|
||||
}
|
||||
|
||||
var result health.ProbeResult
|
||||
err := inNetns(cfg.HealthCheckNetns, func() error {
|
||||
dialer := &net.Dialer{Timeout: cfg.Timeout}
|
||||
if cfg.ProbeSrc != nil {
|
||||
dialer.LocalAddr = &net.TCPAddr{IP: cfg.ProbeSrc}
|
||||
}
|
||||
conn, err := dialer.DialContext(ctx, "tcp", addr)
|
||||
if err != nil {
|
||||
if isTimeout(err) {
|
||||
result = health.ProbeResult{OK: false, Layer: health.LayerL4, Code: "L4TOUT", Detail: err.Error()}
|
||||
} else {
|
||||
result = health.ProbeResult{OK: false, Layer: health.LayerL4, Code: "L4CON", Detail: err.Error()}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if !doTLS {
|
||||
conn.Close()
|
||||
result = health.ProbeResult{OK: true, Layer: health.LayerL4, Code: "L4OK"}
|
||||
return nil
|
||||
}
|
||||
|
||||
// TLS handshake.
|
||||
tlsConn := tls.Client(conn, tlsConfig(serverName, insecureSkipVerify))
|
||||
tlsConn.SetDeadline(time.Now().Add(cfg.Timeout)) //nolint:errcheck
|
||||
if err := tlsConn.HandshakeContext(ctx); err != nil {
|
||||
tlsConn.Close()
|
||||
if isTimeout(err) {
|
||||
result = health.ProbeResult{OK: false, Layer: health.LayerL6, Code: "L6TOUT", Detail: err.Error()}
|
||||
} else {
|
||||
result = health.ProbeResult{OK: false, Layer: health.LayerL6, Code: "L6RSP", Detail: err.Error()}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
tlsConn.Close()
|
||||
result = health.ProbeResult{OK: true, Layer: health.LayerL6, Code: "L6OK"}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return health.ProbeResult{OK: false, Layer: health.LayerL4, Code: "L4CON", Detail: err.Error()}
|
||||
}
|
||||
return result
|
||||
}
|
||||
Reference in New Issue
Block a user