#author("2019-04-28T10:22:08+09:00","default:nowsky","nowsky")
#author("2019-04-28T23:30:33+09:00","default:nowsky","nowsky")
*dnsdist [#n2d45d2d]
DNSに特化したリバース・フォワード兼用ロードバランサー。
バックエンド死活監視、ポリシールーティング、QoS制御などのLSLBが備える機能を一通り実装している。
設定ファイルはLua言語で記述する形式なので、環境に合わせて細かい挙動制御も出来る。
なお、DNSクエリに限定すると、dnsdistはクエリのフォワード動作に特化している為、
バックエンドに権威DNS、キャッシュDNS何れかを構築する必要がある。
バックエンド死活監視、ポリシールーティング、QoS制御などのLSLBが備える機能を実装している。
設定ファイルはLua言語で記述するので、環境に合わせてスクリプト主体の細かい制御も出来る。
DNSクエリ処理に限定すると、dnsdistはクエリ・フォワード動作に特化している為、
バックエンドに権威DNS・キャッシュDNSなどを構築する必要がある。
 
ソフトウェアとしては単一バイナリ動作なので、機能を盛り見過ぎるとバイナリが70MB程まで大きくなる。
必要な機能に限定してソースビルドを行いバイナリ容量の削減をすると、
dnsdist稼働時の仕様メモリ削減も図る事が出来るので、基本はソースビルドが無難な構築方法となる。
アプリケーションは単一バイナリ動作なので、機能を盛り過ぎるとバイナリが70MB程まで大きくなる。
必要な機能を抜粋して自前でソースビルドを行うと、バイナリ容量と使用メモリ容量の削減が出来る。
~
*参考サイト [#ma8ed405]
-[[powerdns+dnsdistの構築:+http://kyudy.hatenablog.com/entry/2016/12/27/193928]]
-[[自宅環境にdnsdist 1.1.0を導入してみた。:+https://kometchtech.blog.fc2.com/blog-entry-2049.html]]
~
*インストール [#x03f304c]
-&size(16){&font(b){1. インストール};};
汎用性が高い為、ソースからdnsdistをビルドする。
今回はopenSUSE環境でビルドを行っているが、CentOS/Debianでも同様の手順でビルド出来る。
prefix指定は、バイナリバージョン管理の為にシンボリックリンクで参照先を切り替える手法をとる。
 # zypper install libev4 libev-devel ragel
 # wget https://github.com/gdnsd/gdnsd/archive/v2.4.0.tar.gz
 # tar zxvf gdnsd-2.4.0.tar.gz
 # cd gdnsd-2.4.0
 # autoreconf --install
 # ./configure --prefix=/usr/local/gdnsd-2.4.0
-&size(16){&font(b){1. ソースビルド};};
ソースビルドだと様々なディストリビューションで動作して汎用性が高いのでソースビルドする。
今回はopenSUSEでビルドを行っているが、CentOS/Debianでも同様の手順でビルド出来る。
下記のビルドオプションはフル機能を有効化している為、不必要な機能を削除するとバイナリが更に軽くなる。
 # zypper install libedit-devel libsodium-devel systemd-devel fstrm-devel protobuf-devel boost-devel re2-devel
 # wget "https://downloads.powerdns.com/releases/dnsdist-1.3.3.tar.bz2"
 # tar jxvf dnsdist-1.3.3.tar.bz2
 # cd dnsdist-1.3.3
 # ./configure --prefix=/usr/local/dnsdist-1.3.3 \
               --enable-dns-over-tls             \
               --enable-dnscrypt                 \
               --enable-fstrm                    \
               --enable-re2                      \
               --enable-systemd                  \
               --with-ebpf                       \
               --with-lua                        \
               --with-net-snmp                   \
               --with-protobuf                   \
               --with-systemd                    \
               --with-systemd-modules-load
 # make
 # make install
 # ln -s /usr/local/dnsdist-1.3.3 /usr/local/dnsdist
 
-&size(16){&font(b){2. 起動準備};};
gdnsdを動かす為の実行ユーザを作成した上で起動スクリプトも準備する。
gdnsdはsystemd起動に最適化されている為、従来のinitスクリプトでは無くサービスファイルから起動を行う。
なお、v3.0.0から起動オプションが変わった為、アップグレード時はserviceファイルを修正する必要がある。
#region(&color(#ff0000){v2.4.0 起動コマンド};)
 # cd /usr/local
 # ln -s /usr/local/gdnsd-2.4.0 gdnsd
 # cd /etc
 # ln -s /usr/local/gdnsd/etc/gdnsd gdnsd
 # vi /usr/lib/systemd/system/gdnsd.service
 ---
 [Unit]
 Description=gdnsd Authoritative GSLB type DNS Server
 After=local-fs.target network.target remote-fs.target nss-lookup.target
 
 [Install]
 WantedBy=multi-user.target
 
 [Service]
 Type=notify
 NotifyAccess=all
 ExecStart=/usr/local/gdnsd/sbin/gdnsd -c /etc/gdnsd -f start
 ExecStop=/usr/local/gdnsd/sbin/gdnsd -c /etc/gdnsd stop
 
 ## Security Setting
 MountFlags=slave
 DevicePolicy=closed
 PrivateDevices=true
 PrivateTmp=true
 ProtectSystem=full
 ProtectHome=true
dnsdist専用ユーザで動作させる為、実行ユーザの作成とサービスファイルの準備を行う。
さらに、今回はDNSクエリログのローカル出力を有効化する為、ログディレクトリ作成、ログローテート設定も実施する。
#region(&color(#ff0000){ディレクトリ作成};)
 # mkdir /var/log/dnsdist
 # mkdir /usr/local/dnsdist/etc
 # ln -s /usr/local/dnsdist/etc /etc/dnsdist
 # groupadd dnsdist
 # useradd -d /var/log/dnsdist -s /sbin/nologin dnsdist
 # chown dnsdist.dnsdist /var/log/dnsdist
 # cp ${SOURCE}/dnsdistconf.lua /etc/dnsdist/dnsdist.conf.sample
#endregion
#region(&color(#ff0000){v3.0.0 起動コマンド};)
 # cd /usr/local
 # ln -s /usr/local/gdnsd-3.0.0 gdnsd
 # cd /etc
 # ln -s /usr/local/gdnsd/etc/gdnsd gdnsd
 # echo '# Type Path            Mode UID   GID   Age Argument' >> /usr/lib/tmpfiles.d/gdnsd.conf
 # echo 'd      /var/run/gdnsd/ 0700 gdnsd gdnsd -   -'        >> /usr/lib/tmpfiles.d/gdnsd.conf
 # vi /usr/lib/systemd/system/gdnsd.service
#region(&color(#ff0000){サービスファイル};)
 # vi /usr/lib/systemd/system/dnsdist.service
 ---
 [Unit]
 Description=gdnsd Authoritative GSLB type DNS Server
 After=local-fs.target network.target remote-fs.target nss-lookup.target
 Description=dnsdist DNS loadbalancer
 Documentation=https://dnsdist.org/
 After=local-fs.target remote-fs.target network.target
 
 [Install]
 WantedBy=multi-user.target
 
 [Service]
 Type=notify
 NotifyAccess=all
 ExecStart=/usr/local/gdnsd/sbin/gdnsd -c /etc/gdnsd -l start
 ExecStop=/usr/local/gdnsd/bin/gdnsdctl -c /etc/gdnsd -l stop
 ExecReload=/usr/local/gdnsd/bin/gdnsdctl -c /etc/gdnsd -l replace
 Restart=on-failure
 EnvironmentFile=/etc/sysconfig/dnsdist
 ExecStartPre=/usr/local/dnsdist/bin/dnsdist --disable-syslog --check-config $OPTIONS
 ExecStart=/usr/local/dnsdist/bin/dnsdist --disable-syslog --supervised -u $USER -g $GROUP $OPTIONS
 ExecStop=/bin/kill -s QUIT $MAINPID
 ExecReload=/bin/kill -s HUP $MAINPID
 
 ## Security, daemon management
 User=gdnsd
 UMask=0022
 RuntimeDirectory=gdnsd
 RuntimeDirectoryMode=0700
 CapabilityBoundingSet=CAP_NET_BIND_SERVICE
 AmbientCapabilities=CAP_NET_BIND_SERVICE
 
 ## Security Setting
 MountFlags=slave
 DevicePolicy=closed
 PrivateDevices=true
 PrivateTmp=true
 ProtectSystem=full
 ProtectHome=true
 ## TUNING
 TasksMax=8192
 LimitNOFILE=65536
#endregion
 
-&size(16){&font(b){3. コンフィグ};};
gdnsdのコンフィグは、&color(#ff0000){[${PREFIX}/etc/gdnsd/config]};から固定参照で読み込んでいるので、
上記設定に合わせてコンフィグを作成しないと、プログラムの起動に失敗する。
今回はprefixをシンボリックリンクで[/usr/local/gdnsd]に変更している為、
作成するコンフィグファイル名も&color(#ff0000){[/usr/local/gdnsd/etc/gdnsd/config]};になる。
コンフィグファイルにはgdnsdのヘルスチェック条件も書く必要があるが、
権威DNSサーバ機能のみ利用するならば、optionsのみ記載すればプログラムを起動出来る。
v3.0.0で一部の設定項目が廃止となった為、エラーが出た場合はコンフィグを修正する。
 # vi /usr/local/gdnsd/etc/gdnsd/config
#region(&color(#ff0000){起動オプション};)
 # vi /etc/sysconfig/dnsdist
 ---
 options => {
     username       => gdnsd,
     chaos_response => "GSLB",
     listen         => 0.0.0.0:53,
     http_listen    => 0.0.0.0:3506,
     log_stats      => 3600,
     tcp_threads    => 1,
     udp_threads    => 1,
 
     include_optional_ns    => true,
     disable_text_autosplit => false,
     zones_strict_data      => false,
     zones_strict_startup   => true,
     zones_rfc1035_auto     => false,
 
     state_dir              => /var/lib/gdnsd,
     run_dir                => /var/run/gdnsd,
     plugin_search_path     => /usr/local/gdnsd/lib64/gdnsd,
 }
#region(&color(#ff0000){設定の解説};)
全オプションはgdnsdの[[公式ドキュメント:+https://github.com/gdnsd/gdnsd/wiki/GdnsdConfig]]を確認する。
最低限の動作を行う場合、下記オプションを参考に設定を行う。
|LEFT:200|CENTER:50|CENTER:50|LEFT:600|c
|CENTER:~OPTIONS HASH|CENTER:~v2.4.0|CENTER:~v3.0.0|CENTER:~DESCRIPTION|h
|&color(#2020ff){username};|○|×|gdnsdの実行ユーザ。グループはユーザに紐付いている物が自動適用される&br;[v3.0.0] serviceファイルに直接設定する方式に変更となり削除|
|&color(#2020ff){chaos_response};|○|○|CHクラスの応答内容&br;権威DNSのバージョン確認クエリに、設定した文字列を返す|
|&color(#2020ff){listen};|○|○|gdnsdの待ち受けIPアドレス・ポート番号&br;複数IPを待ち受けする場合はリスト構造にする|
|&color(#2020ff){http_listen};|○|×|gdnsdヘルスチェック画面の待ち受けIPアドレス・ポート番号&br;[v3.0.0] HTTPサーバ(HTTP listener)廃止により設定項目も削除|
|&color(#2020ff){log_stats};|○|×|DNSクエリの統計ログ出力間隔で、値を"0"にすると統計ログ出力が無効化される&br;[v3.0.0] HTTPサーバ(HTTP listener)廃止により設定項目も削除|
|&color(#2020ff){tcp_threads};|○|○|リスナーアドレスに対して作成されるスレッド数&br;マルチコアCPUの場合、CPUコアの2~4倍にするとパフォーマンスが上がる|
|&color(#2020ff){udp_threads};|○|○|リスナーアドレスに対して作成されるスレッド数&br;マルチコアCPUの場合、CPUコアの2~4倍にするとパフォーマンスが上がる|
|&color(#2020ff){include_optional_ns};|○|×|DNSのAuthoritySectionにオプションのNSレコードを含めて応答する&br;[v3.0.0] 応答速度重視により設定がfalseで固定された為、項目も削除|
|&color(#2020ff){disable_text_autosplit};|○|○|TXTレコードを255バイト毎に自動分割する設定を切り替える&br;通常は自動分割させる為、&color(#ff0000){自動分割を無効(false)};に設定する|
|&color(#2020ff){zones_strict_data};|○|○|DNSゾーンファイルで重要度低のエラーが発生してもデーモンを起動する&br;"zones_strict_startup"の設定に依存する|
|&color(#2020ff){zones_strict_startup};|○|○|gdnsd起動時にDNSゾーンファイルが正しく読めない時は起動停止させる&br;無効化(false)の場合、読込み失敗したDNSゾーンをスキップして起動させる|
|&color(#2020ff){zones_rfc1035_auto};|○|×|DNSゾーンファイルの書き換えを検出し、DNSレコードに自動適用する&br;[v3.0.0] オートスキャン(autoscanning)廃止により削除|
|&color(#2020ff){state_dir};|○|○|gdnsdのデーモン起動情報を外部プログラムと連携する際に使用&br;ディレクトリが存在しない時は自動生成される|
|&color(#2020ff){run_dir};|○|○|gdnsdのPIDファイル保存フォルダ&br;systemdからプロセス操作を行う際に必須となる|
|&color(#2020ff){plugin_search_path};|○|×|プラグインの保存先で、基本的に&color(#ff0000){"${PREFIX}/lib64/gdnsd"};を設定する&br;[v3.0.0] プラグインの外部参照廃止と共に削除|
 USER="dnsdist"
 GROUP="dnsdist"
 OPTIONS="-C /etc/dnsdist/dnsdist.conf"
#endregion
 
-&size(16){&font(b){4. ゾーンファイル};};
DNSゾーンファイルは、権威DNSとしてレコードを登録したいORIGINと同じファイル名にする。
例えば、[gslb.test.org]のゾーンを作成する場合、
DNSゾーンファイルは&color(#ff0000){[/usr/local/gdnsd/etc/gdnsd/zones/gslb.test.org]};となる。
ファイルの書式は基本的にBINDのゾーン記法と同じだが、
ヘルスチェックを元にした可変レコードの箇所のみ、gdnsd特有の設定を行う必要がある。
GSLBの特性上TTLを短くする必要がある為、ゾーンファイル内でTTLを明記して設定を切り替える。
参考として、DNSゾーンファイルの例を構築例に従って作成してみる。
 # vi /usr/local/gdnsd/etc/gdnsd/zones/gslb.test.org
#region(&color(#ff0000){ログローテート};)
 # vi /etc/logrotate.d/dnsdist
 ---
 $ORIGIN gslb.test.org.
 $TTL    3600
 @       IN  SOA  ns1.gslb.test.org.  root.gslb.test.org. (
                                         2018010101  ; serial
                                         3600        ; refresh
                                         1200        ; retry
                                         1209600     ; expire
                                         3600        ; minimum
                                      )
 
 ;; GLUE RECORD
 ;;
         IN  NS      ns1.gslb.test.org.
         IN  NS      ns2.gslb.test.org.
 ns1     IN  A       10.0.0.1
 ns2     IN  A       10.0.0.2
 
 ;; CONTENTS
 sv1     IN  A       192.168.0.1
 sv2     IN  A       192.168.0.2
 
 ;; GSLB
 ;;
 $TTL    10
 ;; この箇所にGSLBの可変レコードを記載
 
-&size(16){&font(b){5. 起動};};
事前に作成したサービスファイルを用いてgdnsdを起動する。
ログはsyslogのdaemonファシリティに出力されるので、起動しない時は該当ログを確認する。
 # systemctl unmask gdnsd
 # systemctl enable gdnsd
 # systemctl start gdnsd
~
*ステータス [#f276bc79]
gdnsdのヘルスチェック確認はメジャーバージョンによって変化する。
v2.4.2までは、同梱するHTTPサーバを用いたGUI確認となるが、
v3.0.0以降は、コマンドで出力したJSON形式の実行結果を見る事となる。
#region(&color(#ff0000){v2.4.0 ステータス確認};)
#block
v2.4.0にはプログラムの稼働状況確認画面(ステータス画面)があり、
コンフィグで設定した[http_listen]パラメータをWebブラウザに入力し、
Webブラウザからgdnsdに接続して見る事が出来る。
 
確認出来る項目は下記の通り基本的な物は網羅している。
また、CSV/JSONを利用して別システムと連携する事も可能になっている。
ただし、gdnsdが処理したDNSクエリ自体は確認する事が出来ない。
-DNSクエリの応答ステータス
-gdnsdの応答クエリ統計情報
-ヘルスチェック稼働状況
-統計情報のCSV/JSONファイル

 
ステータス画面はgdnsdの稼働状況を視認出来るので便利だが、
画面自体をユーザ・パスワード認証する事が出来ない。
よって、本番環境で利用する場合は、iptablesで接続元IP制限を掛けるか、
&color(#ff0000){[http_listen => 127.0.0.1:3506]}; でローカルループバックアドレスで待ち受け、
フロントエンドは認証設定したリバースプロキシにするなど注意して利用する。
#block(next)
#ref(Linux/Source/gdnsd/wiki_gdnsd_02.png,45%,left,nowrap)
#block(end)
#endregion
#region(&color(#ff0000){v3.0.0 ステータス確認};)
v3.0.0ではコマンドラインで確認する形になる。
出力データはJSON型となるが、項目はv2.4.0のGUI画面同等の内容を確認できる。
-バージョン確認
 # /usr/lcoal/gdnsd/bin/gdnsdctl -c /etc/gdnsd status
 ---
 info: version 3.0.0 running at PID 10000
 
-daemonステータス
 # /usr/lcoal/gdnsd/bin/gdnsdctl -c /etc/gdnsd stats
 ---
 {
         "uptime": 3933,
         "stats": {
                 "noerror": 381,
                 "refused": 0,
                 "nxdomain": 0,
                 "notimp": 0,
                 "badvers": 0,
                 "formerr": 0,
                 "dropped": 0,
                 "v6": 0,
                 "edns": 69,
                 "edns_clientsub": 0,
                 "edns_do": 64,
                 "edns_cookie_formerr": 0,
                 "edns_cookie_ok": 0,
                 "edns_cookie_init": 5,
                 "edns_cookie_bad": 0
         },
         "udp": {
                 "reqs": 381,
                 "recvfail": 0,
                 "sendfail": 0,
                 "tc": 0,
                 "edns_big": 0,
                 "edns_tc": 0
         },
         "tcp": {
                 "reqs": 0,
                 "recvfail": 0,
                 "sendfail": 0,
                 "conns": 0,
                 "close_c": 0,
                 "close_s_ok": 0,
                 "close_s_err": 0,
                 "close_s_kill": 0,
                 "proxy": 0,
                 "proxy_fail": 0
         }
 /var/log/dnsdist/dnsdist.log {
     weekly
     compress
     rotate 4
     missingok
     ifempty
     postrotate
         systemctl reload dnsdist > /dev/null
     endscript
 }
 
-ヘルスチェックステータス
 # /usr/lcoal/gdnsd/bin/gdnsdctl -c /etc/gdnsd states
 ---
 {
         "metafo/XXX/active": {"state": "NA", "real_state": "NA"},
         "metafo/XXX/standby": {"state": "NA", "real_state": "NA"},
         "***.***.***.***/XXX": {"state": "UP", "real_state": "UP"},
         "***.***.***.***/XXX": {"state": "UP", "real_state": "UP"},
 }
#endregion
~
*ヘルスチェック [#abacba5f]
GSLBは下位サーバに対してヘルスチェックを行い、ステータスに応じた可変レコード応答が特徴となる。
負荷分散(ラウンドロビン)、冗長化(アクティブ・スタンバイ)など様々な構成を取る事が出来る。
gdnsdにもヘルスチェックが搭載されており、基本的なGSLBとして機能するようになっている。
また、標準のヘルスチェックで機能不足の場合、ヘルスチェックで外部コマンドを実行する事で、
環境に応じた機能拡張を行う事も出来る。
*コンフィグ [#he433c1c]
構築例ではdnsdistのコンフィグを &color(#ff0000){"/etc/dnsdist/dnsdist.conf"}; としている為、
下記コンフィグ例も同じファイルに設定を行う。
dnsdistの設定は単純な為、単にDNSロードバランサーとして稼働させるならば、
「DNSクエリ・クエリタイプ・接続元IPアドレス・パケット制御」の4項目を抑えれば設定出来る。
 
gdnsdのヘルスチェックを利用する時は、gdnsdのconfigファイルにヘルスチェック定義を設定した後、
DNSゾーンファイルで専用の可変レコードを設定する事により利用可能となる。
可変レコードは&color(#ff0000){Aレコードを定義するDYNAレコード};と、&color(#ff0000){CNAMEを定義するDYNCレコード};の2種類が存在する。
ただし、利用出来る可変レコードはプラグイン毎に制限されている為、詳細は公式ドキュメントを確認する。
複数のポリシーを組み合わせる時は、MatchingPackets(Selectors)の &color(#ff0000){"AndRule/NotRule/OrRule"}; 条件、
バックエンドのサーバ設定は、Servers/Poolsの &color(#ff0000){"newServer/getServer"}; を利用する。
その他、細かい設定内容は公式ドキュメントの下記3項目を読めば大体判る。
-[[Configuration Reference:+https://dnsdist.org/reference/config.html]]
-[[Loadbalancing and Server Policies:+https://dnsdist.org/guides/serverselection.html]]
-[[Packet Policies:+https://dnsdist.org/rules-actions.html]]
 
DYNA/DYNCレコードは &color(#ff0000){["プラグイン種別"!"応答レコード定義名"]}; で設定する。
DNSゾーンファイルには下記の様なレコードを追記する事となる。
 www    10  DYNA  multifo!tcp_80
 blog   10  DYNA  weighted!tcp_443
 cname  10  DYNC  weighted!tcp_cname
 
-&size(16){&font(b){ラウンドロビン};};
#region(&color(#ff0000){設定内容};)
ヘルスチェックを行いつつ、コンテンツサーバにラウンドロビンで振り分ける。
コンテンツサーバでWEB(TCP:80)を待ち受けている環境を想定して作成する。
gdnsdのヘルスチェック設定は、既存のconfigファイルに追記を行う事で定義する。
 # vi /usr/lcoal/gdnsd/etc/gdnsd/config
 ---
 service_types   => {
     tcp_80_http => {
         plugin      => http_status,
         port        => 80,
         url_path    => /,
         ok_codes    => [ 200, 301 ],
         up_thresh   => 10,
         ok_thresh   => 5,
         down_thresh => 5,
         interval    => 5,
         timeout     => 4,
     }
 }
 
 plugins     => {
     multifo => {
         tcp_80 => {
             service_types => tcp_80_http,
             up_thresh     => 0.001,
             SERVERA       => 192.168.0.1,
             SERVERB       => 192.168.0.2,
         }
     }
 }
 
DNSゾーンファイルには、Aレコード・CNAMEの応答内容に従って可変レコードを記載する。
例えば、Aレコードとして可変応答させる場合は下記の様になる。
 # vi /usr/local/gdnsd/etc/gdnsd/zones/gslb.test.org
 ---
 ;; DNSゾーンに追記
 $TTL    10
 www     10  DYNA   multifo!tcp_80
#region(&color(#ff0000){単純ロードバランサー};)
 ※ 実際の設定では頭の行番号("01: "など)を消す
 ============================================================================================
 01: -- BACKEND
 02: check01 = "ns1.example.com."
 03: check02 = "ns2.example.com."
 04: newServer({address="10.0.10.1:53", pool="example", checkName=check01, mustResolve=true})
 05: newServer({address="10.0.10.2:53", pool="example", checkName=check02, mustResolve=true})
 06: 
 07: -- LISTEN
 08: addLocal("10.0.0.1:53", {doTCP=true})
 09: 
 10: -- ACL
 11: setACL("0.0.0.0/0")
 12: 
 13: -- RULE
 14: internet = newSuffixMatchNode()
 15: internet:add(newDNSName("example.com."))
 16: 
 17: -- LOG
 18: addAction(AllRule(), LogAction("/var/log/dnsdist/dnsdist.log", false, true, false))
 19: 
 20: -- POLICY
 21: addAction(SuffixMatchNodeRule(internet), PoolAction("example"))
 22: addAction(QTypeRule(dnsdist.TXT),        PoolAction("example"))
 23: addAction(AllRule(),                     RCodeAction(dnsdist.REFUSED))
|LEFT:50|LEFT:250|LEFT:600|c
|CENTER:~LINE|CENTER:~PARAMETER|CENTER:~DESCRIPTION|h
|&color(#2020ff){02行目};|&color(#2020ff){check01};|newServerで設定する監視先DNSサーバのFQDN設定。IPアドレス記述も可能|
|&color(#2020ff){03行目};|&color(#2020ff){check02};|newServerで設定する監視先DNSサーバのFQDN設定。IPアドレス記述も可能|
|&color(#2020ff){04行目};|&color(#2020ff){newServer};|プール名(example)にバックエンド(10.0.10.1:53)を、監視先FQDN(check01)で追加&br;監視先から"NOERROR RCODE"以外が返ってきたらエラー(監視失敗)とする|
|&color(#2020ff){05行目};|&color(#2020ff){newServer};|プール名(example)にバックエンド(10.0.10.2:53)を、監視先FQDN(check02)で追加&br;監視先から"NOERROR RCODE"以外が返ってきたらエラー(監視失敗)とする|
|&color(#2020ff){08行目};|&color(#2020ff){addLocal};|dnsdistが待受けるUDP用IPアドレス&br;doTCPを設定すると、同IPアドレスでTCP待受けも有効化出来る|
|&color(#2020ff){11行目};|&color(#2020ff){setACL};|接続を許可するセグメント&br;setACLで複数記述、addACLで既存のACLに追加設定も出来る|
|&color(#2020ff){14行目};|&color(#2020ff){newSuffixMatchNode};|サフィックス名とインスタンスの定義|
|&color(#2020ff){15行目};|&color(#2020ff){newDNSName};|サフィックス名(internet)に、DNSドメイン名(example.com)を追加定義する|
|&color(#2020ff){18行目};|&color(#2020ff){addAction/LogAction};|dnsdistが処理したDNSクエリログ保存先。addActionの中で必ず最初に設定する&br;パラメータを "false/true/false" にすると見やすい形で保存される|
|&color(#2020ff){21行目};|&color(#2020ff){addAction/SuffixMatchNodeRule};|DNSクエリに "example.com(internetサフィックスで定義)" を含む時、&br;バックエンドの "example" プール(2~5行目で定義)に転送|
|&color(#2020ff){22行目};|&color(#2020ff){addAction/QTypeRule};|DNSクエリタイプが "TXT(dnsdist.TXTで定義)" の時、&br;バックエンドの "example" プール(2~5行目で定義)に転送|
|&color(#2020ff){23行目};|&color(#2020ff){addAction/AllRule};|上段の設定(addAction)で処理されなかったDNSクエリに対して、&br;REFUSED(リクエスト拒否)を返答する。設定の最後に記述する事を強く推奨|
#endregion
 
-&size(16){&font(b){重み付け応答};};
#region(&color(#ff0000){設定内容};)
重み付けに応じて応答するレコードを変更する場合、ラウンドロビン設定内のIP指定部分をリストに変更する。
変更箇所はpluginsフィールド内のみで、service_typesは書き換えなくて良い。
下記設定では、SERVER-Aを1、SERVER-Bを3とした場合の重み付け応答となる。
 # vi /usr/lcoal/gdnsd/etc/gdnsd/config
 ---
 plugins      => {
     weighted => {
         tcp_80 => {
             service_types => tcp_80_http,
             up_thresh     => 0.001,
             multi         => false,
             SERVERA       => [ 192.168.0.1, 1],
             SERVERB       => [ 192.168.0.2, 3],
         }
     }
 }
 
重み付け応答にする為、監視モジュールを[multifo]から[weighted]に切り替えている為、
DNSゾーンファイルのDYNAレコード設定も変更する。
 # vi /usr/local/gdnsd/etc/gdnsd/zones/gslb.test.org
 ---
 ;; DNSゾーンに追記
 $TTL    10
 www     10  DYNA   weighted!tcp_80
#endregion
 
-&size(16){&font(b){ping死活監視};};
#region(&color(#ff0000){設定内容};)
gdnsdのヘルスチェックには、ping死活監視モジュールが存在しない。
その為、ping死活で応答レコードを変更する場合、外部コマンドモジュールを利用してpingを直接実行する。
 
外部コマンドに監視対象のIPアドレスを引き渡す場合、特殊変数の&color(#ff0000){"%%ITEM%%"};を指定する。
"%%ITEM%%"変数を指定する事で、configファイルの応答IPアドレスを監視対象としてスクリプトに引き渡す。
外部コマンドモジュールを利用する場合、パラメータ内で利用するコマンドのタイムアウト秒数が、
gdnsdヘルスチェックのタイムアウト秒数以上にならない様に注意する。
 # vi /usr/lcoal/gdnsd/etc/gdnsd/config
 ---
 service_types    => {
     icmp_command => {
         plugin      => extmon,
         cmd         => ["/usr/sbin/fping", "-t 3", "%%ITEM%%"],
         interval    => 10,
         timeout     => 4,
         up_thresh   => 6,
         ok_thresh   => 3,
         down_thresh => 3,
     }
 }
 
 plugins     => {
     multifo => {
         icmp_check => {
             service_types => icmp_command,
             up_thresh     => 0.001,
             SERVERA       => 192.168.0.1,
             SERVERB       => 192.168.0.2,
         }
     }
 }
 
DNSゾーンファイルの内容も設定に応じて書き換える。
外部コマンドを利用しているが、DYNAレコードに影響のあるpluginsは大きく変更していない為、
従来通りの書式に従ってDYNAレコード設定を変更する。
 # vi /usr/local/gdnsd/etc/gdnsd/zones/gslb.test.org
 ---
 ;; DNSゾーンに追記
 $TTL    10
 www     10  DYNA   multifo!icmp_check
#endregion
 
-&size(16){&font(b){NAT配下監視};};
#region(&color(#ff0000){設定内容};)
クラウドではグローバルIPとインスタンス内部アドレスを、NATで紐付けてアドレスを割り当てている場合が多い。
この時、NAT装置がNATループバック(ヘアピンNAT)に対応していない場合、
グローバルIPからインスタンス内部アドレスに変換が出来ず、&color(#ff0000){グローバルIPでヘルスチェックが出来なくなる。};
解決方法は複数存在するが、楽な方法としては外部コマンドヘルスチェックを応用する事で、
インスタンス内部アドレスで監視しつつ、DNSの応答レコードをグローバルIPにする事が出来る。
 
下記は、Web(TCP:80)への死活監視をインスタンス内部アドレス(SERVER-A/B)で行いつつ、
DNSレコードとしてはグローバルIP(NAT)を応答する設定例となる。
 # vi /usr/lcoal/gdnsd/etc/gdnsd/config
 ---
 service_types  => {
     script_mon => {
         plugin      => extmon,
         cmd         => ["/usr/local/bin/script_mon.pl", "%%ITEM%%", "80"],
         interval    => 10,
         timeout     => 4,
         up_thresh   => 6,
         ok_thresh   => 3,
         down_thresh => 3,
     }
 }
 
 plugins     => {
     multifo => {
         tcp_80 => {
             service_types => script_mon,
             up_thresh     => 0.001,
             SERVERA       => 1.1.0.1,
             SERVERB       => 1.1.0.2,
         }
     }
 }
 
DNSゾーンファイルは今までと同じように、plugins/service_typesを設定する。
この時、重み付け応答を行いたい場合、設定に合わせてDYNAレコードを修正する。
 # vi /usr/local/gdnsd/etc/gdnsd/zones/gslb.test.org
 ---
 ;; DNSゾーンに追記
 $TTL    10
 www     10  DYNA   multifo!tcp_80
 
外部コマンドは様々は作成方法があるが、筆者が作成したperlの作例を公開。
応答性重視の監視スクリプトとして利用する為、例外処理は全部省いている。
 # vi /usr/local/bin/script_mon.pl
 ---
 #!/usr/bin/perl
 
 $GIP  = $ARGV[0];
 $PORT = $ARGV[1];
 %LIP;
 $LIP{'1.1.0.1'} = "10.0.0.1";
 $LIP{'1.1.0.2'} = "10.0.0.2";
 
 $STAT = system("/usr/bin/ncat -w 1 $LOCAL{$GLOBAL} ${PORT} < /dev/null > /dev/null 2>&1");
 $STAT = $STAT >> 8;
 
 exit $STAT;
#endregion
 
-&size(16){&font(b){アクティブ・スタンバイ};};
#region(&color(#ff0000){設定内容};)
GSLB配下のコンテンツサーバ間でセッション同期を行っていない構成や、
通信を片寄せする時にコンテンツサーバをActive/Standby動作させる場合がある。
gdnsdにActive/Standbyモジュールは存在しないが、
データセンター・フェールオーバー機能でアクティブ・スタンバイを実現出来る。
 
下記は、SERVER-Aをアクティブ・SERVER-Bをスタンバイとして稼働させつつ、
ヘルスチェックにWeb(TCP:80)への死活監視を行う設定例となる。
 # vi /usr/lcoal/gdnsd/etc/gdnsd/config
 ---
 service_types   => {
     tcp_80_http => {
         plugin      => http_status,
         port        => 80,
         url_path    => /,
         ok_codes    => [ 200, 301 ],
         up_thresh   => 10,
         ok_thresh   => 5,
         down_thresh => 5,
         interval    => 5,
         timeout     => 4,
     }
 }
 
 plugins    => {
     metafo => {
         resources  => {
             tcp_80 => {
                 datacenters => [ active, standby ]
                 dcmap       => {
                     active  => {
                         plugin        => multifo,
                         service_types => tcp_80_http,
                         up_thresh     => 0.001,
                         SERVERA       => 192.168.0.1,
                     }
                     standby => {
                         plugin        => multifo,
                         service_types => tcp_80_http,
                         up_thresh     => 0.001,
                         SERVERB       => 192.168.0.2,
                     }
                 }
             }
         }
     }
 }
 
DNSゾーンファイルは従来通りに、サービスタイプとプラグインを設定する。
今回は、データセンター・フェールオーバーを利用しているのでmetafoプラグインを指定する。
サービスタイプは作成した物を従来通りに設定する。
 # vi /usr/local/gdnsd/etc/gdnsd/zones/gslb.test.org
 ---
 ;; DNSゾーンに追記
 $TTL    10
 www     10  DYNA   metafo!tcp_80
#endregion
 
-&size(16){&font(b){ソーリーサーバ};};
#region(&color(#ff0000){設定内容};)
障害でコンテンツサーバが全台がダウンした時に緊急コンテンツ(ソーリーサーバー)を表示する事で、
メインサーバがダウンしている事を伝える事がある。
このソーリーサーバをgdnsdで実装するには、データセンター・フェールオーバーを応用する。
 
下記は、SERVER-AとSERVER-Bをラウンドロビン稼働させつつ、
ソーリーサーバとして192.168.0.3へ割り振る設定例となる。
ただし、ソーリーサーバへのヘルスチェックを行わない事で、
ソーリーサーバの稼働状況にかかわらず、コンテンツサーバ全ダウン時もアドレスを応答するようにしてある。
 # vi /usr/lcoal/gdnsd/etc/gdnsd/config
 ---
 service_types   => {
     tcp_80_http => {
         plugin      => http_status,
         port        => 80,
         url_path    => /,
         ok_codes    => [ 200, 301 ],
         up_thresh   => 10,
         ok_thresh   => 5,
         down_thresh => 5,
         interval    => 5,
         timeout     => 4,
     }
 }
 
 plugins    => {
     metafo => {
         resources  => {
             tcp_80 => {
                 datacenters => [ active, sorry ]
                 dcmap       => {
                     active  => {
                         plugin        => multifo,
                         service_types => tcp_80_http,
                         up_thresh     => 0.001,
                         SERVERA       => 192.168.0.1,
                         SERVERB       => 192.168.0.2,
                     }
                     sorry => 192.168.0.3,
                 }
             }
         }
     }
 }
 
ソーリーサーバを利用する場合も、DNSゾーンファイルは従来通りの設定を行う。
gdnsdのプラグインはmetafoを利用しているので、metafoを指定する。
 # vi /usr/local/gdnsd/etc/gdnsd/zones/gslb.test.org
 ---
 ;; DNSゾーンに追記
 $TTL    10
 www     10  DYNA   metafo!tcp_80
#endregion