Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(kubernetes): More configurable readiness/liveness probes #1598

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,10 @@ protected void executeThis() {
vault = new DeploymentEnvironment.Vault();
}

DeploymentEnvironment.LivenessProbeConfig livenessProbeConfig =
DeploymentEnvironment.K8SProbeConfig livenessProbeConfig =
deploymentEnvironment.getLivenessProbeConfig();
if (livenessProbeConfig == null) {
livenessProbeConfig = new DeploymentEnvironment.LivenessProbeConfig();
livenessProbeConfig = new DeploymentEnvironment.K8SProbeConfig();
}

deploymentEnvironment.setAccountName(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ public String getContainerSuffix() {
private Map<String, List<Toleration>> tolerations = new HashMap<>();
private Map<String, String> nodeSelectors = new HashMap<>();
private GitConfig gitConfig = new GitConfig();
private LivenessProbeConfig livenessProbeConfig = new LivenessProbeConfig();
private K8SProbeConfig livenessProbeConfig = new K8SProbeConfig();
private K8SProbeConfig readinessProbeConfig = new K8SProbeConfig();

@ValidForSpinnakerVersion(
lowerBound = "1.10.0",
Expand Down Expand Up @@ -167,8 +168,12 @@ public static class GitConfig {
}

@Data
public static class LivenessProbeConfig {
public static class K8SProbeConfig {
boolean enabled;
Integer initialDelaySeconds;
Integer periodSeconds;
Integer timeoutSeconds;
Integer successThreshold;
Integer failureThreshold;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ default KubernetesContainerDescription buildContainer(
readinessProbe.setHandler(readinessHandler);
container.setReadinessProbe(readinessProbe);

DeploymentEnvironment.LivenessProbeConfig livenessProbeConfig =
DeploymentEnvironment.K8SProbeConfig livenessProbeConfig =
deploymentEnvironment.getLivenessProbeConfig();
if (livenessProbeConfig != null
&& livenessProbeConfig.isEnabled()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ static Container buildContainer(
ProbeBuilder readinessProbeBuilder = buildProbeBuilder(port, scheme, healthEndpoint, null);
ProbeBuilder livenessProbeBuilder = null;

DeploymentEnvironment.LivenessProbeConfig livenessProbeConfig =
DeploymentEnvironment.K8SProbeConfig livenessProbeConfig =
deploymentEnvironment.getLivenessProbeConfig();
if (livenessProbeConfig != null
&& livenessProbeConfig.isEnabled()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import javax.annotation.Nonnull;
import org.apache.commons.lang3.StringUtils;

public interface KubernetesV2Service<T> extends HasServiceSettings<T>, KubernetesService {
Expand Down Expand Up @@ -410,16 +411,17 @@ default String buildContainer(
container.addBinding("port", port.toString());
container.addBinding("volumeMounts", volumeMounts);

TemplatedResource readinessProbe = getProbe(settings, null);
DeploymentEnvironment.K8SProbeConfig readinessProbeConfig =
deploymentEnvironment.getReadinessProbeConfig();
TemplatedResource readinessProbe = getProbe(settings, readinessProbeConfig);
container.addBinding("readinessProbe", readinessProbe.toString());

DeploymentEnvironment.LivenessProbeConfig livenessProbeConfig =
DeploymentEnvironment.K8SProbeConfig livenessProbeConfig =
deploymentEnvironment.getLivenessProbeConfig();
if (livenessProbeConfig != null
&& livenessProbeConfig.isEnabled()
&& livenessProbeConfig.getInitialDelaySeconds() != null) {
TemplatedResource livenessProbe =
getProbe(settings, livenessProbeConfig.getInitialDelaySeconds());
TemplatedResource livenessProbe = getProbe(settings, livenessProbeConfig);
container.addBinding("livenessProbe", livenessProbe.toString());
}

Expand All @@ -430,7 +432,8 @@ default String buildContainer(
return container.toString();
}

default TemplatedResource getProbe(ServiceSettings settings, Integer initialDelaySeconds) {
default TemplatedResource getProbe(
ServiceSettings settings, @Nonnull DeploymentEnvironment.K8SProbeConfig probeConfig) {
TemplatedResource probe;
if (StringUtils.isEmpty(settings.getHealthEndpoint())
|| settings.getKubernetes().getUseTcpProbe()) {
Expand All @@ -445,7 +448,13 @@ default TemplatedResource getProbe(ServiceSettings settings, Integer initialDela
probe.addBinding("path", settings.getHealthEndpoint());
probe.addBinding("scheme", settings.getScheme().toUpperCase());
}
probe.addBinding("initialDelaySeconds", initialDelaySeconds);

probe.addBinding("initialDelaySeconds", probeConfig.getInitialDelaySeconds());
probe.addBinding("periodSeconds", probeConfig.getPeriodSeconds());
probe.addBinding("timeoutSeconds", probeConfig.getTimeoutSeconds());
probe.addBinding("successThreshold", probeConfig.getSuccessThreshold());
probe.addBinding("failureThreshold", probeConfig.getFailureThreshold());

return probe;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,9 @@
{% endfor %}
]
},
"initialDelaySeconds": {{ initialDelaySeconds }}
"initialDelaySeconds": {{ initialDelaySeconds }},
"periodSeconds": {{ periodSeconds }},
"timeoutSeconds": {{ timeoutSeconds }},
"successThreshold": {{ successThreshold }},
"failureThreshold": {{ failureThreshold }}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,9 @@
"path": "{{ path }}",
"scheme": "{{ scheme }}"
},
"initialDelaySeconds": {{ initialDelaySeconds }}
"initialDelaySeconds": {{ initialDelaySeconds }},
"periodSeconds": {{ periodSeconds }},
"timeoutSeconds": {{ timeoutSeconds }},
"successThreshold": {{ successThreshold }},
"failureThreshold": {{ failureThreshold }}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,9 @@
"tcpSocket": {
"port": {{ port }}
},
"initialDelaySeconds": {{ initialDelaySeconds }}
"initialDelaySeconds": {{ initialDelaySeconds }},
"periodSeconds": {{ periodSeconds }},
"timeoutSeconds": {{ timeoutSeconds }},
"successThreshold": {{ successThreshold }},
"failureThreshold": {{ failureThreshold }}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import com.fasterxml.jackson.databind.ObjectMapper
import com.netflix.spinnaker.halyard.config.config.v1.StrictObjectMapper
import com.netflix.spinnaker.halyard.config.model.v1.node.AffinityConfig
import com.netflix.spinnaker.halyard.config.model.v1.node.DeploymentConfiguration
import com.netflix.spinnaker.halyard.config.model.v1.node.DeploymentEnvironment
import com.netflix.spinnaker.halyard.config.model.v1.node.SidecarConfig
import com.netflix.spinnaker.halyard.config.model.v1.node.Toleration
import com.netflix.spinnaker.halyard.config.model.v1.providers.kubernetes.KubernetesAccount
Expand Down Expand Up @@ -422,13 +423,10 @@ class KubernetesV2ServiceTest extends Specification {
yaml.contains('''"readinessProbe": {
"tcpSocket": {
"port": 8000
},
"initialDelaySeconds":
}
''')
}''')
}

def "Readiness probe"() {
def "Readiness probe type"() {
setup:
def settings = new KubernetesSettings()
serviceSettings.kubernetes = settings
Expand All @@ -443,7 +441,7 @@ class KubernetesV2ServiceTest extends Specification {
}

when:
String yaml = testService.getProbe(serviceSettings, null).toString()
String yaml = testService.getProbe(serviceSettings, new DeploymentEnvironment.K8SProbeConfig()).toString()

then:
yaml.contains(readinessProbeResult)
Expand All @@ -456,4 +454,34 @@ class KubernetesV2ServiceTest extends Specification {
"exec probe on" | null | true | "exec"
"exec probe off" | null | false | "http"
}

def "Readiness probe config"() {
setup:
def settings = new KubernetesSettings()
serviceSettings.kubernetes = settings
serviceSettings.port = 8000
serviceSettings.scheme = "http"
serviceSettings.healthEndpoint = "/health"
settings.useTcpProbe = true

def probeSettings = new DeploymentEnvironment.K8SProbeConfig()
probeSettings.enabled = true;
probeSettings.failureThreshold = failureThreshold
probeSettings.successThreshold = successThreshold
probeSettings.initialDelaySeconds = initialDelaySeconds
probeSettings.periodSeconds = periodSeconds
probeSettings.timeoutSeconds = timeoutSeconds

when:
String yaml = testService.getProbe(serviceSettings, probeSettings).toString()

then:
for(def prop : probeSettings.properties) {
yaml.contains("\"${prop.key}\": ${prop.value}")
}

where:
description | failureThreshold | successThreshold | initialDelaySeconds | periodSeconds | timeoutSeconds
"all set" | 5 | 2 | 300 | 10 | 20
}
}