wataメモ

日々のメモをつらつらと書くだけ

次世代 Web カンファレンスを見てみた

 次世代 Web カンファレンスを見ての感想。

nextwebconf.connpass.com

セッションについて

 資料は一切なし、単なるトークのみ。企業の宣伝とかもない。 今回見たのは以下のセッション。

  • server_perf
  • server_arch
  • security
  • http2
  • monitoring

 どれも登壇者が一線級の方々で話はとても興味深く、色々勉強になった。 こんなカンファレンスが無料で行われていて、企業や宣伝が一切ないのは本当にすごいと思った。 各セッションで個別に議論されている技術をすべて組み合わせ、今のシステムが構築されることになる。 範囲として、プロトコル、ネットワークからアーキテクチャ、セキュリティ、監視運用まですべてだ。

server_perf

 途中からになってしまったので、あまり見ることが出来なかった。 結論としてはprometheusよく出来ているよということとgRPC最高ということらしい。

キーワード

security

 セキュリティ周りについては全然情報を追っていなかったのもあり、オリジンをどのように扱っていくかで初めて聞く単語もあった。 正直そこまできっちり意識できていなかったので今後はそういうところも最初から出来るようになっていきたい。 バグハンターという言葉はあまり耳慣れなく、そういうのもあるんだなぁと関心。

キーワード

  • SRI(Subresource integrity)
  • CSP(Content Security Policy)

http2

 仕様策定の話や、h2o等のサーバ側の実装者視点での話が聞けてとても面白かった。 登壇者がすごいこともあり、話の内容も濃くセッションオーナーの方の進め方、質問内容も素晴らしかった。 QUICというプロトコルがハイパージャイアントだからこそ実現出来ることなんだなと改めて認識した。 プロトコル的には通信は張りっぱなしの双方向になっていくとは思っているのでhttp2を足がかりに、面白くなっていくだろう。 一方、UDPやバイナリプロトコルになっていったりすることで、学習コストが上がったり、telnetで簡単にデバッグ出来ない等の指摘もあった。 個人的にはエンジニアの敷居は高くても良いと思っている。 その方が技術力がある人が価値を出せるし、評価される世の中になるのではと考えているからだ。

キーワード

  • HTTP/2
  • TLS1.3
  • QUIC

monitoring

 サーバ監視系や仕事でも長年やっていたのもあり、非常に気持もわかる(夜寝たい等)し、アプリエンジニアとの住み分けも難しいのも共感出来た。 アーキテクチャプロトコルが変わってくることによって監視についても色々考えていかないといけないことが多く、そこで必要とされている技術がプロダクトで使われる技術だったりするから面白い。 監視サーバを監視するシステムも必要になってしまう。 今後プロトコル的に通信張りっぱなしになったらどう監視するのか、クライアントサイドの監視をどうするのか等、フロント界隈の群雄割拠よりは着実に進められる非常に興味深い分野だと感じた。 この辺はデプロイやオートスケールなどとも絡んできて、他と同じように監視という垣根が曖昧になっていくだろう。

キーワード

まとめ

 今までカンファレンスを見て来て一番面白かったと感じた。 その理由としては企業としてではなく個人としての意見ということもあり本当に思っていることを話してくれたと思うし、未来のことを話しているのもワクワクさせる。 そして極めつけはセッション内容のレイヤーの幅広さだ。 一部に特化して行われる事が多いが、今回は様々なレイヤーの話したいっぺんに聞けて、1日があっという間に感じた。 カンファレンスとしては企業には得なことは何一つ無いが、エンジニアとしては非常に価値あるカンファレンスだった。 こういうのがもっと開催されれば、日本のエンジニア界隈がもっと良くなるのではないだろうか。

メタプログラミングRuby第2版読了

 タイトルから面白そうとメタプログラミングRuby第2版を読んだ。

www.amazon.co.jp

お勧め対象者

 読んでみると非常に丁寧にRubyの言語仕様を解説してくれていた。 なんとなくで理解していた事や、ちゃんと調べていなかった部分が色々と晴れた。 Rubyを勉強しようと考えている人には間違いなくお勧めの1冊。 特に自分の様にJavaの知識でRubyの挙動を補間しようとしている人の勘違いを正してくれるので、そういう人にもお勧め。

 第2版ということで、Rubyのバージョンが上がったことにも対応している。 最初は1.8だったのが2.2まで対応で一部Refinementsで書き換えられている。

面白かった部分

Ruby on Railsの歴史

 Rubyの言語仕様的な解説部分も面白かったが、個人的にありがたかったのはRuby on Railsの歴史に軽く触れていることだ。 Ruby on Railsというある意味Web開発における人類の英知の集結がどのように進化していったのか。 本では明記されていないが、恐らくRubyという言語にも多大な影響を与えたことも容易に想像出来る。 こういう歴史的な話はきちんと技術を理解する上で必要なことだと考えているのでありがたい。

