You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by cl...@apache.org on 2025/03/14 09:25:36 UTC

(camel) branch main updated: CAMEL-21842 camel-jbang-plugin-kubernetes pod startup probe fails because of wrong path (#17418)

This is an automated email from the ASF dual-hosted git repository.

claudio4j pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/main by this push:
     new 7f4221292f2 CAMEL-21842 camel-jbang-plugin-kubernetes pod startup probe fails because of wrong path (#17418)
7f4221292f2 is described below

commit 7f4221292f2b505a9e72e69dc1ae0f88dfc18fd1
Author: Claudio Miranda <cl...@claudius.com.br>
AuthorDate: Fri Mar 14 06:25:30 2025 -0300

    CAMEL-21842 camel-jbang-plugin-kubernetes pod startup probe fails because of wrong path (#17418)
---
 .../modules/ROOT/pages/camel-jbang-kubernetes.adoc | 25 +++++++++++++++++++++
 .../templates/spring-boot-kubernetes-pom.tmpl      |  4 ++++
 .../core/commands/kubernetes/KubernetesExport.java | 26 ++++++++++++++++++++++
 .../kubernetes/support/StubComponentResolver.java  |  2 +-
 .../commands/kubernetes/KubernetesExportTest.java  |  9 ++++++++
 .../commands/kubernetes/KubernetesRunTest.java     | 11 +++++++++
 6 files changed, 76 insertions(+), 1 deletion(-)

diff --git a/docs/user-manual/modules/ROOT/pages/camel-jbang-kubernetes.adoc b/docs/user-manual/modules/ROOT/pages/camel-jbang-kubernetes.adoc
index 39c058df18c..ee800b99008 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-jbang-kubernetes.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-jbang-kubernetes.adoc
@@ -180,6 +180,31 @@ The Kubernetes plugin export command also inherits all options from the arbitrar
 
 TIP: See the possible options by running: `camel kubernetes export --help` for more details.
 
+=== Kubernetes Container Health Probes
+
+The xref:components::observability-services.adoc[Observability Services] component is set by default in the project created by the export command, then the health path probes are prefixed with the `/observe` endpoint, regardless if they are Quarkus or Spring Boot.
+
+These are the HTTP Container probe endpoints.
+
+For Quarkus.
+[source]
+----
+/observe/health/live
+/observe/health/ready
+/observe/health/started
+----
+
+For Spring Boot (there is no startup probe)
+[source]
+----
+/observe/health/liveness
+/observe/health/readiness
+----
+
+Note that these container probes are generated by jkube plugin, when you run the `k8s:resource` to generate the manifests in the `target/kubernetes/kubernetes.yml`.
+
+You can export to a project and manually remove the `camel-observability-services` artifact from the `pom.xml`.
+
 == Kubernetes manifest options
 
 The Kubernetes manifest (kubernetes.yml) describes all resources to successfully run the application on Kubernetes.
diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-kubernetes-pom.tmpl b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-kubernetes-pom.tmpl
index 0a20a5ec24c..7de1b7bc0f0 100644
--- a/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-kubernetes-pom.tmpl
+++ b/dsl/camel-jbang/camel-jbang-core/src/main/resources/templates/spring-boot-kubernetes-pom.tmpl
@@ -55,6 +55,10 @@
             <groupId>org.apache.camel.springboot</groupId>
             <artifactId>camel-spring-boot-starter</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.camel.springboot</groupId>
+            <artifactId>camel-observability-services-starter</artifactId>
+        </dependency>
 {{ .CamelDependencies }}
         <dependency>
             <groupId>org.springframework.boot</groupId>
diff --git a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExport.java b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExport.java
index 4e55e823916..301675cf75f 100644
--- a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExport.java
+++ b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExport.java
@@ -331,6 +331,8 @@ public class KubernetesExport extends Export {
         var jkubeVersion = jkubeMavenPluginVersion(settings, mapBuildProperties());
         buildProperties.add("jkube.version=%s".formatted(jkubeVersion));
 
+        setContainerHealthPaths();
+
         // Run export
         int exit = super.export();
         if (exit != 0) {
@@ -455,6 +457,30 @@ public class KubernetesExport extends Export {
         return null;
     }
 
+    private void setContainerHealthPaths() {
+        // the camel-observability-services artifact is set in the pom template
+        // it renames the container health base path to /observe, so this has to be in the container health probes http path
+        // only quarkus and sb runtimes, because there is no published health endpoints when using runtime=main
+        if (RuntimeType.quarkus == runtime) {
+            // jkube reads quarkus properties to set the container health probes path
+            buildProperties.add("quarkus.smallrye-health.root-path=/observe/health");
+        } else if (RuntimeType.springBoot == runtime) {
+            List<String> newProps = new ArrayList<>();
+            // jkube reads spring-boot properties to set the kubernetes container health probes path
+            // in this case, jkube reads from the application.properties and not from the build properties in pom.xml
+            newProps.add("management.endpoints.web.base-path=/observe");
+            // jkube uses the old property to enable the readiness/liveness probes
+            // TODO: rename this property once https://github.com/eclipse-jkube/jkube/issues/3690 is fixed
+            newProps.add("management.health.probes.enabled=true");
+            if (applicationProperties == null) {
+                applicationProperties = newProps.toArray(new String[newProps.size()]);
+            } else {
+                newProps.addAll(Arrays.asList(applicationProperties));
+                applicationProperties = newProps.toArray(new String[newProps.size()]);
+            }
+        }
+    }
+
     private String extractImageGroup(String image) {
         String[] parts = image.split("/");
         if (parts.length == 3) {
diff --git a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/support/StubComponentResolver.java b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/support/StubComponentResolver.java
index 7429bbc82b4..b63512336ef 100644
--- a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/support/StubComponentResolver.java
+++ b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/support/StubComponentResolver.java
@@ -27,7 +27,7 @@ import org.apache.camel.impl.engine.DefaultComponentResolver;
 
 public final class StubComponentResolver extends DefaultComponentResolver {
     private static final Set<String> ACCEPTED_STUB_NAMES = Set.of(
-            "stub", "bean", "class", "direct", "kamelet", "log", "rest", "rest-api", "seda", "vertx-http");
+            "stub", "bean", "class", "direct", "kamelet", "log", "platform-http", "rest", "rest-api", "seda", "vertx-http");
 
     private final Set<String> names;
     private final String stubPattern;
diff --git a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExportTest.java b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExportTest.java
index c49cf8b7359..27499e307a8 100644
--- a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExportTest.java
+++ b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExportTest.java
@@ -69,6 +69,10 @@ class KubernetesExportTest extends KubernetesExportBaseTest {
         Assertions.assertNull(props.get("jkube.docker.push.registry"));
         Assertions.assertNull(props.get("jkube.container-image.registry"));
         Assertions.assertNull(props.get("jkube.container-image.platforms"));
+
+        if (RuntimeType.quarkus == RuntimeType.fromValue(rt.runtime())) {
+            Assertions.assertEquals("/observe/health", props.get("quarkus.smallrye-health.root-path"));
+        }
     }
 
     @ParameterizedTest
@@ -160,6 +164,11 @@ class KubernetesExportTest extends KubernetesExportBaseTest {
 
         Assertions.assertEquals("bar", applicationProperties.get("foo"));
         Assertions.assertEquals("baz", applicationProperties.get("bar"));
+
+        if (RuntimeType.springBoot == RuntimeType.fromValue(rt.runtime())) {
+            Assertions.assertEquals("/observe", applicationProperties.get("management.endpoints.web.base-path"));
+            Assertions.assertEquals("true", applicationProperties.get("management.health.probes.enabled"));
+        }
     }
 
     @ParameterizedTest
diff --git a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesRunTest.java b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesRunTest.java
index fe5943d1088..f854c4d4e0e 100644
--- a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesRunTest.java
+++ b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/test/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesRunTest.java
@@ -105,6 +105,17 @@ class KubernetesRunTest extends KubernetesBaseTest {
         Assertions.assertEquals("route", matchLabels.get(BaseTrait.KUBERNETES_LABEL_NAME));
         Assertions.assertEquals("quay.io/camel-test/route:1.0-SNAPSHOT", containers.get(0).getImage());
         Assertions.assertEquals("IfNotPresent", containers.get(0).getImagePullPolicy());
+
+        // verify the container health probes path to /observe accordingly to the camel-observability-services
+        if (RuntimeType.quarkus == RuntimeType.fromValue(rt.runtime())) {
+            Assertions.assertEquals("/observe/health/live", containers.get(0).getLivenessProbe().getHttpGet().getPath());
+            Assertions.assertEquals("/observe/health/ready", containers.get(0).getReadinessProbe().getHttpGet().getPath());
+            Assertions.assertEquals("/observe/health/started", containers.get(0).getStartupProbe().getHttpGet().getPath());
+        } else if (RuntimeType.springBoot == RuntimeType.fromValue(rt.runtime())) {
+            // spring-boot doesn't set the startup probe
+            Assertions.assertEquals("/observe/health/liveness", containers.get(0).getLivenessProbe().getHttpGet().getPath());
+            Assertions.assertEquals("/observe/health/readiness", containers.get(0).getReadinessProbe().getHttpGet().getPath());
+        }
     }
 
     @ParameterizedTest