2012年の振り返り

2012年は全体的にダラダラ過ごしてしまって印象に残ってることが少ないですが、あえてあげるとこの2つでしょうか。

  • 転職&引越しをした
  • 今年も彼女ができなかった

転職のこと

10月アタマに転職してから3ヶ月がたちました。
『CROOZを退職してナビプラスに入社しました』
社会人になってからずっとインフラエンジニアだったのですが、転職後は開発/インフラを半々でやってます。
現状、『稼働は半々、成果はどっちも0.3人前』状態なので、来年はもっとガツガツ行くぞー

技術的なこと

前職で担当した、

  • 海外向けサービスをAWSで構築
  • Fluentdの導入

あたりについてはいろいろ勉強になりました。
ただどちらも安定した運用を作り上げる前に退職することになってしまって、いろいろ悔いの残るプロジェクトにもなってしまいました。

発表したこと

数はあまり多くなかったですが、LT以外のお誘いをいただけるようになったのが個人的に大きかったです。
Fluentd Meetup 2で話してきました

『おぺかじ!』に参加&トークしてきた


LTはこの2つかな?
MySQL Casual Talksに初参加&LTしてきました
Zabbix勉強会5でLTしてきました

FluentdやMySQL Casual関連で『今まであまり話す機会のなかったDeNA、NHN、Perl界隈の人たちと知り合えたこと』が今年の一番の収穫かもしれません。
Zabbix勉強会のネタも兼ねて初めて作ったAndroidアプリ、『ざびたんウィジェット』はαリリースのまま放置になってるので、来年ガバっと修正したいです!


他には『全社会の3分スピーチ』『kuwa_twさんの結婚式LTネタ』などの小ネタもなかなか評判よかったみたいです。

まとめ

来年本気だす

より快適なDCライフを送るために愛三電機で買ってきたもの

秋葉原に行く用事があったので、愛三電機に立ち寄っていろいろ買ってきました。
http://www.aisan.co.jp/

ベルクロ


LANケーブルを束ねるにはやっぱコレですね!
好きな長さに切れて、付け外しが楽なのがいいです。
4.57mで1200円

つけたり外したりできるタイプの大きめ結束バンド


ケーブル類を束ねるの使う他、ちゃんとしたケーブルガイドを使わない場合にLANケーブルや電源ケーブルをラックに固定するのに使ったり、何かと便利です。

292mm、100本:2415円
160mm、100本:1260円


今回は買ってないですが、つけたら外せないタイプは短めのやつにして、ラック間配線など一度つけたら触らないところに使います。

タグ付き結束バンド


ケーブル類のタグ付けに使います。
かさばるとジャマなので、小さめのつけたら外せないタイプにして余ったところはは切っちゃいます。
109mm、100本:1260円

ケージナット取り付け工具


使ったことない人も説明書の図を見ると欲しくなっちゃうのでは。
マイナスドライバーでがんばって指をグッサリやってしまった経験はみんなあると思います。
1つ735円でした。

0.5m、1mの電源ケーブル


サーバ標準の電源ケーブルはたいてい2mですが、ラックの横に詰め込んだり真下に垂らしてたりすると配線状況の把握も難しいし取り回しがしづらいので、『抜いちゃった/抜けちゃった』系の事故につながりやすいです。
短いケーブル、500-600円くらいで買えちゃうので全部変えちゃうのもありですね。
ちょっとした作業用にも便利です。
※最近は短いケーブルを選択できるベンダーも出てきたっぽいですね。

LANケーブル引っ掛け金具


スイッチをラックに固定する時にいっしょにつけて、LANケーブルを引っ掛けるのに使います。
金属じゃないやつが欲しかったけど大きめのが無かったです。
昔買ってイマイチだった記憶があるので、たぶん使わずに大きめ結束バンドでなんとかすることになるかな。


まとめ

というわけで、愛三電機でいろいろ買って来ました!
他にもいろいろおもしろいの揃ってるので、行ったことないインフラエンジニアはぜひ行ってみましょう。


DC用テプラは買ってもらったし、あと必要なのはこのへんかなぁ。

  • 外付けDVD-Rドライブ(MacBook Airなので)
  • Thunderbolt - ギガビットEthernetアダプタ(USBのやつは100Mbpsなのだ・・・)
  • シリアル-USB 変換アダプタ
  • 暖かい作業服

作業マシンがMacBook Airになったからいろいろ追加で買わないと。
(そういえばMBA、LANケーブルがスポッと抜けちゃうから作業の時ちょっと怖いです!)


他にオススメDCグッズあったらぜひ教えて下さい!!!

GrowthForecastでAPI使って複合グラフ作ったり、グラフの色を変えたりしてみた

