How to install the JProfiler agent in a Kubernetes container?

4/12/2019

What do I have to put into a container to get the agent to run? Just libjprofilerti.so on its own doesn't work, I get

Could not find agent.jar. The agentpath parameter must point to
libjprofilerti.so in an unmodified JProfiler installation. 

which sounds like obvious nonsense to me - surely I can't have to install over 137.5 MB of files, 99% of which will be irrelevant, in each container in which I want to profile something?

-agentpath:/path/to/libjprofilerti.so=nowait

-- Tim Ward
jprofiler
kubernetes

2 Answers

4/14/2019

An approach is to use Init Container.

The idea is to have an image for JProfiler separate from the application's image. Use the JProfiler image for an Init Container; the Init Container copies the JProfiler installation to a volume shared between that Init Container and the other Containers that will be started in the Pod. This way, the JVM can reference at startup time the JProfiler agent from the shared volume.

It goes something like this (more details are in this blog article):

  • Define a new volume:
volumes:
  - name: jprofiler
    emptyDir: {}
  • Add an Init Container:
initContainers:
  - name: jprofiler-init
    image: <JPROFILER_IMAGE:TAG>
    command: ["/bin/sh", "-c", "cp -R /jprofiler/ /tmp/"]
    volumeMounts:
      - name: jprofiler
        mountPath: "/tmp/jprofiler"

Replace /jprofiler/ above with the correct path to the installation directory in the JProfiler's image. Notice that the copy command will create /tmp/jprofiler directory under which the JProfiler installation will go - that is used as mount path.

  • Define volume mount:
volumeMounts:
  - name: jprofiler
    mountPath: /jprofiler
  • Add to the JVM startup arguments JProfiler as an agent:
-agentpath:/jprofiler/bin/linux-x64/libjprofilerti.so=port=8849

Notice that there isn't a "nowait" argument. That will cause the JVM to block at startup and wait for a JProfiler GUI to connect. The reason is that with this configuration the profiling agent will receive its profiling settings from the JProfiler GUI.

Change the application deployment to start with only one replica. Alternatively, start with zero replicas and scale to one when ready to start profiling.

To connect from the JProfiler's GUI to the remote JVM:

  • Find out the name of the pod (e.g. kubectl -n <namespace> get pods) and set up port forwarding to it:
kubectl -n <namespace> <pod-name> port-forward 8849:8849
  • Start JProfiler up locally and point it to 127.0.0.1, port 8849.

Change the local port 8849 (the number to the left of :) if it isn't available; then, point JProfiler to that different port.

-- apisim
Source: StackOverflow

4/12/2019

Looks like you are missing the general concept here.

It's nicely explained why to use containers in the official documentation.

The New Way is to deploy containers based on operating-system-level virtualization rather than hardware virtualization. These containers are isolated from each other and from the host: they have their own filesystems, they can’t see each others’ processes, and their computational resource usage can be bounded. They are easier to build than VMs, and because they are decoupled from the underlying infrastructure and from the host filesystem, they are portable across clouds and OS distributions.

Of course you don't need to install the libraries on each containers separately.

Kubernetes is using Volumes to share files between Containers. So you can create a local type of Volume with JProfiles libs inside.

A local volume represents a mounted local storage device such as a disk, partition or directory.

You also need to keep in mind that if you share the Volume between Pods, those Pods will not know about JProfiles libs being attached. You will need to configure the Pod with correct environment variables/files through the use of Secrets or ConfigMaps.

You can configure your Pod to pull values from a Secret:

apiVersion: v1
kind: Pod
metadata: 
  labels: 
    context: docker-k8s-lab
    name: jp-pod
  name: jp-pod
spec: 
  containers:
  - image: k8s.gcr.io/busybox
    name: jp
    envFrom:
      secretRef:
        name: jp-secret

jp-secret.yaml

apiVersion: v1
kind: Secret
metadata:
  name: jp-secret
type: Opaque
data:
    JPAGENT_PATH="-agentpath:/usr/local/jprofiler10/bin/linux-x64/libjprofilerti.so=nowait"

I hope this helps you.

-- Crou
Source: StackOverflow