LGTM

Looks Good To Me

ネットワーク標準化ギプス

テキストやファイルで設定管理されるようなネットワークの、設定標準化・テンプレート化・Validation について書きます。 経験上、ISP・コンテンツプロバイダなどのネットワークでうまくいった手法ですが、よりよい方法があるかもしれません。ご指摘・コメント頂けるとうれしいです。

  • 現在自動化できていないが、自動化を目指したい
  • 移行過渡期は、もしくは移行後であっても運用上の都合で、手動投入は許容したい
  • ネットワークが正しく設定されているか? を常にチェックしたい

このようなネットワーク運用を想定します。

やりたいこと

ネットワークデバイスはシステム側からもオペレーターからも変更されうる という環境で、

  1. ネットワークポリシー・設定を標準化し、テンプレートとして実装する
    → テンプレートが強制力としてはたらき、ポリシーが維持できる
  2. 何かのトリガーで 構成管理DB + テンプレートから設定を生成し、自動 or 手動によりネットワークデバイスにロードする
    → オペレーターが手動投入した (= テンプレート化されていない) 設定との調整は よしなにやる
  3. オペレーターが投入した設定がポリシーに即しているかチェックする
  4. ネットワーク全体として、意図どおり設定されているかチェックする

👆 がやりたいことの概要です。

自動化によって運用コストを下げるのは当然として、手動オペレーションを許容しつつも ネットワークポリシー(標準設定) を強制することが目的です。

1. 手動オペレーションを許容する

やりたいことについて、いくつか補足します。 この項目は、従来のネットワーク運用から漸進的にシステム導入するために必要です。

手動オペレーションで運用している or 部分的に自動化している という状態から、ネットワークが標準化されていて テンプレートがあり、すべてをシステム経由で行う運用に一足で移行するのは、運用的にはかなり大きなチャレンジで、できれば避けたいところです。

2. 個々の業務を自動化するのではなく、完全な設定をテンプレート出力 & ロードする

こうする必要があるのは、手動オペレーションを許容しつつも、テンプレートにネットワークポリシー強制力を期待するからです。

たとえば「よくやる業務はテンプレートで自動化されているが、まれな作業は手で設定する」ようなケースを想像してください。 この場合、手で入れた設定も含めてポリシーに準拠しているかを判定するのは大変です。

よくやる業務(下図グレー部分) はポリシー準拠ですが、手動設定時(下図ピンク部分) は何が設定されているか分かりません。手動設定の特定でさえ難易度が高いと思います。

  • アクセスできるのは、各業務のテンプレート + 現在の設定(= 各業務の累積) のみ
  • ポリシーは変化する

点にも注意してください。

今回の目的で言えば、「業務を積み重ねた結果である現在の設定」をチェックするほうがシンプルで、「各業務を自動化する」の延長では複雑になりそうです。 完全な設定をテンプレート出力したいのは、こういった理由からです。

実装のためのアプローチ

さて、テンプレートシステムを実装するにあたり、どのようなアプローチを取るかについて。 ここでは具体的な実装例について触れませんが、進め方の指針をいくつか記載します。

1. 標準化とテンプレート開発を同時進行する

「自動化の前に標準化しましょう」というのは基本ですが、個人的な経験でいえば実装前に標準化しきれたことはありません💦

ここでいう標準化とは、ネットワークポリシー・あるべき設定の標準形を制定するだけではなく、実機上の設定を統一するところまでを指します。 手動オペレーションな歴史のあるネットワークであれば、名前の表記揺れ (例: policy-statement / route-map) にはじまり、微妙な設定の揺れがおそらく多々残っていると思います。

これらの標準化に取り組む間もどんどん揺れは混入されますので、もぐらたたきになりがちです。 具体的にどう進めるかは後述しますが、標準化と実装は 同時進行すると良いと思っています。

2. ポリシー外の設定を許容する

