(」・ω・)」うー!(/・ω・)/にゃー!

株式会社ミクシィを退職し、株式会社クロコスに入社しました。

| Comments

新年度ですね。4/2ですね。エイプリルフール終わりましたね。 もう既にご存じの方も多いかと思いますが、3/31をもって前職のミクシィを退職し、4/1よりクロコスにJoinすることになりました。

そして今日いきなりセキュリティカード忘れて遅刻しましたごめんなさい。

クロコスへの入社について

株式会社クロコスは、ソーシャルメディア上でのオンラインマーケティングの企画やツール提供、活用支援などを主要事業とする会社です。 日本初のFacebook認定マーケティングデベロッパーでもあり、マーケティング支援ツールの他にも色々なFacebookアプリなども展開しています。

おそらく、自分とクロコスの前身であるnequalの関係について知っている人からすると、あんまり驚きもない話かもしれません。 色々と自分の中でも考えるところは多かったのですが、最終的に決断したのは、楽しい方を選ぼう・人生の最後で後悔しないようにしよう、という思いからです。

元々、自分は大規模なインフラ/トラフィックに関わりたい、運用者としてのスキルをもっと磨きたいという欲求が強く、どうしてもクロコスの事業からは縁遠いものになりがちだったので、楽しそうとは思いつつもJoinすることは無いだろうと考えていました。

ただ、クロコスの買収の話もあり、メンバーと話をしているうちに「あー、このメンバーがみんな揃って仕事をするタイミングって、今しかないんだろうな。」という感覚を感じたことで、自分の人生でスキルやキャリアというもの以上にもっと大事にしたいものが今あるかもしれないな、と感じるようになりました。

それを感じたことで、こんなにも縁のあるメンバーと今働いておかないと、きっと僕は後で後悔する気がしたのです。 自分の目指すキャリアプランやスキルセットとは若干離れることにはなりますが、後悔のない生き方のために計画的な生き方よりも「楽しい方」をチョイスしてみようと思って、クロコスにJoinする決断をしました。

ミクシィについて

株式会社ミクシィ。。。については、自分が紹介するまでもないかと思います。オレンジ色のSNSです。

前前職では要件定義〜開発、運用っぽいことまでひと通り経験させてもらっていたのですが、その中で、コンピュータをもっとつかいきりたい!もっと巨大なトラフィックと戦いたい!という思いが高まり、どうせやるなら規模のあるところ!と思って運用エンジニアとしてミクシィの中へ飛び込みました。

当時の自分は本格的な運用経験など無いに等しかったので、そんな自分を受け入れてくれたミクシィ社には感謝しています。 入ってからは本当に勉強の連続でしたが、非常にレベルの高いチームメンバーに囲まれ、自分も様々な面で大きく成長させていただきました。

自分のいたアプリ運用グループは実にバラエティ豊かなチームで、少しずつ専門性/指向性が違うメンバーが揃っていてとてもバランスよいチームになっていたと思います。 スキル面・思考面いずれをとっても尊敬できるエンジニアの方が何人もいて、あのチームに在籍できたことは、自分にとって、とても貴重な経験でした。

自分の退職に際しても、大きな体制変革の最中にも関わらず自分の希望を聞いて送り出してくださり、感謝の念に堪えません。 本当にありがとうございました。

というわけで

恥ずかしながら、一度は去ったはずのPHP界隈へ戻ってきてしまいました(笑) 僕PHPerじゃありません><とか言ってたはずなんですけどねぇ。。。

とはいえ、ミクシィで様々な経験をさせていただいたことで、エンジニアとしてさらにボキャブラリを増やすことができたので、今までよりも幅広く活動できるように頑張ろうと思います。

Qpstudy 2012.05 に参加してきた

| Comments

新入社員でもなんでもないけど参加してきた。 個人的には、計算機科学は勉強したことなかったので、全然知らない考え方も多く、いい取っ掛かりを得られた、大変参考になる勉強会だった。

ハードウェアについて

コンピュータの5大要素

  • 入力・記憶・演算・制御・出力
    • 寸劇www
  • ノイマン型コンピュータ

    • 昔からこの基本構造は変わっていない。
  • 仕事の中でのハードウェア

  • ボトルネック調査

    • CPU
    • memory
    • Disk IO(補助記憶)
  • 効率の良いアーキテクチャ

    • ハードウェアをよく知る
  • 効率がいい、とは?

    • アーキテクチャから見て効率がいい
    • コンピュータのきもちを知ること。
      • どのように動いているのか?

