LGTM

Looks Good To Me

Gitlab + Gitlab CI をためす

Gitlab + Jenkins があまりグッとこなかったので,Gitlab + Gitlab CI をためしてみた.結論から言えば,Gitlab + Jenkins より良いと思う.

Docker 上に準備

やることは

  1. Gitlab コンテナを動かす
  2. Gitlab CI コンテナを動かす
  3. Gitlab Runner コンテナを動かす

OSX 環境でためしたので,

$ docker-machine ip default
192.168.99.100

文中の192.168.99.100 とポートは適宜読み替えてください.

1. Gitlab コンテナを動かす

$ curl https://raw.githubusercontent.com/sameersbn/docker-gitlab/master/docker-compose.yml > gitlab.yml
$ docker-compose -f gitlab.yml up

http://192.168.99.100:10080 にアクセスできるようになるので,

  1. root ログインして必要なユーザーをつくる
    • 鍵を登録する
    • 適当なプロジェクトをつくる
  2. System OAuth applications に,あとで必要になる “http://192.168.99.100:10081/user_sessions/callback” を登録しておく
    • Application Id: b3c0249b80e96cc35c4952bd288d8ba27fdfdbb93cfac6939d1438ffbdb9aa63
    • Secret: a791b4b8e7a6515b457cf94a5246b74c1a72377ada25c009413fe0932f152753

参考: https://hub.docker.com/r/sameersbn/gitlab/

2. Gitlab CI コンテナを動かす

$ curl https://raw.githubusercontent.com/sameersbn/docker-gitlab-ci/master/docker-compose.yml > gitlab-ci.yml
$ vi gitlab-ci.yml

適宜編集

-postgresql:
+ci-postgresql:
   image: sameersbn/postgresql:9.4-3
   environment:
     - DB_USER=gitlab_ci
@@ -6,24 +6,24 @@
     - DB_NAME=gitlab_ci_production
   volumes:
     - /srv/docker/gitlab-ci/postgresql:/var/lib/postgresql
-redis:
+ci-redis:
   image: sameersbn/redis:latest
   volumes:
     - /srv/docker/gitlab-ci/redis:/var/lib/redis
 ci:
   image: sameersbn/gitlab-ci:7.13.5
   links:
-    - redis:redisio
-    - postgresql:postgresql
+    - ci-redis:redisio
+    - ci-postgresql:postgresql
   ports:
     - "10081:80"
   environment:
     - TZ=Asia/Kolkata
-    - GITLAB_URL=http://localhost:10080
-    - GITLAB_APP_ID=
-    - GITLAB_APP_SECRET=
-    - GITLAB_CI_SECRETS_SESSION_KEY_BASE=
-    - GITLAB_CI_SECRETS_DB_KEY_BASE=
+    - GITLAB_URL=http://192.168.99.100:10080
+    - GITLAB_APP_ID=b3c0249b80e96cc35c4952bd288d8ba27fdfdbb93cfac6939d1438ffbdb9aa63  # Application Id
+    - GITLAB_APP_SECRET= a791b4b8e7a6515b457cf94a5246b74c1a72377ada25c009413fe0932f152753  # Secret
+    - GITLAB_CI_SECRETS_SESSION_KEY_BASE=v5W2GBFZP9TxTd29tkxSmpdFm66BD8S9fTrVMrJkmGQ2KddgSqRdCL4t4Npk2vWh # pwgen -Bsv1 64 などで作成
+    - GITLAB_CI_SECRETS_DB_KEY_BASE=94fzWmKLLfWKkWlklQ9C4GXN8svTmnS2wMC7Xm9pw6hwdpLXgCcDl3R9Txxv8nLR # pwgen -Bsv1 64 などで作成
     - GITLAB_CI_HOST=localhost
     - GITLAB_CI_PORT=10081
     - GITLAB_CI_EMAIL=ci@example.com
$ docker-compose -f gitlab-ci.yml up

http://192.168.99.100:10081 にアクセスできるようになるので,

  1. OAuth ログイン
  2. プロジェクト一覧が取れる → 必要なプロジェクトを “Add project to CI”
  3. Runners pageトークンを調べる
    • 9967476047fe03df0f230dca181cf4

