- 追加された行はこの色です。
- 削除された行はこの色です。
#author("2018-03-18T21:56:56+09:00","default:nowsky","nowsky")
*gdnsd [#m672254c]
オープンソースのグローバルロードバランサー(GSLB)
ソースコード量が少なく、高速動作と脆弱性の発生しにくさが特長となっている。
ただし、ソースコードを減らす為にプログラムのロギング機能が省略されていたり、
細かいヘルスチェックはスクリプトを別途作成する必要がある為、
フル機能を使いこなすには知識・技術が必要なソフトウェアである。
gdnsdは通信事業者レベルでの採用実績がある。
また、ソースコードが少ない割には整理されている為、機能追加も比較的楽に出来る。
#author("2019-01-09T21:53:41+09:00","default:nowsky","nowsky")
*NGINX [#vcddd263]
同時処理速度、メモリの軽さが特徴のWebサーバ。
Webサーバ以外にもリバースプロキシとして動かす事も出来る。
ソフトウェア実装としては珍しい、UDPリバースプロキシにも対応している。
~
*参考サイト [#u52f6883]
-[[gdnsd:+http://gdnsd.org/]]
-[[GitHub gdnsd:+https://github.com/gdnsd]]
-[[gdnsdでかんたんGSLB:+https://qiita.com/jh1vxw/items/7ce5d14e9f964f001257]]
*参考サイト [#o7c2afd5]
-[[nginx news:+http://nginx.org/]]
-[[Nginxをソースコードからインストール:+https://qiita.com/HayneRyo/items/eccc36302623088ad7f3]]
-[[Serving CGI Scripts With Nginx On OpenSUSE:+https://www.howtoforge.com/serving-cgi-scripts-with-nginx-on-opensuse-11.4-p2]]
~
* 構築環境 [#p9f93553]
-[[配布サイト:+https://github.com/gdnsd/gdnsd/releases/]]
-[[公式ドキュメント:+https://github.com/gdnsd/gdnsd/wiki]]
#block
|LEFT:80|LEFT:180|LEFT:180|c
|CENTER:~Parameter|CENTER:~DNS-A|CENTER:~DNS-B|h
|&color(#2020ff){OS};|openSUSE Leap 42.3|openSUSE Leap 42.3|
|&color(#2020ff){GIP};|1.1.0.1|1.1.0.2|
|&color(#2020ff){IP};|10.0.0.1|10.0.0.2|
|&color(#2020ff){A-RR};|ns1.gslb.test.org|ns2.gslb.test.org|
|&color(#2020ff){USER};|>|gdnsd|
|&color(#2020ff){VERSION};|>|v2.4.0|
|&color(#2020ff){PREFIX};|>|/usr/lcoal/gdnsd-2.4.0|
|&color(#2020ff){CONFIG};|>|/usr/lcoal/gdnsd/etc/gdnsd/config|
|&color(#2020ff){ZONE};|>|/usr/lcoal/gdnsd/etc/gdnsd/zones/gslb.test.org|
|LEFT:80|LEFT:180|LEFT:180|c
|CENTER:~Parameter|CENTER:~SERVER-A|CENTER:~SERVER-B|h
|&color(#2020ff){IP};|192.168.0.1|192.168.0.2|
|&color(#2020ff){A-RR};|sv1.gslb.test.org|sv2.gslb.test.org|
#block(next)
#ref(Linux/Source/gdnsd/wiki_gdnsd_01.png,45%,left,nowrap)
#block(end)
~
* インストール [#ab640717]
*インストール [#f720ffa6]
-&size(16){&font(b){1. インストール};};
gdnsdの最新機能を利用する為、今回はソースからビルドする。
ソースビルド時でもバージョン管理が行える様に、
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
# ./configure --prefix=/usr/local/gdnsd-2.4.0
# make
# make install
nginxの全機能を利用するにはプログラムをソースコードからビルドする必要がある。
特に、リバースプロキシなど最新の実装機能を利用する場合には必須となる。
今回は機能を全部有効化してビルドするので、長くなるconfigure指定を別ファイル化しておき、
configureする時にコマンド置換(バッククォート)で読み込む。
# vi configure.option
---
--prefix=/usr/local/nginx-1.13.9
--with-select_module
--with-poll_module
--with-threads
--with-file-aio
--with-http_ssl_module
--with-http_v2_module
--with-http_realip_module
--with-http_addition_module
--with-http_xslt_module
--with-http_geoip_module
--with-http_gunzip_module
--with-http_gzip_static_module
--with-http_auth_request_module
--with-http_secure_link_module
--with-http_degradation_module
--with-http_slice_module
--with-http_stub_status_module
--with-mail
--with-mail_ssl_module
--with-stream
--with-stream_ssl_module
--with-stream_realip_module
--with-stream_geoip_module
--with-stream_ssl_preread_module
--with-cpp_test_module
--with-compat
--with-pcre
--with-pcre-jit
--with-libatomic
# wget http://nginx.org/download/nginx-1.13.9.tar.gz
# tar zxvf nginx-1.13.9.tar.gz
# cd nginx-1.13.9
# ./configure `cat ../configure.option | tr '\r\n' ''`
# make && make install
-&size(16){&font(b){2. 起動準備};};
gdnsdを動かす為の実行ユーザを作成した上で起動スクリプトも準備する。
gdnsdはsystemd起動に最適化されている為、
従来のinitスクリプトでは無くサービスファイルから起動を行う。
# 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
実行ユーザ、systemdスクリプト、ログローテート設定を準備する。
systemdスクリプトにPIDファイルを埋め込んでいる為、
後で作成するコンフィグのPID指定もsystemdに記載した物と合わせる。
# vi /usr/lib/systemd/system/nginx.service
---
[Unit]
Description=gdnsd Authoritative GSLB type DNS Server
After=local-fs.target network.target
Description=NGINX - Web server and Reverse proxy
Documentation=http://nginx.org/en/docs/
After=local-fs.target remote-fs.target network.target nss-lookup.target
[Install]
WantedBy=multi-user.target
[Service]
Type=notify
Type=forking
NotifyAccess=all
ExecStart=/usr/local/gdnsd/sbin/gdnsd -c /etc/gdnsd -f start
ExecStop=/usr/local/gdnsd/sbin/gdnsd -c /etc/gdnsd stop
PIDFile=/var/run/nginx.pid
ExecStartPre=/usr/local/nginx/sbin/nginx -t -c /etc/nginx/nginx.conf
ExecStart=/usr/local/nginx/sbin/nginx -c /etc/nginx/nginx.conf
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s QUIT $MAINPID
## Security Setting
MountFlags=slave
DevicePolicy=closed
PrivateDevices=true
PrivateTmp=true
ProtectSystem=full
ProtectHome=true
-&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のみ記載すればプログラムを起動出来る。
なお、コンフィグのコメント接頭文字は『#(シャープ)』となる。
# vi /usr/local/gdnsd/etc/gdnsd/config
# vi /etc/logrotate.d/nginx
---
options => {
username => gdnsd,
chaos_response => "GSLB",
listen => 0.0.0.0:53,
http_listen => 0.0.0.0:3506,
log_stats => 3600,
# tcp_threads => 2,
# udp_threads => 2,
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,
/var/log/nginx/*.log {
weekly
compress
rotate 4
missingok
ifempty
sharedscripts
postrotate
systemctl restart nginx > /dev/null 2>/dev/null || true
endscript
}
#region(&color(#ff0000){設定の解説};)
全オプションはgdnsdの[[公式ドキュメント:+https://github.com/gdnsd/gdnsd/wiki/GdnsdConfig]]を確認する。
最低限の動作を行う場合、下記オプションを参考に設定を行う。
|LEFT:200|LEFT:600|c
|CENTER:~OPTIONS HASH|CENTER:~DESCRIPTION|h
|&color(#2020ff){username};|gdnsdを実行するユーザ名&br;グループ名はユーザに紐付いている物が自動適用される|
|&color(#2020ff){chaos_response};|CHクラスの応答内容&br;権威DNSのバージョン確認クエリに、設定した文字列を返す|
|&color(#2020ff){listen};|gdnsdの待ち受けIPアドレス・ポート番号&br;複数IPを待ち受けする場合はリスト構造にする|
|&color(#2020ff){http_listen};|gdnsdヘルスチェック画面の待ち受けIPアドレス・ポート番号&br;複数IPを待ち受けする場合はリスト構造にする|
|&color(#2020ff){log_stats};|DNSクエリの統計ログ出力間隔&br;値を"0"にすると、統計ログ出力が無効化される|
|&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;応答速度とクエリサイズ最小化を優先する時は無効化(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;ファイル変更による意図しない適用が発生しやすいので無効(false)を推奨|
|&color(#2020ff){state_dir};|gdnsdのデーモン起動情報を外部プログラムと連携する際に使用&br;ディレクトリが存在しない時は自動生成される|
|&color(#2020ff){run_dir};|gdnsdのPIDファイル保存フォルダ&br;systemdからプロセス操作を行う際に必須となる|
|&color(#2020ff){plugin_search_path};|ヘルスチェックモジュールの保存先ディレクトリ&br;基本的にPREFIX配下となる&color(#ff0000){"${PREFIX}/lib64/gdnsd"};を設定する|
#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
# ln -s /usr/local/nginx-1.13.9 /usr/local/nginx
# ln -s /usr/local/nginx/conf /etc/nginx
# rm /etc/nginx/koi-utf /etc/nginx/koi-win /etc/nginx/win-utf
# mkdir /var/log/nginx
# groupadd nginx
# useradd -g nginx -s /sbin/nologin -d /var/nginx nginx
# systemctl unmask nginx
# systemctl enable nginx
-&size(16){&font(b){3. 基礎設定};};
nginxは利用する機能に応じてコンフィグの内容が大きく変化する。
下記では、nginxの実行ユーザなど基本的な部分のみ記載する。
# vi /etc/nginx/nginx.conf
---
$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
)
user nginx;
pid /var/run/nginx.pid;
error_log /var/log/nginx/error.log;
;; 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
worker_processes auto;
worker_rlimit_nofile 4096;
;; 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
events {
worker_connections 1024;
accept_mutex_delay 50ms;
multi_accept on;
use epoll;
}
~
* ヘルスチェック [#r3014139]
GSLBは下位サーバに対してヘルスチェックを行い、ステータスに応じた可変レコード応答が特徴となる。
負荷分散(ラウンドロビン)、冗長化(アクティブ・スタンバイ)など様々な構成を取る事が出来る。
gdnsdにもヘルスチェックが搭載されており、基本的なGSLBとして機能するようになっている。
また、標準のヘルスチェックで機能不足の場合、ヘルスチェックで外部コマンドを実行する事で、
環境に応じた機能拡張を行う事も出来る。
*コンフィグ [#l50c23aa]
nginxは通常のWebサーバ動作や、リバースプロキシ動作など様々な用途に利用出来る。
用途に応じて必要な設定とディレクティブ指定が変わる為、使う機能に応じて内容を変更する。
同じサーバで違う処理を実装する場合、 "include" を使って設定を外出しすると整理しやすくなる。
gdnsdのヘルスチェックを利用する時は、gdnsdのconfigファイルにヘルスチェック定義を設定した後、
DNSゾーンファイルで専用の可変レコードを設定する事により利用可能となる。
可変レコードは&color(#ff0000){Aレコードを定義するDYNAレコード};と、&color(#ff0000){CNAMEを定義するDYNCレコード};の2種類が存在する。
ただし、利用出来る可変レコードはプラグイン毎に制限されている為、詳細は公式ドキュメントを確認する。
----
-&size(16){&font(b){UDPリバースプロキシ};};
UDPリバースプロキシのコンフィグは、nginxのTCPリバースプロキシ設定とほぼ同じになる。
ただし、nginxのフロントエンドとなるlistenの箇所にudpを指定する点に注意する。
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,
下記はフロントエンドを「10.0.0.1」で待ち受け、
バックエンドの2IPアドレス「192.168.0.1」「192.168.0.2」へUDP53で振り分ける設定となる。
stream {
access_log /var/log/nginx/access.log basic;
error_log /var/log/nginx/error.log info;
upstream DNS {
hash $remote_addr;
server 192.168.0.1:53;
server 192.168.0.2:53;
}
}
plugins => {
multifo => {
tcp_80 => {
service_types => tcp_80_http,
up_thresh => 0.001,
SERVERA => 192.168.0.1,
SERVERB => 192.168.0.2,
}
server {
listen 10.0.0.1 udp;
proxy_pass DNS;
proxy_timeout 1s;
proxy_responses 1;
}
}
DNSゾーンファイルには、Aレコード・CNAMEの応答内容に従って可変レコードを記載する。
例えば、Aレコードとして可変応答させる場合は下記の様になる。
# vi /usr/local/gdnsd/etc/gdnsd/zones/gslb.test.org
---
;; DNSゾーンに追記
$TTL 10
www 10 DYNA multifo!tcp_80
#endregion
----
-&size(16){&font(b){HTTP Webサーバ};};
Apacheと違う所として「.htaccess」ファイルが動かない事と、
PHPを動かす時にはPHP-FPMを起動させて代理処理する点に注意する
-&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,
}
}
下記はDocumentRootを "/var/nginx/html" とした上で、
nginxをWebサーバとして稼働させる設定例となる。
http {
default_type application/octet-stream;
include /etc/nginx/mime.types;
access_log /var/log/nginx/access.log combined;
plugins => {
multifo => {
icmp_check => {
service_types => icmp_command,
up_thresh => 0.001,
SERVERA => 192.168.0.1,
SERVERB => 192.168.0.2,
# Server Setting
sendfile on;
tcp_nopush on;
autoindex off;
etag off;
server_tokens off;
keepalive_timeout 5;
# Contents Compress
gzip on;
gzip_http_version 1.0;
gzip_disable msie6;
gzip_min_length 1024;
gzip_types text/plain
text/xml
text/css
application/xml
application/xhtml+xml
application/rss+xml
application/atom_xml
application/javascript
application/x-javascript
application/x-httpd-php;
# HTTP Server
server {
listen 0.0.0.0:80 default_server;
server_name _;
location / {
root /var/nginx/html;
index index.html index.htm;
}
add_header X-Frame-Options SAMEORIGIN;
add_header X-XSS-Protection "1; mode=block";
add_header X-Content-Type-Options nosniff;
}
}
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){CGI実行環境};};
nginxの処理体系はイベント型の為、CGIを実行するには別途プログラムを噛ませる必要がある。
今回はCGI実行環境としてFastCGIを利用する。
-&size(16){&font(b){NAT配下監視};};
#region(&color(#ff0000){設定内容};)
クラウドではグローバルIPとインスタンス内部アドレスを、NATで紐付けてアドレスを割り当てている場合が多い。
この時、NAT装置がNATループバック(ヘアピンNAT)に対応していない場合、
グローバルIPからインスタンス内部アドレスに変換が出来ず、&color(#ff0000){グローバルIPでヘルスチェックが出来なくなる。};
解決方法は複数存在するが、楽な方法としては外部コマンドヘルスチェックを応用する事で、
インスタンス内部アドレスで監視しつつ、DNSの応答レコードをグローバルIPにする事が出来る。
下記はopenSUSE上でのCGI実行環境の構築例となる。
# zypper install spawn-fcgi FastCGI FastCGI-devel
# ln -s /usr/include/fastcgi/fastcgi.h /usr/local/include/
# ln -s /usr/include/fastcgi/fcgi_config.h /usr/local/include/
# ln -s /usr/include/fastcgi/fcgi_stdio.h /usr/local/include/
# ln -s /usr/include/fastcgi/fcgiapp.h /usr/local/include/
# ln -s /usr/include/fastcgi/fcgimisc.h /usr/local/include/
# ln -s /usr/include/fastcgi/fcgio.h /usr/local/include/
# ln -s /usr/include/fastcgi/fcgios.h /usr/local/include/
下記は、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,
}
}
}
# cd /usr/local/src
# git clone https://github.com/gnosek/fcgiwrap `date "+%Y%m%d"`
# ln -s `date "+%Y%m%d"` fcgiwrap
# cd fcgiwrap
# autoreconf -i
# ./configure
# make
# make install
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
# vi /etc/init.d/spawn-fcgi
# chmod 755 /etc/init.d/spawn-fcgi
# chown root.root /etc/init.d/spawn-fcgi
# chkconfig --add spawn-fcgi
# systemctl enable spawn-fcgi
# systemctl start spawn-fcgi
#region(/etc/init.d/spawn-fcgi)
#!/bin/sh
#
# spawn-fcgi FastCGI rapper daemon
#
# chkconfig: 35 95 10
# description: FastCGI and SpawnFCGI rapper daemon
#
### BEGIN INIT INFO
# Provides: spawn-fcgi
# Description: Start the spawn-fcgi
# Required-Start: $local_fs $remote_fs $network
# Required-Stop: $local_fs $remote_fs $network
# Default-Start: 3 5
# Default-Stop: 0 1 6
### END INIT INFO
$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";
. /etc/rc.status
rc_reset
$STAT = system("/usr/bin/nc -w 1 $LIP{$GIP} -z ${PORT}");
$STAT = $STAT >> 8;
BIN="/usr/local/sbin/fcgiwrap"
PID="/var/run/spawn-fcgi.pid"
SOCK="/var/run/spawn-fcgi.socket"
OPT="-M 0660"
exit $STAT;
NAME=spawn-fcgi
USER=nginx
GROUP=nginx
case "$1" in
start)
echo -n "Starting ${NAME}"
/usr/bin/spawn-fcgi -u ${USER} -g ${GROUP} -s ${SOCK} -S ${OPT} -F 1 -P ${PID} -- ${BIN}
rc_status -v
;;
stop)
echo -n "Shutdown ${NAME}"
checkproc -p ${PID} ${BIN} || echo -n "- Warning: ${NAME} not running!"
killproc -p ${PID} -TERM ${BIN}
if [ -S ${SOCK} ]; then
rm -f ${SOCK}
fi
rc_status -v
;;
restart)
$0 stop && sleep 3 && $0 start
rc_status
;;
*)
echo "Usage: spawn-fcgi {start|stop|restart}"
exit 1
;;
esac
rc_exit
#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
# vi /etc/nginx/nginx.conf
---
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,
SERVERA => 192.168.0.2,
}
}
}
http {
server {
location ~ [^/]\.(cgi|pl)($|\?|\/) {
root /var/nginx/html;
fastcgi_pass unix:/var/run/spawn-fcgi.socket;
fastcgi_index index.cgi,index.pl;
include /etc/nginx/fastcgi_params;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
}
DNSゾーンファイルは従来通りに、サービスタイプとプラグインを設定する。
今回は、データセンター・フェールオーバーを利用しているのでmetafoプラグインを指定する。
サービスタイプは作成した物を従来通りに設定する。
# vi /usr/local/gdnsd/etc/gdnsd/zones/gslb.test.org
FastCGIビルド時に次の様なエラーが出た場合、
fcgiwrap.cに"FALLTHROUGH"を追記する事でエラーを抑制する
cc -std=gnu99 -Wall -Wextra -Werror -pedantic -O2 -g3 fcgiwrap.c -lfcgi -o fcgiwrap
fcgiwrap.c: In function 'handle_fcgi_request':
fcgiwrap.c:581:4: error: this statement may fall through [-Werror=implicit-fallthrough=]
cgi_error("502 Bad Gateway", "Cannot execute script", filename);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
fcgiwrap.c:583:3: note: here
default: /* parent */
^~~~~~~
cc1: all warnings being treated as errors
make: *** [<builtin>: fcgiwrap] Error 1
#region(fcgiwrap.c)
ソースコード差分
$ diff fcgiwrap.c fcgiwrap.c.org
---
;; DNSゾーンに追記
$TTL 10
www 10 DYNA metafo!tcp_80
582d581
< /* FALLTHROUGH */
書き換え後のソース
execl(filename, filename, (void *)NULL);
cgi_error("502 Bad Gateway", "Cannot execute script", filename);
/* FALLTHROUGH */
#endregion
-&size(16){&font(b){ソーリーサーバ};};
#region(&color(#ff0000){設定内容};)
障害でコンテンツサーバが全台がダウンした時に緊急コンテンツ(ソーリーサーバー)を表示する事で、
メインサーバがダウンしている事を伝える事がある。
このソーリーサーバをgdnsdで実装するには、データセンター・フェールオーバーを応用する。
----
-&size(16){&font(b){PHP実行環境};};
CGIと同様に、nginx上でPHPを実行する場合も別プログラムに投げる必要がある。
PHPを実行する手段は多種存在するが、今回はphp-fpmを利用手法をメモしておく。
# zypper install php7 php7-devel php7-fpm
# cp /etc/php7/fpm/php-fpm.conf.default /etc/php7/fpm/php-fpm.conf
# cp /etc/php7/fpm/php-fpm.d/www.conf.default /etc/php7/fpm/php-fpm.d/www.conf
# vi /etc/php7/fpm/php-fpm.d/www.conf
---
[www]
user = nginx
group = nginx
listen = /var/run/php-fpm.socket
listen.owner = nginx
listen.group = nginx
listen.mode = 0660
listen.allowed_clients = 127.0.0.1
下記は、SERVER-AとSERVER-Bをラウンドロビン稼働させつつ、
ソーリーサーバとして192.168.0.3へ割り振る設定例となる。
ただし、ソーリーサーバへのヘルスチェックを行わない事で、
ソーリーサーバの稼働状況にかかわらず、コンテンツサーバ全ダウン時もアドレスを応答するようにしてある。
# vi /usr/lcoal/gdnsd/etc/gdnsd/config
# /etc/init.d/php-fpm start
# vi /etc/nginx/nginx.conf
---
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,
}
}
http {
server {
location ~ \.(php)$ {
root /var/nginx/html;
fastcgi_pass unix:/var/run/php-fpm.socket;
fastcgi_index index.php;
include /etc/nginx/fastcgi_params;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
}
ソーリーサーバを利用する場合も、DNSゾーンファイルは従来通りの設定を行う。
gdnsdのプラグインはmetafoを利用しているので、metafoを指定する。
# vi /usr/local/gdnsd/etc/gdnsd/zones/gslb.test.org
---
;; DNSゾーンに追記
$TTL 10
www 10 DYNA metafo!tcp_80
#endregion