CPU の話

  • Control Unit + 演算装置 = CPU

  • 5大要素とあわせて

    • Processer
    • Program
    • Data
  • CPU

    • Address Busで指定した場所に、Data Busカラデータが流れる。
  • CPUの4つの原則

    • 時間軸に合わせて4つの仕事をする
      • Fetch
      • Decode
      • Execute
      • Write back
  • Fetch

    • 主記憶からのデータの取り出し
  • Decode

    • 回路で実行できる内容に変換
  • Execute

    • その内容を下に、回路上で実行
  • Write back (or store)

    • 結果を戻す
    • 原則に含まれないこともある。
  • これらがCPU Clockにあわせて動作している。

  • CPU Clock

    • 水晶(クリスタル)に電圧をかけると、一定周期のOn/Offの波形が出てくる。
    • このクロックに合わせて命令を実行する。
    • 市場に出ているCPUの中では、最速は5.2GHz
  • 高速化の方法

    • Pipeline
      • GPUのような計算し続けるものには効果が高い。
      • プログラムの動きによっては、パイプラインの途中で無駄が発生してしまって、効果が少ない。
    • Super Scalar
      • いっぺんに計算してしまえ!というもの
    • Out of Order
      • 遅い処理(memoryからの読み込み)などは他の命令と並行してやってしまってもいいよね、というやり方。
  • CISC vs RISC

    • CISC - いろんな命令セットを回路で実装する考え方
      • でも、実は利用頻度の高い命令は限られていた。
    • RISC - 利用頻度の高い命令セットのみで、プログラム側でそれを組み合わせて使う考え方。
    • 今は、CPUの中で命令セットはCISCで飛ばして、内部は実はRISCの組み合わせをしている、という実装がほとんど。
  • Peak CPU Clocks

    • クロックを上げていくのは、とてもコストがかかるようになってきたので、コア数増やす方向に進んでる。
  • で、ぶっちゃけどう動いてるの?

  • Z80 CPU

    • 今日はコレで考える。
  • bit width?

    • レジスタやバスの幅で決まることが殆ど
  • マシン語

    • を学びたいが。。。つらいのでw
  • アセンブラ

  • register vs memory

    • CPUで実行する際には、memoryから一旦registerに持ってきて実行している。
    • コレをどう使うか?がアセンブラの醍醐味
    • Z80のレジスタは8bit。場合によって2つ合わせて16bitの命令セットとして扱うこともある。
  • Endian

    • big endian - 順番通りにレジスタに入る。ABCD -> ABCD
    • little endian - 順番がひっくり返る。 ABCD -> CDAB
  • Accumulator

    • 何かを計算するときはここを使うレジスタ
  • Status (flag) Register

    • 計算した結果や特定の命令セットの結果が反映されるflagがあるレジスタ
  • どんな命令セットがあるか。

  • 5 functions
    • Data transfer
    • Data Processing
      • Z80は足し算とshift rotateぐらいしかない
    • Test and Jump
    • Input / Output
    • Control
      • 制御コード
  • 1単位時間あたりに実行されているのは、これらの命令のどれか。

  • 引き算はどうするか

    • 2の補数をとって負の数との足し算をしていた。
  • ニーモニックとオペランド

  • まとめ

    • アセンブラ
    • 英語大事

