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

37
© INTERNET MULTIFEED CO. 構成情報データベースを Gitで管理したい ネットワーク運⽤者の憂鬱 インターネットマルチフィード株式会社 川上 雄也 2016/10/27 NetOpsCoding#4

Upload: yuya-rin

Post on 20-Jan-2017

1.345 views

Category:

Internet


2 download

TRANSCRIPT

© INTERNET MULTIFEED CO.

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

インターネットマルチフィード株式会社川上 雄也

2016/10/27 NetOpsCoding#4

© INTERNET MULTIFEED CO. 2

今⽇のお話n  MRTGやNagiosなどのサーバ系のコンフィグをDBから⽣成するようにしましたn  DBにはYAMLを使ってGitで差分管理するようにしましたn  YAML+Gitで運⽤してみてRDBと⽐較して実際にどうだったか振り返りますn  これから⾃動化を進めるにあたってのDB運⽤の課題を紹介します

© INTERNET MULTIFEED CO. 3

⾃⼰紹介

n  お仕事p インターネット・エクスチェンジサービスJPNAPの運⽤⾃動化・⾼度化p 時期バックボーンの設計・検証p その他JPNAPの技術的なこと関すること全般

n  得意な⾔語:Rubyn  関連発表

p  JANOG34「ネットワークエンジニアとソフトウェアエンジニアの狭間で」p  InternetWeek2014「ネットワーク運⽤⾃動化のためのサービス・運⽤設計」

川上 雄也 (@yuyarin)インターネットマルチフィード株式会社 技術部JPNAP ネットワークエンジニア&ソフトウェアエンジニアJANOG運営委員・ShowNet NOCメンバー

© INTERNET MULTIFEED CO. 4

JPNAP (JaPan Network Access Point)n  インターネット・エクスチェンジ・サービス

p  L2スイッチのポートへを提供p  お客様同⼠でBGPでピアを張ってもらい経路交換とトラフィック交換をしてもらうp  接続しているネットワーク(AS)は100ちょっとp  ピークトラフィックは730Gbpsp  詳しくは: http://www.mfeed.ad.jp/service/jpnap.html

BGPルータ L2SW BGPルータ

BGP

経路交換とトラフィック交換

© INTERNET MULTIFEED CO. 5

JPNAPのネットワーク&システム構成

JPNAP Backbone

お客様 ルータ 光スイッチ

監視サーバ(Nagios)

グラフサーバ(MRTG)

ルートサーバL2SW(主系)

L2SW(副系)

JPNAP BGPルータ

アラートサーバ

OpsサーバMLサーバFlowサーバWebサーバ

© 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)

© INTERNET MULTIFEED CO. 7

これまでの運⽤

n  ネットワーク機器の設定p  ⼿順書をテキスト作成して承認をもらってその通りにコマンドを実⾏

n  サーバ系の設定p  わかってる⼈がテキストエディタでコンフィグを書いてRCS管理してscpでデプロイ

n  特にサーバ系は…p  不幸な⼈為ミスのオンパレードp  表記ゆれ、フォーマット違い、バラバラの命名が多発p  1件のSO作業に超絶時間がかかるp  精神が病む

全てが⼿作業!!!

© INTERNET MULTIFEED CO. 8

せめてサーバ系のコンフィグだけでも…

データベースから⾃動⽣成したい!

© INTERNET MULTIFEED CO. 9

どのデータベースを使う?

▶  MySQL/MariaDB ▶  PostgreSQL ▶  SQLite

RDB

▶  CSV, TSV ▶  XML ▶  YAML ▶  JSON

テキスト

▶  MongoDB

NoSQL

▶  Excel

その他

© INTERNET MULTIFEED CO. 10

どうやってデータベースを選ぶか

n  運⽤を無視した「ツール・ファースト」は運⽤現場を崩壊させるだけ

n  ⾒るべきポイントp  データベースの変更⽅法・⼿順p  ⽣成したコンフィグのデプロイ⽅法・⼿順p  ⽣成するツールの使い⽅p  ⽣成するツールを書くプログラミング⾔語p  使⽤したミドルウェアの運⽤

