ネットワークテストの構成を考えてみる

## 雑な前置き

突然ですが「ネットワークのテスト」の話をします。特に、自分たちで物理層を含めたネットワークの構築・運用をしなければいけないケース(オンプレ環境)の話です。要はネットワークの運用・管理って面倒くさいのでなんとかしたいという(毎度の)話です。

ネットワークとその運用の話ってなかなか変わらないんですよね。理由はいろいろあるでしょうけど、ぱっと思い浮かぶものとしては次に挙げるような点があるでしょう。

* システムを機能ごとの階層で見ていったとき、レイヤごとにある程度ライフサイクルがあるんですが、システムの下の方にあるネットワークって、ファシリティ(建物とか)に近くて、いったん作っちゃうと年～10年単位くらいで使う(使わざるを得ない)。
* "車を走らせたままエンジンを修理する"、システム運用ではだいたいこういう状況があります。ただ、ネットワークってひとつのシステムではなくて複数のシステムが共用している(いろんなシステムのトラフィックが流れる)ので、ひとつのオペレーションがどこにどんな影響をおよぼすのか、判断が難しい。

こういう代物をどうやって運用するか。いきなりドカンといま使っているものに手を入れるのは難しいので、テストで安全であることを保証したオペレーションを実施していく、というのが変化させていくためのカギになるんじゃないかと思っています。機器単体ではなくてネットワーク全体、ネットワークおよびその上のシステムが「こう動くはずはずだ」に対して「実際にはこう動いた」という "ふるまい" を見ることを中心に考えるとして、まずは「テストのための環境ってどうやってそろえていけばいいのか」という話です。

## ネットワークテストの構成

まず、「ネットワークのテスト」をするときに必要なものって何でしょうか?

* 環境
  * テスト対象のネットワーク (ネットワーク機器の集合)
    * テストトラフィックを生成するもの
      * テストツール / テスト用ノード
    * テストに付随する機能
      * テスト環境用DNS
      * 時刻同期(NTP)
      * ログサーバ(Syslog etc)
      * 踏み台, オペレーション(自動化)
      * ファイル転送(ftp, tftp, sftp, ssh, http)
* オペレーション
    * テスト対象を操作する
        * 人
        * 機械(デバイス抽象化レイヤ)
    * テスト用ノードを操作する
        * 人
        * 機械(テストフレームワーク)

現状、人力でやってていろいろ思うところがあるわけで、いったん人の話を除きます。ここでいう「人の問題」とは、平たく言えば Excel 手順書に沿ってテスタのセットアップしたり環境作ったりコンフィグ入れたり、という手作業でやる諸々のあれこれを指します。

イメージ的にはこんな感じかなあ
![nw-test-structure.png](https://qiita-image-store.s3.amazonaws.com/0/154230/7d834cf2-42e3-f2ff-7310-5836d24c9a5a.png)

実際にサービスインする前であれば、テスト対象NW = 本番環境というのがやれます。が、これは最初だけなんですよね。はじめに書いたとおり、いったんサービスインして複数のシステムやアプリが上で動き始めると本番環境をぶっつけ本番でいじるのは避けたい。そのために、本番環境とやりたいことを模したテスト対象NW(検証環境)を作ることになります。

テスト対象NWの理想は、本番環境と全く同等のデバイス・OS・機能・ライセンスをもって、本番環境と全く同じIPをつかって、完全に同等な機能を用意できる (そのうえで本番でやるのと全く同じオペレーションができるもの……つまり本番環境と物理的・論理的に全く同一のものです。本番環境で実施するのと同じオペレーションができて、本番環境で期待されるのと同じふるまいが観測される、ということですね。

ですが現実はそんなにうまくいきません。そもそも「物理機器」とか入ってくる時点で、テスト対象を複数用意することがまず困難です。もう第一歩から理想が崩れます。そして数十～数百台とかで構成されるネットワークは仮に物理機器を使わなくても(シミュレータなどで再現するにしても)作るのが大変です。

したがって、テストをしよう、ということになったときにまず考えるのはコレですね。

* 何のために、どんなテストをしたいのか
* そのために、どんなネットワークが必要か
    * 本番環境のどこからどこまでを再現すべきか

## テスト対象ネットワークのグレーゾーン

「テスト対象NW」の理想と現実の間には、やりたいことに応じて様々なグレーゾーンがあります。典型的なものを見てみましょう。

* 使うものを変える
    * 本番環境でつかっているデバイスの、低グレードモデルを使う・低機能ライセンスを使う
    * 本番環境とソフトウェア的に同等の仮想アプライアンスを使う
        * 本番環境が物理機器(物理アプライアンス)ベースでない場合……最初から仮想アプライアンスベースのシステムをターゲットにする場合、これは「理想」状況になる
        * コンテナとか使える道具が増えてきてるので、この辺のバランス感はまだまだ変わっていくでしょう
    * テストの内容的に重要ではないところは、安価な機器やソフトウェアで代替する
        * 単純なルーティングだけできればよいのであれば Linux VM + iptables で代替する、など。
* 数を減らす・パターンを減らす・単純化する・サンプリングする
    * 障害試験・冗長機能試験などをしないなら冗長化構成をやめる
    * 同じパターンでスケールアウトしているところはひとつ(1～数パターン)に減らす
    * 重要でない部分を省略(あるいは単純化)する……中間や外部のネットワーク構成を気にしなくてもよいケースなど。
* 共有する・集約する
    * テスト用機能やテスト対象NWの一部を他の用途 (本番環境や他のシステム用の検証環境) と共有する
    * 本番環境では個別のデバイスになっているものを1台のデバイスにまとめる
        * ネットワーク仮想化機能を使った共有 (IP, VRF, VLAN 等)
        * サーバ仮想化機能を使った共有

これらのグレーゾーンで何をどこまでやるかは、テストで実現したいこと次第です。当然、何かあきらめたことによるリスクがあります。やりたいことに対して、そこのリスクは省いてもよい、という判断が必要です。

* 使う物理機器(アプライアンス)を変えるリスク
    * ファームウェアやハードウェアに固有の機能のテスト
        * めったにありませんが、特定のデバイスとOSの組み合わせで発生するトラブルやバグ…なんてこともあります。
    * 性能試験
        * 性能のために物理アプライアンスを使うケースでは、性能試験にはやっぱりおなじ機械が必要になります。
* 数を減らす・パターンを減らすリスク
    * ひとつ(少数)では問題がなかったものが多数になると顕在化することがあります。
        * たとえば、10 VLAN で問題なかった STP 切替・再計算コストが 1000 VLAN では致命的で、検証環境で障害試験して普通にクリアだと思っていたオペレーションを本番でやったら障害になっちゃったとか……
    * たまたまピックアップした個所では問題なかったものの、そのほかの箇所では設定の抜け漏れや何らかの設定ミスがあることは往々にしてあります。
        * サンプリングはあくまでもサンプリング。当然「全部」問題ないとはいえません。サンプリングしてテストした場合、残りのものが「同じポリシで管理されているか」を確認する必要があります。
    * 局所的には問題なかったものが、全体を結合させた環境ではうまくいかないケース
        * 上の話と近いですが、ネットワークの場合、一部のミスや動きの違いが全体に影響しちゃうことがある、というのが厄介なところです。
        * 機器単体、あるいは一部のネットワークを切り出して直接テストした部分は問題なくても、対向の機器(あるいはネットワーク)側との組み合わせでうまく動かない…なんてこともあります
* 共有することによるリスク
    * 本番環境とは異なる設定がテストに影響する
    * 共有している別のシステムのオペレーションがいまやろうとしているテストに影響してしまう
    * ID変換コスト (共有することによる本番環境とのズレ…IPアドレス, VLAN ID等の際の書き換え・吸収, あるいはその際のオペミスのリスク)



まあ、細かく挙げるときりがないんですけどね。ネットワークだと、特に対外接続やキャリアサービス側は(相互にお互いが)ブラックボックスになってしまうので、どっちの何が問題なのか、というのが往々にして問題になります。

## テスト環境の選択肢?

グレーゾーンがいろいろあるのはわかりました。問題は、そのグレーゾーンのなかで、やりたいことに応じて適切なバランスが選べるかどうかです。

わかりやすいのは完全に仮想でやる (本番同等のネットワーク機能を全部仮想で用意してテスト対象NWを構成する) ことでしょう。道具としては  [GNS3](https://www.gns3.com/) とか  [VIRL](http://virl.cisco.com/) とかがメジャーどころ。

* 各社仮想アプライアンスも出してきてるので、オペレーションの再現性という意味では大きな問題がなくなってきました。
* ボトルネックになるのがスケーラビリティと性能面かな……。製品版仮想アプライアンスの多くはそれなりにメモリもコアも使うので、ひとつのサーバ上で作れる環境のサイズには制限があります。複数のサーバ持ってきて動かすとなると、物理機器を使った環境を作る場合と同じくリソース調達面の都合が発生します。
    * 一般的なクラウドサービスでは「任意のトポロジを再構成する」みたいなのが難しいですしね。ネットワークテストのためのクラウドサービス、みたいな話は今後でてくるかも。
* もし「特定製品のオペレーション」がテスト要求に入らなくて、一般的なプロトコルの動作が見たいのであれば、コンテナ使うとリソース面ではかなり制約が緩和されるはず。ただコンテナ間トポロジどう作るかは工夫が必要になるでしょうけど。

もうひとつは仮想と物理をまぜるケースかな。元々この辺の話を考えていて、ちょっと考えてたことをまとめようというのがこのエントリの(裏の)趣旨でした。

* 物理アプライアンス固有の機能試験や特定のファーム/OSで動作確認したい、あるいは障害試験をやりたい……みたいな話だと、やっぱり実際に使っているデバイスが使いたくなります。
* [自分がかかわっている](https://www.tis.co.jp/news/2018/tis_info/20180605_2.html)プロダクトで [LiquidMetal](https://liquidmetal.io/) というのがあるのですが、これは物理と仮想をハイブリッドで環境構成することができます。
    * 使いたいものは物理でもって来る + 周辺のあまり重要でないところは仮想で構成する = 必要十分な本番同等の構成を安価に再現する
    * テストのための環境構成、そのためのツール(テスト用ノード)、テストスクリプト等をパッケージングする・まとめて管理できるようにする
* あと同じく[去年までやってた話](https://speakerdeck.com/corestate55/jtf2018)で [NetTester](https://github.com/net-tester)
    * こっちはもっと物理機器中心でテスト対象NWをつくる思想
* あくまでも見たいものは「ネットワークの動作」なので、L1/L2/L3/...でどこまでをフォローするかってところですね。L3から上で良いならもっとソフトウェア中心の仕組みでフォローできるはずです。LiquidMetal, NetTester はどちらも L1/L2 に対してどうアプローチするかという話が入ってきます。

もちろん、完全に物理でやるっていう話もあります。

* 前述の通りなんですが、コレはコレでやっぱりスケールさせにくい問題がでます。
* まあフル物理機器でやれるんだったらそれに越したことはないですが、セットアップやオペレーションはとても大変ですね。やりたいことやその頻度に対して、必要なリソースやオペレーションのコストのバランスが取れているかどうか考えることになるかと思います。
    * ただ、テストや検証で、将来的に起きるであろう「やりたいこと」「頻度」ってなかなか読めないですからね。それがわかったら苦労しないわけで…。読めないものに対してどこまでお金突っ込むかですよ。

最後にオマケで。「テスト環境を作る」とは別ですが、テスト対象のコンフィグや設定などをもとに、特定のポリシの充足、不整合の発見などをするというのも考えた方が良いですね。テストというよりは validation かな。この辺で使えそうなもので最近話題なのが [Batfish](https://www.batfish.org/) でしょうかね。

## まとめ

ネットワークのテスト環境を作るときにどんなグレーゾーンがあって、やりたいことに対してよさげな "落としどころ" を決めるのにどんな選択肢があるのかってことを考えたかったエントリでした。いま、テスト対象NW(検証環境)の選択肢としては、全部物理(あるいは全部仮想)だけじゃなくて、間を取るって話をもっと柔軟に考えられるようになってきているよね、というのがやりたかったのでした。