Gマイナー志向

とくに意味はありません

SSLv3亡き今、ciphersuiteはFIPS@STRENGTH:!aNULL:!eNULLでいいんじゃなかろうか

今までSSL(TLS)のciphersuite設定はmozilla wikiのSecurity/Server Side TLS]の記述を個人的に推奨してきましたが、Historyを追ってるとたまに迷走してるし、今の設定が本当に良いのか怪しくなってきたので、もう

FIPS@STRENGTH:!aNULL:!eNULL

でいいんじゃないかと思いました。 FIPS準拠、PCI準拠になるし。
https://matsuu.net/ は2014年10月現在このciphersuiteを実践中です*1

反論お待ちしております。

追記:ciphersuite以外の設定は引き続きmozilla wikiのSecurity/Server Side TLS]を参照するか、Generate Mozilla Security Recommended Web Server Configuration Filesをオススメします。

*1:opensslのバージョンは1.0.1j

第4回ISUCON予選にチーム「ご注文はPHPですか?」で参戦して1日目暫定10位になりましたがPHP使ってません

いい感じにパフォーマンスチューニングするコンテスト第4回ISUCONに参戦しました。まだ現時点で本戦に進めるのかわからないのですが、1日目で暫定10位になりました。

PHPでも十分に戦える!と思った方、ごめんなさい。Go言語使いました。

チーム紹介

チーム名
ご注文はPHPですか?
チーム略称
ごちぺち
予選スコア
44000〜45000ぐらい(暫定)
メンバー
アイコン https://pbs.twimg.com/profile_images/1536770974/square1024_2_normal.jpg https://pbs.twimg.com/profile_images/497897656308350976/wKvhLHq8_normal.jpeg https://pbs.twimg.com/profile_images/2704710656/b3e622404badbefd22b2e516bed625d2_normal.png
Twitter @do_aki @matsuu @netmarkjp
職業 インフラエンジニア インフラエンジニア インフラエンジニア
得意言語 PHP Perl Python
当日の役割 右腕 左腕 ファシリテータ

えぇ、ぺちぱー(PHPer)で有名なdo_aki先生がいるチームですが、Go言語を使いました。

役割分担大事。特にファシリテータ大事です。fujiwara組もたぶんfujiwaraさんがファシリテータだと思います。

Go言語を選んだ理由

ノリと勢い

予選の9日前(9/18)に顔合わせ&作戦会議*1で「どうせならGo言語で出てみる?」となったので。

Go言語の勉強について

Go言語の経験はほとんど無く、9/18からA Tour of Goを始めた程度の素人。
9/20あたりから前回のISUCON3予選のAMIに含まれてるGo実装でチューニング実践してみた程度。三人ともISUCON出場経験がはあったのでチューニングはなんとかなりました。ISUCON3予選問題のチューニング結果は50000ぐらい。Go言語つええええ。

ISUCON3の予選問題はGo言語の勉強に最適ですよ奥さん。

今回の予選の対応方法

基本的にnginxのアクセスログとにらめっこです。

アクセスログ応答時間を出力するようにして、リクエスURIごとのトータル時間、アクセス回数、平均応答時間を算出する簡単なスクリプトを用意。その数字をみて、どのリクエストを改善すべきかを決定していきました。

いきなりソースを見たり、topやdstatなどでボトルネックを調べたりしたくなるんだけどもそこはグッと抑える。これは過去にISUCONに出た経験から導き出されたやり方でした。

ソースの編集について

幸い全員Vim使いで、ターミナル上で編集することに抵抗がないので、3人とも1台のインスタンスSSH接続、役割分担しながらプログラムや設定などを書き換えていく感じでした。
BitBucket上のgitにリポジトリを作りましたが、そこからデプロイ&継続的インテグレーションの類は使ってません。サーバ上で編集したものを同じユーザ名でcommit&pushした程度です。

また、リポジトリを一応用意しましたが、綺麗に保つ努力はしませんでした。時間がもったいないから。main.go.hogeファイルとか平気で作ってました。短時間決戦なので気にしない。

どんな実装になったか

ミドルウェアはGoに変えた以外殆ど変わってません。nginx+Go+MySQLです。NginxとMySQLのバージョンアップもしませんでした。

