⏱この記事を読むのに必要な時間は約 5 分です。
のっけから不穏な画像ですみません。
問題発生
我が家ではIntel NUC(NUC6i7KYK、通称Skull Canyon(初代))でNutanix Community Edition(CE)のクラスターを組んでいますが、ある日、1つのノードのCVMが疎通不能になっているのを発見しました。
排熱があまり得意ではない筐体なので、熱暴走でもしてダウンしたか?と思って本体を見に行ってみると、コンソールにこのようなエラーメッセージが繰り返し、びっしりと表示されていました。
e1000e <中略> eth0: Detected Hardware Unit Hang:
e1000eはIntel製有線LANドライバ。eth0もNICデバイス名。
要するに、NICが繰り返しハングして通信が途切れている…?
疎通不能となったノード以外のコンソールにも同様のエラーメッセージが表示されていたので、ハングしたあと復帰に成功する場合もあるようですが、復帰できなかったノードが通信不能となっていたようです。再起動すれば回復しますが、再び発生する可能性があるため、恒久的な対処方法を探してみました。
原因
何はともあれ、まずはエラーメッセージでググってみるのが第1歩、ということで試してみたら即回答にたどり着きました。Nutanix AHVはLinux KVMベースですが、同様の事象は他のLinuxディストリビューションでも発生しているようです。
あれこれ記事を読んでみると、コンソールに出力されていたエラーメッセージは、ネットワーク負荷によりNICが応答できない場合などに出力される内容で、特にe1000eのTSO(TCP Segmentation Offload)という機能が有効になっていると発生しやすいというIssueが報告されていました。
TSOはTCPにおけるデータの分割処理をNIC側にオフロードすることでCPU負荷を抑えるための機能だそうですが、そのせいで通信が不安定になってしまっては本末転倒であるため、今回は無効化することにしました。
対処方法と結果
AHVにログインし、ethtoolコマンドを使用します。まずは現在の設定を確認。小文字のkオプションを使います。
[root@NTNX-XXXXXXXX-A ~]# ethtool -k eth0 | grep tcp-segmentation-offload
tcp-segmentation-offload: on
デフォルトはオンでした。次に、この設定をオフにします。 大文字のKオプションを使います。
[root@NTNX-XXXXXXXX-A ~]# ethtool -K eth0 tso off
コンソールには何も出力されませんが、設定が反映されたか確認します。再び小文字のkオプションを使います。
[root@NTNX-XXXXXXXX-A ~]# ethtool -k eth0 | grep tcp-segmentation-offload
tcp-segmentation-offload: off
設定が反映されていることが確認できました。これ以降、数週間稼働させていますが、同じエラーは発生していないので対処としては正解だったようです。
設定の永続化 (2021/3/27追記)
ethtoolコマンドは再起動すると設定が消えてしまいますね!
設定を永続化するには設定ファイルの編集が必要です。
AHVにログインし、NICの設定ファイルの末尾に1行追記します。
例:eth0の場合
[root@NTNX-XXXXXXXX-A ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0
# Auto generated by Phoenix
DEVICE=eth0
TYPE=Ethernet
NM_CONTROLLED=no
NOZEROCONF=yes
ONBOOT=yes
BOOTPROTO=none
HWADDR=XX:XX:XX:XX:XX:XX
ETHTOOL_OPTS="-K ${DEVICE} tso off"
ワンライナーなら↓のような感じに。
[root@NTNX-XXXXXXXX-A ~] # echo 'ETHTOOL_OPTS="-K ${DEVICE} tso off"' >> /etc/sysconfig/network-scripts/ifcfg-eth0
設定ファイルに書いた内容は、networkサービス再起動で反映されます。
念のためethtoolコマンドで設定が反映されたかどうかも確認しましょう。
[root@NTNX-XXXXXXXX-A ~]# systemctl restart network
[root@NTNX-XXXXXXXX-A ~]# ethtool -k eth0 | grep tcp-segmentation-offload
tcp-segmentation-offload: off
以上です。