Skip to content

Commit

Permalink
Added support for running multiple kresd instances
Browse files Browse the repository at this point in the history
  • Loading branch information
hectorm committed Mar 10, 2022
1 parent 80e87a1 commit 032f12d
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 37 deletions.
7 changes: 5 additions & 2 deletions Dockerfile.m4
Original file line number Diff line number Diff line change
Expand Up @@ -232,11 +232,12 @@ ENV KRESD_DNS1_IP=1.1.1.1@853
ENV KRESD_DNS1_HOSTNAME=cloudflare-dns.com
ENV KRESD_DNS2_IP=1.0.0.1@853
ENV KRESD_DNS2_HOSTNAME=cloudflare-dns.com
ENV KRESD_INSTANCE_NUMBER=1
ENV KRESD_RECENTLY_BLOCKED_NUMBER=100
ENV KRESD_CERT_MANAGED=true
ENV KRESD_WATCHDOG_QNAME=cloudflare.com.
ENV KRESD_WATCHDOG_QTYPE=A
ENV KRESD_WATCHDOG_INTERVAL=10
ENV KRESD_STATS_BLOCKED_COUNT=100
ENV KRESD_CERT_MANAGED=true
ENV KRESD_NIC=
ENV KRESD_LOG_LEVEL=notice

Expand Down Expand Up @@ -319,6 +320,8 @@ FROM base AS test

