5. Kea Configuration¶
Kea uses JSON structures to represent server configurations. The following sections describe how the configuration structures are organized.
5.1. JSON Configuration¶
JSON is the notation used throughout the Kea project. The most obvious usage is for the configuration file, but JSON is also used for sending commands over the Management API (see Management API) and for communicating between DHCP servers and the DDNS update daemon.
Typical usage assumes that the servers are started from the command
line, either directly or using a script, e.g. keactrl
. The
configuration file is specified upon startup using the -c
parameter.
5.1.1. JSON Syntax¶
Configuration files for the DHCPv4, DHCPv6, DDNS, Control Agent, and NETCONF modules are defined in an extended JSON format. Basic JSON is defined in RFC 7159 and ECMA 404. In particular, the only boolean values allowed are true or false (all lowercase). The capitalized versions (True or False) are not accepted.
Even though the JSON standard (ECMA 404) does not require JSON objects (i.e. name/value maps) to have unique entries, Kea implements them using a C++ STL map with unique entries. Therefore, if there are multiple values for the same name in an object/map, the last value overwrites previous values. Since Kea 1.9.0, configuration file parsers raise a syntax error in such cases.
Kea components use extended JSON with additional features allowed:
- Shell comments: any text after the hash (#) character is ignored.
- C comments: any text after the double slashes (//) character is ignored.
- Multiline comments: any text between /* and */ is ignored. This comment can span multiple lines.
- File inclusion: JSON files can include other JSON files by using a statement of the form <?include “file.json”?>.
The configuration file consists of a single object (often colloquially called a map) started with a curly bracket. It comprises only one of the “Dhcp4”, “Dhcp6”, “DhcpDdns”, “Control-agent”, or “Netconf” objects. It is possible to define additional elements but they will be ignored.
A very simple configuration for DHCPv4 could look like this:
# The whole configuration starts here.
{
# DHCPv4 specific configuration starts here.
"Dhcp4": {
"interfaces-config": {
"interfaces": [ "eth0" ],
"dhcp-socket-type": "raw"
},
"valid-lifetime": 4000,
"renew-timer": 1000,
"rebind-timer": 2000,
"subnet4": [{
"pools": [ { "pool": "192.0.2.1-192.0.2.200" } ],
"subnet": "192.0.2.0/24"
}],
# Now loggers are inside the DHCPv4 object.
"loggers": [{
"name": "*",
"severity": "DEBUG"
}]
}
# The whole configuration structure ends here.
}
More examples are available in the installed share/doc/kea/examples
directory.
Note
As of Kea 1.6.0, the “Logging” element was removed and its contents (the “loggers” object) moved inside the configuration objects (maps) for the respective Kea modules. For example, the “Dhcp4” map contains the “loggers” object, specifying logging configuration for the DHCPv4 server. Support for the top-level “Logging” object was removed in Kea 1.7.10.
The specification for supporting several elements (e.g. “Dhcp4”, “Dhcp6”) in one file was removed in Kea 1.7.10, so each component now requires a separate configuration file.
To avoid repetition of mostly similar structures, examples in the rest of this guide will showcase only the subset of parameters appropriate for a given context. For example, when discussing the IPv6 subnets configuration in DHCPv6, only subnet6 parameters will be mentioned. It is implied that the remaining elements (the global map that holds Dhcp6) are present, but they are omitted for clarity. Usually, locations where extra parameters may appear are denoted by an ellipsis (…).
5.1.2. Comments and User Context¶
Shell, C, or C++ style comments are all permitted in the JSON configuration file if
the file is used locally. This is convenient and works in simple cases where
the configuration is kept statically using a local file. However, since comments
are not part of JSON syntax, most JSON tools detect them as
errors. Another problem with them is that once Kea loads its configuration, the
shell, C, and C++ style comments are ignored. If commands such as
config-get
or config-write
are used, those comments are lost. An example of such
comments was presented in the previous section.
Historically, to address the problem, Kea code allowed the use of comment strings
as valid JSON entities. This had the benefit of being retained through various
operations (such as config-get
), or allowing processing by JSON tools. An
example JSON comment looks like this:
"Dhcp4": {
"subnet4": [{
"subnet": "192.0.2.0/24",
"pools": [{ "pool": "192.0.2.10 - 192.0.2.20" }],
"comment": "second floor"
}]
}
However, the facts that the comment could only be a single line, and that it was not possible to add any other information in a more structured form, were frustrating. One specific example was a request to add floor levels and building numbers to subnets. This was one of the reasons why the concept of user context was introduced. It allows adding an arbitrary JSON structure to most Kea configuration structures.
This has a number of benefits compared to earlier approaches. First, it is fully compatible with JSON tools and Kea commands. Second, it allows storing simple comment strings, but it can also store much more complex data, such as multiple lines (as a string array), extra typed data (such as floor numbers being actual numbers), and more. Third, the data is exposed to hooks, so it is possible to develop third-party hooks that take advantage of that extra information. An example user context looks like this:
"Dhcp4": {
"subnet4": [{
"subnet": "192.0.2.0/24",
"pools": [{ "pool": "192.0.2.10 - 192.0.2.20" }],
"user-context": {
"comment": "second floor",
"floor": 2
}
}]
}
User contexts can store an arbitrary data file as long as it has valid JSON syntax and its top-level element is a map (i.e. the data must be enclosed in curly brackets). However, some hook libraries may expect specific formatting; please consult the specific hook library documentation for details.
In a sense the user-context mechanism has superseded the JSON comment capabilities; ISC encourages administrators to use user-context instead of the older mechanisms. To promote this way of storing comments, Kea compared converts JSON comments to user-context on the fly.
However, if the configuration uses the old JSON
comment, the config-get
command returns a slightly modified
configuration. It is not uncommon for a call for config-set
followed by a
config-get
to receive a slightly different structure.
The best way to avoid this problem is simply to abandon JSON comments and
use user-context.
For a discussion about user-context used in hooks, see User Contexts in Hooks.
5.1.3. Simplified Notation¶
It is sometimes convenient to refer to a specific element in the configuration hierarchy. Each hierarchy level is separated by a slash. If there is an array, a specific instance within that array is referenced by a number in square brackets (with numbering starting at zero). For example, in the above configuration the valid-lifetime in the Dhcp4 component can be referred to as Dhcp4/valid-lifetime, and the pool in the first subnet defined in the DHCPv4 configuration as Dhcp4/subnet4[0]/pool.
5.2. Kea Configuration Backend¶
5.2.1. Applicability¶
Kea Configuration Backend (CB or config backend) is a feature, first
introduced in Kea 1.6.0, that gives Kea servers the ability
to manage and fetch their configuration from one or more databases. In
this documentation, the term “Configuration Backend” may also refer to
the particular Kea module providing support to manage and fetch the
configuration information from the particular database type. For
example, MySQL Configuration Backend is the logic implemented within the
mysql_cb
hook library, which provides a complete set of functions to
manage and fetch the configuration information from the MySQL database.
In small deployments, e.g. those comprising a single DHCP server instance with limited and infrequently changing number of subnets, it may be impractical to use the CB as a configuration repository because it requires additional third-party software to be installed and configured - in particular the MySQL server and MySQL client. Once the number of DHCP servers and/or the number of managed subnets in the network grows, the usefulness of the CB becomes obvious.
One use case for the CB is a pair of Kea DHCP servers that are configured
to support High Availability as described in
ha: High Availability. The configurations of both servers
(including the value of the server-tag
parameter)
are almost exactly the same: they may differ by the server identifier
and designation of the server as a primary or standby (or secondary), and/or
by their interfaces’ configuration. Typically, the
subnets, shared networks, option definitions, and global parameters are the
same for both servers and can be sourced from a single database instance
to both Kea servers.
Using the database as a single source of configuration for subnets and/or other configuration information supported by the CB has the advantage that any modifications to the configuration in the database are automatically applied to both servers.
Another case when the centralized configuration repository is useful is in deployments including a large number of DHCP servers, possibly using a common lease database to provide redundancy. New servers can be added to the pool frequently to fulfill growing scalability requirements. Adding a new server does not require replicating the entire configuration to the new server when a common database is used.
Using the database as a configuration repository for Kea servers also brings other benefits, such as:
- the ability to use database specific tools to access the configuration information;
- the ability to create customized statistics based on the information stored in the database; and
- the ability to backup the configuration information using the database’s built-in replication mechanisms.
5.2.2. CB Capabilities and Limitations¶
Currently, the Kea CB has the following limitations:
- It is only supported for the MySQL database.
- It is only supported for the DHCPv4 and DHCPv6 daemons; the Control Agent, D2 daemon, and the NETCONF daemon cannot be configured from the database,
- Only certain DHCP configuration parameters can be set in the database: global parameters, option definitions, global options, client classes, shared networks, and subnets. Other configuration parameters must be sourced from a JSON configuration file.
Kea CB stores data in a MySQL schema that is public. It is possible to
insert configuration data into the MySQL tables manually or automatically
using SQL scripts, but this requires SQL and schema knowledge.
The supported method for managing the data is through the cb-cmds
hook library,
which provides management commands for config backends. It simplifies many
typical operations, such as listing, adding, retrieving, and deleting global
parameters, shared networks, subnets, pools, options, option definitions, and
client classes. In addition, it provides essential business logic that ensures
the logical integrity of the data. See commands starting with remote-
in
Appendix A of this manual for a complete list.
Note
The cb_cmds
hook library is available only to ISC support subscribers.
For more information on subscription options, please complete the form
at https://www.isc.org/contact.
The schema creation script can be found at dhcpdb_create.mysql; other related design documents are stored in our GitLab: CB Design and Client Classes in CB Design.
We strongly recommend against duplication of configuration information in both the file and the database. For example, when specifying subnets for the DHCP server, please store them in either the configuration backend or in the configuration file, not both. Storing some subnets in the database and others in the file may put users at risk of potential configuration conflicts. Note that the configuration instructions from the database take precedence over instructions from the file, so parts of the configuration specified in the file may be overridden if contradicted by information in the database.
Although it is not recommended, it is possible to specify certain parameter types both in a configuration file and the database. For example, a subnet can be specified in the configuration file and another subnet in the database; in this case, the server will use both subnets. DHCP client classes, however, must not be specified in both the configuration file and the database, even if they do not overlap. If any client classes are specified in the database for a particular DHCP server, this server will use these classes and ignore all classes present in its configuration file. This behavior was introduced to ensure that the server receives a consistent set of client classes specified in an expected order with all inter-class dependencies fulfilled. It is impossible to guarantee consistency when client classes are specified in two independent configuration sources.
Note
It is recommended that the subnet_cmds
hook library not be used to
manage subnets when the configuration backend is used as a source
of information about the subnets. The subnet_cmds
hook library
modifies the local subnets configuration in the server’s memory,
not in the database. Use the cb_cmds
hook library to manage the
subnets information in the database instead.
Note
Using custom option formats requires creating definitions for these options. Suppose a user wishes to set option data in the configuration backend. In that case, we recommend specifying the definition for that option in the configuration backend as well. It is essential when multiple servers are managed via the configuration backend, and may differ in their configurations. The option data parser can search for an option definition appropriate for the server for which the option data is specified.
In a single-server deployment, or when all servers share the same configuration file information, it is possible to specify option definitions in the configuration files and option data in the configuration backend. The server receiving a command to set option data must have a valid definition in its configuration file, even when it sets option data for another server.
It is not supported to specify option definitions in the configuration backend and the corresponding option data in the server configuration files.
5.2.3. CB Components¶
Kea 1.6.0 version or later is required to use the configuration backend.
The mysql_cb
open source hook library implementing the configuration
backend for MySQL must be compiled and loaded by the DHCP servers. This
hook library is compiled when the --with-mysql
configuration switch
is used during the Kea build. The MySQL C client libraries must be
installed, as explained in DHCP Database Installation and Configuration.
Note
Any existing MySQL schema must be upgraded to the latest schema
required by the particular Kea version using the kea-admin
tool,
as described in The kea-admin Tool.
The cb_cmds
premium hook library, which is available to ISC’s paid support
customers, provides a complete set of commands to manage the
servers’ configuration information within the database. This library can
be attached to both DHCPv4 and DHCPv6 server instances. It is
possible to manage the configuration information without the cb_cmds
hook library with commonly available tools, such as MySQL Workbench or
the command-line MySQL client, by directly working with the database.
Refer to cb_cmds: Configuration Backend Commands for the details regarding the
cb_cmds
hook library.
The DHCPv4 and DHCPv6 server-specific configurations of the CB, as well as the list of supported configuration parameters, can be found in Configuration Backend in DHCPv4 and Configuration Backend in DHCPv6, respectively.
5.2.4. Configuration Sharing and Server Tags¶
The configuration database is designed to store configuration information for multiple Kea servers. Depending on the use case, the entire configuration may be shared by all servers; parts of the configuration may be shared by multiple servers and the rest of the configuration may be different for these servers; or each server may have its own non-shared configuration.
The configuration elements in the database are associated with the servers
by “server tags.” The server tag is an arbitrary string holding the name
of the Kea server instance. The tags of the DHCPv4 and DHCPv6 servers are
independent in the database, i.e. the same server tag can be created for
both the DHCPv4 and the DHCPv6 server. The value is configured
using the server-tag
parameter in the Dhcp4 or Dhcp6 scope. The current
server tag can be checked with the server-tag-get
command.
The server definition, which consists of the server tag and the server description, must be stored in the configuration database prior to creating the dedicated configuration for that server. In cases when all servers use the same configuration, e.g. a pair of servers running as High Availability peers, there is no need to configure the server tags for these servers in the database.
Commands which contain the logical server all are applied to all servers
connecting to the database. The all server cannot be
deleted or modified, and it is not returned among other servers
as a result of the remote-server[46]-get-all
command.
In most cases, there are no server tags defined in the configuration database; all connecting servers get the same configuration regardless of the server tag they use. The server tag that a particular Kea instance presents to the database to fetch its configuration is specified in the Kea configuration file, using the config-control map (please refer to the Enabling the Configuration Backend and Enabling Configuration Backend for details). All Kea instances presenting the same server tag to the configuration database are given the same configuration.
It is the administrator’s choice whether multiple Kea instances use the same server tag or each Kea instance uses a different server tag. There is no requirement that the instances running on the same physical or virtual machine use the same server tag. It is even possible to configure the Kea server without assigning it a server tag. In such a case the server will be given the configuration specified for all servers.
To differentiate between different Kea server configurations, a list of the server tags used by the servers must be stored in the database. For the DHCPv4 and DHCPv6 servers, it can be done using the commands described in remote-server4-set, remote-server6-set commands and remote-server4-set, remote-server6-set commands. The server tags can then be used to associate the configuration information with the servers. However, it is important to note that some DHCP configuration elements may be associated with multiple server tags (known as “shareable” elements), while other configuration elements may be associated with only one server tag (“non-shareable” elements). The Configuration Backend in DHCPv4 and Configuration Backend in DHCPv6 sections list the DHCP-specific shareable and non-shareable configuration elements; however, in this section we briefly explain the differences between them.
A shareable configuration element is one which has some unique
property identifying it, and which may appear only once in
the database. An example of a shareable DHCP element is a subnet
instance: the subnet is a part of the network topology and we assume
that any particular subnet may have only one definition within this
network. Each subnet has two unique identifiers: the subnet identifier and the
subnet prefix. The subnet identifier is used in Kea to uniquely
identify the subnet within the network and to connect it with other configuration elements,
e.g. in host reservations. Some commands provided by the
cb_cmds
hook library allow the subnet
information to be accessed by either subnet identifier or prefix, and explicitly prohibit
using the server tag to access the subnet. This is because, in
general, the subnet definition is associated with multiple servers
rather than a single server. In fact, it may even be associated
with no servers (unassigned). Still, the unassigned subnet has an
identifier and prefix which can be used to access the subnet.
A shareable configuration element may be associated with multiple servers, one server, or no servers. Deletion of the server which is associated with the shareable element does not cause the deletion of the shareable element. It merely deletes the association of the deleted server with the element.
Unlike a shareable element, a non-shareable element must not be explicitly associated with more than one server and must not exist after the server is deleted (must not remain unassigned). A non-shareable element only exists within the context of the server. An example of a non-shareable element in DHCP is a global parameter, e.g. renew-timer. The renew timer is the value to be used by a particular server and only this server. Other servers may have their respective renew timers set to the same or different values. The renew timer parameter has no unique identifier by which it could be accessed, modified, or otherwise used. Global parameters like the renew timer can be accessed by the parameter name and the tag of the server for which they are configured. For example: the commands described in The remote-global-parameter4-get, remote-global-parameter6-get Commands allow the value of the global parameter to be fetched by the parameter name and the server name. Getting the global parameter only by its name (without specifying the server tag) is not possible, because there may be many global parameters with a given name in the database.
When the server associated with a non-shareable configuration element is deleted, the configuration element is automatically deleted from the database along with the server because the non-shareable element must be always assigned to a server (or the logical server all).
The terms “shareable” and “non-shareable” only apply to associations with user-defined servers; all configuration elements associated with the logical server all are by definition shareable. For example: the renew-timer associated with all servers is used by all servers connecting to the database which do not have their specific renew timers defined. In a special case, when none of the configuration elements are associated with user-defined servers, the entire configuration in the database is shareable because all its pieces belong to all servers.
Note
Be very careful when associating configuration elements with different server tags. The configuration backend does not protect against some possible misconfigurations that may arise from the wrong server tags’ assignments. For example: if a shared network is assigned to one server and the subnets belonging to this shared network to another server, the servers will fail upon trying to fetch and use this configuration. The server fetching the subnets will be aware that the subnets are associated with the shared network, but the shared network will not be found by this server since it doesn’t belong to it. In such a case, both the shared network and the subnets should be assigned to the same set of servers.
5.2.5. Configuration Files Inclusion¶
The parser provides the ability to include files. The syntax was chosen to look similar to how Apache includes PHP scripts in HTML code. This particular syntax was chosen to emphasize that the include directive is an additional feature and not a part of JSON syntax.
The inclusion is implemented as a stack of files. You can use the include directive in nested includes. Up to ten nesting levels are supported. This arbitrarily chosen limit is protection against recursive inclusions.
The include directive has the form:
<?include "[PATH]"?>
The [PATH] pattern should be replaced with an absolute path or a path relative to the current working directory at the time the Kea process was launched.
To include one file from another, use the following syntax:
{
"Dhcp6": {
"interfaces-config": {
"interfaces": [ "*" ]},
"preferred-lifetime": 3000,
"rebind-timer": 2000,
"renew-timer": 1000,
<?include "subnets.json"?>
"valid-lifetime": 4000
}
}
where the content of “subnets.json” may be:
"subnet4": [
{
"id": 123,
"subnet": "192.0.2.0/24"
},
{
"id": 234,
"subnet": "192.0.3.0/24"
},
{
"id": 345,
"subnet": "10.0.0.0/8"
}
],