In my previous article, we explored ways on how to monitor Dockerized apps in vanilla Docker environments with Dynatrace Application Monitoring. In this article, we will elaborate on monitoring Dockerized applications in Kubernetes and Red Hat OpenShift (v3) environments. If you are unsure how these two container platform technologies relate to each other, real quick, OpenShift is Kubernetes for the enterprise.

As described in the previous article, depending on your particular situation, you may find the one or the other of the following approaches more suitable. Again, to make your decision easier, we have listed known pros and cons.

Option A: Inheritance-based approach

The goal of the "inheritance-based approach" is to bake the Dynatrace Application Monitoring agent into your Docker base images. Since Kubernetes and OpenShift are both container platforms, this approach allows you to smoothly reuse your monitoring enabled images on any of these platforms. Almost. Since OpenShift is a secure container platform, running containers, where processes are executed as "root" (which is how most Docker images have been built so far) is prohibited default. Please refer to the OpenShift Container Image Guidelines on how to prepare your Docker images for OpenShift. For information on how to apply this approach to your Docker images, please refer to our previous article.

Example: Java

Since the particular technologies inside your base images have already been enabled to being monitored by Dynatrace, some simple configuration settings at runtime that bind the agent to the Dynatrace Application Monitoring Collector will be sufficient.

The following example defines a ReplicationController with a container named catalog inside an inline Pod. The environment variables DT_AGENT_NAME and DT_AGENT_COLLECTOR (as defined in our previous article) override the respective values provided in a fictitious acmeco/my-app's base image .

Example: NGINX

Since the particular technologies inside your base images have already been enabled to being monitored by Dynatrace, some simple configuration settings at runtime that bind the agent to the Dynatrace Application Monitoring Collector will be sufficient.

The following example defines a ReplicationController with a container named api-gateway inside an inline Pod. The environment variables DT_WSAGENT_NAME and DT_WSAGENT_COLLECTOR (as defined in our previous article) override the respective values provided in a fictitious acmeco/my-app's base image .

Analysis

  • On the pros side we find that, once the agent has been baked into your Docker base images, it doesn't matter much on which container platform you eventually run your applications. We also find that this approach neatly reduces the integration of a monitoring solution like Dynatrace to less frequent, preparatory work that does not add any overhead to the much more frequent process of building, shipping and running Dockerized applications.
  • On the cons side, depending on your particular use-case and on the technologies you use, you'll have to integrate with each of these technologies by hand. And since this approach tightly ties together the agent with a particular technology in the same base image, these base images may altogether have to be recreated when switching to a new version of either the technology or of Dynatrace Application Monitoring.

Option B: Composition-based approach

With the "composition-based" approach, we equip you with the dynatrace/agent Docker image that includes all variants of the Dynatrace Application Montitoring agent -- that you can attach to your existing Docker containers by simple means of configuration! For information on how this approach actually works, please refer to our previous article.

Examples

The following examples integrates the dynatrace/agent Docker image with a fictitious container acmeco/my-app inside a ReplicationController. To mimic Docker innate capability of exchanging volumes between containers (as described in our previous article), a variety of manual steps have to be carried through to achieve the same behavior on Kubernetes-based platforms. First, let's see what the replication controller looks like without the agent in place.

1. Make the agent available inside the application container

In order to do that, we first need to declare a (shared) Volume inside the Pod definition. In the following example, we set the volume to be an empty directory on the container's underlying host.

Next, we add the dynatrace/agent Docker image to the list of containers, have it mount the volume and use the Container Lifecycle Hook postStart to copy the agent installation present in /dynatrace inside dynatrace/oneagent to /srv/dynatrace (which equals the mount path of the volume).

Please note that the dtappmon-agent container needs to be defined before any application containers that want make use of it. If this order is not maintained, the application container may not be able to eventually pick up the agent once it's started. Finally, we have the application container mount the agent installation directory from the shared volume.

2. Load the agent into the application's process: Java

2. Load the agent into the application's process: NGINX

And this finalizes the composition-based approach. Let's take a look at the analysis.

Analysis

  • On the pros side we find that this approach neatly contributes to a clean separation of concerns, which is a design principle in the containers world. Also, you don't have to care about getting agents into your base images, a simple configuration at runtime is all you need to get your containers monitored.
  • On the cons side, while the Docker runtime has great support for exchanging volumes between containers, doing so on a container orchestration platform such as Kubernetes or OpenShift can render your application configurations overly complex.
  1. Anonymous (login to see details)

    Starting with OpenShift 3.6/Kubernetes 1.6 using initContainers seems like a good option for configuring an AppMon Agent.

    Would it be possible to provide an example config?

    FYI here's a Github Repo showcasing an iniContainer-Pattern to set up a New Relic Agent:

    https://github.com/mjudeikis/ocp-app-agent-example

    Perhaps something similar is possible for the AppMon Agent?