⚗️ Installing kubectl inside container

This commit is contained in:
Andreas Dinauer 2025-06-07 11:22:52 +02:00
parent b40ba6c8ee
commit dc633ead9d
4 changed files with 50 additions and 17 deletions

View File

@ -78,20 +78,36 @@
# accessed directly. (example: "foo.example.com,bar.example.com")
#
###
FROM registry.access.redhat.com/ubi9/openjdk-21:1.21
FROM eclipse-temurin:21-jdk
ENV LANGUAGE='en_US:en'
WORKDIR /root
RUN apt-get update && \
apt-get install -y apt-transport-https ca-certificates curl gnupg && \
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.33/deb/Release.key | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg && \
chmod 644 /etc/apt/keyrings/kubernetes-apt-keyring.gpg && \
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.33/deb/ /' | tee /etc/apt/sources.list.d/kubernetes.list && \
chmod 644 /etc/apt/sources.list.d/kubernetes.list && \
apt-get update && \
apt-get install -y kubectl
RUN useradd -m quarkus
WORKDIR /etc/build
# We make four distinct layers so if there are application changes the library layers can be re-used
COPY --chown=185 target/quarkus-app/lib/ /deployments/lib/
COPY --chown=185 target/quarkus-app/*.jar /deployments/
COPY --chown=185 target/quarkus-app/app/ /deployments/app/
COPY --chown=185 target/quarkus-app/quarkus/ /deployments/quarkus/
COPY target/quarkus-app/lib/ /deployments/lib/
COPY target/quarkus-app/*.jar /deployments/
COPY target/quarkus-app/app/ /deployments/app/
COPY target/quarkus-app/quarkus/ /deployments/quarkus/
EXPOSE 8080
USER 185
ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
USER quarkus
ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0"
ENV JAVA_APP_JAR="/deployments/quarkus-run.jar"
ENTRYPOINT [ "/opt/jboss/container/java/run/run-java.sh" ]
CMD ["java","-jar","/deployments/quarkus-run.jar"]

View File

@ -12,6 +12,8 @@ import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.BufferedReader;
import java.io.IOException;
@ -24,6 +26,8 @@ import java.util.List;
@Authenticated
public class NodeResource
{
private static final Logger LOG = LoggerFactory.getLogger(NodeResource.class);
@Inject
ClientProvider clientProvider;
@ -34,6 +38,7 @@ public class NodeResource
List<NodeStats> result = new ArrayList<>();
List<String> stats = getTopNodes();
for(String nodeName : stats)
{
String[] parts = nodeName.split("\\s+");
@ -53,7 +58,9 @@ public class NodeResource
private List<String> getTopNodes() throws IOException, InterruptedException
{
ProcessBuilder pb = new ProcessBuilder(List.of("kubectl", "top", "nodes", "--no-headers"));
List<String> commands = List.of("kubectl", String.format("--kubeconfig=%s", clientProvider.pathToKubeconfig()), "top", "nodes", "--no-headers");
LOG.info("Executing command: {}", String.join(" ", commands));
ProcessBuilder pb = new ProcessBuilder(commands);
Process p = pb.start();
List<String> text = new ArrayList<>();
@ -65,9 +72,14 @@ public class NodeResource
text.add(line);
}
}
p.waitFor();
int exitCode = p.waitFor();
if(exitCode == 0)
{
LOG.info("Found {} nodes", text.size());
return text;
}
throw new RuntimeException("Failed to retrieve top nodes.");
}
public record NodeStats(Node node, Integer absoluteCpuUsage, Integer relativeCpuUsage, Integer totalCpu, Integer absoluteMemory, Integer relativeMemory, Integer totalMemory)
{

View File

@ -1,29 +1,32 @@
package dev.dinauer.utils;
import io.fabric8.kubernetes.client.Config;
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
import io.fabric8.kubernetes.client.extension.ExtensionAdapter;
import io.fabric8.kubernetes.client.http.HttpClient;
import io.fabric8.kubernetes.client.vertx.VertxHttpClientBuilder;
import io.fabric8.kubernetes.client.vertx.VertxHttpClientFactory;
import io.vertx.mutiny.core.Vertx;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import org.eclipse.microprofile.config.ConfigProvider;
import org.eclipse.microprofile.config.inject.ConfigProperty;
import java.io.File;
@ApplicationScoped
public class ClientProvider
{
@ConfigProperty(name = "dev.dinauer.kobooboo.kubeconfigs.dir")
String configFilePath;
@Inject
Vertx vertx;
public KubernetesClient getClient()
{
String configFilePath = ConfigProvider.getConfig().getValue("dev.dinauer.kobooboo.kubeconfigs.dir", String.class);
return new KubernetesClientBuilder().withConfig(Config.fromKubeconfig(new File(configFilePath))).withHttpClientFactory(new VertxHttpClientFactory(vertx.getDelegate())).build();
}
public String pathToKubeconfig()
{
return configFilePath;
}
}

View File

@ -3,6 +3,7 @@ package dev.dinauer.utils;
import dev.dinauer.login.User;
import dev.dinauer.login.UserRepo;
import io.quarkus.elytron.security.common.BcryptUtil;
import io.quarkus.runtime.Startup;
import jakarta.annotation.PostConstruct;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
@ -10,6 +11,7 @@ import jakarta.inject.Inject;
import java.io.IOException;
import java.util.Set;
@Startup
@ApplicationScoped
public class StartupService
{