参考: https://hub.docker.com/r/sameersbn/gitlab-ci/

3. Gitlab Runner コンテナを動かす

$ docker run -d --name gitlab-runner --restart always \
  -v /srv/gitlab-runner/config:/etc/gitlab-runner \
  gitlab/gitlab-runner:latest
docker exec -it gitlab-runner gitlab-runner register
Please enter the gitlab-ci coordinator URL (e.g. http://gitlab-ci.org:3000/):
http://192.168.99.100:10081/
Please enter the gitlab-ci token for this runner:
9967476047fe03df0f230dca181cf4
Please enter the gitlab-ci description for this runner:
[8370d5d6805a]:
INFO[0129] 99674760 Registering runner... succeeded
Please enter the executor: docker-ssh, ssh, shell, parallels, docker:
[shell]:
INFO[0133] Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

Runners page をリロードすると,Runner が登録されている.

Runner に必要なビルド環境をつくる.(たとえば) ruby をインストール.

$ docker exec -it gitlab-runner bash

$ apt-get update
$ apt-get install -y wget curl gcc libxml2-dev libxslt-dev libcurl4-openssl-dev libreadline6-dev libc6-dev libssl-dev make build-essential zlib1g-dev openssh-server git-core libyaml-dev postfix libpq-dev libicu-dev

$ su gitlab-runner

$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
$ source ~/.bash_profile
$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
$ rbenv install 2.2.3
$ rbenv global 2.2.3

参考: https://gitlab.com/gitlab-org/gitlab-ci-multi-runner/blob/master/docs/install/docker.md

Gitlab CI ができること

  • branch 作成時にCI を回す
  • Merge Request 作成時にCI を回す
    • Gitlab 上に結果表示
  • Status Badge
  • 結果をSlack / HipChat に通知
  • Gitlab と連携
    • OAuth
    • プロジェクト取得

おおよそ十分な機能をもっている.Jenkins がJava なのに対し,go + ruby + rails

Gitlab と一緒に使うならJenkins より直観的だし,プロジェクトごとにrunner を分けられて安心だなと思った.

フルルート入れるのにgobgp を使ってみる

「どの程度お手軽にフルルートを注入できるか?」の続編です.

2015/08/12 追記 : gobgp の不具合,修正されました

codeout.hatenablog.com

今回 gobgp のコミッターさんから「mrt 実装しましたー,もしお時間あったら試してみてください!」と連絡もらったので 試しました.

MRT TABLE_DUMP からフルルートを注入してみます.

gobgp ?

BGP Daemon のGo 実装です. 速そうだしガンガン機能が足されていて 注目のbgpd.

  • Go なので,マルチコアをうまく使ってくれそう
  • gobgpd (サーバー) とgobgp (CLI) で構成されている
  • サーバー <-> CLI 間はgrpc
  • MRT から経路生成できるし,MRT Dump もできる
  • 経路フィルター書けたり,VRF つくれたり,RPKI できたり,route server できたり,EVPN できたりしそう (未確認)
  • ドキュメント

特にサーバーはgrpc を話すので,「手軽にクライアント作れるかもしれないな」とも思ってます.

bgpsimple vs. gobgp

フルルート注入スピードについて,bgpsimple *1と比べてみると

bgpsimple gobgpd
ピアが上がるまで 0'00" 0'07"
フルルート広告し終わるまで 2'42" 1'43"
clear bgp 後,フルルート広告し終わるまで 3'12" 1'24"

gobgp めっちゃ速い!!!

bgpsimple がシングルスレッドなのに対し,gobgpd はマルチスレッドで CPU バウンドな処理と相性よさそう.実際にマルチコアをうまく使ってくれます.

環境

経路受信側は別Hypervisor のvSRX.ボトルネックにならないよう,経路はすべてreject する設定.

gobgp の長所

  • 速い!!!
  • CLI から多少コントロールできる
  • MRT を読んで一旦RIB に格納しているため,経路広告前にbest path selection が走っている
    • 経路の整合性が取れていて,受信側の負荷が下がる
  • MRT を直接入力できる (bgpdump 不要)

gobgp の短所

  • 不具合ありそう
    • eBGP UPDATE メッセージにLP 属性が入っている
    • eBGP UPDATE メッセージのAS_PATH 属性に,自分のAS が入っていない

    見つけた不具合はすぐ修正してもらえました.ありがとうございます

  • サポートOS が少ないかも?

    UNIX 系OS のうち,TCP-MD5 がきちんと実装されているのはLinux くらいだが

    • gobgp「TCP-MD5 サポートのためにLinux 以外は一旦忘れます」
    • 他bgpd「TCP-MD5 は動かないかもしれないけど,他のOS もサポートします」

個人的にはデバッグのためOSX で動くとうれしいが,Linux も手に入りやすい部類だと思う.上記の不具合が解決したら 積極的に使っていきたい.

*1:bgpsimple はMRT から経路生成するならお手軽で便利なので,イチオシだったbgpd

Bot にお願いして 手順書を書いてもらう

ネットワーク運用のなかに「手順書を書く」という業務がある.事業者によっては

  1. 書く
  2. レビュー
  3. 直す
  4. レビュー
  5. 直す

みたいな比較的コスト高い作業になる.

ネットワークは事前にテストしづらく「壊れるとヤバい」という側面から,日本では手作業による温かみのある作業が好まれる.Web アプリのような PRレビュー → Mergeボタン押す → 勝手にデプロイ みたいな自動ワークフローは,エンジニアにとってゴールではあるが,多くの場合まだ現実的でない.

Hubot に手順書を書いてもらう

じゃあ,ということで

GitHub に手順書のテンプレートを置いといて,パラメーターと一緒にお願いしたら,手順書つくってIssue にしてくれるHubot スクリプト

作った.

https://github.com/codeout/hubot-github-templated-issues

f:id:codeout:20150629010651p:plain

テンプレートエンジンはECT を選んだ.

トラブルが起こったときには,すでに手順書ができている

手順書作成のトリガーが人間でない場合もある.たとえばよくあるネットワークトラブルとか,パターン化できてるやつは「通知を受けたときにトラブル対応手順ができてる」のが望ましい.

使っているチャットやログ管理ツールによるが,たとえばHipChat + fluentd の場合:

  1. ネットワークデバイスがsyslog を吐く
  2. fluentd がsyslog をフィルター + 整形して,HipChat にHubot コマンド形式で書く
  3. Hubot が手順書をつくる

ような動作をさせることができる.ここまで自動.*1

f:id:codeout:20150629010658p:plain

# fluent.conf

<source>
  type syslog
  tag network
</source>

<filter network.**>
  type grep
  regexp1 message SNMP_TRAP_LINK_DOWN
</filter>

<filter network.**>
  type record_transformer
  enable_ruby
  <record>
message ${ message =~ /ifName (\S+)/; "hubot issue create templated-issues/intf-down\nhostname: " + host + "\nintfname: " + $1 }
  </record>
</filter>

*1:Slack だと,Web API / Incoming Webhook でHubot にコマンドを送れないため,ひと工夫ひつようっぽい

退職時の年金戦略

昨年12月に会社勤めをやめ,個人事業主になった.5ヶ月たって やっと退職関連の手続きが終わったので,なんでこんな面倒なことになったのかメモっておく.

はー長かった…

企業年金の移換に時間がかかった

会社員だと 企業年金厚生年金基金の積立をしている場合がある.これを個人型の確定拠出年金(DC) に移換しようとしていたため,ものすごい時間かかった.

なんでそんなことしたの?

雑にいえば,税金を取られたくなかったから.

退職時点で 規約型企業年金と企業型確定拠出年金の積立があった.勤務中に年金制度が変わったためにいろんな年金が混ざっているが,

  • 企業年金 → 退職一時金として全額もらうか,個人型DC に移換できる
  • 企業型DC → 個人型DC に移換

前者には選択肢があるが,会社の担当者いわく「みなさん,ほとんど一時金を選択します」とのこと.それ終身雇用の名残なのでは… よく考えないと 自分にあってるかわからないよ? 損するかもよ?

退職一時金を選んだ場合

国民年金と厚生年金の上の3階部分なので 額は大きくないかもしれないが,それでも勤続年数が長いと100万のケタに乗る場合がある.それを受け取ってなにかの資金にするのもアリだが,問題はガッツリ税金をとられること.

退職一時金は退職所得なので,退職金と合算の上 源泉徴収される.所得が増えるので,翌年の住民税が高くなる.

自分の場合は160万の原資に対して,源泉徴収分だけで10% ほど持っていかれる計算だった.

個人型DC に移換する場合

現金が少なくなるのはイタいが,積み立てた原資をそのまま移せる.所得にならないので 翌年の住民税を抑えられる.

自分の場合は150万の使いみちが決まってなかったし,収入が不安定になるから老後とかめちゃくちゃ心配だし,年金運用の資金を少しでも増やすためにこっちを選んだ.

税金って言っても,たかだか15万円とかでしょ?

個人型DC は課税を繰り延べできるので 複利で効いてくる.仮に年5% で運用できたら,30年後には

  • 原資 145万円 → 145 x (1.05 ^ 30) = 626万円
  • 原資 160万円 → 160 x (1.05 ^ 30) = 691万円

65万円のちがいになってる計算.目減りさせないことが鉄則なのです.

繰り延べと言っても,いまの制度だと公的年金と同じ控除 が受けられるので 受給時には税金がかからない可能性もある.

もちろん65歳までに死ぬかもしれないし,運用成績がマイナスになる可能性もあるが,まあそこは目をつぶろう.

まとめ

会社勤めからフリーランスになった場合,もしすぐ現金を必要としてなかったら,企業年金とか厚生年金基金は個人型確定拠出年金に移換したほうが有利そう.

ちなみに,よく知らないが転職の場合も同じように選択できるはず.

BGP Flowspec のバリデーション

BGP ルーターには,Flowspec という機能があります.2009年にRFC5575 として標準化されたもので,ざっくり言えば「遠くのルーターでパケットフィルターを発動させる」機能.

最近 注目されているこのFlowspec のうち,とくにバリデーションについて調べました.

2015-05-28 追記

@shtsuchi さんに指摘をもらい,IOS-XRv の実装が分かりましたので 追記しました.Flowspec ちゃんと動きます.コメントありがとうございました!

2023-01-31 追記

@a16tochjp さんに JUNOS 実装についてコメントをもらい,RFC9117 について追記しました.ありがとうございました!

ところで,使われてるの?

当初脚光を浴びましたが 大規模にデプロイする事業者がなく,その後しばらく下火でした.ここ数年でコンテンツプロバイダー中心にアーリーアダプターが使いはじめ,少しずつ注目されてきたのが現状です.

https://www.slideshare.net/Arbor_Networks/aol-flowspec-2015

BGP Flowspec とは

JANOG35 のセッション が詳しいです.

簡単に言えば

  1. トラフィックを特定するためのL3/L4 情報
  2. 特定したトラフィックの処理方法

をBGP に乗せて伝搬させます.

  1. 通常のBGP で言えば「10.0.0.0/8」が入っていたところに「dst prefix=172.16.0.0/16, src prefix=any, proto=1」のような情報が
  2. BGP community のところに「rate-limit させる」のような情報が

入っているイメージです.*1

show route すれば「ああ,素直に出力してるんだな」と分かる程度にそのまま表示されます.

バリデーション?

Flowspec は パケット操作方法をeBGP にも乗せられる強力な機能なので,標準にも厳しくバリデーション方法が指定されています.各ルーターでは,Flowspec 経路それぞれをバリデーションし,valid であればそこに記述されているパケットフィルターを発動させます.

A flow specification NLRI must be validated such that it is considered feasible if and only if:

a) The originator of the flow specification matches the originator of the best-match unicast route for the destination prefix embedded in the flow specification.

