mirror of https://github.com/k3s-io/k3s
commit
f88550ad5b
|
@ -13524,7 +13524,7 @@
|
|||
},
|
||||
"v1.Probe": {
|
||||
"id": "v1.Probe",
|
||||
"description": "Probe describes a liveness probe to be examined to the container.",
|
||||
"description": "Probe describes a health check to be performed against a container to determine whether it is alive or ready to recieve traffic.",
|
||||
"properties": {
|
||||
"exec": {
|
||||
"$ref": "v1.ExecAction",
|
||||
|
@ -13546,7 +13546,22 @@
|
|||
"timeoutSeconds": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"description": "Number of seconds after which liveness probes timeout. Defaults to 1 second. More info: http://releases.k8s.io/HEAD/docs/user-guide/pod-states.md#container-probes"
|
||||
"description": "Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: http://releases.k8s.io/HEAD/docs/user-guide/pod-states.md#container-probes"
|
||||
},
|
||||
"periodSeconds": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"description": "How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1."
|
||||
},
|
||||
"successThreshold": {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"description": "Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness. Minimum value is 1."
|
||||
},
|
||||
"failureThreshold": {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"description": "Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -3768,7 +3768,7 @@
|
|||
},
|
||||
"v1.Probe": {
|
||||
"id": "v1.Probe",
|
||||
"description": "Probe describes a liveness probe to be examined to the container.",
|
||||
"description": "Probe describes a health check to be performed against a container to determine whether it is alive or ready to recieve traffic.",
|
||||
"properties": {
|
||||
"exec": {
|
||||
"$ref": "v1.ExecAction",
|
||||
|
@ -3790,7 +3790,22 @@
|
|||
"timeoutSeconds": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"description": "Number of seconds after which liveness probes timeout. Defaults to 1 second. More info: http://releases.k8s.io/HEAD/docs/user-guide/pod-states.md#container-probes"
|
||||
"description": "Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: http://releases.k8s.io/HEAD/docs/user-guide/pod-states.md#container-probes"
|
||||
},
|
||||
"periodSeconds": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"description": "How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1."
|
||||
},
|
||||
"successThreshold": {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"description": "Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness. Minimum value is 1."
|
||||
},
|
||||
"failureThreshold": {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"description": "Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -3257,7 +3257,7 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
|
|||
<div class="sect2">
|
||||
<h3 id="_v1_probe">v1.Probe</h3>
|
||||
<div class="paragraph">
|
||||
<p>Probe describes a liveness probe to be examined to the container.</p>
|
||||
<p>Probe describes a health check to be performed against a container to determine whether it is alive or ready to recieve traffic.</p>
|
||||
</div>
|
||||
<table class="tableblock frame-all grid-all" style="width:100%; ">
|
||||
<colgroup>
|
||||
|
@ -3307,11 +3307,32 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
|
|||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">timeoutSeconds</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">Number of seconds after which liveness probes timeout. Defaults to 1 second. More info: <a href="http://releases.k8s.io/HEAD/docs/user-guide/pod-states.md#container-probes">http://releases.k8s.io/HEAD/docs/user-guide/pod-states.md#container-probes</a></p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: <a href="http://releases.k8s.io/HEAD/docs/user-guide/pod-states.md#container-probes">http://releases.k8s.io/HEAD/docs/user-guide/pod-states.md#container-probes</a></p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int64)</p></td>
|
||||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">periodSeconds</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1.</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int64)</p></td>
|
||||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">successThreshold</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness. Minimum value is 1.</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int32)</p></td>
|
||||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">failureThreshold</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1.</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int32)</p></td>
|
||||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
@ -4240,7 +4261,7 @@ Populated by the system when a graceful deletion is requested. Read-only. More i
|
|||
</div>
|
||||
<div id="footer">
|
||||
<div id="footer-text">
|
||||
Last updated 2015-11-04 22:53:25 UTC
|
||||
Last updated 2015-11-06 18:46:07 UTC
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
|
|
@ -5095,7 +5095,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
|
|||
</div>
|
||||
<div id="footer">
|
||||
<div id="footer-text">
|
||||
Last updated 2015-11-04 22:53:25 UTC
|
||||
Last updated 2015-11-06 18:46:07 UTC
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
|
|
@ -3023,7 +3023,7 @@ The resulting set of endpoints can be viewed as:<br>
|
|||
<div class="sect2">
|
||||
<h3 id="_v1_probe">v1.Probe</h3>
|
||||
<div class="paragraph">
|
||||
<p>Probe describes a liveness probe to be examined to the container.</p>
|
||||
<p>Probe describes a health check to be performed against a container to determine whether it is alive or ready to recieve traffic.</p>
|
||||
</div>
|
||||
<table class="tableblock frame-all grid-all" style="width:100%; ">
|
||||
<colgroup>
|
||||
|
@ -3073,11 +3073,32 @@ The resulting set of endpoints can be viewed as:<br>
|
|||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">timeoutSeconds</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">Number of seconds after which liveness probes timeout. Defaults to 1 second. More info: <a href="http://releases.k8s.io/HEAD/docs/user-guide/pod-states.md#container-probes">http://releases.k8s.io/HEAD/docs/user-guide/pod-states.md#container-probes</a></p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: <a href="http://releases.k8s.io/HEAD/docs/user-guide/pod-states.md#container-probes">http://releases.k8s.io/HEAD/docs/user-guide/pod-states.md#container-probes</a></p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int64)</p></td>
|
||||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">periodSeconds</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1.</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int64)</p></td>
|
||||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">successThreshold</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness. Minimum value is 1.</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int32)</p></td>
|
||||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">failureThreshold</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1.</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">false</p></td>
|
||||
<td class="tableblock halign-left valign-top"><p class="tableblock">integer (int32)</p></td>
|
||||
<td class="tableblock halign-left valign-top"></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
@ -6866,7 +6887,7 @@ The resulting set of endpoints can be viewed as:<br>
|
|||
</div>
|
||||
<div id="footer">
|
||||
<div id="footer-text">
|
||||
Last updated 2015-11-04 22:53:19 UTC
|
||||
Last updated 2015-11-06 18:46:00 UTC
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
|
|
@ -23664,7 +23664,7 @@ span.icon > [class^="icon-"], span.icon > [class*=" icon-"] { cursor: default; }
|
|||
</div>
|
||||
<div id="footer">
|
||||
<div id="footer-text">
|
||||
Last updated 2015-11-04 22:53:19 UTC
|
||||
Last updated 2015-11-06 18:46:00 UTC
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
|
|
@ -1694,6 +1694,9 @@ func deepCopy_api_Probe(in Probe, out *Probe, c *conversion.Cloner) error {
|
|||
}
|
||||
out.InitialDelaySeconds = in.InitialDelaySeconds
|
||||
out.TimeoutSeconds = in.TimeoutSeconds
|
||||
out.PeriodSeconds = in.PeriodSeconds
|
||||
out.SuccessThreshold = in.SuccessThreshold
|
||||
out.FailureThreshold = in.FailureThreshold
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -283,6 +283,18 @@ func FuzzerFor(t *testing.T, version string, src rand.Source) *fuzz.Fuzzer {
|
|||
c.FuzzNoCustom(ct) // fuzz self without calling this function again
|
||||
ct.TerminationMessagePath = "/" + ct.TerminationMessagePath // Must be non-empty
|
||||
},
|
||||
func(p *api.Probe, c fuzz.Continue) {
|
||||
c.FuzzNoCustom(p)
|
||||
// These fields have default values.
|
||||
intFieldsWithDefaults := [...]string{"TimeoutSeconds", "PeriodSeconds", "SuccessThreshold", "FailureThreshold"}
|
||||
v := reflect.ValueOf(p).Elem()
|
||||
for _, field := range intFieldsWithDefaults {
|
||||
f := v.FieldByName(field)
|
||||
if f.Int() == 0 {
|
||||
f.SetInt(1)
|
||||
}
|
||||
}
|
||||
},
|
||||
func(ev *api.EnvVar, c fuzz.Continue) {
|
||||
ev.Name = c.RandString()
|
||||
if c.RandBool() {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -713,7 +713,8 @@ type ExecAction struct {
|
|||
Command []string `json:"command,omitempty"`
|
||||
}
|
||||
|
||||
// Probe describes a liveness probe to be examined to the container.
|
||||
// Probe describes a health check to be performed against a container to determine whether it is
|
||||
// alive or ready to recieve traffic.
|
||||
type Probe struct {
|
||||
// The action taken to determine the health of a container
|
||||
Handler `json:",inline"`
|
||||
|
@ -721,6 +722,13 @@ type Probe struct {
|
|||
InitialDelaySeconds int64 `json:"initialDelaySeconds,omitempty"`
|
||||
// Length of time before health checking times out. In seconds.
|
||||
TimeoutSeconds int64 `json:"timeoutSeconds,omitempty"`
|
||||
// How often (in seconds) to perform the probe.
|
||||
PeriodSeconds int64 `json:"periodSeconds,omitempty"`
|
||||
// Minimum consecutive successes for the probe to be considered successful after having failed.
|
||||
// Must be 1 for liveness.
|
||||
SuccessThreshold int `json:"successThreshold,omitempty"`
|
||||
// Minimum consecutive failures for the probe to be considered failed after having succeeded.
|
||||
FailureThreshold int `json:"failureThreshold,omitempty"`
|
||||
}
|
||||
|
||||
// PullPolicy describes a policy for if/when to pull a container image
|
||||
|
|
|
@ -2243,6 +2243,9 @@ func autoconvert_api_Probe_To_v1_Probe(in *api.Probe, out *Probe, s conversion.S
|
|||
}
|
||||
out.InitialDelaySeconds = in.InitialDelaySeconds
|
||||
out.TimeoutSeconds = in.TimeoutSeconds
|
||||
out.PeriodSeconds = in.PeriodSeconds
|
||||
out.SuccessThreshold = in.SuccessThreshold
|
||||
out.FailureThreshold = in.FailureThreshold
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -5268,6 +5271,9 @@ func autoconvert_v1_Probe_To_api_Probe(in *Probe, out *api.Probe, s conversion.S
|
|||
}
|
||||
out.InitialDelaySeconds = in.InitialDelaySeconds
|
||||
out.TimeoutSeconds = in.TimeoutSeconds
|
||||
out.PeriodSeconds = in.PeriodSeconds
|
||||
out.SuccessThreshold = in.SuccessThreshold
|
||||
out.FailureThreshold = in.FailureThreshold
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -1713,6 +1713,9 @@ func deepCopy_v1_Probe(in Probe, out *Probe, c *conversion.Cloner) error {
|
|||
}
|
||||
out.InitialDelaySeconds = in.InitialDelaySeconds
|
||||
out.TimeoutSeconds = in.TimeoutSeconds
|
||||
out.PeriodSeconds = in.PeriodSeconds
|
||||
out.SuccessThreshold = in.SuccessThreshold
|
||||
out.FailureThreshold = in.FailureThreshold
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -128,6 +128,15 @@ func addDefaultingFuncs() {
|
|||
if obj.TimeoutSeconds == 0 {
|
||||
obj.TimeoutSeconds = 1
|
||||
}
|
||||
if obj.PeriodSeconds == 0 {
|
||||
obj.PeriodSeconds = 10
|
||||
}
|
||||
if obj.SuccessThreshold == 0 {
|
||||
obj.SuccessThreshold = 1
|
||||
}
|
||||
if obj.FailureThreshold == 0 {
|
||||
obj.FailureThreshold = 3
|
||||
}
|
||||
},
|
||||
func(obj *Secret) {
|
||||
if obj.Type == "" {
|
||||
|
|
|
@ -545,3 +545,26 @@ func TestSetDefaultLimitRangeItem(t *testing.T) {
|
|||
t.Errorf("Expected request memory: %s, got: %s", "100Mi", requestMinValue.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaultProbe(t *testing.T) {
|
||||
originalProbe := versioned.Probe{}
|
||||
expectedProbe := versioned.Probe{
|
||||
InitialDelaySeconds: 0,
|
||||
TimeoutSeconds: 1,
|
||||
PeriodSeconds: 10,
|
||||
SuccessThreshold: 1,
|
||||
FailureThreshold: 3,
|
||||
}
|
||||
|
||||
pod := &versioned.Pod{
|
||||
Spec: versioned.PodSpec{
|
||||
Containers: []versioned.Container{{LivenessProbe: &originalProbe}},
|
||||
},
|
||||
}
|
||||
|
||||
output := roundTrip(t, runtime.Object(pod)).(*versioned.Pod)
|
||||
actualProbe := *output.Spec.Containers[0].LivenessProbe
|
||||
if actualProbe != expectedProbe {
|
||||
t.Errorf("Expected probe: %+v\ngot: %+v\n", expectedProbe, actualProbe)
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -846,17 +846,27 @@ type ExecAction struct {
|
|||
Command []string `json:"command,omitempty"`
|
||||
}
|
||||
|
||||
// Probe describes a liveness probe to be examined to the container.
|
||||
// Probe describes a health check to be performed against a container to determine whether it is
|
||||
// alive or ready to recieve traffic.
|
||||
type Probe struct {
|
||||
// The action taken to determine the health of a container
|
||||
Handler `json:",inline"`
|
||||
// Number of seconds after the container has started before liveness probes are initiated.
|
||||
// More info: http://releases.k8s.io/HEAD/docs/user-guide/pod-states.md#container-probes
|
||||
InitialDelaySeconds int64 `json:"initialDelaySeconds,omitempty"`
|
||||
// Number of seconds after which liveness probes timeout.
|
||||
// Defaults to 1 second.
|
||||
// Number of seconds after which the probe times out.
|
||||
// Defaults to 1 second. Minimum value is 1.
|
||||
// More info: http://releases.k8s.io/HEAD/docs/user-guide/pod-states.md#container-probes
|
||||
TimeoutSeconds int64 `json:"timeoutSeconds,omitempty"`
|
||||
// How often (in seconds) to perform the probe.
|
||||
// Default to 10 seconds. Minimum value is 1.
|
||||
PeriodSeconds int64 `json:"periodSeconds,omitempty"`
|
||||
// Minimum consecutive successes for the probe to be considered successful after having failed.
|
||||
// Defaults to 1. Must be 1 for liveness. Minimum value is 1.
|
||||
SuccessThreshold int `json:"successThreshold,omitempty"`
|
||||
// Minimum consecutive failures for the probe to be considered failed after having succeeded.
|
||||
// Defaults to 3. Minimum value is 1.
|
||||
FailureThreshold int `json:"failureThreshold,omitempty"`
|
||||
}
|
||||
|
||||
// PullPolicy describes a policy for if/when to pull a container image
|
||||
|
|
|
@ -1068,9 +1068,12 @@ func (PodTemplateSpec) SwaggerDoc() map[string]string {
|
|||
}
|
||||
|
||||
var map_Probe = map[string]string{
|
||||
"": "Probe describes a liveness probe to be examined to the container.",
|
||||
"": "Probe describes a health check to be performed against a container to determine whether it is alive or ready to recieve traffic.",
|
||||
"initialDelaySeconds": "Number of seconds after the container has started before liveness probes are initiated. More info: http://releases.k8s.io/HEAD/docs/user-guide/pod-states.md#container-probes",
|
||||
"timeoutSeconds": "Number of seconds after which liveness probes timeout. Defaults to 1 second. More info: http://releases.k8s.io/HEAD/docs/user-guide/pod-states.md#container-probes",
|
||||
"timeoutSeconds": "Number of seconds after which the probe times out. Defaults to 1 second. Minimum value is 1. More info: http://releases.k8s.io/HEAD/docs/user-guide/pod-states.md#container-probes",
|
||||
"periodSeconds": "How often (in seconds) to perform the probe. Default to 10 seconds. Minimum value is 1.",
|
||||
"successThreshold": "Minimum consecutive successes for the probe to be considered successful after having failed. Defaults to 1. Must be 1 for liveness. Minimum value is 1.",
|
||||
"failureThreshold": "Minimum consecutive failures for the probe to be considered failed after having succeeded. Defaults to 3. Minimum value is 1.",
|
||||
}
|
||||
|
||||
func (Probe) SwaggerDoc() map[string]string {
|
||||
|
|
|
@ -881,12 +881,11 @@ func validateProbe(probe *api.Probe) errs.ValidationErrorList {
|
|||
return allErrs
|
||||
}
|
||||
allErrs = append(allErrs, validateHandler(&probe.Handler)...)
|
||||
if probe.InitialDelaySeconds < 0 {
|
||||
allErrs = append(allErrs, errs.NewFieldInvalid("initialDelay", probe.InitialDelaySeconds, "may not be less than zero"))
|
||||
}
|
||||
if probe.TimeoutSeconds < 0 {
|
||||
allErrs = append(allErrs, errs.NewFieldInvalid("timeout", probe.TimeoutSeconds, "may not be less than zero"))
|
||||
}
|
||||
allErrs = append(allErrs, ValidatePositiveField(probe.InitialDelaySeconds, "initialDelaySeconds")...)
|
||||
allErrs = append(allErrs, ValidatePositiveField(probe.TimeoutSeconds, "timeoutSeconds")...)
|
||||
allErrs = append(allErrs, ValidatePositiveField(int64(probe.PeriodSeconds), "periodSeconds")...)
|
||||
allErrs = append(allErrs, ValidatePositiveField(int64(probe.SuccessThreshold), "successThreshold")...)
|
||||
allErrs = append(allErrs, ValidatePositiveField(int64(probe.FailureThreshold), "failureThreshold")...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
|
@ -1030,6 +1029,11 @@ func validateContainers(containers []api.Container, volumes sets.String) errs.Va
|
|||
cErrs = append(cErrs, validateLifecycle(ctr.Lifecycle).Prefix("lifecycle")...)
|
||||
}
|
||||
cErrs = append(cErrs, validateProbe(ctr.LivenessProbe).Prefix("livenessProbe")...)
|
||||
// Liveness-specific validation
|
||||
if ctr.LivenessProbe != nil && ctr.LivenessProbe.SuccessThreshold != 1 {
|
||||
allErrs = append(allErrs, errs.NewFieldForbidden("livenessProbe.successThreshold", "must be 1"))
|
||||
}
|
||||
|
||||
cErrs = append(cErrs, validateProbe(ctr.ReadinessProbe).Prefix("readinessProbe")...)
|
||||
cErrs = append(cErrs, validatePorts(ctr.Ports).Prefix("ports")...)
|
||||
cErrs = append(cErrs, validateEnv(ctr.Env).Prefix("env")...)
|
||||
|
|
|
@ -18,6 +18,7 @@ package validation
|
|||
|
||||
import (
|
||||
"math/rand"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -807,22 +808,26 @@ func TestValidateVolumeMounts(t *testing.T) {
|
|||
|
||||
func TestValidateProbe(t *testing.T) {
|
||||
handler := api.Handler{Exec: &api.ExecAction{Command: []string{"echo"}}}
|
||||
successCases := []*api.Probe{
|
||||
nil,
|
||||
{TimeoutSeconds: 10, InitialDelaySeconds: 0, Handler: handler},
|
||||
{TimeoutSeconds: 0, InitialDelaySeconds: 10, Handler: handler},
|
||||
// These fields must be positive.
|
||||
positiveFields := [...]string{"InitialDelaySeconds", "TimeoutSeconds", "PeriodSeconds", "SuccessThreshold", "FailureThreshold"}
|
||||
successCases := []*api.Probe{nil}
|
||||
for _, field := range positiveFields {
|
||||
probe := &api.Probe{Handler: handler}
|
||||
reflect.ValueOf(probe).Elem().FieldByName(field).SetInt(10)
|
||||
successCases = append(successCases, probe)
|
||||
}
|
||||
|
||||
for _, p := range successCases {
|
||||
if errs := validateProbe(p); len(errs) != 0 {
|
||||
t.Errorf("expected success: %v", errs)
|
||||
}
|
||||
}
|
||||
|
||||
errorCases := []*api.Probe{
|
||||
{TimeoutSeconds: 10, InitialDelaySeconds: 10},
|
||||
{TimeoutSeconds: 10, InitialDelaySeconds: -10, Handler: handler},
|
||||
{TimeoutSeconds: -10, InitialDelaySeconds: 10, Handler: handler},
|
||||
{TimeoutSeconds: -10, InitialDelaySeconds: -10, Handler: handler},
|
||||
errorCases := []*api.Probe{{TimeoutSeconds: 10, InitialDelaySeconds: 10}}
|
||||
for _, field := range positiveFields {
|
||||
probe := &api.Probe{Handler: handler}
|
||||
reflect.ValueOf(probe).Elem().FieldByName(field).SetInt(-10)
|
||||
errorCases = append(errorCases, probe)
|
||||
}
|
||||
for _, p := range errorCases {
|
||||
if errs := validateProbe(p); len(errs) == 0 {
|
||||
|
|
|
@ -583,6 +583,9 @@ func deepCopy_api_Probe(in api.Probe, out *api.Probe, c *conversion.Cloner) erro
|
|||
}
|
||||
out.InitialDelaySeconds = in.InitialDelaySeconds
|
||||
out.TimeoutSeconds = in.TimeoutSeconds
|
||||
out.PeriodSeconds = in.PeriodSeconds
|
||||
out.SuccessThreshold = in.SuccessThreshold
|
||||
out.FailureThreshold = in.FailureThreshold
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -755,6 +755,9 @@ func autoconvert_api_Probe_To_v1_Probe(in *api.Probe, out *v1.Probe, s conversio
|
|||
}
|
||||
out.InitialDelaySeconds = in.InitialDelaySeconds
|
||||
out.TimeoutSeconds = in.TimeoutSeconds
|
||||
out.PeriodSeconds = in.PeriodSeconds
|
||||
out.SuccessThreshold = in.SuccessThreshold
|
||||
out.FailureThreshold = in.FailureThreshold
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -1815,6 +1818,9 @@ func autoconvert_v1_Probe_To_api_Probe(in *v1.Probe, out *api.Probe, s conversio
|
|||
}
|
||||
out.InitialDelaySeconds = in.InitialDelaySeconds
|
||||
out.TimeoutSeconds = in.TimeoutSeconds
|
||||
out.PeriodSeconds = in.PeriodSeconds
|
||||
out.SuccessThreshold = in.SuccessThreshold
|
||||
out.FailureThreshold = in.FailureThreshold
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -620,6 +620,9 @@ func deepCopy_v1_Probe(in v1.Probe, out *v1.Probe, c *conversion.Cloner) error {
|
|||
}
|
||||
out.InitialDelaySeconds = in.InitialDelaySeconds
|
||||
out.TimeoutSeconds = in.TimeoutSeconds
|
||||
out.PeriodSeconds = in.PeriodSeconds
|
||||
out.SuccessThreshold = in.SuccessThreshold
|
||||
out.FailureThreshold = in.FailureThreshold
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -418,7 +418,6 @@ func NewMainKubelet(
|
|||
klet.statusManager = status.NewManager(kubeClient, klet.podManager)
|
||||
|
||||
klet.probeManager = prober.NewManager(
|
||||
klet.resyncInterval,
|
||||
klet.statusManager,
|
||||
readinessManager,
|
||||
klet.livenessManager,
|
||||
|
|
|
@ -18,7 +18,6 @@ package prober
|
|||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
|
@ -71,13 +70,9 @@ type manager struct {
|
|||
|
||||
// prober executes the probe actions.
|
||||
prober *prober
|
||||
|
||||
// Default period for workers to execute a probe.
|
||||
defaultProbePeriod time.Duration
|
||||
}
|
||||
|
||||
func NewManager(
|
||||
defaultProbePeriod time.Duration,
|
||||
statusManager status.Manager,
|
||||
readinessManager results.Manager,
|
||||
livenessManager results.Manager,
|
||||
|
@ -86,12 +81,11 @@ func NewManager(
|
|||
recorder record.EventRecorder) Manager {
|
||||
prober := newProber(runner, refManager, recorder)
|
||||
return &manager{
|
||||
defaultProbePeriod: defaultProbePeriod,
|
||||
statusManager: statusManager,
|
||||
prober: prober,
|
||||
readinessManager: readinessManager,
|
||||
livenessManager: livenessManager,
|
||||
workers: make(map[probeKey]*worker),
|
||||
statusManager: statusManager,
|
||||
prober: prober,
|
||||
readinessManager: readinessManager,
|
||||
livenessManager: livenessManager,
|
||||
workers: make(map[probeKey]*worker),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,6 +34,16 @@ import (
|
|||
"k8s.io/kubernetes/pkg/util/wait"
|
||||
)
|
||||
|
||||
var defaultProbe *api.Probe = &api.Probe{
|
||||
Handler: api.Handler{
|
||||
Exec: &api.ExecAction{},
|
||||
},
|
||||
TimeoutSeconds: 1,
|
||||
PeriodSeconds: 1,
|
||||
SuccessThreshold: 1,
|
||||
FailureThreshold: 3,
|
||||
}
|
||||
|
||||
func TestAddRemovePods(t *testing.T) {
|
||||
noProbePod := api.Pod{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
|
@ -57,12 +67,12 @@ func TestAddRemovePods(t *testing.T) {
|
|||
Name: "no_probe1",
|
||||
}, {
|
||||
Name: "readiness",
|
||||
ReadinessProbe: &api.Probe{},
|
||||
ReadinessProbe: defaultProbe,
|
||||
}, {
|
||||
Name: "no_probe2",
|
||||
}, {
|
||||
Name: "liveness",
|
||||
LivenessProbe: &api.Probe{},
|
||||
LivenessProbe: defaultProbe,
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
@ -119,10 +129,10 @@ func TestCleanupPods(t *testing.T) {
|
|||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{{
|
||||
Name: "prober1",
|
||||
ReadinessProbe: &api.Probe{},
|
||||
ReadinessProbe: defaultProbe,
|
||||
}, {
|
||||
Name: "prober2",
|
||||
LivenessProbe: &api.Probe{},
|
||||
LivenessProbe: defaultProbe,
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
@ -133,10 +143,10 @@ func TestCleanupPods(t *testing.T) {
|
|||
Spec: api.PodSpec{
|
||||
Containers: []api.Container{{
|
||||
Name: "prober1",
|
||||
ReadinessProbe: &api.Probe{},
|
||||
ReadinessProbe: defaultProbe,
|
||||
}, {
|
||||
Name: "prober2",
|
||||
LivenessProbe: &api.Probe{},
|
||||
LivenessProbe: defaultProbe,
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
@ -266,9 +276,7 @@ outer:
|
|||
}
|
||||
|
||||
func newTestManager() *manager {
|
||||
const probePeriod = 1
|
||||
m := NewManager(
|
||||
probePeriod,
|
||||
status.NewManager(&testclient.Fake{}, kubepod.NewBasicPodManager(nil)),
|
||||
results.NewManager(),
|
||||
results.NewManager(),
|
||||
|
|
|
@ -118,8 +118,8 @@ func (pb *prober) runProbeWithRetries(p *api.Probe, pod *api.Pod, status api.Pod
|
|||
var output string
|
||||
for i := 0; i < retries; i++ {
|
||||
result, output, err = pb.runProbe(p, pod, status, container, containerID)
|
||||
if result == probe.Success {
|
||||
return probe.Success, output, nil
|
||||
if err == nil {
|
||||
return result, output, nil
|
||||
}
|
||||
}
|
||||
return result, output, err
|
||||
|
|
|
@ -56,6 +56,10 @@ type worker struct {
|
|||
|
||||
// The last known container ID for this worker.
|
||||
containerID kubecontainer.ContainerID
|
||||
// The last probe result for this worker.
|
||||
lastResult results.Result
|
||||
// How many times in a row the probe has returned the same result.
|
||||
resultRun int
|
||||
}
|
||||
|
||||
// Creates and starts a new probe worker.
|
||||
|
@ -89,7 +93,7 @@ func newWorker(
|
|||
|
||||
// run periodically probes the container.
|
||||
func (w *worker) run() {
|
||||
probeTicker := time.NewTicker(w.probeManager.defaultProbePeriod)
|
||||
probeTicker := time.NewTicker(time.Duration(w.spec.PeriodSeconds) * time.Second)
|
||||
|
||||
defer func() {
|
||||
// Clean up.
|
||||
|
@ -145,6 +149,7 @@ func (w *worker) doProbe() (keepGoing bool) {
|
|||
w.resultsManager.Remove(w.containerID)
|
||||
}
|
||||
w.containerID = kubecontainer.ParseContainerID(c.ContainerID)
|
||||
w.resultsManager.Set(w.containerID, w.initialValue, w.pod)
|
||||
}
|
||||
|
||||
if c.State.Running == nil {
|
||||
|
@ -159,14 +164,29 @@ func (w *worker) doProbe() (keepGoing bool) {
|
|||
}
|
||||
|
||||
if int64(time.Since(c.State.Running.StartedAt.Time).Seconds()) < w.spec.InitialDelaySeconds {
|
||||
w.resultsManager.Set(w.containerID, w.initialValue, w.pod)
|
||||
return true
|
||||
}
|
||||
|
||||
result, err := w.probeManager.prober.probe(w.probeType, w.pod, status, w.container, w.containerID)
|
||||
if err == nil {
|
||||
w.resultsManager.Set(w.containerID, result, w.pod)
|
||||
if err != nil {
|
||||
// Prober error, throw away the result.
|
||||
return true
|
||||
}
|
||||
|
||||
if w.lastResult == result {
|
||||
w.resultRun++
|
||||
} else {
|
||||
w.lastResult = result
|
||||
w.resultRun = 1
|
||||
}
|
||||
|
||||
if (result == results.Failure && w.resultRun < w.spec.FailureThreshold) ||
|
||||
(result == results.Success && w.resultRun < w.spec.SuccessThreshold) {
|
||||
// Success or failure is below threshold - leave the probe state unchanged.
|
||||
return true
|
||||
}
|
||||
|
||||
w.resultsManager.Set(w.containerID, result, w.pod)
|
||||
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package prober
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -135,18 +136,8 @@ func TestInitialDelay(t *testing.T) {
|
|||
})
|
||||
m.statusManager.SetPodStatus(w.pod, getRunningStatus())
|
||||
|
||||
if !w.doProbe() {
|
||||
t.Errorf("[%s] Expected to continue, but did not", probeType)
|
||||
}
|
||||
|
||||
expectedResult := results.Result(probeType == liveness)
|
||||
result, ok := resultsManager(m, probeType).Get(containerID)
|
||||
if !ok {
|
||||
t.Errorf("[%s] Expected result to be set during initial delay, but was not set", probeType)
|
||||
} else if result != expectedResult {
|
||||
t.Errorf("[%s] Expected result to be %v during initial delay, but was %v",
|
||||
probeType, expectedResult, result)
|
||||
}
|
||||
expectContinue(t, w, w.doProbe(), "during initial delay")
|
||||
expectResult(t, w, results.Result(probeType == liveness), "during initial delay")
|
||||
|
||||
// 100 seconds later...
|
||||
laterStatus := getRunningStatus()
|
||||
|
@ -155,16 +146,76 @@ func TestInitialDelay(t *testing.T) {
|
|||
m.statusManager.SetPodStatus(w.pod, laterStatus)
|
||||
|
||||
// Second call should succeed (already waited).
|
||||
if !w.doProbe() {
|
||||
t.Errorf("[%s] Expected to continue, but did not", probeType)
|
||||
expectContinue(t, w, w.doProbe(), "after initial delay")
|
||||
expectResult(t, w, results.Success, "after initial delay")
|
||||
}
|
||||
}
|
||||
|
||||
func TestFailureThreshold(t *testing.T) {
|
||||
m := newTestManager()
|
||||
w := newTestWorker(m, readiness, api.Probe{})
|
||||
m.statusManager.SetPodStatus(w.pod, getRunningStatus())
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
// First probe should succeed.
|
||||
m.prober.exec = fakeExecProber{probe.Success, nil}
|
||||
|
||||
for j := 0; j < 3; j++ {
|
||||
msg := fmt.Sprintf("%d success (%d)", j+1, i)
|
||||
expectContinue(t, w, w.doProbe(), msg)
|
||||
expectResult(t, w, results.Success, msg)
|
||||
}
|
||||
|
||||
result, ok = resultsManager(m, probeType).Get(containerID)
|
||||
if !ok {
|
||||
t.Errorf("[%s] Expected result to be true, but was not set", probeType)
|
||||
} else if !result {
|
||||
t.Errorf("[%s] Expected result to be true, but was false", probeType)
|
||||
// Prober starts failing :(
|
||||
m.prober.exec = fakeExecProber{probe.Failure, nil}
|
||||
|
||||
// Next 2 probes should still be "success".
|
||||
for j := 0; j < 2; j++ {
|
||||
msg := fmt.Sprintf("%d failure (%d)", j+1, i)
|
||||
expectContinue(t, w, w.doProbe(), msg)
|
||||
expectResult(t, w, results.Success, msg)
|
||||
}
|
||||
|
||||
// Third & following fail.
|
||||
for j := 0; j < 3; j++ {
|
||||
msg := fmt.Sprintf("%d failure (%d)", j+3, i)
|
||||
expectContinue(t, w, w.doProbe(), msg)
|
||||
expectResult(t, w, results.Failure, msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSuccessThreshold(t *testing.T) {
|
||||
m := newTestManager()
|
||||
w := newTestWorker(m, readiness, api.Probe{SuccessThreshold: 3, FailureThreshold: 1})
|
||||
m.statusManager.SetPodStatus(w.pod, getRunningStatus())
|
||||
|
||||
// Start out failure.
|
||||
w.resultsManager.Set(containerID, results.Failure, nil)
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
// Probe defaults to Failure.
|
||||
for j := 0; j < 2; j++ {
|
||||
msg := fmt.Sprintf("%d success (%d)", j+1, i)
|
||||
expectContinue(t, w, w.doProbe(), msg)
|
||||
expectResult(t, w, results.Failure, msg)
|
||||
}
|
||||
|
||||
// Continuing success!
|
||||
for j := 0; j < 3; j++ {
|
||||
msg := fmt.Sprintf("%d success (%d)", j+3, i)
|
||||
expectContinue(t, w, w.doProbe(), msg)
|
||||
expectResult(t, w, results.Success, msg)
|
||||
}
|
||||
|
||||
// Prober flakes :(
|
||||
m.prober.exec = fakeExecProber{probe.Failure, nil}
|
||||
msg := fmt.Sprintf("1 failure (%d)", i)
|
||||
expectContinue(t, w, w.doProbe(), msg)
|
||||
expectResult(t, w, results.Failure, msg)
|
||||
|
||||
// Back to success.
|
||||
m.prober.exec = fakeExecProber{probe.Success, nil}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -205,22 +256,22 @@ func TestCleanUp(t *testing.T) {
|
|||
|
||||
func TestHandleCrash(t *testing.T) {
|
||||
m := newTestManager()
|
||||
w := newTestWorker(m, readiness, api.Probe{})
|
||||
m.statusManager.SetPodStatus(w.pod, getRunningStatus())
|
||||
|
||||
expectContinue(t, w, w.doProbe(), "Initial successful probe.")
|
||||
expectResult(t, w, results.Success, "Initial successful probe.")
|
||||
|
||||
// Prober starts crashing.
|
||||
m.prober = &prober{
|
||||
refManager: kubecontainer.NewRefManager(),
|
||||
recorder: &record.FakeRecorder{},
|
||||
exec: crashingExecProber{},
|
||||
}
|
||||
|
||||
w := newTestWorker(m, readiness, api.Probe{})
|
||||
m.statusManager.SetPodStatus(w.pod, getRunningStatus())
|
||||
|
||||
// doProbe should recover from the crash, and keep going.
|
||||
if !w.doProbe() {
|
||||
t.Error("Expected to keep going, but terminated.")
|
||||
}
|
||||
if _, ok := m.readinessManager.Get(containerID); ok {
|
||||
t.Error("Expected readiness to be unchanged from crash.")
|
||||
}
|
||||
expectContinue(t, w, w.doProbe(), "Crashing probe.")
|
||||
expectResult(t, w, results.Success, "Crashing probe unchanged.")
|
||||
}
|
||||
|
||||
func newTestWorker(m *manager, probeType probeType, probeSpec api.Probe) *worker {
|
||||
|
@ -228,6 +279,19 @@ func newTestWorker(m *manager, probeType probeType, probeSpec api.Probe) *worker
|
|||
probeSpec.Handler = api.Handler{
|
||||
Exec: &api.ExecAction{},
|
||||
}
|
||||
// Apply default values.
|
||||
defaults := map[string]int64{
|
||||
"TimeoutSeconds": 1,
|
||||
"PeriodSeconds": 10,
|
||||
"SuccessThreshold": 1,
|
||||
"FailureThreshold": 3,
|
||||
}
|
||||
for field, value := range defaults {
|
||||
f := reflect.ValueOf(&probeSpec).Elem().FieldByName(field)
|
||||
if f.Int() == 0 {
|
||||
f.SetInt(value)
|
||||
}
|
||||
}
|
||||
|
||||
pod := getTestPod(probeType, probeSpec)
|
||||
return newWorker(m, probeType, &pod, pod.Spec.Containers[0])
|
||||
|
@ -266,6 +330,22 @@ func getTestPod(probeType probeType, probeSpec api.Probe) api.Pod {
|
|||
return pod
|
||||
}
|
||||
|
||||
func expectResult(t *testing.T, w *worker, expectedResult results.Result, msg string) {
|
||||
result, ok := resultsManager(w.probeManager, w.probeType).Get(containerID)
|
||||
if !ok {
|
||||
t.Errorf("[%s - %s] Expected result to be set, but was not set", w.probeType, msg)
|
||||
} else if result != expectedResult {
|
||||
t.Errorf("[%s - %s] Expected result to be %v, but was %v",
|
||||
w.probeType, msg, expectedResult, result)
|
||||
}
|
||||
}
|
||||
|
||||
func expectContinue(t *testing.T, w *worker, c bool, msg string) {
|
||||
if !c {
|
||||
t.Errorf("[%s - %s] Expected to continue, but did not", w.probeType, msg)
|
||||
}
|
||||
}
|
||||
|
||||
func resultsManager(m *manager, probeType probeType) results.Manager {
|
||||
switch probeType {
|
||||
case readiness:
|
||||
|
|
|
@ -560,6 +560,7 @@ var _ = Describe("Pods", func() {
|
|||
},
|
||||
},
|
||||
InitialDelaySeconds: 15,
|
||||
FailureThreshold: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -586,6 +587,7 @@ var _ = Describe("Pods", func() {
|
|||
},
|
||||
},
|
||||
InitialDelaySeconds: 15,
|
||||
FailureThreshold: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -613,6 +615,7 @@ var _ = Describe("Pods", func() {
|
|||
},
|
||||
},
|
||||
InitialDelaySeconds: 15,
|
||||
FailureThreshold: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -640,6 +643,7 @@ var _ = Describe("Pods", func() {
|
|||
},
|
||||
},
|
||||
InitialDelaySeconds: 5,
|
||||
FailureThreshold: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -673,6 +677,7 @@ var _ = Describe("Pods", func() {
|
|||
},
|
||||
},
|
||||
InitialDelaySeconds: 15,
|
||||
FailureThreshold: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue