アルパカDiary Pro

はてなブログProではありません

2014年振り返りと2015年

まずは振り返ってみる。

家電その他の故障率が異常

最初に仕事の話持ってこようかと思ったんですが、
去年一番印象に残っているのは とにかくモノがよく壊れた ということ。
壊れたもの一覧。

  • 冷蔵庫
  • 洗濯機
  • 炊飯器
  • 給湯器
  • 自転車
  • イヤホン

「家電は一気に壊れる」といいますが、本当に立て続けにきたのでびびった。
これだけで50万くらい飛んでる。。
というわけで家電用に自分で修繕積立することにした。
みなさまもしておいたほうが良いですよ!



仕事

2014年前半はかなり駆け抜けた感がありますが、後半は今後に向けてひっそりと動いてた感じです。
(サボっていたわけではない!!!!)
今年は忙しくなりそうなヨカン。たぶん。


業務内容のほうですが、サーバ運用の部分を勉強しつつ
新たにLuaGolang触ってみたり、相変わらず広く浅くやってる感じでした。
Dockerはそれなりに触っていて開発フローにも組み込んでいたりするので
来年は本番運用にも持って行きたいと思っています。


またあまり技術的な話ではないんですけど、去年はチーム開発をするにあたって
自分の中で HRT(謙虚/尊敬/信頼) を特に意識していました。
システム開発ではメンバー間の衝突*1することはよくあることですが
基本的には自分よりも相手の方を尊重して進めてた(つもり…)*2
というか「チームの雰囲気を悪くしない心構え」というか。
結構大事だと思った。


その他ではYAPCでトークできたこともあってか色んな意味で広がりました。とても良かった。


今気になってるOSSやキーワードなど。いくつか取り入れていきたい。

  • Atlas
  • Consul
  • AWS Lambda
  • AWS EC2 Container Service
  • AWS Service Catalog
  • AWS Aurora
  • FoundationDB
  • Aerospike
  • RedisCluster

家庭

上の子はすっかり大きくなって、きちんと(?)人っぽくなってきた。
ただ最近また言うこと聞かなくなってきているので真面目にしつけしないとなぁと思ってる…
下の子は3才になってますます可愛くなってる…が、女の子だからかわからないけど主張が強い。
あとジャイアンみたいに「人のものは私のもの」という感じなので見ててヒヤヒヤする。
パンチ、キックが得意。



2015年

特にこれといって大きな目標は決めてないんですけど、*3
今年は色んな意味でバリュー出すチャンスがありそうなので
それを逃さずに自分を高められればいいかなと思ってます。


では、本年もよろしくお願いします!!!!

*1:仲が良くないという話ではなく、設計上の考え方の違いとか

*2:もちろん明らかに悪手の場合は反論する

*3:小さいのはたくさんある

lua-resty-woothee というモジュールを書きました

Lua Advent Calendar 2014 7日目の記事です。


wootheeというUA解析プロジェクトを最近知ったのですが、
Lua版が無さそうだったので書いてみました。
本当はLua単体で動くようにしたかったんですが、諸事情によりOpenresty依存となっております。
理由は後述。

ちなみに書いた動機など。

  • ちょうど、エンドユーザのUA解析してDB登録したりゴニョゴニョ出来たらいいなーと思っていた
  • Nginx+Luaを書き始めているが、がっつりLuaを触っていたわけではないのでライブラリっぽいのも練習がてら書いてみたかった
  • 期待された https://twitter.com/songmu/status/525610905946447872

使い方

READMEそのままですが…

インストール
luarocks install https://raw.githubusercontent.com/toritori0318/lua-resty-woothee/master/lua-resty-woothee-dev-1.rockspec

または git clone でリポジトリダウンロード後に
lua_package_path をよしなに指定すると使えるようになります。
アップデートしたい場合は、再インストールしてNginxをリスタートするだけで行けるはず。

基本
server {
    location /test {
        content_by_lua '
            local woothee = require "resty.woothee"

            -- parse
            local r = woothee.parse(ngx.var.http_user_agent)
            --  => {"name": "xxx", "category": "xxx", "os": "xxx", "version": "xxx", "vendor": "xxx"}

            -- crawler?
            local crawler = woothee.is_crawler(ngx.var.http_user_agent)
            --  => true

            ngx.header.content_type = "text/plain"
            ngx.say(r.name)
        ';
    }
}

