.. SPDX-License-Identifier: GPL-3.0-or-later

.. _systemd-multiple-instances:

Multiple instances
==================

.. note:: This section describes the usage of kresd when running under systemd
   without Manager.

Knot Resolver can utilize multiple CPUs running in multiple independent instances (processes), where each process utilizes at most single CPU core on your machine. If your machine handles a lot of DNS traffic run multiple instances.

All instances typically share the same configuration and cache, and incoming queries are automatically distributed by operating system among all instances.

Advantage of using multiple instances is that a problem in a single instance will not affect others, so a single instance crash will not bring whole DNS resolver service down.

.. tip:: For maximum performance, there should be as many kresd processes as
   there are available CPU threads.

To run multiple instances, use a different identifier after `@` sign for each instance, for
example:

.. code-block:: bash

   $ systemctl start kresd@1.service
   $ systemctl start kresd@2.service
   $ systemctl start kresd@3.service
   $ systemctl start kresd@4.service

With the use of brace expansion in BASH the equivalent command looks like this:

.. code-block:: bash

   $ systemctl start kresd@{1..4}.service

For more details see ``kresd.systemd(7)``.


.. _systemd-zero-downtime-restarts:

Zero-downtime restarts
----------------------
Resolver restart normally takes just milliseconds and cache content is persistent to avoid performance drop
after restart. If you want real zero-downtime restarts use `multiple instances`_ and do rolling
restart, i.e. restart only one resolver process at a time.

On a system with 4 instances run these commands sequentially:

.. code-block:: bash

   $ systemctl restart kresd@1.service
   $ systemctl restart kresd@2.service
   $ systemctl restart kresd@3.service
   $ systemctl restart kresd@4.service

At any given time only a single instance is stopped and restarted so remaining three instances continue to service clients.


.. _instance-specific-configuration:

Instance-specific configuration
-------------------------------

Instances can use arbitrary identifiers for the instances, for example we can name instances like `dns1`, `tls` and so on.

.. code-block:: bash

   $ systemctl start kresd@dns1
   $ systemctl start kresd@dns2
   $ systemctl start kresd@tls
   $ systemctl start kresd@doh

The instance name is subsequently exposed to kresd via the environment variable
``SYSTEMD_INSTANCE``. This can be used to tell the instances apart, e.g. when
using the :ref:`mod-nsid` module with per-instance configuration:

.. code-block:: lua

   local systemd_instance = os.getenv("SYSTEMD_INSTANCE")

   modules.load('nsid')
   nsid.name(systemd_instance)

More arcane set-ups are also possible. The following example isolates the
individual services for classic DNS, DoT and DoH from each other.

.. code-block:: lua

   local systemd_instance = os.getenv("SYSTEMD_INSTANCE")

   if string.match(systemd_instance, '^dns') then
   	net.listen('127.0.0.1', 53, { kind = 'dns' })
   elseif string.match(systemd_instance, '^tls') then
   	net.listen('127.0.0.1', 853, { kind = 'tls' })
   elseif string.match(systemd_instance, '^doh') then
   	net.listen('127.0.0.1', 443, { kind = 'doh2' })
   else
   	panic("Use kresd@dns*, kresd@tls* or kresd@doh* instance names")
   end