I/O入門

  • I/Oとは

    • コンピュータで必ずしも必要ではないパート
    • なしでも計算はできる
      • とはいえ、ないと使えたものではない。
  • I/Oの基本

    • IA-32の入出力
      • I/Oポート
      • 割り込み
      • DMA
      • メモリマップドI/O
  • IOポート

    • 最も単純な入出力
    • このportに対して何かデータを送れば、(なんだかはわからないけど)その先のデバイスに送られる。
    • 逆に読み出しをするときはポートを読む
    • 基本的には8bitでのアクセス単位
    • キーボードなど。
  • 割り込み

    • 外から何らかの理由で入ってくる、作業を中断させる通知
    • キーボードを押した瞬間などに反応するときは、割り込みで発生させている。
  • I/Oがどう使われるのか?

    • 入力装置が付いているのはわかった。どう使うか?
    • 話が変態的すぎて。。。
  • その他のI/O

  • メモリマップドI/O
    • CPUの物理メモリ空間に、デバイスのメモリ空間をマッピング
      • CPUから直接デバイスのメモリ空間にデータを送れる。
  • DMA
    • プロセッサがDMAコントローラに対して要求し、データ転送をそちらに任せることができる。
    • データ転送の時間中にCPUが処理時間を食われることがない。
  • IRQ

    • 割り込みを送るための線
    • しかし物理線は15本しかない。
      • 同じ線で複数のデバイスが割り込みを入れたりする。
      • CPU側では、どのデバイスが割り込みしてきたかわからない。。。
      • デバイスドライバ側で、ISRレジスタというところに「どのデバイスが割り込んだか」の情報を記録して、それで判断する。
  • Busとは

    • 内部バス
    • 周辺回路
    • 拡張バス
  • PCIバス

    • 32bit,周波数33MHz, 帯域幅133MHz
    • パラレル転送
    • plag and play対応だったが、活線挿抜できたわけではなかった。
  • PCI-X
    • 周波数33MHz, 帯域幅1.06GHzに拡張
    • 上位互換、だがよく物理干渉して刺せなかったりした。
  • PCI Express
    • シリアル転送、複数レーンを束ねて転送可能に
    • 1レーンあたり 250MB/s (1.25GHzで、1クロックあたり2bit転送してる)
    • 4レーン 1GB/s , 16レーンで4GB/s
      • 仕様上は最大32レーン
    • 活線挿抜に対応
  • PCI Express 2.0

    • クロックを2倍(1.25GHz -> 2.5GHz)にして、レーンごとの転送速度も500MB/sに。
    • MSIサポートが必須に。
  • MSI

    • そもそもIRQ使わなくていいじゃん、と気づいた。
    • IRQを使わないで、メモリ書き込みによって割り込みを通知する。
      • ニセのメモリ書き込みをして、CPUに割り込みと認識させる。
      • CPUがいちいちISRを見なくていい。
    • 仮想化環境では、world changeの問題が発生するため、IRQでの割り込みはすごく効率が悪い。
      • コレが解消できるので、仮想環境としてはすごくいい。
  • CPUのインターコネクト

    • NUMA(非対称)とUMA(対象)
      • 今はほぼUMA
    • NUMAだと、メモリはどちらかのCPUに依存してる
      • 下手にマルチプロセッサで使うと、1プロセッサより遅い。。。ということが発生しうる。
  • QPIとHyperTransport

    • Quick Path Interconnect
    • 下手にチューニングなしだと遅くなるかも。。という点は気をつけておく。
  • まとめ

    • I/Oは必須ではないが、ないと使えないもの。
  • IOを勉強するには

    • ArduinoとかPICでやると、勉強しやすい。
    • PIC USBマイコンボードなど。
    • もっとガチな人にはBeagleBoard
      • Linux Boxを手作りで作ろう。。。なんてときに。

