近状とか

ご無沙汰しています。
やっと新しい職場に入ってから3ヶ月がたって、試用期間も終わったところですが、社内のみんなそんなこと信じてくれないか忘れるくらいなじんでます。

普段あまり話さない人から、最近ブログ更新ないし何してるの?って言われたので、いい機会だから近状とかざっくり。

買収直後の辞める面談の時にVGの新経営陣から話だけはされましたが、職歴が汚れるのでVGには転籍せずにKauli所属のまま8月いっぱい有給を消化して辞めました。
引継ぎもあるし年内くらいは居た方がいいかなと思っていたんですが、新経営陣が早く追い出したがってたのでさくっとほっぽりなげて辞めました。
年内でKauliがなくなるから失業したくなければVGに移れ拾ってやる、みたいな物言いだったけど、次の行き先決まってたし。

9月からうってかわって、某ITソリューションプロバイダー()のアカウントSEに転生しました。
生まれてはじめてスーツきて仕事してます。
仕事が集まってきて大変だけど、職場の雰囲気もいいし、無理難題だらけで課題も尽きないので毎日楽しく(?)仕事してます。
むしろVGの騒いでるだけの連中みたいに仕事に派手さを求めない自分にとっては、タダ酒とかゲームできるとかどうてもよくて、落ち着いてて馬鹿が視界に入らない環境のほうが重要ですね。
一度挫折を経験するまでは、とにかく今の職場でがんばろうと思います。

そんなわけで、なにかお困り事ありましたら、こんな最低な自分が直接ご提案にいくことができるようになりました。
ちょっととがったご提案を欲してるときは、自分に声かけてください。
野良不良SEがなんか考えてもっていきます。(ひやかしはやめてね!)

というわけで復帰ついでにSE●LとGI●チームに喧嘩を売るような内容になっちゃうけどVyOSのadvent calendarネタ書かせてもらおうと思います。

Kauliを退職します

本糞ブログの更新を楽しみにしているありがたい方々がちらほらいると方々で聞いているので、お知らせします。

自社であるKauliがVOYAGE GROUPに子会社化され、辞めることにしました。
というか従業員に発表された日に、KSGと思って辞めると決めていました。

元々宗教上の理由で嫌いなVOYAGE GROUPは、買収直後からいろいろひどい話が山ほどありますが・・・、酒の席で機会があった人にはうっかり話しますw
まあ蓋が開いたら予想通りというか想像以上というか・・・。

さて、次の職場はまったくもって別の業種です。
ですので、広告系のインフラネタで書くことはもうありません。
仕事の内容的にも表に出せる内容がかなり限られると思いますが、なにか書けることがあれば細々と続けていこうと思います。
(仕事で超常現象が発生しないかぎりネタがないとも)

8月いっぱいは休みなので、酒飲みたいとか、技術的な話をして欲しいとかあったら@SatchanPまで気軽に声かけてください。

I350のRSS Queueが溢れた

明けましておめでとうございます。
今年も本糞ブログを細々と続けていくのでよろしくお願いします。
去年はイーサネットフレームのバイト数もわからない様々な人たちに自社のインフラにクラウド導入を促されてキレそうになっていましたが、今年は遠慮なくキレようと思います。

コミケにフル参戦していたため年を越してしまいましたが、年末に起きたちょっとしたRSSのQueueに関する騒動をまとめます。

新しく構築した環境の特定のサーバで以前に書いたI350の受信バッファが溢れた時と同様にifconfigのoverrunsのカウンターの急上昇を確認しました。
なんだまたリングバッファ溢れかとその時は思いましたが、前回とは異なりパケットドロップ、破棄のカウンター上昇はありませんでした。

前例からoverrunsが出ている時点でパケットが捨てられているという先入観があったため、最初は意味がわかりませんでしたがぼちぼち調査を開始しました。

例によってethtool -S | grep dropで調べたところ、以下のカウンターがゴリゴリあがっていました。

     rx_queue_0_drops: 0
     rx_queue_1_drops: 0
     rx_queue_2_drops: 1098532642
     rx_queue_3_drops: 5009716490

カーネルソースを読んだところ、このキューはRSSのキューです。
このサーバはRSSでIRQを4個掴んでいるためこのようなキューの合計数になっています。

今回はここからが本題です。