師匠の名言

 7章のエピローグの師匠のセリフがとても良かった。 弟子が「メタプログラミングの真髄とは何なんですか?」と聞いたことに対して最終的に 「メタプログラミングというものなど存在しない。すべてはただのプログラミングじゃ。」と答えたことだ。 こういうことを言えるようになりたいものだ。

踏み台サーバを作ってみた

 まだ全然足りないが、踏み台サーバを構築するプロビジョニングを作り始めてみた。 最初はbastionを作っていて、そこからサーバのプロビジョニングもあった方が良いなと始めて見た。 basionについてはRuby on Railsでサービスを作ってみたpart6で「踏み台サーバ」として簡単に紹介している。

 AWSを使っていて、良く踏み台サーバは作っているが意外と面倒くさい。 AMI化して共有しても良いのだが、「秘伝のAMIになるのも嫌だ」ということでItamaeで作成。 今は書きなぐっている状態なので、もう少しちゃんとcookbooks配下を整理して、リファクタリングしないといけない。

 もう少しちゃんと出来てきたら、全体をちゃんとこのメモでも記載する予定なので今回は証明書作成周り部分のメモ。

証明書の作成

 bastionを動かすためにnginxでhttpsを受けるように設定し、そこへアクセスする為にクライアント証明書が必要にする。 その為に以下を作成する。

  • CA用秘密鍵
  • CA用証明書
  • サーバ用秘密鍵
  • サーバ用公開鍵
  • サーバ用証明書
  • クライアント証明書

 基本opensslコマンドによって生成するが、基本対話式なのでここを自動化する必要があった。 基本パスワード周りなのでオプションで指定してく。

CA用秘密鍵の作成

# 対話式
openssl genrsa -des3 -out ca.key -rand rand.dat 2048
# 自動化
openssl genrsa -des3 -passout pass:#{pass} -out ca.key -rand rand.dat 2048

CA用証明書の作成

 パスワード以外にも色々な情報をsubjオプションで指定する。

# 対話式
openssl req -new -x509 -days 365 -key ca.key -out ca.crt
# 自動化
 openssl req -new -x509 -days 365 -key ca.key -passin pass:#{pass} -out ca.crt \
  -subj "/C=JP/ST=Tokyo/L=Chiyoda-Ku/O=/OU=/CN=/"

サーバ用秘密鍵の作成

# 対話式
openssl genrsa -des3 -out server.key -rand rand.dat 2048
# 自動化
openssl genrsa -des3 -passout pass:#{pass} -out server.key -rand rand.dat 2048

サーバ用公開鍵の作成

# 対話式
openssl req -new -key server.key -out server.csr
# 自動化
openssl req -new -key server.key -passin pass:#{pass} -out server.csr \
  -subj "/C=JP/ST=Tokyo/L=Chiyoda-Ku/O=/OU=/CN=#{node[:cert][:common_name]}/"

パスフレーズ削除

cp server.key server.key.bak
openssl rsa -in server.key.bak -passin pass:#{pass} -out server.key

サーバ用証明書の作成

 sign.shの部分はexpectを使って自動化。 生成にはautoexpectを利用。

# 対話式
mod_ssl-#{MOD_SSL_VER}/pkg.contrib/sign.sh server.csr
# 自動化
expect -f /home/webservice/make_cert.exp /home/webservice/mod_ssl-#{MOD_SSL_VER}/pkg.contrib/sign.sh server.csr

クライアント証明書の作成

 このシェルはbastion側にある。 これは自動化された方だけ紹介。

bastion/ccert/create
openssl genrsa -des3 -passout pass:$PASS -out ${USERS_DIR}/${USERNAME}.key 2048
openssl req -new -key ${USERS_DIR}/${USERNAME}.key -passin pass:$PASS -out ${USERS_DIR}/${USERNAME}.csr \
  -subj "/C=JP/ST=Tokyo/L=Chiyoda-Ku/O=/OU=/CN=${USERNAME}"
openssl x509 -req -days 1095 -passin pass:bastion -in ${USERS_DIR}/${USERNAME}.csr -CA $SSL_CERTS_DIR/ca.crt -CAkey $SSL_PRIVATE_DIR/ca.key -CAserial $SSL_DIR/serial -CAcreateserial -out ${USERS_DIR}/${USERNAME}.crt
openssl pkcs12 -export -clcerts -passin pass:$PASS -passout pass:$PASS -in ${USERS_DIR}/${USERNAME}.crt -inkey ${USERS_DIR}/${USERNAME}.key -out ${USERS_DIR}/${USERNAME}.p12

rails_best_practicesの指摘を修正してみた

 今回はrails_best_practicesの指摘を修正してみる。 survey!に掛けてみたところ23個の警告が出た。

