TECH PLAY

NTTドコモビジネス

NTTドコモビジネス の技術ブログ

613

サマリ 概要 検証 1. Color 200 用 SR Policy の作成 SR Policy の確認 2. Color の付与と広告 経路の確認 動作確認 まとめ サマリ SR-MPLS + VPNv4 + explicit path による BGP Color を用いた Traffic Engineering (TE) を実現 IOS XR + Junos + SR OS の Multi-vendor 環境での動作検証に成功 この記事は Multi-AS Segment Routing 検証連載の第 14 回です。過去の記事一覧は こちら にあります。 概要 イノベーションセンターの田島です。本連載のような Segment Routing 関連の技術検証の指揮を執ったり、自動化による高度な運用を開発したりしています。 本記事では IOS XR + Junos + SR OS の Multi-vendor における Traffic Engineering (TE) についてご紹介します。 Segment Routing では ingress PE において転送するパスを決定し、適切な SID をパケットに付与することで TE を実現します。 本記事では TE の対象となる VPN 経路に対して BGP Color Extended Community (以下単に Color) を付与することで転送するパスを切り替える様子を示します。 第 4 回の記事 でもご紹介した通り、すでに IOS XR + Junos の Multi-vendor 環境での検証は実施済みで、 今回はそれらに Nokia SR OS を加えて検証します。 VPNv4 による L3VPN の相互接続は 第 12 回の記事 にて紹介済みですので、そちらも併せてご参照ください。 検証 本記事での検証は、L3VPN の prefix ごとに Color をつけて広告し、その Color によって転送する経路を変えるものです。 Color そのものや SR Policy に関する説明は 第 4 回の記事 を、 L3VPN に関する説明や設定は 第 12 回の記事 をご覧ください。 検証トポロジーは次のようなシンプルなものを用意します。 各 PE には VRF 100と VRF 200 が設定され、それぞれの経路に Color 100 と Color 200 を付与して広告します。 Color 100 の方は直通の最短経路で、Color 200 の方は迂回する経路での転送を実現します。 本記事では L3VPN はすでに開通しているとし、その後の設定を SR OS を中心に紹介します。 Color による TE は次の 2 ステップで設定します。 Color 200 用 SR Policy の作成 Color の付与と広告 なお本記事では下記のバージョンで検証しました。 rt01: IOS XR 7.4.1 rt02: Junos 21.3R1.9 rt03: SR OS 22.7.R1 1. Color 200 用 SR Policy の作成 Endpoint と Color を指定して SR Policy を作成します。 SR OS では SR Policy 用のラベルブロック (LB) を指定し、 BSID をそのブロックの中から手動で採番する必要があります。 rt01 向けの Segment List は、トポロジー図にあるように rt02 16002 を経由するものです。 router "Base" { mpls-labels { reserved-label-block "SR-Policy-LB" { start-label 52400 end-label 52499 } } segment-routing { sr-policies { admin-state enable reserved-label-block "SR-Policy-LB" static-policy "rt01-color200-policy" { admin-state enable color 200 endpoint 10.255.0.1 head-end local binding-sid 52410 segment-list 1 { admin-state enable segment 1 { mpls-label 16002 } segment 2 { mpls-label 16001 } } } } } } SR Policy の確認 設定した SR Policy が有効になっているかを表示して確認します。 Active になっていることが表示されます。 rt03 (SR OS) A:user@rt03# /show router segment-routing sr-policies static end-point 10.255.0.1 color 200 =============================================================================== SR-Policies Path =============================================================================== ------------------------------------------------------------------------------- Type : srMpls Active : Yes Owner : static Color : 200 Head : 0.0.0.0 Endpoint Addr : 10.255.0.1 RD : 0 Preference : 100 BSID : 52410 TunnelId : 917506 Age : 231 Origin ASN : 0 Origin : 0.0.0.0 NumReEval : 0 ReEvalReason : none NumActPathChange: 0 Last Change : 06/27/2023 05:09:21 Maintenance Policy: N/A Path Segment Lists: Segment-List : 1 Weight : 1 S-BFD State : Down S-BFD Transitio*: 0 Num Segments : 2 Last Change : 06/27/2023 01:41:02 Seg 1 Label : 16002 State : resolved-up Seg 2 Label : 16001 State : N/A =============================================================================== 2. Color の付与と広告 MP-BGP で VPN 経路を広告するときに Color を付与します。 VRF の export policy に設定することにより実現します。 なお、 SR OS では Color を示す color:00:<10進数> という書き方と、 BGP Extended Community 一般の記法で Color を指定する ext:030b:<16進数> という書き方ができます。 今回は見やすい前者で設定します。 policy-options { community "color-100" { member "color:00:100" { } } community "target-100" { member "target:65000:100" { } } policy-statement "vrf-export-100" { entry 10 { action { action-type accept community { add ["target-100" "color-100"] } } } } } service { vprn "100" { bgp-ipvpn { mpls { vrf-export { policy ["vrf-export-100"] } } } } } 経路の確認 rt03 で設定した Color は他のルーターで参照できます。 対向の rt01 では次のように Color 100 の経路と Color 200 の経路がそれぞれ認識されます。 rt01 (IOS XR) RP/0/RP0/CPU0:rt01#show bgp vpnv4 unicast rd 65000:100 192.168.103.0/24 detail Tue Jun 27 14:56:46.266 JST BGP routing table entry for 192.168.103.0/24, Route Distinguisher: 65000:100 Versions: Process bRIB/RIB SendTblVer Speaker 22 22 Flags: 0x00041001+0x00000000; Last Modified: Jun 27 14:56:00.872 for 00:00:45 Paths: (1 available, best #1) Not advertised to any peer Path #1: Received by speaker 0 Flags: 0x2000000085060005, import: 0x9f Not advertised to any peer Local 10.255.0.3 (metric 10) from 10.255.0.3 (10.255.0.3), if-handle 0x00000000 Received Label 524284 Origin IGP, localpref 100, valid, internal, best, group-best, import-candidate, imported Received Path ID 0, Local Path ID 1, version 22 Extended community: Color:100 RT:65000:100 Source AFI: VPNv4 Unicast, Source VRF: 100, Source Route Distinguisher: 65000:100 RP/0/RP0/CPU0:rt01#show bgp vpnv4 unicast rd 65000:200 192.168.203.0/24 detail Tue Jun 27 15:38:56.569 JST BGP routing table entry for 192.168.203.0/24, Route Distinguisher: 65000:200 Versions: Process bRIB/RIB SendTblVer Speaker 31 31 Flags: 0x00363001+0x00000000; Last Modified: Jun 27 15:38:49.872 for 00:00:06 Paths: (1 available, best #1) Not advertised to any peer Path #1: Received by speaker 0 Flags: 0x2000000085060005, import: 0x9f Not advertised to any peer Local 10.255.0.3 (metric 10) from 10.255.0.3 (10.255.0.3), if-handle 0x00000000 Received Label 524283 Origin IGP, localpref 100, valid, internal, best, group-best, import-candidate, imported Received Path ID 0, Local Path ID 1, version 27 Extended community: Color:200 RT:65000:200 Source AFI: VPNv4 Unicast, Source VRF: 200, Source Route Distinguisher: 65000:200 一方で逆向きの、対向ルーターが広告する Color を rt03 で確認します。 それぞれの経路に Color 100 と Color 200 が付与されています。 rt03 (SR OS) A:user@rt03# /show router bgp routes vpn-ipv4 rd 65000:100 detail (snip) Network : 192.168.101.0/24 Nexthop : 10.255.0.1 Route Dist. : 65000:100 VPN Label : 24004 Path Id : None From : 10.255.0.1 Res. Nexthop : n/a Local Pref. : 100 Interface Name : to_rt01 Aggregator AS : None Aggregator : None Atomic Aggr. : Not Atomic MED : 0 AIGP Metric : None IGP Cost : 20 Connector : None Community : color:00:100 target:65000:100 Cluster : No Cluster Members Originator Id : None Peer Router Id : 10.255.0.1 Fwd Class : None Priority : None Flags : Used Valid Best Incomplete Route Source : Internal AS-Path : No As-Path Route Tag : 0 Neighbor-AS : n/a Orig Validation: N/A Source Class : 0 Dest Class : 0 Add Paths Send : Default Last Modified : 00h13m13s VPRN Imported : 100 A:user@rt03# /show router bgp routes vpn-ipv4 rd 65000:200 detail (snip) Network : 192.168.201.0/24 Nexthop : 10.255.0.1 Route Dist. : 65000:200 VPN Label : 24005 Path Id : None From : 10.255.0.1 Res. Nexthop : n/a Local Pref. : 100 Interface Name : to_rt01 Aggregator AS : None Aggregator : None Atomic Aggr. : Not Atomic MED : 0 AIGP Metric : None IGP Cost : 20 Connector : None Community : color:00:200 target:65000:200 Cluster : No Cluster Members Originator Id : None Peer Router Id : 10.255.0.1 Fwd Class : None Priority : None Flags : Used Valid Best Incomplete Route Source : Internal AS-Path : No As-Path Route Tag : 0 Neighbor-AS : n/a Orig Validation: N/A Source Class : 0 Dest Class : 0 Add Paths Send : Default Last Modified : 00h13m46s VPRN Imported : 200 動作確認 Color 100 と Color 200 が付いたそれぞれの宛先に対して traceroute をすることで、直通か迂回路かを使い分けられていることが転送ホップ数から確認できます。 rt03 (SR OS) A:user@rt03# /traceroute 192.168.101.254 router-instance 100 probe-count 1 traceroute to 192.168.101.254, 30 hops max, 40 byte packets 1 10.0.2.1 (10.0.2.1) 3.99 ms A:user@rt03# /traceroute 192.168.201.254 router-instance 200 probe-count 1 traceroute to 192.168.201.254, 30 hops max, 40 byte packets 1 10.0.3.1 (10.0.3.1) 2.62 ms 2 10.0.1.1 (10.0.1.1) 8.97 ms 経路表でも直接 IS-IS で転送先が解決される Color 100 と、 SR Policy によって転送される Color 200 が確認できます。 この tunnel-id 917506 は「SR Policy の確認」節での show 結果に出ている Policy が使用されていることを示します。 [/] A:user@rt03# /show router service-name 100 route-table 192.168.101.0/24 =============================================================================== Route Table (Service: 100) =============================================================================== Dest Prefix[Flags] Type Proto Age Pref Next Hop[Interface Name] Metric ------------------------------------------------------------------------------- 192.168.101.0/24 Remote BGP VPN 00h21m21s 170 10.255.0.1 (tunneled:SR-ISIS:524298) 20 ------------------------------------------------------------------------------- No. of Routes: 1 Flags: n = Number of times nexthop is repeated B = BGP backup route available L = LFA nexthop available S = Sticky ECMP requested =============================================================================== [/] A:user@rt03# /show router service-name 200 route-table 192.168.201.0/24 =============================================================================== Route Table (Service: 200) =============================================================================== Dest Prefix[Flags] Type Proto Age Pref Next Hop[Interface Name] Metric ------------------------------------------------------------------------------- 192.168.201.0/24 Remote BGP VPN 00h15m31s 170 10.255.0.1 (tunneled:SR-Policy:917506) 0 ------------------------------------------------------------------------------- No. of Routes: 1 Flags: n = Number of times nexthop is repeated B = BGP backup route available L = LFA nexthop available S = Sticky ECMP requested =============================================================================== 逆向きの rt01 から rt03 宛ての経路についても同様に、直通経路と、途中に 1 ホップする経路が使い分けられています。 rt01 (IOS XR) RP/0/RP0/CPU0:rt01#traceroute 192.168.103.254 vrf 100 probe 1 Tue Jun 27 15:32:02.036 JST Type escape sequence to abort. Tracing the route to 192.168.103.254 1 192.168.103.254 2 msec RP/0/RP0/CPU0:rt01#traceroute 192.168.203.254 vrf 200 probe 1 Tue Jun 27 15:32:03.991 JST Type escape sequence to abort. Tracing the route to 192.168.203.254 1 10.0.1.2 [MPLS: Labels 16003/524283 Exp 0] 3 msec 2 192.168.203.254 4 msec まとめ 本記事では、SR OS を含めた Multi-vendor 環境における Color-Based TE の検証結果を紹介しました。 (2023/9/19 編集・追記) 次のエントリは予定を変更して Flex-Algo の相互運用性の記事を公開しました: [Multi-AS Segment Routing 検証連載 #15] IGP Flexible Algorithm Interoperability Updates
はじめに こんにちは、イノベーションセンターの黒木(GitHub: krk09 )と鍔木(GitHub: takuma0121 )です。 今回はOT(Operational Technology)ネットワークのセキュリティリスク可視化サービスである OsecT(オーセクト) のリニューアル提供を開始したので、サービス運用で得られた知見をもとに、どのような機能改善をしたのか紹介します。 OsecTとは OsecTとは工場などのOTシステムのセキュリティリスクを可視化・検知するサービスです。 多様化する工場システムのセキュリティ脅威に対して、パケット解析するセンサー機器を設置するだけで、OTシステムへの影響なく、ネットワークの可視化と脅威・脆弱性検知ができます。 早期にリスク感知できる状態を作り、工場停止による損失を未然に防ぐことができます。 詳しくは過去のブログ記事に書いているので、興味がある人はぜひ見てください。 ( OsecTリリース ・ OsecT前編 ・ OsecT後編 ) サービス運用から得た知見 2022年4月にサービスリリースしてから1年ほど経過して、実証実験では得られなかった知見を得ることができました。 その1つが OTネットワークがITネットワークと分離されていない環境が多くある です。この記事ではそのような環境をIT/OT非分離環境と呼びます。 このような環境でOsecTを利用すると、性能不足や過検知が課題になることがわかりました。 その他にもOsecTの利用ユーザーが増えていくにつれて、「可視化画面やアラートが見にくい」「自分で設定したい、またはしたくない」「OTプロトコルの可視化・検知を充実させてほしい」などの声もいただきました。 リニューアル提供での主な改善点 本章ではサービス運用から得られた知見をもとにした改善点を、可視化・検知機能を有するクラウド上にあるOsecTコアと、パケット解析機能を有するOsecTセンサーに分けてご紹介します。 OsecTコア OsecTを利用できる環境を広げるためにIT/OT非分離環境への対応や、脅威検知機能の刷新やサービス名の編集をはじめとしてより使いやすく、分かりやすくするための改善を行いました。 IT/OT非分離環境への対応 これまでITネットワークとOTネットワークが分離されていない環境にOsecTを置いた場合、IT機器によるインターネットへのアクセスが含まれることによって、管理していないインターネット上のIPアドレス等もOsecT上で端末として可視化/検知されてしまうことがありました。その結果、端末(IPアドレス)数が多くなりすぎて処理に影響がでたり過検知によってアラートが大量に出てしまったりするという問題がありました。 これらの問題に対して、グローバルIPアドレスやインターネットドメインを集約する機能を追加することで、IT/OT非分離環境においてもOsecTを利用できるようにしました。 集約されたグローバルIPアドレスは以下の internet_address(v4) などのように1つにまとめて可視化されます。 OTネットワークがITネットワークと分離された環境向けに、従来通り集約せずに可視化することもできます(システム設定からインターネットアドレス可視化の設定をONにする)。 また、一部のグローバルIPアドレスやインターネットドメインのみを集約対象から除外して可視化したい場合のための設定項目も用意しています。 IT/OT非分離環境において、誤ってグローバルIPアドレスを可視化する設定にすると、管理対象外のIPアドレス(グローバルIPアドレス)もLAN内の端末と同じように扱われ、OsecT上にサービス仕様を超えた端末(1,000端末)数が表示されることがあります。 そのような場合に、お客さまへ注意喚起して設定の見直しを促すためにメールで通知する機能も併せて追加しました。 この通知を受け取ったお客さまには、管理対象外のIPアドレスまで可視化対象になっていないかご確認、及び適切な設定をお願いできればと思います。 学習ベース脅威検知の追加 元々OsecTに備わっているホワイトリスト方式の異常検知は、自動化されたシステムのように、端末が機械的な通信を繰り返し、通信先があまり変わらないような厳格なOT環境においては有効です。しかしそうではない環境、例えば人手による端末操作などにより通信先が頻繁に変動する環境では過検知を引き起こしてしまいます。 通信先などが変動するような環境においても適用できる学習ベースの検知機能として、今回新しくIP統計検知を追加しました。 IP統計検知は、IPアドレス単位で宛先IPアドレス数や送受信パケット数などといったIP通信の傾向を表す数値を元に異常を検知する機能です。 具体的には、一定時間毎にIPアドレス単位で宛先IPアドレス数や送信/受信パケット数などの分析に使う値を算出し、信頼区間分析/主成分分析をそれぞれ行います。 信頼区間分析は、学習時に各値で99.9%信頼区間を求めて算出した閾値を元に検知します。 主成分分析では、学習時に各値をまとめた主成分分析によって得られた主成分毎の最小値/最大値を閾値として検知します。 信頼区間分析では各値を個別に分析して検知し、主成分分析では各値を相関的に分析して検知するイメージです。 端末情報表示の整理 「端末」の「IP別接続サービス」タブの名称を「詳細」に変更し、それに伴って表示する情報を拡充しました。 元々MACアドレスやベンダー名など接続サービス以外の情報も表示していたため、実態に合った名称となり、「一覧」タブに表示されているホスト名やOSなどの情報も表示されるようになりました。 また、検知アラート画面において、IPアドレスがリンクになっていたりホバーで端末の情報が表示されたりと挙動が統一されていなかったものを、ホバー表示に統一した上で表示内容を統一・整理しました。 脅威検知アラートのわかりやすさ向上 各検知アラートがどんなアラートなのか(何故発生したのか)分かりやすくするために、検知アラートの一覧ページに各アラートの概要を説明する項目を追加しました。 具体例として新規端末アラートの場合「新規端末192.168.0.xが出現」、脆弱端末アラートの場合「サポート切れOS Windows 7の端末192.168.0.xが出現」といった説明が表示されます。 ポート番号に対する名称変更機能の追加 これまではポート番号やパケットの内容から自動で判定できたプロトコルのみサービス名を表示していましたが、特定のポート番号に対してユーザーがサービス名を編集できる機能を今回追加しました。 TCP/IP上で独自プロトコルを使っている場合などに、この機能を使ってサービス名を設定することによって、自動で判定できないプロトコルでも端末一覧などの可視化のページでユーザーの設定したサービス名が表示されるようになります。 脅威検知の使い勝手向上 より簡単な操作で脅威検知機能を利用できるよう、学習期間・検知期間を細かく設定しなくても学習状況から自動的に検知へ移行する機能を追加しました。 また、どのようなOT環境でも共通的に使っていただきたいおすすめの検知種別については、事前設定不要で利用できるようなりました。 従来の機能はアドバンスモードとして残しているため、学習と検知の期間をそれぞれ設定したい場合はアドバンスモードをONにすることで従来通りの設定が可能です。 OsecTセンサー センサーでは、IT/OT非分離環境でのトラフィック量増加に対応するための性能向上や、ニーズの多いOTプロトコル(CC-Linkファミリー)への対応を行いました。 性能向上 これまでトラフィック量が比較的少ないOTネットワークを想定していたため、tcpdumpでPcapを生成後、 Zeek やSuricataなどのパケット解析ツールでログ化する処理をしていました。 しかしながら、この方式では数十Mbpsが性能の限界(サービス仕様上は10Mbps)だったため、インターフェースから直接ログ化する方式に変更しました。 従来の方式から新しい方式に変更することで、Pcapの生成→ログ化といった2段階の処理が解消されたことや、Pcapのパケット解析だとシングルコアでしか動作しなかったツールがマルチコアで動作できるようになり、数百Mbpsまでのトラフィックを処理できるようになりました(サービス仕様上は100Mbps)。 OTプロトコル(CC-Linkファミリー)への対応 今回のリリースでは、日本国内で開発され、広く普及しているOTプロトコルである CC-Linkファミリー のプロトコルに対応しました。 市販のOTセキュリティ製品のプロトコル対応状況は、製品毎プロトコル毎に異なり、プロトコル名を表示するだけのものからペイロードにある変数を使って異常を検知するものまでありますが、OsecTではCC-Linkのコマンドレベルでの可視化・検知まで実現できるようにしました。 OTプロトコルの対応にはZeekおよびSpicyを利用しており、具体的な実装方法は 【日本初紹介】Zeek・Spicyの使い方まとめ を参照していただければと思います。 OTプロトコルは業界・業種・機器メーカー毎ごとに存在するため、すべてのOTプロトコルに対応することは難しいです。一方で、今回のリニューアルを通じてOTプロトコルに対応するためのフレームワークや具体的な実装方法が確立できつつあります。 今後もユーザーのニーズを汲み取って、リリースごとに優先度の高いOTプロトコルに対応していきたいと考えています。 おわりに 今回はサービス運用を通じて得られた知見をもとに、どのような機能改善をしたのかご紹介しました。 実証実験だけでは明らかにならない課題もあり、サービスリリース後も素早く課題を見つけて改善を続けていくことがより良いサービスの実現につながると感じました。 OsecTは低価格でOTネットワークの可視化や脅威検知ができるので、セキュリティ対策に手が出ていない・不十分と感じている企業さまにはぜひご利用いただきたいです。 ご興味がある企業さまは、 WideAngle (OsecT) ご紹介ページ からお問い合わせいただければ幸いです。
わかること IoTプラットフォームにおける独自のイベント処理ロジックの構築について Things Cloud のノーコードツール「Analytics Builder」でできること ※本記事は、Things Cloud バージョン10.14 (8月以降リリース予定)の利用を想定しています。 はじめに こんにちは、Things Cloud のカスタマーサクセスチーム 井上です。 私たちは、5G&IoTサービス部で IoTプラットフォーム「Things Cloud」のサービス開発やお客さまへの技術支援を担当しています。 早速ですが、皆さんは「IoT化」という言葉を聞いて何を思い浮かべるでしょうか。データの収集から可視化、分析、異常検知、通知、自動制御などIoTで実現できることは幅広く、適用可能なビジネス領域や業界も多様です。特に最近では、専門的なスキルを必要とせず手軽にIoT化を実現できるIoTサービスが多く登場しています。 本記事では、IoTプラットフォームThings Cloudに搭載されているデータ処理機能の1つである「Analytics Builder」を利用して、ノーコードで独自の分析処理を構築する方法ご紹介します。 Analytics Builderとは Things Cloudの紹介 Analytics Builderを紹介する前に、 Things Cloud のサービスについて、概要をご紹介します。 Things Cloudは、NTT CommunicationsのSmart Data Platform(略称SDPF)の中で、データ収集機能を提供するプラットフォームの1つです。 製品やセンサーなどのIoTデバイスからデータを収集し蓄積できるクラウドサービスで、簡単な操作でデータの可視化やアラート通知を実現でき、デバイス接続/ユーザー管理/デバイス管理などIoT導入に必要な機能一式が揃ったIoTプラットフォームです。 Things Cloudには、データをリアルタイムで処理し、データに基づいて通知や制御などのアクションを実行するためのデータ処理機能がいくつか搭載されています。 Things Cloudのデータ処理では、リアルタイムに流れているイベント(データ)をトリガーとして処理を行い、処理結果としてデータベースへの書き込みやメール送信、通知、制御を行います。 データ処理機能の1つとして、今回紹介するAnalytics Builder 1 があります。 Analytics Builderを活用することで、テンプレートベースの標準機能だけでは実現できない独自のデータ処理機能をノーコードで簡単に構築できます。 Analytics Builderの概要 Analytics Builderは、ブラウザ上でグラフィカルに、データ処理モデルを構築できる機能です。 下図のように、事前定義された処理ブロックを線でつなぐことで処理モデルを構築できます。 ブロックは処理内容、ブロック間をつなぐ矢印はデータの入出力を表しています。 Analytics Builderの技術的観点や利用方法などの詳細を知りたい方は、 開発者ドキュメント 〜 Analytics Builder をはじめる〜 をご参照下さい。 ノーコードとは アプリケーションやシステムの開発において、昨今新たな手法として広まっているのが 「ノーコード」 や「ローコード」と呼ばれる開発手法です。 「ノーコード」は、一般的なプログラミングにおいて必要となるソースコードの記述が不要なため、特別なスキルが不要で手軽にアプリケーションを構築できます。 Things Cloudでは、IoTデバイスからのデータを処理するための処理ロジックをノーコードで構築できる「Analytics Builder」をプラットフォーム内に備えています。 参考サイト: DXを加速する「ノーコード ローコード」による開発とは? Analytics Builderの特徴 Analytics Builderには、以下のような特徴があります。 ユースケースに応じた独自処理の実現が可能 Analytics Builderは、テンプレートベースの標準機能では実現できない独自の処理を、ノーコードで簡単に実現できます。 グラフィカルなUIでわかりやすい Analytics Builderは、Things Cloud上のアプリケーションの一部であり、直感的に操作できるグラフィカルなUIを備えています。また、実装時は必要なブロックを選択しUI上で線を使ってつなげていくだけなので、すぐに分析モデルを構築できます。 すぐに始められる Analytics Builderでは、カテゴリ分けされたブロック群から必要なブロック(機能)を選択し、あらかじめ定義されたパラメータ設定するだけで必要な処理を実現できます。一般的なプログラミングのようにさまざまな文法や関数を学習する必要がなく、短時間で手軽に分析モデルを構築できます。 適用ユースケース/処理の例 ここまで、Analytics Builderの強みを説明してきました。 これまでに述べたように、Analytics Builderでは用意された複数の処理ブロックを簡単に組み合わせることができ、それによって個別の要件に応じたさまざまな処理モデルの構築が可能です。 ここでは、代表的な適用例を一部ご紹介します。 温度センサ等を利用したユースケースの場合 温度が3分継続して40℃以上になった時、アラームを生成 デバイスごとの計測値の10分平均を算出し、計測値として登録 特定のデバイスグループ全体の計測値の10分平均を算出 電力使用量を計測するユースケースの場合 日次の総電力使用量の集計 拠点ごとに総電力使用量を集計 その他 デバイスからの通信が途絶した後、復旧した際に通知メールを送信 イベントやアラームをトリガーとしたデバイスデータの更新 (例:機器の動作開始/終了イベントから、デバイス情報の"動作ステータス値"を更新) より簡単な標準機能 「スマートルール」 Things Cloudのデータ処理機能には、より簡単に設定/利用が可能な「スマートルール」が標準搭載されています。 スマートルールは、あらかじめ定義されているテンプレートからUI上でデータにもとづくアクションを簡単に設定できる機能です。 スマートルールのテンプレートでは「しきい値超過時にアラームを発生させる」「アラーム発生時に通知メールを送る」など頻繁に利用される機能が定義されており、操作も非常にわかりやすいため、Things Cloudのデータ処理ではまずスマートルールの利用を考えます。 スマートルールで定義されていないような独自の処理を行いたい場合には、Analytics Builderの活用が有効です。 ※スマートルールの詳細については、 開発者ドキュメント をご参照ください。 Analytics Builder 実装例 ここでは、温度値の集計を題材として、実際にAnalytics Builderを利用して1つの処理モデルを構築した例をご紹介します。 処理内容 入力する計測値: 温度センサで計測した温度値 (20秒おきに送信) 出力する結果: 5分間の平均値がしきい値を上回った場合に、アラームを発生させる 処理内容 : デバイスの温度値を取得 5分間の平均値を算出 平均値がしきい値を超過しているか判定 アラーム通知用の文章を作成 アラームを送信 実装/動作例 Analytics Builderで作成したモデルの例 ブロックの設定例(平均値ブロック) しきい値超過時のアラーム発生画面 他の実装例や具体的な実装方法について知りたい方は、 開発者ドキュメントの例題 をご覧下さい。 応用例:Slackに通知内容を送信 Analytics Builder には、入力/出力/集約など便利で豊富なブロックが標準で搭載されていますが、入出力/パラメータ/処理内容を自身で設定/構築するカスタムブロック 2 というものを作成することも可能です。 以下は、Slackに通知するカスタムブロックを開発し、先ほど紹介したモデルに対して追加した例になります。 ※Slackの Incoming Webhook機能 を利用しています。 Slack通知のカスタムブロック(開発例) Slackに通知される様子 おわりに いかがでしたか? 今回は、Things Cloudのノーコードツール「Analytics Builder」についてご紹介しました。 Things Cloudでは、スマートルールやAnalytics Builderを活用することで、さまざまなユースケースに対応したデータ処理をコーディング不要で簡単に実現可能です。また、より高度で複雑な処理を実現したい場合やプログラミングに慣れている方向けには、コーディングによってデータ処理を構築するApama EPL機能 3 も備えています。 Things Cloud カスタマーサクセスチームでは、ますます広がっていくIoTユースケースにおいて、より便利な使い方を開拓すべく機能検証や内製開発をしています。今後もIoTに関連する開発ネタを発信していきたいと思います! Things Cloud 関連ブログ: IoTデバイス接続の難しさを解決するNTT Comのお手軽IoT Observable を活用した IoT データの可視化探索ガイド 問い合わせ先 お手数ですが@を半角文字に置き換えてください。 Things Cloud サービスについて:iot-info@ntt.com Things Cloud カスタマーサクセスチーム:iot-app@ntt.com Analytics Builderの利用には「カスタムストリーミング処理機能」のオプション申し込みが必要です。 ↩ カスタムブロックの作成には、開発環境の準備および専用の言語によるコーディングが必要です。 ↩ Apama EPL機能の利用には「カスタムストリーミング処理機能」のオプション申し込みが必要です。Apama EPL機能について詳しく知りたい方は、 開発者ドキュメント 〜Apama EPLをはじめる〜 をご覧下さい。 ↩
みなさんこんにちは、イノベーションセンターの @Mahito です。普段は社内のエンジニアが働きやすくなることを目標に、コーポレートエンジニアとしての活動やエンジニア向けイベントの企画・運営をしています。 今回は、本 NTT Communications Engineers' Blog を2年間運営してきたノウハウについて共有できればと思います。先日 はてなブログ DevBlog Meetup #1 に登壇させていただく機会があり、ブログ運営に関していくつかお話しさせていただいたのですが、イベント当日に言えなかったことや言ったことの補足などをできればと思います。 目次 目次 開発者ブログのこれまでと目的 運用のノウハウ・意識していること 執筆者の確保・継続・インセンティブ設計 1. 定期的にブログの取り組みを社内に紹介することで取り組みに興味を持ってもらう 2. ニュースリリースを見て、技術的に面白そうな取り組みをしているところに声をかける 3. 執筆のハードルを下げる 運用 レビュー 記事公開 KPI や指標 その他 長く続けるために個人的に意識していること まとめ 開発者ブログのこれまでと目的 開発者ブログの運用ノウハウをお伝えする前に、少しだけ本ブログについてのお話をさせていただきます。 こちら「 開発者ブログをリニューアルしました! 」でも書いたのですが、NTT Com では元々2015年に6月頃から開発者ブログを開始しました。当時はCMSを自分たちで運用していくスタイルでしたが、CMSの使い勝手やレビューのしづらさなどもあり、リニューアルという形ではてなブログへと引っ越しをする形になりました。 エンジニアブログをリニューアルする際には、開発者ブログに以下のような目的を定めました。 NTT Comのエンジニアの取り組みを広く知ってもらう 社外のユーザーやエンジニアとコミュニケーションをとれるきっかけの場とする NTT Comのエンジニアが自己発信できる場を提供する NTT Comにはさまざまなエンジニアがそれぞれの仕事をしていますが、その多くは外部には見えません。例えば、NTT Comのニュースリリースを見ても、技術の詳細などは書かれていません。そのため、リクルーター活動などをしていると、NTT Comのエンジニアが何をしているのか社外に知られていないと感じることが多くありました。 一方で、エンジニアの中には自分たちの取り組みを知ってもらうことで、社外のエンジニアやユーザーと繋がり、そこから採用や新規ユーザーの獲得に繋げたいと考えている人もいます。しかし、社外のエンジニアやユーザーとの交流のきっかけや、自分たちで発信する場があまりないという問題がありました。そこで、開発者ブログを通じて、これらの問題を解決できるようにしていこうとなりました。 運用のノウハウ・意識していること 執筆者の確保・継続・インセンティブ設計 NTT Comでは、ブログは書きたい人が書くというスタイルを取っています。これは、持ち回りで定期的に記事を出すということよりも、書きたい人のやる気を優先することでいい記事が生まれ、いい結果につながるのではというような話だったと思います。(運営の中で全然議論にならなかったのでうろ覚えです) おかげで1ヶ月近く新しい記事がでないこともありますが、タイミング的にまだ公開できない未公開記事や、「書きたい!」と言って準備してくれている人が常にいる状態のため、運営スタッフは「今週もでなかったね〜」ぐいらいのノリで焦りは特にありません。 新規の執筆者をどう確保するのかという点では、以下の3点を意識しています。 定期的にブログの取り組みを社内に紹介することで取り組みに興味を持ってもらう ニュースリリース を見て、技術的に面白そうな取り組みをしているところに声をかける 執筆のハードルを下げる 1. 定期的にブログの取り組みを社内に紹介することで取り組みに興味を持ってもらう 社内でもまだまだ開発者ブログに取り組んでいることを知らない人もいるため、社内での開発者ブログの認知を上げることや、そのタイミングではブログのネタがなく興味を持たなかった人に再度知ってもらうことで書くきっかけにつながればと思っています。社内に紹介する方法としては、社内ポータルの周知に「今月どんな記事が出たかのまとめ」を掲載したり、新しい記事がでたら Slack や Microsoft Viva Engage(旧称 Yammer) に自動投稿したり、社内のイベントでブログの活動を紹介したりとさまざまです。 2. ニュースリリースを見て、技術的に面白そうな取り組みをしているところに声をかける 我々運営スタッフも社内のすべてを知っているわけではないので、運営の定例などで NTT Com のニュースリリースをチェックし、技術的に面白そうな取り組みをしているところに連絡をしています。こちらの「 駆け出し開発チームでも45万回利用されるシステムを2カ月で作れた話 」 はニュースリリースを見て、運営から声をかけさせてもらった記事です。個人的にはプロジェクトのはじまるきっかけなど、ニュースリリースに書かれていない部分も知ることができとてもいい記事でした。 3. 執筆のハードルを下げる 執筆者のハードルを下げる取り組みは、「執筆したいけどできない」とか「こんなこと書いていいのかな」という問題を解決することです。 前者は、稼働の問題や周囲の理解、技術的な問題など、さまざまな理由がありますが、副社長や幹部に開発者ブログの活動にお墨付きをいただいています。 何か問題があれば「偉い人の承認を得ている取り組みですよ」ということができます(使ったことはないけど)。 また、後者に関しては、運営スタッフが色々サポートできます。 例えば、NTT Comの開発者ブログでは、記事はMarkdownで記載され、GitHubを利用して記事の管理やレビューをしています。 執筆者の中には、これらに慣れていない方もいますが、運営スタッフがサポートして記事が書けるようにお手伝いしています。 「こんなこと書いていいのかな」という疑問に対しては、運営スタッフが相談に乗ることもあります。エンジニアは、自分たちのやっていることがたいしたことではないと思いがちですが、「自分たちならではの部分や工夫」があることも多いため、そういった部分を記事に取り入れることを提案します。 また、開発者ブログを継続することで記事の専門性が深くなったり、難しい課題を解決した話がでることもありますが、それによって新しい執筆者が「自分はそんな記事をかけない」とハードルを感じることもあります。そのため、時々「 知ってるようで知らない YAML のご紹介 」のような比較的軽い記事を投稿して、執筆者のハードルが上がりすぎないように意識しています。 運用 NTT Com 開発者ブログの運用は有志の運営スタッフで行われています。 運営スタッフに参加している理由は面白そう、社内の取り組みが知りたい、社内の人と知り合いたいなど人それぞれですが、業務時間内の仕事の合間を縫って活動をしています。 運営スタッフのやることは主に以下のとおりです。 記事のレビュー 執筆者のサポート 記事のネタ・執筆者探し 運営上の課題解決 運営スタッフは毎週定例を設けており、上記の進捗状況などについて共有したり議論をしています。 レビュー 記事のレビューは GitHub 上で行っており、執筆者の Pull Request(以下、PR) が来るとランダムで運営スタッフからレビュー担当が1名つきます。 また、レビューの前に GitHub Actions が動作し、はてなブログへ下書き状態での記事投稿や、 textlint を用いて表現や文章のチェックがなされます。 レビューでは執筆者が伝えたいことや文章の個性をそのまま読者へ届けられるようにしつつも、より読みやすい形で出すために以下のような点を確認しています。 読者が読んでいて疑問に思うところがないか 読者が読みやすい文章表現になっているか 数字の正確性確認 ブログに使われている画像に問題がないか 記事によってはレビュー担当のカバーする技術分野から離れた専門領域の内容をレビューすることもあります。 そうした場合はその領域をカバーできるスタッフに代わってもらいますが、代わってもらう人がいない場合は自分で調べながらレビューすることもあります。 私自身専門外の記事レビューを何度か経験しましたが、レビューは難しくも普段と違う技術領域を知るきっかけになり楽しんでいました。 textlint では社名(正式略称は「NTT Com」)や商品名、日本語の表現などがチェックされ、問題があれば PR にコメントとして残されます。 これは、読者の方が読みやすい文章になるだけでなく、レビュー担当の負担を減らすことや、レビューの見逃しをなくすことに繋がっています。 記事公開 記事の公開はレビューが終わり次第可能となり、PR の Merge ボタンを押すと GitHub Actions が下書き状態だった記事を公開状態に変更します。 執筆者の希望公開日があればその日にデプロイをしますが、希望がなければ、運営スタッフが Page View(以下、PV) が稼げそうなタイミングでリリースをします。 この2年間でどういうタイミングに公開すると PV が伸びやすいかなど仮説を持って検証してきており、そうしたノウハウを活用しています。 記事公開にはレビューや textlint などのチェックを行っていますが、公開後に見つかるタイポや表現の問題があります。 その場合、修正の PR を作成し、レビュー、マージの手順を踏んで記事を更新しています。 ボタン1つで公開や修正をできる Continuous Delivery のしくみにすることで、記事の公開・修正のハードルを下げることに繋がっています。 KPI や指標 「ブログの KPI をどうしているか」という質問がイベントでもありましたが、NTT Com の開発者ブログにも KPI はあります。 PV 数や記事の投稿数など、定量的な指標を KPI にしていますが、あくまで、「NTT Com の開発者ブログがこういう状態になっていたら嬉しい」ぐらいの目標設定として数字は置かれています。 KPI の管理は毎週のスタッフ定例で進捗確認をしながら KPI の達成に向けた施策の検討や実施をしており、 毎年12月の アドベントカレンダー 企画や、社内の執筆者向けた情報公開、イベントなども行っています。 先日もブログリニューアル2周年を記念した運営スタッフと執筆者の Meetup が行われ、この2年間の活動の振り返りや、今後についての話し合いなどが行われました。 その他 長く続けるために個人的に意識していること ブログ運営を2年間続けている中で私個人として意識していることがあります。 それは、 「ゆるく」 運営をしていくことです。 「8年続く社内勉強会を続けていくために行っていること」 というタイトルの記事でも書かせてもらったのですが、運営を頑張ることはとても大事な一方で、頑張りすぎてしまうと燃え尽きてしまいあとが続かないこともあります。 先述したとおり、運営スタッフはそれぞれが開発者ブログに対して何らかの目的や思いを持って活動をしています。 一方で、運営スタッフは本業の合間を縫ってエンジニアブログの運営をしているため、運営を頑張るほどに運営スタッフの負担が上がり燃え尽きる可能性もあります。 社内の取り組みをより多くの人に知ってもらうための開発者ブログの活動を、運営スタッフが思いを持って運営し続けていけるしくみとして、「ゆるさ」が大事だと考えています。 その運営をゆるくするためにしくみのひとつとして、定例の簡素化があります。 運営スタッフの定例は時間と議題だけを決め、そのとき集まれるメンバが Slack ハドルミーティングに集まります。 議事録などは毎回残しているので参加できなかった運営スタッフは後から読むことができます。 また、Slack ハドルミーティングは普段から開発者ブログに関して運営や執筆者たちがやり取りをするチャンネルを用いているため、 定例には運営スタッフ以外にも開発者ブログの運営や執筆に興味がある人も参加できるオープンな形で開催しています。 この他にも GitHub の PR によるレビューや、GitHub Actions を使った textlint、記事の下書き投稿・公開の自動化などのしくみも、 我々運営スタッフの負担を減らし、ゆるくやっていくためのしくみの1つとして用意したものです。 今後も開発者ブログの運営が長続きするように、我々運営が頑張りすぎず、ゆるく運営を続けていければと思っています。 まとめ 今回は2年間の開発者ブログ運営のノウハウや意識していることなどを紹介しました。 企業の文化やルールによっては使えるノウハウ、使えないノウハウなどあるかもしれませんが、この記事がどこかの開発者ブログの運営のお役に立てれば幸いです。
TOC サマリ 概要 検証 EVI と CE 向けポート設定 EVI と CE 向けポートの状態確認 BGP の設定 Local Preference(LP) の設定 IOS XR ASBR 間 SR OS ASBR 間 経路の確認 EVI 3600 EVI 3700 疎通試験 制約事項 まとめ サマリ Multi-AS で構成されるネットワークにおいて、SR-MPLS + EVPN による L2VPN を実現 IOS XR + Junos + SR OS の Multi-vendor 環境での動作検証に、特定の組み合わせ以外は成功 この記事は Multi-AS SR 検証連載の第 13 回です。過去の記事は こちら 概要 イノベーションセンターの竹中です。普段の業務では Multi-AS Segment Routing に関する技術検証や、ネットワーク運用効率化のためのコントローラー開発などを行なっています。 第3回 の記事で IOS XR + Junos の 2 つのベンダー機器で構成される Single-AS/Multi-AS L2VPN についてご紹介しましたが、今回新たに Nokia SR OS(Service Router Operating System)を PE・P・ASBR に加えた 3 つのベンダー機器での Multi-AS L2VPN 動作検証をご紹介します。 EVPN による L2VPN に関する説明は、 第3回 記事の概要にて紹介しているので、そちらをご参照ください。 検証 EVPN L2VPN の検証例を実際の設定例を添えつつ紹介します。 IOS XR、Junos の設定例は 第3回 の記事で紹介したため本記事では割愛し、SR OS の設定例を中心に紹介します。 本記事の検証は Inter-AS Option B の L2VPN について、SR OS と各ベンダー間の互換性確認を目的とします。 つまり下記を検証します。 SR OS を PE として L2VPN が構築できるかどうかを確認する SR OS と IOS XR/Junos の間で L2VPN 経路を交換できるかどうかを確認する Inter-AS Option B 構成を構築する際に SR OS を ASBR として利用できるかを確認する 下記のトポロジーを利用し L2VPN の検証例を紹介します。 なお、検証は運用中の実機環境を利用しているため、一部トポロジーが雑然としていることはご了承ください。 また、各 EVI で扱う組み合わせを表に示します。 EVI AS65001 PE → → ASBR-ASBR → → AS65002 PE 3600 Juniper Cisco Nokia 3700 Cisco Nokia Juniper 使用する機器は以下の通りです。 IOS XR rt01: Cisco ASR9901 (IOS XR 7.6.1) rt03: Cisco 8201 (IOS XR 7.5.1) rt06、rt08: Cisco ASR9902 (IOS XR 7.5.1) rt10: Cisco NCS55A2 (IOS XR 7.5.1) Junos rt02、rt12: Juniper MX204 (JUNOS 22.1R1.10) rt04: Juniper PTX10001-36MR (JUNOS 21.4R1.15-EVO) SR OS rt05、rt07、rt09、rt11、rt13: Nokia 7750 SR-1 (SR OS 23.3.R1) SR OS の IGP や SR の設定は 第12回 の記事で紹介したため割愛します。下記の設定および確認を順に行います。 EVI と CE 向けポート設定と状態確認 BGP の設定 LP の設定 経路の確認 疎通試験 EVI と CE 向けポート設定 まず、PE で EVI と CE 向けポートを設定します。各 EVI は MP-BGP EVPN にて 64999:<EVI 番号> の RT を用いて経路交換します。 PE (例: rt13) [gl:/configure policy-options] A:user@rt13# info community "comm-3600" { member "target:64999:3600" { } } policy-statement "vsi-export-3600" { entry 10 { action { action-type accept community { add ["comm-3600"] } } } } policy-statement "vsi-import-3600" { entry 10 { from { community { name "comm-3600" } } action { action-type accept } } } [gl:/configure service] A:user@rt13# info customer "3600" { } system { bgp { evpn { ethernet-segment "esi-26-1/2/c16/1" { admin-state enable esi 0x02000000010000002616 multi-homing-mode single-active association { port 1/2/c16/1 { } } } } } } vpls "3600" { admin-state enable customer "3600" bgp 1 { route-distinguisher "10.255.2.26:3600" vsi-import ["vsi-import-3600"] vsi-export ["vsi-export-3600"] } bgp-evpn { evi 3600 mpls 1 { admin-state enable auto-bind-tunnel { resolution any } } } sap 1/2/c16/1:3600 { admin-state enable } } EVI と CE 向けポートの状態確認 EVI と CE 向けポートが紐づき、また Admin/Operation 共に up していることが確認できます。 [/] A:user@rt13# show service id 3600 sap =============================================================================== SAP(Summary), Service 3600 =============================================================================== PortId SvcId Ing. Ing. Egr. Egr. Adm Opr QoS Fltr QoS Fltr ------------------------------------------------------------------------------- 1/2/c16/1:3600 3600 1 none 1 none Up Up ------------------------------------------------------------------------------- Number of SAPs : 1 ------------------------------------------------------------------------------- =============================================================================== BGP の設定 L2VPN 経路を広告するため PE と ASBR で MP-BGP EVPN を設定します。 PE (例: rt13) [gl:/configure router "Base" bgp] A:user@rt13# info rapid-withdrawal true family { evpn true } rapid-update { evpn true } group "iBGP" { peer-as 65002 local-address 10.255.2.2 family { evpn true } } neighbor "10.255.2.6" { admin-state enable group "iBGP" } neighbor "10.255.2.7" { admin-state enable group "iBGP" } ASBR (例: rt07) [gl:/configure router "Base" bgp] A:user@rt07# info inter-as-vpn true rapid-withdrawal true family { evpn true } ebgp-default-reject-policy { import false export false } rapid-update { evpn true } next-hop-resolution { labeled-routes { transport-tunnel { family vpn { resolution any } } } } group "65002" { vpn-apply-import true peer-as 65002 bfd-liveness true family { evpn true } } group "iBGP" { peer-as 65001 local-address 10.255.1.7 family { evpn true } } neighbor "10.100.3.2" { group "65002" } neighbor "10.255.1.1" { group "iBGP" } neighbor "10.255.1.2" { group "iBGP" } Local Preference(LP) の設定 EVI ごとに通過する ASBR を制御するため、ASBR で LP を設定します。 本検証では RT ごとに通過させたい ASBR への経路には LP 300 を、通過させたくない ASBR への経路には LP 50 を明示的に設定します。 IOS XR ASBR 間 rt06 route-policy lp-for-evpn if extcommunity rt matches-any (64999:3600) then set local-preference 300 elseif extcommunity rt matches-any (64999:3700) then set local-preference 50 else pass endif end-policy router bgp 65001 neighbor 10.100.1.2 address-family l2vpn evpn route-policy lp-for-evpn in ! ! rt08 route-policy lp-for-evpn if extcommunity rt matches-any (64999:3600) then set local-preference 300 elseif extcommunity rt matches-any (64999:3700) then set local-preference 50 else pass endif end-policy router bgp 65002 neighbor 10.100.1.1 address-family l2vpn evpn route-policy lp-for-evpn in ! ! SR OS ASBR 間 rt07 [gl:/configure policy-options] A:user@rt07# info community "lp-high-grp" { member "target:64999:3700" { } } community "lp-low-grp" { member "target:64999:3600" { } } policy-statement "lp-for-evpn" { entry 1 { from { community { name "lp-high-grp" } } action { action-type accept local-preference 300 } } entry 2 { from { community { name "lp-low-grp" } } action { action-type accept local-preference 50 } } } [gl:/configure router "Base" bgp] A:user@rt07# info vpn-apply-export true vpn-apply-import true group "65002" { import { policy ["lp-for-evpn"] } } rt09 [gl:/configure policy-options] A:user@rt09# info community "lp-high-grp" { member "target:64999:3700" { } } community "lp-low-grp" { member "target:64999:3600" { } } policy-statement "lp-for-evpn" { entry 1 { from { community { name "lp-high-grp" } } action { action-type accept local-preference 300 } } entry 2 { from { community { name "lp-low-grp" } } action { action-type accept local-preference 50 } } } [gl:/configure router "Base" bgp] A:user@rt09# info vpn-apply-export true vpn-apply-import true group "65001" { import { policy ["lp-for-evpn"] } } 経路の確認 各 PE で構成に従った経路を学習しているかを確認します。 type1 経路、type3 経路が交換されていること、また EVI ごとにそれぞれ nexthop が適切な ASBR となっていることが確認できます。 EVI 3600 AS65001 側 PE (rt02) user@rt02> show route table evpn-3600.evpn.0 evpn-3600.evpn.0: 9 destinations, 17 routes (9 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both 1:10.255.1.2:3600::0207::0/192 AD/EVI *[EVPN/170] 15w4d 20:10:12 Indirect 1:10.255.2.26:3600::02000000010000002616::0/192 AD/EVI *[BGP/170] 2w2d 16:54:52, localpref 300, from 10.255.1.3 AS path: 65002 I, validation-state: unverified to 10.1.3.2 via et-0/0/1.0, Push 16007 > to 10.1.8.2 via et-0/0/0.0, Push 16007 to 10.1.16.2 via et-0/0/2.0, Push 16007 [BGP/170] 2w2d 16:54:52, localpref 300, from 10.255.1.4 AS path: 65002 I, validation-state: unverified to 10.1.3.2 via et-0/0/1.0, Push 16007 > to 10.1.8.2 via et-0/0/0.0, Push 16007 to 10.1.16.2 via et-0/0/2.0, Push 16007 [BGP/170] 2w2d 16:54:52, localpref 300, from 10.255.1.20 AS path: 65002 I, validation-state: unverified to 10.1.3.2 via et-0/0/1.0, Push 16007 > to 10.1.8.2 via et-0/0/0.0, Push 16007 to 10.1.16.2 via et-0/0/2.0, Push 16007 1:10.255.2.26:3600::02000000010000002616::FFFF:FFFF/192 AD/ESI *[BGP/170] 2w2d 16:54:52, localpref 300, from 10.255.1.3 AS path: 65002 I, validation-state: unverified to 10.1.3.2 via et-0/0/1.0, Push 16007 > to 10.1.8.2 via et-0/0/0.0, Push 16007 to 10.1.16.2 via et-0/0/2.0, Push 16007 [BGP/170] 2w2d 16:54:52, localpref 300, from 10.255.1.4 AS path: 65002 I, validation-state: unverified to 10.1.3.2 via et-0/0/1.0, Push 16007 > to 10.1.8.2 via et-0/0/0.0, Push 16007 to 10.1.16.2 via et-0/0/2.0, Push 16007 [BGP/170] 2w2d 16:54:52, localpref 300, from 10.255.1.20 AS path: 65002 I, validation-state: unverified to 10.1.3.2 via et-0/0/1.0, Push 16007 > to 10.1.8.2 via et-0/0/0.0, Push 16007 to 10.1.16.2 via et-0/0/2.0, Push 16007 2:10.255.1.2:3600::0::00:0c:29:f0:5a:09/304 MAC/IP *[EVPN/170] 14w5d 01:18:41 Indirect 2:10.255.2.26:3600::0::00:0c:29:1f:dd:dc/304 MAC/IP *[BGP/170] 00:00:26, localpref 300, from 10.255.1.3 AS path: 65002 I, validation-state: unverified to 10.1.3.2 via et-0/0/1.0, Push 16007 to 10.1.8.2 via et-0/0/0.0, Push 16007 > to 10.1.16.2 via et-0/0/2.0, Push 16007 [BGP/170] 00:00:26, localpref 300, from 10.255.1.4 AS path: 65002 I, validation-state: unverified to 10.1.3.2 via et-0/0/1.0, Push 16007 to 10.1.8.2 via et-0/0/0.0, Push 16007 > to 10.1.16.2 via et-0/0/2.0, Push 16007 [BGP/170] 00:00:26, localpref 300, from 10.255.1.20 AS path: 65002 I, validation-state: unverified to 10.1.3.2 via et-0/0/1.0, Push 16007 to 10.1.8.2 via et-0/0/0.0, Push 16007 > to 10.1.16.2 via et-0/0/2.0, Push 16007 2:10.255.1.2:3600::0::00:0c:29:f0:5a:09::192.168.32.1/304 MAC/IP *[EVPN/170] 14w5d 01:18:36 Indirect 2:10.255.1.2:3600::0::00:0c:29:f0:5a:09::192.168.33.1/304 MAC/IP *[EVPN/170] 1w3d 19:40:14 Indirect 3:10.255.1.2:3600::0::10.255.1.2/248 IM *[EVPN/170] 17w3d 18:54:21 Indirect 3:10.255.2.26:3600::0::10.255.2.26/248 IM *[BGP/170] 2w2d 16:54:52, localpref 300, from 10.255.1.3 AS path: 65002 I, validation-state: unverified to 10.1.3.2 via et-0/0/1.0, Push 16007 to 10.1.8.2 via et-0/0/0.0, Push 16007 > to 10.1.16.2 via et-0/0/2.0, Push 16007 [BGP/170] 2w2d 16:54:52, localpref 300, from 10.255.1.4 AS path: 65002 I, validation-state: unverified to 10.1.3.2 via et-0/0/1.0, Push 16007 to 10.1.8.2 via et-0/0/0.0, Push 16007 > to 10.1.16.2 via et-0/0/2.0, Push 16007 [BGP/170] 2w2d 16:54:52, localpref 300, from 10.255.1.20 AS path: 65002 I, validation-state: unverified to 10.1.3.2 via et-0/0/1.0, Push 16007 to 10.1.8.2 via et-0/0/0.0, Push 16007 > to 10.1.16.2 via et-0/0/2.0, Push 16007 AS65002 側 PE (rt13) [/] A:user@rt13# show router bgp routes evpn auto-disc detail =============================================================================== BGP Router ID:10.255.2.26 AS:65002 Local AS:65002 =============================================================================== Legend - Status codes : u - used, s - suppressed, h - history, d - decayed, * - valid l - leaked, x - stale, > - best, b - backup, p - purge Origin codes : i - IGP, e - EGP, ? - incomplete =============================================================================== BGP EVPN Auto-Disc Routes =============================================================================== Original Attributes Network : n/a Nexthop : 10.255.2.1 Path Id : None From : 10.255.2.1 Res. Nexthop : 10.2.17.1 Local Pref. : 300 Interface Name : to_ar-rt10 Aggregator AS : None Aggregator : None Atomic Aggr. : Not Atomic MED : None AIGP Metric : None IGP Cost : 30 Connector : None Community : target:64999:3600 Cluster : 0.0.0.1 Originator Id : 10.255.2.1 Peer Router Id : 10.255.2.25 Flags : Valid IGP TieBreakReason : PeerIP MP Exc. Reason : NotNextHopDiverse Route Source : Internal AS-Path : 65001 EVPN type : AUTO-DISC ESI : 00:00:00:00:00:00:00:00:02:07 Tag : 0 Route Dist. : 10.255.1.2:3600 MPLS Label : LABEL 60946 Route Tag : 0 Neighbor-AS : 65001 DB Orig Val : N/A Final Orig Val : N/A Source Class : 0 Dest Class : 0 Add Paths Send : Default Last Modified : 52d23h37m Modified Attributes Network : n/a Nexthop : 10.255.2.1 Path Id : None From : 10.255.2.1 Res. Nexthop : 10.2.17.1 Local Pref. : 300 Interface Name : to_ar-rt10 Aggregator AS : None Aggregator : None Atomic Aggr. : Not Atomic MED : None AIGP Metric : None IGP Cost : 30 Connector : None Community : target:64999:3600 Cluster : 0.0.0.1 Originator Id : 10.255.2.1 Peer Router Id : 10.255.2.25 Flags : Valid IGP TieBreakReason : PeerIP MP Exc. Reason : NotNextHopDiverse Route Source : Internal AS-Path : 65001 EVPN type : AUTO-DISC ESI : 00:00:00:00:00:00:00:00:02:07 Tag : 0 Route Dist. : 10.255.1.2:3600 MPLS Label : LABEL 60946 Route Tag : 0 Neighbor-AS : 65001 DB Orig Val : N/A Final Orig Val : N/A Source Class : 0 Dest Class : 0 Add Paths Send : Default Last Modified : 52d23h37m (snip) ------------------------------------------------------------------------------- ------------------------------------------------------------------------------- Routes : 8 =============================================================================== [/] A:user@rt26# show router bgp routes evpn incl-mcast =============================================================================== BGP Router ID:10.255.2.26 AS:65002 Local AS:65002 =============================================================================== Legend - Status codes : u - used, s - suppressed, h - history, d - decayed, * - valid l - leaked, x - stale, > - best, b - backup, p - purge Origin codes : i - IGP, e - EGP, ? - incomplete =============================================================================== BGP EVPN Inclusive-Mcast Routes =============================================================================== Flag Route Dist. OrigAddr Tag NextHop ------------------------------------------------------------------------------- u*>i 10.255.1.2:3600 10.255.1.2 0 10.255.2.1 *i 10.255.1.2:3600 10.255.1.2 0 10.255.2.1 i 10.255.2.26:3600 10.255.2.26 0 10.255.2.26 i 10.255.2.26:3600 10.255.2.26 0 10.255.2.26 ------------------------------------------------------------------------------- Routes : 4 =============================================================================== EVI 3700 AS65001 側 PE (rt01) ※ type3 経路の nexthop が rt07 となっていませんが、こちらは後述の制約事項で扱います。 RP/0/RSP0/CPU0:rt01#show evpn evi vpn-id 3700 ead Mon Jun 19 11:49:14.279 JST VPN-ID Encap Ethernet Segment Id EtherTag Nexthop Label SID ---------- ------ ------------------------ ---------- --------------------------------------- -------- --------------------------------------- 3700 MPLS 0000.0000.0000.0000.0132 0x0 :: 24019 3700 MPLS 0000.0000.0000.0000.1607 0x0 10.255.1.22 507880 3700 MPLS 0000.0000.0000.0000.1607 0xffffffff 10.255.1.22 0 RP/0/RSP0/CPU0:rt01#show evpn evi vpn-id 3700 inclusive-multicast detail Mon Jun 19 11:48:06.327 JST VPN-ID Encap EtherTag Originating IP ---------- ------ ---------- ---------------------------------------- 3700 MPLS 0 10.255.1.1 TEPid : 0xffffffff PMSI Type: 6 Nexthop: :: Label : 26015 SR-TE Info: N/A Source : Local E-Tree : Root 3700 MPLS 0 10.255.2.8 TEPid : 0x02000002 PMSI Type: 6 Nexthop: 10.255.2.8 Label : 507882 SR-TE Info: N/A Source : Remote E-Tree : Root AS65002 側 PE (rt12) user@rt12> show route table evpn-3700.evpn.0 evpn-3700.evpn.0: 8 destinations, 12 routes (8 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both 1:10.255.1.1:1::0132::FFFF:FFFF/192 AD/ESI *[BGP/170] 2d 00:11:42, localpref 300, from 10.255.2.5 AS path: 65001 I, validation-state: unverified to 10.2.4.1 via et-0/0/1.0, Push 16009 > to 10.2.16.2 via et-0/0/2.0, Push 16009 [BGP/170] 2d 00:11:42, localpref 300, from 10.255.2.25 AS path: 65001 I, validation-state: unverified to 10.2.4.1 via et-0/0/1.0, Push 16009 > to 10.2.16.2 via et-0/0/2.0, Push 16009 1:10.255.1.1:3700::0132::0/192 AD/EVI *[BGP/170] 2d 00:11:42, localpref 300, from 10.255.2.5 AS path: 65001 I, validation-state: unverified > to 10.2.4.1 via et-0/0/1.0, Push 16009 to 10.2.16.2 via et-0/0/2.0, Push 16009 [BGP/170] 2d 00:11:42, localpref 300, from 10.255.2.25 AS path: 65001 I, validation-state: unverified > to 10.2.4.1 via et-0/0/1.0, Push 16009 to 10.2.16.2 via et-0/0/2.0, Push 16009 1:10.255.2.8:3700::1607::0/192 AD/EVI *[EVPN/170] 14w1d 00:55:46 Indirect 2:10.255.1.1:3700::0::00:0c:29:f0:5a:13/304 MAC/IP *[BGP/170] 2d 00:11:42, localpref 300, from 10.255.2.5 AS path: 65001 I, validation-state: unverified > to 10.2.4.1 via et-0/0/1.0, Push 16009 to 10.2.16.2 via et-0/0/2.0, Push 16009 [BGP/170] 2d 00:11:42, localpref 300, from 10.255.2.25 AS path: 65001 I, validation-state: unverified > to 10.2.4.1 via et-0/0/1.0, Push 16009 to 10.2.16.2 via et-0/0/2.0, Push 16009 2:10.255.2.8:3700::0::00:0c:29:1f:dd:c8/304 MAC/IP *[EVPN/170] 00:11:41 Indirect 2:10.255.2.8:3700::0::00:0c:29:1f:dd:c8::192.168.33.3/304 MAC/IP *[EVPN/170] 00:06:33 Indirect 3:10.255.1.1:3700::0::10.255.1.1/248 IM *[BGP/170] 2d 00:11:42, localpref 300, from 10.255.2.5 AS path: 65001 I, validation-state: unverified to 10.2.4.1 via et-0/0/1.0, Push 16009 > to 10.2.16.2 via et-0/0/2.0, Push 16009 [BGP/170] 2d 00:11:42, localpref 300, from 10.255.2.25 AS path: 65001 I, validation-state: unverified to 10.2.4.1 via et-0/0/1.0, Push 16009 > to 10.2.16.2 via et-0/0/2.0, Push 16009 3:10.255.2.8:3700::0::10.255.2.8/248 IM *[EVPN/170] 15w6d 23:38:46 Indirect 疎通試験 各 EVI について、ce01 から ping で ce02 への疎通確認を行います。 EVI 3600 (192.168.32.0/24) user@ce01:~$ ping 192.168.32.2 -c 5 PING 192.168.32.2 (192.168.32.2) 56(84) bytes of data. 64 bytes from 192.168.32.2: icmp_seq=1 ttl=64 time=1.92 ms 64 bytes from 192.168.32.2: icmp_seq=2 ttl=64 time=2.02 ms 64 bytes from 192.168.32.2: icmp_seq=3 ttl=64 time=1.92 ms 64 bytes from 192.168.32.2: icmp_seq=4 ttl=64 time=1.96 ms 64 bytes from 192.168.32.2: icmp_seq=5 ttl=64 time=2.10 ms --- 192.168.32.2 ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 4006ms rtt min/avg/max/mdev = 1.919/1.984/2.096/0.067 ms EVI 3700 (192.168.33.0/24) user@ce01:~$ ping 192.168.33.2 -c 5 PING 192.168.33.2 (192.168.33.2) 56(84) bytes of data. 64 bytes from 192.168.33.2: icmp_seq=1 ttl=64 time=1.66 ms 64 bytes from 192.168.33.2: icmp_seq=2 ttl=64 time=1.50 ms 64 bytes from 192.168.33.2: icmp_seq=3 ttl=64 time=1.59 ms 64 bytes from 192.168.33.2: icmp_seq=4 ttl=64 time=1.49 ms 64 bytes from 192.168.33.2: icmp_seq=5 ttl=64 time=1.46 ms --- 192.168.33.2 ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 4007ms rtt min/avg/max/mdev = 1.461/1.541/1.660/0.073 ms パケットが転送でき、VPN が構築できていることが確認できました。 以上、2パターンの組み合わせで L2VPN が構築できている事が確認できました。 制約事項 2023/8/21 現在、L2VPN の Option-B シグナリングは IOS XR と SR OS で可能です。 しかし、相互接続において IOS XR と SR OS で Option-B によるシグナリング時の type3 経路 (IMET route) の解釈違いがありました。 解釈違いによって IOS XR を PE、SR OS を ASBR とする組み合わせの場合に AS を越えて BUM トラフィックが通らないことにご注意ください。 まとめ IOS XR 、Junos と SR OS の Multi-vendor 環境における Multi-AS L2VPN の検証結果を紹介しました。 次回の記事では、同様の Multi-vendor 環境における Color-Based TE について紹介予定です。 (2023/9/4 追記) 公開しました: [Multi-AS Segment Routing 検証連載 #14] Color-Based Steering using IOS XR, Junos and SR OS
TOC サマリ 概要 検証 検証項目とトポロジー 基本設定 IS-IS - 設定 IS-IS - 動作確認 VRF と MP-BGP VPNv4 - 機器設定 MP-BGP VPNv4 - 動作確認 LP の設定 cust-c の動作確認 cust-d の動作確認 cust-e の動作確認 まとめ サマリ Multi-AS で構成されるネットワークにおいて、SR-MPLS + VPNv4 による L3VPN を実現 IOS XR + Junos + SR OS の Multi-vendor 環境で動作検証に成功 この記事は Multi-AS SR 検証連載の第 12 回です。目次は こちら 概要 イノベーションセンターの岩田です。普段の業務では Multi-AS Segment Routing に関する技術検証や、ベンチャー企業への技術支援でスマートフォンアプリケーション開発業務などを行なっています。 第1回 、 第2回 の記事で IOS XR + Junos の 2 つのベンダー機器で構成される L3VPN についてご紹介しましたが、今回新たに Nokia SR OS(Service Router Operating System)を加えた 3 つのベンダー機器での L3VPN 相互動作確認をご紹介します。 L3VPN や Segment Routing など今回扱う技術の説明は、 第1回 、 第2回 記事の概要章にて紹介しているので、そちらをご参照ください。 検証 以降は L3VPN の検証例を実際の設定例を添えつつ紹介します。 IOS XR、Junos の設定例は 第1回 や 第2回 の記事で紹介したため本記事では割愛し、SR OS の設定例を中心に紹介します。 検証項目とトポロジー 本記事の検証では、Inter-AS Option B の L3VPN について、SR OS と 各ベンダー(SR OS 自身を含む)間の互換性確認を目的とします。 そのため、以下の検証項目を設定します。 項目1: SR OS(PE)と SR OS(PE)間で L3VPN が構築できるかを確認する 項目2: SR OS(PE)と IOS XR(PE)間で L3VPN が構築できるかを確認する 項目3: SR OS(PE)と Junos(PE)間で L3VPN が構築できるかを確認する 項目4: Inter-AS Option B 構成を構築する際に SR OS を ASBR として利用できるかを確認する 上記の確認のため、本記事では下図のようなトポロジーからなるネットワークを用いて検証します。 検証項目と、構築する L3VPN を構成する VRF と機器の組み合わせを以下の表に示します。 検証項目 VRF AS65001 PE → → ASBR-ASBR → → AS65002 PE 項目 2 cust-c IOS XR (rt01) Junos (rt05、 rt09) SR OS (rt13) 項目 3 cust-d Junos (rt02) IOS XR (rt04、 rt08) SR OS (rt13) 項目 1、 4 cust-e IOS XR (rt01) SR OS (rt06、 rt10) Junos (rt12) 使用する機器は以下の通りです。 rt01、rt04、rt07、rt08: Cisco IOS XR 7.4.1 rt02、rt05、rt09、rt12: Juniper Junos OS 21.3R1.9 rt06、rt10、rt13: Nokia SR OS 22.7.R1 この後は下記の流れに従って設定を紹介します。 IS-IS 設定と状態確認 VRF と MP-BGP 設定と状態確認 PE 間の ping 疎通試験 基本設定 IS-IS - 設定 IS-IS の SR 拡張を利用し、SR-MPLS の SID 情報を広告します。 SR OS(例: rt13) A:admin@rt13# /info router isis admin-state enable advertise-router-capability as level-capability 2 traffic-engineering true area-address [49.0000] segment-routing { admin-state enable prefix-sid-range { global } } interface "system" { } interface "to_rt08" { interface-type point-to-point level-capability 2 } interface "to_rt09" { interface-type point-to-point level-capability 2 } interface "to_rt10" { interface-type point-to-point level-capability 2 } level 2 { wide-metrics-only true } [ro:/configure] A:admin@rt13# /info router mpls-labels static-label-range 0 sr-labels { start 16000 end 23999 } [ro:/configure] A:admin@rt13# /info router segment-routing sr-mpls { prefix-sids "system" { ipv4-sid { index 13 } } } IS-IS - 動作確認 IS-IS ネイバーの状態と SID Table を確認します。 IS-IS ネイバーの状態の確認 [ro:/configure] A:admin@rt13# /show router isis adjacency =============================================================================== Rtr Base ISIS Instance 0 Adjacency =============================================================================== System ID Usage State Hold Interface MT-ID ------------------------------------------------------------------------------- rt08 L2 Up 25 to_rt08 0 rt09 L2 Up 25 to_rt09 0 rt10 L2 Up 20 to_rt10 0 ------------------------------------------------------------------------------- Adjacencies : 3 =============================================================================== SID Table の確認 [/] A:admin@rt13# /show router isis prefix-sids =============================================================================== Rtr Base ISIS Instance 0 Prefix/SID Table =============================================================================== Prefix SID Lvl/Typ SRMS AdvRtr Shared MT Flags ------------------------------------------------------------------------------- 10.255.2.2/32 12 2/Int. N rt12 N.A. 0 N 10.255.2.3/32 13 2/Int. N rt13 Yes 0 NnP 10.255.2.4/32 8 2/Int. N rt08 N.A. 0 N 10.255.2.5/32 9 2/Int. N rt09 N.A. 0 N 10.255.2.6/32 10 2/Int. N rt10 N.A. 0 NnP 10.255.2.7/32 14 2/Int. N rt14 N.A. 0 N ------------------------------------------------------------------------------- No. of Prefix/SIDs: 6 (6 unique) ------------------------------------------------------------------------------- SRMS: Y/N = prefix SID advertised by SR Mapping Server (Y) or not (N) S = SRMS prefix SID is selected to be programmed Flags: R = Re-advertisement N = Node-SID nP = no penultimate hop POP E = Explicit-Null V = Prefix-SID carries a value L = value/index has local significance Shared: Yes = local shared Node-SID No = not a local shared Node-SID N.A. = not applicable for Remote prefix-sid =============================================================================== VRF と MP-BGP VPNv4 - 機器設定 cust-c、d、e の VRF 設定と、経路を広告する MP-BGP L3VPN を設定します。 VPN の各パラメータは下記の通りです。 SR Domain 1 AS 番号: 65001 VRF 300(cust-c): RD/RT 65001:300 AS 間での VPN 経路広告用 RT: 64999:300 VRF 400(cust-d): RD/RT 65001:400 AS 間での VPN 経路広告用 RT: 64999:400 VRF 500(cust-e): RD/RT 65001:500 AS 間での VPN 経路広告用 RT: 64999:500 SR Domain 2 AS 番号: 65002 VRF 300(cust-c): RD/RT 65002:300 AS 間での VPN 経路広告用 RT: 64999:300 VRF 400(cust-d): RD/RT 65002:400 AS 間での VPN 経路広告用 RT: 64999:400 VRF 500(cust-e): RD/RT 65002:500 AS 間での VPN 経路広告用 RT: 64999:500 PE の設定(例: rt13、SR OS) A:admin@rt13# info policy-options community "shared-comm-cust-c" { member "target:64999:300" { } } community "shared-comm-cust-d" { member "target:64999:400" { } } policy-statement "vrf-export-cust-c" { entry 10 { action { action-type accept community { add ["shared-comm-cust-c"] } } } } policy-statement "vrf-export-cust-d" { entry 10 { action { action-type accept community { add ["shared-comm-cust-d"] } } } } policy-statement "vrf-import-cust-c" { entry 10 { from { community { name "shared-comm-cust-c" } } action { action-type accept } } } policy-statement "vrf-import-cust-d" { entry 10 { from { community { name "shared-comm-cust-d" } } action { action-type accept } } } A:admin@rt13# info service customer "cust-c" { customer-id 300 } customer "cust-d" { customer-id 400 } vprn "300" { admin-state enable customer "cust-c" bgp-ipvpn { mpls { admin-state enable route-distinguisher "65002:300" vrf-import { policy ["vrf-import-cust-c"] } vrf-export { policy ["vrf-export-cust-c"] } auto-bind-tunnel { resolution any } } } interface "to_cust-c" { admin-state enable ipv4 { primary { address 192.168.1.254 prefix-length 24 } } sap 1/1/c4/1:0 { admin-state enable } } } vprn "400" { admin-state enable customer "cust-d" bgp-ipvpn { mpls { admin-state enable route-distinguisher "65002:400" vrf-import { policy ["vrf-import-cust-d"] } vrf-export { policy ["vrf-export-cust-d"] } auto-bind-tunnel { resolution any } } } interface "to_cust-d" { admin-state enable ipv4 { primary { address 192.168.1.254 prefix-length 24 } } sap 1/1/c5/1:0 { admin-state enable } } } ASBR の設定(例: rt10、SR OS) A:admin@rt13# info router bgp vpn-apply-export true inter-as-vpn true rapid-withdrawal true family { vpn-ipv4 true } ebgp-default-reject-policy { import false export false } rapid-update { vpn-ipv4 true } next-hop-resolution { labeled-routes { transport-tunnel { family vpn { resolution any } } } } group "65001" { peer-as 65001 family { vpn-ipv4 true } } group "iBGP" { peer-as 65002 local-address 10.255.2.6 family { vpn-ipv4 true } } neighbor "10.100.3.1" { group "65001" local-address 10.100.3.2 } neighbor "10.255.2.7" { group "iBGP" } MP-BGP VPNv4 - 動作確認 下記 3 ステップで L3VPN の経路学習と転送動作を確認します。 今回は各ベンダーの ASBR の組で動作確認をするために ASBR へ LP を設定し、VRF ごとに ASBR を選択します。 動作確認したい ASBR の組が選択されるように LP を調整する PE で BGP から受信した経路を確認 ping による疎通確認 LP の設定 以下の設定で LP を調整し、cust-c、d、e に対応する ASBR を選択します。 cust-c(rt04、IOS XR) route-policy lp-high if extcommunity rt matches-any (64999:400) then set local-preference 300 endif end-policy ! router bgp 65001 neighbor-group ibgp address-family vpnv4 unicast route-policy lp-high out ! cust-d(rt05、Junos) set policy-options community CUST-C-SHARED members target:64999:300 set policy-options policy-statement lp-high term 1 from community CUST-C-SHARED set policy-options policy-statement lp-high term 1 then local-preference 300 set policy-options policy-statement lp-high term 1 then accept set protocols bgp group ibgp export lp-high cust-e(rt06、SR OS) A:admin@rt06# info policy-options community "CUST-E-SHARED" { member "target:64999:500" { } } policy-statement "lp-high" { entry 1 { from { community { name "CUST-E-SHARED" } } action { action-type accept local-preference 300 } } } A:admin@rt06# info router bgp vpn-apply-export true group "iBGP" { export { policy ["lp-high"] } } 動作確認 以下のように cust-c、d、e で適切な ASBR が選択されていることが確認できました。 RP/0/RP0/CPU0:rt07#show bgp vpnv4 unicast Fri Feb 3 15:50:04.866 JST BGP router identifier 10.255.1.7, local AS number 65001 BGP generic scan interval 60 secs Non-stop routing is enabled BGP table state: Active Table ID: 0x0 RD version: 0 BGP main routing table version 181 BGP NSR Initial initsync version 1 (Reached) BGP NSR/ISSU Sync-Group versions 0/0 BGP scan interval 60 secs Status codes: s suppressed, d damped, h history, * valid, > best i - internal, r RIB-failure, S stale, N Nexthop-discard Origin codes: i - IGP, e - EGP, ? - incomplete Network Next Hop Metric LocPrf Weight Path Route Distinguisher: 65001:300 *>i192.168.0.0/24 10.255.1.1 0 100 0 ? Route Distinguisher: 65001:400 *>i192.168.0.0/24 10.255.1.2 100 0 i Route Distinguisher: 65001:500 *>i192.168.0.0/24 10.255.1.1 0 100 0 ? Route Distinguisher: 65002:300 *>i192.168.1.0/24 10.255.1.5 300 0 65002 i *>i192.168.1.254/32 10.255.1.5 300 0 65002 i Route Distinguisher: 65002:400 *>i192.168.1.0/24 10.255.1.4 300 0 65002 i *>i192.168.1.254/32 10.255.1.4 300 0 65002 i Route Distinguisher: 65002:500 *>i192.168.1.0/24 10.255.1.6 300 0 65002 i cust-c の動作確認 rt01(PE)で対向 AS から広告された VRF 経路を受け取れていることを確認します。 RP/0/RP0/CPU0:rt01#show route vrf cust-c Fri Feb 3 14:03:42.980 JST Codes: C - connected, S - static, R - RIP, B - BGP, (>) - Diversion path D - EIGRP, EX - EIGRP external, O - OSPF, IA - OSPF inter area N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2 E1 - OSPF external type 1, E2 - OSPF external type 2, E - EGP i - ISIS, L1 - IS-IS level-1, L2 - IS-IS level-2 ia - IS-IS inter area, su - IS-IS summary null, * - candidate default U - per-user static route, o - ODR, L - local, G - DAGR, l - LISP A - access/subscriber, a - Application route M - mobile route, r - RPL, t - Traffic Engineering, (!) - FRR Backup path Gateway of last resort is not set C 192.168.0.0/24 is directly connected, 6d20h, GigabitEthernet0/0/0/3 L 192.168.0.254/32 is directly connected, 6d20h, GigabitEthernet0/0/0/3 B 192.168.1.0/24 [200/0] via 10.255.1.5 (nexthop in vrf default), 1d23h B 192.168.1.254/32 [200/0] via 10.255.1.5 (nexthop in vrf default), 1d23h ping で疎通確認を行なってみます。 RP/0/RP0/CPU0:rt01#ping 192.168.1.254 vrf cust-c Fri Feb 3 16:07:13.844 JST Type escape sequence to abort. Sending 5, 100-byte ICMP Echos to 192.168.1.254, timeout is 2 seconds: !!!!! Success rate is 100 percent (5/5), round-trip min/avg/max = 3/8/14 ms RP/0/RP0/CPU0:ar1018-rt01#traceroute 192.168.1.254 vrf cust-c Fri Feb 3 16:07:17.423 JST Type escape sequence to abort. Tracing the route to 192.168.1.254 1 10.1.2.2 [MPLS: Label 62 Exp 0] 14 msec 7 msec 14 msec 2 10.100.2.2 [MPLS: Label 31 Exp 0] 4 msec 11 msec 4 msec 3 192.168.1.254 8 msec 13 msec 3 msec パケットが転送でき、VPN が構築できていることが確認できました。 cust-d の動作確認 rt02(PE)で対向 AS から広告された VRF 経路を受け取れていることを確認します。 user@rt02> ping 192.168.1.254 routing-instance CUST-D PING 192.168.1.254 (192.168.1.254): 56 data bytes 64 bytes from 192.168.1.254: icmp_seq=0 ttl=62 time=2.849 ms 64 bytes from 192.168.1.254: icmp_seq=1 ttl=62 time=2.507 ms 64 bytes from 192.168.1.254: icmp_seq=2 ttl=62 time=3.050 ms ^C --- 192.168.1.254 ping statistics --- 3 packets transmitted, 3 packets received, 0% packet loss round-trip min/avg/max/stddev = 2.507/2.802/3.050/0.224 ms user@rt02> traceroute 192.168.1.254 routing-instance CUST-D no-resolve traceroute to 192.168.1.254 (192.168.1.254), 30 hops max, 52 byte packets 1 10.1.4.2 11.656 ms 2.224 ms 2.109 ms MPLS Label=24018 CoS=0 TTL=1 S=1 2 10.100.1.2 3.361 ms 10.787 ms 2.800 ms MPLS Label=24017 CoS=0 TTL=1 S=1 3 192.168.1.254 2.290 ms 1.691 ms 1.632 ms パケットが転送でき、VPN が構築できていることが確認できました。 cust-e の動作確認 rt01(PE)で対向 AS から広告された VRF 経路を受け取れていることを確認します。 RP/0/RP0/CPU0:rt01#show route vrf cust-e Fri Feb 3 14:03:54.438 JST Codes: C - connected, S - static, R - RIP, B - BGP, (>) - Diversion path D - EIGRP, EX - EIGRP external, O - OSPF, IA - OSPF inter area N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2 E1 - OSPF external type 1, E2 - OSPF external type 2, E - EGP i - ISIS, L1 - IS-IS level-1, L2 - IS-IS level-2 ia - IS-IS inter area, su - IS-IS summary null, * - candidate default U - per-user static route, o - ODR, L - local, G - DAGR, l - LISP A - access/subscriber, a - Application route M - mobile route, r - RPL, t - Traffic Engineering, (!) - FRR Backup path Gateway of last resort is not set C 192.168.0.0/24 is directly connected, 6d19h, GigabitEthernet0/0/0/4 L 192.168.0.254/32 is directly connected, 6d19h, GigabitEthernet0/0/0/4 B 192.168.1.0/24 [200/0] via 10.255.1.6 (nexthop in vrf default), 00:37:18 ping で疎通確認を行なってみます。 RP/0/RP0/CPU0:rt01#ping 192.168.1.254 vrf cust-e Fri Feb 3 16:07:29.739 JST Type escape sequence to abort. Sending 5, 100-byte ICMP Echos to 192.168.1.254, timeout is 2 seconds: !!!!! Success rate is 100 percent (5/5), round-trip min/avg/max = 3/7/13 ms RP/0/RP0/CPU0:ar1018-rt01#traceroute 192.168.1.254 vrf cust-e Fri Feb 3 16:07:33.584 JST Type escape sequence to abort. Tracing the route to 192.168.1.254 1 10.100.3.1 [MPLS: Labels 16006/524284 Exp 0] 11 msec 14 msec 5 msec 2 10.2.6.1 [MPLS: Label 524276 Exp 0] 12 msec 4 msec 7 msec 3 192.168.1.254 13 msec 6 msec 16 msec パケットが転送でき、VPN が構築できていることが確認できました。 以上で全ての組で VPN が構築できている事が確認できました。 まとめ IOS XR 、Junos と SR OS の Multi-vendor 環境における Multi-AS L3VPN の検証結果を紹介しました。 次回の記事では、これらの Multi-vendor 環境における Multi-AS L2VPN について紹介予定です。 (2023/8/21 追記) 公開しました: [Multi-AS Segment Routing 検証連載 #13] SR-MPLS L2VPN(EVPN) using IOS XR, Junos and SR OS
みなさんこんにちは、イノベーションセンターの @Mahito です。 普段は社内のエンジニアが働きやすくなることを目標に、コーポレートエンジニアとしての活動やエンジニア向けイベントの企画・運営をしています。 今回は NTT ComのSpeaker Deckアカウント ができましたというお知らせになります。 Speaker Deck 開設の背景 以前から、社内のエンジニアがイベントなどで外部発表をしたものの、 発表資料を置く場所がないという話がありました。 今まで会社として公式に発表資料を掲載する場所はなく、 部署単位での発表資料を公開する場所を用意していた時期もあります。 しかし、社内の組織変更や、利用していたサービスの仕様変更などもあり使われなくなったという過去があります。 結果として、外部発表をしたエンジニアは資料を公開しない、もしくは、個人のアカウントにアップロードをするという状況が続いていました。 特に前者は、せっかく発表する価値のある内容の資料が誰にも共有されることもなく仕舞われているという状況でした。 こうした状況の背景には、全社に関わるプロモーションは広報の仕事なので、 発表資料を公開する場所は広報が用意をするべきだという空気がありました。 しかしながら、なかなか整理等を実施して実現方法を含めて環境まで準備するには時間がかかりそうであったため、 本ブログのようにエンジニアが主体になって全社に関わるプロモーションの活動している実績もあり、 今回はエンジニアサイドから広報に外部発表の資料を置く場所を作らせてほしいという提案へ行くことにしました。 広報との話し合い 広報とは現状の課題として、会社のプレゼンス向上機会の損失という話をメインに進めました。 広報からは公式サイトに資料を置くこともできるという話もありましたが、 単純にPDFを置いて資料を見たい人がダウンロードするという流れを考えると、 不便さがあるという話をしました。 一方、Speaker Deckではブラウザ上で資料を見えることやページごとにURLが発行されており、 資料を見る側にとって便利なサービスであることを伝えました。 話し合いの結果、広報室から発表資料をSpeaker Deckに置くこと理解を得ることができ、 エンジニアブログの運用の実績から、Speaker Deckの運用もエンジニアサイドに一任して貰う形で終わりました。 Speaker Deck の運用 Speaker Deckへの資料掲載はハードルや手間を減らすために、 全社員が使えるマイクロソフトのサービスで簡易な掲載フローを組みました。 掲載までの流れは以下のようになっています。 掲載希望者はMS Formsから掲載のエントリー Power AutomateがMS Formsのエントリー情報をTeamsのSpeaker Deckの管理チームに通知 通知を元にSpeaker Deckへ記事を掲載 本当は3の部分もAPIを使って自動化しておきたいところですが、 あいにくSpeaker DeckにはAPIがないようなので手作業となっています。 今のところ依頼がまだそんなに多くないので人力でなんとかなっていますが、 依頼が増えてくるようならばヘッドレスブラウザなどを使うことも考えます。 おわりに 今まで社内のエンジニアたちが「外部で発表したけど資料を公開する場所がない!」というフラストレーションをためていましたが、 今回Speaker Deckを作ったことでこうした問題の解決になればと思っています。 また、「NTT Comがイベントで発表していたけどその資料が見つからない!」なんてご不便をおかけすることもあったかと思います。 これからはNTT Com社員が外部発表などをした際には、Speaker Deckに発表資料をアップロードすることもありますので、 興味のあるかたは是非 NTT ComのSpeaker Deckアカウント をフォローしてみてください。
目次 目次 はじめに L5GとICGWの相互接続構成 デモ内容 温湿度、Co2濃度の可視化 カメラ画像 各社L5Gのスループット計測値 設定・運用面の工夫 ゼロタッチプロビジョニング デバイスの遠隔保守 おわりに はじめに こんにちは、5G&IoTサービス部、IoTサービス部門の岩辻です。 NTTコミュニケーションズ株式会社 (以下、NTT Com) は、世界最大級のネットワーク展示会である 「Interop Tokyo 2023 (会場 : 幕張メッセ、会期 : 2023年6月14日〜16日、以下Interop) 」 において会場内に構築されたローカル5G (以下、L5G) と IoT Connect Gateway (以下、ICGW) の相互接続を実現しました。 また、L5G、ICGWを通じて収集したIoTデバイスのセンサデータ、L5Gネットワークのスループット計測などの可視化も実施しました。 本記事ではその構成や可視化方法、IoTデバイス運用面での工夫について解説します。 Interopでの取り組みを通じて、ICGWによって実現できること、 それをいかに効率よく構築・運用できるかを知っていただけると思います。 L5GとICGWの相互接続構成 現状、ICGWはNTT ComのMVMO回線であるIoT Connect Mobile Type S (以下 、ICMS) のみで利用できるサービスとなっていますが、今回はL5Gとの相互接続にチャレンジしました。 下図にあるように、Flexible Inter Connect (以下、FIC) を活用して、各社スライスを切ったL5G環境とICGWを容易に繋げることができました。 ICGWからThings Cloudへの接続はすでに商用提供されている機能となり、L5GとSDPF商材との組み合わせによって新たなソリューション展開が可能であるという技術的確認ができました。 ICGW以外にも様々なSDPFサービスの組み合わせにより、お客様環境を柔軟に構築することが可能になります。 L5Gの基地局や上流NWのトラブルによって、ICGWがデバイスを識別できなくなるという事象はありましたが、これについては暫定対処を実施しました。 デバイスに対して監視用のPingを定期的に飛ばし、疎通がなくなったら通知する仕組みを急遽用意し、異常検知を通知していました。 この通知によって問題解決をスピード感をもって実現できました。 デモ内容 Interop会場内にセンサー類を取り付けたデバイスを計8台配置し、会場内のL5G経由でICGWに接続 & クラウドへ転送して可視化しました。 クラウド上で可視化したデモ一覧は以下となります。 温湿度、Co2濃度の可視化 カメラ画像 各社様L5Gのスループット計測値 順次、実際の画面を交えて説明していきます。 温湿度、Co2濃度の可視化 センサーから送られてきたデータをICGWのクラウドサービス接続機能を使ってThings Cloudに送り、可視化をしています。 Things Cloudの標準ウィジェット機能を利用して温湿度のグラフ化を行っています。 また、Co2濃度に関してはカスタムウィジェット機能を使って、Interopの会場図上にヒートマップで可視化しました。 過去の類似例を参考に、Angularで開発してThings Cloud上にデプロイしています。 Things Cloudが受け取るデータのフォーマットは厳しく決められており、それに合わせるのはデバイスにとって負担となりますが、ICGWのフォーマット変換機能 (2023/09リリース予定) を使って解決しています。 予め作成した変換テンプレートに沿ってICGW内でデータの加工するため、デバイスからは計測値のみ送って、ICGW内でThings Cloudの形に統一する、ということが可能です。 デバイス側でのデータ加工の負担をなくし、送信するデータのサイズも小さくできるメリットがあります。 カメラ画像 M5Stack UnitV2 AI カメラをデバイスに取り付け、画像をThings Cloudで表示しています。 また、今回取り付けたカメラには物体認識の機能が備わっているため、撮影された画像の中のオブジェクト数と人数もデバイスから送信し、Things Cloud上でグラフ化しています。 実際のユースケースでは、イベント会場内の来客人数把握や人流検知に応用できるものだと考えています。 各社L5Gのスループット計測値 各社L5GのスループットをThings Cloudと、AWS EC2上に立てたGrafanaで可視化しました。 当初、Things Cloud上での可視化のみを予定していましたが、各社のLatency/Jitterの制御をよりきれいにグラフで表現したいという声があったため、急遽Grafanaでの可視化も行いました。 データはThings Cloudにのみアップロードし、Grafana側はThings Cloudに対してデータ取得のリクエストを発行して取得&利用しています。 今回は稼働が足りず断念しましたが、ICGWのミラーリング機能 (2023/09リリース予定) を利用すればThings Cloudに送りつつ、他クラウドにも同時に送ることが可能となり、複数のクラウドでの可視化がさらに容易になります。 (※ 各社帯域に制限をかけているため、Upload/Downloadについては差分が出ています) 設定・運用面の工夫 実際のお客様の環境では、IoT デバイスの数は多数になり、また設置場所もそれぞれバラバラになってしまうことが多いです。 設定の変更やトラブル対応時にはデバイスの元まで駆けつける必要がありますが、ICGWを利用すればその負担も軽減できます。 今回はInterop会場を実際のお客様環境に見立てて、我々が運用する上でチャレンジした内容を紹介させていただきます。 ゼロタッチプロビジョニング 今回のInteropで利用したデバイス数は8台程度で1台1台設定しても大きな負担にはなりませんが、実際のお客様環境ではもっと多数を利用することがほとんどです。 そのため、ICGWのコンフィグ配信、ストレージ機能を使って、下図のような構成でゼロタッチプロビジョニングを実現しています。 まずは以下の事前設定をします。 Node-REDでICGWにセンサーデータを送信するシナリオファイルを作成 シナリオファイルをクラウドストレージ (Wasabi) にアップロード ストレージ機能を使うための設定情報をコンフィグ配信機能に登録 設定ファイルの更新をICGWに問い合わせ、更新があればストレージ機能を使ってWasabiにシナリオファイルを取得するスクリプトを作成 4で作成したスクリプトをデバイス上で動作し続けるよう設定 事前設定を終えると、SIMをデバイスに差すだけで、シナリオファイルの取得&センサーデータの送信が始まり、ゼロタッチプロビジョニングが実現できます。 また、Node-REDのシナリオファイルを更新する際にも、1デバイス上でシナリオファイルを修正してWasabiにアップロードし、設定ファイルを更新するだけで8台全てにシナリオファイルの変更が完了します。 初期設定だけでなく、更新にも強い構成にでき、準備段階での稼働削減になりました。 デバイスの遠隔保守 ICGWのリモートアクセス機能を使って、IoTデバイスに遠隔から入れるようにしました。 リモートアクセス機能は、下図のようにICGW上で設定するだけで、外からオンデマンドにデバイスへアクセスできるエンドポイントを提供する機能です。 各デバイス毎のリモートアクセス設定を投入さえすれば、場所を選ばずデバイスの設定ができるため、まずはリモートアクセス設定を入れるところから始め、Interopの準備を進めていました。 会期中の運用では、デバイス上で動作するNode-REDに入ってシナリオの動作確認をしたり、必要であれば修正してました。 会場が広く、設置場所もバラバラであったため、一台一台デバイスの元まで行って確認する手間を省け、大きなメリットとなりました。 おわりに Interop会場に構築されたL5GとICGWの相互接続と環境データの可視化、運用負担の軽減などについて紹介させていただきました。 今回L5GとICGWの相互接続とのフィージビリティが検証できたので、今後はICMS以外の回線とも連携を進めていき、あらゆる回線からICGWを利用できて、よりお客様に利用していただきやすくなるよう努めていきたいと考えております。 9月以降にはインターネット回線からICGWを利用できる機能もリリース予定です。 ご興味のある方はぜひICGWのご利用を検討してみてください。 ICGWに関するお問い合わせ先 IoT Connect Gatewayサービス詳細 ICGWに関するお問い合わせ先 トライアル、サービス導入に関するお問い合わせ 資料請求・お問い合わせフォーム 開発チームへのお問い合わせ(お手数ですが@を半角文字に置き換えてください) メールを送る Interop Tokyo 2023 のその他関連記事 Engineer's Blog では本記事以外にもInterop Tokyo 2023 に関する記事が投稿されてます。 ご興味をお持ちの方は是非御覧ください。 Interop Tokyo 2023 〜 マルチベンダL5G x IoTサービス連携の取り組み〜 Interop Tokyo 2023 〜 L5G x AWS Outpostsサーバーの取り組み紹介 〜
概要 はじめまして。イノベーションセンター所属の鄭(GitHub: nbhgytzheng )です。2021年入社し、現在はテクノロジー部門のOsecT-Ops プロジェクトに所属して、 OsecT の開発・運用業務に取り組んでいます。 今回はOsecTで利用している Zeek (ネットワーク・セキュリティ・モニタリングツール)とZeekのプロトコル拡張ツールである Spicy (Zeekで利用するC++のパーサーをC++で記述することなく簡易に生成できるツール)の概要及び使い方・利用例を紹介します。探した限り日本語での使い方の紹介記事がないため、今回が日本初紹介です。本記事の目標は、ZeekとSpicyを使って任意のプロトコルを含むトラフィック解析ができるようになることです。 OsecTとは OsecTとは工場などの制御システム(OT; Operational Technology)のセキュリティリスクを可視化・検知するサービスです。 多様化する工場システムのセキュリティ脅威に対して、パケット解析するセンサー機器を設置するだけで、OTシステムへの影響なく、ネットワークの可視化と脅威・脆弱性検知ができます。早期にリスク感知できる状態を作り、工場停止による損失を未然に防ぐことができます。詳しくは過去のブログ記事に書いているので、興味がある人はぜひ見てください。( OsecTリリース ・ OsecT前編 ・ OsecT後編 ) Zeekとは Zeekとはネットワークを監視し、トラフィックを解析して、IPアドレス、MACアドレスやプロトコルなどの情報をログとして出力するOSSです。Zeekは下記のような基本ログ(conn.log, dns.log, dhcp.logなど)を出力します。また必要に応じて、プラグインを利用することで出力ログの追加ができます。 # 生成のログの例:dns.log #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path dns #open 2023-03-14-16-15-20 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p proto trans_id rtt query qclass qclass_name qtype qtype_name rcode rcode_name AA TC RD RA Z answers TTLs rejected pkts #types time string addr port addr port enum count interval string count string count string count string bool bool bool bool count vector[string] vector[interval] bool int 1539457598.376546 CHTBxA4O2ypY1PxYPg fd00:f81d:f5f:6b92:fd0d:9399:3d28:3984 5353 ff02::fb 5353 udp 0 - _ipp._tcp.local 1 C_INTERNET 12 PTR - - F F F F 0 - - F - 1539459646.378861 COMnQY2JaJZ3TllMYb fd00:f81d:f5f:6b92:fd0d:9399:3d28:3984 5353 ff02::fb 5353 udp 0 - _ipp._tcp.local 1 C_INTERNET 12 PTR - - F F F F 0 - - F - 1539463246.380625 Cgu5Zw1ASoGNZ2UGok fd00:f81d:f5f:6b92:fd0d:9399:3d28:3984 5353 ff02::fb 5353 udp 0 - _ipp._tcp.local 1 C_INTERNET 12 PTR - - F F F F 0 - - F - 1539466846.382677 C5X9v4snqSDPMj3u7 fd00:f81d:f5f:6b92:fd0d:9399:3d28:3984 5353 ff02::fb 5353 udp 0 - _ipp._tcp.local 1 C_INTERNET 12 PTR - - F F F F 0 - - F - ... Spicyとは プラグインを利用することで、出力ログを増やせますが、必要なログを出力するプラグインがないこともあります。例えば、以下の要件を満たすプラグインは存在しません。 Zeekが対応しているプロトコルの出力ログ内に追加の情報を加えて出力したい場合 Zeekが対応していないプロトコルの情報をログに出するしたい場合 ここで登場するのがSpicyです。SpciyとはZeekで利用するC++のパーサーをC++で記述することなく簡易に生成するためのツールです。Spicyを利用すれば、ログ情報の追加やZeek及びプラグインで解析できないプロトコルの解析ができるようになります。 Zeek・Spicyによるプロトコル解析 ここまではZeek, Spicyの概要について紹介しました。本章ではZeek, Spicyの利用方法について、環境構築からコーディングまで紹介します。 1. ZeekとSpicyのインストール はじめに、Zeek, Spicyの実行環境を構築します。今回はUbuntu 22.04.1をベースに環境構築の方法を示します。その他のOSでのインストール方法は 公式サイト を参照してください。 1.まずはZeekのリソース(GitHub)を取得するため、gitコマンドをインストールします。 ~$ sudo apt install git 2.次にgitコマンドを利用して、Zeekのリソースをクローンします。 ~$ git clone --recursive https://github.com/zeek/zeek -b v5.0.0 3.Zeekのリソースはcmakeコマンドを利用して自動インストールできるので、cmakeコマンドと関連パッケージをインストールします。 ~$ sudo apt-get install cmake make gcc g++ flex libfl-dev bison libpcap-dev libssl-dev python3 python3-dev swig zlib1g-dev 4.最後にクローンしたZeekディレクトリへ移動し、以下のコマンドを実行すれば自動でインストールされます。makeは状況に応じて1時間以上かかる場合もあります。最後のmake installはスーパーユーザーで実行しないと、エラーになるため注意してください。 ~$ ./configure --build-type=Release ...一部省略... ================================================================ -- Configuring done -- Generating done -- Build files have been written to: /home/xxx/zeek/build ~$ make ...一部省略... Consolidate compiler generated dependencies of target zeek-archiver make[3]: Leaving directory '/home/xxx/zeek/build' [100%] Built target zeek-archiver ~$ sudo make install ...一部省略... make[1]: Leaving directory '/home/xxx/zeek/build' 5.以上でZeekのインストールは完了です。以下のコマンドでZeekが利用できることを確認します。 # パス追加 ~$ export PATH="$PATH:/usr/local/zeek/bin" # zeekコマンド確認 ~$ zeek -version zeek version 5.0.0 6.Spicyのインストールは 公式サイト でDEBファイルを取得し、以下のコマンドを順に実行すればインストールが完了です。 ~$ sudo dpkg --install xxx.deb (例:spicy-dev.deb) Selecting previously unselected package spicy. (Reading database ... 212653 files and directories currently installed.) Preparing to unpack spicy-dev.deb ... Unpacking spicy (2.4.8) ... Setting up spicy (2.4.8) ... 7.インストールが完了したら、以下のコマンドでSpicyが利用できることを確認します。 # パス追加 ~$ export PATH="$PATH:/opt/spicy/bin/spicyc" # spicyコマンド確認 ~$ spicyz -version 1.3.16 ~$ spicyc -version spicyc v1.5.0 (d0bc6053) 以上でZeekとSpicyの実行環境の構築は完了です。 2. プロトコル仕様の確認 SpicyではIPベースのプロトコルだけでなく、イーサネットベースのプロトコルのパーサーも作成できます。今回はIPベースのUDPプロトコルを例に説明します。IPベースのプロトコル構造は以下のようになっています。IPベースでSpicyを利用する場合、Spicyが自動的に青い部分(イーサネットヘッダー、IPヘッダー、TCP/UDPヘッダー)を除き、オレンジ色の部分を処理します。 まず、ログに出力する内容を決めるために、解析対象のプロトコル仕様を確認します。プロトコル仕様はGoogleなどで検索して見つけられるケースもありますが、プロトコルに関わる各種団体・協会経由で仕様書を取得するケースもあります。プロトコル仕様からポート番号(今回の例では1111)と以下のようなパケットフォーマット定義を用意して、Spicyでのパーサー実装に進みます。 項目名/フィールド名 サイズ(オクテット) 内容 header1 2 プロトコルヘッダー header2 1 プロトコルヘッダー command 2 リクエストのタイプを表す subCommand 2 実行する動作を表す … … … 次にパーサーで利用するSpicyファイル・evtファイル・Zeekファイルの作成方法について紹介します。 3. Spicyファイルを作成 本節では以下のテンプレートと前節で取得したプロトコル情報(ポート番号・パケットフォーマット定義)を利用したSpicyファイルの基本的な作成方法を紹介します。Spicyファイルでは、通信プロトコルのプロトコルフォーマットを定義します。 # spicyテンプレート module MYPROTOCOL; import zeek; import spicy; public type Message = unit { PROTOCOL_FIELD1: FIELD_TYPE &size=1; PROTOCOL_FIELD2: FIELD_TYPE &size=2; ... on %done { print self; zeek::confirm_protocol();} }; テンプレートの各部分を解説します。 module MYPROTOCOL; :任意のモジュール名を宣言 多くの場合、解析対象のプロトコル名を記述します。 import xxx :Spicy関数の取り込み 基本的には、Spicyの基本関数が入っている”spicy”とconn.logのservice列にプロトコル名を出力ための”zeek”が必要です。 public type Message = unit {} :プロトコルのデータ部分を格納する変数 データ部分はこの Message に渡されます。 PROTOCOL_FIELD1: FIELD_TYPE &size=1; :データ部分をブロックごとに分解 書き方はFIELD_TYPEによって異なるため 公式サイト を参照してください。 on %done { print self; zeek::confirm_protocol();} :Spicyが解析を終えたときに実行する関数 print self; :解析データの全てをprint(debug用) zeek::confirm_protocol(); :解析が終わったことをZeekに通知 そして、前節で取得したプロトコル情報を利用して、テンプレートを改造すると以下のようなSpicyファイルが作成できます。ここで、 subCommand までが必要なデータとした場合、最後に tmp という PROTOCOL_FIELD を追加で作成し、 subCommand 以降のデータをtmpに入れることができます。 module protocol_name; # Spicyを単独で実行する場合は下の import zeek をコメントアウトする import zeek; import spicy; public type Message = unit { header1: bytes &size=2; header2: bytes &size=1; command: bytes &size=2; subCommand: bytes &size=2; tmp: bytes &eod; # Spicyを単独で実行する場合は zeek::confirm_protocol(); 部分をコメントアウトする on %done { print self; zeek::confirm_protocol();} }; 実行すると、以下の出力が得られます。(Spicyのみ実行したい場合は上記のコードをコメントに従って変更する必要があります) # 実行結果 ~$ printf '\x00\x00\x01\x02\x02\x03\x03\x11\x11\x11\x11\x11\x11\x11' | spicy-driver test.spicy [$header1=b"\x00\x00", $header2=b"\x01", $command=b"\x02\x02", $subCommand=b"\x03\x03", $tmp=b"\x11\x11\x11\x11\x11\x11\x11"] 4. evtファイルを作成 本節では以下のテンプレートとプロトコル情報(ポート番号・パケットフォーマット定義)・Spicyファイルを利用して、evtファイルの作成方法を紹介します。evtファイルでは解析したいプロトコルを指定します。 protocol analyzer spicy::MYPROTOCOL over UDP: parse with MYPROTOCOL::Message, port PORT_NUMBER/udp; import MYPROTOCOL; on MYPROTOCOL::Message -> event MYPROTOCOL::message($conn, self.PROTOCOL_FIELD1, ...); 例えば、以下のようにプロトコルのポート番号(1111)、プロトコル名(protocol_name)、Zeekに渡したいプロトコルフィールド(header1、header2など)を記述します。 protocol analyzer spicy::protocol_name over UDP: parse with protocol_name::Message, port 1111/udp; import protocol_name; on protocol_name::Message -> event protocol_name::message($conn, self.header1, self.header2, ...); evtファイルを作成後、コンパイルしてオブジェクトファイルであるhtloファイルを生成します。 ~$ spicyz -o test.hlto test.spicy test.evt ~$ # test.hltoが生成される 5. Zeekファイルを作成 最後に、以下のテンプレートを利用して、Zeekファイルの作成方法を紹介します。Zeekファイルでは、Spicyの処理結果をログに出力します。 # Spicy側のパーサーを利用するための宣言 module MYPROTOCOL; # 実行開始前に必要な変数の宣言(global変数) export { redef enum Log::ID += { LOG }; # この変数の内容はlogに書き出す type Info: record { ts: time &log; uid: string &log; id: conn_id &log; ## MYPROTOCOL data. PROTOCOL_FIELD1: string &log; ## MYPROTOCOL data. PROTOCOL_FIELD2: string &log; ## MYPROTOCOL data. PROTOCOL_FIELD3: string &log; ... ... final_block: count &optional; done: bool &default=F; }; global log_myprotocol: event(rec: Info); } global expected_data_conns: table[addr, port, addr] of Info; redef record connection += { myprotocol: Info &optional; }; # $pathで出力ファイル名を指定する event zeek_init() &priority=5 { Log::create_stream(MYPROTOCOL::LOG, [$columns = Info, $ev = log_myprotocol, $path="myprotocol"]); } # logに書き出す時の動作を書く関数 event MYPROTOCOL::message(c: connection, PROTOCOL_FIELD1: string, PROTOCOL_FIELD2: string, PROTOCOL_FIELD3: string, ... ) { local info: Info; info$ts = network_time(); info$uid = c$uid; info$id = c$id; info$PROTOCOL_FIELD1 = PROTOCOL_FIELD1; info$PROTOCOL_FIELD2 = PROTOCOL_FIELD2; info$PROTOCOL_FIELD3 = PROTOCOL_FIELD3; ... ... c$myprotocol = info; # info内の変数を全部logに書き出す Log::write(MYPROTOCOL::LOG, info); } テンプレートの各部分を解説します。 module MYPROTOCOL; :Spciyで作成したパーサーをインポートするために宣言 export {…}; :Zeekで利用する変数の宣言 ログに出力したい項目はここで指定します。 event zeek_init() &priority=5 {…} :出力ログのパスを指定 event MYPROTOCOL::message(…) {…} :パーサーの処理結果をログに出力 ログに出力するタイミングで加工することもできます。 上記のテンプレートと今までの結果を利用し、プロトコル名(protocol_name)、出力したいフィールド(header1など)、出力したいログファイルの名前($path="protocol_name")を書き換えることで、以下のようなZeekファイルを作成できます。 # Spicy側のパーサーを利用するための宣言 module protocol_name; # 実行開始前に必要な変数の宣言(global変数) export { redef enum Log::ID += { LOG }; # この変数の内容はlogに書き出す type Info: record { ts: time &log; uid: string &log; id: conn_id &log; ## MYPROTOCOL data. header1: string &log; ## MYPROTOCOL data. header2: string &log; final_block: count &optional; done: bool &default=F; }; global log_protocol_name: event(rec: Info); } global expected_data_conns: table[addr, port, addr] of Info; redef record connection += { protocol_name: Info &optional; }; # $pathで出力ファイル名を指定する event zeek_init() &priority=5 { Log::create_stream(protocol_name::LOG, [$columns = Info, $ev = log_protocol_name, $path="protocol_name"]); } # logに書き出す時の動作を書く関数 event protocol_name::message(c: connection, header1: string, header2: string ) { local info: Info; info$ts = network_time(); info$uid = c$uid; info$id = c$id; info$header1 = header1; info$header2 = header2; c$protocol_name = info; # info内の変数を全部logに書き出す Log::write(protocol_name::LOG, info); } 6. テスト用Pcapで出力ログの確認 最後にテスト用Pcapを使って出力ログを確認します。 ~$ zeek -Cr cclink_ief_basic.pcap test.hlto test.zeek ~$ # protocol_name.logが生成される 生成されたログの中身を確認すると、以下のようになっています。最後の16進数の部分( P\x00 \x00 など)は今回出力したい部分です。今回は16進数のデータを出力しただけですが、Zeekファイルを作り込むことで人間が解釈できる文字列として出力もできます。 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path protocol_name #open 2023-06-12-15-53-06 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p header1 header2 #types time string addr port addr port string string 1655284124.859924 C3KZkP3l8QTJaS2vg7 172.16.134.128 61450 172.16.134.255 61450 P\x00 \x00 1655284124.953994 CG3NWX3t9Qf1Xrezl5 172.16.134.129 61450 172.16.134.128 61450 \xd0\x00 \x00 1655284125.375608 C3KZkP3l8QTJaS2vg7 172.16.134.128 61450 172.16.134.255 61450 P\x00 \x00 1655284125.484180 CG3NWX3t9Qf1Xrezl5 172.16.134.129 61450 172.16.134.128 61450 \xd0\x00 \x00 1655284125.500485 C3KZkP3l8QTJaS2vg7 172.16.134.128 61450 172.16.134.255 61450 P\x00 \x00 1655284125.610011 CG3NWX3t9Qf1Xrezl5 172.16.134.129 61450 172.16.134.128 61450 \xd0\x00 \x00 ... ... Zeek・Spicyの活用例 ここまで、Zeek, Spicyの使い方まで紹介しました。本章ではイメージを深めるため、OsecTで実装したZeekが対応していないプロトコルの追加と、Zeekの基本ログへの情報追加の2つの例を紹介します。 CC-Linkファミリーへの対応 今回は市場ニーズを踏まえた上で、Zeekが対応していないOTプロトコル( CC-Linkファミリー )に対応しました。具体的なプロトコルはCC-Link IE FieldとCC-Link IE ControlとCC-Link IE Field Basicです。実装したコードは公開しているため、興味がある方は以下のリンクを参照ください。 zeek-parser-CCLinkFieldBasic zeek-parser-CCLinkField-CCLinkControl CC-Link IE Field Basicの出力ログは以下のようになっています。ペイロードの奥深くまで情報を取得することもできますが、今回はパケットの種類(cyclicDataRes、cyclicDataReq)と使っているコマンド(cyclic)をログに出力しました。 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path cclink-ief-basic #open 2023-05-27-00-52-06 #fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p pdu cmd number ts_end #types time string addr port addr port string string int time 1655284124.953994 CIAp8bugKIZRVpAYk 172.16.134.129 61450 172.16.134.128 61450 cyclicDataRes - 222 1655284149.499713 1655284124.859924 Ckkc3929guO41BnpSa 172.16.134.128 61450 172.16.134.255 61450 cyclicDataReq cyclic 222 1655284149.392238 #close 2023-05-27-00-52-06 CC-Link IE FieldとCC-Link IE Controlの出力ログは以下のようになっています。ここではパケットの種類(select、scanなど)と種類別の情報(0x0001など)をログに出力しました。今回はテスト用Pcapを自作したため、全て 0x0001 になっています。 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path cclink-ie #open 2023-03-15-16-56-36 #fields ts src_mac dst_mac service pdu_type cmd node_type node_id connection_info src_node_number number ts_end #types time string string string string string string int string string int time 1667903833.066101 00:11:11:11:11:11 00:00:00:00:00:01 cclink_ie_control select - - - - 0x0001 61 1667903833.134207 1667903833.065821 00:11:11:11:11:11 00:00:00:00:00:01 cclink_ie_control scan - - - - 0x0001 48 1667903833.129023 1667903833.064742 00:11:11:11:11:11 00:00:00:00:00:01 cclink_ie_control connectAck - - - - 0x0001 61 1667903833.133590 1667903833.065511 00:11:11:11:11:11 00:00:00:00:00:01 cclink_ie_control connect - - - - 0x0001 62 1667903833.134085 1667903833.067818 00:11:11:11:11:11 00:00:00:00:00:01 cclink_ie_control nTNTest - - - - 0x0001 53 1667903833.131018 1667903833.068939 00:11:11:11:11:11 00:00:00:00:00:01 cclink_ie_control dummy - - - - 0x0001 57 1667903833.133957 1667903833.065083 00:11:11:11:11:11 00:00:00:00:00:01 cclink_ie_control collect - - - - 0x0001 61 1667903833.133231 1667903833.064936 00:11:11:11:11:11 00:00:00:00:00:01 cclink_ie_control launch - - - - 0x0001 40 1667903833.132990 1667903833.066240 00:11:11:11:11:11 00:00:00:00:00:01 cclink_ie_control token - - - - 0x0001 57 1667903833.133351 #close 2023-03-15-16-56-36 Zeekの基本ログへの情報追加 DHCPv4はZeekが対応しているプロトコルですが、出力されるログの情報量に過不足がありました。そのため、Zeek, Spicyを利用して必要のない情報を削除・必要な情報を追加しました。実装したコードは公開しているため、興味がある方は MYDHCP を参照ください。 デフォルトの出力ログは以下のようになっています。 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path dhcp #open 2023-06-16-18-23-59 #fields ts uids client_addr server_addr mac host_name client_fqdn domain requested_addr assigned_addr lease_time client_message server_message msg_types duration #types time set[string] addr addr string string string string addr addr interval string string vector[string] interval 1624301983.013489 Cah1vz3icJOQ3kUtk4,C6uWeo2ldOmwsjKUj7 10.0.2.15 10.0.2.2 00:00:20:b0:60:b0 kali - - 10.0.2.15 10.0.2.15 86400.000000 - - REQUEST,ACK 0.000309 #close 2023-06-16-18-23-59 そして、Zeek, Spicyによって改造後のログは以下のように変更しました。本来のログのMACアドレスとタイムスタンプをそのまま利用し、 SrcIP,Hostname,Parameter,ListClassId を追加しました。 #separator \x09 #set_separator , #empty_field (empty) #unset_field - #path mydhcp #open 2023-06-16-18-23-59 #fields ts SrcIP SrcMAC Hostname ParameterList ClassId #types time addr string string vector[count] string 1624301983.013489 0.0.0.0 00:00:20:b0:60:b0 kali 1,2,6,12,15,26,28,121,3,33,40,41,42,119,249,252,17 - #close 2023-06-16-18-23-59 おわりに 今回はZeekとSpicyの概要及び使い方・利用例について紹介しました。この記事を参考に、プロトコルのパーサーを実装、ログ出力までできるようになれば幸いです。そして、Zeek, Spicyの活用例の章で紹介したスクリプトはすでにOsecTへ実装しリリース済です。OsecTもこれからZeek, Spicyを利用し、対応プロトコルの拡張などを続けていくので、興味を持たれた方はぜひご連絡ください。
はじめに こんにちは、イノベーションセンターの藤田、鈴ヶ嶺です。NTTコミュニケーションズ株式会社 (以下、NTT Com) は、世界最大級のネットワーク展示会である 「Interop Tokyo 2023(会場:幕張メッセ、会期:2023年6月14日〜16日)」 において構築されるShowNetに対し、コントリビューターとしてローカル5G(以下、L5G)システムを提供しました。その基盤としてAWS Outpostsサーバーを構築し提供しました。 本記事ではその構成や技術的な挑戦について解説します。 AWS Outpostsサーバーを用いたL5G基盤構築への挑戦 今回ShowNetにてL5G基盤をAWS Outposts サーバーを用いて構築するにあたり、2点の挑戦をしました。 Flexible InterConnectを利用したハイブリッドクラウドネットワーク EKS x EC2セルフマネージド型ノード on AWS Outpostsサーバー基盤 Flexible Inter Connectを利用したハイブリッドクラウドネットワーク 今回会場では、NTTドコモのキャリア 5G とNTT ComのL5G を組み合わせた環境で、ネットワークスライシング連携のデモンストレーションを構築・展示しています。その構築・展示に当たり、NTT Com内製のマイクロサービス開発フレームワーク Qmonus を活用しました。 このデモンストレーションを実現するためには、AWS Outposts サーバーをはじめとするオンプレミスと、Public Cloud (Public AWS) 間を安定して接続する必要があります。 本構築ではFlexible InterConnect、FIC-Connection AWSを利用することで、AWS OutpostsサーバーほかオンプレミスとPublic AWSに対して専用回線による安定した接続が可能なネットワークを実現しました。 EKS x EC2セルフマネージド型ノード on AWS Outpostsサーバー基盤 AWS OutpostsサーバーをL5G基盤として利用するにあたり、構築可能なEC2インスタンスタイプの制限があるため柔軟なリソース配分がしづらい問題がありました。 今回の構成ではより柔軟かつ可用性の高い基盤提供を目指し、Public AWSにてEKSクラスターを構築しAWS Outpostsサーバー上のEC2インスタンスをEKSのセルフマネージド型ノードとして動作する構成に挑戦をしています。 AWS Outpostsサーバー上のEC2インスタンスは同一VPC上に構築されたPublic AWS上のEC2インスタンスやEKSクラスターと疎通可能であるため、EKSの機能を利用しつつAWS Outpostsサーバーの機能であるLocal Network Interface(以下、LNI)を通じたpodレベルでのオンプレミスのネットワークとの接続を実現しています。 本構成によりAWSのマネージドなサービスをオンプレミスまで拡張することで、オンプレミスのネットワークと統合しつつ柔軟なリソース配分が可能となる可用性の高い基盤の提供に成功しています。 発見した課題 L5GのUPFをAWS Outpostsサーバー上に構築するにあたり、モバイル特有の処理を高速化する観点から1つのpodに対してLNI経由で複数のインターフェースをアタッチしDPDK経由で複数のVLANを接続をする挑戦も行いました。 しかしLNIはPromiscuous modeをサポートしていないため、macvlanによるNICの仮想化ができません。 1 またENA Poll Mode DriverはVLANをサポートしていないため、tagged vlanを利用できません。 2 以上から、本構成においてDPDK経由で複数のvlanを利用する高速化が困難であるといった課題が発見されました。 まとめ 本記事ではInterop Tokyo 2023のShowNetにおいて、L5G基盤に利用したAWS Outpostsサーバーの構成について紹介しました。本構成ではいくつか課題も見つかったため、それを踏まえてより柔軟性が高く可用性の高い基盤の提供を目指していくと共に、NTT Comのサービスへの応用について検討していきます。 https://docs.aws.amazon.com/outposts/latest/server-userguide/local-network-interface.html ↩ https://doc.dpdk.org/guides/nics/ena.html ↩
NTTコミュニケーションズ(以下、NTT Com)を含めたドコモグループではこの夏に3種類のインターンシップを開催します! ビジネス創造インターンシップ ドコモハッカソン 現場受け入れ型インターンシップ このうち、この記事ではNTT Comのリアルな業務を体験できる「現場受け入れ型インターンシップ」について紹介します。 現場受け入れ型インターンシップとは NTTドコモやNTT Comの社員と一緒に働きながら、実務を体験していただくインターンシップです。 セールスやビジネスデザイン、エンジニア、デザイナー、リーガルなど幅広い職種を取り揃えて、業務体験を通じて仕事の理解を深め、成長機会を提供する内容となっています。 今季は2023年8月28日(月)~9月8日(金)の土日祝を除く平日10日間(2weeks)で開催されます。開催場所は、出社+リモートワークのハイブリッド形式です(出社割合はポストにより異なります)。 募集ポスト 募集ポストについては下記のページの「受け入れポスト情報」をご覧ください。 information.nttdocomo-fresh.jp 記載されているポストのうち、受け入れ会社に NTTコミュニケーションズ株式会社 と記載されたポストがNTT Comでの業務です。 ポスト一覧表をこの記事の 末尾 にも掲載したので参考にしてください。 これまでのインターンシップの様子 これまで開催したインターンシップでNTT Comのエンジニア系ポストに参加してくれた学生の方々がこのEngineers' Blogに体験記を寄稿してくれています。 なお、NTT Comのデザイン系ポスト(KOEL)については KOEL公式note 、NTTドコモのエンジニア系ポストについては ドコモ開発者ブログ をご覧ください。 「インターンシップでどんなことに取り組むのだろう?」、「インターンシップを通して何が学べるのだろう?」といった疑問を解消する手助けになれば幸いです。 AI分野 engineers.ntt.com セキュリティ分野 engineers.ntt.com engineers.ntt.com engineers.ntt.com engineers.ntt.com ネットワーク分野 engineers.ntt.com engineers.ntt.com engineers.ntt.com engineers.ntt.com engineers.ntt.com ソフトウェア/クラウド分野 engineers.ntt.com engineers.ntt.com engineers.ntt.com engineers.ntt.com engineers.ntt.com まとめ みなさんもこの夏、ドコモのインターンシップに参加して、興味分野で圧倒的成長をしてみませんか? 気になるポストの詳細やエントリーはこちらです(再掲)。 information.nttdocomo-fresh.jp エントリー締め切りは 6月30日(金)23:59 です。 みなさんのご応募をお待ちしています! 参考:ポスト一覧表 各ポストの詳細については、 現場受け入れ型インターンシップ をご覧ください。 カラムの説明 ポスト:ポスト名 受入:受け入れ会社( D =NTTドコモ、 C =NTT Com) 参考:参考情報 ビジネスデザイン(通信) ポスト 受入 参考 1.ドコモオンラインショップ/オンライン手続きの運用、 データ分析、販売促進施策企画、WEB広告運用業務 D 2.ahamoのモバイルサービスサイト・アプリのUI/UX戦略の企画/開発/運用/分析/改善 D ネットワークデザイン ポスト 受入 参考 3.ドコモビジネスを実現するNW装置の開発・検証を行うエンジニア D - ドコモビジネス - Arcstar Universal Oneイーサネット専用線 セールス(スマートライフ) ポスト 受入 参考 4.dポイント・d払い既存加盟店へのデジタルマーケティングを活用した販売促進支援 D ビジネスデザイン(スマートライフ) ポスト 受入 参考 5.自治体に向けた新たなヘルスケアサービスの企画とセールス統括を担うプロダクトマネージャー D - 健康マイレージ 6.クレジットカードサービス/dカードにおけるサービス戦略・企画 D - Theo+docomo×dカート積立投資 7.映像配信メディア「Lemino」向けオリジナルコンテンツの制作業務 D - 「Lemino」サービスサイト 8.dポイントクラブ会員基盤の拡大、及び新たな価値創出/サービスグロース検討 D - カボニューレコード プロダクト・サービスエンジニア ポスト 受入 参考 9.新デバイス・サービスの企画・開発 D セールス(法人) ポスト 受入 参考 10.法人のお客さまへの営業活動 C ビジネスデザイン(法人) ポスト 受入 参考 11.新サービスやビジネスの企画/プロモーション施策の立案 C - Smart Go / SmartGo Staple - OPEN HUB ソリューションエンジニア ポスト 受入 参考 12.法人のお客さま向けの新サービスの開発 C 13.法人向けのICTソリューション提供 C 14.次世代ネットワークサービスのソフトウェアエンジニア C - OCNにネットワークコントローラ入れてみたよ 15.次世代ネットワークサービスのセキュリティ機能開発 C 16.サイバー攻撃からお客さまを守るマネージドセキュリティサービスのサービス戦略/企画/マーケティング業務や、実際のお客さまへのセキュリティコンサルティング業務 C 17.オンライン英会話・オンライン医療などのビデオ通話を実現するプラットフォームサービス「SkyWay」の技術開発 C - SkyWay 先端研究開発(AI・データサイエンス) ポスト 受入 参考 18.機械翻訳/語学学習に関わる言語処理AIの研究開発 D 19.パブリッククラウドを活用した超大規模データ処理・分析環境開発 D 20.新しい画像認識技術の実用化開発および画像認識技術を活用したソリューション創出 D 21.FinTech領域における新規データ分析手法の検討業務 D 22.データ分析アプローチで全社・現場の課題を解決し、DXを推進(主にOSSを用いた分析システム) C 23.データ分析アプローチで全社・現場の課題を解決し、DXを推進(主にサービス開発組織の分析) C 24.データ分析アプローチで全社・現場の課題を解決し、DXを推進(主にセールス部門向け(大企業・中小企業担当)の分析) C 25.お客さまに具体的な価値を提供するAIテキスト分析プロダクトの開発 C 先端研究開発(ソフトウェア・セキュリティ) ポスト 受入 参考 26.大規模にクラウドを利用するドコモのCCoE(Cloud Center of Excellence)エンジニア D 27.エンタープライズ向け大規模クラウド/ネットワークサービスを支えるコントローラ開発 C - DSIGW - FRA - FIG - 2021 Cloud Meetup Egawa 「入社してから今までのお話」 - SDPFクラウド/サーバー ESIチームにおけるCI改善の取り組み - クラウドサービスのウラオモテ - Managed Load Balancer のつくりかた 28.エンタープライズ向け大規模クラウドサービス(仮想サーバー)のソフトウェア開発 C - Open TechLunch: 元ウェブ系エンジニアが語る IaaS(VM屋さん)の開発ってなにしてんの? - CODT2022: エンタープライズ向けクラウドサービス 仮想サーバー基盤開発のリリースサイクル改善 - CODT2021: エンタープライズ向けクラウドサービスにおける大規模・商用環境でのホストOSバージョンアップ - CODT2020: エンタープライズ向けクラウドサービスにおける大規模・商用環境でのOpenStackバージョンアップとVMHAの実運用 29.エンタープライズ向け大規模クラウド/ネットワークサービスを支える共通機能のソフトウェア開発 C 30.エンタープライズ向け大規模クラウドサービスのコントローラにおけるSRE推進のためのクラウドネイティブな共通基盤開発・運用 C - Blue-Green デプロイメントを採用したデプロイの仕組みを実装して共通基盤として導入した話 31.仮想アプライアンス専用基盤に関わる仮想サーバ技術開発 C 32.NTTグループ向けDevOps基盤「Qmonus」の内製開発および導入支援 C - OCNにネットワークコントローラ入れてみたよ - Cloud Native環境におけるエンタープライズシステムに対する高可用性実現への取り組み - DevOpsプラットフォームの取り組み, NTTコミュニケーションズ(NTTドコモの法人事業) エンジニアズブログ 33.CSIRTでのサイバー攻撃への対応実践と高度化 C 34.Webアプリケーションの脆弱性診断実践 C 35.テレプレゼンス(遠隔操作ロボット)の研究開発 C - テレプレゼンスPJ インターン参加レポート - 63. テレプレゼンス・ロボット・最後にRust w/ nakakura, kmat - みんなの夢を叶える「走るコタツ」を作ってみた - NTT Com、ロボットやカーボンクレジットなど先進ICTサービスを披露 36.データ分析基盤エンジニア C 38.サイバー攻撃の原理を理解し、攻撃インフラ(マルウェアインフラ)を解明するセキュリティアナリスト C - アクセスログ解析サービスVisionalistで利用していたドメイン(tracer[.]jp)の脅威分析と注意喚起 - 本当にあったドロップキャッチの怖い話 〜Visionalistの場合〜 (InternetWeek 2022) - サイバー脅威インテリジェンス(CTI)配信はじめました - インターンシップ体験記 〜Cobalt StrikeのC2サーバ追跡〜 41.Webアプリケーションソフトウェアエンジニアとして、コミュニケーションサービスの新機能開発 C - NeWork 先端研究開発(ネットワーク・デバイス) ポスト 受入 参考 42.5Gデバイス観点から5G NW運用を解明する無線通信スペシャリスト D 43.人間拡張技術を用いた体験共有に関する評価 D - 離れていても触れられる。「フィールテック™」が未来のコミュニケーションを変える。 - 6Gの時代に向けて挑む、「スキルをダウンロードする」技術とは。 44.6Gユースケース、要求条件、要素技術検討 D - ドコモの標準化への取組み 45.HAPS実用化に向けた技術検討 D - 世界初、成層圏下層から38GHz帯の電波伝搬実験に成功 - エアバス、NTT、ドコモ、スカパーJSATの4社がHAPSの早期実用化に向けた研究開発などの推進を検討する覚書を締結 - 未来を考える研究開発で、“世界のあたりまえ”を変える 46.携帯電話基地局などからの電波の測定技術検討 D - ドコモの電波の安全性に関する取組み - (お知らせ)国内初、マンホール型基地局の試作機を開発 - モバイル基地局環境における電波強度評価法 47.All Photonics Networkのための次世代光伝送ネットワークインフラおよびサービス開発エンジニア C 48.エンタープライズ向け大規模クラウドサービスを支えるネットワーク開発 C - OpenTech Lunch: クラウドの作り方(使い方じゃないよ) - EVPN Anycast Gateway を商用導入した話 - JANOG: エンタープライズ向けクラウドのSDN基盤の安定化への挑戦 - CNTOM: NFVサービスの 試験自動化とCI/CD 49.5G・IoTおよびIOWNを支えるNW基盤開発エンジニア C 50.ローカル5G無線(RAN), コア(5GC), トランスポートネットワーク(TN)の技術検証 C - Interop Tokyo 2022 〜400G-ZRを用いたイーサネット回線とローカル5G検証・展示のご紹介〜 リーガル ポスト 受入 参考 51.企業経営を支える法務業務 D/C
はじめに こんにちは、イノベーションセンターの内藤です。NTTコミュニケーションズ株式会社 (以下、NTT Com) は、世界最大級のネットワーク展示会である 「Interop Tokyo 2023(会場:幕張メッセ、会期:2023年6月14日〜16日)」 において構築されるShowNet 1 に対しコントリビューターとしてローカル5G(以下、L5G)システムを提供し、実機運用することに成功しました。 昨年 2 に引き続き、今年はより高度なマルチベンダーでの5Gコア/RAN端末の相互接続やネットワークスライシングにチャレンジ。実験試験局の免許も取得して無線区間をOTA 3 とし、End-to-Endでアプリケーションのトラフィック流通を実現しました。 本記事ではその構成やスライシング手法、技術的なチャレンジについて解説します。 マルチベンダーによるEnd to Endスライシング 私たちは、ユーザーの要求に応じてネットワークやエッジコンピューティング環境といったリソースを柔軟に提供することを目標としています。 それを達成するには、ユーザーやアプリケーション単位での細かい粒度で品質の異なるNW経路を提供する、ネットワークスライシング技術が必要になります。 ネットワークスライシングの説明は昨年の記事が参考になります。今回は詳細記載を省略します。 NTT ComではShowNetにて、昨年に引き続きマルチベンダーによる基地局(gNB)から5Gコアの先のData Network (N6) を含めたEnd to Endスライシングの実現にチャレンジしました。 下図が構成となります。順番に解説していきます。 スライシングに関する昨年からのアップデートは以下3点です。 1.マルチベンダーでのスライシングにチャレンジ Capgemini Engineering ViNGCは、Kubernetes/OpenShiftで動作する5GCであり、各Functionは1つ以上のPodとして構成されます。 C/U分離が可能であることから、UPFはKaloom UPFを使用します。Kaloom UPFはOpenShift上で動作するUPFであり、Edgecore Networks社のホワイトボックススイッチ上で動作します。 LeafとUPFからなる1つのクラスタで、複数の仮想UPFを動作させることが可能です。 ネットワークスライシングの手法は多数あり、昨年はS-NSSAIを用いた手法を実施しました。今回はマルチベンダーで相互接続をする観点から、インターオペラビリティの成熟度も探りつつ、仮想UPFを3台構成し、それぞれのN6に異なるDNN 4 を設定する方式を採用しました。DNNに紐ついたバックボーンネットワークは異なる品質設定がされており、UEではDNNを切り替えることで通過するネットワークの変更ができます。これをDNNスライスと定義しました。 2.5GCの設置場所としてMECを想定し、実サービスであるSDPF Edge 5 と連携 SDPF Edgeは任意のVM+アプリケーションをクラウド上の管理コンポーネントからZTPし、ユーザ拠点で起動できるサービスです。ViNGCの起動にはリソースが多く必要だったため、まだ商用ラインナップにはない高リソースMECをカスタマイズして作成し、Kubernetesを起動。5GCを構築しました。 3.自社開発のオーケストレーターであるQmonusを利用し設定自動化を実現 ViNGCに対して加入者データの投入やスライス作成/削除は、単体のAPI実行で完結するものではなく、複数のAPIを直列に、かつ5GC/UPF/バックボーン機器それぞれに対して操作が必要​となります。 NTT Com内製のマイクロサービス開発フレームワーク「Qmonus SDK」のトランザクション機能を用いて、システムを跨いだオーケストレーションスコープの一貫性を担保できます。トランザクションの状態と進行状況はフレームワークで管理されており、処理失敗時にはトランザクションの進捗状況に合わせて、各システムに対して最適な打ち消し処理を実行できます。 Qmonusを用いることでAPIによるデータ投入を実現しました。 なお、今回私たちはAWS Outposts ServerについてもShowNetにコントリビュートし、その上にNTTドコモの5GCを構築しました。この5GCについてもQmonusとの連携を実現しています。NTTドコモのコントリビューション部分については、NTTドコモのENGINEERING BLOG 6 をご覧ください。 実験試験局の運用 昨年のShowNetではUE – RU – CU/DUの無線区間はエミュレートしましたが、今年は免許申請を行い、電波を発波する実験試験局を運用しました。NTT Comには無線従事者免許を保有しているエンジニアが多数在籍しています。遵法し適切に電波を使用できるよう、輪番を組んで運用しました。 gNB装置は昨今登場した「RU/CU/DU一体型」を特徴とするものを採用。Airspan社のAirSpeed 1900を幕張メッセのhall6に設置しました。Interop準備期間中、遮蔽物が少なく、同時接続するUEの数も少ない好条件では期待以上の速度(DL790Mbps)が観測できたことも。 IoT Connect Gatewayとの接続 私たちはL5Gとその他サービスの組み合わせによる新しいユースケースの発掘にも日々挑戦しており、今回はN6に接続するサービスとしてIoT Connect Gateway(以下、ICGW)を選択しました。 ICGWは、IoTデバイスの通信をクラウド側でプロトコル変換(暗号化など)することでお客様の開発・運用コストを削減できるサービスです。 今回はCO2センサを会場に複数設置し、L5Gを介しICGWに接続。データの可視化を行いました。 ICGWはNTT Comが提供するSDP 7 サービスのひとつであり、今後も他のSDPサービスとL5Gとの連携を狙っていきます。 おわりに この記事ではInterop Tokyo 2023(会場:幕張メッセ、会期:2023年6月14日〜16日)において構築されたShowNetについて、L5GのマルチベンダーによるEnd to Endスライシングなどを紹介をしました。今後は、今回のフィールドテストの成果を踏まえより多種多様なユースケースに対応できるネットワークスライシングの方式や、UE/RU/CU/DU/5GC/UPE構成のベストプラクティスとなる提供方法を探り、NTT Comのネットワークサービスへの応用について検討していきます。 なお、私たちのチームはインターン 8 も募集しています。一緒にL5Gの高度化に取り組んでくれる仲間を募集しています。 ぜひご検討ください。 ShowNet: Interop Tokyoにおいて、様々な機器・サービスの相互接続性検証を実施するとともに、近未来のサービスアーキテクチャを実際に動かしている形で見ることができる世界最大規模のライブネットワークデモンストレーションです。Interop Tokyoへの出展社がインターネットへの接続性を利用して製品の動態展示のほか、来場者のインターネットへのアクセスとしても利用されるネットワーク。 https://www.interop.jp/2023/shownet/ ↩ 昨年: ShowNet2022でも我々はネットワークスライシングの取り組みを実施しました。 https://engineers.ntt.com/entry/2022/06/15/090043 ↩ OTA: Over The Airの略。データの送受信を無線通信で行う技術をさします。 ↩ DNN: Data Network Nameの略。5Gにおいて、UPFのN6以降のネットワークをさします。 ↩ SDPF Edge: NTT Comが提供中のMEC(Multi-access Edge Computing)サービスです。 https://www.ntt.com/business/sdpf/service/edge.html ↩ ENGINEERING BLOG: https://nttdocomo-developers.jp/ ↩ SDP: データ利活用に必要な機能をワンストップで提供するNTT Comのアーキテクチャです。 https://www.ntt.com/business/sdpf/about.html ↩ インターン: 「先端研究開発(ネットワーク・デバイス)」分野の「ローカル5G無線(RAN), コア(5GC), トランスポートネットワーク(TN)の技術検証」が私のチームです。 https://information.nttdocomo-fresh.jp/event/on-site-internship/ ↩
目次 はじめに 開発背景 機能紹介 実際に使ってみた ストレージ転送機能のセットアップ SSH一括実行機能のセットアップ SSH一括実行機能の動作確認 おわりに はじめに こんにちは、5G & IoT部/IoTサービス部門のIoT Connect Gateway (ICGW)サービス開発チームの岩田です。 我々のチームでは日頃からインキュベーション開発というものに取り組んでおります。 インキュベーション開発では、近い将来の需要や新規分野への展開を見据えた機能を実証実験的に開発し、実際に需要が上がった際に迅速に機能を商用展開することを目的としています。 本記事では、インキュベーション開発として実装されて機能の1つである SSH一括実行機能 を紹介します。 開発背景 ICGWでは2022年12月から リモートアクセス という機能の提供を開始しました。 リモートアクセス機能では、お客様の必要な時にセキュアなリモートアクセス用の経路をオンデマンドで提供します。 この機能を活用することで、お客様拠点や外出先から遠隔地の各デバイスにアクセスし、遠隔監視や設定変更などのメンテナンスを行うことができます。 ICGWを利用可能なSIMを装着したデバイスであれば、デバイス側に特別な設定をする必要はなく、SSH接続を含めた任意のデバイスポートにアクセスできます。 また、リモートアクセス経路を作成する際に、デバイスへアクセス可能なソースIPを制限できるのでセキュアな経路を確保できます。 利用料金に関しては、使用した月にのみ料金が発生する課金方式をとっているため、必要な時にだけ最低限のコストでご利用いただけます。 図1 リモートアクセス機能の概要図 リモートアクセス機能をさらに活用していく上で「あるデバイスでの設定変更やアップデートを他のデバイスにも同様に行いたい」というケースが想定できます。 例えば、各デバイスに蓄積されたログファイルを定期的に一括で取得したい・該当のモジュールやファームを一括で更新したい・最新の設定ファイルを各デバイスに配布したい、といったケースが考えられます。 デバイスの数が少ないうちは運用者が逐一接続して作業できますが、デバイスが増えるほど困難を伴います。 この課題を解決するために開発された機能がSSH一括実行機能になります。 機能紹介 図2 SSH一括実行機能の概要図 SSH一括実行機能は「特定のデバイスグループに対してSSH接続し、ユーザ定義したスクリプトを実行する機能」です。 利用の流れは以下のようになります。 SSHグループの設定 手動でSSH一括実行をトリガー リザルト画面で結果を確認 ステップ1では、一括実行対象のSIMや実行するスクリプトを登録します。 SSH接続では鍵認証方式を利用するため、鍵情報やログインユーザなどのセットアップも行います。 ステップ3では、実際にデバイス上で実行されたコマンドの結果をリザルト画面から確認できます。ログテキストやexitコードといった詳細情報を提供しています。 実際に使ってみた 今回は「各デバイスに蓄積されたファイルを一括でAmazon S3に送信する」というケースを例にとって、SSH一括実行機能を紹介します。 図3 各デバイスのファイルを一括でAmazon S3に送信するユースケース ユーザがSSH一括実行機能をトリガー ICGWが各デバイスに対してSSH接続しコマンドを実行 デバイスからICGWに対してストレージ機能を使いファイルを送信 送信されたファイルをAmazon S3へ転送 図3のフローを実装することを目標にセットアップをしていきます。 デバイスとして、Aterm MR10LN とRaspberry Piをそれぞれ2セット用意しました。 Atermには IoT Connect Mobile Type S のSIMを挿入してあります。 図4 AtermとRaspberry Pi 図5 ICGWとデバイス間の接続構成 ストレージ転送機能のセットアップ まず、デバイスからAmazon S3へデータを送信するためのセットアップを行います(図3のステップ3-4)。 デバイスから直接Amazon S3へデータを送信することも可能ですが、今回はデータの暗号化やクラウド接続をサポートできるICGWの ストレージ転送機能 を利用します。 ストレージ転送機能の詳細に関しては 過去の記事 で取り扱っておりますので、そちらもご参照ください。 図6 ストレージ転送機能の設定画面 ストレージ転送機能の設定画面では、ICGW側のデータの受け口である エントリーポイント やデータの転送先である 宛先設定 、付与するデータを設定する必要があります。 今回はICGWのポータルから図6のように設定しました。 ポイントとしては宛先設定のファイルパスを $YYYY-$MM-$DD/$imsi/log.txt とすることで、データ送信時にICGW側で自動的に日時やSIMの固有識別子であるIMSI(International Mobile Subscriber Identity)を埋め込んでくれるようにしています。 そのため、各デバイスから同一のコマンドでファイルを送信しても、Amazon S3上でファイル名が重複しないように転送できます。 デバイスからのファイル送信コマンドとして、以下のコマンドを実行します(ICGWのエントリーポイントは こちら をご参照ください)。 curl -v -X PUT --data-binary @./Documents/test/ssh/sample_log.txt http://***:8081/S3_ssh SSH一括実行機能のセットアップ 次に、ICGWからデバイスへSSH接続するためのセットアップを行います(図3のステップ2)。 以下のコマンドで、 raspberry-pi-zero という名前の公開鍵認証用キーペアの作成し、その公開鍵をRaspberry Piへ転送します。 # キーペア作成 ssh-keygen -t rsa -b 4096 -f raspberry-pi-zero # 公開鍵転送 ssh-copy-id -i ~/.ssh/raspberry-pi-zero.pub user@raspberrypi.local 鍵の準備ができたのちに、ICGWのポータル上でSSH一括実行機能の設定をします。 Secret Key には先ほど作成したキーペアの秘密鍵を、 Command にはストレージ転送機能のセットアップで使用したコマンドをそれぞれ登録します。 今回は2デバイスを対象に実行するので、 SIMs には該当の2SIMを登録しています。 図7 SSH一括実行機能の設定画面 SSH一括実行機能の動作確認 一通りの設定を終えたので、実際にSSH一括実行機能の動作を確認します。 図8 SSH一括実行機能のトップ画面 図8の EXECUTE から手動でトリガーします。 実行が終わったのちに、ICGWのポータル上から各デバイスに対するコマンドの実行ログを確認できます。 図9では Status や Exit Code が表示されていますが、さらに各IMSIを選択することで図10のような詳細な実行ログテキストも確認できます。 図9 SSH一括実行機能のログ画面 図10 SSH一括実行機能のログ詳細画面 ポータル上のログからSSH一括実行機能が問題なく動作していることがわかったので、Amazon S3にファイルが送信されているか確認します。 図11のように日付のフォルダが作成され、その中にIMSI毎のフォルダも作成されました。図12からIMSIのフォルダにはデバイスから送信されたファイルが格納されていることも確認できました。 図11 デバイスからAmason S3へファイルを送信した結果1 図12 デバイスからAmason S3へファイルを送信した結果2 以上で、SSH一括実行機能を活用した「各デバイスに蓄積されたファイルをAmazon S3に一括で送信する」ケースの実装および動作確認を行うことができました。 おわりに 今回はインキュベーション開発物である、SSH一括実行機能を紹介しました。 まだインキュベーション段階ということもあり、本機能は必要最低限のものとなっております。 さらなる機能追加として、定期的に実行できるようなスケジュール機能、デバイスに応じたコマンドを実行できるようなプレースホルダ機能などを検討しております。 皆様の反響次第では近い将来に商用展開できるかも(?)しれないので、ぜひお声をいただけると嬉しいです! 本記事を通して、ICGWに興味を持っていただけたら幸いです! ICGWに関するお問い合わせ先 IoT Connect Gatewayサービス詳細 ICGWに関するお問い合わせ先 トライアル、サービス導入に関するお問い合わせ 資料請求・お問い合わせフォーム 開発チームへのお問い合わせ(お手数ですが@を半角文字に置き換えてください) メールを送る
はじめに 当ポストは、低遅延配信の技術であるWHIP(WebRTC-HTTP Ingestion Protocol)を自分で動かしてみたい方へ向けた記事となります。 WebRTCを利用した配信映像の集信プロトコルであるWHIPは現在Internet-Draftではありますが、配信技術者やWebRTC技術者の注目を得て、実際に動かせる環境が整ってきました。 当ポストでは、WHIPが動く環境を作り、自前のWebRTCスタックをWHIPで使う簡単な方法を紹介します。 とはいえInternet-Draftということもあり、「WebRTCなら聞いたことあるけど、WHIPって何?配信とWebRTCが関係あるの?」という方も多いと思いますので、最初はWHIPの紹介から入りたいと思います。 WHIPとは WHIP は、WebRTCを利用したインジェストのためのHTTPSベースのシグナリングプロトコルです。 インジェストというのは、放送機器からメディアサーバーに映像音声を送信することを言います。 人によっては"アップストリーム"、"打ち上げ"などの方が馴染み深い言葉かもしれません。 つまりWHIPは、誤解を恐れずにいうとRTMPのような配信のアップストリームにWebRTCを使おうといった試みです。 さらにWebRTCは、リアルタイム性を重視した双方向コミュニケーションの技術スタックです。 Webで使えるビデオ通話の技術ですね。 WebRTCの実体は大別して以下の特徴を持ったプロトコルセットです。 リアルタイムメディア伝送のためのワイヤプロトコルのセット メディアストリームを設定・制御するための記述プロトコル(SDP) これらにより、どうやって端末間の通信を確立するか?どうやってパケットをほどき、どうやって映像・音声として解釈するか?といった課題を柔軟に解決しています。 最近はこのリアルタイム性やセッションの自由度などから、大規模配信のメカニズムとしてWebRTCの利用が人気を集めており、いくつかの企業がWebRTCベースのメディア配信ネットワークを展開しています。 さて、WebRTCをアップストリームに利用しようとしたとき、ひとつの課題が浮き上がります。 WebRTCを利用するサービスでは、それぞれが独自にシグナリングプロトコルを開発する必要があるということです。 セッションに必要な情報は用途によって異なるという考え方のため、WebRTCではセッション確立までのプロトコルが規定されていないことが理由です。 ただし放送の場合はメディアを送るためにエンコーダと呼ばれる専用の機器を用いることが多いため、WebRTCを利用したい場合、サービス毎に専用機器へシグナリングプロトコルを実装する必要があります。 そういった背景で立ち上がったのがIETFのWISH(WebRTC Ingest Signaling over HTTPS) WGであり、現在は放送機器からWebRTCメディアサーバーへのセッションを確立するためのシグナリングプロトコルである WebRTC-HTTP ingestion protocol (WHIP) がInternet-Draftとして提案されています。 このWHIPというプロトコルで、どういった順番でHTTPリクエストを出して、どういった内容のHTTPレスポンスを返してね、といったことが決められている訳です。 WHIPを体験してみる WHIPを体験してみるという場合でも、WHIPをこれから実装してみるという場合でも、まずは今実際に動作するソフトウェアのことを知っておくと役に立ちます。 簡単に、WHIPクライアントおよびWHIPサーバーの紹介と動かし方の解説をしたいと思います。 これ以降、配信映像の視聴方法としてブラウザは最新版のGoogle Chromeを推奨します。 simple-whip-server (WHIP server) 手軽に試せるWHIPサーバーは、janus-gatewayを用いた meetecho/simple-whip-server があります。 これはWHIPサーバーのエンドポイントになりつつ、janus-gatewayのAPIを操作してビデオルーム上にWHIPクライアントのメディアを流してくれます。 simple-whip-serverの動作条件としてHTTP, WebSocketを有効にしたjanus-gatewayが必要なので、まずはそのセットアップから解説します。 janus-gatewayのセットアップ WebSocketを有効にしたjanus-gatewayをビルドします。 まず janus-gatewayの依存解決 を参考に、依存環境を整えてください。 今回はREST APIとWebSocket APIを利用するので、最低限必要なのは当該ページのリストの内以下のものになります。 Jansson libconfig libnice OpenSSL libsrtp libmicrohttpd libwebsockets cmake 環境が揃ったら、リポジトリをcloneして autogen.sh を実行します。 $ git clone --depth 1 https://github.com/meetecho/janus-gateway $ cd janus-gateway $ sh autogen.sh すると configure という実行可能なスクリプトが生成されるので、これを実行します。 ここでjanusの関連ファイルのビルド先を --prefix で指定できます。 デフォルトが /opt/janus 以下なので、適当に設定します。 また、 configure を実行したら Makefile が生成され、 make できるようになるので実行します。 $ ./configure --prefix=/usr/local/janus --enable-websockets $ make ここで、 macOSを利用している方のみ 確認していただく内容があります。 src/transports/libjanus_websockets.la というファイルの中身を読んで、 dlname の値を確認します。 # The name that we can dlopen(3). dlname='libjanus_websockets.1.dylib' 上記のように、 libjanus_websockets.<version>.dylib のフォーマットで書き込まれていると思います。 この version の数字を覚えておいて、次は src/janus.c のプリプロセッサを確認します。 以下のようにライブラリの拡張子を指定している場所があります。 #ifdef __MACH__ #define SHLIB_EXT "0.dylib" #else この 0.dylib を先ほど確認した version の数字となるように編集してください。 例えば、 libtool 2.4.7 な私のmacOS環境で生成したファイルは libjanus_websockets.1.dylib となっていたので、以下のようにしておきます。 #ifdef __MACH__ #define SHLIB_EXT "1.dylib" #else 準備ができたら make install と、janus関連の設定ファイルを有効化するために make configs を実行します。 $ make install && make configs このあとクライアント側で映像コーデックにVP8とH.264を利用したいので、設定ファイルを一部修正します。 <prefix>/etc/janus/janus.plugin.videoroom.jcfg を編集し、 room-1234 の中の videocodec の値を vp8,h264 に変更してください。 room-1234: { description = "Demo Room" secret = "adminpwd" publishers = 6 bitrate = 128000 fir_freq = 10 #audiocodec = "opus" videocodec = "vp8,h264" # もともとは"vp8"のみで、コメントアウトされている record = false #rec_dir = "/path/to/recordings-folder" } この状態でjanusを実行して、最終的に以下のようなログが出れば成功です。 $ <prefix>/bin/janus (省略) Loading transport plugin 'libjanus_http.1.dylib'... HTTP transport timer started HTTP webserver started (port 8088, /janus path listener)... JANUS REST (HTTP/HTTPS) transport plugin initialized! このままjanusを実行させておいてください。以降の試験で利用します。 ついでに、別のプロセスでjanusのビデオルームをブラウザで開けるように、janus-gatewayの html ディレクトリ以下にあるデモHTMLをホストしてください。 $ cd html $ python -m http.server 下記URLが開ければ準備完了です。 http://localhost:8000/videoroomtest.html simple-whip-serverのセットアップ 次にWHIPのサーバーとなるsimple-whip-serverを用意します。 Node.jsが必要になります。 $ git clone --depth 1 https://github.com/meetecho/simple-whip-server $ cd simple-whip-server $ npm i これで準備ができました。 REST API, WebSocketが有効なjanus-gatewayのプロセスが立ち上がっていれば、 npm run start を実行すると以下のようなログが出力され、simple-whip-serverが実行されます。 $ npm run start > janus-whip-server@0.0.1 start > DEBUG=whip:*,-whip:debug,janus:*,-janus:debug,-janus:vdebug node src/server.js [1. Janus] Connecting to Janus: { address: 'ws://127.0.0.1:8188' } janus:info Connecting to ws://127.0.0.1:8188 +0ms janus:info Janus WebSocket Client Connected +13ms janus:info Janus session ID is 1549944700292951 +3ms janus:info Janus instance version: 1.1.3 (multistream) +2ms whip:info Connected to Janus: ws://127.0.0.1:8188 +0ms [2. WHIP REST API] WHIP REST API listening on *:7080 WHIP server prototype started! [ 'Janus OK', 'WHIP REST API OK' ] これでWHIPのサーバーサイドは準備できました。 ここまでで、以下の3つのアプリケーションが動作していることを前提として進めます。 janus-gateway janus-gateway/html の静的サーバー simple-whip-server 次に、janusのビデオ会議の部屋を作りつつ、WHIPクライアントが配信するためのリソースを作っておきましょう。 $ curl -H 'Content-Type: application/json' -d '{"id": "abc123", "room": 1234}' http://localhost:7080/whip/create simple-whip-serverが動いているときに http://localhost:7080 を開くことでWHIP配信先の管理ができるのですが、ここで Endpoint ID=abc123 であり VideoRoom=1234 であるエンドポイントが追加されていることを確認できます。 この状態で http://localhost:8000/videoroomtest.html を開いて、Startボタンを押し、ルーム名に 1234 を入力して Join the room ボタンを押すことで、このあとWHIPクライアントから配信した映像を視聴する画面に移ることができます。 WHIPサーバーを立て、WHIPクライアントが配信した映像を視聴する準備が整ったので、以降は三種類のWHIPクライアントを紹介します。 simple-whip-client (WHIP client) WHIPのクライアント、つまりインジェストを行うソフトウェアとして最初に紹介するのは、simple-whip-serverと対になる meetecho/simple-whip-client です。 かなりシンプルな実装であり、自作のWHIPサーバーの細かい検証をしたい場合では一番扱いやすいと思います。 依存環境として、以下が必要になります。 pkg-config GLib libsoup~=2.4 GStreamer>=1.16 gst-plugins-base gst-plugins-bad libsoup~=2.4 について、今libsoupを入れようとすると3系が入るので、2系を明示的にインストールするよう注意してください。 また、3系がシステムデフォルトになっている場合、ビルド時にpkg-configの参照先が2系になるように注意してください。 例えば私の環境では、ビルド時の環境変数 PKG_CONFIG_PATH に /usr/local/libsoup/2.74.2/lib/pkgconfig を追加しました。 simple-whip-clientのセットアップは以下です。 $ git clone --depth 1 https://github.com/meetecho/simple-whip-client $ cd simple-whip-client $ make make だけで whip-client というバイナリが作成されます。 実行する際は、 -A および -V オプションで配信する音声映像としてGStreamerのパイプラインを入力できます。 GST_DEBUG =WARNING ./whip-client -u " http://localhost:7080/whip/endpoint/abc123 " \ -A " audiotestsrc ! audioconvert ! audioresample ! queue ! opusenc ! rtpopuspay pt=100 ssrc=1 ! queue ! application/x-rtp,media=audio,encoding-name=OPUS,payload=100 " \ -V " videotestsrc ! videoconvert ! queue ! vp8enc deadline=1 ! rtpvp8pay pt=96 ssrc=2 ! queue ! application/x-rtp,media=video,encoding-name=VP8,payload=96 " 起動オプションも豊富で、WHIPのInternet-Draftにあるoptionalな実装を無効にしたりできます。 起動オプションはコマンドライン引数なしの実行か、 -h オプションをつけて実行することで確認できます。 GStreamer (WHIP client) ソフトウェアの音声/映像処理によく使われるGStreamerでも、 バージョン1.22 からWHIPがサポートされました。 利用するには、 gst-plugins-rs が必要です。 ここで追加された whipsink を利用すれば、以下のようなパイプラインでgstreamerから映像配信ができます。 gst-launch-1. 0 whipsink name =whip whip-endpoint =" http://localhost:7080/whip/endpoint/abc123 " \ audiotestsrc ! audioconvert ! opusenc ! rtpopuspay pt = 100 ! queue ! " application/x-rtp,media=audio,encoding-name=OPUS,payload=100 " ! whip. \ videotestsrc ! videoconvert ! queue ! vp8enc deadline = 1 ! rtpvp8pay pt = 96 ! queue ! " application/x-rtp,media=video,encoding-name=VP8,payload=96 " ! whip. OBS Studio (WHIP client) OBS Studioでは現在PRのDraftという状況ですが、 Sean-Der/obs-studio でWHIPを使うプラグインが開発されています。 PRは #7926 で、バイナリが欲しい場合は自分でビルドする他、OBS StudioではGitHub Actionsでのビルドが行われているので自身の環境にあったバイナリをArtifactからダウンロードすることもできます。 下記ページの最新のビルドから、Artifactsにアップロードされているファイルをダウンロードできます。 macos-x86_64 のように対応するOS・CPUアーキテクチャがファイル名に記されているので、自分の環境にあったパッケージをダウンロードしてください。 Actions・obsproject/obs-studio 自分でビルドするか、Actionsからダウンロード・インストールしたOBS Studioを利用すると、配信先の設定の選択肢に WHIP があります。 これを選択し、サーバーに http://localhost:7080/whip/endpoint/abc123 を入れることでOBS StudioからWHIPでの配信ができます。 おわりに 当ポストではWHIPのサーバーとしてsimple-whip-serverを、クライアントとしてsimple-whip-client・GStreamer 1.22・OBS Studioを紹介しました。 この記事がWHIPへの興味に繋がったら幸いです。 最後に宣伝をさせてください。 NTT Comには Smart vLive というサービスがあり、実はWebRTCを利用した配信をしています。 インターネット配信におけるWebRTCのリアルタイム性に注目しており、インジェスト側ではなくメディアを配信する側でWebRTCを利用しています。 本ポストでは「なんで配信をWebRTCでしたいの?」という論点を取り上げませんでしたが、Smart vLiveの事例を見ていただくとどんな利用シーンがあるのかイメージしやすいかと思います。 私が個人的に好きな事例はオークション/ライブコマースです。 リアルタイム性がそのまま価値につながる利用シーンの1つだと思います。 オンサイトとリモートの時間的優位性を極力減らしたときにどんな価値が生まれるのか? 未来の当たり前に向かって、技術開発はもちろん、こういった視点での価値創出も一緒に取り組んでくれる仲間をNTT Comでは募集しています。 WebRTC配信技術の開発をしている私のチームの募集ポストは こちら になります。
2023/5/19更新: 本記事のタイトルを「インターンシップ体験記 ~RedTeamでの攻撃技術検証業務~」から「インターンシップ生があるSaaSを用いた未知のC2脅威を実証してみた」に変更しました。内容に変更はありません。 イノベーションセンター RedTeamプロジェクトでは、2月に現場受け入れ型インターンシップを実施しました。 本記事は、本取り組みに参加していただいたインターンシップ生による寄稿となります。 インターンシップ生本人の希望により匿名での投稿とさせていただきます。 ※今回注目したあるSaaSに関する発展的な攻撃テクニック(本記事記載のC2への応用を含む)について、NTTコミュニケーションズ RedTeamとして国内外のカンファレンスへ投稿する予定です。 そのため、本記事では具体的なSaaS名の記載を控えます。 よろしくお願いいたします。 はじめに こんにちは、今回NTTコミュニケーションズのインターンシップに参加させて頂いた者です。 現在大学3年生で、大学ではWebセキュリティ、特にXSSの検知・防御に関する研究をしています。 2023年2月に2週間、RedTeamのメンバーとして業務体験をさせていただきました。 この記事ではインターンシップで行った取り組みについて紹介したいと思います。 概要 今回私は、RedTeamサービスを提供するにあたっての攻撃技術の開発・検証業務を行いました。 今回のインターンシップでは、初日と最終日の2日間を現地にて実施し、他の日程はリモートでの実施でした。 参加に至った経緯 私は元々サイバーセキュリティ分野に興味があり、これまでに脆弱性診断、PSIRT(脆弱性通報対応)、インシデントレスポンス、セキュリティツール開発などのインターンシップに参加しました。 インターンシップに参加する中で特にオフェンシブセキュリティに興味を持ち、RedTeamの業務体験ができるインターンシップを探したところこちらのインターンシップを見つけ、今回応募させていただきました。 また、これまでに参加したインターンシップでは長くとも4、5日という期間でしたが、今回は2週間の現場受け入れ型インターンシップということで、 より実務に近い部分で深くセキュリティエンジニアとしての業務を体験できるという点にも興味がありました。 取り組んだこと RedTeamの受け入れポストの応募要項としては、以下のような記述がありました。(2023年2月16日時点) 攻撃者視点を持ち企業のセキュリティ強化をミッションとするRedTeam ●業務内容 RedTeamサービスに関する攻撃技術の開発・検証を経験していただきます。 ■主な業務内容 MITRE ATT&CKをフレームワークとした攻撃技術の開発・検証 実際のサイバー攻撃と同様の技術を用いた、演習形式の企業セキュリティ対策評価 ■RedteamPJの業務一例 https://engineers.ntt.com/entry/2021/12/09/103248 ●応募要件 【必須】 RedTeamに興味があり、攻撃技術の深堀り、習得する意欲のある方 Pythonを用いたプログラミング経験がある方。 【推奨】 情報、通信、コンピュータ系、セキュリティ専攻学科の方 CTFなどのセキュリティコンテスト入賞経験 ●受け入れ会社 NTTコミュニケーションズ株式会社 ●勤務地 〒108-8118 東京都港区芝浦3-4-1 グランパークタワー 現場受け入れ型インターンシップコース | インターンシップ情報 | NTTドコモ新卒採用 主な業務内容の項にあるように、RedTeamサービスに関する攻撃技術の開発・検証に関する業務を行いました。 一般的にSaaSを悪用したC2の脅威について注意喚起されている事例がありますが、今回はまだ世の中に事例がない、 あるSaaSとそのエージェントの仕組みを悪用したC2のPoC(Proof of Concept: 概念実証)コードを開発しました。 初日に取り組むテーマを2つ提示していただき、興味のあるほうを選ぶという形で今回のテーマを進めていくことになりました。 今回開発したC2について まずC2とは、Command & Controlの略で、攻撃者が対象のホストへ侵入した後にホストと攻撃者の間で通信を確立し、 ネットワーク経由で外部からコマンドによる操作が可能な状態を維持する技術です。 今回注目したSaaSでは公式エージェントが提供されており、SaaS利用者はエージェントをインストールしたホストに対し、 SaaSを介して任意の処理を実行させることができます。 攻撃者がこのSaaSをC2として悪用できる可能性があり、今回はその脅威について調査し、実際に実現可能であるかを検証しました。 このSaaSをC2に利用する攻撃者側のメリットは、「通信先が攻撃者の用意したサーバーなどではなくSaaSとなるため悪性通信の判別が難しい」、 「公式から提供されているエージェント実行ファイルからコマンドを実行するため検知されにくい」という点です。 結果として、実際にC2の仕組みをCLIツールとして実装し、C2通信が可能であることを検証によって確かめられました。 また、Microsoft Defender for Endpoint(MDE)を有効にしたWindows環境下で検証したところ、通信の過程では検知がされないという結果となりました。 実装について 言語はPython3で、 Click というCLIツール用のライブラリを使用して開発しました。 コマンドとしては、以下のような構成で実装しました。 シェルコマンドによる命令実行 エージェントに付属のスクリプトエンジンによる命令実行 ファイルアップロード ファイルダウンロード ログ閲覧機能 ファイルアップロード/ダウンロードは、C2を通じて攻撃者と標的ホスト間でファイルを送受信するための機能です。 この機能は、目的達成に必要なファイルの転送やデータの持ち出しのために利用されることを想定しています。 命令の実行やファイルダウンロード/アップロードはSaaSやそのエージェントの機能を利用して実行し、出力結果をログ閲覧機能から確認するという形式になりました。 攻撃者が悪用する場合の実用性に関する検証 提供されているエージェントはシェルコマンドの実行及び、エージェント自身に付属のスクリプトエンジンで命令を実行できます。 付属のスクリプトエンジンを用いる場合、PowerShell等を使用しないため、 Antimalware Scan Interface (AMSI) による検知を回避できる可能性があります。 実際に悪性ファイルとしてInvoke-Mimikatz.ps1 1 を用い、付属のスクリプトエンジンでの命令実行により配布サイトからファイルダウンロードをする際にAMSIにより検知されるかについて検証しました。 結果的にファイルを保存する時点で検知されましたが、悪性ファイルを配信するURLへの通信という段階では検知がされないということが確かめられました。 企業の業務環境などでは認証プロキシが使用されていることがあります。 これらの環境を想定し、認証プロキシ下でC2通信ができるかについて検証しました。 結果として、現状提供されているエージェントはBASIC認証以外には対応しておらず、Kerberos認証やNTLM認証といった認証プロキシ下で通信させるには工夫が必要であるということがわかりました。 エージェントをサービスとして動作させるためには管理者権限が必要となります。 ユーザ権限下で永続化が可能であるかの検証として、永続化の代表的な手法である Boot or Logon Autostart Execution を検証しました。 Windowsでは、 C:\Users\[Username]\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup などに配置したファイルが起動時に自動的に実行されるという機能があります。 ここに、VBScriptで記述したエージェントを起動させるためのスクリプトファイルを配置し、実際に起動時にエージェントが起動することを確かめられました。 PoC全体像 成果報告会について 最終日の前日にセキュリティプロジェクト内で、最終日にはNTTドコモグループ全体で、業務体験を通して得られた成果の報告会を行いました。 特に最終日の成果報告会では、セキュリティエンジニアのポストとして参加したインターン生以外に、ソフトウェアエンジニア、 ネットワークエンジニア、AIエンジニア、ビジネス企画、マーケティング、デザイナーなど様々な部署でのインターン生の成果発表を聞くことができました。 そのため、同年代の様々な就活生の取り組みや、他分野での業務イメージなどが掴めて良い経験となりました。 感想 自分の興味のある部分や実装していく中で思いついた提案などを元に、自由に開発や検証を進めさせていただいたため、インターンシップ期間を通して非常に多くのことが学べました。 業務を行うにあたって、学生が普段触れることのできないような企業向けセキュリティツールに触れることができたことも、とても貴重な経験となりました。 また、開発で詰まった際の相談や検証環境の準備についても親身にサポートして頂き、とてもやりやすい環境で業務に取り組むことができました。 また、期間中にチーム構成や過去のプロジェクトについての説明の時間を設けていただいたり、他部署合同のミーティングに参加させていただいたりしたため、 実際の企業における業務や組織の構成という点でも理解が深まりました。 おわりに 本記事では2022年度冬インターンシップの参加記として取り組みや感想について書かせていただきました。 親身にサポートをしてくださったトレーナー、RedTeam、NTTコミュニケーションズの皆様には大変お世話になりました。 2週間ありがとうございました。 認証情報窃取等の機能を持つMimikatzをメモリ上に読み込み、その機能を利用できるようにするPowerShellスクリプト。 ↩
はじめに こんにちは、イノベーションセンターの野山です。 今回、NTTコミュニケーションズの IoT Connect Gateway (以降ICGW)を用いて、IoT/Edgeのアーキテクチャ検証をしました。 NTTコミュニケーションズの以下メンバーとともに行った結果を共有させていただこうと思います。 角田 佳史 (PS本部 5G&IoT部/IoTサービス部門) 鈴ヶ嶺 聡哲 (イノベーションセンター テクノロジー部門) 野山 瑛哲 (イノベーションセンター テクノロジー部門) PoCの目的とモチベーション 今回のPoC(Proof of Concept)には、主に2つのモチベーションがあります。 1. IoTアーキテクチャのユースケース検証 このプロジェクトでは、IoTのアーキテクチャにおける具体的なユースケースを検証し、その適用可能性を技術的観点から検証することを目指しました。 これにより、読者の皆様にもこの技術を使用するイメージを明確に伝えられるよう、共有したいと考えています。 2. Azureの新技術の調査・検証 また、今回のPoCではMicrosoft Azureにおける最新技術の調査および検証も重要な目的としています。 特に以下の技術要素が注目されており、それらの適用範囲や効果を検証しました。 Azure Arc Enabled k8s この検証を通じて、これらの新技術の特徴や利点、そして適用上の注意点などを明らかにし、 皆様に有益な情報を提供できることを目指しています。 アーキテクチャ概要 先ほど述べた2つのモチベーションに基づいて、以下のようなPoCを実施しました。 このセクションでは、アーキテクチャの概要と主要な要素について説明します。 PoCイメージ 概要として、以下のような画像イメージを想定してPoCを構築した形となります。 ユースケースとしては、製造業などの各拠点に点在する拠点から、部品(ネジ/カメラ/カプセル/etc.....)の故障検知のアーキテクチャを作成しました。 流れとしては以下となります。 地方の拠点から定期的に撮影した画像を、中央拠点に定期的にアップロードする(大体30s~1mくらいの間隔を想定) アップロードされると同時にAWSのS3に画像をバックアップする 中央拠点にアップロードされた画像はその都度、故障推論を行いその様子をリアルタイムで可視化する 地方拠点でアップロードされる画像は15種類くらいを想定しました。とはいえ物理的に地方拠点で設置して、というのはなかなか難しいので サンプルイメージ を用いてランダムにアップロードすることで、イメージに近づけています。 Rawな画像と故障推論された画像が可視化された次の図です。アップロードの頻度によって動的に変わっていきます。 アーキテクチャ概要 このようなPoCのイメージを実現したアーキテクチャ概要が下のイメージとなります。 説明するにあたり、このアーキテクチャを3つの機能(Upload/Eventdriven/Inference)に分けて説明します。 Upload 地方の拠点から、画像をUploadする部分となります。 多くの拠点や様々な画像をアップロードし、S3にバックアップをするためにNTT Comの製品であるIoTConnectGateway(ICGW)を使用しています。 ポイントとしては3つあります。 UploadするDevice側の追加・削除はICGWを通して任意に変更でき、拡張性が高い ICGWのMirroring機能を用いて、Device側は意識することなく、S3へバックアップされる Device側の固有設定をICGWで設定できるため、統括管理しやすい (ConfigManager機能) 概要 要素技術の説明(ICGW) 上記でポイントとしているICGWにどんなサービス/機能があるのかご紹介します。 今回のPoCで使用しているICGWのサービスは以下の3つです。 ストレージ転送機能 ミラーリング機能(近日商用リリース予定) コンフィグマネージャー ストレージ転送機能とコンフィグマネージャーに関する機能説明や取り組みは、 過去連載でも紹介されているのでご興味がある方はご参照ください。 IoT Connect Gatewayを使ってみた 番外編 第2回 ~インターンシップでStorage転送機能を使って開発してみた~ 【IoT Connect Gateway】コンフィグマネージャーのご紹介 【IoT Connect Gateway】コンフィグマネージャーで設定ファイルを生成してみよう ストレージ転送機能 ストレージ転送機能は、クラウドストレージへデータ転送をする機能です。 ICGWの基本機能であるプロトコル変換機能をベースに、デバイス固有のIMSIやIMEIなどのメタデータを付与した上で転送先のクラウドストレージへデータを転送できます。 概要 今回のPoCでは、Amazon S3やオンプレミス上で構築されたMinioへカメラ画像を送信するために、ストレージ転送機能とミラーリング機能を使用しています。 現在、ストレージ転送機能は、AWS S3互換のストレージのみ対応していますが、OSSであるMinioはS3互換なのでICGWの転送先として設定できます。 ただ、 現在のストレージ転送機能単体では、設定されたエンドポイントへのデータ送信時に、複数のクラウドサービスへ同時にデータを転送はできません 。厳密に言えば、複数の転送設定を作成し、転送先毎にデータを送信する仕組みを、IoTデバイスへ実装すれば実現可能です。 とはいえ、転送設定を追加する度に、IoTデバイス側で改修が必要になるため、FOTA(Firmware Over The Air)などの遠隔アップデートのような効率的なファームウェア・ソフトウェア管理の仕組みが無い場合は、見逃せないコストに繋がる可能性があります。 そこで、ICGWチームでは、あるエンドポイントにデータを1回送信するだけで、複数のクラウドサービスにデータを転送できる”ミラーリング機能”を開発しました。 記事執筆時点では、ミラーリング機能はベータ機能として一部ユーザのみに提供しており、今回のPoCを通じて試験的に活用し、必要に応じて機能を改善することで品質を高める取り組みを行っています。 ミラーリング機能 ミラーリング機能は、あるエンドポイントにデータを1回送信するだけで、複数のクラウドサービスにデータを転送できる機能です。クラウドサービスの転送設定(スタンダード・イベント・ファンクションの転送設定など)をミラーリングの転送設定へ紐付けることにより、1回のデータ送信で複数のクラウドサービスへデータを転送できるようになります。 今回のPoCでは、ミラーリングの転送設定にストレージ転送設定を紐づけており、オンプレミスストレージ(Minio)とクラウドストレージ(Amazon S3)に対して同時にデータを転送しています。今回はバックアップ用途で使用していますが、通信データのキャプチャ用途で使用し、ミラーリング機能の転送先クラウドサービスでログ解析を行うなど、問題切り分けやセキュリティにこのミラーリング機能が寄与できると考えています。 コンフィグマネージャー コンフィグマネージャーは、IoTデバイスごとの設定ファイルの生成と配信ができる機能です。IoTデバイス毎の設定ファイルの生成および配信設定は、ポータル上から簡単に行えます。 今回のPoCでは、カメラ画像のアップロード間隔を変更するためにコンフィグマネージャーを使用しており、IoTデバイスの要件に応じた設定ファイルの配信を実現しています。今回はアップロード間隔の変更に使用していますが、設定ファイルの内容次第で様々な要件に対応できます。 Eventdriven 中央拠点にUploadされた画像のEventをTriggerに推論するまでのEventを制御する部分となります。 ポイントとしては3つあります。 Kubernetes上で開発を効率的にするためAzureFunctionsを使用 複数のEventをハンドルするためにAzure EventGridを使用 これらはAzureArcの機能の一部としてオンプレでも使用可能 概要 要素技術の説明(Azure Arc Enabled K8s) 今回、Eventdrivenの機能を実装するにあたり Azure Arc Enabled K8sを使用しています。 主要な機能が5つあり、オンプレ/パブリッククラウドなど実行場所を広く選べる使用感の高さが魅力です。 またこの Azure Arc Enabled K8s には AzureFunctionsとEventgridの機能がリリースされており、概要としては以下となっています。 Eventdriven説明 これらの機能を用いてEventdrivenの機能を実装しており、 概要フローとしては以下となっています。 また概要フローの中には、さらに2つのサブフローが存在し、それぞれについて詳しくご紹介します。 イベントの送信 以下のようにAzureClIを使って、EventGridのリソースを作成できます。 ルーティング先のEndpointやPathを意識していれば簡単に作成できると思います。 実際の画面はこんな感じです。 推論の実行 また、Eventがルーティングされたあとに推論処理をトリガーするAzureFunctionsの展開方法についても概要を説明いたします。 Inference TriggerされたEventから推論する部分です。 ポイントとしては2つあります。 15種類の画像を推論するため、GPUの割当効率を考える必要がある。 この問題をマルチインスタンスGPUを用いて解決している。 概要 要素技術の説明(Mig) 上記での問題についてマルチインスタンスGPUを用いて解決しています。 まとめ 以下に今回用いた技術をまとめてみます。 本記事では、IoTアーキテクチャのユースケース検証と、Azureの新技術の調査・検証を目的としたPoCプロジェクトについて説明しました。 この検証を通じて、IoTアーキテクチャにおける具体的なユースケースの適用可能性を技術的観点から検証し、 EdgeにおけるICGWとAzureの主要技術(Azure Arc Enabled Kubernetes)の特徴や利点、適用上の注意点などが参考になれば幸いです。
はじめに こんにちは、インターン生の 魏心宇 と申します。 2023 年 2 月 6 日から 2 週間にわたって、NTT Com の現場受け入れ型インターンシップに参加させていただきました。 普段は大学で SR (セグメントルーティング) を用いたトラフィックエンジニアリングについて研究しています。 今回のインターンシップでは「SR を用いたキャリアネットワークの開発」をテーマに、NTT Com 発の OSS である Pola PCE への SRv6 機能実装・検証に取り組みました。 この記事では、2 週間の開発体験をご紹介します! インターンシップに参加したモチベーション 私は学部 3 年の冬、 NTT Com TechWorkshop 「プロのネットワークエンジニアと学ぶ!ISP ネットワークのつくりかた」 に参加したことがきっかけで、SR という斬新なネットワークアーキテクチャを知り、技術の素晴らしさに感銘を受けました。 SR を利用することで、従来では実現困難であった複雑な経路制御が簡単に実現可能となるため、国境を超えた高品質なネットワーク回線や特定のアプリに対するネットワークの混雑解消など様々な可能性を生み出し、新たなネットワークサービスを開拓できると期待しています。 NTT Com の R&D 部門であるイノベーションセンターでは SR をはじめとする次世代インターネット技術の研究開発が行われており、独自のアーキテクチャである Multi-AS SR をはじめとした先進的な社会実装の最前線となっています。 大学院に入り、日々の研究とネットワーク運用を通して最先端技術に触れる機会が増える中で、企業ではどのようなネットワーク技術が求められ活用されているのかを学びたいと思うようになり、今回のインターンシップに応募いたしました。 インターンシップで取り組んだこと 今回のインターンシップでは、SR-TE を一元的に管理するための OSS 実装である Pola PCE に対する SRv6 機能の追加と、複数のベンダーの機器(Cisco、Juniper)との相互接続を目標として定めました。 インターンシップの前提として、NTT Com イノベーションセンターではマルチベンダー機器環境で SR を検証しています。 検証内容については Multi-AS Segment Routing 検証連載 で公開されています。 SR、SR-TE、PCE とは何かについて詳しく紹介されているため是非参考にしてください。 [Multi-AS Segment Routing 検証連載#10] PCE を用いた SR-TE の一元管理 で紹介されている通り、SR-TE の実装には各 PE ルーターへの設定が必要であるため、台数が増えると管理が複雑になります。 そこでコントローラーを用いた SR-TE の一元管理により、パス計算の効率化や機器設定の簡素化などが期待できます。 Path Computation Element(PCE)は、前述した SR-TE の一元管理を実現するための技術です。 PCE には発行済み LSP/SR Policy を管理しない Stateless PCE と、これらの情報を管理する Stateful PCE が存在します。 Stateful PCE は既存の LSP/SR Policy を管理するため、それらを条件として考慮した複雑な経路を計算することが可能となります。 また、Stateful PCE には、クライアントである PCC からのリクエストに基づいた経路計算のみを行う Passive Stateful PCE と、自ら経路を発行し PCC へ送信する Active Stateful PCE が存在します。 Active Stateful PCE は新規 SR Policy の発行や既存 SR Policy の更新などの操作ができるため、SR Policy の集中的な管理に適しています。 PCE-PCC の間や複数の PCE 間の通信は、 RFC5440 により定義される Path Computation Element Protocol(PCEP)を用いて行われます。 Pola PCE は、SR-TE の一元管理を実現するための Stateful PCE であり、Active Stateful PCE として動作し、SR-TE の一元管理を実現します。 Pola PCE の概要は Pola PCE で SR 網の TE を体験してみよう! にて紹介されていますので、ぜひ参考にしてみてください。 インターンシップ参加時点では、Pola PCE の実装は SR-MPLS のみを対象としていました。 そのため、Pola PCE を Multi-vendor で動作する SRv6 PCE へと拡張することを今回のインターンシップの目標と定めました。 PCEP プロトコルの SRv6 拡張は draft-ietf-pce-segment-routing-ipv6 にて定義されています。 まだ Internet-Draft で議論中の技術であるため、各ベンダーの SRv6 PCC 機能の実装状況を確認しつつ、開発内容を調整する必要があります。 以下では、PCEP プロトコルの SRv6 拡張およびインターンシップでの実装内容を具体的に紹介します。 PCEP Extensions for SRv6 draft-ietf-pce-segment-routing-ipv6 では、RFC8664 と比べて主に以下の内容が追加されています。 SRv6 PCE Capability sub-TLV PCC/PCE は、PCEP セッション初期化フェーズ(OPEN object)において、 PATH-SETUP-TYPE-CAPILITY TLV に含まれる新しい Path Setup Type: 3 と新しい SRv6-PCE-CAPABILITY sub-TLV を介して、SRv6 をサポートする能力を示します。 SRv6-ERO Subobject SRv6 をサポートするために、ERO オブジェクトに含まれる新しい SRv6-ERO サブオブジェクトが定義されました。 SRv6-RRO Subobject SRv6 をサポートするために、RRO オブジェクトに含まれる新しい SRv6-RRO サブオブジェクトが定義されました。 実装内容 今回のインターンシップでの実装内容について、Pola PCE への SRv6-ERO Subobject の追加 を例に説明します。 パケットキャプチャによるプロトコルの確認・理解 RFC 準拠のコントローラー&プロトコルライブラリ開発の進め方 で紹介されている通り、PCEP メッセージは単一の Common header と複数の Object から構成されます。 それをより直感的に理解するため、関連の RFC を読みながら、パケットキャプチャツールである Wireshark を使って PCEP メッセージの構造を確認します。 上図は、実際に PCC から PCE 宛てに送信された PCRpt メッセージのパケットキャプチャです。 図の通り、PCEP メッセージは、1 つの Common header と複数の Object から構成されています。 Common header にはそれがどの PCEP メッセージであるかを示す Message type が格納されており、今回の例で Common header の Message type は 10 で、 RFC8231 の 8.2 節の定義の通り、PCRpt メッセージであることが分かります。 そして各 Object は Common object header と Object body から構成されていて、Common object header には、その Object を示す Object class と Object type が格納されています。 今回の例では Object class は 7、Object type は 1 であり、 RFC5440 の 7.9 節を参照すると Explicit Route Object (ERO)であることが分かります。 上図の ERO Object の内容を詳しく確認すると、黄色でハイライトされいる Non defined subobject (40) が 2 つあります。内容は次の通りです。 SRv6 関連の Subobject はまだ Internet-Draft で議論中のため、Wireshark ではまだうまく認識されていません。 そこで前述の draft-ietf-pce-segment-routing-ipv6 の 4.3.1 節を参照すると、SRv6-ERO Subobject は下記のように定義されています。 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |L| Type=40 | Length | NT | Flags |V|T|F|S| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Reserved | Endpoint Behavior | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | | | SRv6 SID (optional) | | (128-bit) | | | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ // NAI (variable, optional) // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | SID Structure (optional) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ パケットキャプチャの内容を見ると、 Non defined subobject (40) の部分の 1 バイト目は A8 で、2 進数で変換すると 1010 1000 になります。 SRv6-ERO Subobject の定義と合わせて見ると、 1010 1000 の 1 ビット目は'L' Flag の値、2 ビット目から 8 ビット目の 0101000 は Type の値で 10 進数の 40 と合致しているため、SRv6-ERO Subobject は、 Non defined subobject (40) と表示されていることが分かります。 プロトコルライブラリの実装 - Pola PCE への SRv6-ERO Subobject の追加 これから Pola PCE へ SRv6-ERO Subobject を追加します。 まず、 pkg/packet/pcep/object.go に SRv6-ERO Subobject の定義を追加します。 const ERO_SUBOBJECT_SRV6 uint8 = 0x28 const ( NT_MUST_NOT_BE_INCLUDED uint8 = 0x00 // draft-ietf-pce-segment-routing-ipv6 4.3.1 NT_SRV6_NODE uint8 = 0x02 // draft-ietf-pce-segment-routing-ipv6 4.3.1 NT_SRV6_ADJACENCY_GLOBAL uint8 = 0x04 // draft-ietf-pce-segment-routing-ipv6 4.3.1 NT_SRV6_ADJACENCY_LINKLOCAL uint8 = 0x06 // draft-ietf-pce-segment-routing-ipv6 4.3.1 ) 次に、 draft-ietf-pce-segment-routing-ipv6 の 4.3.1 節を参照し、SRv6-ERO Subobject の構造体とパケット操作に関するメソッドを追加します。 パケット操作メソッドとしては、バイト列を構造体に格納する DecodeFromBytes() 、構造体をバイト列に変換する Serialize() の 2 つのメソッドと、新たに構造体を作成する NewSRv6EroSubObject 関数と SRv6-ERO Subobject から SID を抽出する ToSegment() メソッドが必要となります。 type SRv6EroSubobject struct { LFlag bool SubobjectType uint8 Length uint8 NaiType uint8 VFlag bool TFlag bool FFlag bool SFlag bool Behavior uint16 Segment table.SegmentSRv6 Nai netip.Addr } func (o *SRv6EroSubobject) DecodeFromBytes(subObj [] uint8 ) error { o.LFlag = (subObj[ 0 ] & 0x80 ) != 0 o.SubobjectType = subObj[ 0 ] & 0x7f o.Length = subObj[ 1 ] o.NaiType = subObj[ 2 ] >> 4 o.VFlag = (subObj[ 3 ] & 0x08 ) != 0 o.TFlag = (subObj[ 3 ] & 0x04 ) != 0 o.FFlag = (subObj[ 3 ] & 0x02 ) != 0 o.SFlag = (subObj[ 3 ] & 0x01 ) != 0 o.Behavior = binary.BigEndian.Uint16(subObj[ 6 : 8 ]) sid, _ := netip.AddrFromSlice(subObj[ 8 : 24 ]) o.Segment = table.NewSegmentSRv6(sid) if o.NaiType == 2 { o.Nai, _ = netip.AddrFromSlice(subObj[ 24 : 40 ]) } return nil } func (o *SRv6EroSubobject) Serialize() [] uint8 { buf := make ([] uint8 , 4 ) buf[ 0 ] = o.SubobjectType if o.LFlag { buf[ 0 ] = buf[ 0 ] | 0x80 } buf[ 1 ] = o.Length buf[ 2 ] = o.NaiType * 16 if o.VFlag { buf[ 3 ] = buf[ 3 ] | 0x08 } if o.TFlag { buf[ 3 ] = buf[ 3 ] | 0x04 } if o.FFlag { buf[ 3 ] = buf[ 3 ] | 0x02 } if o.SFlag { buf[ 3 ] = buf[ 3 ] | 0x01 } reserved := make ([] uint8 , 2 ) behavior := make ([] uint8 , 2 ) binary.BigEndian.PutUint16(behavior, o.Behavior) byteSid := o.Segment.Sid.AsSlice() byteSRv6EroSubobject := AppendByteSlices(buf, reserved, behavior, byteSid) return byteSRv6EroSubobject } func (o *SRv6EroSubobject) Len() ( uint16 , error ) { // The Length MUST be at least 24, and MUST be a multiple of 4. // An SRv6-ERO subobject MUST contain at least one of a SRv6-SID or an NAI. if o.NaiType == NT_MUST_NOT_BE_INCLUDED { // Type, Length, Flags (4byte) + Reserved(2byte) + Behavior(2byte) + SID (16byte) return uint16 ( 24 ), nil } else if o.NaiType == NT_IPV6_NODE { // Type, Length, Flags (4byte) + Reserved(2byte) + Behavior(2byte) + SID (16byte) + Nai (16byte) return uint16 ( 40 ), nil } else { return uint16 ( 0 ), errors.New( "unsupported naitype" ) } } func NewSRv6EroSubObject(seg table.SegmentSRv6) (*SRv6EroSubobject, error ) { subo := &SRv6EroSubobject{ LFlag: false , SubobjectType: ERO_SUBOBJECT_SRV6, NaiType: NT_MUST_NOT_BE_INCLUDED, VFlag: false , TFlag: false , FFlag: true , SFlag: false , Behavior: uint16 ( 1 ), Segment: seg, } length, err := subo.Len() if err != nil { return subo, err } subo.Length = uint8 (length) return subo, nil } func (o *SRv6EroSubobject) ToSegment() table.Segment { return o.Segment } そして、ERO Object から SR-ERO Subobject と SRv6-ERO Subobject を区別するために、ERO Object の DecodeFromBytes() メソッドを修正します。 func (o *EroObject) DecodeFromBytes(typ uint8 , objectBody [] uint8 ) error { o.ObjectType = typ if len (objectBody) == 0 { return nil } for { var eroSubobj EroSubobject if (objectBody[ 0 ] & 0x7f ) == 36 { eroSubobj = &SREroSubobject{} } else if (objectBody[ 0 ] & 0x7f ) == 40 { eroSubobj = &SRv6EroSubobject{} } else { return errors.New( "invalid Subobject type" ) } if err := eroSubobj.DecodeFromBytes(objectBody); err != nil { return err } o.EroSubobjects = append (o.EroSubobjects, eroSubobj) if objByteLength, err := eroSubobj.Len(); err != nil { return err } else if int (objByteLength) < len (objectBody) { objectBody = objectBody[objByteLength:] } else if int (objByteLength) == len (objectBody) { break } else { return errors.New( "srerosubobject parse error" ) } } return nil } ERO Object の新構造体を作成する NewEroSubobject 関数も同様に修正します。 func NewEroSubobject(seg table.Segment) (EroSubobject, error ) { if v, ok := seg.(table.SegmentSRMPLS); ok { subo, err := NewSREroSubObject(v) if err != nil { return nil , err } return subo, nil } else if v, ok := seg.(table.SegmentSRv6); ok { subo, err := NewSRv6EroSubObject(v) if err != nil { return nil , err } return subo, nil } else { return nil , errors.New( "invalid Segment type" ) } } これにより、Pola PCE へ SRv6-ERO Subobject に対する処理機能を追加できました。 以上では、Pola PCE への SRv6-ERO Subobject の追加を例に、今回のインターンシップでの Pola PCE 開発の流れを紹介しました。 それ以外にも、SRv6 に対応するため、Pola PCE における LSP Object の IPV6-LSP-IDENTIFIERS TLV の追加や、explicit SRv6-TE Policy を扱うための関数の修正などの変更を加えました。 詳しい説明は記事の長さの都合上、割愛しますが、ご興味のある方はこちらの PR をご参照ください。 動作検証 本章では、作成した実装を用い、複数のベンダーの機器(Cisco、Juniper)との相互接続検証を実施します。 検証環境は上図の通りで、環境の構築には OSS ツールの Containerlab を使用しました。 Containerlab を用いることで、YAML ファイルベースで簡単に検証環境を構築できます。 今回の検証用の Containerlab 設定ファイルはこちらの Repo で公開しています。 ぜひご活用ください。 SRv6 機能を追加した Pola PCE とベンダー機器との相互接続試験を行います。 まずは Containerlab の動作状態を確認します。 % sudo containerlab inspect INFO[0000] Parsing & checking topology file: nttcom-internship.clab.yml +---+---------------------------------+--------------+--------------------------------+--------+---------+----------------+----------------------+ | # | Name | Container ID | Image | Kind | State | IPv4 Address | IPv6 Address | +---+---------------------------------+--------------+--------------------------------+--------+---------+----------------+----------------------+ | 1 | clab-nttcom-internship-host01 | 2758bf898616 | wbitt/network-multitool:latest | linux | running | 172.20.20.5/24 | 2001:172:20:20::5/64 | | 2 | clab-nttcom-internship-host02 | ee82fd3f4bba | wbitt/network-multitool:latest | linux | running | 172.20.20.2/24 | 2001:172:20:20::2/64 | | 3 | clab-nttcom-internship-host03 | f2747f464ffd | wbitt/network-multitool:latest | linux | running | 172.20.20.8/24 | 2001:172:20:20::8/64 | | 4 | clab-nttcom-internship-pcc-rt01 | acb1ba1cb010 | vrnetlab/vr-vmx:22.4R1.10 | vr-vmx | running | 172.20.20.7/24 | 2001:172:20:20::7/64 | | 5 | clab-nttcom-internship-pcc-rt02 | 1928d17fae80 | ios-xr/xrd-control-plane:7.8.1 | xrd | running | 172.20.20.3/24 | 2001:172:20:20::3/64 | | 6 | clab-nttcom-internship-pcc-rt03 | f29848103688 | vrnetlab/vr-vmx:22.4R1.10 | vr-vmx | running | 172.20.20.6/24 | 2001:172:20:20::6/64 | | 7 | clab-nttcom-internship-pola-pce | 0dc707b9dd09 | ghcr.io/nttcom/pola:latest | linux | running | 172.20.20.9/24 | 2001:172:20:20::9/64 | | 8 | clab-nttcom-internship-xtc-pce | f31bc03d953a | ios-xr/xrd-control-plane:7.8.1 | xrd | running | 172.20.20.4/24 | 2001:172:20:20::4/64 | +---+---------------------------------+--------------+--------------------------------+--------+---------+----------------+----------------------+ 次に、Pola PCE のコンテナで Pola PCE を起動し、動作を確認します。 % sudo docker exec -it clab-nttcom-internship-pola-pce bash root@pola-pce:~# cat polad.yaml # polad.yaml global: pcep: address: "[fc00::ffff]" port: 4189 grpc-server: address: "127.0.0.1" port: 50051 log: path: "/var/log/pola/" name: "polad.log" ted: enable: false root@pola-pce:~# polad > /var/log/polad.log 2>&1 & [1] 65 root@pola-pce:~# ps -aux | grep polad root 65 0.0 0.0 1083748 11216 pts/1 Sl 07:18 0:00 polad root 73 0.0 0.0 3468 1720 pts/1 S+ 07:19 0:00 grep polad pola session コマンドにより PCEP Session を確認します。 root@pola-pce:~# pola session sessionAddr(1): fc00::1 sessionAddr(2): fc00::2 sessionAddr(3): fc00::3 pola sr-policy list コマンドにより各ルーター既存の SR Policy を確認します。 root@pola-pce:~# pola sr-policy list Session: fc00::1 PolicyName: vrf-100-policy-pcc-rt03 SrcAddr: fd00:ffff::1 DstAddr: 2a0b:2542:400:3:1:: Color: 100 Preference: 100 SegmentList: 2a0b:2542:400:3:1:: Session: fc00::2 PolicyName: cfg_vrf-100-policy-pcc-rt03_discr_10 SrcAddr: fd00:ffff::2 DstAddr: 2a0b:2542:400:3:1:: Color: 100 Preference: 10 SegmentList: None Session: fc00::3 PolicyName: vrf-100-policy-pcc-rt01 SrcAddr: fd00:ffff::3 DstAddr: 2a0b:2542:400:1:1:: Color: 100 Preference: 100 SegmentList: 2a0b:2542:400:1:1:: PolicyName: vrf-100-policy-pcc-rt02 SrcAddr: fd00:ffff::3 DstAddr: 2a0b:2542:400:2:1:: Color: 100 Preference: 100 SegmentList: 2a0b:2542:400:2:1:: SR Policy のパラメータを指定する yaml ファイルを確認します。 root@pola-pce:~# cat policy_explicit_rt01.yaml # policy_explicit_rt01.yaml srPolicy: pcepSessionAddr: "fc00::1" srcAddr: "fd00:ffff::1" dstAddr: "2a0b:2542:400:2:1::" name: vrf-100-policy-pcc-rt02-by-pola color: 100 segmentList: - sid: "2a0b:2542:400:3:1::" nai: "fd00:ffff::3" - sid: "2a0b:2542:400:2:1::" nai: "fd00:ffff::2" root@pola-pce:~# cat policy_explicit_rt02.yaml # policy_explicit_rt02.yaml srPolicy: pcepSessionAddr: "fc00::2" srcAddr: "fd00:ffff::2" dstAddr: "2a0b:2542:400:1:1::" name: vrf-100-policy-pcc-rt01-by-pola color: 100 segmentList: - sid: "2a0b:2542:400:3:1::" nai: "fd00:ffff::3" - sid: "2a0b:2542:400:1:1::" nai: "fd00:ffff::1" pola sr-policy add コマンドにより SR Policy を新たに発行します。 root@pola-pce:~# pola sr-policy add -f policy_explicit_rt01.yaml -l success! root@pola-pce:~# pola sr-policy add -f policy_explicit_rt02.yaml -l success! 再び pola sr-policy list コマンドを実行し各ルーターの SR Policy を確認します。 root@pola-pce:~# pola sr-policy list Session: fc00::1 PolicyName: vrf-100-policy-pcc-rt03 SrcAddr: fd00:ffff::1 DstAddr: 2a0b:2542:400:3:1:: Color: 100 Preference: 100 SegmentList: 2a0b:2542:400:3:1:: PolicyName: vrf-100-policy-pcc-rt02-by-pola SrcAddr: fd00:ffff::1 DstAddr: 2a0b:2542:400:2:1:: Color: 100 Preference: 100 SegmentList: 2a0b:2542:400:3:1:: -> 2a0b:2542:400:2:1:: Session: fc00::2 PolicyName: cfg_vrf-100-policy-pcc-rt03_discr_10 SrcAddr: fd00:ffff::2 DstAddr: 2a0b:2542:400:3:1:: Color: 100 Preference: 10 SegmentList: None Session: fc00::3 PolicyName: vrf-100-policy-pcc-rt01 SrcAddr: fd00:ffff::3 DstAddr: 2a0b:2542:400:1:1:: Color: 100 Preference: 100 SegmentList: 2a0b:2542:400:1:1:: PolicyName: vrf-100-policy-pcc-rt02 SrcAddr: fd00:ffff::3 DstAddr: 2a0b:2542:400:2:1:: Color: 100 Preference: 100 SegmentList: 2a0b:2542:400:2:1:: 上記の pola sr-policy add コマンドおよび pola sr-policy list コマンドを実行すると、Pola PCE から以下のようなログが出力されます。 2023-04-14T11:39:28.367Z info Received Keepalive {"session": "fc00::1"} 2023-04-14T11:39:46.795Z info received CreateSRPolicy API request {"input": "{\"SRPolicy\":{\"pcepSessionAddr\":\"/AAAAAAAAAAAAAAAAAAAAQ==\",\"srcAddr\":\"/QD//wAAAAAAAAAAAAAAAQ==\",\"dstAddr\":\"KgslQgQAAAIAAQAAAAAAAA==\",\"color\":100,\"policyName\":\"vrf-100-policy-pcc-rt02-by-pola\",\"segmentList\":[{\"sid\":\"2a0b:2542:400:3:1::\"},{\"sid\":\"2a0b:2542:400:2:1::\"}]}}", "server": "grpc"} 2023-04-14T11:39:46.795Z info Send PCInitiate {"session": "fc00::1"} 2023-04-14T11:39:46.895Z info Received PCRpt {"session": "fc00::1"} 2023-04-14T11:39:46.895Z info Finish Stateful PCE request {"session": "fc00::1", "srpID": 1} 2023-04-14T11:39:48.829Z info Send Keepalive {"session": "fc00::2"} 2023-04-14T11:39:48.837Z info Received Keepalive {"session": "fc00::2"} 2023-04-14T11:39:51.430Z info received CreateSRPolicy API request {"input": "{\"SRPolicy\":{\"pcepSessionAddr\":\"/AAAAAAAAAAAAAAAAAAAAg==\",\"srcAddr\":\"/QD//wAAAAAAAAAAAAAAAg==\",\"dstAddr\":\"KgslQgQAAAEAAQAAAAAAAA==\",\"color\":100,\"policyName\":\"vrf-100-policy-pcc-rt01-by-pola\",\"segmentList\":[{\"sid\":\"2a0b:2542:400:3:1::\"},{\"sid\":\"2a0b:2542:400:1:1::\"}]}}", "server": "grpc"} 2023-04-14T11:39:51.430Z info Send PCInitiate {"session": "fc00::2"} 2023-04-14T11:39:56.697Z info Send Keepalive {"session": "fc00::3"} 2023-04-14T11:39:56.778Z info Received Keepalive {"session": "fc00::3"} 2023-04-14T11:39:58.285Z info Send Keepalive {"session": "fc00::1"} 2023-04-14T11:40:06.190Z info Receive GetSRPolicyList API request {"server": "grpc"} 2023-04-14T11:40:06.190Z info Send SRPolicyList API reply {"server": "grpc"} 2023-04-14T11:40:16.903Z info Received Keepalive {"session": "fc00::1"} 確認した結果、Pola PCE と各ルーターとの PCEP Session が確立されており、Juniper vMX ルーターである pcc-rt01 の SR Policy が発行され、pcc-rt01 からの既存 SR Policy のレポートも正しく受け取っていることがわかります。 Cisco IOS XRd ルーターである pcc-rt02 については既存 SR Policy のレポートが受け取れておらず、Pola PCE から pcc-rt02 に対して SR Policy を発行できそうに見えますが、pcc-rt02 側が正しく受け取れているかどうかは不明のため、もっと詳細を調べる必要があります。 Wireshark を利用して PCEP パケットをキャプチャします。 Containerlab 環境からのパケットキャプチャは以下のように行います。 Windows WSL2 環境から SSH 経由でパケットキャプチャをする場合のコマンド例: ssh $clab_host "sudo ip netns exec clab-nttcom-internship-pola-pce tcpdump -U -nni eth1 -w -" | /mnt/c/Program\ Files/Wireshark/wireshark.exe -k -i - macOS/Linux 環境から SSH 経由でパケットキャプチャをする場合のコマンド例: ssh $clab_host "sudo ip netns exec clab-nttcom-internship-pola-pce tcpdump -U -nni eth1 -w -" | wireshark -k -i - Cisco IOS XRd との相互接続検証 Cisco IOS XRd ルーターである pcc-rt02 側でのパケットキャプチャ結果を以下に示します。 パケットキャプチャ結果を確認すると、Pola PCE の実装通りに PCInitiate メッセージが送られましたが、pcc-rt02 からは PCReport メッセージが返ってきていません。 pcc-rt02 で show コマンドによって SR Policy の状態を確認すると、以下のように新規発行された SR Policy は存在していないことがわかります。 RP/0/RP0/CPU0:pcc-rt02#show segment-routing traffic-eng policy Fri Apr 14 13:43:15.021 UTC SR-TE policy database --------------------- Color: 100, End-point: 2a0b:2542:400:3:1:: Name: srte_c_100_ep_2a0b:2542:400:3:1:: Status: Admin: up Operational: down for 02:52:28 (since Apr 14 10:50:46.274) Candidate-paths: Preference: 10 (configuration) (inactive) Name: vrf-100-policy-pcc-rt03 Last error: SRv6 locator does not support USID Requested BSID: dynamic PCC info: Symbolic name: cfg_vrf-100-policy-pcc-rt03_discr_10 PLSP-ID: 1 Constraints: Protection Type: protected-preferred Maximum SID Depth: 19 Explicit: segment-list vrf-100-segment-list-pcc-rt03 (inactive) Weight: 10, Metric Type: TE SID[0]: 2a0b:2542:400:3:1:: SRv6 Information: Locator: WOLFLAB Binding SID requested: Dynamic Binding SID behavior: End.B6.Insert.Red Attributes: Forward Class: 0 Steering labeled-services disabled: no Steering BGP disabled: no IPv6 caps enable: yes Invalidation drop enabled: no Max Install Standby Candidate Paths: 0 また、初期設定による既存の SR Policy である vrf-100-policy-pcc-rt03 に関しても、 Last error: SRv6 locator does not support USID が原因で (inactive) が表示されます。 pcc-rt02 の SRv6 関連設定は以下のようになっています。 RP/0/RP0/CPU0:pcc-rt02#show running-config segment-routing Fri Apr 14 13:44:27.988 UTC segment-routing traffic-eng segment-lists srv6 sid-format usid-f3216 ! segment-list vrf-100-segment-list-pcc-rt03 srv6 index 10 sid 2a0b:2542:400:3:1:: ! ! ! policy vrf-100-policy-pcc-rt03 srv6 locator WOLFLAB binding-sid dynamic behavior ub6-insert-reduced ! color 100 end-point ipv6 2a0b:2542:400:3:1:: candidate-paths preference 10 explicit segment-list vrf-100-segment-list-pcc-rt03 weight 10 ! ! ! ! pcc source-address ipv6 fc00::2 pce address ipv6 fc00::ffff ! report-all ! ! srv6 locators locator WOLFLAB prefix 2a0b:2542:400:2::/64 ! ! ! ! pola sr-policy list コマンドによる既存 SR Policy の確認結果では、 SegmentList: None と表示され、SR Policy が学習されていません。 Cisco のドキュメント Segment Routing Configuration Guide for Cisco ASR 9000 Series Routers, IOS XR Release 7.8.x を参照したところ、インターンシップ参加時点(2023年2月)の最新版である Cisco IOS XR 7.8.1 では SRv6 policy が uSID 以外の SID 形式をサポートしていないようであり、これが原因と考えられます。 また同様に、Cisco のドキュメントからはインターンシップ参加時点で PCE-initiated SRv6 policies via PCEP 機能がサポートされていないことがわかります。 以上が原因で残念ながら今回のインターンシップでは Cisco IOS XRd との接続検証は成功しませんでした。 Juniper vMX との相互接続検証 Juniper vMX ルーターである pcc-rt01 側でのパケットキャプチャ結果を以下に示します。 パケットキャプチャ結果を確認すると、Pola PCE の実装通りに PCInitiate メッセージが送られ、pcc-rt01 から PCReport メッセージが返ってきていることがわかります。 pcc-rt01 で show コマンドによって SR Policy の状態を確認すると、以下のように新規発行された SR Policy である vrf-100-policy-pcc-rt02-by-pola が存在していることがわかります。 admin@pcc-rt01> show spring-traffic-engineering lsp To State LSPname 2a0b:2542:400:2:1::-100<c6> Up vrf-100-policy-pcc-rt02-by-pola 2a0b:2542:400:3:1::-100<c6> Up vrf-100-policy-pcc-rt03 Total displayed LSPs: 2 (Up: 2, Down: 0) 最後に、疎通確認を行います。 % sudo docker exec -it clab-nttcom-internship-host01 /bin/bash bash-5.1# ping -c 3 fd00:192:168:2::1 PING fd00:192:168:2::1(fd00:192:168:2::1) 56 data bytes 64 bytes from fd00:192:168:2::1: icmp_seq=1 ttl=62 time=4.00 ms 64 bytes from fd00:192:168:2::1: icmp_seq=2 ttl=62 time=3.61 ms 64 bytes from fd00:192:168:2::1: icmp_seq=3 ttl=62 time=3.77 ms --- fd00:192:168:2::1 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 2003ms rtt min/avg/max/mdev = 3.610/3.795/4.003/0.161 ms host01 から host02 への経路は、SR Policy(vrf-100-policy-pcc-rt02-by-pola) により pcc-rt01 -> pcc-rt03 -> pcc-rt02(緑色の線)経由になると期待されます。 pcc-rt03 の ge-0/0/0 でパケットキャプチャし、SR Policy の挙動を確認します。 % sudo ip netns exec clab-nttcom-internship-pcc-rt03 tcpdump -nni eth1 -v ip6 tcpdump: listening on eth1, link-type EN10MB (Ethernet), snapshot length 262144 bytes 00:22:59.940361 IP6 (flowlabel 0x47e1e, hlim 255, next-header Routing (43) payload length: 128) fd00:ffff::1 > 2a0b:2542:400:3:1::: RT6 (len=2, type=4, segleft=1, last-entry=0, flags=0x0, tag=0, [0]2a0b:2542:400:2:40::) IP6 (flowlabel 0xe793a, hlim 63, next-header ICMPv6 (58) payload length: 64) fd00:192:168:1::1 > fd00:192:168:2::1: [icmp6 sum ok] ICMP6, echo request, id 13, seq 1 00:23:00.939071 IP6 (flowlabel 0x47e1e, hlim 255, next-header Routing (43) payload length: 128) fd00:ffff::1 > 2a0b:2542:400:3:1::: RT6 (len=2, type=4, segleft=1, last-entry=0, flags=0x0, tag=0, [0]2a0b:2542:400:2:40::) IP6 (flowlabel 0xe793a, hlim 63, next-header ICMPv6 (58) payload length: 64) fd00:192:168:1::1 > fd00:192:168:2::1: [icmp6 sum ok] ICMP6, echo request, id 13, seq 2 00:23:01.941300 IP6 (flowlabel 0x47e1e, hlim 255, next-header Routing (43) payload length: 128) fd00:ffff::1 > 2a0b:2542:400:3:1::: RT6 (len=2, type=4, segleft=1, last-entry=0, flags=0x0, tag=0, [0]2a0b:2542:400:2:40::) IP6 (flowlabel 0xe793a, hlim 63, next-header ICMPv6 (58) payload length: 64) fd00:192:168:1::1 > fd00:192:168:2::1: [icmp6 sum ok] ICMP6, echo request, id 13, seq 3 3 packets captured 3 packets received by filter 0 packets dropped by kernel 結果の通り、pcc-rt03 でパケットキャプチャして確認すると、pcc-rt01 から pcc-rt03 へ ICMP Request パケットが想定した経路で送られていることがわかります。 また、host02 から host01 へ ICMP Reply パケットについて、前述の原因により pcc-rt02 側で有効な SR Policy が存在しないため、経路は IGP に従って pcc-rt02 -> pcc-rt01(青色の線)になります。 同様に pcc-rt02 の Gi0/0/0/0 でパケットキャプチャして確認します。 % sudo ip netns exec clab-nttcom-internship-pcc-rt02 tcpdump -nni Gi0-0-0-0 -v ip6 tcpdump: listening on Gi0-0-0-0, link-type EN10MB (Ethernet), snapshot length 262144 bytes 00:45:20.822110 IP6 (flowlabel 0x5aab2, hlim 64, next-header IPv6 (41) payload length: 104) fd00:ffff::2 > 2a0b:2542:400:1:6::: IP6 (flowlabel 0x5aab2, hlim 63, next-header ICMPv6 (58) payload length: 64) fd00:192:168:2::1 > fd00:192:168:1::1: [icmp6 sum ok] ICMP6, echo reply, id 16, seq 1 00:45:21.820163 IP6 (flowlabel 0x5aab2, hlim 64, next-header IPv6 (41) payload length: 104) fd00:ffff::2 > 2a0b:2542:400:1:6::: IP6 (flowlabel 0x5aab2, hlim 63, next-header ICMPv6 (58) payload length: 64) fd00:192:168:2::1 > fd00:192:168:1::1: [icmp6 sum ok] ICMP6, echo reply, id 16, seq 2 00:45:22.822313 IP6 (flowlabel 0x5aab2, hlim 64, next-header IPv6 (41) payload length: 104) fd00:ffff::2 > 2a0b:2542:400:1:6::: IP6 (flowlabel 0x5aab2, hlim 63, next-header ICMPv6 (58) payload length: 64) fd00:192:168:2::1 > fd00:192:168:1::1: [icmp6 sum ok] ICMP6, echo reply, id 16, seq 3 3 packets captured 3 packets received by filter 0 packets dropped by kernel キャプチャした結果、ICMP Reply パケットの経路は想定通り pcc-rt02 -> pcc-rt01(青色の線)になっていることがわかります。 これにより、今回のインターンシップで実装した Pola PCE の SRv6 機能が正しく動作していることが確認できました。 まとめと今後の課題 本体験記では、インターンシップで取り組んだ Pola PCE への SRv6 新規機能実装・検証内容をご紹介しました。 前半では、Pola PCE への SRv6-ERO Subobject の追加を例に、今回のインターンシップでの開発の流れについて説明しました。 後半では、インターンシップ中に実施した複数のベンダーの機器(Cisco、Juniper)とPola PCE との相互接続検証を紹介しました。 結果として、Pola PCE へ実装した SRv6 機能が正しく動作していることが確認できました。 今回のインターンシップでは、実装状況の関係から、残念ながら本来の目標であった複数のベンダーの機器との相互接続は実現できませんでした。 SRv6 の TE は今後の発展が期待される分野であり、また私自身の研究にもつながるトピックです。 今後もベンダーの動向に注視しつつ、研究や運用に役立つ機能の開発に積極的に取り組んでいきたいと思います。 また、Pola PCE では次のステップとして、Dynamic SRv6-TE や BGP SR Policy NLRI への対応を検討しています。 これらの技術開発についても引き続き携わりたいと期待しています。 インターンシップの感想 わずか 2 週間のインターンシップでしたが、Pola PCE の開発準備から相互接続検証までの全プロセスに取り組むことができ、大変素晴らしい経験となりました。 Go 言語と PCEP 初心者の私にとっては大きな挑戦でしたが、Pola PCE のコア開発者の三島さんと竹中さんの丁寧な指導のお陰で、数々の課題を乗り越え、インターンシップの最終日までに開発目標を達成できました。 また、チーム全体の定例ミーティングへの参加を通して、Pola PCE の開発者の先輩社員の方だけでなく配属チームの社員の方々と交流でき、チーム全体の雰囲気を感じると共に普段の業務内容をより深く理解できました。 今回インターンシップで獲得した貴重な経験を今後の研究活動に活かしていきたいと思います。 トレーナーの三島さん、竹中さん、上長の木村さん、そしてお世話になった NTT Com の皆さん、2 週間大変貴重な経験をさせていただき、本当にありがとうございました。 トレーナーからのコメント トレーナーを担当したイノベーションセンターの竹中です。2週間のインターンシップお疲れ様でした。 今回のインターンシップでは、魏さんには主に SR PCE である Pola PCE の SRv6 拡張を実施していただきました。プロトコルやパケット構造の理解からはじめ、RFC や Internet-Draft とコードを比較しつつ拡張する部分を検討し、そして実際に機能拡張・動作確認まで行い成功させてくれました。インターン前は PCEP も Go 言語にもあまり馴染みがなかったということでしたが、その中でもプロトコルや実装を即座に理解し、手早く機能拡張されている様子はとても印象的でした。 また、本ブログでは SRv6 機能拡張について触れていただきましたが、それ以外に IPv6 underlay の環境情報を取得するための BGP-LS の各ベンダ実装状況など、PCE を活用する上で必要となる機能を調査していただきました。 SR PCE は SR 技術において様々な Traffic Engineering を行う上で今後重要となる技術です。 今回実施いただいた Pola PCE の SRv6 拡張によって、SRv6 環境においてより柔軟な TE の管理や検証が行えるようになりました。我々の SRv6 環境へ導入し、運用や検証に活用していきます! また、調査いただいたベンダの機能実装状況なども、今後の検証方針の決定やベンダへの問い合わせに活用させていただきます。 このインターンシップを通して得られた様々な知見が魏さんの今後の活動にも役立つことを願っています。 改めて、インターンシップへのご参加とご活躍、ありがとうございました!
はじめに こんにちは、インターンシップ生の大平です。 2023年2月にNTTコミュニケーションズで開催された2週間の現場受け入れ型インターンシップに参加させていただきました。 普段は大学でエッジコンピューティングに関する研究をしています。 今回のインターンシップでは「SR (セグメントルーティング) を用いたキャリアネットワークの開発」というテーマで、 IPv6 Single/Dual-Stack SR-MPLSを検証しました。 この記事ではインターンシップの体験記として、どのような内容に取り組んだかを紹介します。 インターンシップに参加するまで 以前からカンファレンスネットワークの構築などでNTTコミュニケーションズの取り組みに触れる機会や社員の方とお話しする機会があり、会社の雰囲気やどのような業務をしているのかに興味を持ちインターンシップへの参加を決めました。 また、セグメントルーティングについては、以前から大まかな概要については知っていましたが実際に触れたことはなかったため、この機会に学んでみたいと考えたのも理由の1つです。 インターンシップで取り組んだこと 今回のインターンシップではマルチベンダー(Cisco、Juniper、Nokia)の機器が相互接続したIPv6 Single/Dual-Stack SR-MPLSを検証しました。 NTT Comが提案する mutli-AS SR は、役割や機能、地理的に異なるSR網を複数のASに分離し、疎結合に構成しつつEnd-to-EndにTE を行う独自のアーキテクチャとなっています。 multi-AS SRのユースケースの1つとして、SR-MPLSのASにIPv6 Underlayを敷設することによるSRv6 Migrationがありますが、2022年時点ではSR-MPLS IPv6 Underlayの実用例は存在しません。 そこでこの検証では、IPv6 Underlayで得られるPlug-and-Playなネットワーク構築やSRv6 Migrationなどのメリットを整理するとともに、現時点の実装で出来ることと出来ないことを洗い出すことを目的としています。 インターンシップの最初の1週間では、同一ベンダーの機器同士でIPv6 Single-Stack構成のSR-MPLSを構築しました。 これにより、各ベンダーの機器における基本的なSR-MPLSの機能を理解できました。 次に、マルチベンダーの機器同士でIPv6 Single-Stack構成のSR-MPLSを構築しました。 最後に、IPv4/IPv6 Dual-Stack構成のSR-MPLSを検証し、各ベンダーでできること・できないことの洗い出しを行いました。 以下では、SR-MPLSについてや検証の手順を説明します。 SR-MPLSについて SR-MPLSは、データプレーンにMPLSを利用したセグメントルーティングです。 MPLSはパケットの転送情報をラベルで表現するフォワーディング技術です。 ラベルが付与されたパケットを受け取ったルーターは、MPLS Tableを参照し、ラベルを変換しつつパケットを転送します。 セグメントルーティングはパケットの転送情報をセグメントとして表現し、パケットに付与したセグメントリストに従ってパケットを転送するソースルーティングのパラダイムに沿ったルーティング技術です。 セグメントリストはパケットのヘッダーに追加され、各ルーターはこれに従って転送処理を行います。 このため、従来の経路制御技術よりも柔軟なトラフィックエンジニアリング可能となり、経路の最適化やネットワークリソースの効率的な利用などを実現できます。 検証手順 今回の検証では、下記の図のようなトポロジーを作成します。 このトポロジーでは9つのルーターからなるSR domainをコア網として構成し、3つの顧客を収容することを想定しています。 今回使用する機器は以下のとおりです。 rt01, rt04, rt07: IOS XR 7.4.1 rt02, rt05, rt08: JUNOS 22.3R1.11 rt03, rt06, rt09: SR OS 22.7.R1 v6-cust01, v6-cust02: Ubuntu Server 22.04 この検証では、以下のWebページを参考にIPv6 Underlayを検証しました。 [Multi-AS Segment Routing 検証連載 #1] SR-MPLS L3VPN in Single-AS - NTT Communications Engineers' Blog [Multi-AS Segment Routing 検証連載 #4] Color-Based Steering in Single-AS - NTT Communications Engineers' Blog 基本設定 インターフェースのIPv6有効化とLoopbackインターフェースを設定します。 そして、インターフェースに付与されたリンクローカルアドレスを用いてルータ同士の疎通確認を行います。 IS-ISの設定 IS-ISを用いてSR-MPLSのSID情報を広告します。 各ルーターにIS-ISを設定し、IS-ISネイバーがUpしていることとSID TableにSID情報が登録されていることを確認します。 Cisco IS-ISネイバーの確認 RP/0/RP0/CPU0:v6-rt01#show isis neighbors IS-IS 1 neighbors: System Id Interface SNPA State Holdtime Type IETF-NSF v6-rt04 Gi0/0/0/0 *PtoP* Up 22 L2 Capable v6-rt05 Gi0/0/0/1 *PtoP* Up 25 L2 Capable SID Table (MPLS Table) の確認 RP/0/RP0/CPU0:v6-rt01#show mpls forwarding Local Outgoing Prefix Outgoing Next Hop Bytes Label Label or ID Interface Switched ------ ----------- ------------------ ------------ --------------- ------------ 16002 16002 SR Pfx (idx 2) Gi0/0/0/0 fe80::20c:29ff:fe3e:f7e8 \ 2192 16002 SR Pfx (idx 2) Gi0/0/0/1 fe80::20c:29ff:feb0:78e2 \ 0 16003 16003 SR Pfx (idx 3) Gi0/0/0/1 fe80::20c:29ff:feb0:78e2 \ 2594 16004 Pop SR Pfx (idx 4) Gi0/0/0/0 fe80::20c:29ff:fe3e:f7e8 \ 1501 16005 Pop SR Pfx (idx 5) Gi0/0/0/1 fe80::20c:29ff:feb0:78e2 \ 2662 16006 16006 SR Pfx (idx 6) Gi0/0/0/1 fe80::20c:29ff:feb0:78e2 \ 2602 16007 16007 SR Pfx (idx 7) Gi0/0/0/0 fe80::20c:29ff:fe3e:f7e8 \ 1433 16007 SR Pfx (idx 7) Gi0/0/0/1 fe80::20c:29ff:feb0:78e2 \ 0 16008 16008 SR Pfx (idx 8) Gi0/0/0/0 fe80::20c:29ff:fe3e:f7e8 \ 0 16008 SR Pfx (idx 8) Gi0/0/0/1 fe80::20c:29ff:feb0:78e2 \ 2654 16009 16009 SR Pfx (idx 9) Gi0/0/0/1 fe80::20c:29ff:feb0:78e2 \ 2662 24000 Pop SR Adj (idx 1) Gi0/0/0/1 fe80::20c:29ff:feb0:78e2 \ 0 24001 Pop SR Adj (idx 3) Gi0/0/0/1 fe80::20c:29ff:feb0:78e2 \ 0 24002 Pop SR Adj (idx 1) Gi0/0/0/0 fe80::20c:29ff:fe3e:f7e8 \ 0 24003 Pop SR Adj (idx 3) Gi0/0/0/0 fe80::20c:29ff:fe3e:f7e8 \ 0 24004 Aggregate 100: Per-VRF Aggr[V] \ 100 0 Juniper IS-ISネイバーの確認 user@v6-rt02> show isis adjacency Interface System L State Hold (secs) SNPA ge-0/0/0.0 v6-rt04 2 Up 26 ge-0/0/1.0 v6-rt05 2 Up 18 ge-0/0/2.0 v6-rt06 2 Up 23 SID Table (MPLS Table) の確認 user@v6-rt02> show route table mpls.0 mpls.0: 31 destinations, 31 routes (31 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both 0 *[MPLS/0] 00:12:33, metric 1 to table inet.0 0(S=0) *[MPLS/0] 00:12:33, metric 1 to table mpls.0 1 *[MPLS/0] 00:12:33, metric 1 Receive 2 *[MPLS/0] 00:12:33, metric 1 to table inet6.0 2(S=0) *[MPLS/0] 00:12:33, metric 1 to table mpls.0 13 *[MPLS/0] 00:12:33, metric 1 Receive 16 *[VPN/0] 00:12:33 > via lsi.0 (100), Pop 17 *[VPN/0] 00:12:33 > via lsi.1 (200), Pop 18 *[VPN/0] 00:12:33 > via lsi.2 (300), Pop 19 *[L-ISIS/14] 00:11:01, metric 0 > to 10.2.5.5 via ge-0/0/1.0, Pop 19(S=0) *[L-ISIS/14] 00:11:01, metric 0 > to 10.2.5.5 via ge-0/0/1.0, Pop 20 *[L-ISIS/14] 00:11:01, metric 0 > to fe80::20c:29ff:feb0:7800 via ge-0/0/1.0, Pop 20(S=0) *[L-ISIS/14] 00:11:01, metric 0 > to fe80::20c:29ff:feb0:7800 via ge-0/0/1.0, Pop 21 *[L-ISIS/14] 00:10:36, metric 0 > to 10.2.6.6 via ge-0/0/2.0, Pop 21(S=0) *[L-ISIS/14] 00:10:36, metric 0 > to 10.2.6.6 via ge-0/0/2.0, Pop 22 *[L-ISIS/14] 00:10:36, metric 0 > to fe80::38:ffff:fe00:0 via ge-0/0/2.0, Pop 22(S=0) *[L-ISIS/14] 00:10:36, metric 0 > to fe80::38:ffff:fe00:0 via ge-0/0/2.0, Pop 23 *[L-ISIS/14] 00:08:46, metric 0 > to 10.2.4.4 via ge-0/0/0.0, Pop 23(S=0) *[L-ISIS/14] 00:08:46, metric 0 > to 10.2.4.4 via ge-0/0/0.0, Pop 24 *[L-ISIS/14] 00:08:36, metric 0 > to fe80::20c:29ff:fe3e:f7fc via ge-0/0/0.0, Pop 24(S=0) *[L-ISIS/14] 00:08:36, metric 0 > to fe80::20c:29ff:fe3e:f7fc via ge-0/0/0.0, Pop 16001 *[L-ISIS/14] 00:08:31, metric 30 to fe80::20c:29ff:fe3e:f7fc via ge-0/0/0.0, Swap 16001 > to fe80::20c:29ff:feb0:7800 via ge-0/0/1.0, Swap 16001 16003 *[L-ISIS/14] 00:10:36, metric 20 to fe80::20c:29ff:feb0:7800 via ge-0/0/1.0, Swap 16003 > to fe80::38:ffff:fe00:0 via ge-0/0/2.0, Swap 16003 16004 *[L-ISIS/14] 00:08:36, metric 20 > to fe80::20c:29ff:fe3e:f7fc via ge-0/0/0.0, Pop 16004(S=0) *[L-ISIS/14] 00:08:36, metric 20 > to fe80::20c:29ff:fe3e:f7fc via ge-0/0/0.0, Pop 16005 *[L-ISIS/14] 00:11:01, metric 10 > to fe80::20c:29ff:feb0:7800 via ge-0/0/1.0, Pop 16005(S=0) *[L-ISIS/14] 00:11:01, metric 10 > to fe80::20c:29ff:feb0:7800 via ge-0/0/1.0, Pop 16006 *[L-ISIS/14] 00:10:36, metric 10 > to fe80::38:ffff:fe00:0 via ge-0/0/2.0, Swap 16006 16007 *[L-ISIS/14] 00:08:36, metric 30 to fe80::20c:29ff:fe3e:f7fc via ge-0/0/0.0, Swap 16007 > to fe80::20c:29ff:feb0:7800 via ge-0/0/1.0, Swap 16007 16008 *[L-ISIS/14] 00:08:31, metric 20 to fe80::20c:29ff:fe3e:f7fc via ge-0/0/0.0, Swap 16008 to fe80::20c:29ff:feb0:7800 via ge-0/0/1.0, Swap 16008 > to fe80::38:ffff:fe00:0 via ge-0/0/2.0, Swap 16008 16009 *[L-ISIS/14] 00:10:31, metric 20 to fe80::20c:29ff:feb0:7800 via ge-0/0/1.0, Swap 16009 > to fe80::38:ffff:fe00:0 via ge-0/0/2.0, Swap 16009 Nokia IS-ISネイバーの確認 [/] A:user@v6-rt03# show router isis adjacency =============================================================================== Rtr Base ISIS Instance 0 Adjacency =============================================================================== System ID Usage State Hold Interface MT-ID ------------------------------------------------------------------------------- v6-rt06 L2 Up 24 if-to-rt06 0 v6-rt05 L2 Up 21 if-to-rt05 0 ------------------------------------------------------------------------------- Adjacencies : 2 =============================================================================== SID Table (MPLS Table) の確認 [/] A:user@v6-rt03# tools dump router segment-routing tunnel =================================================================================================== Legend: (B) - Backup Next-hop for Fast Re-Route (D) - Duplicate label stack is ordered from top-most to bottom-most =================================================================================================== --------------------------------------------------------------------------------------------------+ Prefix | Sid-Type Fwd-Type In-Label Prot-Inst(algoId) | Next Hop(s) Out-Label(s) Interface/Tunnel-ID | --------------------------------------------------------------------------------------------------+ fd00:ffff::1 Node Orig/Transit 16001 ISIS-0 fe80::20c:29ff:feb0:7814 16001 if-to-rt05 fd00:ffff::2 Node Orig/Transit 16002 ISIS-0 fe80::20c:29ff:feb0:7814 16002 if-to-rt05 fd00:ffff::3 Node Terminating 16003 ISIS-0 fd00:ffff::4 Node Orig/Transit 16004 ISIS-0 fe80::20c:29ff:feb0:7814 16004 if-to-rt05 fd00:ffff::5 Node Orig/Transit 16005 ISIS-0 fe80::20c:29ff:feb0:7814 3 if-to-rt05 fd00:ffff::6 Node Orig/Transit 16006 ISIS-0 fe80::38:ffff:fe00:0 16006 if-to-rt06 fd00:ffff::7 Node Orig/Transit 16007 ISIS-0 fe80::20c:29ff:feb0:7814 16007 if-to-rt05 fd00:ffff::8 Node Orig/Transit 16008 ISIS-0 fe80::20c:29ff:feb0:7814 16008 if-to-rt05 fd00:ffff::9 Node Orig/Transit 16009 ISIS-0 fe80::20c:29ff:feb0:7814 16009 if-to-rt05 fe80::20c:29ff:feb0:7814-"if-to-rt05" Adjacency Transit 524283 ISIS-0 fe80::20c:29ff:feb0:7814 3 if-to-rt05 10.3.5.5 Adjacency Transit 524284 ISIS-0 10.3.5.5 3 if-to-rt05 fe80::38:ffff:fe00:0-"if-to-rt06" Adjacency Transit 524285 ISIS-0 fe80::38:ffff:fe00:0 3 if-to-rt06 10.3.6.6 Adjacency Transit 524287 ISIS-0 10.3.6.6 3 if-to-rt06 --------------------------------------------------------------------------------------------------+ No. of Entries: 13 --------------------------------------------------------------------------------------------------+ VRF、MP-BGP VPNv6の設定 MP-BGP VPNv6を用いて、顧客のVRFの経路を広告します。 各PEルーターにVRF及びMP-BGP VPNv6を設定します。 そして、BGPネイバーの状態と顧客の経路(VRFの経路)が登録されていることを確認します。 Cisco BGPネイバーの確認 RP/0/RP0/CPU0:v6-rt01#show bgp vpnv6 unicast summary BGP router identifier 10.254.1.1, local AS number 65000 BGP generic scan interval 60 secs Non-stop routing is enabled BGP table state: Active Table ID: 0x0 RD version: 0 BGP main routing table version 23 BGP NSR Initial initsync version 20 (Reached) BGP NSR/ISSU Sync-Group versions 0/0 BGP scan interval 60 secs BGP is operating in STANDALONE mode. Process RcvTblVer bRIB/RIB LabelVer ImportVer SendTblVer StandbyVer Speaker 23 23 23 23 23 0 Neighbor Spk AS MsgRcvd MsgSent TblVer InQ OutQ Up/Down St/PfxRcd fd00:ffff::2 0 65000 53 48 23 0 0 00:22:42 1 fd00:ffff::3 0 65000 49 48 23 0 0 00:22:41 1 fd00:ffff::4 0 65000 24 25 23 0 0 00:22:38 0 fd00:ffff::5 0 65000 52 48 23 0 0 00:22:42 0 fd00:ffff::6 0 65000 48 48 23 0 0 00:22:39 0 fd00:ffff::7 0 65000 26 25 23 0 0 00:22:41 1 fd00:ffff::8 0 65000 53 48 23 0 0 00:22:40 1 fd00:ffff::9 0 65000 49 48 23 0 0 00:22:40 1 VRFの経路確認 RP/0/RP0/CPU0:v6-rt01#show route vrf 100 ipv6 Codes: C - connected, S - static, R - RIP, B - BGP, (>) - Diversion path D - EIGRP, EX - EIGRP external, O - OSPF, IA - OSPF inter area N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2 E1 - OSPF external type 1, E2 - OSPF external type 2, E - EGP i - ISIS, L1 - IS-IS level-1, L2 - IS-IS level-2 ia - IS-IS inter area, su - IS-IS summary null, * - candidate default U - per-user static route, o - ODR, L - local, G - DAGR, l - LISP A - access/subscriber, a - Application route M - mobile route, r - RPL, t - Traffic Engineering, (!) - FRR Backup path Gateway of last resort is not set C fd00:100:1::/64 is directly connected, 00:23:23, GigabitEthernet0/0/0/2 L fd00:100:1::ffff/128 is directly connected, 00:23:23, GigabitEthernet0/0/0/2 B fd00:100:2::/64 [200/0] via fd00:ffff::8 (nexthop in vrf default), 00:21:23 Juniper BGPネイバーの確認 user@v6-rt02> show bgp summary Threading mode: BGP I/O Default eBGP mode: advertise - accept, receive - accept Groups: 1 Peers: 8 Down peers: 0 Table Tot Paths Act Paths Suppressed History Damp State Pending bgp.l3vpn-inet6.0 5 5 0 0 0 0 Peer AS InPkt OutPkt OutQ Flaps Last Up/Dwn State|#Active/Received/Accepted/Damped... fd00:ffff::1 65000 52 55 0 0 24:15 Establ bgp.l3vpn-inet6.0: 1/1/1/0 100.inet6.0: 1/1/1/0 fd00:ffff::3 65000 57 59 0 0 26:18 Establ bgp.l3vpn-inet6.0: 1/1/1/0 300.inet6.0: 1/1/1/0 fd00:ffff::4 65000 50 55 0 0 24:18 Establ bgp.l3vpn-inet6.0: 0/0/0/0 fd00:ffff::5 65000 60 59 0 0 26:25 Establ bgp.l3vpn-inet6.0: 0/0/0/0 fd00:ffff::6 65000 56 59 0 0 26:16 Establ bgp.l3vpn-inet6.0: 0/0/0/0 fd00:ffff::7 65000 52 55 0 0 24:17 Establ bgp.l3vpn-inet6.0: 1/1/1/0 300.inet6.0: 1/1/1/0 fd00:ffff::8 65000 61 59 0 0 26:12 Establ bgp.l3vpn-inet6.0: 1/1/1/0 100.inet6.0: 1/1/1/0 fd00:ffff::9 65000 57 59 0 0 26:17 Establ bgp.l3vpn-inet6.0: 1/1/1/0 200.inet6.0: 1/1/1/0 VRFの経路確認 user@v6-rt02> show route table 200.inet6.0 200.inet6.0: 5 destinations, 5 routes (5 active, 0 holddown, 0 hidden) + = Active Route, - = Last Active, * = Both fd00:200:1::/64 *[Direct/0] 00:27:19 > via ge-0/0/3.0 fd00:200:1::ffff/128 *[Local/0] 00:27:19 Local via ge-0/0/3.0 fd00:200:2::/64 *[BGP/170] 00:24:54, localpref 100, from fd00:ffff::9 AS path: I, validation-state: unverified > to fe80::20c:29ff:fe3e:f7fc via ge-0/0/0.0, Push 524286, Push 16009, Push 16005(top) fe80::20c:29ff:fe57:ca87/128 *[Local/0] 00:27:19 Local via ge-0/0/3.0 ff02::2/128 *[INET6/0] 00:28:50 MultiRecv Nokia BGPネイバーの確認 [/] A:user@v6-rt03# show router bgp summary <snip.> =============================================================================== BGP Summary =============================================================================== Legend : D - Dynamic Neighbor =============================================================================== Neighbor Description AS PktRcvd InQ Up/Down State|Rcv/Act/Sent (Addr Family) PktSent OutQ ------------------------------------------------------------------------------- fd00:ffff::1 65000 31 0 00h14m08s 0/0/1 (VpnIPv6) 33 0 fd00:ffff::2 65000 39 0 00h16m12s 0/0/1 (VpnIPv6) 38 0 fd00:ffff::4 65000 31 0 00h14m14s 0/0/1 (VpnIPv6) 33 0 fd00:ffff::5 65000 38 0 00h16m12s 0/0/1 (VpnIPv6) 37 0 fd00:ffff::6 65000 39 0 00h17m33s 0/0/1 (VpnIPv6) 40 0 fd00:ffff::7 65000 32 0 00h14m07s 1/1/1 (VpnIPv6) 33 0 fd00:ffff::8 65000 40 0 00h16m34s 0/0/1 (VpnIPv6) 38 0 fd00:ffff::9 65000 40 0 00h17m33s 0/0/1 (VpnIPv6) 40 0 ------------------------------------------------------------------------------- VRFの経路確認 [/] A:user@v6-rt03# show router service-name "300" route-table ipv6 =============================================================================== IPv6 Route Table (Service: 300) =============================================================================== Dest Prefix[Flags] Type Proto Age Pref Next Hop[Interface Name] Metric ------------------------------------------------------------------------------- fd00:300:1::/64 Local Local 00h21m21s 0 if-to-cust01 0 fd00:300:2::/64 Remote BGP VPN 00h16m08s 170 fd00:ffff::7 (tunneled:SR-ISIS:524298) 30 ------------------------------------------------------------------------------- No. of Routes: 2 Flags: n = Number of times nexthop is repeated B = BGP backup route available L = LFA nexthop available S = Sticky ECMP requested =============================================================================== tracerouteを用いた動作確認とSR-MPLS TE(Traffic Engneering)の設定について 各ルータでtracerouteコマンドを用いて想定した経路でパケットが転送されていることを確認します。 ここではrt07 (Cisco) とrt03 (Nokia) でのping/traceroute例を示します。 RP/0/RP0/CPU0:v6-rt07#traceroute fd00:300:1::ffff vrf 300 Thu Apr 13 09:54:05.712 UTC Type escape sequence to abort. Tracing the route to fd00:300:1::ffff 1 fd00:ffff::5 [MPLS: Labels 16003/524286 Exp 0] 4 msec 5 msec 12 msec 2 fd00:300:1::ffff 3 msec 12 msec 3 msec [/admin] A:user@v6-rt03# traceroute fd00:300:2::ffff router-instance "300" detail probe-count 1 traceroute to fd00:300:2::ffff, 30 hops max, 60 byte packets 1 1 fd00:300:2::ffff (fd00:300:2::ffff) 2.91 ms 以降は各PEルーターでSR Policyを設定し、広告する各VRFごとにColor Extended Communityを付加します。 そして、対向のPEルーターで受け取った経路にColorが付加されていることと対向の顧客への経路にSR Policyが適用されていることを確認します。 今回の検証では、機器の実装状況等の理由からIPv6 UnderlayでのSR Policyの動作確認はできませんでした。 検証例と成果 今回のインターンシップでは、動作確認のためこのような表を作成し検証を実施しました。 この体験記では、動作に成功した内容のうち、一部を紹介させて頂きました。 SR-MPLSのSID学習については各ベンダーで概ね動作し、学習したSIDを利用しての相互接続や通信にも成功しました。 またIPv6 Underlayを用いたSR-MPLS網の構築では、ルーターに自動的に設定されるリンクローカルアドレスを用いてIS-ISのルーティングを行うことができ、IPv4 Underlayと比較して効率的な構築が可能でした。 一方、今回の検証ではIPv6 Single/Dual-Stackの双方において、TEの設定を投入した際に想定通りの動作をしない事象が見られました。 これらの動作結果については、検証中の部分もあり実際の結果の掲載は控えますが、動かなかった場合の詳細な症状やメッセージなどをまとめることで、その後のメーカーへの問合せにつなげることができました。 インターンシップの感想 インターンシップに参加する前は、SR-MPLSという技術について全く知識がなかったため、業務を無事に進められるか非常に不安でした。 しかし、インターンシップではトレーナーの方々のサポートを受けながら、問題に直面しつつも楽しく検証作業を進めることができました。 SR-MPLS IPv6 Underlayを検証する中で、前提となるSR-MPLSの動作など、技術に関する知識や理解を深めておくことの重要性を感じました。 SRやその周辺技術については今後も継続して学習を続けたいと考えています。 業務以外の部分では、オフィスの見学やMTGへの参加、交流会や懇親会などを通じて、受け入れていただいたチームの雰囲気や別のチームの業務内容などを知るとともに会社全体のイメージを掴むことが出来ました。 最後にはなりますが、2週間のインターンシップで数々の貴重な経験をさせていただき、心から感謝しています。 竹中さん、三島さん、木村さんありがとうございました。 トレーナーからのコメント トレーナーの三島です。2週間のインターンシップお疲れ様でした! インターンシップで検証した、IPv6 Underlay SR-MPLSの相互接続は、我々を含めおそらく業界でも誰も試したことがない難易度の高いテーマでした。 その中でも、SRに関する事前学習や検証項目の整理や環境構築から動作結果をまとめたレポートの作成、ベンダへの問い合わせ項目の作成まで検証の一連の流れを一人称で進めていただけたこと、とても嬉しく思っております。 IPv6 Underlay SR-MPLSは、Plug-and-Playなネットワーク構築やSRv6 Migrationなどの固有の利点をもった面白い技術です。 大平さんに検証していただいたことで、各社の実装状況や、IPv6 Underlayの持つ利点が明確になり、SRv6 Migration等に向けた下地を得ることができました! 検証いただいた内容を基に我々も検証を進め、今後のネットワーク作りに役立てていきたいと思います。 このインターンシップで得た知見が、今後の大平さんの研究活動に役立つことを祈っています。 改めて、インターンシップへの参加とご活躍ありがとうございました!
はじめに こんにちは!イノベーションセンターテクノロジー部門 GPU-K8s Projectに二週間、インターン参加させていただいた石本直也と申します。 大学院では、WebAssemblyに関するObservabilityについて研究をしています。 今回の職場体験型インターンシップでは「モダンなICTインフラを支える技術の検証・開発(クラウド, コンテナ or データ基盤領域)」をテーマとして以下のことに取り組みました。 GPU ServerのWorker Nodeとしての設定(cuda,containerd,NVIDIA Container Toolkit) K8sクラスタへのGPU Worker Node追加 Ansibleでのセッティングの自動化 参考:職場体験型インターンシップとは? ドコモが仕掛ける数多くの事業の中から厳選したポストにて、実務を体験していただきます。 業務体験を通じて通信/ICT業界の仕事が理解できるだけでなく、皆さん自身の成長を実感できるインターンシップとなっています。 現場受け入れ型インターンシップコース | インターンシップ情報 | NTTドコモ新卒採用 インターン先 GPU-K8s Projectについて NTT ComのAIインフラ分野を牽引するテックリード的なプロジェクトで、ストレージ、GPUといったハードウェアからAIエンジニアが使うKubeflowといったAIプラットフォームOSSまで管理しています。 所属人数は10名以下ですが、扱う領域は広く運用効率化のためにK8s OperatorやKustomizeなどのOSSやAzure Arcなどのベンダー製品まで幅広くを検証しています。 以下の図は、社内向けAI基盤を構成している技術スタックを示した図です。 職場環境 フルリモートが主体の働き方を実現しているチームです。主なコミュニケーションツールとして、Slack, Google Meet, NeWorkを使用し、特にNeWorkの活用によってオフィスと遜色ない、場合によっては対面以上の働き方だと感じました。 その証拠に、函館からのリモートインターンシップでも二週間何も不自由なく参加でき、素直にすごいと感じました。 体験内容 一社員としてプロジェクトに配属され、実際に行われている業務内容を割り当てていただき社員の方のサポートの元で開発しました。その際、割り当てとなる業務内容に関しては、初日に自身の技術面や希望を話す機会を設けられそこで決定する流れでした。 私がAIインフラに関するGPUとK8sに関することがやりたいとお伝えしたところ、以下の2つを提示いただきました。その中で1番を選択し、GPU-K8s基盤へのworker node追加・その自動化に関するインターンシップを行いました。 [インフラ構築と自動化]:GPU-K8s基盤へのworker node追加・その自動化 [Go言語でのソフトウェア開発]:チームで内製開発中のK8s Operator の開発に参加 業務内容 GPU Worker Nodeの構築に関する調査、構築手順のドキュメント化 今回、Worker Nodeを追加するK8sクラスタは、実際にAIエンジニア向けに提供されているプロダクション基盤に追加する業務で、バグ等を踏み、業務使用されているK8sクラスタを壊す危険性がありました。 その際の影響を最小限に抑えるため、NVIDIA公式のインストールサイトや、Kubernetes.io docsを参考に一旦作業手順をNotionにまとめ、社員の方にご確認をいただき構築作業を開始しました。 GPU ServerのWorker Nodeとしての設定(cuda,containerd,NVIDIA Container Toolkit) Notionにまとめた作業手順を参考に、設定するサーバにsshし構築しました。 まず、CUDAドライバーのインストール、Containerdのインストール、コンテナ上からGPU利用を可能とするNVIDIA Container Toolkitのインストールを行いました。 最後にサーバ上で、Contaienrdのコマンドを用いてコンテナ上からGPUが見えていることをテストしました。 ctr image pull docker.io/nvidia/cuda:11.6.2-base-ubuntu20.04 K8sクラスタへのGPU Worker Node追加 設定したサーバをK8sクラスタへ追加するために、Kubeadm、Kubelet、Kubectlをインストールしました。 追加するK8sクラスタにおいて、Control Planeでのトークン作成 kubeadm token create --print-join-command を行いました。そのトークンをもとに kubeadm join を実行し、GPU Worker NodeをK8sクラスタへの追加を完了しました。 画像はメンテナンス中のもの Ansibleでのセッティングの自動化 次世代のH100 GPUが登場する中で、今後同様の設定を複数回行うことが予想されます。その構築や運用に関わる負荷軽減のために構築手順のAnsible化を行いました。 インターン最終日までにAnsible によりKubeadm joinを除くGPU Worker Nodeに関する設定のコード化ができました。 その際の自身のAnsible知識レベルは、OSS等でAnsibleのスクリプトは実行したことがあるものの、スクリプトを書いたことはない状態でした。そのためGCPで検証用VMを立てる権限をいただき、業務時間中に実際にスクリプトを書きながら学習しました。 以下の図が、Ansibleを実行した際の出力結果となります。 一部shellスクリプトによる実行を挟んでいるため、全てokでなくchangeになるものが発生しているのですが、冪等性(何回設定スクリプトを実行しても同じ結果となる)は担保できました。 学んだこと、感じたこと 私がこのインターンシップを経験して、学びその過程で感じたことは、大きく分けて3つありました。 基盤運用を効率化する技術について GPUが乗った状態の素のUbuntuOSに対して、GPUやK8sに関する設定を実施し、Ansibleによる設定の自動化までを経験したことで、実際に触った技術以外の運用技術もその役割や利用するメリットを理解できました。 Ansibleに関してはチームリポジトリへのプルリクエスト段階で、Ansibleのご経験がある社員の方からコードレビューをいただきました。自分では気づけない我流かつ荒削りになっていた部分や、よりわかりやすいディレクトリ構造や変数の使い方を学べとても良い貴重な経験になりました。 以下の図のように、運用効率化技術(AnsibleやK8s Operator)のAI基盤における使い分けについて実際に検証を通して学びました。 Ansible:Linux、K8s K8s Operator:K8s、OSS on K8s(e.g Prometheus、Kubeflow) AI処理に関する専用ハードウェアの重要性について DGX A100サーバを用いて検証する中で、 nvidia-smi で見た消費電力がGeForceシリーズと比べて大差がないことに疑問を感じました。そこで検証に使用しているnodeのGPU性能について知るために、NVIDIA製GPUのベンチマークについて調べてみることしました。 YouTubeの NVIDIA A100とRTX 3090のベンチマーク動画が大変参考になり、特に機械学習(ResNet50)に関する計算において、エンタープライズGPUとコンシューマGPU間で目に見えてわかる電力効率差があることにはかなり驚きました。 このことからPreferred Networks社が、MN-Coreと呼ばれる独自のハードウェアアクセラレータを開発し、計算機クラスタを構築する意図について理解できました。 参考:NVIDIA REFUSED To Send Us This - NVIDIA A100 NVIDIA A100とRTX3090のベンチマーク評価 参考:MN-Core 深層学習の学習フェーズに最適化した専用ハードウェア その他 (Sphinxを用いてネットワーク図の作成) 大学プロジェクト活動でのドキュメントが更新されてなくて苦しんだ経験があり、それの打開策になると感じました。 スライド等で図を作成するのではなくSphinxでアーキテクチャ図を作成することで保守性をあげることができると思うので、ぜひ取り入れていきたいです。 参考:Sphinx 図を含めたドキュメントをコード管理を可能とするツール 今後取り組みたいこと・学習指針 AIモデルとハードウェア処理の関係性調査 エンタープライズGPUとコンシューマGPUでは明らかに計算特性が異なることを知り、これと機械学習モデルの関係性が気になりました。機械学習モデルの推論や学習においてモデル内部の計算処理等を追うことでの適切なハードウェアを選択できるようになりたいです。 ソフトウェアレベルでのAI処理の効率化技術調査 これまで大規模言語モデルでは、そのモデルサイズと重みの大きさからA100やA6000のような大容量のVRAMを積んだGPUが必須とされてきました。しかしFlexGenの登場によって、コンシューマGPU(2023年4月時点で多くとも24GBのVRAMを搭載)でも大規模モデルを動かすことが可能となりました。今後上記を可能とするモデル処理に関するアーキテクチャについても調査し、ハードウェアとソフトウェアの両面からAI処理を効率化を行えるエンジニアになれるよう頑張ります。 参考:FlexGen 限られた GPU メモリで大規模な言語モデルを実行するための高スループット生成エンジン AI処理に関するハードウェアアクセラレータの調査 Preferred Networks社のMN-Core以外にも、SONYのIMX500といったCMOSセンサにAI推論機能を搭載したものが開発されています。ハードウェアアクセラレータはエッジAIの実現・普及に向けて欠かせない技術だと考えており、その検証も機会があればやっていきたいです。 参考:IMX500 世界初のAI処理機能を搭載したイメージセンサー 最後に 今回のインターンシップでは、実際にGPU基盤構築と自動化を通して実際の GPU運用効率化手法や更なるインフラ系の技術分野とその運用技術について知り、専門性を高めることができました。また、共同運営されているハイブリッドクラウドチームの方から、検証中の技術に関してお聞きし、OSSだけでなくAzure Arcといったより大規模な管理手法の理解も深まりました。 個人では触ることができない技術群で、そんな貴重機会をいただけたGPU-K8s Projectの皆さんに感謝でいっぱいです。 紀本さん、他にも業務を抱えている中でメンターとして二週間付きっきりでサポートしていただきありがとうございます!とても気さくに対応していただき、こんなこと聞いていいんだろうかと悩むことなく業務の体験・技術検証に集中できました。 GPU-K8s Projectの皆さん、上長としてサポートしてくださった松田さん、メンターとしてサポートしていただいた紀本さん、二週間本当にありがとうございました。
はじめに こんにちは!イノベーションセンター テレプレゼンスPJの渋谷です。 最近は日に日に暖かくなり,人々も花粉も舞い踊る気候になってきました。 ついこの間までの寒さが嘘のようです。 寒さといえば,そう,コタツ。 皆さんも「リモコンを取りたいのに手が届かない!だけどコタツからは出たくない!」「コタツが自分と一緒に動いてくれたら...」と,一度は考えたことがあるのではないでしょうか? そんな怠惰な願望を叶えるために,ロボティクスノウハウと余った時間と予算をフル活用し,今春,遂に「走るコタツ」が完成しました!! 今回は既に季節外れとなってしまった走るコタツの制作記録をご紹介します。 設計 はじめに,走るコタツを実現するには3つの要素があると考えました。 コタツと人を載せられるパワーを持つ駆動装置付きの台車 直感的な操作が可能な制御プログラム コードレスなコタツ これらを満たすソフト・ハードを細かく設計していきます。 台車 走るコタツには,人が乗るための強度とモーターで動かすための軽さの両方を備えた台車が必要です。そこで,軽くて強度の高いアルミフレームと木材を材料に選びました。 材料の特性を考慮して,効率的に人の体重を支えられる構造で設計されています。 駆動系 ロボットの駆動機構には,車輪やキャタピラ,多足など様々な方法がありますが,狭い屋内で重い荷重を運搬することを考えるとオムニホイールやメカナムホイールを用いた方式が適しています。 オムニホイールやメカナムホイールとは,空転する小さな筒がいくつも付いた特殊な構造の車輪です。各車輪の回転数を制御することで,前後に加え,斜め・真横への移動やその場で回転する動作ができます。また,自動車のようなタイヤをステアリングする方式と比べると地面の凹凸や砂・砂利に弱く,屋内などの平らな床面上に使用が限られます。 また,オムニホイールとメカナムホイールを比較すると,前者は4方向の特性が均一で回転時に車輪と路面の間にねじれが生じないという利点に対し,後者は前後方向の移動の効率・走破性に特化した性質を持ちます。 「走るコタツ」では,基本的には前後移動がメインとなることに加え,ノウハウの蓄積を兼ねて新たにメカナムホイールを利用することにしました。 また,人と台車の合計重量を駆動させるため,モーターもかなり強力なものが必要です。 今回は,100Wの大出力モーターを使用して,大きな負荷も駆動できる構成にしています。 駆動系設計の詳細 速歩き程度のスピードで走らせるため,以下のスペックのモーター・車輪を選定し最高時速5.4[km/h]で走行できるように設計しました。 モーター最大回転数4000[rpm],最大トルク0.319[N・m] ギヤ比1:30 車輪直径20.3[cm] 床面の転がり摩擦係数 を0.03,全重量 を120[kg]とすると,静止摩擦力を上回るために必要なトルクは となり,最大出力トルクの0.319[N・m]のほうが十分大きいため駆動可能です。 配線 モーターを駆動するには,バッテリー,モータードライバ回路,そして制御を行うPCが必要となります。 モーターのドライバ回路にはシリアル通信で命令できるI/Fが用意されているため,回路が非常にシンプルです。 実際には上記の回路に加え,電源スイッチや非常停止ボタン,PC電源用の降圧コンバーターやコントローラーが取り付けられています。 制御系 さて,これまでハードウェアについて解説してきましたが,人がロボットを動かすには操縦するコントローラーとその信号を受け取ってモーターに命令を出す制御プログラムが必要になります。 そこで,ジョイスティックを使うことでロボットのように操縦できるようなUIにしました。 走るコタツはジョイスティックを倒した方向に走行するだけなので,コンピューターにはそこまで大きな処理能力は求められません。 今回はJetsonを制御用コンピューターに使用しました(それでも十分すぎますが笑)。 このロボットでは,ROS on Dockerで動作環境を整備しています。 こうすることで突然PCが壊れてしまっても,簡単に同じ構成を復旧できます(ちなみに, 普段の業務でも作業効率向上のために同様なスキームを使っています)。 ROSは,ノードと呼ばれる単体のプログラムを組み合わせて大規模なシステムを構築するという構想でつくられています。 今回のロボットでは操作を受け取ってモーターを駆動するだけなので,1. 操作の入力,2. データの加工,3. ハードウェアの駆動の3つのノードで構成されています。 よく使われる機能が様々なライブラリとして公開されているのもROSのいいところで,ジョイスティックのデータを取得するプログラムが数行のコマンドでインストールできました。 また,ロボット本体の速度を各車輪の回転数に変換してモーターを駆動するノードを自作しました。 メカナムホイールで走行するロボットの順運動学,逆運動学を計算すると以下の式になったため,この式に基づいてそれぞれのモーターの回転速度を計算するプログラムを記述しました。 順運動学 逆運動学 , , はロボットのxy及び回転速度, ~ は車輪の回転速度, は車輪半径, , はトラック幅とホイールベースを表します。 軸,回転の方向は下記画像のように定義しています。 速度制御 これでジョイスティックから取得した値をメカナムホイール制御ノードに流せばロボットが動かせる状態になりました。しかし,このままではジョイスティックの角度がそのまま速度指令値となり,動き出しや停止時に大きな衝撃が加わって乗り心地が悪くなってしまいます。 そこで,入力デバイスとモーター制御モジュールの間に速度制御モジュールを挿入して,なめらかに加減速するためのフィードフォワード制御を行いました。 乗り心地を左右するのはズバリ加速度です。例えば,車のアクセルを突然踏むのと徐々に踏むのとでは,最終的な速度が同じでも後者のほうが衝撃が小さいということが想像できると思います。 つまり,ロボットを停止状態から(速度ではなく)加速度を徐々に大きくする必要があります。 これを工学的に実現するために,2次の伝達関数を設計しました。 このブロック図を簡単に説明すると,中央の と∫(インテグラル)のループで加速度aを徐々に変化するようにしており,外側のループで命令速度 が入力速度 に追従するようになっています。 この と を調整することで,「徐々に」の度合いを決めていきます。 まず,速度指令が入力されてから最大速度になるまでの時間の逆数がおおよそ になります。 また, は の10倍程度※の値で,小さいほど動き出しがゆっくりになりますが, の4倍より小さくすると共振が生じてしまいます。 最終的な値は,組み立て後に動かしながらいくつかの値で試し, , としました。 この制御ブロックをROSのノードとして実装すればソフトの完成です。 制御系設計の詳細 伝達関数,ステップ応答を計算した結果がこちらになります。 伝達関数 ステップ応答 , with , , ステップ応答の時間関数 今回の設計値を代入し,時間応答をプロットするとこんなグラフになります。 比較:1次の伝達関数で同じように設計した場合,速度を上げた瞬間に加速度が急激に変化してしまいます。 あれこれ難しいことやってるけど実際に効果あるの?と気になると思いますが,実際の乗り心地は全然違います! コーヒーを乗せて比較した映像がこちら(左:2次の伝達関数を使用(工夫した方),右:1次の伝達関数を使用)。 どちらも同じ入力を与えているのですが,制御を工夫した方は液面の揺れがだいぶ抑えられています。 コタツ 最後に,この走るコタツのアイデンティティとなるコタツを用意します。 会社にコタツがあるわけ...と思いますよね?実はあるんです!私もチームに入ったときびっくりしました。 どうしてコタツがあるかは定かではありませんが,休憩時間にほっこりできるのはいいものです。 このコタツを台車に載せれば走るコタツが完全体になります!! もちろん電源も乗せているので,温かいコタツに入りながら移動できます笑 組み立て 設計ができたので,あとはアルミフレームなどのパーツや回路部品を発注して組み立てていきます。 そのときの作業風景がこちらになります。普段から本チームのメンバーはこんなスペースで仕事をしています。 余談ですが,この作業風景は実はキャタピラ駆動の「走るコタツVer.1」を作成したときの映像です。キャタピラでは人を乗せてターンできなかったため,今回「Ver.2」としてメカナムホイールで作り直しています。 回路はこの画像のようにロボットの内部に配線されています。 数百ワットの出力が出せるバッテリーを搭載しており,万が一ショートしたら大変なことになるため丁寧に配線しました。 各部品は3Dプリンタで印刷したジグでアルミフレームの柱に固定されていて,後の整備のために真ん中の天板を外して回路にアクセスできるようになっています。 部品を取り付けるスペースが若干足りなかったので,一番軽いJetsonが裏面送りになりました笑 最後に,ジョイスティックと非常停止スイッチ,そしてみかんを設置すれば完成です!! 実際に乗ってみた 一言でいうとめっちゃ楽しいです! メカナムホイールならではの真横移動はとてもシュールです笑 その場で回転もできるため,思ったより狭い通路も通ることができます。 これで来年の冬は,1日中コタツから出ることなく過ごせそうです!! 春夏秋でも,動画の後半部分のようにコタツを外して「走るスノコベッド」としても利用できます笑 転職・就職をお考えの皆様へ 本記事では,我々の夢を詰め込んだ「走るコタツ」プロジェクトについて,設計から組み立て,試乗までをご紹介しました。NTT Comでロボティクスの研究開発をしているチームがあることを知らなかった人も多いのでは無いでしょうか? ものづくりやロボティクスの楽しさが少しでも伝わっていたら嬉しいです。 私が所属するテレプレゼンスPJでは,ソフトウェアだけでは届かない物理空間をスマート化することを目的に,ロボットと通信をかけ合わせた領域の技術開発とビジネス展開に取り組んでいます。 中途採用を通年募集中で,2024年度から新卒採用を再開する予定です(※インターンの受け入れも計画しています)。興味のある方,通信×ロボティクスをやってみたい方はぜひご応募ください! 中途採用リンク: https://hrmos.co/pages/nttcom0033/jobs/1821073673089876026 新卒採用リンク: https://information.nttdocomo-fresh.jp/information/requirement 免責事項 本プロジェクトではしっかり安全対策した上でスタッフ個人の責任の元で制作・試乗しています。 この記事を見て作成したロボット等で発生したいかなる損害の保証もできませんので,このような乗り物を作成する際はパーツの注意事項等をきちんと把握した上で十分に事故等にお気をつけください。