b) There are no more specific unicast routes, when compared with the flow destination prefix, that have been received from a different neighboring AS than the best-match unicast route, which has been determined in step a).

By originator of a BGP route, we mean either the BGP originator path attribute, as used by route reflection, or the transport address of the BGP peer, if this path attribute is not present.

けっこう重要そうな項目なのに,これだけだと意味がわかりませんね.メーカーサイトにもわかりやすいドキュメントがなかったので「いくつかの実装を試して確かめました」というのが今回の趣旨です.

試したのはJuniper vSRX (12.1X47-D15.4),Cisco IOS-XRv (5.2.2).ともにFlowspec をFIB にインストールする部分が実装されていないようで,今回はルーティングだけの確認です.

Flowspec のオリジネーターDestination Prefix

a) Flowspec のオリジネーターは,Flowspec 中のdestination prefix に対するベストマッチ経路のものと一致する必要がある

意味がわからない その1.

オリジネーターとは,BGP originator パスアトリビュートかBGP ピアのトランスポートアドレス

とあります.

BGP originator パスアトリビュートには,ORIGINATOR_ID のことですが,ルートリフレクターがクライアントのrouter ID を格納します.トランスポートアドレスは,ピアを張るIPアドレスそのものを指します.ですのでFlowspec ルーターは,RR 構成であれば経路のrouter ID を,そうでなければneighbor IP アドレスを使ってオリジネーターを識別していることになります.

