CubicLouve

Spring_MTの技術ブログです。https://github.com/SpringMT (http://spring-mt.tumblr.com/ からの移転)

JapanContainerDays v18.12で「1人でできる
Docker Kubernetes(GKE)を
使った新規サービス立ち上げ」というタイトルでRailsアプリをGKE上で運用した事例の紹介をしました

JapanContainerDays v18.12 で「1人でできる
Docker Kubernetes(GKE)を
使った新規サービス立ち上げ」というタイトルでRailsアプリをGKE上で運用した事例の紹介をしました。

運営の皆様、発表する機会をいただき本当にありがとうございました!
また、スタッフ、スポンサーの皆様お疲れ様でした!
発表資料は以下です。

Rails特有の話もしていて、ちょっと混乱させてしまったかもしれません >_<
今回話せなかった、分析環境周りの構築や、サービス運用に必要な設定データ(俗に言うマスターデータ)の管理についても機会があればどこかで話せれば話したいなあと思っています。

参加メモ(随時更新中)

1日目

本番環境のKubernetesマニフェストに 最低限必要な 7 のこと @ Japan Container Days v18.12 / jkd1812-prd-manifests - Speaker Deck

この発表を聞いて、BachendConfigを初めてしりました。。
早速導入してみました。

BackendConfig Custom Resource  |  Kubernetes Engine  |  Google Cloud

2日目

2日目は保育園からの呼び出しがあったので、途中で離脱してしまいました >_<

Cloud Native Deep Dive@JKD

Cloud Native Deep Dive@JKDの取り組みが本当によかったと思います。
kubernetes周りで色々ディスカッションできて、今まで悩んでいたことに対して解決策が見えてきました。
こうした取り組みが他のカンファレンスでもあるといいですね。

参考資料(随時更新中)

ヘルスチェック

Kubernetesヘルスチェックの使い方 - Ian Lewis

カスタムメトリクス

Autoscaling Deployments with Custom Metrics  |  Kubernetes Engine Tutorials  |  Google Cloud

Creating Custom Metrics  |  Stackdriver Monitoring  |  Google Cloud

GitHub - GoogleCloudPlatform/k8s-stackdriver

Google StackdriverでKubernetesのモニタリングに挑戦してみよう (3/3):CodeZine(コードジン)

HPA

Horizontal Pod Autoscaler Walkthrough - Kubernetes

autoscalerの挙動

readyのpodの扱い

kubernetes/replica_calculator.go at 9e9c4144600538fb3032bf8e4a070e6570112ac1 · kubernetes/kubernetes · GitHub

Podの終了

Kubernetes: 詳解 Pods の終了 - Qiita

SecurityContext周り

Using sysctls in a Kubernetes Cluster - Kubernetes

その他今まで参考にした資料

12-Factor Rails App and Kubernetes - Speaker Deck

コンテナ未経験新人が学ぶコンテナ技術入門