インストール

 developmentグループのところにgemを追加してbundle install。

Gemfile

gem 'rails_best_practices'

実行

 今回はhtmlに出力させたいので以下で実行。

bundle exec rails_best_practices -f html .

f:id:wata_htn:20151011171553p:plain

警告一覧

Filename Line Number Warning Message
app/views/survey/_result_question.html.slim 14 move code into model (q use_count > 2)
app/views/kaminari/_paginator.html.slim 6 move code into model (page use_count > 2)
config/routes.rb 7 needless deep nesting (nested_count > 2)
app/helpers/answer_helper.rb 1 remove empty helpers
app/helpers/question_helper.rb 1 remove empty helpers
app/helpers/survey_helper.rb 1 remove empty helpers
app/helpers/welcome_helper.rb 1 remove empty helpers
app/models/free_choice.rb 2 remove unused methods (FreeChoice#value_data)
app/models/surveys.rb 5 remove unused methods (Surveys#my_collab)
app/models/multiple_choice.rb 10 remove unused methods (MultipleChoice#value_data)
app/models/date_choice.rb 12 remove unused methods (DateChoice#value_data)
app/models/question.rb 21 remove unused methods (Question#resize_image_url)
app/models/single_choice.rb 12 remove unused methods (SingleChoice#value_data)
app/views/question/_single_choice.html.slim 1 replace instance variable with local variable
app/views/question/_single_choice.html.slim 3 replace instance variable with local variable
app/views/question/_multiple_choice.html.slim 1 replace instance variable with local variable
app/views/question/_multiple_choice.html.slim 4 replace instance variable with local variable
app/views/question/_date_choice.html.slim 1 replace instance variable with local variable
app/views/question/_date_choice.html.slim 8 replace instance variable with local variable
app/views/question/_free_choice.html.slim 2 replace instance variable with local variable
app/controllers/survey_controller.rb 46 simplify render in controllers
app/controllers/survey_controller.rb 62 simplify render in controllers
app/views/welcome/index.html.slim 13 remove trailing whitespace

move code into model (q use_count > 2)

モデルに条件を寄せたほうが良いということ。 今回はdecorator側へ移動。 Kaminari Themesのテンプレートにも指摘があったが今回はexclude指定することにした。

before

app/views/survey/_result_question.html.slim

- if q.single_choice? || q.multiple_choice? || q.date_choice?

after

app/decorators/question_decorator.rb

def choice?
  single_choice? || multiple_choice? || date_choice?
end

app/views/survey/_result_question.html.slim

- if q.choice?

needless deep nesting (nested_count > 2)

 ルーティングのネストが3つになっているのがまずいらしい。 ここで言うと答え(answer)は質問(question)に属しており、アンケート(survey)に属しているわけではないということらしい。

before

config/routes.rb

resources :survey do
  resources :question, only: :show do
    resources :answer, only: [:create, :update]
  end
end

after

config/routes.rb

resources :survey do
  resources :question, only: :show
end
resources :question, only: :show do
  resources :answer, only: [:create, :update]
end

 確かに書いている時にも3つはやり過ぎかなとは思ったが・・・。 しかし、これを変えると基点テーブルが変わるのでActiveRecordの書き方も変えないといけない。

remove empty helpers

空のヘルパーはロード時間もかかるし勿体無いということだ。 指摘の内容のソースを実行して削除。

Dir.glob("app/helpers/**/*.rb").each do |file|
  if !File.read(file).index('def')
    FileUtils.rm file
    FileUtils.rm_f file.sub("app/", "test/unit/").sub(".rb", "_test.rb") if File.exists?("test")
    FileUtils.rm_f file.sub("app/", "spec/").sub(".rb", "_spec.rb") if File.exist?("spec")
  end
end

remove unused methods

 タイトルの通り使われていないメソッドの削除。

replace instance variable with local variable

 partialはインスタンス変数を参照せずに、localで変数を渡したものだけにした方が良い。 明示的に指定することで何が必要かを明確に出来るメリットが有る。

simplify render in controllers

 renderを簡潔に書けということ。

before

app/controllers/survey_controller.rb

render action: 'edit'

after

app/controllers/survey_controller.rb

render :edit

remove trailing whitespace

 不要な行末の空白を削除しろということ。 テーブルで空のヘッダがあったのを以下のように記述していたのでパイプ部分を削除。

before

th.two.wide.computer.only
  | 

after

th.two.wide.computer.only

結果

f:id:wata_htn:20151011171613p:plain

まとめ

 ベストプラクティスがツールでチェック出来るのは便利で、Railsを学ぶ上では非常に良いと感じた。 そして知っていたとしてもチェックの意味もあるのでお勧めだ。

AWS LambdaのScheduled EventでEC2インスタンスの定期停止、起動してみた

 AWS Lambdaで「Scheduled Functions (Cron)」というのが増えてcronのように定時実行が追加された。 試してみようと思って、題材としてはちょうどインスタンスを定期的起動、停止をする必要があったのでそれにしてみた。 今まではJenkinsで行っていたが、それだけの為にはJenkinsは要らなくなる。

Lambdaソース

 まずはLambdaのソースは以下を用意した。

EC2インスタンス起動

gist13e268a8040d8d008ece

EC2インスタンス停止

gistf8292b79ebd68b8b98e8

Scheduled Functions (Cron)

設定

Functionsの「Event sources」タブで「Add event source」をクリックしてダイアログから設定する。

f:id:wata_htn:20151010193703p:plain

f:id:wata_htn:20151010193727p:plain

「Schedule expression」にcronの様な設定を入れるのだが、数が1つ多く6つになっている。 ドキュメントを見ると以下のようになっている。

Field Values Wildcards
Minutes 0-59 , - * /
Hours 0-23 , - * /
Day-of-month 1-31 , - * ? / L W
Month 1-12 or JAN-DEC , - * /
Day-of-week 1-7 or SUN-SAT , - * ? / L #
Year 1970-2199 , - * /

最後の「年」指定が増えている。 うるう年とか年を意識する時に使うイメージなのだろうか。

形式

 基本crontabの書き方と同じなのだが、「?」が追加されている。 「Day-of-month」か「Day-of-week」のどちらかは「?」にしなければならない。

タイムゾーン

 時間の指定はUTC指定となる。 日本時間(JST)とは9時間ずらす必要がある。

イベント

 Lambda側に渡されるイベントは以下。 「time」をハンドリングして、処理を変えるは出来そうだ。

{
    "id": "bd142023-9806-4b1d-9957-acea12a09f89",
    "detail-type": "Scheduled Event",
    "source": "aws.events",
    "account": "XXXXXXXXXXXX",
    "time": "2015-10-10T05:15:00Z",
    "region": "ap-northeast-1",
    "resources": [
        "arn:aws:events:ap-northeast-1:XXXXXXXXXXXX:rule/stop_ec2_instance"
    ],
    "detail": {}
}

まとめ

 インスタンスがいらないのは良いが、時間を修正したい場合にこのままだとAWS Consoleにログインする必要がある。 簡単に修正出来るようにしないと色々な人が修正出来ない。 そこでインスタンスを立ててしまっては意味が無いので、S3とLambdaとかAPI Gatewayを組み合わせて簡単な画面を用意すれば良いかも。

起動時にELBに再登録するシェルを簡単にインストール出来るようにしてみた

 別に大したことではないのだが、最近設定することになって面倒だったので一発で出来るようにしたかった。元ネタはクラスメソッド株式会社のブログの「EC2を停止して開始した時はELBに再登録する」。 開発環境など、夜中はインスタンスを落としておきたい場合があり、朝インスタンスを起動させた時にELBから検知されないことがある。 その場合の対処として、EC2インスタンスをELBから外して、再登録するという手順がある。 当然これを毎回手でやるのは面倒なので、起動スクリプトに仕込んでしまおうと言うのがこのスクリプトだ。 ブログの手順だとシェルファイルを3つ作って、権限を付けて、chkconfigして・・・と手順が若干多いので簡単にしたいと考えた。

 インストールの仕方としてはgistに登録したのでEC2インスタンス側からはcurlでダウンロードしたのをシェルに流し込んで終了。その前にELB名をNAME環境変数に入れておく。

export NAME=elb_name
curl https://gist.githubusercontent.com/wata-gh/2a2ce9357967e2736391/raw/a143ddd68c6b858ed34881ff76b1940fa1553a95/ec2-elb-re-register-installer.sh | sh

 もちろんこのシェルを実行するには権限とAWSコマンドラインインターフェースが必要。

クックパッドのインターンシップ講義資料のプログラミングパラダイム編をやってみた

 今回はクックパッドの「夏の技術職インターンシップ講義資料公開」を見て「五日目 プログラミングパラダイム編(青木峰郎)」をやってみた。 開発者ブログで見て、非常に面白そうだったからだ。

techlife.cookpad.com

 合間を見つけてちょこちょこ3,4時間ほどやったが、発展課題1、2まではいけず。 こういう事をインターンシップ講義でやってしまうところは凄すぎる。 自分も言語処理系は触ったことがなかったので、聞きかじった知識しか無かった。(まあ、今もだが) なので実際にAST(Abstract Syntax Tree)を見ながら実装を埋めていくのは楽しく、そしてより具体的にイメージが出来るようになった。 バイナリはMac OS X Yosemite用なのでMacを持っている人は興味があればやってみることをお勧めする。

 このブログでもいくつかメモを書いてきたオープンソースの公開もそうだが、こういった講義資料も公開してくれるのは非常にありがたい。