ぶていのログでぶログ

思い出したが吉日

OpenStack ネットワークノードはgc_threshを増やしておいたほうがよい

会社のプライベートクラウドで、SNATルーターが度々不調になるということに出くわした…。 調べていくとネットワークノードで以下のメッセージが出ていた。

neighbour: arp_cache: neighbor table overflow!

このメッセージはARPキャッシュエントリーの数が設定値を超えると発生するらしい。 ARPエントリが追加できないので、通信ができなくなるということらしい。 プライベートクラウドのSNATルーターはHA構成になっているため、通信断になるとフェイルオーバーするのだが、フェイルオーバーしたことを検知することもできないし、即時にARPテーブルの空きができてフェイルバックするために、通信断の状態が長くなるのであった…。

これを解決するには以下のカーネルパラメータを変更すればよい

  • net.ipv4.neigh.default.gc_thresh1
  • net.ipv4.neigh.default.gc_thresh2
  • net.ipv4.neigh.default.gc_thresh3

それぞれのデフォルト値とパラメータの意味は以下を参照。 Man page of ARP


どうしたらneighbor table overflow!が発生するのか?

例の如く id:hiboma がどういう実装になっているのかを調べてくれた。hiboma++

static struct neighbour *neigh_alloc(struct neigh_table *tbl, struct net_device *dev)
{
    struct neighbour *n = NULL;
    unsigned long now = jiffies;
    int entries;

    entries = atomic_inc_return(&tbl->entries) - 1;
    if (entries >= tbl->gc_thresh3 ||
        (entries >= tbl->gc_thresh2 &&
         time_after(now, tbl->last_flush + 5 * HZ))) {
        if (!neigh_forced_gc(tbl) &&
            entries >= tbl->gc_thresh3) {
            net_info_ratelimited("%s: neighbor table overflow!\n",
                         tbl->id);
            NEIGH_CACHE_STAT_INC(tbl, table_fulls);
            goto out_entries;
        }
    }
-- -- snip -- --

上記を見ると gc_thresh3 を超えると発生するようだ。 ARPキャッシュエントリー数は lnstat コマンドで確認できる。 これも id:hiboma に教えてもらった。 hiboma++

$ lnstat -c 1 -k arp_cache:entries
arp_cach|
 entries|
    4162|

このエントリ数を見て gc_treshX を設定するのが良いと思う。 会社のプライベートクラウドでは、インスタンス数600、ポート数1600弱だったが上記の通りそこそこのエントリ数だったので以下のように設定し回避した。

echo 4096 > /proc/sys/net/ipv4/neigh/default/gc_thresh1
echo 8192 > /proc/sys/net/ipv4/neigh/default/gc_thresh2
echo 8192 > /proc/sys/net/ipv4/neigh/default/gc_thresh3

また、エントリ数をMackerelに投稿するやーつを @r_takaishi が作ったのでまたエントリ数が増えてきたら設定を増やすような運用にしたい。


(追記)各パラメータの設定値について、OpenStack-Ansibleでは8GBメモリ以上なら 4096 8192 16384 で設定しているように見受けられた。 搭載メモリが多ければなるべく大きめに設定しておくと良さそうだ。 OpenStack Docs: OpenStack-Ansible openstack_hosts