Add Plugins to the Telegraf Docker Container and keep the Container Size small
How to add external plugins to the Telegraf docker container while keeping container size as small as possible.
At gridscale, we currently use InfluxDB for some things. That means we collect our metrics with Telegraf. Telegraf does collect a lot of metrics already by default. But sometimes you just need more.
It does not make sense for the Telegraf team to put everything into the Telegraf core. This would blow up the project and most people would only use a small percentage of those metrics.
On the other side, this means some more work for you. Yes, you the dev, ops, DevOps whatever guy! So here is a quick example how I have manged this.
Keep the Telegraf Docker image small while adding functionality
With a multi-staged docker build you can add more plugins while keeping the container size small and the Dockerfile readable. The docker container will only increase by the size of the artifact you are adding with the
COPY directive. The downloaded git repo, possible build artifact, etc. will be discarded.
I highly advise naming your build stages for readability. Here an example of using one stage:
# Get repo for psi plugin FROM bitnami/git AS git-psi WORKDIR /app RUN git clone --depth 1 --branch v0.1.0 https://github.com/gridscale/linux-psi-telegraf-plugin.git linux-psi-telegraf-plugin # Build psi binary FROM golang:1.16-alpine AS binary-psi WORKDIR /go/src/app/ COPY --from=git-psi /app/ ./ WORKDIR /go/src/app/linux-psi-telegraf-plugin RUN go build -o psi cmd/main.go # Build the telegraf container with your plugins FROM telegraf:alpine COPY --from=binary-psi /go/src/app/linux-psi-telegraf-plugin/psi /usr/local/bin/psi
Now you just have to add some config for your new plugin. That of course depends on the plugin you want to add.
[...] [[inputs.execd]] command = ["/usr/local/bin/psi"] signal = "none"
So you did find another plugin from this list? Or you found something useful on GitHub like this plugin to get btrfs file system metrics:
Just add another block to get the code, build the binary and copy the artifact:
# Get repo for psi plugin FROM bitnami/git AS git-psi WORKDIR /app RUN git clone --depth 1 --branch v0.1.0 https://github.com/gridscale/linux-psi-telegraf-plugin.git linux-psi-telegraf-plugin # Build psi binary FROM golang:1.16-alpine AS binary-psi WORKDIR /go/src/app/ COPY --from=git-psi /app/ ./ WORKDIR /go/src/app/linux-psi-telegraf-plugin RUN go build -o psi cmd/main.go # Get repo for telegraf-exec-btrfs-status FROM bitnami/git AS git-btrfs-stats WORKDIR /app RUN git clone --single-branch --depth 1 https://github.com/iwvelando/telegraf-exec-btrfs-status.git telegraf-exec-btrfs-status # Build telegraf-exec-btrfs-status binary FROM golang:1.16-alpine AS binary-btrfs-stats WORKDIR /go/src/app/ COPY --from=git-btrfs-stats /app/ ./ WORKDIR /go/src/app/telegraf-exec-btrfs-status RUN go build -o telegraf-exec-btrfs-status . # Build the telegraf container with your plugins FROM telegraf:alpine COPY --from=binary-psi /go/src/app/linux-psi-telegraf-plugin/psi /usr/local/bin/psi # Copy binary for btrfs-stats COPY --from=binary-btrfs-stats /go/src/app/telegraf-exec-btrfs-status/telegraf-exec-btrfs-status /usr/local/bin/telegraf-exec-btrfs-status # Copy config for btrfs-stats COPY --from=git-btrfs-stats /app/telegraf-exec-btrfs-status/btrfs_device_stats_template.txt /etc/telegraf/ COPY --from=git-btrfs-stats /app/telegraf-exec-btrfs-status/btrfs_filesystem_usage_template.txt /etc/telegraf/ COPY --from=git-btrfs-stats /app/telegraf-exec-btrfs-status/btrfs_scrub_status_template.txt /etc/telegraf/
It still is relatively easy to understand what is going on.
You could put the
git pull for both repositories in one stage. You would have to switch paths or working directories. This makes the code more complex and less obvious in my opinion. Imagine you just want to delete 1 plugin later on. You need more brainpower to distinguish what is where and what.
Also, you could get some trouble starting a binary that was built on Ubuntu and using it on the alpine-based container. I had some problems with that and was forced to build the binary on alpine in order to get it working on alpine as well.
Anyway, I hope this helps some fellow out there and if so let me know down in the comment section ?
Have a great day!