Dependency Redundancy Groups in Icinga 2.14

by | Oct 11, 2023

Icinga 2.14 introduced a new feature that allows to better model complex dependencies between your hosts and services: redundancy groups. Let’s take an e-mail server as an example. In order to deliver outgoing messages, it has to look up the addresses of the destination servers and relies on DNS for doing so. For incoming messages, it has to know which accounts exist and in a corporate environment, this typically means looking up user accounts in a directory service like LDAP. Both DNS and LDAP services are often crucial for many other services in IT landscape of a company, therefore they are often replicated to provide redundancy and avoid single points of failure.

In the past, modelling something like this in Icinga turned out to be tricky as there was actually no mechanism to configure this. This has changed in Icinga 2.14 where we introduced redundancy groups that allow exactly this. Just like before, you can create multiple Dependency objects that define a relation to multiple parents in Icinga 2. What’s new is that you can now put them into different groups to actually define what parent provides redundancy for which other parents. So in our example, we can define a redundancy group called DNS and another one called LDAP, meaning that within each group, at least one parent has to be available for the dependencies of the child to be fulfilled.

Mail service with two dependencies that are in a DNS group for two DNS servers and two dependencies in another LDAP group for two LDAP servers.

This can be configured in Icinga 2 using the new redundancy_group attribute. Simply set it to a string value that represents the group. Note that there are no explicit group objects that have to be created. All dependencies of a child that share the same value in the redundancy_group attribute are grouped together. For our example from above, the configuration would look something like the following. In order to keep the example shorter, it defines dependencies between Host objects. It will work just as well for Service objects, you just have to specify additional parent_service_name and child_service_name attributes.

#############################################
# DNS redundancy group for mail.example.com #
#############################################

object Dependency "dns1" {
  parent_host_name = "dns1.example.com"
  child_host_name = "mail.example.com"
  redundancy_group = "DNS"
}

object Dependency "dns2" {
  parent_host_name = "dns2.example.com"
  child_host_name = "mail.example.com"
  redundancy_group = "DNS"
}


##############################################
# LDAP redundancy group for mail.example.com #
##############################################

object Dependency "ldap1" {
  parent_host_name = "ldap1.example.com"
  child_host_name = "mail.example.com"
  redundancy_group = "LDAP"
}

object Dependency "ldap2" {
  parent_host_name = "ldap2.example.com"
  child_host_name = "mail.example.com"
  redundancy_group = "LDAP"
}

Now, if dns1.example.com and ldap2.example.com fail for example (see left image below), but the other server from each group is still available, the dependencies of mail.example.com are satisfied. If the mail server happens to have a problem as well at that time, it’s considered to be a separate problem. However, if dns2.example.com now fails additionally (see right image below), no parent from the DNS redundancy group is left and the dependency is no longer satisfied and the mail server problem is now considered to be a dependency problem.

Same services and dependencies as before. Within the DNS group, one server is now marked as failed while to other is still available. Same for the LDAP group. This results in the dependencies being satisfied resulting in a problem of the mail server being independent of dependencies.Same services and dependencies again. Now, both DNS servers in the DNS group are marked as failed, meaning the the dependencies of the mail server are no longer fulifilled.

Dependencies that set redundancy_group can be mixed with ones that don’t. If the attribute isn’t set, that dependency is treated as if it’s part of its very own group containing only itself. Thus, such a dependency is always considered to be essential for the child.

Another more generic example with a child service that has 6 parent services named A to F. Parents A and B are in a group named G1 and parents D and E in a group G2. The remaining parents C and F are not in any named group and thus each is in its own unnamed group.

In this example, child depends on at least one parent from group G1 (that is A or B), at least one parent from G2 (that is D or E), as well as on both parents C and F that are not part of any group. Or if you prefer a formula: (A or B) and C and (D or E) and F determines whether the dependencies of child are satisfied.

I’d also like to thank Edgar Fuß who suggested the feature and also contributed code changes for it. If you want to contribute to Icinga as well, you can head over to our GitHub profile where you will find our projects.

You May Also Like…

Subscribe to our Newsletter

A monthly digest of the latest Icinga news, releases, articles and community topics.