<p>I want to monitor internals of JVM for my Spring Boot application inside a Docker which is running as a pod in a Kubernetes cluster. But I couldn't find satisfactory answer anywhere even after spending considerable time. 
I tried referring the accepted answer on <a href="https://stackoverflow.com/questions/31257968/how-to-access-jmx-interface-in-docker-from-outside">this</a> but it was connecting only when my docker was running locally, and ceased to connect while behind a Kubernetes cluster. </p>

<p>Assume I wanted to monitor on port 8001 while my app was serving on 8000. 
Adding these to my VM options worked fine(VisualVM was showing this process for monitoring) while running Docker locally and mapping port 8001 from my local to Docker(-p 8001:8001)</p>

<pre><code>-Dcom.sun.management.jmxremote \
-Djava.rmi.server.hostname=localhost \
-Dcom.sun.management.jmxremote.port=8001 \
-Dcom.sun.management.jmxremote.rmi.port=8001 \
-Dcom.sun.management.jmxremote.local.only=false \
-Dcom.sun.management.jmxremote.authenticate=false \
-Dcom.sun.management.jmxremote.ssl=false
</code></pre>

<p>But it didn't work on a pod in remote Kubernetes Cluster. I found <a href="https://medium.com/cloud-native-the-gathering/remotely-connecting-through-kubernetes-to-a-jmx-agent-in-a-spring-boot-1-x-cf83bb83f499" rel="noreferrer">this</a> but my requirement was to monitor without going via Service and then by reading couple of other articles I got it working, so collating those steps below for saving someone's time:-</p>

<ol>
<li>Removed VM options mentioned above in the startup script</li>
<li>Updated my application.yaml as below where I enabled jmx and added url for running JMXMP Connector server</li>
</ol>

<pre><code>spring:
  application:
    name: stack-application
  jmx:
    enabled: true
    url: service:jmx:jmxmp://localhost:8001/
server:
  port: 8000
</code></pre>

<ol start="3">
<li>Updated my Kubernetes deployment YAML under Deployment block as:</li>
</ol>

<pre><code>apiVersion: apps/v1
kind: Deployment
----your content----
          ports:
            - name: stack-app-port
              containerPort: 8000
            - name: stack-jmx-port
              containerPort: 8001
</code></pre>

<ol start="4">
<li>Added following dependency to my pom.xml for downloading <a href="https://docs.oracle.com/cd/E19698-01/816-7609/connectors-116/index.html" rel="noreferrer">JMXMP</a> as after my research I concluded that JMX monitoring over RMI is a tough job and hence JMXMP is everyone's recommendation.</li>
</ol>

<pre><code>        &lt;dependency&gt;
            &lt;groupId&gt;org.glassfish.main.external&lt;/groupId&gt;
            &lt;artifactId&gt;jmxremote_optional-repackaged&lt;/artifactId&gt;
            &lt;version&gt;5.0&lt;/version&gt;
        &lt;/dependency&gt;
</code></pre>

<ol start="5">
<li>Created a new class <code>ConnectorServiceFactoryBeanProvider</code> which fetches URL from our application.yaml</li>
</ol>

<pre><code>@Configuration
public class ConnectorServiceFactoryBeanProvider {
    @Value("${spring.jmx.url}")
    private String url;

    @Bean
    public ConnectorServerFactoryBean connectorServerFactoryBean() throws Exception {
        final ConnectorServerFactoryBean connectorServerFactoryBean = new ConnectorServerFactoryBean();
        connectorServerFactoryBean.setServiceUrl(url);
        return connectorServerFactoryBean;
    }
}
</code></pre>

<ol start="6">
<li>Build and deploy your docker on Kubernetes and find out the IP address of the pod. You may use <code>kubectl describe pod</code> for that on CLI</li>
<li>Now to start VisualVM, we also need to add the JMXMP jar downloaded above in classpath. I created an alias to do the same, and since the JAR was downloaded in my local .m2 directory the command looked like this:- </li>
</ol>

<pre><code>alias viz='jvisualvm -cp "$JAVA_HOME:~/.m2/repository/org/glassfish/main/external/jmxremote_optional-repackaged/5.0/jmxremote_optional-repackaged-5.0.jar"'
</code></pre>

<ol start="8">
<li>Now, execute "viz" or your alias, it'll start the Visual VM application shipped with your Java. </li>
<li>Click on the +JMX icon in the toolbar of VisualVM or go to (File -> Add JMX Connection...) add the link </li>
</ol>

<pre><code>service:jmx:jmxmp://&lt;IP address obtained in step 6 above&gt;:8001
</code></pre>

<p>and Check "Do not require SSL connection". Once you hit OK, you should see your remote application internals on VisualVM in a while. Screenshot attached below. </p>

<p><a href="https://i.stack.imgur.com/544OE.png" rel="noreferrer">VisualVM screenshot monitoring remote app on 8001</a></p>
