8000 support setting periodSeconds and failureThreashold in the Keyclock CR by KyriosGN0 · Pull Request #40117 · keycloak/keycloak · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

support setting periodSeconds and failureThreashold in the Keyclock CR #40117

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

Merged
merged 9 commits into from
Jun 13, 2025
Merged
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
33 changes: 11 additions & 22 deletions docs/guides/operator/advanced-configuration.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -149,15 +149,9 @@ spec:
secretName: keycloak-additional-secret
----

===== Probe Timeouts
===== Probe Configuration

The unsupported podTemplate may be used to override the default probes.

In particular the default startup probe timeout of 10 minutes may be too short in scenarios where there is a long-running migration.

If your instances encounter this startup failure or if you wish to proactively prevent such a startup failure from occurring, then the startup probe timeout should be increased.

With otherwise default settings, something like the following increases the timeout to 20 minutes:
The Keycloak CR exposes options to set periodSeconds and failureThreshold on each of the three probes (readiness, liveness and startup)

[source,yaml]
----
Expand All @@ -166,22 +160,17 @@ kind: Keycloak
metadata:
name: example-kc
spec:
...
unsupported:
podTemplate:
spec:
containers:
startupProbe:
httpGet:
path: "/health/started"
port: 9000
scheme: "HTTPS"
failureThreshold: 1200
periodSeconds: 1
readinessProbe:
periodSeconds: 20
failureThreshold: 5
livenessProbe:
periodSeconds: 20
failureThreshold: 5
startupProbe:
periodSeconds: 20
failureThreshold: 5
----

Note that the usage of a relative HTTP path, or an alternative management port, requires changes to the probe configuration.

=== Disabling required options

