JANOG53 では NETCON の作問や採点回りを担当しました!
こちらのブログでは、level 4-2 の問題について解説します。
level 4-2 問題の概要
トポロジ
問題文
LB01 の配下に認証用の Server を冗長化して設置し、Client01 から LB01 の Frontend IP (10.150.0.100) に対して認証用の通信を行います。
認証用の通信は複数のコネクションを張る必要がありますが、仕様上すべてのコネクションが同じ Backend Server に到達する必要があります。
認証用のプログラムは Client01 の /root/auth.py にあり、 python3 auth.py
で実行可能です。
しかし、現在は Client01 から 10.150.0.100 までの到達性がなく、認証に失敗してしまいます。
まずは Client01 から LB01 の Frontend IP (10.150.0.100) への到達性を確保し、その後認証用のプログラムがすべて OK となるよう、ネットワーク構成を変更してください。
達成条件
- Client01 から LB01 の Frontend IP (10.150.0.100) に到達性があること (iBGP を使用し、 ECMP で冗長性を持たせてください。)
- Backend Server の冗長性は維持されていること
- python3 auth.pyの結果がすべて OK となること
制約
- Client01 内の
auth.py
を編集しないでください。(中身の閲覧は可能です) - 各 L3SW および RT 間は iBGP でネイバーを確立してください。
- Server01, Server02にはログインできません
補足事項
L3SW01 : SONiC
RT01 : cEOS
RT02 : cEOS
L3SW02 : cEOS
Client01 : Alpine Linux
LB01 : Alpine Linux で openrc を利用して LVS が稼働
Server01 : http リクエストを受け付け、Server01 という文字列を返す
Server02 : http リクエストを受け付け、Server02 という文字列を返す
初期 Config
L3SW01 initial config – /etc/frr/zebra.conf
interface eth1 description To_RT01 ip address 10.11.0.2/30 no shutdown interface eth2 description To_RT02 ip address 10.21.0.2/30 no shutdown interface eth3 description To_Client01 ip address 10.100.0.254/24 no shutdown
L3SW01 initial config – /etc/frr/bgpd.conf
router bgp 64512 maximum-paths 100 neighbor 10.11.0.1 remote-as 64512 neighbor 10.11.0.1 update-source eth1 neighbor 10.21.0.1 remote-as 64512 neighbor 10.21.0.1 update-source eth2 network 10.100.0.0/24
L3SW02 initial config
hostname L3SW02 interface Ethernet1 description To_RT01 no switchport ip address 10.12.0.2/30 no shut interface Ethernet2 description To_RT02 no switchport ip address 10.22.0.2/30 no shut vlan 200 interface Ethernet3 description To_LB01_Backend_Port switchport mode access switchport access vlan 200 no shut interface Ethernet4 description To_LB_Frontend_Port no switchport ip address 10.150.0.254/24 no shut interface Ethernet5 description To_Server01 switchport mode access switchport access vlan 200 no shut interface Ethernet6 description To_Server02 switchport mode access switchport access vlan 200 no shut interface vlan200 description Vlan200_Gateway ip add 10.200.0.254/24 no shut ip routing router bgp 64512 maximum-paths 100 neighbor 10.12.0.1 remote-as 64512 neighbor 10.12.0.1 update-source Ethernet1 neighbor 10.22.0.1 remote-as 64512 neighbor 10.22.0.1 update-source Ethernet2 network 10.200.0.0/24
RT01 initial config
hostname RT01 interface Ethernet1 description To_L3SW01 no switchport ip address 10.11.0.1/30 no shut interface Ethernet2 description To_L3SW02 no switchport ip address 10.12.0.1/30 no shut route-map Change_NH_To_10_11_0_1 set ip next-hop 10.11.0.1 route-map Change_NH_To_10_12_0_1 set ip next-hop 10.12.0.1 ip routing router bgp 64512 neighbor 10.11.0.2 remote-as 64512 neighbor 10.11.0.2 update-source Ethernet1 neighbor 10.12.0.2 remote-as 64512 neighbor 10.12.0.2 update-source Ethernet2
RT02 initial config
hostname RT02 interface Ethernet1 description To_L3SW01 no switchport ip address 10.21.0.1/30 no shut interface Ethernet2 description To_L3SW02 no switchport ip address 10.22.0.1/30 no shut route-map Change_NH_To_10_21_0_1 set ip next-hop 10.21.0.1 route-map Change_NH_To_10_22_0_1 set ip next-hop 10.22.0.1 ip routing router bgp 64512 neighbor 10.21.0.2 remote-as 64512 neighbor 10.21.0.2 update-source Ethernet1 neighbor 10.22.0.2 remote-as 64512 neighbor 10.22.0.2 update-source Ethernet2
auth.py
import requests import sys auth_url = 'http://10.150.0.100/' class Authenticator(): def request_authentication(self): try: response = requests.get(auth_url, timeout=1) content_without_empty_lines = response.text.replace('\n', '') return content_without_empty_lines except: print("例外が発生しました。") print(sys.exc_info()) exit() def main(): authenticator = Authenticator() first_result = authenticator.request_authentication() for i in range(1, 11): tmp_result = authenticator.request_authentication() if first_result == tmp_result: print("Step" + str(i) + " = " + "OK") else: print("Step" + str(i) + " = " + "ERROR") main()
想定解答
① L3SW01 で bgpd を起動する必要があります。
`sed -i -e 's/bgpd=no/bgpd=yes/g' /etc/frr/daemons` service frr restart
②L3SW02/RT01/RT02 で iBGP に関する設定を投入する必要があります。
L3SW02 router bgp 64512 network 10.150.0.0/24 RT01 router bgp 64512 neighbor 10.11.0.2 route-reflector-client neighbor 10.11.0.2 route-map Change_NH_To_10_11_0_1 out neighbor 10.12.0.2 route-reflector-client neighbor 10.12.0.2 route-map Change_NH_To_10_12_0_1 out RT02 router bgp 64512 neighbor 10.21.0.2 route-reflector-client neighbor 10.21.0.2 route-map Change_NH_To_10_21_0_1 out neighbor 10.22.0.2 route-reflector-client neighbor 10.22.0.2 route-map Change_NH_To_10_22_0_1 out
③LB01 でセッションパーシステンスを有効化する必要があります。
ipvsadm -C ipvsadm -A -t 10.150.0.100:80 -s rr -p ipvsadm -a -t 10.150.0.100:80 -r 10.200.0.1:80 -m ipvsadm -a -t 10.150.0.100:80 -r 10.200.0.2:80 -m rc-service ipvsadm save rc-service ipvsadm restart
解説
①L3SW01 で bgpd を起動
まずは L3SW01 で bgpd を起動する必要がありました。
これは SONiC では BGP の実装に FRR を利用しているためです。
少し古い部分もありますが、SONiC のアーキテクチャ概要は以下に記載があります。
Architecture · sonic-net/SONiC Wiki (github.com)
②L3SW02/RT01/RT02 で iBGP に関する設定を投入
以下の 3 点が達成できていれば基本的には点数となったはずです。
・route-reflector-client の設定
・nexthop-self の設定 (route-map でも nexthop-self でも ok)
・10.150.0.0/24 の広報
認証プログラムの疎通性があったとしても、Static Route での設定や、ECMP で冗長化されていない場合など、減点しています。
③LB01 でセッションパーシステンスを有効化
アプリケーションによっては異なるセッションが同じ Backend Server に到達する要件を持つ場合があり、それを簡易的に再現させました。
最初は LVS の -p オプションで session persistence を有効化する解答を想定していましたが、scheduling method を sh (soure hashing) とする方法も正解としました。
いくつか scheduling method を lblc としている回答がありましたが、サーバーの負荷状況によってはアプリケーションの要件を満たさない場合があると考え、減点しました。
lblc – Locality-Based Least-Connection: assigns jobs destined for the same IP address to the same server if the server is not overloaded and available; otherwise assign jobs to servers with fewer jobs, and keep it for future assignment.
ipvsadm(8) — ipvsadm — Debian unstable — Debian Manpages
※ 私も LVS にそこまで明るいわけではないので、見当違いだったら申し訳ありません。。
これらの設定を実施すると、 auth.py の実行結果がすべて ok となります。
おわりに
問題を解いていただいた皆様ありがとうございました!
皆様の解答を拝見して、すこし問題の前提条件が甘かったかなと反省しています。
反省点は次回に活かします!
本問題が SONiC や LVS を知るきっかけになれば幸いです。