読者です 読者をやめる 読者になる 読者になる

Sionの技術ブログ

インフラエンジニアとして日々の学習を書いて行きます。twitterは@sion_cojp

VOYAGE GROUPのfluctに入社しました

お前 is 誰

前職の話

eurekaでpairsというアプリのインフラやってました。

オンプレばかりやってきたので、100% AWS楽しかったです。

1年も経たずに辞めてしまったので、結構突っ込まれます。

辞めた理由はプログラム寄りに身を置きたかったのと、会社へのネガティブ要素が多かったです。

ただ会社は成長するもので。今は私の言ってた意見が徐々に反映されてるみたいです。

ネガティブ要素を書いてたら、結構エグかったので、具体的に聞きたい人はtwitterで気軽に飲みにでも誘ってください。



そして転職

行く当てなく退職届を先に出し、会社の許可を得てtwitterで募集してみました。




そして、id:katzchangさんに誘われて、VOYAGE GROUPfluctでSREとして働くことになりました。

他にも魅力的な会社からお誘い頂き光栄で、嬉しい反面とても悩ましかったです。

VOYAGEは面接段階でソースコードを見せて頂けたりしたので、そこが若干ポイントになったのかなぁと思います。



現職の話

3月から働いてます。

入社時には色んなところにGetWildの文字が書いてたり、曲が流れたりして、たっぷりGetWild歓迎されて最高でした!

今の仕事はAWS-オンプレでインフラやりつつ、とあるシステムをPHP->Goに書き直して、入れ替えるプロジェクトをやってます。

やりたいことを意思表示すればやらせてくれるので、ビビらず責任持って、技術力でサービスに貢献していきたいです。

逆に意思表示できない人は腐ってくんじゃないか?という課題感はあるので、なんとか改善していきたいなぁと思いつつ。


あと大企業なのに意見が通りやすいのもびっくり。(私は通りにくい印象ありました)

「キーボードとモニタ(2枚)は会社として用意して欲しい!」と意見を言ったらその週には購入してもらえるようになりました。爆速。

今の段階ではとても働きやすいので、このまま維持していきたいです。


皆様、どこかで勉強会でお会いしたときは、何卒宜しくお願いします!

プロセスとスレッドと違い





プロセス、スレッドの違い

プロセス スレッド
特徴 プロセスはリソースを共有できない。ロックかけたりしないといけない。
プロセス間通信も出来る(unixだとパイプ)
メモリや、オープン中のファイルなどのリソースを共有することができる。
競合(レースコンディション)が問題になる
生成方法 親プロセスからforkで子プロセス生成 親プロセスからpthread_createでスレッド生成
データ保持 ・1プロセス毎に専用の仮想アドレス空間を保持。
・データセグメントのデータはそれぞれのメモリ領域内に保持。
・なのでスレッドよりコンテキストスイッチによるオーバーヘッドが大きい
・全て親プロセスのメモリ領域内に保持されているため、利用する仮想アドレス空間を切り替える必要がない。
TLBフラッシュはいらない。
・スタック領域、SP、PCを親プロセスに生成する
切り替える場合 ・仮想アドレス ⇔ 物理アドレスマッピングをそのプロセス用のものへの切り替える必要がある。
・1度アドレスを解決した結果は MMU がキャッシュしているため、そのままの状態でプロセスを切り替えてしまうと前のプロセスの領域が見えてしまう。
・そのためMMUキャッシュをクリア=TLBフラッシュが必要。
スタック領域、SP、PCの切り替えだけで済む
メモリに保持する情報 ①親プロセスのテキストセグメント
②親プロセスのデータセグメント③子プロセスのデータセグメント(親のコピー)
①親プロセスが作った、スレッド用のテキストセグメント
②親プロセスが作った、スレッド用のデータセグメント
・ 親プロセスのスタック領域
・スレッドのスタック領域(親のコピー)
処理速度 遅い 速い
データの安全性 メモリ領域が独立してるので安全 スレッドセーフでなければならない
並列処理の動作 子プロセスを複数立ち上げて並列 スレッドを複数立ち上げて並列

プロセスの実装と生成・終了ってどうなってるの?





プロセスってどう管理されてるの?

  • プロセステーブルにプロセスが起動するたびにエントリが追加、削除されてる




プロセステーブルのエントリには何が書かれてるの?

  • C言語のstructとして定義されてることが多い(プロセス構造体)
  • 主に下記3つ
  • ①プロセス管理情報
    • レジスタの退避領域:プロセス切替えの時レジスタ(PCやSP)を退避するための領域
    • プロセスの属性:プロセスIDや所有者など
    • 統計情報:プロセスが動いた時間
  • ②メモリ管理情報(コード、データ、スタック領域)
  • ③ファイル管理情報(オープンしたファイルの情報)




