Add Dockerfile, compose.yaml, and an unbound example config (#66)
This adds a Dockerfile for unbound exporter, which we can publish in the future. An example docker compose.yml is included to demonstrate and test using it with unbound, along with a sample configuration file for unbound showing how to set up the remote-control. The unbound example config file is based on the one inside the mvance/docker image that's used here. A small integration test runs against the docker-compose setup to smoke-test unbound_exporter.
This commit is contained in:
parent
cbed00787a
commit
e54ee016b6
|
@ -0,0 +1,27 @@
|
|||
---
|
||||
name: integration
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
integration:
|
||||
runs-on: [ubuntu-latest]
|
||||
steps:
|
||||
- name: Install Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: "1.21.x"
|
||||
- name: checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Start containers
|
||||
run: docker compose up --build --detach
|
||||
- name: run integration test
|
||||
run: go test -v --tags=integration
|
||||
- name: Stop containers
|
||||
if: always()
|
||||
run: docker compose down
|
|
@ -0,0 +1,20 @@
|
|||
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.21.4-bookworm AS build
|
||||
|
||||
WORKDIR /go/src/app
|
||||
|
||||
COPY go.mod .
|
||||
COPY go.sum .
|
||||
|
||||
RUN go mod download
|
||||
|
||||
COPY *.go .
|
||||
|
||||
ENV CGO_ENABLED=0
|
||||
|
||||
RUN GOOS=$TARGETOS GOARCH=$TARGETPLATFORM go build -v -o /go/bin/unbound_exporter ./...
|
||||
|
||||
FROM gcr.io/distroless/static-debian12
|
||||
|
||||
COPY --from=build /go/bin/unbound_exporter /
|
||||
|
||||
ENTRYPOINT ["/unbound_exporter"]
|
|
@ -0,0 +1,21 @@
|
|||
services:
|
||||
unbound_exporter:
|
||||
build: .
|
||||
command: [ "-unbound.host=unix:///var/run/socket/unbound.ctl" ]
|
||||
volumes:
|
||||
- socket:/var/run/socket:ro
|
||||
ports:
|
||||
- "9167:9167"
|
||||
depends_on:
|
||||
unbound:
|
||||
condition: service_started
|
||||
unbound:
|
||||
image: "mvance/unbound:1.18.0"
|
||||
volumes:
|
||||
- socket:/var/run/socket:rw
|
||||
- ./unbound-example.conf:/opt/unbound/etc/unbound/unbound.conf
|
||||
ports:
|
||||
- "1053:1053/udp"
|
||||
- "1053:1053/tcp"
|
||||
volumes:
|
||||
socket:
|
|
@ -0,0 +1,52 @@
|
|||
//go:build integration
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/prometheus/common/expfmt"
|
||||
)
|
||||
|
||||
// TestIntegration checks that unbound_exporter is running, successfully
|
||||
// scraping and exporting metrics.
|
||||
//
|
||||
// It assumes unbound_exporter is available on localhost:9167, and Unbound on
|
||||
// localhost:1053, as is set up in the docker-compose.yml file.
|
||||
//
|
||||
// A typical invocation of this test would look like
|
||||
//
|
||||
// docker compose up --build -d
|
||||
// go test --tags=integration
|
||||
// docker compose down
|
||||
func TestIntegration(t *testing.T) {
|
||||
resp, err := http.Get("http://localhost:9167/metrics")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to fetch metrics from unbound_exporter: %v", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Fatalf("Expected a 200 OK from unbound_exporter, got: %v", resp.StatusCode)
|
||||
}
|
||||
|
||||
parser := expfmt.TextParser{}
|
||||
metrics, err := parser.TextToMetricFamilies(resp.Body)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to parse metrics from unbound_exporter: %v", err)
|
||||
}
|
||||
|
||||
// unbound_up is 1 if we've successfully scraped metrics from it
|
||||
unbound_up := metrics["unbound_up"].Metric[0].Gauge.GetValue()
|
||||
if unbound_up != 1 {
|
||||
t.Errorf("Expected unbound_up to be 1, not: %v", unbound_up)
|
||||
}
|
||||
|
||||
// Check some expected metrics are present
|
||||
for _, metric := range []string{"go_info", "unbound_queries_total", "unbound_response_time_seconds", "unbound_cache_hits_total"} {
|
||||
if _, ok := metrics[metric]; !ok {
|
||||
t.Errorf("Expected metric is missing: %s", metric)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
## This is an example Unbound configuration file
|
||||
## This is needed to use unbound_exporter
|
||||
remote-control:
|
||||
control-enable: yes
|
||||
control-interface: /var/run/socket/unbound.ctl
|
||||
|
||||
# The rest of this file is standard Unbound configuration
|
||||
# There's nothing special here.
|
||||
server:
|
||||
cache-max-ttl: 86400
|
||||
cache-min-ttl: 300
|
||||
directory: "/opt/unbound/etc/unbound"
|
||||
do-ip4: yes
|
||||
do-ip6: no
|
||||
do-tcp: yes
|
||||
do-udp: yes
|
||||
edns-buffer-size: 1232
|
||||
interface: 0.0.0.0
|
||||
port: 1053
|
||||
prefer-ip6: no
|
||||
rrset-roundrobin: yes
|
||||
username: "_unbound"
|
||||
log-local-actions: no
|
||||
log-queries: no
|
||||
log-replies: no
|
||||
log-servfail: yes
|
||||
logfile: /opt/unbound/etc/unbound/unbound.log
|
||||
verbosity: 2
|
||||
infra-cache-slabs: 4
|
||||
incoming-num-tcp: 10
|
||||
key-cache-slabs: 4
|
||||
msg-cache-size: 142768128
|
||||
msg-cache-slabs: 4
|
||||
num-queries-per-thread: 4096
|
||||
num-threads: 3
|
||||
outgoing-range: 8192
|
||||
rrset-cache-size: 285536256
|
||||
rrset-cache-slabs: 4
|
||||
minimal-responses: yes
|
||||
prefetch: yes
|
||||
prefetch-key: yes
|
||||
serve-expired: yes
|
||||
so-reuseport: yes
|
||||
aggressive-nsec: yes
|
||||
delay-close: 10000
|
||||
do-daemonize: no
|
||||
do-not-query-localhost: no
|
||||
neg-cache-size: 4M
|
||||
qname-minimisation: yes
|
||||
access-control: 127.0.0.1/32 allow
|
||||
access-control: 192.168.0.0/16 allow
|
||||
access-control: 172.16.0.0/12 allow
|
||||
access-control: 10.0.0.0/8 allow
|
||||
access-control: fc00::/7 allow
|
||||
access-control: ::1/128 allow
|
||||
auto-trust-anchor-file: "var/root.key"
|
||||
chroot: ""
|
||||
deny-any: yes
|
||||
harden-algo-downgrade: yes
|
||||
harden-below-nxdomain: yes
|
||||
harden-dnssec-stripped: yes
|
||||
harden-glue: yes
|
||||
harden-large-queries: yes
|
||||
harden-referral-path: no
|
||||
harden-short-bufsize: yes
|
||||
hide-http-user-agent: no
|
||||
hide-identity: yes
|
||||
hide-version: yes
|
||||
http-user-agent: "DNS"
|
||||
identity: "DNS"
|
||||
private-address: 10.0.0.0/8
|
||||
private-address: 172.16.0.0/12
|
||||
private-address: 192.168.0.0/16
|
||||
private-address: 169.254.0.0/16
|
||||
private-address: fd00::/8
|
||||
private-address: fe80::/10
|
||||
private-address: ::ffff:0:0/96
|
||||
ratelimit: 1000
|
||||
tls-cert-bundle: /etc/ssl/certs/ca-certificates.crt
|
||||
unwanted-reply-threshold: 10000
|
||||
use-caps-for-id: yes
|
||||
val-clean-additional: yes
|
||||
include: /opt/unbound/etc/unbound/a-records.conf
|
||||
include: /opt/unbound/etc/unbound/srv-records.conf
|
Loading…
Reference in New Issue