# Perform a test run
RUN printf '%s\n' 'Starting services...' \
&& export TINI_SUBREAPER=1 \
&& export KRESD_INSTANCE_NUMBER=2 \
&& (nohup container-init &) \
&& TIMEOUT_DURATION=240s \
&& TIMEOUT_COMMAND='until container-healthcheck; do sleep 1; done' \
Expand Down
24 changes: 14 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,12 @@ Hostname of the DNS-over-TLS server to which the queries will be forwarded
Certificate hash of the DNS-over-TLS server to which the queries will be forwarded
([key-pinned authentication docs](https://knot-resolver.readthedocs.io/en/stable/modules-policy.html#key-pinned-authentication)).

#### `KRESD_WATCHDOG_QNAME` (default: `cloudflare.com.`)
Query name to check the health status of kresd.
#### `KRESD_INSTANCE_NUMBER` (default: `1`)
Number of instances to launch.

#### `KRESD_WATCHDOG_QTYPE` (default: `A`)
Query type to check the health status of kresd.

#### `KRESD_WATCHDOG_INTERVAL` (default: `10`)
Interval in seconds to check the health status of kresd.

#### `KRESD_STATS_BLOCKED_COUNT` (default: `100`)
Number of recently blocked domains to expose in stats.
#### `KRESD_RECENTLY_BLOCKED_NUMBER` (default: `100`)
Number of recently blocked domains to store in memory for each instance.
The `/recently_blocked` endpoint returns an aggregated list of all instances.

#### `KRESD_CERT_MANAGED` (default: `true`)
If equals `true`, a self-signed certificate will be generated. You can provide your own certificate with these options:
Expand All @@ -66,6 +61,15 @@ If equals `true`, a self-signed certificate will be generated. You can provide y
> **Note:** for a more advanced setup, look at the [following example](examples/caddy) with [Let's Encrypt](https://letsencrypt.org) and
[Caddy](https://caddyserver.com/).

#### `KRESD_WATCHDOG_QNAME` (default: `cloudflare.com.`)
Query name to check the health status of kresd.

#### `KRESD_WATCHDOG_QTYPE` (default: `A`)
Query type to check the health status of kresd.

#### `KRESD_WATCHDOG_INTERVAL` (default: `10`)
Interval in seconds to check the health status of kresd.

#### `KRESD_NIC` (default: empty)
If defined, kresd will only listen on the specified interface. Some users observed a considerable, close to 100%, performance gain in Docker
containers when they bound the daemon to a single interface:ip address pair
Expand Down
31 changes: 19 additions & 12 deletions config/knot-resolver/kresd.conf.d/080-policy-blocklist.conf
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ if not stats then modules.load('stats') end
if not http then modules.load('http') end

local lru = require('lru')
local recently_blocked = lru.new(tonumber(env.KRESD_STATS_BLOCKED_COUNT))
local recently_blocked = lru.new(tonumber(env.KRESD_RECENTLY_BLOCKED_NUMBER))

local blocked_metric = 'answer.blocked'
stats[blocked_metric] = 0
Expand All @@ -26,24 +26,31 @@ local function deny_and_count(msg)
end
end

local function get_recently_blocked()
local out = {}
for qname, count in recently_blocked:pairs() do
table.insert(out, { qname = qname, count = count })
end
if out[1] == nil then return '[]'
else return tojson(out) end
end

policy.add(policy.rpz(
deny_and_count('Blocked domain'),
env.KRESD_DATA_DIR .. '/hblock/blocklist.rpz',
true
))

http.configs._builtin.webmgmt.endpoints['/blocked'] = {
function get_recently_blocked()
local rb = {}
for qname, count in recently_blocked:pairs() do
rb[qname] = count
end
return rb
end

http.configs._builtin.webmgmt.endpoints['/recently_blocked'] = {
'application/json',
function ()
return get_recently_blocked()
local out = {}
for _, result in pairs(map('get_recently_blocked()')) do
if type(result) == 'table' then
for qname, count in pairs(result) do
out[qname] = (out[qname] or 0) + count
end
end
end
return tojson(out)
end
}
1 change: 1 addition & 0 deletions run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ printf '%s\n' "Creating \"${CONTAINER_NAME:?}\" container..."
--publish '127.0.0.153:8453:8453/tcp' \
--mount type=volume,src="${CONTAINER_NAME:?}-data",dst='/var/lib/knot-resolver/' \
--mount type=volume,src="${CONTAINER_NAME:?}-cache",dst='/var/cache/knot-resolver/' \
--env KRESD_INSTANCE_NUMBER=4 \
"${IMAGE_NAME:?}" "$@" >/dev/null

printf '%s\n\n' 'Done!'
Expand Down
13 changes: 8 additions & 5 deletions scripts/bin/container-healthcheck
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
set -eu
umask 0002

# kresd service must be running
if ! is-sv-status kresd run; then
>&2 printf '%s\n' 'kresd service is not running'
exit 1
fi
# kresd services must be running
id=0; while [ "${id:?}" -lt "${KRESD_INSTANCE_NUMBER:?}" ]; do
if ! is-sv-status "kresd${id:?}" run; then
>&2 printf '%s\n' "kresd${id:?} service is not running"
exit 1
fi
id=$((id + 1))
done

# kres-cache-gc service must be running
if ! is-sv-status kres-cache-gc run; then
Expand Down
10 changes: 10 additions & 0 deletions scripts/bin/container-init
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,15 @@ if [ ! -e "${KRESD_DATA_DIR:?}"/hblock/blocklist.rpz ]; then
hblock
fi

# Create a service for each kresd instance
if [ "${KRESD_INSTANCE_NUMBER:?}" -gt 1 ]; then
id=1; while [ "${id:?}" -lt "${KRESD_INSTANCE_NUMBER:?}" ]; do
if [ ! -d "${SVDIR:?}"/kresd"${id:?}"/ ]; then
cp -a "${SVDIR:?}"/kresd0/ "${SVDIR:?}"/kresd"${id:?}"/
fi
id=$((id + 1))
done
fi

# Start all services
exec tini -- runsvdir -P "${SVDIR:?}"
19 changes: 11 additions & 8 deletions scripts/bin/kres-console
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
set -eu
umask 0002

if is-sv-status kresd run; then
KRESD_PID=$(cat "${SVDIR:?}"/kresd/supervise/pid)
KRESD_SOCKET=${KRESD_CACHE_DIR:?}/control/${KRESD_PID:?}
kresc "${KRESD_SOCKET:?}"
else
>&2 printf '%s\n' 'kresd is not running'
exit 1
fi
id=0; while [ "${id:?}" -lt "${KRESD_INSTANCE_NUMBER:?}" ]; do
if is-sv-status "kresd${id:?}" run; then
KRESD_PID=$(cat "${SVDIR:?}"/"kresd${id:?}"/supervise/pid)
KRESD_SOCKET=${KRESD_CACHE_DIR:?}/control/${KRESD_PID:?}
exec kresc "${KRESD_SOCKET:?}"
fi
id=$((id + 1))
done

>&2 printf '%s\n' 'kresd is not running'
exit 1
File renamed without changes.

0 comments on commit 032f12d

Please sign in to comment.