なるほど.iBGP だけの世界なら単純そう.ところがiBGP とeBGP を混ぜて考えると少しわかりにくいかもしれません.

トランスポートアドレスが一致する,とは?

iBGP とeBGP がある構成を考えます.

上の構成では どこにも経路フィルターを設定していません.RTR1 から10.0.0.0/8 の経路を広告し,RTR3 まで伝えます.

この構成でRTR2 にstatic なFlowspec (dst=10.0.0.0/8) を設定したとすると,RTR3 にも伝搬しますが,そこでは該当のFlowspec 経路はvalid になります.通常の経路はRTR1 でオリジネートし,Flowspec はRTR2 でオリジネートしたにも関わらず,です.

これは経路の向きを逆にして,RTR1 上で考えたとしても同じです.

このような動作になるのは,Flowspec ルーターがトランスポートアドレスによってオリジネーターを識別しているからです.ようするに「オリジネーターが同じ」とは,「同じBGP セッションから受信した」と解釈して構いません.*2

ベストマッチ経路とは?

該当のprefix を含有する最小の経路のことです.

たとえばBGP テーブル上に10.0.0.0/8 と10.0.0.0/16 がある場合,dst=10.0.0.0/24 なFlowspec 経路に対するベストマッチ経路は10.0.0.0/16 です.