この問題は自社では新しい環境のリアルサーバとLVSとで初めて確認されました。
原因は特定のホストとの同一の条件の通信が大量発生することによるRSSのキューイングアルゴリズムの偏りです。

RSSはデフォルトではIPとPortをHask keyにして各キューに分散しているため、特定のホストと同じ条件の通信が集中するとRSSのキューの分散に偏りがでます。
偏った結果、キューが溢れ順番にリキューされ、上記のようにdropのカウンターが階段状になります。

対策としてRSSのキュー自体を綺麗に分散する方法を考えましたが、現状Linuxで実用的な方法はないようです。
Symmetrical RSSというロードバランス方法がひっそり世間に出つつあるようなので期待しています。

自社の対策としてはキューであるリングバッファの設定値をデフォルトの256から4096にすることも考えましたが、現状の通信状況を考慮してあえてデフォルトの256のままで運用することにしました。
根拠は以下の図の通りです。

rss_queueキューが偏っている状態でキューサイズであるリングバッファの設定を増やしても遅延するだけと考えました。
現状では効率は悪いけどリキューさせたほうがまだ遅延しないという判断です。

各界で言われているようにバッファは確かに遅延を招きます、しかしバッファが溢れドロップした場合はさらに膨大な遅延を招きます。
キューやバッファマネージメントは土管が太くなる一方の世の中で、我々ネットワークに携わる者に求められる能力になると思います。

ウェブ広告のインフラについて(第3回) vyattaのチューニング

梅雨入り前の微妙な天気が続きますね。

今回は前回の基本構成で紹介した、vyattaに実際どういったチューニングを施しているのかと愚痴を書いていきます。

自社でのサービス系のトラフィックのほとんどはLVSから入りvyattaから出て行きます。
vyattaはLVSを通った戻りのトラフィックだけでなく、多数あるDSPへのビッドリクエストも処理しています。
また、グローバルIP節約のためにIPマスカレードをしています。

実は自社のネットワークではここがコアスイッチに次いで重いのですが、CPUが i7 870 メモリ16G NIC 82574L 2口のサーバでピーク時に上り 500Mbps 200K/pps 程度を処理しています。
ただbufferbloatやマイクロバーストの影響と思われる送信キューの再キューが発生してしまっています。これは今度の課題です。

現状使っているハードウェアがかなりショボイので、箱を変えるだけで10GクラスのIPマスカレードもvyattaでいけると確信しています。
そもそもIntelに言わせると、82574LなんてNICじゃなくてPHYだ!だそうで…。

では具体的なチューニングを紹介していきます。

リングバッファを増やす

82574Lに限らずIntelのNICはTx/Rx共に最大値が4096ですが、デフォルトだと256固定になっています。
これにより、受信の場合だとTCPスタックのキューに入る前にリングバッファが溢れてパケットが破棄されてしまいます。

ただバッファも多ければいいというわけではなく、bufferbloatやバッファが増えることによりレイテンシーが低下します。
パフォーマンスを求めるなら、NAPIのチューニングも必要になります。
難しいことはいつもの次回以降に。

デフォルトの状態です。

ethtool -g eth0
Ring parameters for eth0:
Pre-set maximums:
RX:		4096
RX Mini:	0
RX Jumbo:	0
TX:		4096
Current hardware settings:
RX:		256
RX Mini:	0
RX Jumbo:	0
TX:		256

増やしてみます。
この際リンクダウンが発生するので注意が必要です。

ethtool -G eth0 rx 4096 tx 4096

なお現状に適正なリングバッファの値を調べることはかなり面倒です。
闇雲に増やしてもマイクロバーストの原因となってしまいます。
リングバッファが常に溢れていないか、またはフルになった形跡を確認する必要があります。
これについては確証は得ていないのですが、それっぽい方法は調べてあるので次回以降です。

RFS/RPS

82574LはとてもいいNICなのですが、NICのインタラプトが以下のようになっています。

 50:   81480180          0          0          0   PCI-MSI-edge      eth0-rx-0
 51:    7064255          0          0          0   PCI-MSI-edge      eth0-tx-0
 52:       4786          0          0          0   PCI-MSI-edge      eth0
 53:          2   77843270          0          0   PCI-MSI-edge      eth1-rx-0
 54:          1    1888030          0          0   PCI-MSI-edge      eth1-tx-0
 55:          8          0          0          0   PCI-MSI-edge      eth1

一応マルチキューになってはいますが、Rx/Txが単体で分散していないため、どうして特定のコアに負荷が集中します。
これを分散する為にRFS/RPSを利用しています。

なお評価中のi350ではRx/Txをモジュールに与える値で変更できます。
以下は一例です。

  65:          7          0          0          0          0          0  IR-PCI-MSI-edge      eth2
  66:   47472804          0          0          0         21         27  IR-PCI-MSI-edge      eth2-rx-0
  67:   49140306          0          0          0          0          0  IR-PCI-MSI-edge      eth2-rx-1
  68:         31          0         29   68618984          0          0  IR-PCI-MSI-edge      eth2-rx-2
  69:    9835040          0          0          0          0          0  IR-PCI-MSI-edge      eth2-tx-0
  70:         26          0          0          0    9837578          0  IR-PCI-MSI-edge      eth2-tx-1
  71:         24          0          0   10782440          0          0  IR-PCI-MSI-edge      eth2-tx-2
  72:   17034513          0          0          0          0          0  IR-PCI-MSI-edge      ahci
  73:          1          0          0          0          0          0  IR-PCI-MSI-edge      isci-msix
  74:          0          0          0          0          0          0  IR-PCI-MSI-edge      isci-msix
  75:          7          0          0          0          0          0  IR-PCI-MSI-edge      eth3
  76:         25          0          0         11         35   27880083  IR-PCI-MSI-edge      eth3-rx-0
  77:    9845213          0          0          0          0          0  IR-PCI-MSI-edge      eth3-rx-1
  78:         22    9845071          0          0          0          0  IR-PCI-MSI-edge      eth3-rx-2
  79:    9825399          0          0          0          0          0  IR-PCI-MSI-edge      eth3-tx-0
  80:         23          0    9825377          0          0          0  IR-PCI-MSI-edge      eth3-tx-1
  81:    9825424          0          0          0          0          0  IR-PCI-MSI-edge      eth3-tx-2
  82:          3          0          0          0          0          0  IR-PCI-MSI-edge      eth0
  83: 1383727826          0          0          0          0          0  IR-PCI-MSI-edge      eth0-rx-0
  84:         55          0         71        155 1302104857          0  IR-PCI-MSI-edge      eth0-rx-1
  85: 1324395997          0          0          0          0          0  IR-PCI-MSI-edge      eth0-rx-2
  86: 1830013044        164          0          0          0          0  IR-PCI-MSI-edge      eth0-tx-0
  87:        262         75          0          0          0 1928280549  IR-PCI-MSI-edge      eth0-tx-1
  88: 1883840698          0          0          0          0          0  IR-PCI-MSI-edge      eth0-tx-2
  89:          3          0          0          0          0          0  IR-PCI-MSI-edge      eth1
  90:         44          0   62434654          0          0          0  IR-PCI-MSI-edge      eth1-rx-0
  91:    9853611          0          0          0          0          0  IR-PCI-MSI-edge      eth1-rx-1
  92:    9840908          0          0          0          0          0  IR-PCI-MSI-edge      eth1-rx-2
  93:         21    9825401          0          0          0          0  IR-PCI-MSI-edge      eth1-tx-0
  94:    9825431          0          0          0          0          0  IR-PCI-MSI-edge      eth1-tx-1
  95:    9825440          0          0          0          0          0  IR-PCI-MSI-edge      eth1-tx-2

上記の場合パラメータはこんな感じです。CPUはXeon E5-1650v2なので6コアを意識しています。

options igb IntMode=2,2,2,2 RSS=3,3,3,3 QueuePairs=0,0,0,0

さて脱線しましたが、ついでにeth0とeth1でflow entryを使い切るように設定します。
国内で有名なコピペ設定でもいいと思いますが、ここは海外含めて事例を調べてこう設定してみました。
この部分に関してはまだカーネルの実装までは追っていませんので確証がもてません。

echo "f" > /sys/class/net/eth0/queues/rx-0/rps_cpus
echo 16384 > /sys/class/net/eth0/queues/rx-0/rps_flow_cnt
echo "f" > /sys/class/net/eth1/queues/rx-0/rps_cpus
echo 16384 > /sys/class/net/eth1/queues/rx-0/rps_flow_cnt
echo 32768 > /proc/sys/net/core/rps_sock_flow_entries

カーネルをアップグレード