できるだけ前の方で返すべく以下のような実装にしました。

  • スタイルシートや画像ファイルなどの静的ファイルはnginxから返す
  • ログイン失敗でbanされたIP/ユーザをチェックするためにlogin_logをSELECTしている部分は、ログイン失敗した回数をGo上でカウント、banされたリストもGo言語上で保持してMySQLを参照しない*2
  • usersテーブルは初回のデータ投入以降増えないので、初回に全部Go実装上にキャッシュしてGoで返す
  • 最終ログイン日時もユーザ毎にGo上で記録しておき、Go上で返す
  • トップページは出力パターンが4パターンしかないので、4パターンの静的HTMLファイルを生成しておき、nginxでCookieの値を見てrewriteして静的ファイルを返す

それぞれの修正を適用するたびにアクセスログ応答時間を見て遅いリクエストを改善していく感じですね。

結果としてこのような対策になったので、今回MySQLのチューニングは殆どやってません。my.cnfの設定も大した設定は追加してないし、インデックスも結果的には何も追加しませんでした。

なお、プログラム以外の具体的な変更内容はnetmarkjp先生がブログに詳しくかかれているのでそちらをご参照ください。

便利情報

いくつかピックアップ

BitBucketは無料でプライベートなgitリポジトリを作れる

情報をもらさずにリポジトリを共有できて便利

BitBucketのプライベートなgitリポジトリと連携できるCIはWerckerが便利

wercker、便利ですよ!今回使ってないけど。boxにwercker/golangを使えばGo1.3系をにも対応してます。

Vimで同じファイル複数人で開きたいけどreadonlyでいい場合は-Rオプションが便利

vim -Rで最初からreadonlyで開くことができるので邪魔せずに便利

mysqltuner.plが便利

MySQLのざっとしたチューニングはこれを少し参考にしてます。

curl http://mysqltuner.pl > mysqltuner.pl
perl mysqltuner.pl

でも今回は殆ど使わなかった。

iotopコマンドが便利

disk ioを発生させているプロセスが何かわかります。

yum install -y iotop
iotop -o
dstatのオプションは-tlamp -N loが便利

今回は1台構成でloしか使わないので-N loをつけると便利です。

yum install -y dstat
dstat -tlamp -N lo

loの通信量が多くなれば、おそらくたくさん捌けてるんだな(スコアがあがるかもな)と判断できます。

Goのつらかったこと

いくつかピックアップ

経験が浅い

基礎的なことを把握してなかった。例えばinit()ってどこでどう呼ばれるのか知らなかった。

使えるプロファイラがない

pprofはCPU時間ベースのプロファイリングやchannelによるblock頻度を出力できるものの、Go以外の理由(mysqlなど)で待ちになった場合も含めて簡単にプロファイリングする術を見つけられませんでした。

なんとかNitroなるものを見つけてこれをtimer代わりにStepで調査してたのですが、Goroutineを使いはじめると破綻するし、アクセスが増えた場合の調査が難しいので結局あまり使えず。いいソリューションないですかね。

まとめ

よく言われる「推測するな、計測せよ」ですね。
dstatやtopを見てると計測してる気になるんですが、計測すべきはスコアに直結する応答時間でした、って感じです。

*1:作戦会議という名の飲み会

*2:login_logは最初からデータが入っているのでそのデータもキャッシュしておく必要がある

DockerでPublic JNetHack serverを立ててみた

Dockerfileの練習も兼ねて、DockerでPublic JNetHack serverを立ててみました。UTF-8対応のtelnetクライアントを用意して、

telnet nethack.matsuu.net

JNetHackをプレイできます。全プレーヤー統一ランキング機能があるみたいです。
詳しくはこちら → https://matsuu.net/nethack/

Docker環境があれば誰でもPublic JNetHack serverを用意できます

Docker Hubに登録したので、誰でもサーバを用意できます。

docker run --detach --publish=23:23 matsuu/jnethack-server

同じインスタンスを使っている限りはアカウントとセーブデータは残ります。

詳しくはこちら → https://github.com/matsuu/docker-jnethack-server

手元でこっそりプレイするためのDockerfileも用意しました

こちらもDocker Hubに登録したのですぐにプレイが可能です。

docker run -it matsuu/jnethack

毎回上記コマンドで起動するとランキングが保存されないのでよしなに頑張って下さい。

詳しくはこちら → https://github.com/matsuu/docker-jnethack

nginx-1.7.1でsyslogにログを飛ばせるようになったので試してみた

nginxのアクセスログやエラーログをsyslogに直接飛ばす機能は商用版のNGINX Plusでのみ提供されていたのだが、1.7.1でオープンソース版にもその機能が取り込まれた。

CHANGES

Changes with nginx 1.7.1                                         27 May 2014

    *) Feature: the "error_log" and "access_log" directives now support
       logging to syslog.

早速試してみた。

