構成情報データベースをGitで管理したいネットワーク運用者の憂鬱

498 views

Published on

NetOpsCoding#4の発表資料です。現時点では事前資料ですので、講演後に予告なく資料が更新される可能性があります。

Published in: Internet
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
498
On SlideShare
0
From Embeds
0
Number of Embeds
21
Actions
Shares
0
Downloads
6
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

構成情報データベースをGitで管理したいネットワーク運用者の憂鬱

  1. 1. © INTERNET MULTIFEED CO. 構成情報データベースを Gitで管理したい ネットワーク運⽤者の憂鬱 インターネットマルチフィード株式会社 川上 雄也 2016/10/27 NetOpsCoding#4
  2. 2. © INTERNET MULTIFEED CO. 2 今⽇のお話 n  MRTGやNagiosなどのサーバ系のコンフィグをDBから⽣成するようにしました n  DBにはYAMLを使ってGitで差分管理するようにしました n  YAML+Gitで運⽤してみてRDBと⽐較して実際にどうだったか振り返ります n  これから⾃動化を進めるにあたってのDB運⽤の課題を紹介します
  3. 3. © INTERNET MULTIFEED CO. 3 ⾃⼰紹介 n  お仕事 p  インターネット・エクスチェンジサービスJPNAPの運⽤⾃動化・⾼度化 p  時期バックボーンの設計・検証 p  その他JPNAPの技術的なこと関すること全般 n  得意な⾔語:Ruby n  関連発表 p  JANOG34「ネットワークエンジニアとソフトウェアエンジニアの狭間で」 p  InternetWeek2014「ネットワーク運⽤⾃動化のためのサービス・運⽤設計」 川上 雄也 (@yuyarin) インターネットマルチフィード株式会社 技術部 JPNAP ネットワークエンジニア&ソフトウェアエンジニア JANOG運営委員・ShowNet NOCメンバー
  4. 4. © INTERNET MULTIFEED CO. 4 JPNAP (JaPan Network Access Point) n  インターネット・エクスチェンジ・サービス p  L2スイッチのポートへを提供 p  お客様同⼠でBGPでピアを張ってもらい経路交換とトラフィック交換をしてもらう p  接続しているネットワーク(AS)は100ちょっと p  ピークトラフィックは730Gbps p  詳しくは: http://www.mfeed.ad.jp/service/jpnap.html BGPルータ L2SW BGPルータ BGP 経路交換とトラフィック交換
  5. 5. © INTERNET MULTIFEED CO. 5 JPNAPのネットワーク&システム構成 JPNAP Backbone お客様 ルータ 光スイッチ 監視サーバ(Nagios) グラフサーバ(MRTG) ルートサーバ L2SW(主系) L2SW(副系) JPNAP BGPルータ アラートサーバ OpsサーバMLサーバ FlowサーバWebサーバ
  6. 6. © INTERNET MULTIFEED CO. 6 JPNAPで必要な設定作業 n  作業内容 p  プロビジョニング u  モジュールの増設・撤去 p  SO作業 u  新規開通、増速、接続場所変更、VLAN追加など p  UNIに影響のないバックボーン作業(⼣⽅) u  バックボーン増速や機器の追加などの作業 p  UNIに影響のあるバックボーン作業(深夜) u  ファームウェア更新など機器の再起動を伴う作業 n  作業対象 p  L2スイッチなどのネットワーク機器のコンフィグ(UNI側) p  L2スイッチなどのネットワーク機器のコンフィグ(BB側) p  MRTGやNagiosなどのサーバ系のコンフィグ(BB&UNI)
  7. 7. © INTERNET MULTIFEED CO. 7 これまでの運⽤ n  ネットワーク機器の設定 p  ⼿順書をテキスト作成して承認をもらってその通りにコマンドを実⾏ n  サーバ系の設定 p  わかってる⼈がテキストエディタでコンフィグを書いてRCS管理してscpでデプロイ n  特にサーバ系は… p  不幸な⼈為ミスのオンパレード p  表記ゆれ、フォーマット違い、バラバラの命名が多発 p  1件のSO作業に超絶時間がかかる p  精神が病む 全てが⼿作業!!!
  8. 8. © INTERNET MULTIFEED CO. 8 せめてサーバ系のコンフィグだけでも… データベースから ⾃動⽣成したい!
  9. 9. © INTERNET MULTIFEED CO. 9 どのデータベースを使う? ▶  MySQL/MariaDB ▶  PostgreSQL ▶  SQLite RDB ▶  CSV, TSV ▶  XML ▶  YAML ▶  JSON テキスト ▶  MongoDB NoSQL ▶  Excel その他
  10. 10. © INTERNET MULTIFEED CO. 10 どうやってデータベースを選ぶか n  運⽤を無視した「ツール・ファースト」は運⽤現場を崩壊させるだけ n  ⾒るべきポイント p  データベースの変更⽅法・⼿順 p  ⽣成したコンフィグのデプロイ⽅法・⼿順 p  ⽣成するツールの使い⽅ p  ⽣成するツールを書くプログラミング⾔語 p  使⽤したミドルウェアの運⽤ まずは⾃分たちの運⽤⽅法や⽂化に即した技術を選ぶ
  11. 11. © INTERNET MULTIFEED CO. 11 深夜のある⼤規模作業 n  スイッチのファームウェアのバージョンアップ p  ラインカードを⾼密度のものに変更する p  そのためにUNIの収容ポートを変更しないといけない n  データベースの変更⼿順 1.  顧客ポートから抜去するラインカードのポートを削除 2.  スイッチからラインカードを削除 3.  スイッチのファームウェアのバージョンを変更 4.  スイッチに新しいラインカードを登録 5.  新しいラインカードのポートを顧客ポートに登録
  12. 12. © INTERNET MULTIFEED CO. 12 JPNAPのオペレーションの体制 n  オフィス作業者:2名(作業者+確認者) p  ネットワーク機器の設定を実施する u  ⼿順書は予め作成しておき承認を得る必要がある p  深夜作業の場合はサーバ系の設定も実施する u  通常はサーバ系の設定はサーバ担当で作業の前後のどこかで⾮同期に実施するが、 ⼤規模深夜作業の場合は、作業中に何度も設定を⾏わないといけないから u  そのためコンフィグは予め作成して正しいか確認しておく必要がある n  現地作業者:各DCに2名(必要な場合)
  13. 13. © INTERNET MULTIFEED CO. 13 ⼤規模作業時のサーバ系設定の要件 n  サーバ担当がいなくてもサーバ系の設定作業が実施できる p  どうしようもなく⼤変なときは専任でサーバ担当をつけるけど… n  サーバ系の設定作業と確認にはあまり時間がかけられない p  ネットワーク機器の設定・確認だけでも結構な時間がかかる n  各ステップのデータベース変更後に吐き出される予定のコンフィグは 作業前⽇までに確認・承認しておきたい p  ただし作っている間にも別の作業でデータベースは更新される p  コンフリクトが起きないようにしておくか、誰でもコンフリクトを解消できるように しておく必要がある
  14. 14. © INTERNET MULTIFEED CO. 14 もしもデータベースがRDBだったら… n  コンフィグの事前の作り込みと確認はどうやる… p  データベースをどこかにクローンしてきて、変更を加えて、コンフィグを吐き出す? n  DBにどうやって変更を加える?⼿順書には何が書かれる? p  パターン1:SQL⽂を直接実⾏ p  パターン2:WebUIから操作する p  パターン3:rails cでワンライナーを撃ちまくる
  15. 15. © INTERNET MULTIFEED CO. 15 もしもデータベースがRDBだったら… n  パターン1:SQL⽂を直接実⾏する p  SELECT⽂で確認して、UPDATEやINSERTで更新する p  SQLの⼿順書を作ってから構成情報に変更があって、コンフリクトに気づかずに 実⾏したら悲惨なことになる u  コンフリクトに気づいたときに適切にマージできる判断⼒が必要になる u  この場合は解決するための適切なSQL⽂を作ることができる必要がある p  作業者がシステム設計、DB、SQLについて詳しくないと何かあったときに対応できない u  何が起きるのか理解できていないコマンドを実⾏させるの?という問題も p  てか、まじで⽣SQL叩くの? u  モデルのバリデーションはすっとばすの? u  例えばモジュールを搭載したらインターフェイスのオブジェクトも作らないといけないので… ▼db9 SELECT switch_modules.status FROM switch_modules JOIN switches ON switch_modules.switch_id = switch.id WHERE switch.hostname = 'ix-tky-sw1' AND switch_modules.slot_number = 1 → Empty であること UPDATE (以下略)
  16. 16. © INTERNET MULTIFEED CO. 16 もしもデータベースがRDBだったら… n  パターン2:WebUIを操作する p  コンフリクトの問題は発⽣するが、WebUIの操作ならなんとかできる気がする p  WebUIの操作⼿順書は書くのが⾟い p  WebUIの操作⼿順は作成者の意図した通りの操作が⾏われる保証がない p  WebUIの操作は時間がかかるのでメンテナンス中にやってられない p  そもそもWebUIの実装コストが⾼い u  scaffoldとかActive Adminの画⾯ではみんな満⾜してくれない… ▼トップ画⾯ 左上のメニューから「スイッチ⼀覧」を選択 ▼スイッチ⼀覧画⾯ スイッチ⼀覧から「ix-tky-sw1」を選択 ▼スイッチ詳細画⾯ ix-tyk-sw1のモジュール⼀覧のSlot 1の⾏の「状態」が「Empty」であることを確認 同じ⾏の右端のカラムの「搭載」を押下 ▼モジュール選択画⾯ モジュール検索窓に「4x10G」と⼊⼒し、表⽰された⾏の「選択」ボタンを押下 ▼スイッチ詳細画⾯ ix-tyk-sw1のモジュール⼀覧のSlot 1の⾏の「種別」が「4x10G」であることを確認
  17. 17. © INTERNET MULTIFEED CO. 17 もしもデータベースがRDBだったら… n  パターン3:rails cで打つワンライナーが書いてある p  rails cを起動して、Rubyのワンライナーで確認、更新する p  モデルのバリデーションを通すだけパターン1よりまだマシ p  コントローラを呼ぶならもっとマシ p  コンフリクトしたときの解決はシステムとRoRに詳しくないと無理 ▼db9 rails c → rails consoleを起動 irb> slot = SwitchModule.includes(:switch).where("switch.hostname ='ix-tyk- sw1'").where("switch_module.slot_number = 1").first irb> slot.state.name → Emptyであること ※以下⻑すぎて書く気が起きなかった…
  18. 18. © INTERNET MULTIFEED CO. 18 RDBは作業⼿順を考えるとやっぱ⾟いので Gitなら…! なんとかなる 気がする…!
  19. 19. © INTERNET MULTIFEED CO. 19 JPNAPの選択 n  要件 p  運⽤者が読み書きしやすいフォーマットであること(human readable) p  機械処理が簡単であること(machine friendly) p  バージョン管理(差分管理とブランチ作成)ができること n  利点 p  ファイルなので誰でも操作できてテキストエディタで編集もできる p  ミドルウェアの管理が必要なくなる p  意味のある単位でコミットが作られるので後からトレースしやすい p  ⼤規模作業⽤にブランチを切ってコンフィグを作り込んでおける p  ssh & git pullで簡単にデプロイできる テキストベースのYAMLをデータベースにしてGitで管理
  20. 20. © INTERNET MULTIFEED CO. 20 ⼤規模作業時のサーバ系コンフィグのワークフロー n  ⼀週間前くらい p  ⼤規模作業⽤にブランチを作成 p  作業のステップごとにDBを書き換えてコミットを作成、Tag打ちする p  各ステップのDBの内容に基づいてコンフィグを⽣成し、レビューする n  メンテナンスの直前の⼣⽅ p  サーバ担当者が⼤規模作業⽤ブランチをrebaseする u  ブランチを作成してから加えられた変更をマージする u  コンフリクトが発⽣したら適切にマージする p  これ以降はDBへの変更投⼊を禁⽌する n  深夜のメンテナンス中 p  作業担当者が各ステップごとにcherry-pickでDBへの変更を反映して、 コンフィグを⽣成し、各サーバにデプロイする n  メンテナンス後の平⽇⽇中 p  ブランチを削除する
  21. 21. © INTERNET MULTIFEED CO. 21 コンフィグの⽣成⼿順 1.  データベースであるYAMLに変更を加える 2.  rake コマンドでデータベースとテンプレートからコンフィグを⽣成 3.  rake diff コマンドで差分を確認する 4.  rake commit コマンドでcommitしてGitLabのリポジトリにpush 5.  rake deploy コマンドでサーバにデプロイ ※ ⼤規模作業時は⼿順1がgit cherry-pickになります GitLab push 監視サーバ(Nagios) グラフサーバ(MRTG) YAML DB ConfigGenerator Config Templates pull ⚙ libjpnap
  22. 22. © INTERNET MULTIFEED CO. 22 ⼤規模作業時のサーバ系コンフィグの⼿順 n  変更作業がgitコマンド1発で完了 n  実⾏する各コマンドの意味は数分のレクチャーで簡単に理解可能 ▼ops:~/server-config-generator/database git cherry-pick -n origin/20161027_netopscoding4_step01 rake rake diff →差分を確認 rake commit M="Insert 4x10G module to slot 1" rake deploy → OKと表⽰されること → システム側で確認作業を実施
  23. 23. © INTERNET MULTIFEED CO. 23 テキストベースDB&Git管理の評価 n  運⽤実績 p  2014年3⽉に導⼊してから約2年半で約900コミットの作業を実施 p  YAMLとGitに関するトラブルは無し n  良かった点 p  ブランチを切る運⽤は⾮常に良く機能した p  意味のある単位でコミットが作られ、差分がわかりやすいのでダブルチェックが楽 n  悪かった点 p  YAMLを読み込んで作ったRubyのオブジェクト間のリレーションシップが相互参照にな る実装だったので… u  ppしたときに全オブジェクトが出⼒されるし、pryのデバッグが地獄 u  Stack Traceが重すぎる(Rack AppだとCPU100%で固まる) p  git pullでのデプロイに結構時間がかかる u  GitLabのパフォーマンスがボトルネックで並列化できない p  プログラムからDBを変更する必要がある次のレベルの⾃動化には適さない u  オブジェクトを操作してYAMLに吐いてGit管理する?
  24. 24. © INTERNET MULTIFEED CO. 24 運⽤⾃動化の段階 ▶  単体の機能・スクリプトだけを実装すればOK Phase 1 スクリプトに必要なパラメータを渡して⼈間が実⾏ ▶  データベースとテンプレートを作っておけばOK ▶  ただし機器やシステム側にコンフィグリロードの仕組みがないとダメ Phase 2 データベースから全コンフィグを⽣成して機器にデプロイ ▶  ワークフロー、イベントハンドラ、メッセージキューイング、シリア ライズ、ロックなどの⾼度な仕組みが必要 ▶  データベースはシステムによりその都度⾃動で更新されていく Phase 3 イベントドリブンで必要なコンフィグの差分を機器に投⼊ イマココ
  25. 25. © INTERNET MULTIFEED CO. 25 Phase 3でのテキストベースのDB n  ファイルを読み込んで、オブジェクトにして、オブジェクトを操作して、また ファイルに書き出す p  コメントは全部消えます(まぁ仕⽅ないか) p  YAMLだと⼈間の書いたコンフィグと吐き出されるコンフィグの差分が… u  その都度吐いて、吐かれたものをコミットすればなんとか u  マージは⼈間がやる n  ⼈間の編集とシステムによる⾃動更新のコンフリクト p  ⼈間がDBを直接編集することは避けられない p  ⼈間が編集中はDBをロックしておく? u  その間お客さまが何か作業をしたくてもエラーになってしまう…(まぁそれはそれであり) u  トランザクション機能は必要 p  まぁでもRDBでもそれは起きるよなぁ そこそこつらみがあるがなんとかなる?
  26. 26. © INTERNET MULTIFEED CO. 26 Phase 3でのPhase 2ベースのシステムの課題 n  データベースからコンフィグを全⽣成するタイミング p  イベントごとに意味のある処理が⾏われたら⽣成する? u  デプロイに10分とかかかってると次のイベントがブロックされてしまう p  定期的に⽣成する? u  たまたまそのタイミングでデータベースが不完全な状態だったらどうしよう u  トランザクションを使ってAtomic性を保証しておく?
  27. 27. © INTERNET MULTIFEED CO. 27 ブランチ切れるRDBって… n  こういうのもあるっぽいけど… p  https://github.com/attic-labs/noms
  28. 28. © INTERNET MULTIFEED CO. 28 Phase 3の⾃動化に向けて n  データベースの実装 p  Rails + PostgreSQLを利⽤するつもり n  ネットワーク機器の操作スクリプト p  Telnet/sshのラッパーライブラリを各機器種別ごとに作成 p  細かい単位のワークフローの実装 p  従来のテキスト⼿順書のようにコードを記述できるDSLライブラリ n  「ワークフロー、イベントハンドラ、メッセージキューイング、シリアライズ 、ロックなどの⾼度な仕組み」 p  StackStormを有効活⽤ p  Webポータル操作をイベントとして、スクリプトを実⾏
  29. 29. © INTERNET MULTIFEED CO. 29 おわり
  30. 30. © INTERNET MULTIFEED CO. 30 (参考) ツールの構成 n  Rakefile 各タスクを記述 n  lib/ 各システム⽤のコンフィグ⽣成のためのライブラリ n  libjpnap/ YAMLを読み込んでRubyオブジェクトを作るライブラリ(git管理) n  database/ YAMLのデータベース(git管理) n  template/ 各システム⽤のコンフィグ⽣成のためのテンプレート(git管理) n  output/ 各システム⽤に⽣成されたコンフィグの置き場所(git管理)
  31. 31. © INTERNET MULTIFEED CO. 31 (参考) YAMLの例 n  設計したモデルに基づいてYAMLを記述する p  switches.yml の例 ix-tky-sw1: hostname: ix-tky-sw1.mgmt.mfeed.ad.jp mgmt_ip_address: 172.16.0.1 vendor: brocade chassis: mlxe32 firmware_version: 10.0 snmp_community: hogehoge modules: S1: 8x10G S2: 2x100G ix-tky-sw2: hostname: ix-tky-sw2.mgmt.mfeed.ad.jp mgmt_ip_address: 172.16.0.2 vendor: brocade chassis: mlxe16 firmware_version: 11.0 modules: S1: 8x10G
  32. 32. © INTERNET MULTIFEED CO. 32 (参考) YAMLのデータからオブジェクトを⽣成する例 n  YAMLを読み込んでRubyのオブジェクトにするライブラリ(libjpnap) p  YAMLのデータをコンストラクタに渡してインスタンスを作っていきリレーションシッ プはオブジェクトの参照として持たせる p  database.rb の例 class Database def load_switches data = YAML.load('switches.yml') data.each do |hostname, switch_data| @switches[hostname] = Switch.new(switch_data) end end end
  33. 33. © INTERNET MULTIFEED CO. 33 (参考) YAMLのデータからオブジェクトを⽣成する例 n  YAMLを読み込んでRubyのオブジェクトにするライブラリ(libjpnap) p  YAMLのデータをコンストラクタに渡してインスタンスを作っていきリレーションシッ プはオブジェクトの参照として持たせる p  switch.rb の例 class Switch attr_reader :hostname, :interfaces def initialize(data) @hostname = data['hostname'] @mgmt_ip_address = data['mgmt_ip_address'] @modules = data['modules'] build_interfaces_from_modules ... end def interface(interface_name) @interfaces[interface_name] end end
  34. 34. © INTERNET MULTIFEED CO. 34 (参考) コンフィグテンプレートの例 n  Rubyのオブジェクトを操作して必要なデータを作成し、ERBのテンプレートで コンフィグを⽣成する(generator) p  各スイッチのインターフェイスのトラフィックを取るMRTGのコンフィグのテンプレー トの例 LogFormat: rrdtool PathAdd: /usr/local/rrdtool/bin/ EnableIPv6: no LogDir: /mrtg-logs/traffic/switch/<%= switch.hostname %> HtmlDir: /mrtg-images/traffic/switch/<%= switch.hostname %> ImageDir: /mrtg-images/traffic/switch/<%= switch.hostname %> NoMib2: Yes SnmpOptions: timeout => 2, retries => 5 RRDRowCount[_]: 19200 MaxBytes[_]: 12500000000 <% switch.interfaces.each do |if_index, interface| -%> <% outfile = "#{switch.hostname}_#{interface.code}" -%> Target[<%= outfile %>]: <%= interface.if_index %>:<%= switch.snmp_community %>@<%= switch.management_ip_address %>:::::2 Title[<%= outfile %>]: <%= switch.hostname %> <%= interface.name %> <br /> ifIndex = <%= interface.if_index %> MaxBytes[<%= outfile %>]: <%= interface.speed.to_bytes %> <% end -%>
  35. 35. © INTERNET MULTIFEED CO. 35 (参考) デプロイの⽅法 n  対象になる全てのサーバに、全システムのコンフィグを含んだGitリポジトリを クローンしておく n  git pullすることでデプロイする n  必要なファイルをシンボリックリンクすることでアプリケーションに読み込ま せる
  36. 36. © INTERNET MULTIFEED CO. 36 (参考) 実装の規模 n  コンフィグ⽣成ツール p  ライブラリ u  12ファイル、18クラス、1,263⾏ p  Rakefile u  35タスク、227⾏ p  スクリプト(sh) u  16ファイル、505⾏ n  データベース p  18ファイル、10,496⾏ n  ライブラリ(libjpnap) p  85ファイル、98クラス、308メソッド、6,048⾏ n  テンプレート p  9種類、81ファイル、2,248⾏ n  コンフィグ p  10種類、1,216ファイル、111,521⾏
  37. 37. © INTERNET MULTIFEED CO. 37 (参考) 時系列 n  2013年秋頃から ⾃動化のための整理を開始 p  ⾊々な命名規則とかファイルの配置とかフォーマットを統⼀する p  ルール作りから初めて、ルールに従ってコンフィグやファイルパスを変更していく p  ハードリンクを張ってファイルパスを切り替える作業とか超⼤変 n  2014年年始から コンフィグ⽣成ツールの実装開始 p  ⽣成したコンフィグと元々のコンフィグの差分を両⽅から埋めていく n  2014年3⽉25⽇ コンフィグ⽣成ツールでの運⽤開始 p  モデルの改良を加えながら2年半運⽤ p  2016年10⽉25⽇までに916コミット

×