最近、大ブームなFluentd+GrowthForecastを試し始めました!

で、サクッと『GrowthForecastで複合グラフ作ったりグラフいじったりするの┌┤´д`├┐ダル〜』となりました。


なんとかサボれないかなーとソースを眺めていたら、JSON APIっぽいものがあるのに気づきました。
GrowthForecast:Web.pm

@tagomorisさんが最近コミットしたようです。
add json api to get/list/edit graph and complex, and to create complex


それっぽいURL叩くとJSONが返ってくる!

[mikeda@fluentd01 api]$ curl -s http://localhost:5125/json/list/graph
[{"service_name"=>"test","graph_name"=>"percentile_95","section_name"=>"access","id"=>88},{"service_name"=>"test","graph_name"=>"avg","section_name"=>"access","id"=>87},{"service_name"=>"test","graph_name"=>"5xx_count","section_name"=>"access","id"=>86},...

というわけでザクっとひと通り使ってみました。


/json/list/graph:グラフのリストを取得

[mikeda@fluentd01 api]$ curl -s http://localhost:5125/json/list/graph | ruby -r json -r pp -e 'pp JSON.parse(ARGF.read)'
...
 {"service_name"=>"test",
  "graph_name"=>"3xx_count",
  "section_name"=>"access",
  "id"=>80},
 {"service_name"=>"test",
  "graph_name"=>"2xx_count",
  "section_name"=>"access",
  "id"=>78},
...

パス情報とIDだけが返ってくるようです。

/json/graph/:グラフの詳細情報を取得

[mikeda@fluentd01 api]$ curl -s http://localhost:5125/json/graph/78 | ruby -r json -r pp -e 'pp JSON.parse(ARGF.read)'
{"llimit"=>-1000000000,
 "number"=>0,
 "stype"=>"AREA",
 "mode"=>"gauge",
 "complex"=>false,
 "adjustval"=>"1",
 "created_at"=>"2012/12/26 12:05:35",
 "color"=>"#99cc33",
 "service_name"=>"test",
 "gmode"=>"gauge",
 "ulimit"=>1000000000,
 "section_name"=>"access",
 "id"=>78,
 "graph_name"=>"2xx_count",
 "description"=>"",
 "sort"=>0,
 "unit"=>"",
 "sulimit"=>100000,
 "updated_at"=>"2012/12/26 15:16:07",
 "adjust"=>"*",
 "sllimit"=>-100000,
 "type"=>"AREA"}

かなりいろんな情報があります。また今度調べてみよう


このAPIの出力は、/api//

/とほぼ同じなので、状況によって使い分けるのがよさげですね。

/json/list/complex:複合グラフのリストを取得

[mikeda@fluentd01 api]$ curl -s http://localhost:5125/json/list/complex | ruby -r json -r pp -e 'pp JSON.parse(ARGF.read)'
...
 {"service_name"=>"test",
  "graph_name"=>"response_time",
  "section_name"=>"access",
  "id"=>7},
 {"service_name"=>"test",
  "graph_name"=>"access_status",
  "section_name"=>"access",
  "id"=>44},
...

/json/list/graphと同じですね。

/json/complex/:複合グラフの詳細情報を取得

[mikeda@fluentd01 api]$ curl -s http://localhost:5125/json/complex/44 | ruby -r json -r pp -e 'pp JSON.parse(ARGF.read)'
{"number"=>0,
 "complex"=>true,
 "created_at"=>"2012/12/30 03:30:55",
 "service_name"=>"test",
 "section_name"=>"access",
 "id"=>44,
 "graph_name"=>"access_status",
 "data"=>
  [{"gmode"=>"gauge", "stack"=>false, "type"=>"AREA", "graph_id"=>78},
   {"gmode"=>"gauge", "stack"=>true, "type"=>"AREA", "graph_id"=>80},
   {"gmode"=>"gauge", "stack"=>true, "type"=>"AREA", "graph_id"=>83},
   {"gmode"=>"gauge", "stack"=>true, "type"=>"AREA", "graph_id"=>86}],
 "sumup"=>false,
 "description"=>"アクセス数(レスポンスコード)",
 "sort"=>10,
 "updated_at"=>"2012/12/30 03:30:55"}

こっちはわかりやすいですね。

/json/list/all:全グラフ、複合グラフの詳細情報を取得

[mikeda@fluentd01 api]$ curl -s http://localhost:5125/json/list/all | ruby -r json -r pp -e 'pp JSON.parse(ARGF.read)'
...
 {"number"=>0,
  "llimit"=>-1000000000,
  "mode"=>"gauge",
  "stype"=>"AREA",
  "complex"=>false,
  "adjustval"=>"1",
  "service_name"=>"test",
  "created_at"=>"2012/12/26 12:05:35",
  "gmode"=>"gauge",
  "color"=>"#99cc33",
  "section_name"=>"access",
  "ulimit"=>1000000000,
  "id"=>78,
  "graph_name"=>"2xx_count",
  "description"=>"",
  "sort"=>0,
  "unit"=>"",
  "sulimit"=>100000,
  "updated_at"=>"2012/12/26 15:16:07",
  "adjust"=>"*",
  "type"=>"AREA",
  "sllimit"=>-100000},
...
 {"number"=>0,
  "complex"=>true,
  "created_at"=>"2012/12/19 09:43:37",
  "service_name"=>"test",
  "section_name"=>"dev04",
  "id"=>1,
  "graph_name"=>"access",
  "data"=>
   [{"gmode"=>"gauge", "stack"=>false, "type"=>"AREA", "graph_id"=>"2"},
    {"gmode"=>"gauge", "stack"=>true, "type"=>"AREA", "graph_id"=>"3"},
    {"gmode"=>"gauge", "stack"=>true, "type"=>"AREA", "graph_id"=>"4"},
    {"gmode"=>"gauge", "stack"=>true, "type"=>"AREA", "graph_id"=>"5"}],
  "sumup"=>false,
  "description"=>"アクセス数",
  "sort"=>19,
  "updated_at"=>"2012/12/19 09:43:37"}]

豪快ダンプですね。通常のグラフか複合グラフ化はcomplexフラグで判別するようです。

/json/create/complex:複合グラフを作成

助かった!とばかりに全サービスに特定の複合グラフを作るスクリプトを作りました。
https://gist.github.com/4406576

ちょっと個人的な用途向けすぎなので、もうちょっとベーシックなサンプルを書いてみました。

#!/usr/lib64/fluent/ruby/bin/ruby
# -*- encoding: utf-8 -*-

require 'net/http'
require 'json'
require 'pp'

GF_HOST = 'localhost'
GF_PORT = 5125

# 複合グラフに統合するグラフ
from_graphs= [
  {:path => 'test/access/2xx_count', :gmode => 'gauge', :stack => true, :type => 'AREA'},
  {:path => 'test/access/3xx_count', :gmode => 'gauge', :stack => true, :type => 'AREA'},
  {:path => 'test/access/4xx_count', :gmode => 'gauge', :stack => true, :type => 'AREA'},
  {:path => 'test/access/5xx_count', :gmode => 'gauge', :stack => true, :type => 'AREA'},
]

# 複合グラフ
to_complex = {
  :path         => 'test/access/access_status',
  :description  => 'アクセス数(レスポンスコード)',
  :sort         => 10,
}

def api_get(path)
  json = ''
  Net::HTTP.start(GF_HOST, GF_PORT) do |http|
    res  = http.get(path)
    json = res.body
  end
  JSON.parse(json)
end

def api_post(path, data)
  json = JSON.generate(data)
  Net::HTTP.start(GF_HOST, GF_PORT) do |http|
    res  = http.post(path, json)
    pp res.body
  end
end


# 全グラフデータの取得
#/api/<sercice>/<section>/<graph>で個別に取るほうが簡単そうだからあとで直す。
all_graphs = api_get('/json/list/graph')

# POSTデータの作成
graph_data = []
from_graphs.each do |from_graph|
  service, section, graph = from_graph[:path].split('/')
  graph_id = all_graphs.detect{|g|
    g['service_name'] == service &&
    g['section_name'] == section &&
    g['graph_name']   == graph
  }['id']

  graph_data << {
    :gmode    => from_graph[:gmode],
    :stack    => from_graph[:stack],
    :type     => from_graph[:type],
    :graph_id => graph_id
  }
end

to_service, to_section, to_graph = to_complex[:path].split('/')
post_params = {
  :service_name => to_service,
  :section_name => to_section,
  :graph_name   => to_graph,
  :description  => to_complex[:description],
  :sort         => to_complex[:sort],
  :data         => graph_data
}

# 複合グラフ作成
pp post_params
api_post('/json/create/complex', post_params)

できた!!!

/json/edit/graph/:グラフの設定を変更

これもサンプルを。

同じグラフなのに、サービスごとに色がバラバラだと見づらいですよね。


作成時に指定しないとランダムになるっぽいです。

...
my @colors = List::Util::shuffle(qw/33 66 99 cc/);
$color ||= '#' . join('', splice(@colors,0,3));
...

とりあえず上のグラフの色を、こんな感じに変更してみましょう!

  • 2xx_count:青
  • 3xx_count:緑
  • 4xx_count:黄色
  • 5xx_count:赤
ソースコード
# -*- encoding: utf-8 -*-

require 'net/http'
require 'json'
require 'pp'

GF_HOST = 'localhost'
GF_PORT = 5125

SERVICE_NAME = 'test'
SECTION_NAME = 'access'
GRAPH_COLORS = {
  '2xx_count' => '#1111cc',
  '3xx_count' => '#11cc11',
  '4xx_count' => '#cccc11',
  '5xx_count' => '#cc1111',
}

def api_get(path)
  json = ''
  Net::HTTP.start(GF_HOST, GF_PORT) do |http|
    res  = http.get(path)
    json = res.body
  end
  JSON.parse(json)
end

def api_post(path, data)
  json = JSON.generate(data)
  Net::HTTP.start(GF_HOST, GF_PORT) do |http|
    res  = http.post(path, json)
    pp res.body
  end
end


GRAPH_COLORS.each do |graph_name, color|
  path = [SERVICE_NAME, SECTION_NAME, graph_name].join("/")
  graph_data = api_get("/api/#{path}")

  # meta情報に変なのが入っちゃうのでいらなそうなの削除
  %w[number adjust adjustval meta md5 created_at updated_at data unit mode].each{|key|
    graph_data.delete(key)
  }
  graph_data['color'] = color

  pp graph_data
  api_post("/json/edit/graph/#{graph_data['id']}", graph_data)
end

でけた!!!

/json/edit/complex/:複合グラフの設定を変更

上と似たようなもんなので割愛!!!



まとめ?

だいぶ手が抜けそうで安心しました!
他にもRRDの設定やデータをダンプするAPIなどなどもあるっぽいです。
また気がついたことあったら追記/修正していきます!


追記

もうすぐRuby/Perlのクライアントライブラリが出るっぽいです!

『おぺかじ!』に参加&トークしてきた

ずいぶん時間がたってしまいましたが『おぺかじ!』という勉強会に参加して来ました。
『おぺかじ(Operation Engineers' Casual Talks)』
そしてなんとトークセッションに登壇させてもらいました!
※@studio3104さん、お誘いありがとうございました!


DevOpsだとかクラウド、Chefなどの言葉やらツールやらが流行ってきて、
『インフラエンジニアもコード書けないと!』というテーマが立ち上がったっぽいです。
というわけでこれについて考えていることや、参加してみて思ったことを書きます。

インフラエンジニアがコードを書くこと

僕自身はコードを書く、書かないを特に意識したことはないです。
『必要があれば書く』だけで、そのほうが効率的だと思ったらそうします。
全メンバーがそうである必要はないと思いますが、チームに1人もそういう人がいないのは致命的に非効率的だと思います。
サービスのコードは基本的に見ないです。


使う言語は主にシェルスクリプトPerlでした(Rubyに切り替え中)
ボンヤリ設計を考えて、配列、ハッシュなど複雑なデータ構造が出そうならPerlにします。
Perlが好きだったのはこういう理由です。

  • どのサーバにも入っている
  • バージョンが安定(たいてい5.8.8が入ってる)
  • 簡単なことが簡単にできる(特にテキスト処理)
  • サービスで使っている言語と別(前職はサービスはPHPでした)

なんだかんだ言って上2つが大きいですね。
一番下は『サービス用の言語はいじると怒られる』というネガティブな理由で別の言語をあえて選択していた、ということなのですが、

  • 開発チームとライブラリ、知識の共有ができない
  • rvm/rbenv、perlbrew/cpanmなど、用途ごとに簡単に実行バイナリを切り替えられるようになってきた

という理由から今後は避けようと思っています。

インフラエンジニアとして意識していること

インフラエンジニアとしての僕の仕事は、品質とコストのバランスを取りながらサービス(の基盤システム)を効率的に運用することです。
そこでよく思うのは自分の扱う規模/環境にあった運用を考えること、です。


例えばとある書籍なり勉強会なりでこういうことを聞いたとします!

  • Chefを導入。サーバ構築時間を30分から10分に短縮
  • PHPC++に変換してコンパイルするシステムを導入し、APPサーバの負荷を20%削減
  • DBの負荷を30%下げるキャッシュシステムを開発

素晴らしい!ぜひ導入しよう!と短絡的に考えてもしゃあないです。
これって要するにこういうことだったりするのです。

  • 検証/導入2ヶ月、各メンバー(Ruby知識なし)の教育に2週間かけてChefを導入。サーバ構築時間を30分から10分に短縮
  • PHPC++に変換してコンパイルするシステムを導入し、APPサーバの負荷を20%削減。毎回のデプロイに30分かかる。
  • 年俸1000万の優秀なエンジニアを半年使ってDBの負荷を30%下げるキャッシュシステムを開発


これは自分の会社の規模/環境でペイするのか?を考えないといけない。
(このくらいの条件なら、たぶんサーバ1000台規模じゃないとペイしないと判断する)
『技術の最先端を走る』という言葉はかっこいいです。『Cで書かれたミドルウェアソースコードを読む』『日本語情報がないので英語のドキュメントを読む』とかも。
ただそこで最先端を走る必要のある規模、サービス特性なのかについては必ず考えます。
たいていは規模的に最先端を走る必要のある会社(DeNAサイバーエージェントなど)で初期のバグをひと通り踏んでもらって、日本語情報とかもだいぶ出てきた頃(導入コストが下がって小中規模でもペイするようになったころ)に導入を考えます。


もちろんそういうのを否定してるわけじゃないし、『やりたいこと』は発案者/担当者にもよりますがコスト30-50%減とかで考えたりもします。モチベーションって大事なので。
あんまりなんでも鵜呑みにせずに、自分でウンウンうなって考えるのが大事だと思います、ということです。

コード書きたいけど書けないという意見について

アンケート見たらいろんな理由づけがありましたが、たぶん気のせいです。まずはやっちゃえばいいと思います。
自分がと社会人になってとあるSIerで初めて書いたコードは、『サーバ監視項目のリストをお客さん提出用のフォーマットに変更するExcelマクロ』でした。

最初はたぶん週末とか早朝とか、個人の時間を使うことになるでしょう。
会社は『だれかがプログラムの勉強しながら半月かけて10分/日の作業を自動化すること(ができるかも)』を承認できないからです。
ただそうやって週末潰して書いたプログラムを『お昼休みに作っちゃいました』『昔作ったのがありました』とか言って出してると、しばらくするとそれが言葉通りになります。


自分は『勉強なんて一人でできる』『できることが仕事になる』、と思ってるので環境云々はあんまり関係ないと思ってます。


まとめ、じゃなくてクラウドの話

スピリチュアルなお題なのでまとめられませんw


ただ最近クラウドAWS)のコストについてよく考えているのですが、
実際にある程度の規模で運用してる人たちの話を聞くと、『物理サーバよりちょっと高いくらい』という意見が多いです。
このへんがポイントになりそうです。

リザーブドインスタンスは『3年予約すると3年使わないといけない』というイメージをもっちゃいますが、実際は初期コストが発生するだけでその後は従量課金で『3年予約して半年使えば既にオンデマンドよりお得』とかになったりするらしいです。
US-EASTのm1.largeを半年使う例だと

  • オンデマンドで半年利用:$1,123(0.26*24*30*6)
  • 3年軽度予約で半年利用:$960(425 + 0.124*24*30*6)

詳しくはここの『オンデマンドとの比較による、RI 3年間の節減率』を。


動的な台数変更はCookpadのように

  • 大規模(全体規模に対して支配的)な単一のサービスを運用している
  • 1年の特定の時期だけ大幅にトラフィックが増加する

という運用特性がある場合は大きなコスト削減につながるでしょう。


しかもけっこう大きいと思うのが、『AWSはなんもしなくても勝手に値段が下がる』ことです。
HWの値段が下がれば物理サーバの値段も下がるじゃないかと言われますがなかなかそう簡単でもない。

  • けっこうな割合を占めるDCコストが下がらない
  • HWの性能が上がっても台数を削減できるサーバは一部だけ(スケールアウトが簡単なAPP、DBスレーブくらい)&載せ替え作業が必要


というわけでやっぱり今後もクラウド利用は拡大していって、
そうなるとRailsのようなフレームワークAWSSDKとChefのレシピが組み込まれて、
・エイヤッとデプロイすれば必要なサーバが勝手に作成される
・さらに負荷状況を見て自動でサーバのスペックや台数が調整される
とかって状況はすぐ来るんじゃないかなと思うわけです。
その時、自分の仕事なくなるじゃん!と不安になる人は、いろいろ考えたほうがいいかもです。



※さすがにまとまりが無すぎ!!!また気が向いたら見直すかも(´・ω・`)