別の重要なポイントとして、ビジネスを止めたくありません。 ネットワークポリシーを標準化し、実装し、できればキレイな状態で維持したいのですが、どんどん変わるビジネス要件に対応する必要があります。 「ユーザーの新たな要望に応えたい」だったり、「バグ対応で設定や運用を変えたい」だったり、要件は様々です。

そのたびに「ポリシーとして標準化して、ツール化しないとネットワークに入れられません」ではスピード感を損ないます。 これまでの「ネットワークポリシーを強制したい」と矛盾するのですが、「この設定はポリシー違反だけど例外としてオッケー」というステージを作るということです。

  • 一時的な設定
  • ビジネスとしてGO 判定されたが、ネットワークポリシー・標準とするか判断されていない設定

向けのステージですね。「この設定ブロックがそうですよ」と明記しつつ、一時的に許容します。

実装のヒント

多くのネットワークデバイスの設定は宣言的であり、それ自体設定ではないが設定を削除するコマンド ( no, delete など ) があることを利用し、

  • 標準化済みの設定を出力 (構成管理DB + テンプレートから)
  • その後に標準化されていない設定を出力 (自由記述)

とするだけで、結構うまくいきます。

標準化済みの設定 (ピンクの部分) をテンプレートが生成し、別管理してある標準化されていない自由記述設定 (白の部分) と結合するだけですね。結合してうまくいくように、白の部分は工夫して書く必要があります。

個人的には 自由記述枠のことを昔「hack」と呼んでいましたが、最近は「patch」と呼んでいます。

標準化・実装が間に合わない部分をパッチすることで 1. 標準化とテンプレート開発を同時進行する ことができ、2. ポリシー外の設定を管理する ことができます。当初はパッチが大半ですが、テンプレート実装と実機設定の標準化を進めながら、ピンク部分を100% にすることを目指します。

実機設定とのdiff

パッチのしくみで、テンプレート出力 (パッチ含む) は簡単に手に入りますが、これだけでは「手で入れた設定」が抽出できません。別途うまいことdiff するしくみが必要になります。

テンプレート出力(左) と実機設定(右) をdiff する際、パッチブロックをうまくマージしつつ、同一のものとして扱います。これによって「手で入れた設定」が抽出でき、 それをテンプレート実装する or パッチに入れるの判断が下せるようになります。

パッチには nodelete が混じっている可能性もあり、うまくdiff するには構文解析が必要になります。 ここはそれなりに手間がかかりますが、うまいことやってください。

なお、Juniper の構文解析機能は OSS として公開しています。興味があればご覧ください。

github.com

パッチの運用

手で入れた設定は、テンプレート出力(パッチ含む) をロードしてしまうと失われます。 なので定期的に、もしくは何か Event を hook してチェックし、テンプレート実装する or パッチに入れる 判断を促す必要があります。

手で入れた設定は、👇 のようなライフサイクルをたどるイメージになります。

  1. ビジネス判断により、ネットワークに入れる
  2. diff によって検知され、パッチする = 永続化される
  3. 標準として認められれば、テンプレート実装する

パッチを個別に管理することは「ポリシー外がこれだけありますよ」と定量評価できる点で重要だと思っています。

運用的な観点でいえば、例外は想定外なルーティングをし、事故の原因になるかもしれません。 一方で全てテンプレート化するのも毒で、パターンの多さはコードが複雑になるだけではなく、オペレーターを混乱させてしまいます。

何を標準とするか、どれくらいのパターンを許容するか、どのくらいの量のパッチを許容するかは 各社のビジネスや運用によるため「これ」という基準を提示できませんが、定期的に棚卸しする場を持つことは重要だと思います。

「このパッチは標準にいれるべきか」「このパッチは消すべきではないか」などを議論する場ですね。

まとめ

手動オペレーションを許容しつつ、テンプレートシステムによってネットワークポリシーを強制するアプローチについて書きました。これは、従来のネットワーク運用から漸進的に自動運用に移行することを意識しています。

ここでは「全体として、意図どおり設定されているか」のチェックに留まっていますが、本来のNetwork Validation はふるまいの確認であり、さらに先にあります。それについてはまた別で書きたいと思います。