docker-nginx

syslogサーバのホスト名は仮にlogserverとする。

Dockerfile
FROM centos:latest
ADD nginx.repo /etc/yum.repos.d/
RUN yum install -y nginx
ADD access_log.conf /etc/nginx/conf.d/
EXPOSE 80
CMD ["/usr/sbin/nginx", "-g", "daemon off; error_log syslog:server=logserver,facility=local2 notice;"]
nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=0
enabled=1
access_log.conf
access_log syslog:server=logserver,facility=local1 main;

具体的な書式は公式のDocumentationを参照

docker-rsyslog

syslogを受けるサーバはこんな感じか。

Dockerfile
FROM centos:latest
RUN yum install -y rsyslog
ADD remote.conf /etc/rsyslog.d/
CMD ["/sbin/rsyslogd", "-c5", "-n"]
remote.conf
$ModLoad imudp
$UDPServerRun 514
$AllowedSender UDP, 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16

local1.* /var/log/nginx_access_log
local2.* /var/log/nginx_error_log

AllowedSenderで0/0が書けなかったのでなんかダサい。もっと良い書き方ないものか。

動作確認

アクセスログ

Jun  3 10:53:33 c65d458cb3e9 nginx: 127.0.0.1 - - [03/Jun/2014:10:53:33 -0400] "GET / HTTP/1.1" 200 612 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.13.6.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2"

エラーログ

Jun  3 10:53:23 c65d458cb3e9 nginx: 2014/06/03 10:53:23 [notice] 23#0: start worker processes
Jun  3 10:53:23 c65d458cb3e9 nginx: 2014/06/03 10:53:23 [notice] 23#0: start worker process 25

いいじゃないか、と思うでしょう。しかしsyslogには1行あたりの文字数制限があるため、長いログだとお尻が途切れて残念なことになる。

Jun  3 11:42:42 c65d458cb3e9 nginx: 127.0.0.1 - - [03/Jun/2014:11:42:42 -0400] "GET /12345678901234(中略)012345678

syslog自体は2048文字あたりが上限になるようだが、手元で試した限りは2043文字が上限になった。このあたりの詳細は調べてない。

nginxの派生で独自にsyslog対応されているTengineでも試したが、2043文字あたりが上限になるのは同じだった。syslogの制約だからそりゃそうか。

まとめ

ログをコンテナ内に蓄積しないことでよりImmutable Infrastructureっぽくなるし、1コンテナ1プロセスを実現できていいのだがsyslogには文字数制限があるので注意。

ちなみにnginxから直接fluentdに飛ばせるnginx-fluentd-moduleも試したのだが、受信側fluentdにfluent-plugin-udpが必要なのはまぁ良いとしても、記号などのエスケープ処理周りが怪しい感じで若干微妙だった。こちらもその内紹介できればと思う。

追記

オープンソースになったFC2ブログをDockerで構築してみた

FC2ブログがオープンソースになったと聞いたので、Dockerfileの作成練習も兼ねてDockerで構築してみた。ソースはこちら。

https://github.com/matsuu/docker-fc2blog/

ベースOSとしてCentOS版とUbuntu版を用意した。

工夫したこと

  • Link Containerを使ってMySQLApacheを接続している
  • できるだけ環境変数でパラメータを渡せるようにした
  • できるだけDockerfileファイルにすべて収まるようにした
  • 複数のApache/MySQLが起動してもできるだけ大丈夫なように調整(かぶるのは外向けの80番ポートのみ)
  • ここ数日で身につけたノウハウをすべて注ぎ込んでみた

作ってみてわかったこと

  • FC2ブログのdomain(Cookie)周りがアレな実装なのでドメイン名を渡す必要があってアレ
    • HTTP_HOSTを使うようにした
  • ブラウザで初期設定投入後/admin/install.phpを消す必要があるがdockerで自動化しにくい
  • Dockerfileに全部詰め込むのなんとかなる

改善が必要なところ

  • セキュリティを考慮してmysql_secure_installを実行したい
  • ログ周りをsyslogかfluentdに吐くようにしたい
  • fc2blogはMySQLのMaster-Slaveに対応してるようなので対応する
  • Nginxに対応させたい
  • phpのセッションをmemcachedに食わせ、ロードバランサも用意してスケールアウトしたい
  • クラスタ構成のCoreOSでfleetを使ってウハウハしたい
    • fleet経由で起動できるようにしたがetcdを活用できてない
  • Apache(ブログ部分)だけ更新する手段を用意する
  • テストする仕組みを考える
  • プロセス監視、サービス監視
  • Gentoo版をまだ用意してない
    • 用意した