まずは⾃分たちの運⽤⽅法や⽂化に即した技術を選ぶ

© INTERNET MULTIFEED CO. 11

深夜のある⼤規模作業n  スイッチのファームウェアのバージョンアップ

p  ラインカードを⾼密度のものに変更するp  そのためにUNIの収容ポートを変更しないといけない

n  データベースの変更⼿順1.  顧客ポートから抜去するラインカードのポートを削除2.  スイッチからラインカードを削除3.  スイッチのファームウェアのバージョンを変更4.  スイッチに新しいラインカードを登録5.  新しいラインカードのポートを顧客ポートに登録

© INTERNET MULTIFEED CO. 12

JPNAPのオペレーションの体制n  オフィス作業者:2名(作業者+確認者)

p  ネットワーク機器の設定を実施するu ⼿順書は予め作成しておき承認を得る必要がある

p  深夜作業の場合はサーバ系の設定も実施するu 通常はサーバ系の設定はサーバ担当で作業の前後のどこかで⾮同期に実施するが、

⼤規模深夜作業の場合は、作業中に何度も設定を⾏わないといけないからu そのためコンフィグは予め作成して正しいか確認しておく必要がある

n  現地作業者:各DCに2名(必要な場合)

© INTERNET MULTIFEED CO. 13

⼤規模作業時のサーバ系設定の要件n  サーバ担当がいなくてもサーバ系の設定作業が実施できる

p  どうしようもなく⼤変なときは専任でサーバ担当をつけるけど…

n  サーバ系の設定作業と確認にはあまり時間がかけられないp  ネットワーク機器の設定・確認だけでも結構な時間がかかる

n  各ステップのデータベース変更後に吐き出される予定のコンフィグは作業前⽇までに確認・承認しておきたいp  ただし作っている間にも別の作業でデータベースは更新されるp  コンフリクトが起きないようにしておくか、誰でもコンフリクトを解消できるように

しておく必要がある

© INTERNET MULTIFEED CO. 14

もしもデータベースがRDBだったら…n  コンフィグの事前の作り込みと確認はどうやる…

p  データベースをどこかにクローンしてきて、変更を加えて、コンフィグを吐き出す?

n  DBにどうやって変更を加える?⼿順書には何が書かれる?p  パターン1:SQL⽂を直接実⾏p  パターン2:WebUIから操作するp  パターン3:rails cでワンライナーを撃ちまくる

© 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 例えばモジュールを搭載したらインターフェイスのオブジェクトも作らないといけないので…

▼db9SELECT 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 (以下略)

© 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」であることを確認

© 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").firstirb> slot.state.name→ Emptyであること

※以下⻑すぎて書く気が起きなかった…

© INTERNET MULTIFEED CO. 18

RDBは作業⼿順を考えるとやっぱ⾟いので

Gitなら…!なんとかなる気がする…!

© INTERNET MULTIFEED CO. 19

JPNAPの選択n  要件

p  運⽤者が読み書きしやすいフォーマットであること(human readable)p  機械処理が簡単であること(machine friendly)p  バージョン管理(差分管理とブランチ作成)ができること

n  利点p  ファイルなので誰でも操作できてテキストエディタで編集もできるp  ミドルウェアの管理が必要なくなるp  意味のある単位でコミットが作られるので後からトレースしやすいp  ⼤規模作業⽤にブランチを切ってコンフィグを作り込んでおけるp  ssh & git pullで簡単にデプロイできる

テキストベースのYAMLをデータベースにしてGitで管理

© 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  ブランチを削除する

© INTERNET MULTIFEED CO. 21

コンフィグの⽣成⼿順1.  データベースであるYAMLに変更を加える2.  rake コマンドでデータベースとテンプレートからコンフィグを⽣成3.  rake diff コマンドで差分を確認する4.  rake commit コマンドでcommitしてGitLabのリポジトリにpush5.  rake deploy コマンドでサーバにデプロイ

※ ⼤規模作業時は⼿順1がgit cherry-pickになります

GitLab

push

監視サーバ(Nagios)

グラフサーバ(MRTG)YAML DB

ConfigGenerator

Config Templates

pull

⚙libjpnap

© 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と表⽰されること→ システム側で確認作業を実施

© 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管理する?

© INTERNET MULTIFEED CO. 24

運⽤⾃動化の段階

▶  単体の機能・スクリプトだけを実装すればOK

Phase 1 スクリプトに必要なパラメータを渡して⼈間が実⾏

▶  データベースとテンプレートを作っておけばOK▶  ただし機器やシステム側にコンフィグリロードの仕組みがないとダメ

Phase 2 データベースから全コンフィグを⽣成して機器にデプロイ

▶  ワークフロー、イベントハンドラ、メッセージキューイング、シリアライズ、ロックなどの⾼度な仕組みが必要

▶  データベースはシステムによりその都度⾃動で更新されていく

Phase 3 イベントドリブンで必要なコンフィグの差分を機器に投⼊

イマココ

© INTERNET MULTIFEED CO. 25

Phase 3でのテキストベースのDBn  ファイルを読み込んで、オブジェクトにして、オブジェクトを操作して、また

ファイルに書き出すp  コメントは全部消えます(まぁ仕⽅ないか)p  YAMLだと⼈間の書いたコンフィグと吐き出されるコンフィグの差分が…

u その都度吐いて、吐かれたものをコミットすればなんとかu マージは⼈間がやる

n  ⼈間の編集とシステムによる⾃動更新のコンフリクトp  ⼈間がDBを直接編集することは避けられないp  ⼈間が編集中はDBをロックしておく?

u その間お客さまが何か作業をしたくてもエラーになってしまう…(まぁそれはそれであり)u トランザクション機能は必要

p  まぁでもRDBでもそれは起きるよなぁ

そこそこつらみがあるがなんとかなる?

© INTERNET MULTIFEED CO. 26

Phase 3でのPhase 2ベースのシステムの課題n  データベースからコンフィグを全⽣成するタイミング

p  イベントごとに意味のある処理が⾏われたら⽣成する?u デプロイに10分とかかかってると次のイベントがブロックされてしまう

p  定期的に⽣成する?u たまたまそのタイミングでデータベースが不完全な状態だったらどうしようu トランザクションを使ってAtomic性を保証しておく?

© INTERNET MULTIFEED CO. 27

ブランチ切れるRDBって…n  こういうのもあるっぽいけど…

p  https://github.com/attic-labs/noms

© INTERNET MULTIFEED CO. 28

Phase 3の⾃動化に向けてn  データベースの実装

p  Rails + PostgreSQLを利⽤するつもりn  ネットワーク機器の操作スクリプト

p  Telnet/sshのラッパーライブラリを各機器種別ごとに作成p  細かい単位のワークフローの実装p  従来のテキスト⼿順書のようにコードを記述できるDSLライブラリ

n  「ワークフロー、イベントハンドラ、メッセージキューイング、シリアライズ、ロックなどの⾼度な仕組み」p  StackStormを有効活⽤p  Webポータル操作をイベントとして、スクリプトを実⾏

© INTERNET MULTIFEED CO. 29

おわり

© INTERNET MULTIFEED CO. 30

(参考) ツールの構成n  Rakefile 各タスクを記述n  lib/ 各システム⽤のコンフィグ⽣成のためのライブラリn  libjpnap/ YAMLを読み込んでRubyオブジェクトを作るライブラリ(git管理)n  database/ YAMLのデータベース(git管理)n  template/ 各システム⽤のコンフィグ⽣成のためのテンプレート(git管理)n  output/ 各システム⽤に⽣成されたコンフィグの置き場所(git管理)

© INTERNET MULTIFEED CO. 31

(参考) YAMLの例n  設計したモデルに基づいてYAMLを記述する

p  switches.yml の例

ix-tky-sw1:hostname:ix-tky-sw1.mgmt.mfeed.ad.jpmgmt_ip_address:172.16.0.1vendor:brocadechassis:mlxe32firmware_version:10.0snmp_community:hogehogemodules:S1:8x10GS2:2x100Gix-tky-sw2:hostname:ix-tky-sw2.mgmt.mfeed.ad.jpmgmt_ip_address:172.16.0.2vendor:brocadechassis:mlxe16firmware_version:11.0modules:S1:8x10G

© INTERNET MULTIFEED CO. 32

(参考) YAMLのデータからオブジェクトを⽣成する例n  YAMLを読み込んでRubyのオブジェクトにするライブラリ(libjpnap)

p  YAMLのデータをコンストラクタに渡してインスタンスを作っていきリレーションシップはオブジェクトの参照として持たせる

p  database.rb の例

classDatabasedefload_switchesdata=YAML.load('switches.yml')data.eachdo|hostname,switch_data|@switches[hostname]=Switch.new(switch_data)endendend

© INTERNET MULTIFEED CO. 33

(参考) YAMLのデータからオブジェクトを⽣成する例n  YAMLを読み込んでRubyのオブジェクトにするライブラリ(libjpnap)

p  YAMLのデータをコンストラクタに渡してインスタンスを作っていきリレーションシップはオブジェクトの参照として持たせる

p  switch.rb の例

classSwitchattr_reader:hostname,:interfacesdefinitialize(data)@hostname=data['hostname']@mgmt_ip_address=data['mgmt_ip_address']@modules=data['modules']build_interfaces_from_modules...enddefinterface(interface_name)@interfaces[interface_name]endend

© INTERNET MULTIFEED CO. 34

(参考) コンフィグテンプレートの例n  Rubyのオブジェクトを操作して必要なデータを作成し、ERBのテンプレートで

コンフィグを⽣成する(generator)p  各スイッチのインターフェイスのトラフィックを取るMRTGのコンフィグのテンプレー

トの例LogFormat:rrdtoolPathAdd:/usr/local/rrdtool/bin/EnableIPv6:noLogDir:/mrtg-logs/traffic/switch/<%=switch.hostname%>HtmlDir:/mrtg-images/traffic/switch/<%=switch.hostname%>ImageDir:/mrtg-images/traffic/switch/<%=switch.hostname%>NoMib2:YesSnmpOptions:timeout=>2,retries=>5RRDRowCount[_]:19200MaxBytes[_]:12500000000<%switch.interfaces.eachdo|if_index,interface|-%><%outfile="#{switch.hostname}_#{interface.code}"-%>Target[<%=outfile%>]:<%=interface.if_index%>:<%=switch.snmp_community%>@<%=switch.management_ip_address%>:::::2Title[<%=outfile%>]:<%=switch.hostname%><%=interface.name%><br/>ifIndex=<%=interface.if_index%>MaxBytes[<%=outfile%>]:<%=interface.speed.to_bytes%><%end-%>

© INTERNET MULTIFEED CO. 35

(参考) デプロイの⽅法n  対象になる全てのサーバに、全システムのコンフィグを含んだGitリポジトリを

クローンしておくn  git pullすることでデプロイするn  必要なファイルをシンボリックリンクすることでアプリケーションに読み込ま

せる

© INTERNET MULTIFEED CO. 36

(参考) 実装の規模n  コンフィグ⽣成ツール

p  ライブラリu 12ファイル、18クラス、1,263⾏

p  Rakefileu 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⾏

© INTERNET MULTIFEED CO. 37

(参考) 時系列n  2013年秋頃から ⾃動化のための整理を開始

p  ⾊々な命名規則とかファイルの配置とかフォーマットを統⼀するp  ルール作りから初めて、ルールに従ってコンフィグやファイルパスを変更していくp  ハードリンクを張ってファイルパスを切り替える作業とか超⼤変

n  2014年年始から コンフィグ⽣成ツールの実装開始p  ⽣成したコンフィグと元々のコンフィグの差分を両⽅から埋めていく

n  2014年3⽉25⽇ コンフィグ⽣成ツールでの運⽤開始p  モデルの改良を加えながら2年半運⽤p  2016年10⽉25⽇までに916コミット