公式のコミュニティ版だとカーネルが古いためVyatta4People.Org版(?)にアップグレードして使っています。
設定はそのままでコマンド一発でアップグレードすることができます

vyatta@rt4:~$ add system image http://ftp.het.net/iso/vyatta/vc6.7/images/vyatta-livecd-redding-20130712-amd64.iso

 CoDel等、最近になって野心的に実装されたおいしい機能を試すためです。

conntrack tableを正確に設定する

ここがIPマスカレードの一番の肝です。
まとめエントリーはこちらになります。

メモリ16Gで以下の設定で運用しています。

 expect-table-size 196608
 hash-size 23576
 table-size 196608

実メモリから逆算することにより限界値が明確になります。
expect-table-sizeは自社の使い方だとほぼ使われることがありませんが、メモリも余裕があるので保険で同じ値をいれてあります。

conntrackタイムアウトを短くする

conntrack tableは実メモリの制限を受けるため、不要なものはさっさとconntrack tableから削除してしまします。

 timeout {
     icmp 3
     other 600
     tcp {
         close 10
         close-wait 1
         established 10
         fin-wait 10
         last-ack 30
         syn-recv 60
         syn-sent 5
         time-wait 3
     }
     udp {
         other 30
         stream 10
     }
 }

vyattaに限らずconntrack tableは特定の環境でかなりの頻度で溢れます。
少ないデフォルト値を増やして対処できればいいですが、消えないのにタイムアウトが長めになっている場合もあります。
どう対処したかは結構前にかいたこの辺のテキストにまとまっています。

愚痴

分裂したようなんですがどうなんでしょうか…。

次回はたぶんLVSのチューニングです。

 

ウェブ広告のインフラについて(第2回) 基本構成

まだ二回なのであまり深く突っ込んだ話はしません。

今回は自社DCのNW構成と、その際の注意していることなどを書いていこうと思います。

下の図をご覧ください。

実際はもう少し複雑ですが、LVS-DR構成を利用したシンプルな作りになっています。
入社直後チューニングノウハウがない時期にLVS-NATで運用していましたが、いきなり負荷でLVSがつぶされた経緯があり、現在と比べてかなり小さい規模でしたが思い切ってLVS-DRに切り替えました。
今でもその流れを継いでいます。

このように外から入ってくるギガ線のトラフィックをすべてLVSで受けて、内部のLVSでnginxから各APサーバに分散し、DRでデフォルトゲートウェイのVyattaから投げ返しています。

LVS-DRを表のLBに使ってるとかマジキチと自分でも思うんですが、使い始めると案外なんとかなってしまうもので、高い箱物をアテにしていないので、予算とか読めない事業予測にとらわれないスケーラブル()なインフラが結果的にできてしまいました。
CPUはいい仕事してくれます。

FWどうしてんだよ!とかは次回以降で!

しかしLVS-DR構成もデメリットとまでは言いませんが、運用に工夫が必要です。

スイッチの配置と挙動を考慮する

何も考えずに配線すると簡単にUnicastがFloodingします。
こちらのエントリーを参考にしてください。
2ラックでサーバを両ラックに分割して配置など特に要注意です。
結局スイッチまたぎの問題は解決できず、pingを定期的に実行するサーバを運用しています。

また以下の図のようにスイッチ間のトラフィックも偏りがでないように、実際はL2コアスイッチ的なものを一台はさんで配置しています。

ブロードキャストドメインの制限がある

LVS-DRはブロードキャストドメインの制限のために、スケールに限界があります。
現在は1ブロードキャストドメインにおとなしく納まる台数ですが、今後はもう1セットLVSを用意してDNSで分散するか、LVS-DRを多段にするか、そもそもLVS-DRを捨てるか等考えている最中です。
L2 over L3。。。おっと誰かきたようだ。

リアルサーバでVIPを受けるためにループバックインターフェイスを使っている

リアルサーバでVIPの通信でするためにiptablesを使っている場合が多いと思いますが、数多くある配信サーバでconntrack tableの管理をしたくないため、ループバックインターフェイスを使っています。
うっかりarp_ignore等重要な設定を忘れたりしないために、puppetで管理をしています。
manifestはgithubで公開しているので参考にしてください。

目次の前に書いてある内容程度ですが今日はこの辺で。
細々とやるのが長く続ける秘訣ですね。

次回はLVSとVyattaのチューニングについて書こうと思います。