また,ベストマッチ経路が存在しない場合はFlowspec 経路はinvalid です.

逆に言うとBGP テーブル上に10.0.0.0/8 がある場合は,dst=10.0.0.0/8~/32 までのFlowspec 経路がベストマッチ経路を持ち,valid になる可能性があります.

Destination Prefix が指定されていなかった場合は?

「dst 条件がなかったらどうなんの?」と思った方はするどいですね.

  • Juniper vSRX の場合
    • dst=0.0.0.0/0 相当です.この場合のベストマッチ経路はデフォルトルート(0.0.0.0/0) です.なので,dst 条件のないFlowspec 経路をvalid にするには,デフォルトルートが必要になります.
  • Cisco IOS-XRv の場合
    • オリジネーターバリデーションしません.なので,dst 条件のないFlowspec 経路をvalid にするために,デフォルトルートは必要ありません.

ここまでのまとめ

a) Flowspec のオリジネーターは,Flowspec 中のdestination prefix に対するベストマッチ経路のものと一致する必要がある

というのは,言いかえると

Flowspec 経路と,そのdestination prefix を含む最小の経路は,同じBGP セッションから受信する必要がある

2015-05-28 追記

Cisco IOS-XRv は「iBGP からFlowspec 経路を受信した場合に限り,上のオリジネーターバリデーションをスキップする」という実装になっています.詳しくは後述しますが,Juniper vSRX と動作が違うので注意です.