あとはparseメソッドにUserAgent渡せば結果がtableで返ってきます。簡単。

応用編

parseした結果をアクセスログに直接埋め込んだり、プロキシしているバックエンドサーバに渡したりと
いろいろ応用が効きそうですね。
この辺りのサンプルもREADMEに書いてあるので参考にどうぞ。
アクセスログ出力した時はこんな感じでparseした情報を付与できます。

xxx.xxx.xxx.xxx - - [01/Nov/2014:15:47:38 +0000] "GET /test HTTP/1.1" 200 17 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.111 Safari/537.36" "Chrome" "pc" "Mac OSX" "38.0.2125.111" "Google" "10.9.5"
xxx.xxx.xxx.xxx - - [01/Nov/2014:15:47:41 +0000] "GET /test HTTP/1.1" 200 18 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9; rv:33.0) Gecko/20100101 Firefox/33.0" "Firefox" "pc" "Mac OSX" "33.0" "Mozilla" "10.9"
xxx.xxx.xxx.xxx - - [01/Nov/2014:15:48:01 +0000] "GET /test HTTP/1.1" 200 17 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_5) AppleWebKit/600.1.17 (KHTML, like Gecko) Version/7.1 Safari/537.85.10" "Safari" "pc" "Mac OSX" "7.1" "Apple" "10.9.5"

Openresty依存になった理由など

実は最初はLua単体で動くように書いていました。
実装がだいたい終わってよっしゃーテストやるぞーとテスト通し始めたら

で、あとで知ったんですが(オイ) Luaのは正規表現というか独自パターンマッチングなのでそりゃ通らないわけですね。
最初は独自の方に寄せようとしたんですが「(a|b)」とか「()?」とか使えなくてだいぶ辛い…