今話題のいろいろなコンテナランタイムを比較してみた [Docker Meetup Tokyo #26発表レポート]

Operating Rails in Kubernetes - Speaker Deck

鯨物語~Dockerコンテナとオーケストレーションの理解

Beyond the Twelve-Factor App

【Fixed】 docker official rubyの中で、2.5.1-stretch、2.5-stretch、2-stretch、stretch、2.5.1、2.5、2、latest のtagが付いているイメージにおいて、OSがdebian stretchではなくdebian jessie でビルドされていた

期間

2018/6/6 10時頃 (JST) 〜 2018/6/7 3:00頃 (JST)

対象

docker official rubyの中で、2.5.1-stretch2.5-stretch2-stretchstretch2.5.12.52latest のtagがついているイメージ

https://hub.docker.com/r/_/ruby/

状態

OSがdebian stretchではなく、debian jessieになっていた。

github.com

期間中に対象のイメージを使ってビルドしている場合、今日の最新のイメージ使ってビルドし直しをしましょう。

Rubyのお気持ちを読む

Rubyのお気持ちが分からないことがたまにありますよね。

このスクリプトで最終的になにが表示されるでしょうか。

class A
  attr_accessor :foo
  def bar
    foo = baz(foo)
    foo
  end

  def baz(v)
    v
  end
end

a = A.new
a.foo = 1
p a.bar # ここで表示される値は?

答えは 1 ではなく nil です。

barメソッドの foo = baz(foo) において、foo =foo=メソッド呼び出しではなく、ローカル変数 foo への代入とみなされて、 ローカル変数fooが新たに定義され、そのローカル変数foobazメソッドに引数と渡されるため、最終的にnilが表示されることとなります。

ローカル変数の定義はリファレンスマニュアルにも明記されています。

変数と定数 (Ruby 2.4.0)

ただ、こういうRubyの挙動を忘れてしまったときはどのように判断すれば良いのでしょうか?

そういうときはRubyVMの命令シーケンスを確認することでRubyの挙動を追うことが可能です。

RubyVMの命令シーケンスを取得する

RubyVMの命令シーケンスを取得するにはRubyVM::InstructionSequenceクラスを使います。

https://docs.ruby-lang.org/ja/latest/class/RubyVM=3a=3aInstructionSequence.html

今回試したスクリプトをsample.rbとして保存し、そのファイルを読み込んで命令シーケンスを出力させてみます。

出力させるには下記のスクリプトを実行します。

puts RubyVM::InstructionSequence.compile_file("./sample.rb", true).disasm

実行した結果はこんな感じになります。

fooがローカル変数になる

これだけではわかりにくいので、実際にメソッド呼び出しがされる場合も見てみましょう。

class A
  attr_accessor :foo
  def bar
    test = baz(foo)
    test
  end

  def baz(v)
    v
  end
end

a = A.new
a.foo = 1
p a.bar

上記スクリプトの命令シーケンスはこんな感じです。

fooがメソッド呼び出しになる

わかりにくいので、diffを取ってみます。

gist.github.com

最初のスクリプトではローカル変数 fooが設定されていることが分かるかと思います。

Rubyの挙動で困ったときはVMの命令シーケンスを確認してみてはいかがでしょうか?

Macで自分のRubyのプロセスのrssを調べるには

bugs.ruby-lang.org

このチケットをみていて、Macで同じことをどうやるか?を考えてみました。

Macには/procがありません。

% ruby -rzlib -e'END{puts File.readlines("/proc/self/status").grep(/RSS/)}' -e'd=Zlib.gzip("data"); 100_000.times{Zlib.gunzip(d)}' 
-e:1:in `readlines': No such file or directory @ rb_sysopen - /proc/self/status (Errno::ENOENT)
    from -e:1:in `block in <main>'

なので、psコマンド経由でrssを取得します。

% ruby -rzlib -e'END{puts `ps -o rss= -p #{Process.pid}`.to_i}' -e'd=Zlib.gzip("data"); 100_000.times{Zlib.gunzip(d)}'
927852

(rssはデフォルトの単位はkB)

他にいい方法あるかな。。。

Array#samplesの実装を追う(途中)

candidates = [
  'hoge',
  'foo',
  'bar',
  'Sring_MT'
]

puts candidates.sample

のようなスクリプトでなぜか自分がよく当たるような気もしたので、Array#sampleの実装を追ってみた。

instance method Array#sample (Ruby 2.4.0)

source

メソッド定義場所はここ https://github.com/ruby/ruby/blob/trunk/array.c#L6258

sampleの実装はここ https://github.com/ruby/ruby/blob/trunk/array.c#L4802

特に乱数生成器のオブジェクトが指定されていなければ、random.cが使われます。 ruby/random.c at trunk · ruby/ruby · GitHub

sampleは下記マクロを呼び出して、ランダムなインデックスを返す。 https://github.com/ruby/ruby/blob/trunk/array.c#L4699

このマクロから呼び出されるのは、rb_random_ulong_limited https://github.com/ruby/ruby/blob/trunk/random.c#L1026

このrandom.cは MT19937 をベースにした擬似乱数生成を行う。

メルセンヌ・ツイスタ - Wikipedia

cpprefjp.github.io

random.cを追ってみる

Google SpreadsheetのJOINみたいなことがしたかったのでgoでコマンド作った

今まで改行された標準出力から、grepのOR検索するための条件を作るためにperlでゴニョゴニョしてました。

(他にもいい方法あるかな。。。)

% echo "test\ntest\ntest" | perl -e 'my @list; while (my $m = <>) {chomp($m); push @list, $m}; print join("\\\|", @list)'; echo
test\|test\|test

こんなときにGoogle SpreadsheetのJOIN関数みたいなことができば一発だなと思ってgoの勉強がてらコマンド作ってみました。

github.com

(すでにjoinコマンドは存在しているので、名前は結構やっつけでつけちゃいました。よい名前があればそれに変えます)

gs-joinを使うとこんな感じでできます。

% echo "test\ntest\ntest" | ./gs-join -d '\|'
test\|test\|test

まあ、goの勉強を始めて2日で作ったので中身は微妙なのです。。。

これからテスト書いたり、リファクタリングとかしていく予定です。

slack APIで自分がjoinしているチャンネル一覧取得

token取得

api.slack.com

レガシーなのでいつdisableになるかわからないですが。。。。

id取得

curl -s -XPOST 'https://slack.com/api/users.list?token=#{自分のToken}&pretty=1' | jq -r '.members[]|"\(.id) \(.profile.email)"' | grep '登録しているメアド' | cut -c 1-9`

publicなチャンネル取得

curl -s -XPOST 'https://slack.com/api/channels.list?token=#{自分のToken}&pretty=1' | jq -r '.channels[]|select(.is_archived =  "false")' | jq -r '"\(.name) \(.members[])"' | grep #{自分のID} | cut -d " " -f1

privateなチャンネル取得

 curl -s -XPOST 'https://slack.com/api/groups.list?token=#{自分のToken}&pretty=1' | jq -r '.groups[]|select(.is_archived =  "false")' | jq -r '"\(.name) \(.members[])"' | grep #{自分のID} | cut -d " " -f1