web-dev-qa-db-ja.com

BINDICMPポート到達不能応答

ロードバランサーの背後で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受信エラーの問題に関連する発生を見つけました:

UDP In traffic

UDP Errors

カーネルメモリの値を次のように増やしました。

# 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メトリックとの相関関係が見つかりました。

TCP4ConnFailTCP4SendErr

増加はUDPInErrorsと同じスケールではありませんが、この効果は他の時間には存在しないため、それと強く相関しています。

編集6:プロットが厚くなる... Syslogが要因のようです

影響を受けるDNSサーバーは、クエリログをsyslogのlocal0機能に記録するように構成されており、syslogはそれらをUDP経由でリモートサーバーに転送します。これは過去にパフォーマンスの問題の原因でした。実際、そのため、最もビジーなDNSサーバーでは有効にしていません。

クエリログを無効にしようとしましたが、udpInErrorsの問題が消えたようだったので、実験を設定しました。同じロードバランサーの背後に2つのサーバーがあり、クエリログをコントロールとしてアクティブにしてserverAを維持し、serverBでクエリログ(したがってsyslogの転送)を無効にしました。問題の発生が停止しました両方のサーバーでまったく同時に。

次に、serverBでクエリログを再度有効にすると、問題が再び発生しました両方のサーバーで

これは、ワークロードが軽い場合と最も忙しい時間の2回に分けて試行されましたが、忙しい時間にのみ現れたため、負荷に部分的に関連しているようです。

以下のグラフは、ネットワークトラフィックとUDP受信エラーの関係を示しています。

ServerBserverB eth0 outserverB udpInErrors

ServerAserverA eth0 outserverB udpInErrors

同じ増加効果は、編集5で言及されているTCPインジケーターにも見られます。

したがって、根本的な原因はネットワークに関連しているようです。ネットワークは、示されているすべての症状をカスケードして作成します。トリッキーな部分は、これらのサーバー(実際には仮想マシン)が別々のインフラストラクチャ(異なるラック、場合によっては部屋)で実行されるため、サーバー間で影響が伝播しないようにする必要があることです。

クエリログ自体に関連しているようには見えません。そうでない場合、効果はサーバー間で伝播されません。

私が思いついたのは、受信側のsyslogサーバーがこれらのサーバーに戻るルーティングを持っていないため、応答パケットがない場合(存在する場合)、syslogはベストエフォートの「ファイアアンドフォーゲット」方式で動作することです。 。これが原因でしょうか?

3
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に増加します。

2
Andrew B