正規表現ライブラリ使うことも考えたんですが
あまり他のライブラリに依存するとユーザの導入障壁が高くなるでしょうし、
自分は(そして多分殆どの人が)Openrestyでしか使わないでしょうし、
OpenrestyはPCREの正規表現実装を含んでいるのでそれ使えば解決するし、
という感じでOpenresty依存にしました。
(関連する会話 https://twitter.com/toritori0318/status/527151195719077891


この辺り、うまく共存してOpenresty依存無くすことも出来るかもしれないですが
自分は必要なかったのでそこは頑張りませんでした。
もしLua単体で動かしたいという要件があれば挑戦してみてください。



まとめ

Nginx+luaで解析することによって
高いパフォーマンスで、かつ汎用的に解析結果を使えるようになりました。
大抵はアプリケーションサーバよりNginxのほうがリソース空いていることが多いと思いますし、
そちらによけいな処理をお任せしてしまうのは悪いことではないと思います。
よろしければ使ってみてください〜

おまけ1:luayamlモジュールでハマった

http://yaml.luaforge.net/
これの最新版使ったらバグなのかわからないけどtestsetsのparse結果がおかしくてめっちゃハマった。つらい*1

おまけ2:Nginxのset変数はLuaから定義出来ない

Nginxのset変数もライブラリの中からよしなに出来ればもう少しシンプルに書けるかなと思いましたが
"That is, nginx variables cannot be created on-the-fly." とのことでした:(

おまけ3:Openrestyモジュールのテストについて

Openrestyモジュールのテスト、coreから野良モジュールまでほとんどperlのTest::Nginxで書かれています。
perl...うっ」となるかもしれないですが、実際にperlを知らなくても書けます。
なかなか面白い手法だったので紹介してみます。

# vim:set ft= ts=4 sw=4 et:

use Test::Nginx::Socket::Lua;
use Cwd qw(cwd);

repeat_each(1);

plan tests => repeat_each() * (3 * blocks());

my $pwd = cwd();

our $HttpConfig = qq{
    lua_package_path "$pwd/lib/?.lua;;";
};

$ENV{TEST_NGINX_RESOLVER} = '8.8.8.8';

no_long_string();
#no_diff();

run_tests();

__DATA__

=== TEST 1: basic
--- http_config eval: $::HttpConfig
--- config
    location /t {
        content_by_lua '
            local woothee = require "resty.woothee"
            ngx.say("OK")
        ';
    }
--- request
    GET /t
--- response_body
OK
--- no_error_log
[error]

たとえばこちら、lua-resty-wootheeのテストです。
__DATA__ 以下のところだけ変えればOKです。
見たらわかりますが、Nginxコンフィグをそのまま記述して、期待するレスポンスを書く感じです。簡単ですね。
(ただ、printデバッグなどが非常に面倒なのが少し辛い…)

おまけ4:ベンチマーク

単純なLuaスクリプトと比較し、どの程度性能劣化するかを検証してみました。

now()を返すだけのLuaスクリプト
ab -c 10 -n 50000 -H "User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)" http://localhost/now
Requests per second:    10291.40 [#/sec] (mean)
woothee.parse ON
ab -c 10 -n 50000 -H "User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0)" http://localhost/test
Requests per second:    8541.17 [#/sec] (mean)

たぶんUser-Agentによって多少は性能変化すると思いますが、許容範囲ではないでしょうか。


*1:datasetのテストをするときのみyamlモジュールに依存している

【練馬/板橋エリア】お金をかけずに子供を遊ばせるスポットのご紹介

↓こちらに移動しました!
http://www.adventar.org/calendars/681

GitLab+DroneでHerokuにCIする、という最高の環境を10分で作る

※2015/4/17
GitLab7.9 / Drone0.3 版に記事をアップデートしました。
Drone0.3で大きく変更されたため、手順もだいぶ変わっています。
今回の手順で主な変更点としては以下の様なものがあります。

  • GitLabでDroneアプリケーションを登録する必要がある
  • Drone側でリポジトリをsyncする機能が追加され、その中から選択する方式になっている
  • Herokuへのdeployについて、0.3からsshキーではなくAPIキー(token)を用いる方法に変更されている


GitLab+OSS版DroneをEC2に0から構築し、herokuにCIする
という環境を10分くらいで作ってみます*1
また、すこしだけDroneについての説明もメモ程度ですが書き記しておきます。



GitLabとは/Droneとは

GitLabGitHubクローンのOSSです。
DroneTravisやCircleCIに似たCIサービスです。
全てがDockerコンテナ上で動く、というのが特徴です。
OSS版も公開されていて、v0.2.1のREADMEを見ると
どのようなことができるかざっくり確認できると思います。
テストを動かしたり、S3やHerokuにパブリッシュしたり、DBコンテナを起動できたりと
主要なものは機能提供されていますし
普通にシェルスクリプトも書けるので柔軟なデプロイなども行うことが出来ます。


また現在は GitHub/GitLab/Bitbucket と連携することが出来るようです。
なのでGitLab限定というわけではないですよ:)


DroneのOSS版が公開されているので今回はこちらをEC2上に構築します。



構築環境

Droneがubuntu推奨らしいので、EC2のubuntu(ami-e74b60e6)に0から構築してみます。
たぶんt2.microでもよいですが、メモリが若干心配なのでt2.smallで構築してみました。
また、本番として使うときにはディスクサイズ多めで起動したほうが良いでしょう。
(さらにプラスでセキュリティ周りも追加しておいたほうが良いですね)

ami ami-e74b60e6
インスタンスタイプ t2.small
Drone webポート 80
GitLab webポート 81

もちろん、EC2限定ではないのでお好きなクラウドVPCで実行してもOKです!


前準備

Heroku

Herokuのアプリケーションが無い場合は
アカウントとアプリケーションを新規作成しておきましょう。
また、HerokuデプロイのためにAPIキーが必要があります。
アカウント設定からAPIキーをメモしておきましょう。

Docker/Drone/GitLabインストール

Gistにスクリプトを公開しているのでこれを実行すると一発構築出来ます。

一応、個々のインストールについてのRefも記載しておきます。

GitLabとDroneの連携について補足説明

連携するためにどういうことが必要か説明します。

  1. GitLabにDroneアプリケーションを登録。
  2. GitLabにリポジトリ登録。.drone.ymlを追加しておく。
  3. Droneの設定でGitLabのURLやクライアントキーを登録。
  4. DroneにログインするとGitLabのリポジトリ一覧がsyncされているので、CIしたいリポジトリをActiveにする

あとはGitLabのリポジトリが更新されると .drone.yml の内容でCIが実行されます。
意外と簡単。

GitLabにDroneアプリケーション登録

それでは設定を準備する手順を進めていきましょう。
まずはGitLabにDroneアプリケーションを登録します。
管理者用画面から「Applications」から名前とコールバックURLを登録します。
コールバックURLは「/api/auth/gitlab.com」です。

この辺りのドキュメントはこちら

GitLabにリポジトリ作成/Herokuへpush

次に、GitLabのGUIからリポジトリ作成しソースコードをpushしておきます。
今回はこちらのチュートリアルのコードを利用してみました。
さらにプラスで.drone.ymlを追加しておきましょう。以下のようなファイルを用意しておきます。

image: dockerfile/ubuntu

deploy:
  heroku:
    app: gitlab-drone-test
    token: "<Herokuで確認したAPIキー>"
    force: false

また、この時点でHerokuへpushしておきましょう*2

Drone

コンフィグ設定

まず、インストール後にGitLabの情報を/etc/drone/drone.tomlに記述しておく必要があります。

[gitlab]
url="http://<GitLabのURL>"
client="<GitLabで登録したアプリケーションのApplication Id>"
secret="<GitLabで登録したアプリケーションのSecret>"
skip_verify=false
open=false

修正後に restart drone で反映しておきます。


すると、Droneの画面で以下のような画面が表示されているはずです。
ここの GitLab のボタンをクリックするとGitLabへのOAuthが開始されるので
GitLabでログインしている情報でAcceptすると、DroneとGitLabの連携が完了します。


GitLabリポジトリを選択

ダッシュボードを見ると、GitLabのリポジトリの一覧がsyncされていると思います。
ここで、先ほど登録したリポジトリを選択して Activate しましょう。


あとはリポジトリに .drone.yml が存在していれば
pushを契機にherokuへのCIが開始されます。

正常に終わるとグリーン表示されます。
(ちなみにDrone0.3から、リアルタイムでbuildログを確認することが可能になっています)


サイトにも反映されているようですね。iei!!!

Drone:気になるところ/ハマりどころ

CI速度について

一度目、Dockerイメージのpullが入ると遅いですが
二回目以降は速くなるので気にしなくてよいです。

公式のイメージサイズがバカでかい

割とサイズが大きい物が多いので、自前で必要な物だけインストールしたイメージを使うのが良いでしょう。

自前のイメージを使うときの注意点

gitが必須です。また、publish/s3 を動かすためには aws-cliも必要になるので
一緒にインストールしておくとよいでしょう。

Dockerなので

ディスク容量には気をつけましょう。

コンテナに入りたいナリ〜

Droneの機能としては(おそらく)提供されていないので入るのは難しそうです。
.drone.ymlがscriptの羅列だけであれば
ローカルで同じコンテナ起動してscript実行してみる、というくらいでしょうか…
(もしかしたらもっといい方法があるのかも)



まとめ

繰り返しますが、このスクリプトを実行すると一発で構築できます!!
またここでは詳しく説明しませんでしたが、
OSS版Droneがよく出来ているのでお手軽CIツールとしてだいぶ良いのではないでしょうか。
オススメです!

Drone:ref

*1:ちなみにs3の機嫌が大きく左右するので10分で終わるとは限りません><

*2:Droneから連携する場合、Herokuへ一度でもmasterにpushされている必要があるようです

OSS版DroneでDockerコンテナに対してansibleを実行しserverspecでテストをする

さよならインターネット:CircleCIでDockerコンテナに対してansibleを実行しserverspecでテストをする
こちらの補足エントリです。

OSS版Drone.io

https://github.com/drone/drone
drone.ioオープンソース版です。
Golang+Dockerで実装されているCIサービスです。
社内用のCIサービスとして使い勝手良いのでJenkinsの変わりに結構利用しています。

.drone.yml

リポジトリにこんなの置いておきます。
Droneではgit入りのイメージが必要なので、今回はDockerRegistry上の別イメージで実行してみました。
2回目以降は前回pullしたイメージを使いまわすので速くなります。

image: tvservices/ubuntu-ansible:13.04

script:
  - echo "start!!"
  - ansible-playbook ansible/ci.yml -i ansible/localhost -c local
  - echo "end!!"

試しにplaybook置いてこんなの書くだけで動いた。
serverspecまで試してないですがそのままscriptに記述すれば行けるはず。



OSS版Droneについて

いま、stableはv0.2.1ですが、v0.3に上がろうとしているところで
READMEなどが中途半端っぽいのでrelease commitの方を見ると良いかもしれません。
https://github.com/drone/drone/tree/22268eb2e669619b8dbc4b92f65a487eec946861

一人isuconで遊んでみた

予選出れず泣いていたのですが、AMIが公開されたようなので遊んでみました。


以下条件。

  • 今日の0時-3時で集中してやる
  • マニュアルは事前に読んだ
  • isucon参加者ブログは意識して見ないようにしてた。けどなんとなくヒントっぽい単語は目に入ってた


なので、フェアではないです。

時系列にやったこと

  • AMIからインスタンス起動。
  • とりあえずwebappだけバックアップ。
  • アプリをperlに置き換え。
  • ベンチマーク流してアクセスログをダラ見。
  • 静的ファイルをnginx経由にした
  • engineをStarletにした
  • アプリをUNIXドメインソケットにした
  • too manyなんとかが出始めたので、ついでにsysctlの設定をしたり。
  • topで見ると、mysqlが断トツネックだったのでslowlogの設定やらDevel::KYTProfの設定入れた
  • kytprofの結果から遅いSQL見つけてインデックス貼ったりした
  • この辺りでスコア20000超えてた
  • MySQLの設定いじったりしたけど、何故か遅くなったりして結局元に戻したりした。
  • workloadの最適値を探したり。最終的には10にした。
  • どう考えてもlogin_logのinsert/select(特にinsert)が重いので、どうやってRedis化しようかなーとか考えてた
  • この辺りで停滞
  • ふとMySQLのメモリエンジンを思いつき、試してみたら30000近くになったw(・o・)w
  • アプリに手を入れるの時間的に無理っぽいので、ログを消したりソケットファイルをtmpfsに置いたり悪あがき

最終結果

まとめ

  • Devel::KYTProf最高〜(^q^
  • isucon超楽しい〜(^q^
  • やっとisucon参加者ブログが見れるぞい〜(^q^

YAPC::Asia2014 レポート #yapcasia

YAPC、今までに何度か参加していますが
今年は念願のスピーカーとして参加することが出来ました。
話した内容についてはこちらをご参照ください。


たぶん言いたいこと全部書くとグダグダになるのでシュバッと。

最高でした

  • 無限コーヒー
  • 無限かき氷
  • 無料ランチ
  • 無料懇親会/巨大プリン
  • 無料HUB
  • ネットワーク

辛かった点

大人の事情もあると思いますが、会場のキャパシティ(特に多目的室)は辛かったです。
おじさんには立ち見は苦行…

印象に残ったトーク

どちらも愛に溢れた、熱い想いが伝わってくるトークでした。
deeetさんのトーク、自分もCLI好きなのでよくツール書くのですが
あまりこういう思想を持って書いているわけではなかったのでとても参考になりました。
songmuさんのトークはPerl愛がひしひしと感じられました。
さらにPerl言語自体の話からコミュニティ、文化に至るまで話されていて
非常に勉強になるトークでした。

Perlに関するトークが減ってきていることについて

自分はPerl好きなので個人的にPerl使いたいと思うシーンは多いんですが、
年々少しずつ使いづらいな〜と思っていて、
特に一番辛いのが世の中のサービスが大抵Perl対応してくれないのが辛くて*1
そういう理由から
Perlを選択肢に入れたいけど入れることが出来なくなってきている
ところがあるのかなと(自分に限らず)。
なのでトークが減ってきているのも仕方がないことなのかな〜という気もしています…
これ打開するには真面目にPerl6が(ry


ただ、Perlのトークが少なくなってきているからといって参加者的には文句があるわけではなく
みなさん楽しめていたようなので特に問題視することもないのかなとも思いました:)

typesterさんのキーノート

刺さりまくって意識最高潮に高まったところで、
最後にお子さんと一緒に壇上に上がったところをみて
なんでかわからないんですけどすごくホロりときました。
感動。

まとめ

運営のみなさま、自分のトークを聞きに来て下さったみなさま、ありがとうございました!
今年も最高に楽しかったです!
来年もまたスピーカーとして参加できるように日々精進します!!

*1:AWSとか