Skip to content

Commit

Permalink
add readiness probe types (#410)
Browse files Browse the repository at this point in the history
* add readiness probe types
  • Loading branch information
mangas authored Mar 18, 2021
1 parent b67d70d commit c9c324f
Show file tree
Hide file tree
Showing 7 changed files with 284 additions and 73 deletions.
13 changes: 11 additions & 2 deletions pkg/kev/config/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,17 @@ const (
// LabelWorkloadReadinessProbeRetries defines number of times workload liveness probe will retry
LabelWorkloadReadinessProbeRetries = LabelPrefix + "workload.readiness-probe-retries"

// LabelWorkloadReadinessProbeDisabled disables workload liveness probe
LabelWorkloadReadinessProbeDisabled = LabelPrefix + "workload.readiness-probe-disabled"
// LabelWorkloadLivenessProbeType defines the command for workload liveness probe.
LabelWorkloadReadinessProbeType = LabelPrefix + "workload.readiness-probe-type"

// LabelWorkloadLivenessProbeHTTPPort defines the port for the http liveness probes.
LabelWorkloadReadinessProbeHTTPPort = LabelPrefix + "workload.readiness-probe-http-port"

// LabelWorkloadLivenessProbeHTTPPath defines the path for the http liveness probe.
LabelWorkloadReadinessProbeHTTPPath = LabelPrefix + "workload.readiness-probe-http-path"

// LabelWorkloadLivenessProbeTCPPort defines the path for the http liveness probe.
LabelWorkloadReadinessProbeTCPPort = LabelPrefix + "workload.readiness-probe-tcp-port"

// LabelServiceType defines the type of service to be created
LabelServiceType = LabelPrefix + "service.type"
Expand Down
4 changes: 4 additions & 0 deletions pkg/kev/config/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@ var ServicesSchema = map[string]interface{}{
LabelWorkloadLivenessProbeInterval: map[string]interface{}{"type": "string", "format": "duration"},
LabelWorkloadLivenessProbeRetries: map[string]interface{}{"type": "string", "pattern": `^\d+$`},
LabelWorkloadLivenessProbeTimeout: map[string]interface{}{"type": "string", "format": "duration"},
LabelWorkloadReadinessProbeType: map[string]interface{}{"type": "string", "enum": []string{"none", "command", "http", "tcp"}},
LabelWorkloadReadinessProbeCommand: map[string]interface{}{"type": "string"},
LabelWorkloadReadinessProbeHTTPPort: map[string]interface{}{"type": "string"},
LabelWorkloadReadinessProbeTCPPort: map[string]interface{}{"type": "string"},
LabelWorkloadReadinessProbeHTTPPath: map[string]interface{}{"type": "string"},
LabelWorkloadReadinessProbeInitialDelay: map[string]interface{}{"type": "string", "format": "duration"},
LabelWorkloadReadinessProbeInterval: map[string]interface{}{"type": "string", "format": "duration"},
LabelWorkloadReadinessProbeRetries: map[string]interface{}{"type": "string", "pattern": `^\d+$`},
Expand Down
129 changes: 97 additions & 32 deletions pkg/kev/converter/kubernetes/project_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -756,36 +756,102 @@ func (p *ProjectService) livenessProbeRetries() int32 {

// readinessProbe returns project service readiness probe
func (p *ProjectService) readinessProbe() (*v1.Probe, error) {
probeType, err := p.readinessProbeType()
if err != nil {
return nil, err
}

if !p.readinessProbeDisabled() {
command := p.readinessProbeCommand()
timeoutSeconds := p.readinessProbeTimeout()
periodSeconds := p.readinessProbeInterval()
initialDelaySeconds := p.readinessProbeInitialDelay()
failureThreshold := p.readinessProbeRetries()
var hnd v1.Handler

switch *probeType {
case ProbeTypeNone:
return nil, nil
case ProbeTypeCommand:
hnd.Exec = &v1.ExecAction{
Command: p.readinessProbeCommand(),
}

if len(command) == 0 || len(command[0]) == 0 || timeoutSeconds == 0 || periodSeconds == 0 ||
initialDelaySeconds == 0 || failureThreshold == 0 {
if len(hnd.Exec.Command) == 0 || len(hnd.Exec.Command[0]) == 0 {
log.Error("Readiness probe misconfigured")
return nil, errors.New("Readiness probe misconfigured")
}

probe := &v1.Probe{
Handler: v1.Handler{
Exec: &v1.ExecAction{
Command: command,
},
},
TimeoutSeconds: timeoutSeconds,
PeriodSeconds: periodSeconds,
InitialDelaySeconds: initialDelaySeconds,
FailureThreshold: failureThreshold,
case ProbeTypeHTTP:
hp, err := p.readinessHTTPProbe()
if err != nil {
return nil, err
}

return probe, nil
hnd.HTTPGet = hp
case ProbeTypeTCP:
tcpP, err := p.readinessTCPProbe()
if err != nil {
return nil, err
}

hnd.TCPSocket = tcpP
}

timeoutSeconds := p.readinessProbeTimeout()
periodSeconds := p.readinessProbeInterval()
initialDelaySeconds := p.readinessProbeInitialDelay()
failureThreshold := p.readinessProbeRetries()

if timeoutSeconds == 0 || periodSeconds == 0 || initialDelaySeconds == 0 || failureThreshold == 0 {
log.Error("Readiness probe misconfigured")
return nil, errors.New("Readiness probe misconfigured")
}

probe := &v1.Probe{
Handler: hnd,
TimeoutSeconds: timeoutSeconds,
PeriodSeconds: periodSeconds,
InitialDelaySeconds: initialDelaySeconds,
FailureThreshold: failureThreshold,
}

return nil, nil
return probe, nil
}

// readinessTCPProbe returns a TCPSocketAction if all the necessary information is available.
func (p *ProjectService) readinessTCPProbe() (*v1.TCPSocketAction, error) {
port, ok := p.Labels[config.LabelWorkloadReadinessProbeTCPPort]
if !ok {
return nil, errors.Errorf("%s not correctly defined", config.LabelWorkloadReadinessProbeTCPPort)
}

if port == "" {
return nil, errors.Errorf("%s cannot be empty", config.LabelWorkloadReadinessProbeTCPPort)
}

return &v1.TCPSocketAction{
Port: intstr.FromString(port),
}, nil
}

// readinessHTTPProbe returns an HTTPGetAction if all the necessary information is available.
func (p *ProjectService) readinessHTTPProbe() (*v1.HTTPGetAction, error) {
path, ok := p.Labels[config.LabelWorkloadReadinessProbeHTTPPath]
if !ok {
return nil, errors.Errorf("%s not correctly defined", config.LabelWorkloadReadinessProbeHTTPPath)
}

port, ok := p.Labels[config.LabelWorkloadReadinessProbeHTTPPort]
if !ok {
return nil, errors.Errorf("%s not correctly defined", config.LabelWorkloadReadinessProbeHTTPPort)
}

if port == "" {
return nil, errors.Errorf("%s cannot be empty", config.LabelWorkloadReadinessProbeHTTPPort)
}

return &v1.HTTPGetAction{
Path: path,
Port: intstr.IntOrString{
Type: intstr.String,
StrVal: port,
},
}, nil
}

// readinessProbeCommand returns readiness probe command
Expand Down Expand Up @@ -852,19 +918,18 @@ func (p *ProjectService) readinessProbeRetries() int32 {
return int32(config.DefaultProbeRetries)
}

// readinessProbeDisabled tells whether readiness probe should be activated
func (p *ProjectService) readinessProbeDisabled() bool {
if val, ok := p.Labels[config.LabelWorkloadReadinessProbeDisabled]; ok {
if v, err := strconv.ParseBool(val); err == nil {
return v
}
func (p *ProjectService) readinessProbeType() (*ProbeType, error) {
none := ProbeTypeNone

log.WarnfWithFields(log.Fields{
"project-service": p.Name,
"enabled": val,
}, "Unable to extract Bool value from %s label. Readiness probe will be disabled.",
config.LabelWorkloadReadinessProbeDisabled)
t, ok := p.Labels[config.LabelWorkloadReadinessProbeType]
if !ok {
return &none, nil
}

return true
pt, ok := ProbeTypeFromString(t)
if !ok {
return nil, errors.Errorf("%s is not a supported readiness probe type", t)
}

return &pt, nil
}
Loading

0 comments on commit c9c324f

Please sign in to comment.