Skip to content

Commit

Permalink
feat(discovery): Podman platform (#1394)
Browse files Browse the repository at this point in the history
* tmp

* rebase fixes

* working on experimental podman handler

* update netty native version

* fixup! working on experimental podman handler

* add comment with vertx deps BOM note

* add note about systemctl start podman.socket

* fixup! update netty native version

* fixup netty version

Signed-off-by: Andrew Azores <aazores@redhat.com>

* add security opt flag for mounting podman socket

* cleanup UID lookup, run on worker thread, set API version to 2.3

* add Podman built-in discovery plugin

Signed-off-by: Andrew Azores <aazores@redhat.com>

* use request query param to filter for containers with specific label

* cleanup

* remove obsolete podman API testing endpoints

* improve JMX URL handling, add label to smoketest targets

* perform fewer COW updates

Signed-off-by: Andrew Azores <aazores@redhat.com>

* fix ignored podless containers

* rebase cleanup

* refactor platform selection

allow multiple available strategies to be selected. the highest priority available platform provides the authmanager if none explicitly specified. set of selected strategies can be mapped to set of available platform clients, allowing multiple enabled built-in plugins at once

Signed-off-by: Andrew Azores <aazores@redhat.com>

* deregister builtin plugins if they are no longer available/selected

Signed-off-by: Andrew Azores <aazores@redhat.com>

* CRYOSTAT_PLATFORM takes comma-separated list

Signed-off-by: Andrew Azores <aazores@redhat.com>

---------

Signed-off-by: Andrew Azores <aazores@redhat.com>
  • Loading branch information
andrewazores authored Mar 14, 2023
1 parent ef6b6bd commit d675fef
Show file tree
Hide file tree
Showing 13 changed files with 576 additions and 81 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ Cryostat can be configured via the following environment variables:
* `CRYOSTAT_CORS_ORIGIN`: the origin for CORS to load a different cryostat-web instance. Defaults to the empty string, which disables CORS.
* `CRYOSTAT_MAX_WS_CONNECTIONS`: the maximum number of websocket client connections allowed (minimum 1, maximum `Integer.MAX_VALUE`, default `Integer.MAX_VALUE`)
* `CRYOSTAT_AUTH_MANAGER`: the authentication/authorization manager used for validating user accesses. See the `USER AUTHENTICATION / AUTHORIZATION` section for more details. Set to the fully-qualified class name of the auth manager implementation to use, ex. `io.cryostat.net.BasicAuthManager`. Defaults to an AuthManager corresponding to the selected deployment platform, whether explicit or automatic (see below).
* `CRYOSTAT_PLATFORM`: the platform client used for performing platform-specific actions, such as listing available target JVMs. If `CRYOSTAT_AUTH_MANAGER` is not specified then a default auth manager will also be selected corresponding to the platform, whether that platform is specified by the user or automatically detected. Set to the fully-qualified name of the platform detection strategy implementation to use, ex. `io.cryostat.platform.internal.KubeEnvPlatformStrategy`.
* `CRYOSTAT_PLATFORM`: the platform clients used for performing platform-specific actions, such as listing available target JVMs. If `CRYOSTAT_AUTH_MANAGER` is not specified then a default auth manager will also be selected corresponding to the highest priority platform, whether those platforms are specified by the user or automatically detected. Set to the fully-qualified names of the platform detection strategy implementations to use, ex. `io.cryostat.platform.internal.KubeEnvPlatformStrategy,io.cryostat.platform.internal.PodmanPlatformStrategy`.
* `CRYOSTAT_ENABLE_JDP_BROADCAST`: enable the Cryostat JVM to broadcast itself via JDP (Java Discovery Protocol). Defaults to `true`.
* `CRYOSTAT_JDP_ADDRESS`: the JDP multicast address to send discovery packets. Defaults to `224.0.23.178`.
* `CRYOSTAT_JDP_PORT`: the JDP multicast port to send discovery packets. Defaults to `7095`.
Expand Down
8 changes: 8 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,14 @@
<artifactId>jasypt-hibernate5</artifactId>
<version>${org.jasypt-hibernate5.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport-native-epoll</artifactId>
<classifier>linux-x86_64</classifier>
<version>4.1.86.Final</version><!-- FIXME this should be tied to the vertx version -->
<!-- https://repo1.maven.org/maven2/io/vertx/vertx-dependencies/${io.vertx.web.version}/vertx-dependencies-${io.vertx.web.version}.pom -->
<!-- https://groups.google.com/g/vertx/c/uzzcgw-YuOg -->
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
Expand Down
11 changes: 11 additions & 0 deletions run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,22 @@ if ! podman pod exists cryostat-pod; then
--publish "$CRYOSTAT_EXT_WEB_PORT":"$CRYOSTAT_WEB_PORT"
fi

# do: $ podman system service -t 0
# or do: $ systemctl --user start podman.socket
# to create the podman.sock to volume-mount into the container
#
# to check the podman socket is reachable and connectable within the container:
# $ podman exec -it cryo /bin/sh
# sh-4.4# curl -v -s --unix-socket /run/user/0/podman/podman.sock http://d:80/v3.0.0/libpod/info
#
# run as root (uid 0) within the container - with rootless podman this means
# that the process will actually run with your own uid on the host machine,
# rather than the uid being remapped to something else
podman run \
--pod cryostat-pod \
--name cryostat \
--user 0 \
--label io.cryostat.connectUrl="service:jmx:rmi:///jndi/rmi://localhost:0/jmxrmi" \
--memory 768M \
--mount type=bind,source="$(dirname "$0")/archive",destination=/opt/cryostat.d/recordings.d,relabel=shared \
--mount type=bind,source="$(dirname "$0")/certs",destination=/certs,relabel=shared \
Expand All @@ -122,6 +131,8 @@ podman run \
--mount type=bind,source="$(dirname "$0")/templates",destination=/opt/cryostat.d/templates.d,relabel=shared \
--mount type=bind,source="$(dirname "$0")/truststore",destination=/truststore,relabel=shared \
--mount type=bind,source="$(dirname "$0")/probes",destination=/opt/cryostat.d/conf.d/probes.d,relabel=shared \
-v "$XDG_RUNTIME_DIR"/podman/podman.sock:/run/user/0/podman/podman.sock:Z \
--security-opt label=disable \
-e CRYOSTAT_ENABLE_JDP_BROADCAST="true" \
-e CRYOSTAT_REPORT_GENERATOR="$CRYOSTAT_REPORT_GENERATOR" \
-e CRYOSTAT_PLATFORM="$CRYOSTAT_PLATFORM" \
Expand Down
4 changes: 4 additions & 0 deletions smoketest.sh
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ runDemoApps() {
--env HTTP_PORT=8081 \
--env JMX_PORT=9093 \
--pod cryostat-pod \
--label io.cryostat.connectUrl="service:jmx:rmi:///jndi/rmi://localhost:9093/jmxrmi" \
--rm -d quay.io/andrewazores/vertx-fib-demo:0.9.1

podman run \
Expand All @@ -105,6 +106,7 @@ runDemoApps() {
--env JMX_PORT=9094 \
--env USE_AUTH=true \
--pod cryostat-pod \
--label io.cryostat.connectUrl="service:jmx:rmi:///jndi/rmi://localhost:9094/jmxrmi" \
--rm -d quay.io/andrewazores/vertx-fib-demo:0.9.1

podman run \
Expand All @@ -114,6 +116,7 @@ runDemoApps() {
--env USE_SSL=true \
--env USE_AUTH=true \
--pod cryostat-pod \
--label io.cryostat.connectUrl="service:jmx:rmi:///jndi/rmi://localhost:9095/jmxrmi" \
--rm -d quay.io/andrewazores/vertx-fib-demo:0.9.1

local webPort;
Expand Down Expand Up @@ -234,6 +237,7 @@ runReportGenerator() {
--name reports \
--pull always \
--pod cryostat-pod \
--label io.cryostat.connectUrl="service:jmx:remote+http://localhost:${RJMX_PORT}" \
--cpus 1 \
--memory 512M \
--restart on-failure \
Expand Down
58 changes: 39 additions & 19 deletions src/main/java/io/cryostat/discovery/BuiltInDiscovery.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,19 +37,22 @@
*/
package io.cryostat.discovery;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.UUID;
import java.util.function.Consumer;
import java.util.stream.Stream;

import io.cryostat.configuration.Variables;
import io.cryostat.core.log.Logger;
import io.cryostat.core.sys.Environment;
import io.cryostat.messaging.notifications.NotificationFactory;
import io.cryostat.platform.PlatformClient;
import io.cryostat.platform.TargetDiscoveryEvent;
import io.cryostat.platform.discovery.EnvironmentNode;
import io.cryostat.platform.internal.CustomTargetPlatformClient;
import io.cryostat.platform.internal.PlatformDetectionStrategy;

import dagger.Lazy;
import io.vertx.core.AbstractVerticle;
Expand All @@ -60,33 +63,48 @@ public class BuiltInDiscovery extends AbstractVerticle implements Consumer<Targe
static final String NOTIFICATION_CATEGORY = "TargetJvmDiscovery";

private final DiscoveryStorage storage;
private final Set<PlatformClient> platformClients;
private final Set<PlatformDetectionStrategy<?>> selectedStrategies;
private final Set<PlatformDetectionStrategy<?>> unselectedStrategies;
private final Lazy<CustomTargetPlatformClient> customTargets;
private final Environment env;
private final Set<PlatformClient> enabledClients = new HashSet<>();
private final NotificationFactory notificationFactory;
private final Logger logger;

BuiltInDiscovery(
DiscoveryStorage storage,
Set<PlatformClient> platformClients,
SortedSet<PlatformDetectionStrategy<?>> selectedStrategies,
SortedSet<PlatformDetectionStrategy<?>> unselectedStrategies,
Lazy<CustomTargetPlatformClient> customTargets,
Environment env,
NotificationFactory notificationFactory,
Logger logger) {
this.storage = storage;
this.platformClients = platformClients;
this.selectedStrategies = selectedStrategies;
this.unselectedStrategies = unselectedStrategies;
this.customTargets = customTargets;
this.env = env;
this.notificationFactory = notificationFactory;
this.logger = logger;
}

@Override
public void start(Promise<Void> start) {
storage.addTargetDiscoveryListener(this);
(env.hasEnv(Variables.DISABLE_BUILTIN_DISCOVERY)
? Set.of(customTargets.get())
: platformClients)

unselectedStrategies.stream()
.map(PlatformDetectionStrategy::getPlatformClient)
.forEach(
platform ->
storage.getBuiltInPluginByRealm(
platform.getDiscoveryTree().getName())
.map(PluginInfo::getId)
.ifPresent(storage::deregister));

Stream.concat(
// ensure custom targets is always available regardless of other
// configurations
Stream.of(customTargets.get()),
selectedStrategies.stream()
.map(PlatformDetectionStrategy::getPlatformClient))
.distinct()
.forEach(
platform -> {
logger.info(
Expand Down Expand Up @@ -126,6 +144,7 @@ public void start(Promise<Void> start) {
try {
platform.start();
platform.load(promise);
enabledClients.add(platform);
} catch (Exception e) {
start.fail(e);
}
Expand All @@ -136,14 +155,15 @@ public void start(Promise<Void> start) {
@Override
public void stop() {
storage.removeTargetDiscoveryListener(this);
this.platformClients.forEach(
platform -> {
try {
platform.stop();
} catch (Exception e) {
logger.error(e);
}
});
Iterator<PlatformClient> it = enabledClients.iterator();
while (it.hasNext()) {
try {
it.next().stop();
} catch (Exception e) {
logger.error(e);
}
it.remove();
}
}

@Override
Expand Down
17 changes: 13 additions & 4 deletions src/main/java/io/cryostat/discovery/DiscoveryModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@

import java.time.Duration;
import java.util.Set;
import java.util.SortedSet;

import javax.inject.Named;
import javax.inject.Singleton;
Expand All @@ -50,9 +51,10 @@
import io.cryostat.core.log.Logger;
import io.cryostat.core.sys.Environment;
import io.cryostat.messaging.notifications.NotificationFactory;
import io.cryostat.platform.PlatformClient;
import io.cryostat.platform.PlatformModule;
import io.cryostat.platform.discovery.AbstractNode;
import io.cryostat.platform.internal.CustomTargetPlatformClient;
import io.cryostat.platform.internal.PlatformDetectionStrategy;
import io.cryostat.recordings.JvmIdHelper;
import io.cryostat.rules.MatchExpressionEvaluator;
import io.cryostat.util.PluggableTypeAdapter;
Expand Down Expand Up @@ -116,13 +118,20 @@ static DiscoveryStorage provideDiscoveryStorage(
@Singleton
static BuiltInDiscovery provideBuiltInDiscovery(
DiscoveryStorage storage,
Set<PlatformClient> platformClients,
@Named(PlatformModule.SELECTED_PLATFORMS)
SortedSet<PlatformDetectionStrategy<?>> selectedStrategies,
@Named(PlatformModule.UNSELECTED_PLATFORMS)
SortedSet<PlatformDetectionStrategy<?>> unselectedStrategies,
Lazy<CustomTargetPlatformClient> customTargets,
Environment env,
NotificationFactory notificationFactory,
Logger logger) {
return new BuiltInDiscovery(
storage, platformClients, customTargets, env, notificationFactory, logger);
storage,
selectedStrategies,
unselectedStrategies,
customTargets,
notificationFactory,
logger);
}

@Provides
Expand Down
5 changes: 4 additions & 1 deletion src/main/java/io/cryostat/net/HttpServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,10 @@ public class HttpServer extends AbstractVerticle {
.setPort(netConf.getInternalWebServerPort())
.addWebSocketSubProtocol("*")
.setCompressionSupported(true)
.setLogActivity(true)));
.setLogActivity(true)
.setTcpFastOpen(true)
.setTcpNoDelay(true)
.setTcpQuickAck(true)));

if (!sslConf.enabled()) {
this.logger.warn("No available SSL certificates. Fallback to plain HTTP.");
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/io/cryostat/net/NetworkModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
import dagger.Provides;
import dagger.multibindings.IntoSet;
import io.vertx.core.Vertx;
import io.vertx.core.VertxOptions;
import io.vertx.ext.web.client.WebClient;
import io.vertx.ext.web.client.WebClientOptions;

Expand Down Expand Up @@ -155,7 +156,7 @@ static JFRConnectionToolkit provideJFRConnectionToolkit(
@Provides
@Singleton
static Vertx provideVertx() {
return Vertx.vertx();
return Vertx.vertx(new VertxOptions().setPreferNativeTransport(true));
}

@Provides
Expand Down
Loading

0 comments on commit d675fef

Please sign in to comment.