U.log

CML2でHSRPの切り替えと切り戻しを検証した記録

前の記事では、CML2上にVLANとHSRPを使った冗長デフォルトゲートウェイを構築し、L2の状態と通常時の疎通を確認しました。

この記事では、その環境を使って確認したHSRPの役割と通信経路、Router1の障害時と復旧時の挙動をまとめておきます。

検証の前提と結果の概要

今回確認した環境の前提と、フェイルオーバー検証の結果を整理しておきます。

前提となる通常時の状態

  • HSRPの役割: VLAN 10はRouter1、VLAN 20はRouter2がActive
  • 通信経路: 行きと帰りで異なるルーターを通る非対称経路

障害・復旧時の検証結果

確認内容結果
Router1の障害時Router2が両VLANのActiveへ切り替わった
Router1の復旧時preemptにより障害前の役割へ戻った
連続ping障害時・復旧時ともにパケットロスは観測されなかった

連続pingは約1秒間隔のため、この結果だけで短い瞬断もなかったとは断定できません。疎通結果とあわせて、HSRPの状態とログも確認しました。

通常時の役割と通信経路の確認

VLAN 10ではRouter1、VLAN 20ではRouter2がActiveになっているかを確認しました。あわせて、VLAN間通信が実際にどちらのルーターを通るかも確認しています。

まず、Router1でHSRPの役割を確認しました。 Et0/0.10のStateActive、Et0/0.20のStateStandbyになっています。この表示から、VLAN 10ではRouter1、VLAN 20ではRouter2がActiveとして動作していることが分かります。また、Pの表示から、両グループにpreemptが設定されていることも確認できました。

Router1#show standby brief

Interface  Grp  Pri  P  State    Active       Standby      Virtual IP
---------  ---  ---  -  -------  -----------  -----------  -----------
Et0/0.10   10   110  P  Active   local        10.10.10.3   10.10.10.1
Et0/0.20   20   100  P  Standby  10.10.20.3   local        10.10.20.1

ActiveまたはStandbyの欄にあるlocalは、コマンドを実行したRouter1自身を表しています。Et0/0.10ではActivelocal、Et0/0.20ではStandbylocalなので、設定した通りVLANごとにActiveの役割が分かれていることを確認できました。

次に、通信経路を確かめるため、Ubuntu0とUbuntu1から互いのIPアドレスへtracerouteを実行しました。 Ubuntu0からVLAN 20側のPCへtracerouteを実行したところ、1ホップ目に10.10.10.2と表示されました。このアドレスはRouter1のVLAN 10側の実IPなので、往路がRouter1を経由していることが分かります。

cisco@ubuntu0:~$ traceroute 10.10.20.11
traceroute to 10.10.20.11 (10.10.20.11), 30 hops max, 60 byte packets
 1  10.10.10.2  0.945 ms  1.534 ms  1.525 ms
 2  10.10.20.11  2.127 ms  2.118 ms  2.208 ms

逆方向にUbuntu1からUbuntu0へtracerouteを実行すると、1ホップ目に10.10.20.3と表示されました。このアドレスはRouter2のVLAN 20側の実IPなので、復路がRouter2を経由していることが分かります。

cisco@ubuntu1:~$ traceroute 10.10.10.11
traceroute to 10.10.10.11 (10.10.10.11), 30 hops max, 60 byte packets
 1  10.10.20.3  1.206 ms  1.158 ms  1.146 ms
 2  10.10.10.11  1.629 ms  1.667 ms  1.826 ms

今回の検証で得られた学び

Ubuntu0のデフォルトゲートウェイにはHSRP仮想IPの10.10.10.1を設定していますが、tracerouteでは実際に転送を行ったRouter1の実IP(10.10.10.2)が表示されました。ルーター自身が応答を返す際、仮想IPではなく実際のインターフェースIPが使われる仕様になっていると分かりました。

tracerouteで実IPが表示される詳しい仕組み

tracerouteは、TTL(生存期間)を少しずつ増やしながらパケットを送信し、途中でパケットを破棄したルーターが送り返してくる「ICMP Time Exceeded」メッセージから経路を割り出します。このエラーメッセージの送信元IPアドレスには、HSRPの仮想IPではなく、ルーターが持つ実際のインターフェースIPアドレスが使用される仕様であるため、このような見え方になります。

また、両方向の結果を比べることで、VLAN 10からVLAN 20への通信はRouter1、逆方向はRouter2を通る「非対称ルーティング」となっていることが確認できます。今回の環境では通信できましたが、経路上にステートフルファイアウォールなどがある場合、行きと帰りで通る機器が違うとパケットが破棄されてしまう可能性があるため注意が必要だと学びました。

非対称ルーティングとファイアウォールの関係

ステートフルファイアウォールは、通信の「行き」と「帰り」のフローを管理して許可する仕組みを持っています。行きと帰りで通る機器が違うと、セッション状態を正しく追跡できず、不正な通信と見なされてパケットが破棄されてしまいます。実際の設計では、こうした非対称ルーティングが発生しないように設計するか、発生しても問題ない構成にする必要があります。

障害時の切り替え