VyattaでVPC接続するなら6.5がオススメ!

いつのまにかAWS VPCのコンフィグダウンロード機能にVyattaが加わってました!!!

バージョンが6.5+なので既存ユーザはアップデートが必要になるかもしれません。
ただ6.3と6.5の両方で設定してみた自分としては迷わず
『VyattaでVPC接続するなら6.5がオススメ!』
です。


インターネットで検索して出てくる6.5以前の手順は

  • サンプルの各種設定値を手動置換
  • トンネル周りの設定がかなりムリヤリ
  • BGPなのにLAN/VPCのセグメントをコンフィグに記載
  • 設定投入後に別途コマンドを直接実行

などとても面倒でわかりづらいものでした。
『HOWTO connect vyatta and amazon vpc』


6.5の場合はダウンロードしたコンフィグを貼り付けるだけです。
自分の環境では調整が必要なのはここだけでした。

set vpn ipsec ipsec-interfaces interface 'eth0'
↓
set vpn ipsec ipsec-interfaces interface 'pppoe1'


ダウンロードしたコンフィグを投入するとこうなります。

interfaces {
    vti vti0 {
        address 169.254.252.6/30
        description "VPC tunnel 1"
        mtu 1436
    }
    vti vti1 {
        address 169.254.252.2/30
        description "VPC tunnel 2"
        mtu 1436
    }
}
protocols {
    bgp 65000 {
        neighbor 169.254.252.1 {
            remote-as 10124
            soft-reconfiguration {
                inbound
            }
            timers {
                holdtime 30
                keepalive 30
            }
        }
        neighbor 169.254.252.5 {
            remote-as 10124
            soft-reconfiguration {
                inbound
            }
            timers {
                holdtime 30
                keepalive 30
            }
        }
        network 0.0.0.0/0 {
        }
    }
}