プロセスの生成の流れ

  1. プロセステーブル内の空き領域を探す
  2. プロセス構造体を割り当てる
  3. プロセス構造体の初期化(プロセスID決め、データ・スタック・コード領域の大きさを決め割り当て)
  4. プロセス実行




プロセス終了の流れ

  1. オープンしてたファイルをすべて閉じる
  2. プロセスが使用してたメモリ領域の解放
  3. プロセス構造体を解放
  4. プロセステーブルのエントリ解放
  5. プロセスの終了

プロセスって何?





はじめに




そもそもOSは

f:id:sion_cojp:20170223172326p:plain:w500

  • OSではマルチタスク機能によって、細かくプロセスを切り替えることで"同時に動かしてる様に見せる"
  • 並列ではなく並行。
  • Webブラウザやメーラーなど複数アプリを実行してるときマルチタスク機能を使っている。




プロセスって何?

  • 実行状態にあるプログラム
  • アプリは(複数の)プロセスから作られてる
  • CPU(プロセッサ)は1度に1つのプロセスしか処理できない




プロセスの動き

f:id:sion_cojp:20170228164344p:plain:w500

  • プロセスは実行準備、実行、待ちの3種類状態がある
  • プロセスは常に1つのプログラムしか実行出来ないので、うまく切り替えてる。




プロセスの切り替えってどうやってるの?

  • 切り替える手法は、プリエンプティブ方式と、ノンプリエンプティブ方式がある




プリエンプティブ方式と、ノンプリエンプティブ方式って何?

  • プリエンプティブ:OSがプロセッサの実行権限を管理して、切り替える。現在のOSはこれ。
  • ノンプリエンプティブ:プログラム自身に任せる。昔のOS。
    • ちなみにgoroutineはノンプリエンプティブ方式を使って切り替えてる




プロセスの実行スケジュール管理はどうやってるの?

  • OSによって色々ある
  • 例えば、ラウンドロビン方式:実行可能状態にあるプロセスを順番に実行す




プロセスとメモリの関係

  • CPUは、指定したプログラムコードがある場所(アドレス)にジャンプする命令を持っている
  • アドレスはメモリ 1byte
  • CPUのビット数でアドレスの数が決まる
    • 32bit 232 = 0xFFFFFFFF ≒ 4GByte
    • 64bit 264 = 0xFFFFFFFFFFFFFFFF = 16EByte ≒ 172億GByte
    • までのアドレスを認識出来る(0xは16進数って意味)
  • 誰も使っていないアドレスを探して利用する必要があるので、MMU(memory managemanet unit)がアドレス管理している
  • CPUがプロセスを実行する際、そのプロセスが持っているアドレスに対して演算を行う




演算って何?

  • 四則演算(足す、引く、かける、割る)
  • 論理演算(AND・OR・NOT)
  • など




MMUって何?

f:id:sion_cojp:20170223172335p:plain:w500

  • プロセス毎に物理メモリ領域を確保->その領域にアクセスするための仮想アドレスを用意する
    • 同一OS内のすべてのプロセスは同一サイズの仮想アドレスを持つ
    • CPUの中にMMUと仮想アドレスがある。メモリ上にはない
    • プロセスが「メモリを使用する」宣言すると確保される
  • プロセス->仮想アドレス->物理アドレス




仮想アドレスのメリットは?

f:id:sion_cojp:20170327020132p:plain:w500

  • 他のプロセスからアクセスできないように制御されてるので、セキュア
  • 物理メモリはバラバラでも、仮想アドレスは連続した領域のように扱えるため、メモリの隙間も有効に使える
  • 図のように、同じ物理メモリをマッピングすることで、複数のプロセスでメモリを共有できる
    • 共有ライブラリのロードとか




複数のプロセスが共有してるデータにアクセスすると競合(レースコンディション)しない?

  • もし、あるプロセスが共有メモリを読んでいるなら、 他のプロセスは「書きこみ終了するのを待つ 機構」を作る必要があるよね
  • UNIXでは、そのようなプロセス間通信(IPC)に下記手法があるよ
  • 例えばセマフォ排他制御
    • 0,1の値を保持しておき、0の場合はアクセスNG、1の場合はアクセスOKなど。
    • 解放出来なかった(この場合だとずっと1にならない)場合、デッドロックって言うよ
  • ちなみにGolangでは「メモリ共有より、メッセージ共有」を推奨している




プロセスがメモリに保持するデータってどんなの?

f:id:sion_cojp:20170327020230p:plain:w500

  • 上位アドレスはCPUのビット数と、メモリの数によって変わる
    • 32bit OSだったら、232 = 0xFFFFFFFF = 4GB(先ほども出ましたね)
  • 大きく3つに分かれる
  • ①テキストセグメント
    • 実行されるプログラム。
  • ②データセグメント
    • 静的領域:定数、グローバル変数など。データ(初期化ありとBSS(初期化なし))がある
    • ヒープ:malloc()などで動的に確保。GCでクリア。
  • ③スタックセグメント
    • スタック:CPUのレジスタを一時的に退避させたりする。ローカル変数を確保。上位アドレス側には引数と環境変数が置かれる。