インターフェース入門

  • インターフェースとは

    • 2つのものの間にたって、情報をやりとりするもの。
  • ハードウェアインターフェース

    • 音響カプラ
    • X.21企画
    • RS-232C
      • 俗に言う「シリアル端子」
      • 25 pin
      • 9pinもあるが、同期通信できない。
    • DB-60(HD60)
      • Cisco独自規格
  • 端子数が上がった
    • 通信速度は上がった
    • でも、データの通信並列数は1
    • シリアル通信
  • 端子数が多いわけ

    • 直接データを送受信しない端子
    • 同じデータを流す端子
    • 使ってないものも。
      • なぜ多い?信頼性の工場のため。
    • ある程度やると、性能頭打ち。
  • 動作周波数

    • 33MHz
    • 1cycle = 0.03 nano sec
  • SDR
    • Single Data Rate
    • 1cycleあたり1bitのデータ転送
    • 1周期のup /down を1bitと見る
  • DDR

    • Double Data Rate
    • 1cycleの周期up downを別々のサイクルと見て、1cycle 2bitのデータを送る。
  • なぜ性能が頭打ちになるか?

    • 費用対効果
    • 主に、半導体性能がネックだった。
  • パラレル通信

    • データを同時送受信する。
    • IEEE 1284
      • RS-232Cと端子は同じ
      • 同時送受信 8bit
    • SCSI
      • 50pin
      • 同時送受信 8bit
    • ATA
      • 40pin
      • 16bit
    • Ultra SCSI 320
      • 2.56Gbps
  • しかし、世界はパラレルからシリアルへ。

    • なぜ。。?
    • パラレルじゃダメだから戻ってきた。
    • 半導体性能のUP
      • 動作性能UP
      • スキュー発生率UP
  • スキューとは

    • クロック同期型の回路において、異なるタイミングでデータ転送が行われてしまうこと。
    • コレを回避するためには、基板設計を考え直す必要がある。
      • ミクロン単位で配線を設計する必要がある。。
  • 今流行の端子

    • USB
      • 端子数 4 - 9
      • シリアル通信
    • IEEE 1394
      • FireWire
      • 端子数4 -9
      • シリアル通信
    • S-ATA
      • 端子数7
      • シリアル通信
    • SAS
      • Serial Attached SCSI
      • 端子数7
      • シリアル通信
    • Thunderbolt
      • 20pin
      • 非同期パラレル通信
      • 内部的にはPCI Express
    • InfiniBand
      • 4 - 48
      • シリアル通信 (1X)
      • 非同期パラレル(2X - 12X) レーンのような考え方。
    • 最近のはやりは非同期パラレル
      • 同期しないのでスキューは発生しない。

今日のまとめ

  • ハードウェアは、インフラエンジニアにとって結構重要
  • アーキテクチャ
    • 基本構造は昔から一緒
    • コンピュータの気持ちになろう。
  • CPU
    • 動作原理を知っておこう。
  • バス
    • データ転送をよく知っておくと、よりコンピュータを理解できる。
  • インターフェース

  • 気になったらどんどん自分で調べよう!

GitLabのリポジトリをJenkinsと連動させる

| Comments

さくらVPSの移行にともなってリポジトリとかを移行する必要が出たので、 リポジトリ管理をGitwebからGitLabに移行したんだが、そこでちょっと悩ましい問題にあたった。

GitLabは単体で見るととっても便利だなーと思う半面、ガツガツ成長してきたプロジェクトだけあって まだハードコーディングになってるところや、連携部分で弱いところがあったりする。

簡単に言うと枯れてない。まだ各所で細かーくバグっぽい。1 面白いからいいけど。 で、今回はJenkinsとの連携の際にちょっと悩むことになった。

GitLabにpublic repos がない。

サブタイトルのとおりなんだけど。ないんです。 なので、Jenkinsその他オートメーションツールからのcloneをするにも、他のユーザーと同様に鍵認証が必要になる。

これ自体はgitoliteの時代からあった話ではあるんだけど、問題はリポジトリのアクセス権やらユーザーやらの管理を、 GitLabが独自の機構で面倒見ている点。

そのため、GitLabの仕組みの中で解決しようとすると、Jenkinsユーザを作って全てのプロジェクトにJenkinsユーザを追加しなければいけない。 しかし、このやり方だとオートメーションツールが増えるごとにユーザーを増やして全プロジェクトにReporterとして追加。。。とかやらなきゃいけなくてすごく面倒。

どうしたか: Gitoliteを直接弄った。

しょうがないじゃなーい、と思ってGitoliteに直接jenkinsユーザを追加、systemグループを作って全リポジトリをreadonlyでアクセスさせた。 ちなみに、gitolite.confをいじることになるけど、このファイルはGitLabがパースして書き換えをゴリゴリやるので、やたらめったらいじらないほうがいい。2

gitolite-adminをいじれるのはgitlabユーザだけなので、こんな感じ。

1
2
3
4
5
6
7
8
9
10
11
% sudo -u gitlab git clone git@git.example.com:gitolite-admin.git /tmp/gitolite-admin
% sudo -u gitlab cp /path/to/jenkins.pub /tmp/gitolite-admin/keydir/
% vi /tmp/gitolite-admin/conf/gitolite.conf

(以下の様な内容を追記)
@system             = jenkins

repo    @all
   R                              = @system

% (以下略)

このあたりの情報は、GitLab側のパーサもエラーになることなくうまいことマージしてくれた。

とりあえず、これなら連携するシステム系は、いちいちリポジトリに追加しまくらなくてもサクサク進められるので、よさそう。

