[FEATURE] Timing and threshold fields for liveness and readiness probes
Nobody has claimed this yet.
- Dominant language
- Makefile
- Stars
- 8.1k
- Forks
- 2.1k
- PR merge metrics
- No merged PRs in 30d
Description
Detailed description
Right now a probe can only say how to check (httpGet or exec), not when or how often. The containerProbe definition has no timing fields at all:
containers:
main:
image: my-slow-app
livenessProbe:
httpGet:
path: /healthz
port: 8080
For anything that takes more than a second or two to start (a JVM service, Rails, something loading a model or warming a cache), this is a real problem. With no way to set an initial delay, the implementation falls back to its default, and on Kubernetes that means the liveness probe starts hitting /healthz almost immediately, fails, and the container gets killed and restarted before it ever finishes booting. The workload crash-loops, and there's nothing in the Score file you can do about it.
The only workaround today is to drop into patch-templates and hand-write the probe, which is exactly the platform-specific detail Score is supposed to keep me away from.
I'd like to add the standard probe timing and threshold fields to containerProbe, so they apply to both livenessProbe and readinessProbe:
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 2
failureThreshold: 3
All optional, all with the usual defaults, so existing files don't change.
Context
This is the missing half of a feature the spec already has. Probes have been in for a while, and exec was added recently in #114, but without timing they only really work for apps that start instantly. Most real workloads don't.
I think these fields belong in the spec rather than in each implementation, for the same reason that came up in #124: if a setting is required for the workload to actually run, it can't be left to the implementation to guess. An app that needs a 30 second start-up grace will crash-loop without it, whichever implementation runs it. That's a property of the workload, not the platform.
And unlike some platform-specific settings, these map cleanly everywhere. Both reference implementations already support all of them natively:
| Score | Kubernetes | Docker Compose healthcheck |
|---|---|---|
initialDelaySeconds |
initialDelaySeconds |
start_period |
periodSeconds |
periodSeconds |
interval |
timeoutSeconds |
timeoutSeconds |
timeout |
failureThreshold |
failureThreshold |
retries |
So there's no new platform surface to invent here. It's wiring up fields that both targets already have.
Possible implementation
Add the fields to the shared containerProbe definition, so both livenessProbe and readinessProbe pick them up. They sit next to httpGet/exec, which is where Kubernetes keeps them too.
"containerProbe": {
"type": "object",
"description": "The probe definition. At least one of 'httpGet' or 'exec' must be specified. The execProbe should be preferred if the Score implementation supports both types.",
"additionalProperties": false,
"properties": {
"httpGet": { "$ref": "#/$defs/httpProbe" },
"exec": { "$ref": "#/$defs/execProbe" },
"initialDelaySeconds": {
"description": "Number of seconds after the container has started before the probe is first initiated. Defaults to 0.",
"type": "integer",
"minimum": 0
},
"periodSeconds": {
"description": "How often, in seconds, to run the probe. Defaults to 10.",
"type": "integer",
"minimum": 1
},
"timeoutSeconds": {
"description": "Number of seconds after which the probe times out. Defaults to 1.",
"type": "integer",
"minimum": 1
},
"failureThreshold": {
"description": "Number of consecutive failures before the probe is considered failed. Defaults to 3.",
"type": "integer",
"minimum": 1
}
},
"anyOf": [
{ "required": ["httpGet"] },
{ "required": ["exec"] }
]
}
The defaults match the common Kubernetes ones, so files that don't set them keep working exactly as they do today. Rollout is the usual path:
- add the fields to
containerProbe, plus an example insamples/score-full.yaml -
score-gostruct and parsing -
score-composemaps them to the healthcheck block (start_period,interval,timeout,retries) -
score-k8smaps them straight onto the probe fields
Additional information
One field I left out of the set above on purpose: successThreshold. Kubernetes has it, but Docker Compose healthchecks don't, and Kubernetes forces it to 1 for liveness probes anyway. So it's the one field that wouldn't map everywhere. I'm fine either way: leave it out to keep the set fully portable, or add it and document that it's readiness-only and ignored where there's no equivalent.
Two smaller calls I'm happy to follow your lead on:
- Whether to put upper bounds on any of these (say a sane cap on
timeoutSeconds) or just keepminimumand leave the rest to the implementation. - Whether the defaults live in the field descriptions or are left for each implementation to document.
This is backward compatible, so like the ports/resources one I think it can stay in v1b1. Happy to bring it to the next community meeting first if you'd rather talk it through before any PR.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the shared containerProbe definition and the example in samples/score-full.yaml, then trace how probe fields are parsed in score-go and rendered by score-compose and score-k8s. Add the four portable timing and threshold fields, preserving existing defaults, and verify the sample and both implementation mappings cover livenessProbe and readinessProbe.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- docker-compose, go, json, kubernetes, yaml
- Domain
- devops, infrastructure
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 64/100