More Specific な経路があってはいけない,とは?

b) 異なるAS から受信する,more specific な経路がないこと

意味がわからない その2.

こちらも経路フィルターがない構成で,RTR1 とRTR3 から経路を注入します.すると,RTR2 のBGP テーブルに10.0.0.0/8 と10.0.0.0/24 が乗ります.

この状態ではRTR2 上でdst=10.0.0.0/8 なFlowspec 経路はinvalid になり,Flowspec テーブルには乗りません.more specific な/24 の経路があるためです.

「割り当てられた/8 から/24 を他者に割り振る」ような状況も考慮すると,「/8 単位での制御は危険だからやめとくべき」という意図だと思われますが,ちょっと窮屈ですね.

また,今回のテストではなぜか「異なるAS かどうか」は評価されないように見えました.10.0.0.0/24 をiBGP から受信しようが,eBGP から受信しようが,static な経路だろうが,dst=10.0.0.0/8 なFlowspec 経路はinvalid になります.

RFC によると「異なるAS からmore specific 経路が広告された場合のみinvalid」になりそうですが,そのような動作はしません.*3

Destination Prefix が指定されていなかった場合は?
  • Juniper vSRX の場合
    • dst=0.0.0.0/0 相当なので,デフォルトルート以外の経路が存在しない場合に限り 該当のFlowspec 経路はvalid になります.通常そんなことはありえないので,destination prefix が指定されていないFlowspec は常にinvalid です.
  • Cisco IOS-XRv の場合
    • more specific バリデーションしません.destination prefix が指定されていないFlowspec もvalid になる可能性があります.

Flowspec をstatic に設定することができる

ここまでで,Flowspec のバリデーションは

  • Flowspec 経路と,そのdestination prefix を含む最小の経路は,同じBGP セッションから受信している
  • BGP テーブル上に,destination prefix よりmore specific な経路がない

ことを確認するものだ,と理解できます.

この動作に不都合を感じる場合は,Flowspec をstatic に設定することで,設定したルーター上に限りバリデーションをスキップすることができます.

たとえばJUNOS でdst prefix を指定せずFlowspec を有効にしたい場合,該当ルーターすべてにstatic 設定することで実現できます.ただ,「そこまでするならパケットフィルターを書いて回ったほうがいいんでは」と感じます.

ほかにstatic 設定はFlowspec をオリジネートするためにも使われますが,通常はこっちがメインだと思います.

Neighbor やピアグループ単位でバリデーションを無効にできる (2015-05-28 追記)

AS内だけでFlowspec を使う場合など,厳しいバリデーションが邪魔になることがあります.その場合はNeighbor やピアグループ単位でバリデーションをスキップすることができます.

Juniper vSRX:

protocols {
    bgp {
        group ibgp {
            family inet {
                flow {
                    no-validate skip-validation;
                }
            }
        }
    }
}

policy-options {
    policy-statement skip-validation {
        then accept;  # フィルター条件をいろいろ書ける
    }
}

Cisco IOS-XRv

router bgp 64600
 neighbor 192.168.1.20
  address-family ipv4 flowspec
   validation disable

Juniper vSRX とCisco IOS-XRv のちがい (2015-05-28 追記)

destination prefix 指定のないFlowspec の扱いなどに違いはありますが,一番大きな差は

です.Cisco IOS-XRv はdraft-ietf-idr-bgp-flowspec-oid-02 が実装されており,オリジネーターバリデーションが一部変更されています.

Step (a) of the validation procedure specified in RFC 5575, section 6 is redefined as follows:

        a) One of the following conditions MUST hold true:
           o The originator of the flow specification matches the
             originator of the best-match unicast route for the
             destination prefix embedded in the flow specification.
           o The AS_PATH and AS4_PATH attribute of the flow
             specification are empty.
           o The AS_PATH and AS4_PATH attribute of the flow
             specification does not contain AS_SET and AS_SEQUENCE
             segments.

