Running Metricbeat on Dockeredit

Docker images for Metricbeat are available from the Elastic Docker registry. You can retrieve an image with a docker pull command.

docker pull docker.elastic.co/beats/metricbeat:6.0.1

The base image is centos:7 and the source code can be found on GitHub.

Configure Metricbeat on Dockeredit

The Docker image provides several methods for configuring Metricbeat. The conventional approach is to provide a configuration file via a bind-mounted volume, but it’s also possible to create a custom image with your configuration included.

Bind-mounted configurationedit

One way to configure Metricbeat on Docker is to provide metricbeat.yml via bind-mounting. With docker run, the bind-mount can be specified like this:

docker run \
  -v ~/metricbeat.yml:/usr/share/metricbeat/metricbeat.yml \
  docker.elastic.co/beats/metricbeat:6.0.1
Custom image configurationedit

It’s possible to embed your Metricbeat configuration in a custom image. Here is an example Dockerfile to achieve this:

FROM docker.elastic.co/beats/metricbeat:6.0.1
COPY metricbeat.yml /usr/share/metricbeat/metricbeat.yml
USER root
RUN chown metricbeat /usr/share/metricbeat/metricbeat.yml
USER metricbeat

Monitor the host machineedit

When executing Metricbeat in a container, there are some important things to be aware of if you want to monitor the host machine or other containers. Let’s walk-through some examples using Docker as our container orchestration tool.

This example highlights the changes required to make the system module work properly inside of a container. This enables Metricbeat to monitor the host machine from within the container.

docker run \
  --volume=/proc:/hostfs/proc:ro \ 
  --volume=/sys/fs/cgroup:/hostfs/sys/fs/cgroup:ro \ 
  --volume=/:/hostfs:ro \ 
  --net=host 
  docker.elastic.co/beats/metricbeat:6.0.1 -system.hostfs=/hostfs

Metricbeat’s system module collects much of its data through the Linux proc filesystem, which is normally located at /proc. Because containers are isolated as much as possible from the host, the data inside of the container’s /proc is different than the host’s /proc. To account for this, you can mount the host’s /proc filesystem inside of the container and tell Metricbeat to look inside the /hostfs directory when looking for /proc by using the -system.hostfs=/hostfs CLI flag.

By default, cgroup reporting is enabled for the system process metricset, so you need to mount the host’s cgroup mountpoints within the container. They need to be mounted inside the directory specified by the -system.hostfs CLI flag.

If you want to be able to monitor filesystems from the host by using the system filesystem metricset, then those filesystems need to be mounted inside of the container. They can be mounted at any location.

The system network metricset uses data from /proc/net/dev, or /hostfs/proc/net/dev when using -system.hostfs=/hostfs. The only way to make this file contain the host’s network devices is to use the --net=host flag. This is due to Linux namespacing; simply bind mounting the host’s /proc to /hostfs/proc is not sufficient.

The special filesystems /proc and /sys are only available if the host system is running Linux. Attempts to bind-mount these filesystems will fail on Windows and MacOS.

Monitor a service in another containeredit

Next, let’s look at an example of monitoring a containerized service from a Metricbeat container.

docker run \
  --network=mysqlnet \ 
  -e MYSQL_PASSWORD=secret \ 
  docker.elastic.co/beats/metricbeat:6.0.1

Placing the Metricbeat and MySQL containers on the same Docker network allows Metricbeat access to the exposed ports of the MySQL container, and makes the hostname mysql resolvable to Metricbeat.

If you do not want to hardcode certain values into your Metricbeat configuration, then you can pass them into the container either as environment variables or as command line flags to Metricbeat (see the -E CLI flag in Metricbeat commands).

The mysql module configuration would look like this:

metricbeat.modules:
- module: mysql
  metricsets: ["status"]
  hosts: ["mysql:3306"] 
  username: root
  password: ${MYSQL_PASSWORD} 

The mysql hostname will resolve to the address of a container named mysql on the mysqlnet Docker network.

The MYSQL_PASSWORD variable will be evaluated at startup. If the variable is not set, this will lead to an error at startup.