スタックって何?

  • 処理中のデータを一時的に退避(入れたり出したり)するデータ構造
  • 最後に入った要素が最初に取り出されるのでLIFOともいう(Last-In, First-Out)
  • 同じデータ構造のキューは最初に入った要素が最初に取り出されるのでFIFO(First-In, First-Out)という
空のスタック             [
Aをスタックに入れる       [A
Bをスタックに入れる       [A B
Bをスタックから取り出す    [A
]




malloc()って何?

  • memoryをallocate(確保)するための関数
  • 必要な量を必要なときに動的にヒープ領域に確保できるのがメリット
  • 通信プログラムだと、クライアントが接続してきたときに、メッセージ交換に使うメッセージ用のバッファを動的に確保したり。
  • クライアントが切断したら、free()で解放できるので、柔軟にメモリが使える。




スタック領域とヒープ領域

  • どちらも実行時にメモリを確保する領域
ヒープ スタック
領域確保 動的
実行時確保
静的
コンパイル時確保
解放 手動 自動
容量
速度




GCって何?

  • ヒープ領域がいっぱいになると新しいオブジェクトがロード出来なくてプログラムが実行できない
  • GCは、ヒープ領域に空きがなくなると、使用されてないオブジェクトを判別してメモリ上から消去する




スタックメモリって何?

  • タスクや、関数内だけで使われる変数やアドレス情報を保持するメモリ領域
  • タスクを終了する or 関数から抜けると、スタックの内容も破棄される
  • この中にスタックを構築し、下記を保持していく。

    • スタックポインタ (SP): スタック領域のどこを見ているかを指す値
    • プログラムカウンタ (PC): プログラムのどこを実行しているかを指す値
  • ちなみにGolangでは、スタックメモリが不足すると、新しいチャンクが確保されて追加されるので、スタックオーバーフロー(スタックにメモリを積み過ぎて死ぬ)は発生しにくい




Golangでスタックオーバーフローを起こすには?

package main

import "fmt"

func main() {
    var a []interface{}
    a = make([]interface{}, 0, 10)
    a = append(a,
        append(a, 1))
    fmt.Println(a)
}
// runtime: goroutine stack exceeds 250000000-byte limit
// fatal error: stack overflow
// ......
広告を非表示にする

インフラエンジニアの綺麗で優しい手順書の書き方

書きました。 手順書って書くの難しいし、面倒くさいですよね。 綺麗でわかりやすい手順を書いても、会社に評価してもらえなかったりとかも原因だと思ってます。 けどちゃんと書けば会社や皆さんのためになるので、是非ご参考下さい。

リブセンスに勤めて2年間を振り返って





前職(某DC:3年ちょっと : サーバエンジニア)

  • サーバとネットワーク機器のハードウェア周りをメインに、キッティング、Firmware, Bios, IOSの* アップデートや初期化や障害対応
  • サーバとネットワーク機器の開梱、マウント、ケーブリング、OS初期構築
  • 色んなサーバのベンチマークテスト
  • DNSの運用
  • エッジルータの運用
  • 顧客のL3, L2スイッチ、Juniper FWの構築
  • ioDriveの運用。
  • 社内ツールを色々とPerlで作成(ioDriveのベンチマークとか。)

現職(リブセンス : 2年(7月入社) : インフラエンジニア)

1年目まで
  • 保守期限切れのため、大量のサーバリプレイス
  • 新たなサーバ選定、購入
  • 物理、論理ネットワーク構成図作成
  • L3,L2の設定見直し、適用
  • 実運用されてる全てのサーバのリバースエンジニアリング(構築、運用、再起動手順作成)
  • vyatta→vyos移行
  • メール配信サーバのスケールアウト
  • 手順をいっぱい作成する毎日
  • メディアに所属し、keepalive, modroxy, nginx, apache, mysql, mysqld_multi, NAT, memcache などなどの構築、運用。
  • DNSレコードの整理
  • 稼働率を集計するアプリをrailsで作成
  • 開発環境と本番環境の完全分離
  • nagiosとmunin

  • qiitaで一番buzzたのは"インフラエンジニアとしてよく使うコマンド集"(http://qiita.com/sion_cojp/items/04a2aa76a1021fe77079

    1年目までを振り返って
  • 勝手がわからなかった部分もあってあたふたしてた時代。
  • エンジニア用語難しい
  • 社内用語難しい
  • Linuxはかなり知識不足で入社しましたが、実際に運用をしてみて多くの知識を得た。
  • 入社前にapache + nginx周りをガリガリ触ってたことで結構助けられた。
  • 会話の中で聞いた単語をメモって調べての繰り返し。他人のソースコードをみて調べての繰り返し。それで力が付いた。
  • 今でもやれてるのは素敵。
  • nagiosでアラートが上がった時、何もできない悔しさをバネに障害に積極参加「どうやって復旧したんですか?」と聞いたり
  • かなり良い経験でした。
  • railsとか触ったことないけどなんとか2週間で出来た。
2年目まで
  • 社内DNS構築、運用
  • apacheとnginxの最新版のベンチマークhttp://qiita.com/sion_cojp/items/edb20a6b87f10e186c23
  • OpenStackの検証と開発環境に導入(Controller, Network, Compute, Cinder)
  • knife-solo(chef)を使ったOS構築自動化
  • packer + chefを使ったvagrant box作成
  • ansibleで各環境に置かれたサーバに対してコマンドが発行できるようにした

  • qiitaで一番buzzったのは “CentOS6とCentOS7の比較表"(http://qiita.com/sion_cojp/items/115e1671fcbc8f214aee

    2年目までを振り返って
  • 会社に慣れてきたこともあって、スピード感持って攻める姿勢に。
  • なんでもできる と思ってきたのはこの頃。
  • 一時的に人数少なくなったけど、目標設定は変えない頑固さとスピード感。そして達成。
  • スクラムによるタスク管理と、2週間毎の振り返りでかなり良くなったと思ってます。
  • 特にタスク毎にPDCA回してタスク完了スピードをもっと速く。
  • 障害対応も速くなった。
  • 曖昧な部分はなくし、自動化促進。結果色んな技術に触れることが出来ました。
  • メディアの人たち巻き込んだり、色々調整したり。
  • これおかしい、と思ったら即修正いれたり。
  • OpenStackの検証に手こずって、頭悩ましてた時期。OpenStackIRCに突撃もしたり。OpenStackの実運用tipsってネットに載ってないことが多かったりする。
  • 開発環境に導入出来てよかった
  • qiita記事よくbuzzってた
  • defconの問題を初めて解いた。かなり手探りだったけど楽しかった!
  • MVPノミネート1回、受賞1回と良い

    今後の豊富

  • Goでプラグイン書いてます。どんどん書いてoutputを出したい
  • consulも触っていきます。自動化万歳
  • 詳解カーネルを読んでカーネルにもっと詳しく。
  • defconの問題をもっと解きたい
  • アプリ作ってみたい。
  • これからもスピード感は持っていきたい
  • 2016年には1度は社外発表したい。します。
  • 次こそはMVPとります

VolgaCTF 2015 : 100 - poemのwriteup

手探り

### ファイルを落として、調べてみる
$ wget http://files.2015.volgactf.ru/poem/poem.pdf
 
### ファイル形式でだまされないように、ちゃんと確認。
$ file poem.pdf
poem.pdf: PDF document, version 1.5

ちゃんとpdfでした。

中身を見てみる

行間が怪しい。バーコードか。ってことは2進数か。ASCII変換か。
改行してないものを0、改行を1として調べて行く。

f:id:sion_cojp:20150514200830j:plain

地味な作業。
なんか途中で9bit部分が出て来た。ページじゃなくて全体としてビット数を数えていくっぽい。
とりあえずhttp://d.hatena.ne.jp/kobapan/20081225/1230156733 に当てはめて行く

{siz

まで読めたが、次から読めなかった。
文末か文頭にビットが入るのかな?
文末に0が入る事にしてみると、全て8ビットに入れ替わったページをまたぐ部分は米印を入れている

{ 01111011
s 01110011
i 01101001 
z 01111010
e *01100101
_ 01011111
d 01100100
o 01101111
% *00100101
s 01110011
_ 01011111
m 01101101
A *01000001
t 01110100
t 01110100
e 01100101
r *01110010
_ 01011111
a 01100001
f 01100110
p *01110000
e 01100101
r 01110010
_ 01011111
` *01100000
l 01101100
l 01101100
~ 01111110

うむ。{で始まってるのに、}で終わってない。
最後は01111101になるべきだ。ということは文末は0or1で正しく出力出来た方か。
というかこの段階でなんとなくキーは予想出来そう笑

完成品

ASCII 2進数
{ 01111011
s 01110011
i 01101001
z 01111010
e ページまたぎ 01100101
_ 01011111
d 01100100
o 01101111
e ページまたぎ  01100101
s 01110011
_ 01011111
m 01101101
a ページまたぎ 01100001
t 01110100
t 01110100
e 01100101
r ページまたぎ 01111000
_ 01011111
a 01100001
f 01100110
t ページまたぎ 01110100
e 01100101
r 01110010
_ 01011111
a ページまたぎ 01100001
l 01101100
l 01101100
} 01111111

答え

{size_does_matter_after_all}