vpn {
    ipsec {
        esp-group AWS {
            compression disable
            lifetime 3600
            mode tunnel
            pfs enable
            proposal 1 {
                encryption aes128
                hash sha1
            }
        }
        ike-group AWS {
            dead-peer-detection {
                action restart
                interval 15
                timeout 30
            }
            lifetime 28800
            proposal 1 {
                dh-group 2
                encryption aes128
                hash sha1
            }
        }
        ipsec-interfaces {
            interface pppoe1
        }
        site-to-site {
            peer 27.0.1.16 {
                authentication {
                    mode pre-shared-secret
                    pre-shared-secret ****************
                }
                description "VPC tunnel 1"
                ike-group AWS
                local-address 219.117.206.163
                vti {
                    bind vti1
                    esp-group AWS
                }
            }
            peer 27.0.1.144 {
                authentication {
                    mode pre-shared-secret
                    pre-shared-secret ****************
                }
                description "VPC tunnel 1"
                ike-group AWS
                local-address 219.117.206.163
                vti {
                    bind vti0
                    esp-group AWS
                }
            }
        }
    }
}


6.5から導入されたVirtual Tunnel Interface(VTI)を使うことで、非常にシンプルでわかりやすいコンフィグになってると思います。
みなさんもぜひアップしてみましょう!!!