Ubuntu0からUbuntu1へ連続pingを実行した状態で、VLAN 10のActiveであるRouter1のEthernet0/0を意図的に停止し、障害時の挙動を確認しました。

cisco@ubuntu0:~$ ping 10.10.20.11

Router1(config)#interface Ethernet0/0
Router1(config-if)#shutdown

Ubuntu0側のpingを確認すると、Router1のインターフェースを停止する前から停止後まで、28パケットすべてで応答がありました。

cisco@ubuntu0:~$ ping 10.10.20.11
28 packets transmitted, 28 received, 0% packet loss

続いて、ルーター側のHSRPの状態とログを確認します。 Router1のログには、グループ10のActive -> Initとグループ20のStandby -> Initが記録されました。この表示から、Ethernet0/0の停止によってRouter1が両グループのHSRP動作から外れたことが分かります。

%HSRP-5-STATECHANGE: Ethernet0/0.10 Grp 10 state Active -> Init
%HSRP-5-STATECHANGE: Ethernet0/0.20 Grp 20 state Standby -> Init
%LINK-5-CHANGED: Interface Ethernet0/0, changed state to administratively down

障害後のRouter2側でも状態を確認しました。 Et0/0.10とEt0/0.20のStateがどちらもActiveActive欄がlocalになっていました。この表示から、Router2が両方のVLANでActiveになったことが分かります。一方、Standby欄はどちらもunknownとなっており、対向のStandbyルーターを認識できていない状態です。

Router2#show standby brief

Interface  Grp  Pri  P  State   Active  Standby  Virtual IP
---------  ---  ---  -  ------  ------  -------  -----------
Et0/0.10   10   100  P  Active  local   unknown  10.10.10.1
Et0/0.20   20   110  P  Active  local   unknown  10.10.20.1

Router2のログにもグループ10のStandby -> Activeが記録されているため、Router1の障害後にRouter2がActiveへ切り替わったことを確認できました。

%HSRP-5-STATECHANGE: Ethernet0/0.10 Grp 10 state Standby -> Active

復旧時の切り戻し

引き続き、Ubuntu0からUbuntu1へ連続pingを実行した状態で、Router1のEthernet0/0を復旧させました。

cisco@ubuntu0:~$ ping 10.10.20.11

Router1(config)#interface Ethernet0/0
Router1(config-if)#no shutdown

Ubuntu0側のpingを見ると、復旧する前から復旧後まで、20パケットすべてで応答がありました。以前の確認では復旧時に1パケットのロスを観測していましたが、今回の再検証では同じ現象は再現しませんでした。このように、タイミングによってはpingのロスすら発生せずに切り戻ることもあります。

cisco@ubuntu0:~$ ping 10.10.20.11
20 packets transmitted, 20 received, 0% packet loss

次に、Router1とRouter2のそれぞれで状態遷移と収束後の役割を確認します。

Router1のログでは、Ethernet0/0のchanged state to upに続いて、グループ10のListen -> Activeとグループ20のSpeak -> Standbyが記録されました。この表示から、リンクの復旧後にRouter1がVLAN 10ではActive、VLAN 20ではStandbyへ戻ったことが分かります。

%LINK-3-UPDOWN: Interface Ethernet0/0, changed state to up
%HSRP-5-STATECHANGE: Ethernet0/0.10 Grp 10 state Listen -> Active
%LINEPROTO-5-UPDOWN: Line protocol on Interface Ethernet0/0, changed state to up
%HSRP-5-STATECHANGE: Ethernet0/0.20 Grp 20 state Speak -> Standby

Router2のログでは、グループ10がActive -> Speak、続いてSpeak -> Standbyと遷移していました。この表示から、復旧したRouter1へActiveの役割を譲り、Router2がStandbyへ戻ったことが分かります。

%HSRP-5-STATECHANGE: Ethernet0/0.10 Grp 10 state Active -> Speak
%HSRP-5-STATECHANGE: Ethernet0/0.10 Grp 10 state Speak -> Standby

収束後のRouter2のHSRP状態も確認しました。 Et0/0.10のStateStandbyActive欄が10.10.10.2、Et0/0.20のStateActiveActive欄がlocalになっていました。この表示から、VLAN 10ではRouter1、VLAN 20ではRouter2がActiveとなり、障害前の役割へ無事戻ったことが分かります。

Router2#show standby brief

Interface  Grp  Pri  P  State    Active       Standby      Virtual IP
---------  ---  ---  -  -------  -----------  -----------  -----------
Et0/0.10   10   100  P  Standby  10.10.10.2   local        10.10.10.1
Et0/0.20   20   110  P  Active   local        10.10.20.2   10.10.20.1

振り返り

今回の検証では、通常時の役割分担だけでなく、障害発生から切り替え、復旧後の切り戻しまでを実際の状態とログで確認できました。

連続pingでは障害時・復旧時ともにパケットロスを観測しませんでしたが、それだけで冗長化が正常に働いたとは言い切れません。疎通、HSRPの状態、ログを組み合わせて見ることが大切だと思います。

構成図、IPアドレス、L2の状態、通常時の疎通結果については、CML2で構築した冗長デフォルトゲートウェイの検証記録に記載しています。