簡単に言えば「iBGP からFlowspec 経路を受信した場合に限り,上のオリジネーターバリデーションをスキップする」です.オリジネーターがベストマッチ経路と一致しない場合や,ベストマッチ経路が存在しない場合でもvalid になる可能性があります.

RFC9117 (2023-01-31 追記)

現在👆のI-Dは RFC9117 になっています.

datatracker.ietf.org

未確認ですが,多くの実装で iBGP から受信したFlowspec 経路に関するバリデーションをスキップすると思われます。@a16tochjp さんのコメントによると「JUNOSもそうなっている」とのことです.

その他

どう使うか?

今回のIOS-XRv のように期待通り動かないことや,CloudFlare でのトラブル のような例もあります.議論の余地はありますが,現状だと まだ「コミュニティに知見が足りないため検証するしかないが,コストに対して得られるメリットが小さい」場合が多そうです.

一方で「用途を限ればすごく便利で,コスト問題も解決できるかも」と感じています.

たとえば,次のような使い方はよさそう.

  • DDoS 対策など,小さいdst prefix を守るために使う

    • dst prefix が広い場合,more specific バリデーションで落とされる可能性が高い
    • more specific 経路が無ければ大きいdst prefix でも動くが,いちいち確認するのが手間
  • exabgp のようなAPI 豊富なソフトウェアルーターを使い,Flowspec を注入する

    • 自動化のため
  • AS ボーダーでフィルターする目的で,ソフトウェアルーターは1段階だけ下流ルーターとピアする

    • 小さいdst prefix を守りたい場合,その経路はおそらく下流からくる
    • トランスポートアドレスバリデーションにより,AS ボーダーでのみFlowspec が動くと期待できる
  • 特定のルーターでのみ発動させたい場合は,BGP community で制御

強力なので,ハマれば便利そうですが…どうでしょうかね. 「こういう使い方できそう」「こうやってる」などなど,ぜひご意見ください!

*1:1. はMP_REACH_NLRI or MP_UNREACH_NLRI で,2. はExtended BGP community

*2:厳密に言えばこれは間違っていて,たとえばRR - RR client 間に複数BGP セッションがあった場合は,RR から見てどのセッションから受信してもオリジネーターは同じ

*3:仕様なのかバグなのか,未確認

VirtualBox 上の IOS-XRv コンソールに接続する

Cisco IOS-XRv は ハイパーバイザーが開くTTY にコンソールを接続してくれないので,自分で設定する必要がある.

たとえばVMWare FusionコンソールをPTY に繋ぐ機能があるので簡単だが,VirtualBox は面倒.

コンソールをドメインソケットとして出す

下のような設定をする.

socat で接続する

brew install socat
socat UNIX-CONNETCT:/tmp/iosxrv_console stdio,raw,echo=0,escape=0x1a

こんな感じで標準入出力をドメインソケットに接続できる.escape=0x1a^Z で接続を切るための設定.このへん を参考にしながら好みで変えるといいと思う.

ネットワークエンジニアリングはアジャイルじゃない

リーン・スタートアップと言ってもいい.Web 界隈ではあたりまえの開発手法を ネットワークの開発に使うのはむずかしい.

自分はインターネットが得意で (ネットワークとしてのインターネットね!) たかだかIP と上下レイヤーくらいしか分からないんだけど,なにか新機能を作るときの事情はだいたい共通していると思うし,幅広く「ネットワーク」とくくってしまう.実際は共通どころか,エンタープライズネットワークのほうが制約が多いし,IP よりPHY のほうがつらい.まだ自由度があるインターネットでさえ,Web 界隈やミドルウェア,サーバーインフラ界隈のようなスピードで動けない.

うらやましいことに,それらの開発についてはオンライン/オフラインいろんなところで議論され,本が出版され,ノウハウが溜まっていく.一方でネットワーク開発は 低いギアでアクセル踏みっぱなしのような,なんか「タスクこなしてるんだけど進んでない感じ」がする.なんですかこの違い.アプリレイヤーの仕事をしているときとは違ったストレスを感じる.

ネットワークエンジニアリングの現場

