ロードバランサーの背後でBIND9.8.2(RHEL6)を実行しているDNSリゾルバーでランダムな問題が発生しています。
ロードバランサーは、DNSクエリを使用してサーバーをアクティブにプローブし、サーバーが稼働しているかどうかを確認します。サーバーは、ポート53の「接続拒否」(ICMP)を取得することがあります。これにより、サーバーはロードバランサーサーバープールでサービスを利用できなくなります。
これは、一度に数分間断続的に発生し(LBは10秒ごとにプローブし、通常は1つまたは2つの失敗が発生し、その後成功します)、その後停止します。ピーク負荷時に発生しますが、トラフィックが最低でも。
問題が発生すると、BINDが稼働していて、「接続が拒否されました」というメッセージが混乱します。ポート53にリスニングサービスがないサーバーからはそうではないことが予想されます。プローブレコードのDNS解決が失敗した場合でも、答えはNXDOMAINまたはSERVFAILであり、フラットアウトUDP拒否ではありません。
クエリログには失敗したプローブは表示されません。つまり、UDPパケットは、処理のためにBINDに配信される前に拒否されます。
私の推測では、これはある種のリソースの枯渇が原因であると推測されますが、正確に何を理解することはできません。開いているファイル記述子、net.netfilter.nf_conntrack_count
、CPU、メモリ、recursive-clients
などを監視しており、問題が発生したときにこれらのインジケータのいずれも制限に近づいていません。
問題が発生した時点では、どのログファイルにも関連するエラーメッセージはありません。
だから、私の質問:どのネットワークメトリック/パラメータを調べる必要がありますか?
構成
/ etc/sysconfig/named
OPTIONS="-4 -n10 -S 8096 "
named.conf
options {
directory "/var/named";
pid-file "/var/run/named/named.pid";
statistics-file "/var/named/named.stats";
dump-file "/var/named/named_dump.db";
zone-statistics yes;
version "Not disclosed";
listen-on-v6 { any; };
allow-query { clients; privatenets; };
recursion yes; // default
allow-recursion { clients; privatenets; };
allow-query-cache { clients; privatenets; };
recursive-clients 10000;
resolver-query-timeout 5;
dnssec-validation no;
//querylog no;
allow-transfer { xfer; };
transfer-format many-answers;
max-transfer-time-in 10;
notify yes; // default
blackhole { bogusnets; };
// avoid reserved ports
avoid-v4-udp-ports { 1935; 2605; 4321; 6514; range 8610 8614; };
avoid-v6-udp-ports { 1935; 2605; 4321; 6514; range 8610 8614; };
max-cache-ttl 10800; // 3h
response-policy {
zone "rpz";
zone "rpz2";
zone "static";
};
rate-limit {
window 2; // seconds rolling window
ipv4-prefix-length 32;
nxdomains-per-second 5;
nodata-per-second 3;
errors-per-second 3;
};
};
編集:UDP受信エラー
$ netstat -su
IcmpMsg:
InType3: 1031554
InType8: 115696
InType11: 178078
OutType0: 115696
OutType3: 502911
OutType11: 3
Udp:
27777696664 packets received
498707 packets to unknown port received.
262343581 packet receive errors
53292481120 packets sent
RcvbufErrors: 273483
SndbufErrors: 3266
UdpLite:
IpExt:
InMcastPkts: 6
InOctets: 2371795573882
OutOctets: 13360262499718
InMcastOctets: 216
編集2:ネットワークメモリのサイズ設定
$ cat /proc/sys/net/core/rmem_max
67108864
$ cat /proc/sys/net/ipv4/udp_mem
752928 1003904 1505856
編集3:UdpInErrorsに問題はありません
UDPパケット受信エラーの対応する増加がないプローブ障害イベントがあったため、原因として除外されているようです。
編集4:ここで2つの問題が発生している可能性があります。失敗のインスタンスには、対応するUdpInErrorsが増加するものと、増加しないものがあります
UDP受信エラーの問題に関連する発生を見つけました:
カーネルメモリの値を次のように増やしました。
# cat /proc/sys/net/core/wmem_max
67108864
# cat /proc/sys/net/core/rmem_max
67108864
# cat /proc/sys/net/ipv4/udp_rmem_min
8192
# cat /proc/sys/net/ipv4/udp_wmem_min
8192
負荷に関連しているようには見えません。同じ、さらに大きなワークロードを持つ同様のサーバーは問題を示しませんが、同時に、同じロードバランサーの背後にある他のサーバーは、その期間中にまったく同じ動作を示しました。
編集5:TCP BINDの統計チャネルデータに問題があるという証拠が見つかりました
高UDPパケット受信エラーとBINDの statistics-channels データからのTCP4ConnFail
およびTCP4SendErr
メトリックとの相関関係が見つかりました。
増加はUDPInErrorsと同じスケールではありませんが、この効果は他の時間には存在しないため、それと強く相関しています。
編集6:プロットが厚くなる... Syslogが要因のようです
影響を受けるDNSサーバーは、クエリログをsyslogのlocal0
機能に記録するように構成されており、syslogはそれらをUDP経由でリモートサーバーに転送します。これは過去にパフォーマンスの問題の原因でした。実際、そのため、最もビジーなDNSサーバーでは有効にしていません。
クエリログを無効にしようとしましたが、udpInErrors
の問題が消えたようだったので、実験を設定しました。同じロードバランサーの背後に2つのサーバーがあり、クエリログをコントロールとしてアクティブにしてserverAを維持し、serverBでクエリログ(したがってsyslogの転送)を無効にしました。問題の発生が停止しました両方のサーバーでまったく同時に。
次に、serverBでクエリログを再度有効にすると、問題が再び発生しました両方のサーバーで!
これは、ワークロードが軽い場合と最も忙しい時間の2回に分けて試行されましたが、忙しい時間にのみ現れたため、負荷に部分的に関連しているようです。
以下のグラフは、ネットワークトラフィックとUDP受信エラーの関係を示しています。
同じ増加効果は、編集5で言及されているTCPインジケーターにも見られます。
したがって、根本的な原因はネットワークに関連しているようです。ネットワークは、示されているすべての症状をカスケードして作成します。トリッキーな部分は、これらのサーバー(実際には仮想マシン)が別々のインフラストラクチャ(異なるラック、場合によっては部屋)で実行されるため、サーバー間で影響が伝播しないようにする必要があることです。
クエリログ自体に関連しているようには見えません。そうでない場合、効果はサーバー間で伝播されません。
私が思いついたのは、受信側のsyslogサーバーがこれらのサーバーに戻るルーティングを持っていないため、応答パケットがない場合(存在する場合)、syslogはベストエフォートの「ファイアアンドフォーゲット」方式で動作することです。 。これが原因でしょうか?
Udp:
27777696664 packets received
...
262343581 packet receive errors
UDP受信エラー1回ごとに受信される105.88データグラムは、DNSパケット損失の比率が非常に高く、ソフトウェアにボトルネックがあることを示しています。カーネルがパケットをハンドオフしようとしたときにUDPソケットに関連付けられた受信キューがいっぱいになると、パケットは失われ、このカウンターが増加します。これは、このサーバーだけで最後に再起動してから、この現象によって2億パケット以上が失われたことを意味します。
受信キューがいっぱいになると、ソフトウェアがカーネルからパケットを十分な速度で削除しておらず、最終的にバッファのサイズを超えるバックログが作成されます。次のステップは、whyキューが非常に高く実行されていることを確認することです。 example として、ユーザーの1人が、大量のディスクログが原因でシステムがiowaitで飽和していることを発見しました。すべてのSNMPパフォーマンスメトリックを確認し、相関関係を探すことを提案する以外に、根本原因を特定するための包括的なガイドを提供することはできません。相関関係が見つからない場合は、ハードウェアとソフトウェアスタックの全容量で実行している可能性があり、サーバーを追加することで問題を解決できます。
ちなみに、受信キューのサイズを増やすことは可能ですが、これはバーストトラフィックを処理するための容量として最もよく見られます。バーストトラフィックis notキューのスピルが発生している理由の場合、キューサイズが大きいと、受け入れるトラフィックの処理時間が長くなりますdoこれは、おそらく望ましくありません。 。 BINDは、最大32Kの受信キューの深さを使用しますが、/proc/sys/net/rmem_max
で指定された値に制限されます。この数は、BINDを -with-tuning = large option で再コンパイルすることでさらに増やすことができます。これにより、潜在的な最大値が32Kから16Mに増加します。