{project_name} and the {project_name} Operator provide the best production-ready experience with security in mind.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
import org.keycloak.operator.crds.v2alpha1.deployment.ValueOrSecret;
import org.keycloak.operator.crds.v2alpha1.deployment.spec.CacheSpec;
import org.keycloak.operator.crds.v2alpha1.deployment.spec.HttpManagementSpec;
import org.keycloak.operator.crds.v2alpha1.deployment.spec.ProbeSpec;
import org.keycloak.operator.crds.v2alpha1.deployment.spec.SchedulingSpec;
import org.keycloak.operator.crds.v2alpha1.deployment.spec.Truststore;
import org.keycloak.operator.crds.v2alpha1.deployment.spec.TruststoreSource;
Expand Down Expand Up @@ -327,15 +328,18 @@ private StatefulSet createBaseDeployment(Keycloak keycloakCR, Context<Keycloak>
// probes
var protocol = isTlsConfigured(keycloakCR) ? "HTTPS" : "HTTP";
var port = HttpManagementSpec.managementPort(keycloakCR);
var readinessOptionalSpec = Optional.ofNullable(keycloakCR.getSpec().getReadinessProbeSpec());
var livenessOptionalSpec = Optional.ofNullable(keycloakCR.getSpec().getLivenessProbeSpec());
var startupOptionalSpec = Optional.ofNullable(keycloakCR.getSpec().getStartupProbeSpec());
var relativePath = readConfigurationValue(Constants.KEYCLOAK_HTTP_MANAGEMENT_RELATIVE_PATH_KEY, keycloakCR, context)
.or(() -> readConfigurationValue(Constants.KEYCLOAK_HTTP_RELATIVE_PATH_KEY, keycloakCR, context))
.map(path -> !path.endsWith("/") ? path + "/" : path)
.orElse("/");

if (!containerBuilder.hasReadinessProbe()) {
containerBuilder.withNewReadinessProbe()
.withPeriodSeconds(10)
.withFailureThreshold(3)
.withPeriodSeconds(readinessOptionalSpec.map(ProbeSpec::getProbePeriodSeconds).orElse(10))
.withFailureThreshold(readinessOptionalSpec.map(ProbeSpec::getProbeFailureThreshold).orElse(3))
.withNewHttpGet()
.withScheme(protocol)
.withNewPort(port)
Expand All @@ -345,8 +349,8 @@ private StatefulSet createBaseDeployment(Keycloak keycloakCR, Context<Keycloak>
}
if (!containerBuilder.hasLivenessProbe()) {
containerBuilder.withNewLivenessProbe()
.withPeriodSeconds(10)
.withFailureThreshold(3)
.withPeriodSeconds(livenessOptionalSpec.map(ProbeSpec::getProbePeriodSeconds).orElse(10))
.withFailureThreshold(livenessOptionalSpec.map(ProbeSpec::getProbeFailureThreshold).orElse(3))
.withNewHttpGet()
.withScheme(protocol)
.withNewPort(port)
Expand All @@ -356,8 +360,8 @@ private StatefulSet createBaseDeployment(Keycloak keycloakCR, Context<Keycloak>
}
if (!containerBuilder.hasStartupProbe()) {
containerBuilder.withNewStartupProbe()
.withPeriodSeconds(1)
.withFailureThreshold(600)
.withPeriodSeconds(startupOptionalSpec.map(ProbeSpec::getProbePeriodSeconds).orElse(1))
.withFailureThreshold(startupOptionalSpec.map(ProbeSpec::getProbeFailureThreshold).orElse(600))
.withNewHttpGet()
.withScheme(protocol)
.withNewPort(port)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.keycloak.operator.crds.v2alpha1.deployment.spec.HttpSpec;
import org.keycloak.operator.crds.v2alpha1.deployment.spec.IngressSpec;
import org.keycloak.operator.crds.v2alpha1.deployment.spec.NetworkPolicySpec;
import org.keycloak.operator.crds.v2alpha1.deployment.spec.ProbeSpec;
import org.keycloak.operator.crds.v2alpha1.deployment.spec.ProxySpec;
import org.keycloak.operator.crds.v2alpha1.deployment.spec.SchedulingSpec;
import org.keycloak.operator.crds.v2alpha1.deployment.spec.TracingSpec;
Expand Down Expand Up @@ -135,6 +136,20 @@ public class KeycloakSpec {
@JsonPropertyDescription("Configuration related to Keycloak deployment updates.")
private UpdateSpec updateSpec;

@JsonProperty("readinessProbe")
@JsonPropertyDescription("Configuration for readiness probe, by default it is 10 for periodSeconds and 3 for failureThreshold")
private ProbeSpec readinessProbeSpec;


@JsonProperty("livenessProbe")
@JsonPropertyDescription("Configuration for liveness probe, by default it is 10 for periodSeconds and 3 for failureThreshold")
private ProbeSpec livenessProbeSpec;

@JsonProperty("startupProbe")
@JsonPropertyDescription("Configuration for startup probe, by default it is 1 for periodSeconds and 600 for failureThreshold")
private ProbeSpec startupProbeSpec;


public HttpSpec getHttpSpec() {
return httpSpec;
}
Expand Down Expand Up @@ -316,4 +331,22 @@ public UpdateSpec getUpdateSpec() {
public void setUpdateSpec(UpdateSpec updateSpec) {
this.updateSpec = updateSpec;
}

public ProbeSpec getLivenessProbeSpec() {return livenessProbeSpec;}

public void setLivenessProbeSpec(ProbeSpec livenessProbeSpec) {
this.livenessProbeSpec = livenessProbeSpec;
}

public ProbeSpec getReadinessProbeSpec() {return readinessProbeSpec;}

public void setReadinessProbeSpec(ProbeSpec readinessProbeSpec) {
this.readinessProbeSpec = readinessProbeSpec;
}

public ProbeSpec getStartupProbeSpec() {return startupProbeSpec;}

public void setStartupProbeSpec(ProbeSpec startupProbeSpec) {
this.startupProbeSpec = startupProbeSpec;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.keycloak.operator.crds.v2alpha1.deployment.spec;


import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.sundr.builder.annotations.Buildable;

@JsonInclude(JsonInclude.Include.NON_NULL)
@Buildable(editableEnabled = false, builderPackage = "io.fabric8.kubernetes.api.builder")
public class ProbeSpec {

@JsonProperty("periodSeconds")
private int probePeriodSeconds;

@JsonProperty("failureThreshold")
private int probeFailureThreshold;

public int getProbeFailureThreshold() {return probeFailureThreshold;}
public void setProbeFailureThreshold(int probeFailureThreshold) {this.probeFailureThreshold = probeFailureThreshold;}
public int getProbePeriodSeconds() {return probePeriodSeconds;}
public void setProbePeriodSeconds(int probePeriodSeconds) {this.probePeriodSeconds = probePeriodSeconds;}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import org.keycloak.operator.crds.v2alpha1.deployment.ValueOrSecret;
import org.keycloak.operator.crds.v2alpha1.deployment.spec.BootstrapAdminSpec;
import org.keycloak.operator.crds.v2alpha1.deployment.spec.HostnameSpecBuilder;
import org.keycloak.operator.crds.v2alpha1.deployment.spec.ProbeSpec;
import org.keycloak.operator.testsuite.apiserver.DisabledIfApiServerTest;
import org.keycloak.operator.testsuite.unit.WatchedResourcesTest;
import org.keycloak.operator.testsuite.utils.CRAssert;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,14 @@ public void testDeserialization() {
HttpManagementSpec managementSpec = keycloak.getSpec().getHttpManagementSpec();
assertNotNull(managementSpec);
assertEquals(9003, managementSpec.getPort());

assertEquals(50,keycloak.getSpec().getReadinessProbeSpec().getProbePeriodSeconds());
assertEquals(3,keycloak.getSpec().getReadinessProbeSpec().getProbeFailureThreshold());
assertEquals(60,keycloak.getSpec().getLivenessProbeSpec().getProbePeriodSeconds());
assertEquals(1,keycloak.getSpec().getLivenessProbeSpec().getProbeFailureThreshold());
assertEquals(40,keycloak.getSpec().getStartupProbeSpec().getProbePeriodSeconds());
assertEquals(2,keycloak.getSpec().getStartupProbeSpec().getProbeFailureThreshold());

}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,37 @@ public void testAffinity() {
assertThat(podTemplate.getSpec().getAffinity()).isNotEqualTo(affinity);
}

@Test
public void testProbe(){
PodTemplateSpec additionalPodTemplate = null;
var readinessProbe = new ProbeBuilder().withFailureThreshold(1).withPeriodSeconds(2).build();
var livenessProbe = new ProbeBuilder().withFailureThreshold(3).withPeriodSeconds(4).build();
var startupProbe = new ProbeBuilder().withFailureThreshold(5).withPeriodSeconds(6).build();
var readinessPodTemplate = getDeployment(additionalPodTemplate, null,
s-> s.withNewReadinessProbeSpec()
.withProbeFailureThreshold(1)
.withProbePeriodSeconds(2)
.endReadinessProbeSpec()).getSpec().getTemplate();
assertThat(readinessPodTemplate.getSpec().getContainers().get(0).getReadinessProbe().getPeriodSeconds()).isEqualTo(readinessProbe.getPeriodSeconds());
assertThat(readinessPodTemplate.getSpec().getContainers().get(0).getReadinessProbe().getFailureThreshold()).isEqualTo(readinessProbe.getFailureThreshold());

var livenessPodTemplate = getDeployment(additionalPodTemplate, null,
s-> s.withNewLivenessProbeSpec()
.withProbeFailureThreshold(3)
.withProbePeriodSeconds(4)
.endLivenessProbeSpec()).getSpec().getTemplate();
assertThat(livenessPodTemplate.getSpec().getContainers().get(0).getLivenessProbe().getPeriodSeconds()).isEqualTo(livenessProbe.getPeriodSeconds());
assertThat(livenessPodTemplate.getSpec().getContainers().get(0).getLivenessProbe().getFailureThreshold()).isEqualTo(livenessProbe.getFailureThreshold());

var startupPodTemplate = getDeployment(additionalPodTemplate, null,
s-> s.withNewStartupProbeSpec()
.withProbeFailureThreshold(5)
.withProbePeriodSeconds(6)
.endStartupProbeSpec()).getSpec().getTemplate();
assertThat(startupPodTemplate.getSpec().getContainers().get(0).getStartupProbe().getPeriodSeconds()).isEqualTo(startupProbe.getPeriodSeconds());
assertThat(startupPodTemplate.getSpec().getContainers().get(0).getStartupProbe().getFailureThreshold()).isEqualTo(startupProbe.getFailureThreshold());
}

private Job getUpdateJob(Consumer<KeycloakSpecBuilder> newSpec, Consumer<KeycloakSpecBuilder> oldSpec, Consumer<StatefulSetBuilder> existingModifier) {
// create an existing from the old spec and modifier
StatefulSetBuilder existingBuilder = getDeployment(null, null, oldSpec).toBuilder();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,15 @@ spec:
annotations:
myAnnotation: myValue
anotherAnnotation: anotherValue
readinessProbe:
periodSeconds: 50
failureThreshold: 3
livenessProbe:
periodSeconds: 60
failureThreshold: 1
startupProbe:
periodSeconds: 40
failureThreshold: 2
networkPolicy:
enabled: true
http:
Expand Down
Loading
0