ネットワーク標準化ギプス
テキストやファイルで設定管理されるようなネットワークの、設定標準化・テンプレート化・Validation について書きます。 経験上、ISP・コンテンツプロバイダなどのネットワークでうまくいった手法ですが、よりよい方法があるかもしれません。ご指摘・コメント頂けるとうれしいです。
- 現在自動化できていないが、自動化を目指したい
- 移行過渡期は、もしくは移行後であっても運用上の都合で、手動投入は許容したい
- ネットワークが正しく設定されているか? を常にチェックしたい
このようなネットワーク運用を想定します。
やりたいこと
ネットワークデバイスはシステム側からもオペレーターからも変更されうる という環境で、
- ネットワークポリシー・設定を標準化し、テンプレートとして実装する
→ テンプレートが強制力としてはたらき、ポリシーが維持できる - 何かのトリガーで 構成管理DB + テンプレートから設定を生成し、自動 or 手動によりネットワークデバイスにロードする
→ オペレーターが手動投入した (= テンプレート化されていない) 設定との調整は よしなにやる - オペレーターが投入した設定がポリシーに即しているかチェックする
- ネットワーク全体として、意図どおり設定されているかチェックする
👆 がやりたいことの概要です。
自動化によって運用コストを下げるのは当然として、手動オペレーションを許容しつつも ネットワークポリシー(標準設定) を強制することが目的です。
1. 手動オペレーションを許容する
やりたいことについて、いくつか補足します。 この項目は、従来のネットワーク運用から漸進的にシステム導入するために必要です。
手動オペレーションで運用している or 部分的に自動化している という状態から、ネットワークが標準化されていて テンプレートがあり、すべてをシステム経由で行う運用に一足で移行するのは、運用的にはかなり大きなチャレンジで、できれば避けたいところです。
2. 個々の業務を自動化するのではなく、完全な設定をテンプレート出力 & ロードする
こうする必要があるのは、手動オペレーションを許容しつつも、テンプレートにネットワークポリシー強制力を期待するからです。
たとえば「よくやる業務はテンプレートで自動化されているが、まれな作業は手で設定する」ようなケースを想像してください。 この場合、手で入れた設定も含めてポリシーに準拠しているかを判定するのは大変です。
よくやる業務(下図グレー部分) はポリシー準拠ですが、手動設定時(下図ピンク部分) は何が設定されているか分かりません。手動設定の特定でさえ難易度が高いと思います。
- アクセスできるのは、各業務のテンプレート + 現在の設定(= 各業務の累積) のみ
- ポリシーは変化する
点にも注意してください。
今回の目的で言えば、「業務を積み重ねた結果である現在の設定」をチェックするほうがシンプルで、「各業務を自動化する」の延長では複雑になりそうです。 完全な設定をテンプレート出力したいのは、こういった理由からです。
実装のためのアプローチ
さて、テンプレートシステムを実装するにあたり、どのようなアプローチを取るかについて。 ここでは具体的な実装例について触れませんが、進め方の指針をいくつか記載します。
1. 標準化とテンプレート開発を同時進行する
「自動化の前に標準化しましょう」というのは基本ですが、個人的な経験でいえば実装前に標準化しきれたことはありません💦
ここでいう標準化とは、ネットワークポリシー・あるべき設定の標準形を制定するだけではなく、実機上の設定を統一するところまでを指します。 手動オペレーションな歴史のあるネットワークであれば、名前の表記揺れ (例: policy-statement / route-map) にはじまり、微妙な設定の揺れがおそらく多々残っていると思います。
これらの標準化に取り組む間もどんどん揺れは混入されますので、もぐらたたきになりがちです。 具体的にどう進めるかは後述しますが、標準化と実装は 同時進行すると良いと思っています。
2. ポリシー外の設定を許容する
別の重要なポイントとして、ビジネスを止めたくありません。 ネットワークポリシーを標準化し、実装し、できればキレイな状態で維持したいのですが、どんどん変わるビジネス要件に対応する必要があります。 「ユーザーの新たな要望に応えたい」だったり、「バグ対応で設定や運用を変えたい」だったり、要件は様々です。
そのたびに「ポリシーとして標準化して、ツール化しないとネットワークに入れられません」ではスピード感を損ないます。 これまでの「ネットワークポリシーを強制したい」と矛盾するのですが、「この設定はポリシー違反だけど例外としてオッケー」というステージを作るということです。
- 一時的な設定
- ビジネスとしてGO 判定されたが、ネットワークポリシー・標準とするか判断されていない設定
向けのステージですね。「この設定ブロックがそうですよ」と明記しつつ、一時的に許容します。
実装のヒント
多くのネットワークデバイスの設定は宣言的であり、それ自体設定ではないが設定を削除するコマンド ( no
, delete
など ) があることを利用し、
- 標準化済みの設定を出力 (構成管理DB + テンプレートから)
- その後に標準化されていない設定を出力 (自由記述)
とするだけで、結構うまくいきます。
標準化済みの設定 (ピンクの部分) をテンプレートが生成し、別管理してある標準化されていない自由記述設定 (白の部分) と結合するだけですね。結合してうまくいくように、白の部分は工夫して書く必要があります。
個人的には 自由記述枠のことを昔「hack」と呼んでいましたが、最近は「patch」と呼んでいます。
標準化・実装が間に合わない部分をパッチすることで 1. 標準化とテンプレート開発を同時進行する ことができ、2. ポリシー外の設定を管理する ことができます。当初はパッチが大半ですが、テンプレート実装と実機設定の標準化を進めながら、ピンク部分を100% にすることを目指します。
実機設定とのdiff
パッチのしくみで、テンプレート出力 (パッチ含む) は簡単に手に入りますが、これだけでは「手で入れた設定」が抽出できません。別途うまいことdiff するしくみが必要になります。
テンプレート出力(左) と実機設定(右) をdiff する際、パッチブロックをうまくマージしつつ、同一のものとして扱います。これによって「手で入れた設定」が抽出でき、 それをテンプレート実装する or パッチに入れるの判断が下せるようになります。
パッチには no
や delete
が混じっている可能性もあり、うまくdiff するには構文解析が必要になります。
ここはそれなりに手間がかかりますが、うまいことやってください。
なお、Juniper の構文解析機能は OSS として公開しています。興味があればご覧ください。
パッチの運用
手で入れた設定は、テンプレート出力(パッチ含む) をロードしてしまうと失われます。 なので定期的に、もしくは何か Event を hook してチェックし、テンプレート実装する or パッチに入れる 判断を促す必要があります。
手で入れた設定は、👇 のようなライフサイクルをたどるイメージになります。
- ビジネス判断により、ネットワークに入れる
- diff によって検知され、パッチする = 永続化される
- 標準として認められれば、テンプレート実装する
パッチを個別に管理することは「ポリシー外がこれだけありますよ」と定量評価できる点で重要だと思っています。
運用的な観点でいえば、例外は想定外なルーティングをし、事故の原因になるかもしれません。 一方で全てテンプレート化するのも毒で、パターンの多さはコードが複雑になるだけではなく、オペレーターを混乱させてしまいます。
何を標準とするか、どれくらいのパターンを許容するか、どのくらいの量のパッチを許容するかは 各社のビジネスや運用によるため「これ」という基準を提示できませんが、定期的に棚卸しする場を持つことは重要だと思います。
「このパッチは標準にいれるべきか」「このパッチは消すべきではないか」などを議論する場ですね。
まとめ
手動オペレーションを許容しつつ、テンプレートシステムによってネットワークポリシーを強制するアプローチについて書きました。これは、従来のネットワーク運用から漸進的に自動運用に移行することを意識しています。
ここでは「全体として、意図どおり設定されているか」のチェックに留まっていますが、本来のNetwork Validation はふるまいの確認であり、さらに先にあります。それについてはまた別で書きたいと思います。