で、結論として。

この方法がいいのかどうかは正直わからない。というか、本当はやりたくないけど仕方ない感じ。 今の状況で言うと、正しい選択肢ってのは特にない気がする。

今後に期待したいなー。

  1. たとえばgitoliteとは連携を謳っているにもかかわらず、インストールプロセスがg3に追随できてない。これはlib/tasks/gitlab/status.rake のumask検証部分の問題。gitlab.yamlをデフォルトのままインストールプロセスをすすめるととりあえず回避できる。
  2. いじるときには、一度 lib/gitlabhq/gitolite.rbを読むといい。以前、gitoliteのwildcard reposを設定していた時に、Cなどの権限をGitLabが理解できずにパースエラーになってて参ったことがあった。。。

KVMでlibvirt( < 0.8.2) を使って管理をしている場合の、マイグレーション時の注意

| Comments

KVMなどの仮想サーバを使って運用をする場合の一つのメリットとして、物理サーバに依存せずにマイグレーションを行える、 という点があるのだけれど、うまく行かなくてはまった事があった。

CentOS 5.5 on libvirtのHost上で動いていたqcow2のGuestイメージをCentOS 5.6のHostに移して動かしたら、どういうわけかうんともすんとも言わなくなった。

その時はどうにかこうにか対策だけはできたものの、どうしてそうなったか原因を特定しきれなかったのだが、その後自分なりに調べてみて、 最近やっと原因のコードを見つけて、対策方法とか対象になるバージョンを特定できたのでまとめた。

おそらく間違ってないと思うけど、KVMのすべてを把握してるわけじゃないので、おかしなところ等あれば突っ込み頂けるとうれしいです。

結論

経緯とかコードとかどうでもいい人のために先に結論から。

対象となる環境

以下2点の両方に当てはまる場合、適切な対策が必要。

1. Guest VMにはファイルのdisk imageを使っており、raw以外の形式(qcow2など)で運用していた。
  • rawで扱っている場合には、問題は発生しない。
    • (raw deviceの場合もrawなので当然発生しない。)
2. libvirt 0.8.2以前のHostで運用していたGuestを、libvirt 0.8.3以降のHostにマイグレーションした。
  • CentOS (他のRedhat系は未調査)では、5.5以前から5.6以降にが該当。
    • CentOS 5.6はlibvirt 0.8.2だが、該当のpatchがbackportされて当たっているため、対策が必要。
  • debian leny 以前からsqeeze以降へ
  • Ubuntu は10.04 以前から10.10以降へ

対策

以下の2つのパターンがある。

1. 移植時にXMLを編集し、disk deviceの中の、driverの項目にname=”qemu” type=”qcow2” などの形式を明示するようにする。

明示的にフォーマットを指定する方法。 多分こっちの方がよい。

2. /etc/libvirt/qemu.conf (CentOSの場合はこの場所) にallow_disk_format_probing = 1 の項目を設定する。

フォーマットの自動認識を有効にする方法。 ただしセキュリティ上のリスクを伴うので、極力やらないほうがよい。

経緯と原因

遭遇した状況

仮想マシンはdisk imageファイル(qcow2圧縮)上に作成されたもので、CentOS 5.5上で使っていたxmlとともに丸っとCentOS 5.6上に移した。 すると、qemu自体の起動はするもののdisk imageを正しく認識せず、エラーもでないまま応答しなくなってしまった。

原因と対処

原因は、libvirtのバージョンがあがる過程でdisk imageのデータ形式の判定に仕様変更が入ったことだった。

それまでlibvirtに食わせていたXML定義の中では、disk deviceのdriver typeを明示的に指定しておらず、kvmの自動認識に任せていた。

それが新しいバージョンのlibvirtでは「driverのtype未指定時には、デフォルトでtype=rawのパラメータを自動補完する」という仕様に変わっていたために、 qcow2のimageをrawとして読んでしまい、認識できなくなってしまった。

この点に気づいたため、前述の対策方法の通り、明示的にtype = qcow2を指定してやる事で問題は解決した。

原因になった箇所

どうしてこうなった、と思ったので、KVMのコードとgit logを追ってみて、どうやら下記の変更が原因のようだった。

libvirt.org Git - libvirt.git/commitdiff

