feat(pool-manager): add /healthz handler for k8s liveness/readiness probes (#56)
- pool-manager/main.go: serve HTTP on :3990 with /healthz that does a 2s-context pgxpool.Ping; returns 200 OK when Postgres is reachable, 503 otherwise. Runs alongside the existing signal-blocking main loop. - pool-manager/Dockerfile: distroless static-debian12 image exposing :3990. - pool-manager/.gitignore: skip built pool-manager binary and *.tar. Refs marcus/engineering#56 Closes marcus/engineering#56
This commit is contained in:
parent
19d82d5c41
commit
45b3b62389
3 changed files with 69 additions and 0 deletions
2
pool-manager/.gitignore
vendored
Normal file
2
pool-manager/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
pool-manager
|
||||
*.tar
|
||||
8
pool-manager/Dockerfile
Normal file
8
pool-manager/Dockerfile
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
FROM gcr.io/distroless/static-debian12:nonroot
|
||||
WORKDIR /app
|
||||
COPY pool-manager /app/pool-manager
|
||||
EXPOSE 3990
|
||||
ENV PORT=3990 \
|
||||
HOST=0.0.0.0 \
|
||||
POOL_CONFIG=/app/harness.yaml
|
||||
ENTRYPOINT ["./pool-manager"]
|
||||
59
pool-manager/main.go
Normal file
59
pool-manager/main.go
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"scobleclaw.dev/pool-manager/poolq"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgxpool"
|
||||
)
|
||||
|
||||
func main() {
|
||||
dsn := os.Getenv("PG_DSN")
|
||||
if dsn == "" {
|
||||
dsn = "host=/var/run/postgresql dbname=postgres sslmode=disable"
|
||||
}
|
||||
|
||||
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
|
||||
defer stop()
|
||||
|
||||
pool, err := pgxpool.New(ctx, dsn)
|
||||
if err != nil {
|
||||
log.Fatalf("pgxpool: %v", err)
|
||||
}
|
||||
defer pool.Close()
|
||||
|
||||
if err := poolq.EnsureSchema(ctx, pool); err != nil {
|
||||
log.Fatalf("ensure schema: %v", err)
|
||||
}
|
||||
|
||||
log.Println("pool-manager schema ensured, poolq ready")
|
||||
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/healthz", func(w http.ResponseWriter, r *http.Request) {
|
||||
pingCtx, cancel := context.WithTimeout(r.Context(), 2*time.Second)
|
||||
defer cancel()
|
||||
if err := pool.Ping(pingCtx); err != nil {
|
||||
w.WriteHeader(http.StatusServiceUnavailable)
|
||||
fmt.Fprintln(w, "pg unreachable:", err)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprintln(w, "ok")
|
||||
})
|
||||
go func() {
|
||||
log.Println("healthz server listening on :3990")
|
||||
if err := http.ListenAndServe(":3990", mux); err != nil {
|
||||
log.Fatalf("healthz server: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
<-ctx.Done()
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue