Slide 1

Slide 1 text

ネットワーク運⽤用   ⾃自動化の世界2   運⽤用を⽀支援する   システム  /  API  の作り⽅方

Slide 2

Slide 2 text

小島 慎太郎 ! " DPEFPVU http://about.me/codeout w *41೥ OUUOFU"4 w *9೥ +1/"1 w クラウド೥ #)&$

Slide 3

Slide 3 text

ここまでの話

Slide 4

Slide 4 text

デバイスの制御 w ಛʹ෺ཧσόΠε w $-*ΛQBSTF͢Δͷ͸ϋʔυϧ͕ߴ͍ w ίϚϯυ࣮ߦͷͨͼʹTIPXίϚϯυͰ֬ೝ w /&5$0/'͕࢖͑Δ # $ # 制御したい デバイス 管理 サーバー

Slide 5

Slide 5 text

これからの話

Slide 6

Slide 6 text

ωοτϫʔΫӡ༻ʹ͸ɺ ΄͔ʹ΋͍Ζ͍Ζ ίϯϙʔωϯτ͕͋Δ ໨తΛୡ੒͢ΔͨΊʹɺ ͦΕΒΛ͏·͘࿈ܞͤͯ͞ɺ ࣗ෼ͨͪͷӡ༻ʹ͋ͬͨܗͰɺ Ͳ͏΍ͬͯࣗಈԽͨ͠Β͍͍ʁ

Slide 7

Slide 7 text

ネットワーク運⽤用のコンポーネント # $ # 制御したい デバイス 管理 サーバー  管理 データベース & オペレーター 監視 サーバー ' | 可視化/分析 サーバー

Slide 8

Slide 8 text

⾃自動化の⽬目的 w ޮ཰Խ εέʔϧͷ࣮ݱ ίετ࡟ݮ ώϡʔϚϯΤϥʔτϥϒϧͷഉআ ଈ࣌ੑͷ࣮ݱ

Slide 9

Slide 9 text

ଈ࣌ੑͷ ࣮ݱ どこを⾃自動化する? 作業の 複雑さ 対象の多さ / 頻度 多 少 単純 複雑 εέʔϧͷ
 ࣮ݱ ώϡʔϚϯ
 Τϥʔτϥ ϒϧͷഉআ ίετ࡟ݮ 高頻度 コスト: 自動化 < 手動 自動なら エラーしない

Slide 10

Slide 10 text

どこを⾃自動化しない? ΦϖϨʔλʔͷख໨ΛڬΈ͍ͨϓϩηε͸
 ͋Δ͔ʁ w ਓؒͷ໨ͰνΣοΫ͍ͨ͠ w ະ஌ͷΤϥʔʹؾͮ͘Մೳੑ w ϢʔβʔͱҰॹʹ࡞ۀ͍ͨ͠ w ࡞ۀ಺༰͕มΘΔ͔΋ w ࣗࡏʹϩʔϧόοΫதஅ あくまで 可能性…

Slide 11

Slide 11 text

⽬目的によって、   どこを⾃自動化するか   どこを⾃自動化しないか   が変わる

Slide 12

Slide 12 text

ntt.net  (AS2914)

Slide 13

Slide 13 text

ntt.net  (AS2914) w άϩʔόϧ5JFS*41 w ੈքதʹ਺ඦ୆ͷϧʔλʔ w ௿Ձ֨Ͱఏڙ͢Δ͜ͱ͕ॏཁ

Slide 14

Slide 14 text

ଈ࣌ੑͷ ࣮ݱ どこを⾃自動化する? 作業の 複雑さ 対象の多さ / 頻度 多 少 単純 複雑 εέʔϧͷ
 ࣮ݱ ώϡʔϚϯ
 Τϥʔτϥ ϒϧͷഉআ ίετ࡟ݮ

Slide 15

Slide 15 text

すべてを⾃自動化 # $ # (3) 設定投入  (1) データ投入 & (2) 管理サーバーで
 コマンド発行 未使用のもの 含め、すべて監視 ' | 未使用のもの含め、 すべて取得

Slide 16

Slide 16 text

⾃自動化を前提としたサービス w ࣗಈԽͰ͖ͳ͍ػೳ͸ϦϦʔε͠ͳ͍ w Ϣʔβʔཁ๬͕͋ͬͯ΋ɺಛผରԠΛආ͚Δ w ආ͚ΒΕͳ͔ͬͨ΋ͷ͸ɺྫ֎ͱͯ͠؅ཧ w ྫ֎ΛςϯϓϨʔτʹࠩ͠ࠐΉ͘͠Έ w ࣗಈ੍ޚͰ͖ͳ͍σόΠε͸࢖Θͳ͍ w ϫʔΫϑϩʔΛඇಉظʹ͢Δ

Slide 17

Slide 17 text

) ProTip:  rancid • http://www.shrubbery.net/rancid/ w ෇ଐͷDMPHJO KMPHJO qPHJOͳͲ͕ศར w FYQFDUεΫϦϓτͰɺ$-*ͷೖग़ྗΛXSBQ w αϙʔτ͢ΔσόΠε͕ଟ͍ w Τϥʔิ଍ w ϓϩϯϓτมԽʹ௥ਵ $ clogin -x cmd.txt host1 host2

Slide 18

Slide 18 text

さて、⼀一⽅方   JPNAP  では

Slide 19

Slide 19 text

JPNAP w ೔ຊͷ*9 w αʔϏεͷ҆ఆఏڙ͕ॏཁ

Slide 20

Slide 20 text

ଈ࣌ੑͷ ࣮ݱ どこを⾃自動化する? 作業の 複雑さ 対象の多さ / 頻度 多 少 単純 複雑 εέʔϧͷ
 ࣮ݱ ώϡʔϚϯ
 Τϥʔτϥ ϒϧͷഉআ ίετ࡟ݮ

Slide 21

Slide 21 text

デバイス制御以外を⾃自動化 # $ # (2) 手順書 生成  (1) データ投入 & (3) デバイスに
 設定投入 (4) 管理サーバー が自動設定 ' | (4) 管理サーバー が自動設定

Slide 22

Slide 22 text

管理理サーバー w ௚઀σόΠεΛ੍ޚ͢Δ୅ΘΓɺखॱॻΛग़ྗ w Τϥʔัଊ͸ΦϖϨʔλʔʹ·͔͍͍ͤͯ w Θ͔Γ΍͍ࣗ͢વݴޠʹ͢Δඞཁ͋Γ w ࡞ۀεςοϓΛࡉ͔͘෼͚ɺεςοϓ୯ҐͰࣗ ಈԽ w ΦϖϨʔλʔ޲͚ίϚϯυ $-* ntt.net の 管理サーバーと ぜんぜん違う

Slide 23

Slide 23 text

⽬目的が違うと   まねても   うまくいかない

Slide 24

Slide 24 text

じゃあ、   どうすればいいの?

Slide 25

Slide 25 text

部品に注⽬目する w ·ͶΔ͜ͱ͔Β࢝ΊΔͷ͸ॏཁ w Ͱ΋ɺશମΛ·Ͷͯ΋͏·͍͔͘ͳ͍ ‎ߏ੒෦඼ʹ஫໨ͯ͠ɺࣗ෼ͨͪͷαʔϏεʹ ͏·͘ϋϚΔͱ͜Ζ͚ͩΛऔΓࠐΉ

Slide 26

Slide 26 text

連携させる w ෦඼ؒͰ௨৴͢Δ w ͳΔ΂͘Ͱ͋Ε͹ɺ෦඼Λަ׵Մೳʹ w ͍͔ͭมߋ͕ඞཁʹͳΔ w ඞཁʹͳͬͨͱ͖ɺมߋ͠΍͍͢ w खΛೖΕΔൣғ͕খ͍͞‎ϦεΫ௿ݮ w ෦඼୯ҐͰͷςετ͕Ͱ͖Δ w ΠϯλʔϑΣΠε "1* ΛܾΊΔ

Slide 27

Slide 27 text

部品とAPIを   作ってみる

Slide 28

Slide 28 text

# $ # 制御したい デバイス 管理 サーバー & オペレーター 監視 サーバー ' | 可視化/分析 サーバー  管理 データベース ネットワーク運⽤用のコンポーネント

Slide 29

Slide 29 text

# $ # 制御したい デバイス 管理 サーバー & オペレーター 監視 サーバー ' | 可視化/分析 サーバー  管理 データベース STEP  #1:  データベース オペレーター⽤用のGUIと   API  を持つ

Slide 30

Slide 30 text

⾃自作する w Ϛϧνϕϯμʔ؀ڥͰ࢖͑Δ੡඼͕ͳ͍ w ϕϯμʔ੡ͷ΋ͷ͸͋Δ͕ɺ֘౰ϕϯμʔ ઐ༻ w αʔυύʔςΟ੡ w * ϚϧνϕϯμʔରԠͷ΋ͷ͕͋Δ w +"1*͕ͳ͍ w +֦ுੑ͕௿͍

Slide 31

Slide 31 text

Ruby  on  Rails  +  PostgreSQL w *1"EESFTT1SFpY."$"EESFTT
 σʔλܕ͕͋Δʂ w ύϑΥʔϚϯεΛඞཁͱ͠ͳ͍ w ϝϯςφϯεੑΛॏࢹ͢Δ΂͖ w ׳Ε͍ͯΔ͔ w ࣾ಺ඪ४͸͋Δ͔

Slide 32

Slide 32 text

プログラミング⾔言語の選定 w ·ͣɺ׳Ε͍ͯΔݴޠΛબ΅͏ w αʔόʔ w --ʹҰ೔ͷ௕͕͋Δ w ॻ͚Δਓ͕ଟ͘ɺϝϯςφϯε͠΍͍͢ w ੒ख़ͨ͠03. 8FCϑϨʔϜϫʔΫ w (P /PEFΑΓॻ͖΍͍͢ w 3VCZ 1ZUIPO 1)1 1FSM ʜ w ΫϥΠΞϯτ w +BWB4DSJQU

Slide 33

Slide 33 text

データベースの選定 w ·ͣɺ׳Ε͍ͯΔσʔλϕʔεΛબ΅͏ w 3%#.4͕͍͍ w σʔλͷ੔߹ੑΛҡ͍࣋ͨ͠ w ύϑΥʔϚϯεΛඞཁͱ͠ͳ͍ w 1PTUHSF42-WT.Z42- w %JHJUBM0DFBOͷൺֱ͕ࢀߟʹͳΔ w όʔδϣϯʹΑΓ;Δ·͍͕ҟͳΔ৔߹͕͋ΔͷͰ ஫ҙ

Slide 34

Slide 34 text

Device https://github.com/codeout/iw2014_demo $ gem install rails $ rails new configdb --database=postgresql $ cd configdb $ rails g scaffold device name:text fqdn:text platform:text $ rake db:create db:migrate $ rails s # tag v1.0 この時点での状態に タグを打ちました

Slide 35

Slide 35 text

Device

Slide 36

Slide 36 text

JSON  REST  API  ! $ curl http://localhost:3000/devices.json | jq . [ { "id": 1, "name": "device1", "fqdn": "device1.example.com", "platform": "juniper", "url": "http://localhost:3000/devices/1.json" }, { "id": 2, "name": "device2", "fqdn": "device2.example.com", "platform": "juniper", "url": "http://localhost:3000/devices/2.json" } ]

Slide 37

Slide 37 text

Device $ vi Gemfile +gem 'twitter-bootswatch-rails' +gem 'twitter-bootswatch-rails-helpers' +gem 'therubyracer' $ bundle $ rails g bootswatch:install flatly $ rails g bootswatch:themed Devices $ vi app/assets/javascripts/application.js +//= require flatly/loader +//= require flatly/bootswatch $ vi app/assets/stylesheets/application.css + *= require flatly/loader + *= require flatly/bootswatch $ rails s # tag v1.1

Slide 38

Slide 38 text

Device

Slide 39

Slide 39 text

Interface $ rails g scaffold gigabit_ethernet device:belongs_to name:text description:text speed:text $ rake db:migrate $ rails g bootswatch:themed GigabitEthernets # 表示部分 3行修正 $ rails s # tag v1.2

Slide 40

Slide 40 text

Interface

Slide 41

Slide 41 text

どんどん作る w *QW w *QW w "VUOVN w 1FFS UBHW BGP 情報を 格納したい

Slide 42

Slide 42 text

ER図 Configdb domain model Autnum asn integer id integer ∗ name text Device autnum_id integer fqdn text id integer ∗ name text platform text Peer autnum_id integer device_id integer id integer ∗ neighbor text GigabitEthernet description text device_id integer id integer ∗ name text speed text Ipv4 address text gigabit_ethernet_id integer id integer ∗ primary boolean Ipv6 address text gigabit_ethernet_id integer id integer ∗ primary boolean AS-SET 監視フラグ バックアップフラグ SNMP Community duplex MTU up / down フラグ 監視フラグ rate limit ピア種別 MD5 description

Slide 43

Slide 43 text

データモデル w ͍··Ͱͷܗͩͱݕ౼ෆ଍ w ඪ४Խ͞Ε͍ͯΔσʔλϞσϧ͕͋Δ w :"/(.PEFM w *&5'/&5$0/'%BUB.PEFMJOH-BOHVBHF8( w l":"/(%BUB.PEFMGPS*OUFSGBDF.BOBHFNFOUz 3'$ w l":"/(%BUB.PEFMGPS*1.BOBHFNFOUz 3'$ w l":"/(%BUB.PEFMGPS4ZTUFN.BOBHFNFOUz 3'$ w ଐੑ໊΍ߏ଄ͳͲɺ:"/(.PEFMʹ߹Θ͓ͤͯ͘ w ΍Γ͗͢஫ҙ メンテナンス性が 下がる

Slide 44

Slide 44 text

& オペレーター 監視 サーバー ' | 可視化/分析 サーバー STEP  #2:  デバイス制御 # $ # 制御したい デバイス 管理 サーバー  管理 データベース データベースから情報取得   デバイスを制御

Slide 45

Slide 45 text

パラメーターを   データベースから取得 Ͱ౉͢৘ใ͸lΩʔz͚ͩ # $ # (3) 192.168.0.1
 …  (1)device1
 ge-0/0/0
 192.168.0.1
 … & (2) device1
 ge-0/0/0 (4) 設定投入

Slide 46

Slide 46 text

Python  によるREST  API  Client • rest_client.py 1 import json 2 from httplib import HTTPConnection 3 4 session = HTTPConnection('localhost:3000') 5 session.request('GET', '/devices.json') 6 7 response = json.load(session.getresponse()) 8 print(json.dumps(response))

Slide 47

Slide 47 text

Python  によるREST  API  Client $ python rest_client.py | jq . [ { "id": 1, "name": "device1", "fqdn": "device1.example.com", "platform": "juniper", "url": "http://localhost:3000/devices/1.json" }, { "id": 2, "name": "device2", "fqdn": "device2.example.com", "platform": "juniper", "url": "http://localhost:3000/devices/2.json" } ] 4FSWFS 3VCZ Š$MJFOU 1ZUIPO ͕ͩɺ ͥΜͥΜେৎ෉

Slide 48

Slide 48 text

 管理 データベース # $ # 制御したい デバイス 管理 サーバー & オペレーター | 可視化/分析 サーバー STEP  #3:  監視 監視項⽬目を⾃自動設定する 監視 サーバー '

Slide 49

Slide 49 text

監視項⽬目の⾃自動投⼊入 $  & ' (2) 192.168.0.1
 … (1) device1
 ge-0/0/0 (3) 設定投入

Slide 50

Slide 50 text

監視ツール 設定用API 状態取得用API Zabbix ○␣ ○␣ Nagios - ○␣ ϓϥάΠϯ Icinga - ○␣ Sensu ○␣ ○␣

Slide 51

Slide 51 text

Zabbix

Slide 52

Slide 52 text

Zabbix:  監視項⽬目追加 +40/ϝοηʔδΛ)5511045͢Δ { "params": { "interfaceid": "3", "hostid": "10105", "key_": "icmpping[192.168.0.1]", "name": "ping to ge-0/0/1", "delay": 30, "value_type": 3, "type": 0 }, "jsonrpc": "2.0", "method": "item.create", "auth": "580ef2d1e3d7db0f2962bca17de415d1", "id": 2 }

Slide 53

Slide 53 text

pyzabbix  で実装 45 device = 'device1' 46 interface = 'ge-0/0/1' 47 48 device_id = Device(device).device_id() 49 interface_id = GigabitEthernet(device_id, interface).gigabit_ethernet_id() 50 addresses = Ipv4(interface_id).addresses() 51 52 api = ZabbixAPI('http://localhost:8080/zabbix') 53 api.login('admin', 'zabbix') 54 55 hosts = api.host.get(filter={'name': 'device1'}, selectInterfaces=['interfaceid']) 56 57 if hosts: 58 api.item.create( 59 hostid = hosts[0]['hostid'], 60 name = 'ping to %s' % interface, 61 key_ = 'icmpping[%s]' % addresses[0] , 62 type = 0, # Numeric (unsigned) 63 value_type = 3, # Decimal 64 interfaceid = hosts[0]['interfaces'][0]['interfaceid'], 65 delay = 30 66 ) 67 68 # tag v2.0 JSON をPOST DB から 情報取得 add_item.py

Slide 54

Slide 54 text

Zabbix:  監視項⽬目追加 追加できた!

Slide 55

Slide 55 text

Nagios  /  Icinga:   監視項⽬目追加 ϩʔΧϧϑΝΠϧΛฤू͢Δඞཁ͕͋Δ  & ' (2) パラメーター 取得 (3) 設定変更 (1) 追加命令

Slide 56

Slide 56 text

Nagios  /  Icinga:   パラメーター取得  +  設定作成 31 Device.all.each do |device| 32 interface = GigabitEthernet.find_by_device_id(device.id) 33 next unless interface 34 35 ipv4 = Ipv4.find_by_gigabit_ethernet_id(interface.id) 36 puts ERB.new(File.read('template.conf.erb')).result(binding) 37 end • config.rb 1 object Host "<%= device.name %>" { 2 import "generic-host" 3 4 address = "<%= ipv4.address %>" 5 } 6 7 object Service "ping" { 8 import "generic-service" 9 10 host_name = "<%= device.name %>" 11 check_command = "ping4" 12 } # tag v3.0 • template.conf.erb

Slide 57

Slide 57 text

) ProTip:  バージョン管理理 w ઃఆϑΝΠϧͳͲɺςΩετσʔλΛߋ ৽͢Δͨͼʹόʔδϣϯ؅ཧ͢Δ w ઃఆͷཤྺΛอଘ͓ͯ͘͠ͱτϥϒϧ࣌ʹ໾ ཱͭ w ଈ࣌҆શʹϩʔϧόοΫͰ͖Δखஈͱͯ͠

Slide 58

Slide 58 text

API  化したい:   メッセージキューを使う w 4JEFLJR w 3FTRVF w 3BCCJU.2 w ʜ ' (1) メッセージ (命令) を 送信 $ . (2) メッセージ (命令) を 取得し、実行 キュー

Slide 59

Slide 59 text

1 require 'sidekiq' 2 3 Sidekiq.configure_server do |config| 4 config.redis = {namespace: 'icinga'} 5 end 6 7 class Icinga 8 include Sidekiq::Worker 9 10 def perform(command) 11 case command 12 when 'reload' 13 # 設定更新 + Icinga リロード処理 14 end 15 end 16 end # tag v4.0 Nagios  /  Icinga:   Sidekiq  Server • sidekiq_server.rb $ sidekiq -r ./sidekiq_server.rb -c 1 シリアルに処理 メッセージ (命令) ごとの処理を記述

Slide 60

Slide 60 text

1 require 'sidekiq' 2 3 Sidekiq.configure_client do |config| 4 config.redis = {url: 'http://server.example.com:6379', namespace: 'icinga', size: 1} 5 end 6 7 class Icinga 8 include Sidekiq::Worker 9 end 10 11 Icinga.perform_async(:reload) # tag v4.0 Nagios  /  Icinga:   Sidekiq  Client • sidekiq_client.rb サーバー側の キューを指定 メッセージ (命令) 送信

Slide 61

Slide 61 text

 管理 データベース # $ # 制御したい デバイス 管理 サーバー & オペレーター | 可視化/分析 サーバー STEP  #4:  ChatOps イベントをトリガに   決まった作業を実⾏行行し、   情報を流流す 監視 サーバー '

Slide 62

Slide 62 text

ChatOps:
 イベントをチャットに流流す # / # & ' 障害通知 -

Slide 63

Slide 63 text

Slack 通知スクリプトから 特定のURL に JSON データを POST する

Slide 64

Slide 64 text

zabbix-‐‑‒slack-‐‑‒alertscript https://github.com/ericoc/zabbix-slack-alertscript チャットが 流れすぎないよう、 1行に情報を詰め込む

Slide 65

Slide 65 text

デバイスの状態を取得するAPI # / # & ' (2) 情報を埋め込んで 障害通知 - $  (1) デバイスの 状態を取得

Slide 66

Slide 66 text

例例:  デバイスのバージョンを   取得するAPI $ curl http://localhost:3000/devices/3/status/platform.json | jq . { "machine": "firefly-perimeter", "os-name": "JUNOS", "os-version": "12.1X46-D10" } # tag v5.0 このようなAPI を作る

Slide 67

Slide 67 text

) ProTip:  チャットから操作 w νϟοτʹɺಛఆͷϝοηʔδ ໋ྩ Λ ॻ͖ࠐΉ͜ͱͰӡ༻γεςϜΛૢ࡞ w IVCPU w νϟοταʔϏεʹ૊Έࠐ·Ε͍ͯΔ৔߹΋ w ྫ0VUHPJOH8FCIPPLT 4MBDL

Slide 68

Slide 68 text

いきなりスゴいのを⽬目指したらダメ # $ #  & ' | / 設定は 管理サーバー よくある作業は チャットから操作

Slide 69

Slide 69 text

⽬目的に沿っていて、   うまく運⽤用にハマりそう なものから、少しずつ
 連携させてみてください

Slide 70

Slide 70 text

連携し始めたら、   APIが変わってないか   テストしてください

Slide 71

Slide 71 text

運⽤用⽀支援システムを作るコツ w খ͍͞෦඼Λ࿈ܞͤ͞Δ w ෦඼͸ަ׵Ͱ͖ΔΑ͏ʹ w "1*ΛܾΊΔ w ςΩετͰखʹೖΔ΋ͷ͸όʔδϣϯ؅ཧ w ӡ༻ͱטΈ߹͍ͬͯΔ͔͔֬Ίͳ͕Βɺগͣͭ͠ w "1*ͷςετΛ๨Εͣʹ

Slide 72

Slide 72 text

Questions  ?