理由について詳しくは探りきれなかったのだけれど、disk imageのファイル形式を自動認識する場合にセキュリティ的な問題があるようで、 それを防ぐためのセキュリティパッチとして、この変更を含むいくつかのFIXが行われたらしい。

そして、disk imageの形式に明示的な指定がない場合には、qemuのraw形式としてパラメータを補完してしまうように変更になった。 対策のところにのせたallow_disk_format_probingという設定は、その名の通り上記patchのallowDiskFormatProbingパラメータのフラグを立てるためのもので、 デフォルトではoffになっている。

この一連のpatchはlibvirt 0.8.3で取り込まれているので、問題が起きるのは0.8.2以前から移行してくる場合。 例外として、CentOS 5.6では0.8.2にこのpatch群をバックポートして当ててあるため、対象に含まれる。(srpmで確認済み。)

というわけで。

変更自体はもう結構前の物なので、今更間のある話題かもしれませんが、KVM Hostを移行するなんてそんなに頻繁にやる物でもないだろうから、誰か一人の役に立つ機会でもあれば幸いです。

しかし、libvirtって結構ログが少なくて、いつも苦労する。。。infoとか出してくれるとうれしいよね><

VM Disk Image の Mount 方法いくつかメモ

| Comments

仮想マシンのdisk imageをmountしたいことってよく有るけどよく忘れるのでメモメモ。 libguestfs使ってごにょごにょ、見たいなプログラマブルな話は含まない。

横着する方法

KVM raw image / Xen image

パーティションアライメントの分を考慮すれば簡単に行ける。 1セクタが512byteなら、

1
# mount -o loop,offset=$((63*512)) /path/to/image /mnt

怒られるなら1セクタのsizeが違う可能性が高いので調べる。

1
# /sbin/fdisk -l /path/to/images

とかすれば、1セクタが何byteかわかる。

KVM qcow2 image

基本は同じだけど、qcow2圧縮されてるのでこれを何とかしてから処理する。 qemu-nbdを使えば可能。 kernel moduleとしてnbdが普通は有効になってないことが多いので、これを有効にして使う。

1
2
# modprobe nbd
# qemu-nbd -c /dev/nbd0 /path/to/image.qcow2

これで/dev/nbd0のディスクとして見えるようになるので、あとはraw imageと同様にすればOK.

1
2
# /sbin/fdisk -l /dev/nbd0
# mount -o loop,offset=$((63*512)) /dev/nbd0 /mnt/

外すなら逆手順。

1
2
3
# umount /mnt
# qemu-nbd -d /dev/nbd0
# rmmod nbd

ちゃんとやる方法

適当なoffsetとかでゴツンてやるんじゃなくて、真面目にやるにはどうするか。 単に、mount -o loop,offset=…ってやらずに、kpartxとかを使ってやる、という違い。

kpartxを使うことで、いちいちセクタサイズを気にしなくて良くなるので、自動化するならこっちが便利。

raw image

まずはループデバイスとしてmountしてから、kpartで個別のpartitionにアクセスできるようにする。

1
2
3
4
5
6
7
# losetup -f
/dev/loop0
# losetup /dev/loop0 /path/to/image
# kpartx -av /dev/loop0
add map loop0p1 (253:0): 0 51199092 linear /dev/loop0 63
add map loop0p2 (253:1): 0 4096575 linear /dev/loop0 51199155
# mount /mnt /dev/mapper/loop0p1

これでアクセスできるようになる。 外すときは以下の要領で。

1
2
3
# umount /mnt
# kpart -dv /dev/loop0
# losetup -d /dev/loop0

qcow2 image

要領は同じで、losetupでやる代わりにnbdでやる感じ。

1
2
3
4
5
6
# modprobe nbd
# qemu-nbd -c /dev/nbd0 /path/to/image.qcow2
# kpartx -av /dev/nbd0
add map nbd0p1 (253:0): 0 51199092 linear /dev/nbd0 63
add map nbd0p2 (253:1): 0 4096575 linear /dev/nbd0 51199155
# mount /mnt /dev/mapper/nbd0p1

これでOK。 外すときは以下の通り。

1
2
3
4
# umount /mnt
# kpartx -dv /dev/nbd0
# qemu-nbd -d /dev/nbd0
# rmmod nbd

いじょ。