ハードウェア / ソフトウェアを使ってネットワークに新機能を足したり,地理的に / 帯域的に拡張したり,運用を変えたりする場合,

  1. どういう技術があるか調査する
  2. テスト環境で粗く試す
  3. 設計する
  4. 必要なハードウェア,ソフトウェアを調達する
  5. 検証環境でちゃんと試す
  6. 必要な回線を調達する
  7. ユーザーから借用をとる
  8. ハードウェア,ソフトウェア,回線をインストールする
  9. デプロイする

みたいなことが必要だが,あるあるネタとして

  • 調達のリードタイムが予測できない / 長い
  • やってみないと,実網にどんな影響が出るかわからない
  • 借用に要する時間が予測できない / 長い

こういう問題をよく見る.たとえばソフトウェア開発と比較すると「ソフトウェアには起こらない問題」と「起こってるんだけど頑張って回避している問題」が含まれていて,ネットワークエンジニアはソフトウェアエンジニアが頑張っているところを盗まないといけないと思う.

もちろん「コード書いて自動化しましょう」もその1つなんだけど,生産性が低い原因はたぶんそれだけではない.

生産性の低さ

自分は,デプロイまでの待ち時間が大きな原因だと思っている.調達とか 会社をまたいで調整しないといけないタスクが挟まっていたり,借用 (お客さんに「メンテしていいですか」と聞いて回る営み) のようなタスクがあるかもしれない.契約上は1ヶ月前に通知すればメンテできるが,慣例で一部法人ユーザーにお伺いを立てたりすることがある.「これ!と決めたやつをデプロイするまでに1ヶ月待たないといけない」なんて普通にある.

そのせいで 年間のデプロイ回数が限られ,フィードバックがないから試行錯誤できず,一発で大成功させようとして準備の時間が増え,待っている間にネットワークが変わって手戻りが発生する. 他者との調整が主なボトルネックだから,ミーティングが増え,資料を作りまくり,調整能力だけがグングン伸びる.

ソフトウェア開発はどうやっているか

アジャイルイテレーションを小さく回せ」リーン・スタートアップ「MVP から始めよ」両方とも,デプロイに時間をかけず フィードバックを短期間で得るための努力があってのことだと思う.大規模にやれば「マージに時間がかかる」「QA チームが求める品質にならない」いろんな問題が出るところを,「CI を回す」「毎週火曜日にリリースすることにする」「組織を変えて,QA 機能をプロジェクト内に持つ」「ベータ提供するしくみ」「一部ユーザーにのみデプロイし,小さく失敗して早く直す」など,技術で解決するのはもちろんのこと 組織 / ワークフロー / ポリシーを見直して頑張ってる.

ネットワーク開発は何ができるか

「調達のリードタイムが予測できない / 長い」というのはしょうがない.でも「在庫を持つコスト」と「持たないことによる生産性の低下」は天秤にかけられるかもしれない.

「やってみないと,実網にどんな影響が出るかわからない」とくにインターネットルーティングは生き物だからしょうがないけど「自分たちのネットワークは複雑だから,やってみないとわかりません」は避けないといけない.シンプルに保つ努力は必要だし,インターネットの端っこにテストベッドを持つ選択肢もあるし,堅く作る前のベータサービスに付き合ってくれるユーザーがいるかもしれない.

「借用に要する時間が予測できない / 長い」レイヤーが低いほど上に乗っているものが多い = 影響範囲が大きいので,メンテナンスには慎重になるべき.でもメンテナンスポリシーが曖昧だと「うーん,分からんけど安全側に倒して…」ってなるし「契約ではできることになってるけど,いままでそうしてなかったから…」みたいなのも癌だと思う.

ちなみに

いま,週のうち数日はフリーのネットワークエンジニアとして働いており,タスクをガッとこなす日と何もしない日が極端に分かれている.それでも自分がボトルネックになるケースは少ない (はず!) ので,待ちが多いと時間を区切って生産性を上げるという手が効く.そういう意味では,トヨタのリーン生産方式の方は勉強しないとなあ,と思ってる.