さくらのクラウドでCoreOSを動かしてみた

最近になってようやくDockerに目覚めまして、本番環境にDockerを使った場合の監視方法などを模索している今日このごろ。

ちょうどオープンソースカンファレンスさくらのクラウドの2万円分無料クーポンをもらった*1ので、さくらのクラウドGentooベース(のChromeOSベース)で有名なCoreOSを載せてDocker環境を構築してみた次第。さくらさんありがとう!ありがとう!ありがとう!

どうすればCoreOSを構築できるか

さくらのクラウドではKVM/QEMUを使用しており、CoreOSはQEMU用イメージを用意しているものの、ホスト側を操作できるわけではないのでこの方法は取れない。

そこでInstalling CoreOS to Diskを参考に構築することにした。

CoreOSを起動するサーバをまず用意する

さくらのクラウドDHCPIPアドレスが取得できず、またCoreOSのcoreユーザにはパスワードが設定されていないため、Installing CoreOS to Diskの手順でそのまま構築するとSSH、コンソールのどちらからもアクセスできなくなってしまう。

そこでまずIPアドレスを決定するためにブランクディスクでサーバを作成する。

作成後、NICタブを押して以下の4つを控えておく。

また、ディスクタブでHDDを取り外す。

Ubuntuサーバを用いてDiskにCoreOSをインストール

つづいてUbuntuでサーバを作成。先ほど取り外したディスクを接続して起動。手順はInstalling CoreOS to Diskのとおりだが、さくらのクラウドに合わせて適宜読み替え。

wget https://raw.github.com/coreos/init/master/bin/coreos-install
chmod +x coreos-install
sudo ./coreos-install -d /dev/vdb
cat > cloud-config.yml <<EOF
#cloud-config.yml

ssh_authorized_keys:
  - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC0g+ZTxC7weoIJLUafOgrm+h...(ssh公開鍵を記述)

write_files:
  - path: /etc/systemd/network/10-static.network
    content: |
      [Match]
      Name=ens*

      [Network]
      Address=(IPv4アドレス)/(ネットマスク)
      Gateway=(ゲートウェイ)
      DNS=(推奨ネームサーバ1)
      DNS=(推奨ネームサーバ2)
EOF
sudo mount /dev/vdb6 /mnt
sudo cp cloud-config.yml /mnt/
sudo umount /mnt
CoreOSを起動する

ここまでできたら一旦Ubuntuサーバの電源を落として20GBの追加ディスクを取り外し、CoreOSサーバに接続しなおして起動。

ssh core@(IPv4アドレス)

で接続すればok。

   ______                ____  _____
  / ____/___  ________  / __ \/ ___/
 / /   / __ \/ ___/ _ \/ / / /\__ \
/ /___/ /_/ / /  /  __/ /_/ /___/ /
\____/\____/_/   \___/\____//____/
core@localhost ~ $ 

ヒャッホーイ!

まとめ

*1:実はもらったクーポンを紛失したので中の人に再発行してもらった

Mac Pro(Late 2013)を火鉢に見立てて暖を取る方法

Appleの初売りに並んでる皆様、寒い中お疲れ様です。寒いですね!ツライですね!

そんな時は最新のMac ProのCPUをぶん回せば暖かくなるかもしれませんね!
え?インターネット接続環境がないからベンチマークソフトをダウンロードできない?大丈夫、Mac OS Xに標準で含まれているソフトウェアでお手軽にCPUをぶん回すことが可能です。

  • Finder→アプリケーション→ユーティリティ→ターミナル
  • CPUが論理12コアの場合
openssl speed -multi 12
  • CPUのコア数がわからない場合
openssl speed -multi `getconf _NPROCESSORS_ONLN`

これでしばらくはCPU負荷がガンガンかかり、Mac Pro上部の排気口がほのかに暖かくなりますよ!良かったですね!良かったですね!
もしかしたらアップルストアの店員さんがMac Proを用意してくれるかもしれませんね!ご期待ください!

ご参考

きっかけはTwitterから。

yes > /dev/nullでもok。ただ論理CPU1つ分しか負荷がかからないので論理CPUの数だけ起動が必要となる。

どんどんプロセスを立ち上げるのでこれはfork bombに近い。やっちゃダメー。

openssl speedはOpenSSLが対応するアルゴリズムの処理速度を計測するベンチマーク。-multiで指定された数だけパラレルに実行されるのでカジュアルにCPUに負荷をかけられる。これは素晴らしい。