Judge how a module says it is ready, beside whether it stays up (hq ADR 0240, to-be 48 Phase B)
Liveness alone could not see a web application whose port was open and whose program ran while every request hung for eleven hours (issue 145). A resource now carries the `health` its module declared: the engine makes http and tcp looks itself from the machine to the endpoint's published port, reads a unit's readiness from the show it already makes, hands an exec command or the image's own check to the runtime as the container's check with the declared timing and reads its state from the inspect it already makes, and asks a module's tool on its own node tools. Starting until the check passed, unhealthy once its looks after the grace fail the declared number of times; never more looks than the measured budget; nothing restarted. The statement says contract 2, which tells the controller this engine may be sent the field.
This commit is contained in:
+18
-2
@@ -1164,6 +1164,11 @@ func runLink(ctx context.Context, opts options) error {
|
||||
// And whether what it runs stays up, looked at on its own clock and said when it changes (novox/hq
|
||||
// ADR 0240) — between applies, which is when a container crash-loops.
|
||||
if judging != nil {
|
||||
// The looks it makes itself — http, tcp, a module's own tool — each at its declared interval,
|
||||
// spaced to the budget (ADR 0240 Phase B); a tool is asked of this machine's node tools over the
|
||||
// link open at the time.
|
||||
judging.Probes = &liveness.Probes{AskTool: queue.AskTool}
|
||||
go judging.Probe(aside)
|
||||
go judgeWhatRuns(aside, judging, queue, say)
|
||||
}
|
||||
// And the core builds this host placed are judged, whichever host placed them (to-be 45 §8).
|
||||
@@ -1373,6 +1378,7 @@ func judgeWhatRuns(ctx context.Context, j *liveness.Judge, queue *link.Queue, sa
|
||||
defer ticker.Stop()
|
||||
var lastSaid time.Time
|
||||
owed := true
|
||||
spaced := 1.0
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
@@ -1381,6 +1387,14 @@ func judgeWhatRuns(ctx context.Context, j *liveness.Judge, queue *link.Queue, sa
|
||||
}
|
||||
st, changed := j.Look(ctx)
|
||||
owed = owed || changed
|
||||
// Never more looks than the budget (ADR 0240): said when the engine has to space its own out.
|
||||
if sp := j.Spacing(); sp != spaced {
|
||||
if sp > 1 {
|
||||
say(fmt.Sprintf("the declared health checks here would cost more than %d looks a minute; the engine's "+
|
||||
"own looks are spaced %.1f times their declared interval", liveness.Budget, sp))
|
||||
}
|
||||
spaced = sp
|
||||
}
|
||||
since := time.Since(lastSaid)
|
||||
if !owed && !(!st.Healthy() && since >= sayUnhealthyAgain) && since < sayAnyway {
|
||||
continue
|
||||
@@ -1401,11 +1415,13 @@ func judgeWhatRuns(ctx context.Context, j *liveness.Judge, queue *link.Queue, sa
|
||||
|
||||
// healthAsReported is a statement as the report and the event carry it.
|
||||
func healthAsReported(st liveness.Statement) *link.Health {
|
||||
h := &link.Health{Contract: link.LivenessContract, At: st.At.UTC(), Resources: []link.ResourceHealth{}}
|
||||
// ReadinessContract: this engine reads a resource's declared `health` and judges it (ADR 0240 Phase
|
||||
// B), which is what tells the controller it may be sent the field.
|
||||
h := &link.Health{Contract: link.ReadinessContract, At: st.At.UTC(), Resources: []link.ResourceHealth{}}
|
||||
for _, r := range st.Resources {
|
||||
h.Resources = append(h.Resources, link.ResourceHealth{Module: r.Module, Resource: r.ID, Kind: r.Kind,
|
||||
Target: r.Target, State: r.State, Reason: r.Reason, Since: r.Since.UTC(), Streak: r.Streak,
|
||||
Restarts: r.Restarts})
|
||||
Restarts: r.Restarts, Check: r.CheckOf(), Needs: r.NeedsOf()})
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user