Vyattaを6.5にアップしたらMTU制限が効かなくなって切り戻した→解決!?

以前ブログに書いたように、自宅のルータはVyatta(KVM上のVM)を使っています。
先日そのバージョンを6.5にアップしようとしたのですが、うまくいかずに切り戻すことになったのでその時のメモを。


移行前後のバージョンはこんな感じ。
移行前のバージョン

Version:      VC6.3-2011.07.21
Description:  Vyatta Core 6.3 2011.07.21
Copyright:    2006-2011 Vyatta, Inc.
Built by:     autobuild@vyatta.com
Built on:     Thu Jul 21 06:05:47 UTC 2011
Build ID:     1107210607-a17b235

移行後のバージョン

Version:      VC6.5R1
Description:  Vyatta Core 6.5 R1
Copyright:    2006-2012 Vyatta, Inc.
Built by:     autobuild@vyatta.com
Built on:     Fri Nov 16 16:39:16 UTC 2012
Build ID:     1211161646-334fb58


インストールに関しては、ディスクインストールのコマンドがちょっと変わってたくらいで特に困ることはありませんでした。

・6.3
$ install-image 
・6.5
$ install image


コンフィグはけっこう変わっていたので、公式のドキュメントを見ながら書き換えです。

移行前のコンフィグ

interfaces {
    ethernet eth0 {
        address 192.168.1.1/24
    }
    ethernet eth1 {
        pppoe 1 {
            default-route auto
            mtu 1454
            name-server auto
            password ****************
            user-id XXXXX@XXXXX
        }
    }
}
service {
    nat {
        rule 10 {
            outbound-interface pppoe1
            source {
                address 192.168.1.0/24
            }
            type masquerade
        }
        rule 100 {
            destination {
                port 80
            }
            inbound-interface pppoe1
            inside-address {
                address 192.168.1.111
            }
            protocol tcp
            type destination
        }
        rule 110 {
            destination {
                port 22222
            }
            inbound-interface pppoe1
            inside-address {
                address 192.168.1.11
                port 22
            }
            protocol tcp
            type destination
        }
    }
    ssh {
        listen-address 192.168.1.1
        port 22
        protocol-version v2
    }
}
system {
    host-name vyatta01
    time-zone Asia/Tokyo
}


移行後のコンフィグ

interfaces {
    ethernet eth0 {
        address 192.168.1.1/24
    }
    ethernet eth1 {
        pppoe 1 {
            default-route auto
            mtu 1454
            name-server auto
            password ****************
            user-id XXXXX@XXXXX
        }
    }
}
nat {
    destination {
        rule 100 {
            destination {
                port http
            }
            inbound-interface pppoe1
            protocol tcp
            translation {
                address 192.168.1.111
            }
        }
        rule 110 {
            destination {
                port 22222
            }
            inbound-interface pppoe1
            protocol tcp
            translation {
                address 192.168.1.11
                port 22
            }
        }
    }
    source {
        rule 10 {
            outbound-interface pppoe1
            source {
                address 192.168.1.0/24
            }
            translation {
                address masquerade
            }
        }
    }
}
service {
    ssh {
        listen-address 192.168.1.1
        port 22
    }
}
system {
    host-name vyatta02
    time-zone Asia/Tokyo
}

特にNAT周りで、かなり書き方が変わってました。
※重要じゃないデフォルト設定は省略しています。いいかげんFireWallの設定やらないと・・・


そして既存ルータをshutdownして、新規ルータのコンフィグをcommit、
疎通やNATをひと通り確認、
特に問題なし!!!



。。。と思いきや・・・
あれ、なんかTwitterの表示がおかしい・・・
HTMLはGETできてるけど、CSSがとれてない・・・


いくつかのページで、ping疎通は問題ないけどHTTPのGETができない、という状態になってました。

[mikeda@test01 ~]$ ping -n si0.twimg.com
PING cs107.wac.edgecastcdn.net (68.232.44.139) 56(84) bytes of data.
64 bytes from 68.232.44.139: icmp_seq=1 ttl=53 time=4.39 ms
64 bytes from 68.232.44.139: icmp_seq=2 ttl=53 time=4.40 ms
64 bytes from 68.232.44.139: icmp_seq=3 ttl=53 time=3.95 ms
64 bytes from 68.232.44.139: icmp_seq=4 ttl=53 time=4.50 ms
64 bytes from 68.232.44.139: icmp_seq=5 ttl=53 time=4.45 ms
...
[mikeda@test01 ~]$ curl https://si0.twimg.com/a/1355419703/t1/css/t1_core.bundle.css
沈黙

straceやtcpdumpで確認したところ、コネクション張ってリクエスト出すところまではいってるのですが、レスポンスが受信できてません。

[mikeda@test01 tmp]$ strace wget https://si0.twimg.com/a/1355419703/t1/css/t1_core.bundle.css
…
socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET, sin_port=htons(443), sin_addr=inet_addr("68.232.44.139")}, 16) = 0
write(2, "\346\216\245\347\266\232\343\201\227\343\201\276\343\201\227\343\201\237\343\200\202\n", 22接続しました。
) = 22
gettimeofday({1355758206, 249904}, NULL) = 0
gettimeofday({1355758206, 249961}, NULL) = 0
write(3, "\26\3\1\0l\1\0\0h\3\1P\317:~GHB=<Z\307\322\214\311\330\251H\320\21\0054"..., 113) = 113
read(3, 

どうもエンド間でPPPoE用のMTUの調整がうまくいってないようです。
クライアント側で明示的に設定してやるといけのですが、

[root@test01 tmp]# ifconfig eth0 mtu 1454
[root@test01 tmp]# curl https://si0.twimg.com/a/1355419703/t1/css/t1_core.bundle.css
.btn{position:relative;display:inline-block;overflow:visible;padding…..

デフォルトの1500だとレスポンスパケットが帰って来ません。

[root@test01 tmp]# ifconfig eth0 mtu 1500
[root@test01 tmp]# curl https://si0.twimg.com/a/1355419703/t1/css/t1_core.bundle.css
沈黙


しばらくいろいろ試したのですがけっきょく解決方法が見つからず、全クライアント機器でMTUを調整するのは難しいので切り戻しました。
うーん、何がダメなんだろう・・・何か設定が足りないんだろうけど・・・

追記

これが正しい方法なのかはわからないけど、LAN側インタフェースのポリシールートでMTU調整してやると通信できるようになった

set policy route PPPOE-IN rule 10 protocol 'tcp'
set policy route PPPOE-IN rule 10 set tcp-mss '1414'
set policy route PPPOE-IN rule 10 tcp flags 'SYN'

set interfaces ethernet eth0 policy route 'PPPOE-IN'

twilogからリア充度グラフを作る

先日、友人の結婚パーティでLTをすることになり、
リア充化(奥さんと付き合い始めた)前後で、その友人のTwitterのツイートにどのような変化があったか』
について語って来ました。

メインはこの2つのグラフでした。


Tweet数の推移

リア充度の推移

※ちょっと茶化し過ぎたかと反省したので名前はふせます(´・ω・`)


今回はこのグラフ(主に下側)をどうやって作ったかについて、簡単に説明します。

リア充度について

元ネタは@namikawaさんのブログエントリ、
『俺流、リア充・ネト充の見分け方』
です。
詳細は上記ブログを見てもらうとして、ポイントはここで提唱されている、
リア充ほど休日のtweet率が低くなる』(リア充は休日はリア充活動が忙しくてTwitterなんてやってられん)
という理論です。
これもとに、リア充度=平日ツイートの割合』と定義すると

ぐらいになることがわかりました。

これをベースに、月ごとにリア充度を算出したのが最初に出したグラフです。

データの取得

TwitterAPIは現状の仕様では3200件までしか過去ツイートをさかのぼれません。
なのでデータはtwilogのCSVダウンロード機能で取得することにしました。

※本人しかダウンロードできないです!

データの解析

CSV形式なので簡単に解析ができます。
試しにツイート数やリプライ件数ランキングなど。

$ wc -l mikeda121216.csv 
   15055 mikeda121216.csv
$ perl -nle 'print for /@\w+/g' mikeda121216.csv | sort | uniq -c | sort -rn | head
 740 @xcir
 329 @kuwa_tw
 285 @n0ts
 223 @oranie
 203 @ar1
 178 @ishikawa84g
 124 @mikeda
 124 @iara
 115 @tnmt
 108 @sechiro

月ごとのツイート数、リア充度はスクリプトで集計しました。

$ ruby rj.rb mikeda121216.csv 
2007/12	1	1	100.0
2009/12	12	7	58.333333333333336
2010/1	11	7	63.63636363636363
2010/2	22	16	72.72727272727273
2010/3	94	39	41.48936170212766
2010/4	79	44	55.69620253164557
2010/5	339	223	65.78171091445428
2010/6	415	263	63.373493975903614
2010/7	361	211	58.448753462603875
2010/8	556	342	61.510791366906474
2010/9	492	353	71.7479674796748
2010/10	435	153	35.172413793103445
2010/11	577	309	53.552859618717505
2010/12	469	281	59.914712153518124
2011/1	329	155	47.11246200607903
2011/2	283	147	51.9434628975265
2011/3	342	190	55.55555555555556
2011/4	477	204	42.76729559748428
2011/5	644	407	63.19875776397515
2011/6	381	203	53.28083989501312
2011/7	610	301	49.34426229508197
2011/8	769	480	62.418725617685304
2011/9	479	302	63.04801670146138
2011/10	395	233	58.9873417721519
2011/11	685	447	65.25547445255475
2011/12	592	357	60.304054054054056
2012/1	556	365	65.64748201438849
2012/2	528	335	63.446969696969695
2012/3	623	346	55.53772070626003
2012/4	444	213	47.972972972972975
2012/5	689	407	59.0711175616836
2012/6	406	234	57.635467980295566
2012/7	372	190	51.075268817204304
2012/8	340	250	73.52941176470588
2012/9	312	161	51.6025641025641
2012/10	373	229	61.394101876675606
2012/11	367	187	50.95367847411444
2012/12	152	79	51.973684210526315

左から

  • 総ツイート数
  • 平日ツイート数
  • リア充度(平日ツイート数/総ツイート数)

です。
スクリプトソースコードはこんな感じです。

#!/usr/bin/ruby

require 'csv'
require 'pp'

counts = {}

CSV.parse(ARGF) do |rows|
  /^(..)(..)(..)/ =~ rows[1]
  year, month, day = "20#{$1}".to_i, $2.to_i, $3.to_i
  wday = Date.new(year, month, day).wday

  counts[year] ||= {}
  counts[year][month] ||= {:all => 0, :weekday => 0}

  counts[year][month][:all] += 1
  counts[year][month][:weekday] += 1 unless wday == 0 || wday == 6
end

counts.sort.each do |year, monthly_counts|
  monthly_counts.sort.each do |month, count|
    weekday_rate = 100 * count[:weekday].to_f / count[:all]
    puts ["#{year}/#{month}", count[:all], count[:weekday], weekday_rate].join("\t")
  end
end

祭日、月ごとの平日/休日比率の違いを考慮していないのがちょっとダメですね。


ほんとは
・感情解析
・顔文字、「おっぱい」など特定フレーズの使用頻度
なども分析したかったのですが、それは次のだれかの結婚式にまわします(・∀・)ニヤニヤ