.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.43) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). .\" Fear. Run. Save yourself. No user-serviceable parts. . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds / .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE .\} .rm #[ #] #H #V #F C .\" ======================================================================== .\" .IX Title "GDNSD-PLUGIN-METAFO 8" .TH GDNSD-PLUGIN-METAFO 8 "2024-01-05" "gdnsd 3.8.2" "gdnsd" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" gdnsd\-plugin\-metafo \- gdnsd plugin for address meta\-failover .SH "SYNOPSIS" .IX Header "SYNOPSIS" Minimal example gdnsd config file using this plugin: .PP .Vb 10 \& plugins => { \& metafo => { \& resources => { \& prod_www => { \& datacenters => [ dc\-01, dc\-02, dc\-03 ] \& dcmap => { \& dc\-01 => 192.0.2.1 \& dc\-02 => { lb01 => 192.0.2.2, lb02 => 192.0.2.3 } \& dc\-03 => [ 192.0.2.4, 192.0.2.5, 192.0.2.6 ] \& } \& }, \& prod_foo => { \& datacenters => [ dc\-01, dc\-02, dc\-bk ] \& dcmap => { \& dc\-01 => { lb01 => 192.0.1.1, lb02 => 192.0.1.2 } \& dc\-02 => [ 192.0.5.1, 192.0.5.2, 192.0.5.3 ] \& dc\-bk => fallback.static.cname.example.org. \& } \& } \& } \& } \& } .Ve .PP Example zonefile RRs in zone example.com: .PP .Vb 3 \& www 600 DYNA metafo!prod_www \& www\-dc01 600 DYNA metafo!prod_www/dc\-01 \& foo 700 DYNC metafo!prod_foo .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" \&\fBgdnsd-plugin-metafo\fR is a meta-plugin. It does static-ordered address failover between multiple \f(CW\*(C`datacenters\*(C'\fR (which may or may not correspond with real datacenters, it's just a convenient label). Each datacenter is defined in terms of other plugins such as \&\f(CW\*(C`multifo\*(C'\fR, \f(CW\*(C`weighted\*(C'\fR, etc, as described below. .SH "CONFIGURATION \- TOP-LEVEL" .IX Header "CONFIGURATION - TOP-LEVEL" The top level of the metafo plugin's configuration (i.e. \f(CW\*(C`plugins => { metafo => { ... } }\*(C'\fR) supports only one fixed, required key, \&\f(CW\*(C`resources\*(C'\fR, whose value must be a hash. The contents of \f(CW\*(C`resources\*(C'\fR is a key per named resource, with the value defining that resource. .PP Any other keys present at the top level will be inherited down inside of each per-resource hash inside the \f(CW\*(C`resources\*(C'\fR stanza, acting as per-resource defaults for anything not defined explicitly there, as explained below. .SH "CONFIGURATION \- RESOURCES" .IX Header "CONFIGURATION - RESOURCES" All keys within the resources stanza represent named resources, which can be referenced by \f(CW\*(C`DYNA\*(C'\fR RRs in zonefiles (e.g. \f(CW\*(C`www DYNA metafo!resource_name\*(C'\fR). Each resource's value must be a key-value hash configuring the resource itself. Lightweight structural example: .PP .Vb 5 \& plugins => { \& metafo => { \& resources => { resA => { ... }, resB => { ... } } \& } \& } .Ve .PP Within a resource, there are only three specifically meaningful keys: .ie n .IP """datacenters = [ A, B, C, ... ]""" 4 .el .IP "\f(CWdatacenters = [ A, B, C, ... ]\fR" 4 .IX Item "datacenters = [ A, B, C, ... ]" Array of datacenter names, required. This is the set of datacenter name labels used for this resource, in the order they will be checked for failover. .ie n .IP """dcmap = { ... }""" 4 .el .IP "\f(CWdcmap = { ... }\fR" 4 .IX Item "dcmap = { ... }" Hash, required. The \f(CW\*(C`dcmap\*(C'\fR is a key-value hash where the keys must be exactly the list of datacenters defined in this resource's \f(CW\*(C`datacenters\*(C'\fR list, and the values defined the address configuration of each datacenter. Another minimal structural example down to this level: .Sp .Vb 10 \& plugins => { \& metafo => { \& resources => { \& resA => { \& datacenters => [ dc01, dc02 ], \& dcmap => { \& dc01 => ??? \& dc02 => ??? \& } \& } \& } \& } \& } .Ve .Sp There are several forms the per-datacenter values (\f(CW\*(C`???\*(C'\fR above) can take, documented in the next section. .ie n .IP """skip_first = true""" 4 .el .IP "\f(CWskip_first = true\fR" 4 .IX Item "skip_first = true" If this boolean configuration flag is set, the resolver code will skip the first datacenter when resolving this resource. This is mostly useful in the context of the geoip plugin, and is discussed in more detail there. .PP Any keys other than \f(CW\*(C`datacenters\*(C'\fR and \f(CW\*(C`dcmap\*(C'\fR at the per-resource level serve as inherited defaults for each per-datacenter configuration inside of the \f(CW\*(C`dcmap\*(C'\fR. .SH "PER-DATACENTER RESOLUTION" .IX Header "PER-DATACENTER RESOLUTION" The value of the datacenters within the \f(CW\*(C`dcmap\*(C'\fR section of a resource can take several forms. It is important to understand that for the most part, plugin_metafo does not deal with this level of results itself, but instead delegates the work at this scope to other plugins. These sub-plugins, in turn, also notify metafo of complete failure at their level, which is the information metafo uses to know to fail over to the next datacenter in the list. .PP The most direct and obvious way to do this is with a direct reference of the form \f(CW\*(C`%plugin!resource\*(C'\fR, as shown here: .PP .Vb 10 \& plugins => { \& metafo => { \& resources => { \& resA => { \& datacenters => [ dc1, dc2 ], \& dcmap => { \& dc1 => %multifo!res_mfo1 \& dc2 => %multifo!res_mfo2 \& } \& } \& } \& } \& multifo => { \& res_mfo1 => { lb01 => 192.0.2.1, lb02 => 192.0.2.3 } \& res_mfo2 => { lb01 => 192.0.2.111, lb02 => 192.0.2.113 } \& } \& } .Ve .PP However, to make life simpler in the simple cases, plugin_metafo can synthesize the lower-level plugin's configuration from a hash, like so: .PP .Vb 10 \& plugins => { \& metafo => { \& resources => { \& resA => { \& datacenters => [ dc1, dc2 ], \& dcmap => { \& dc1 => { plugin => multifo, lb01 => 192.0.2.1, lb02 => 192.0.2.3 } \& dc2 => { lb01 => 192.0.2.111, lb02 => 192.0.2.113 } \& # the above are effectively treated as: \& # dc1 => %multifo!metafo_resA_dc1 \& # dc2 => %multifo!metafo_resA_dc2 \& } \& } \& } \& } \& # below does not exist in your configfile, but is what plugin_metafo \& # synthesizes to support the above: \& #multifo => { \& # metafo_resA_dc1 => { lb01 => 192.0.2.1, lb02 => 192.0.2.3 } \& # metafo_resA_dc2 => { lb01 => 192.0.2.111, lb02 => 192.0.2.113 } \& #} \& } .Ve .PP Within a hash like the above, the special key \f(CW\*(C`plugin\*(C'\fR will be stripped out internally and used to name the plugin we synthesize the config for. \&\f(CW\*(C`plugin\*(C'\fR defaults to \f(CW\*(C`multifo\*(C'\fR if not specified. Note that \f(CW\*(C`plugin\*(C'\fR could also be specified at the resource level (just inside of the \f(CW\*(C`resA\*(C'\fR stanza) to change the default for all \f(CW\*(C`dcmap\*(C'\fR entries in one resource, and could also be specified at the outer-most scope (just inside the \f(CW\*(C`metafo\*(C'\fR stanza) to change the default for all resources. .PP The defaulted-down \f(CW\*(C`plugin\*(C'\fR is also the default for the direct-reference \&\f(CW\*(C`%plugin!resource\*(C'\fR form discussed earlier. With the correct default plugin name, it can be shortened to just \f(CW\*(C`!resource\*(C'\fR. .PP The same sort of key-value inheritance scheme (top-level \-> per-resource level \-> per-datacenter level) can also be used for any other parameter in synthesized resource configurations specific to the per-datacenter plugin(s) you are using. A common example would be the \f(CW\*(C`service_types\*(C'\fR parameter that most plugins which support monitored address results have. Note that these other values (e.g. service_types) would only apply to synthesized resources, \fBnot\fR to direct-references like \f(CW\*(C`%multifo!foo\*(C'\fR, which must be configured entirely separately within that plugin's config. .PP There are three other possible shortcut values for datacenters: a single direct address, an array of addresses, or a single \s-1CNAME\s0 hostname. If a single \s-1IP\s0 address or an array of \s-1IP\s0 addresses are specified, plugin_metafo will synthesize a hash from them with the plugin forced to \f(CW\*(C`multifo\*(C'\fR (since it cannot know the syntax of hashes for all other plugins, which may differ), and give them address labels \f(CW1\fR, \f(CW2\fR, etc. .PP If the value for a datacenter is a single \s-1CNAME\s0 hostname, no sub-plugin is used, and that \s-1CNAME\s0 result is returned directly. Note that any resource with such an entry can only be used with \f(CW\*(C`DYNC\*(C'\fR RRs, and not \&\f(CW\*(C`DYNA\*(C'\fR RRs (as is the case if any subplugin's configuration is capable of returning \s-1CNAME\s0 data). .PP A much more complete example, showing off most of the features above: .PP .Vb 10 \& plugins => { \& metafo => { \& plugin => multifo # change default for all resources \& service_types => [ bar ] # default service_types for synthesized below \& resources => { \& resA => { \& plugin => multifo # change default for this resource \& service_types => [foo, bar] # services types for synthesized below: \& datacenters => [ dc1, dc2, dc3, dc4, dc5, dc6, dc7, dc8 ], \& dcmap => { \& dc1 => { plugin => multifo, lb01 => 192.0.2.1, lb02 => 192.0.2.3 } \& dc2 => { lb01 => 192.0.2.111, lb02 => 192.0.2.113 } \& dc3 => %simplefo!foo \& dc4 => { plugin => simplefo, primary => 192.0.2.100, secondary => 192.0.2.101 } \& dc5 => !bar \& dc6 => 192.0.2.150 \& dc7 => [ 192.0.2.180, 192.0.2.181 ] \& dc8 => last.resort.example.com. \& } \& } \& } \& } \& # below, commented\-out sections show configuration synthesized \& # by plugin_metafo, whereas the rest are direct\-references that \& # had to be manually specified here: \& multifo => { \& # metafo_resA_dc1 => { lb01 => 192.0.2.1, lb02 => 192.0.2.3, service_types => [foo, bar] } \& # metafo_resA_dc2 => { lb01 => 192.0.2.111, lb02 => 192.0.2.113, service_types => [foo, bar] } \& bar => { asd => 192.0.2.77, xyz => 192.0.2.88 } \& # metafo_resA_dc6 => { 1 => 192.0.2.150, service_types => [foo, bar] } \& # metafo_resA_dc7 => { 1 => 192.0.2.180, 2 => 192.0.2.181, service_types => [foo, bar] } \& } \& simplefo => { \& foo => { primary => 192.0.2.80, secondary => 192.0.2.81 } \& # metafo_resA_dc4 => { primary => 192.0.2.100, secondary => 192.0.2.101, service_types => [foo, bar] } \& } \& } .Ve .PP Note in the example above that \f(CW\*(C`%multifo!bar\*(C'\fR and \f(CW\*(C`%simplefo!foo\*(C'\fR would have had their default \f(CW\*(C`service_types = up\*(C'\fR rather than the one specified at the metafo level, because they were not synthesized. It would be up to you to keep all of the service_types in sync when using direct references. .SH "SYNTHETIC PER-DATACENTER RESOURCES" .IX Header "SYNTHETIC PER-DATACENTER RESOURCES" This plugin will synthesize additional, per-datacenter resource names from your configuration. They are named as \f(CW\*(C`resname/dcname\*(C'\fR. For example, if you define a metafo resource named \f(CW\*(C`prodwww\*(C'\fR with the datacenter list \&\f(CW\*(C`[ pri, sec ]\*(C'\fR, the resource names \f(CW\*(C`prodwww/pri\*(C'\fR and \f(CW\*(C`prodwww/sec\*(C'\fR will be sythesized and can be used in zonefile records, e.g.: .PP .Vb 1 \& www\-backup 300 DYNA metafo!prodwww/sec .Ve .PP When used, these per-datacenter synthetic resource names cause a given lookup to skip the normal failover process and directly return results from that particular datacenter. .SH "SEE ALSO" .IX Header "SEE ALSO" \&\fBgdnsd.config\fR\|(5), \fBgdnsd.zonefile\fR\|(5), \fBgdnsd\fR\|(8) .PP The gdnsd manual. .SH "COPYRIGHT AND LICENSE" .IX Header "COPYRIGHT AND LICENSE" Copyright (c) 2012 Brandon L Black .PP This file is part of gdnsd. .PP gdnsd is free software: you can redistribute it and/or modify it under the terms of the \s-1GNU\s0 General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. .PP gdnsd is distributed in the hope that it will be useful, but \s-1WITHOUT ANY WARRANTY\s0; without even the implied warranty of \&\s-1MERCHANTABILITY\s0 or \s-1FITNESS FOR A PARTICULAR PURPOSE.\s0 See the \&\s-1GNU\s0 General Public License for more details. .PP You should have received a copy of the \s-1GNU\s0 General Public License along with gdnsd. If not, see .