Quantcast
Channel: コネヒト開発者ブログ
Viewing all 376 articles
Browse latest View live

DockerとJavaScriptの付き合いかた

$
0
0

f:id:dachi023:20181220161955p:plain

こんにちは。エンジニアの安達 (@dachi_023) です。会社用アカウントとして @ry0_adachiを用意していましたが全然呟かなくなっちゃったので辞めました。複数アカウントの運用って面倒ですね...。はい、コネヒト Advent Calendar 2018の20日目はDockerとJSです。

まえがき

DockerfileにJS (とかCSSとかHTMLとか) のビルド処理を書いてコンテナ立ち上げてブラウザで見えるところまでの話です。

本記事では最低限これができていればそんなに遅くならないよねってものをいくつか書いています。コードは GitHubに上がってますのでそちらを見ていただいてもOKです。このコードは create-react-appで生成したものをビルドしてコンテナ上のNginxで公開するという簡単なものですが、実際にママリのProduction環境に投入したものもJSに限って見てみればやってることはほとんど一緒になったので、この手の問題はあんまり難しく考えないほうがいいんだろうな、というのが現状の結論です。

今回はやってませんがSSRする場合は他にも考慮すべき点がありそうなのでもうちょい複雑かもなと思ってます。

Dockerfileを書くときに気にしてること

めちゃくちゃ普通なんですけど一応書いておきます。

  • キャッシュをなるべく使えるようにする
  • イメージのサイズを小さくする

JS起因でDockerのビルドが遅いのはだいたいインストールとビルドのせいなのでキャッシュが効くべき時に効くのが大事そうです。あとはイメージサイズを小さくするためにどのイメージを使うかとか、ビルドの過程で使ったツールなどをイメージに含まないかとか、そういうのを意識してます。

たとえば

上記は GitHubに上げたDockerファイルですがこの12行だけでも気にしてることを満たせているはずです。

  • yarn [install]でキャッシュを効かせたいので実行前にCOPYしてくるのは package.jsonyarn.lockだけにして、ビルド時に使うものはその後にCOPYしてくる
  • multi-stage buildを使うことでnode_modulesやビルド前のファイルなどを最終イメージに残さない

実際にdocker buildした結果はこんな感じです。

キャッシュ無

$ time docker build -t dachi023/docker-create-react-app:test .
real    1m5.287s
user    0m0.375s
sys 0m0.249s

フルキャッシュ

real   0m2.172s
user    0m0.165s
sys 0m0.116s

一部キャッシュ (JSのコードを編集)

real   0m18.399s
user    0m0.229s
sys 0m0.147s

あとは $ docker run -itd --name docker-create-react-app -p 8080:80 dachi023/docker-create-react-app:testなどとやると起動までちゃんとするのでサクッと何かを作りたい時などにご活用ください。

まとめ

キャッシュが効いててイメージが軽ければ開発時のストレス減りそうだね、というお話でした。アプリケーションが複雑になっても基本この2つがブレないようにしていればいいのではないかと思ってます。Dockerチューニングでやれることはまだあるかと思いますが、まずは効き目のある部分からやっていきましょう!

明日は nkurodaさんの引っ越し話です!技術が絡んでくるかもしれないし絡まないかもしれません、ご期待ください! 👋


プロダクション環境ですぐに活かせそうなAWS re:Invent 2018のSageMakerアップデート5選

$
0
0

f:id:tatsushim:20181223233656p:plain

この記事はコネヒトアドベントカレンダーの23日目の記事です。 qiita.com

ざっくり言うと

  • 11月にSageMakerのお話で登壇したけど、12月のAWS re:Invent 2018でたくさんアップデートがあった
  • 既存機能の強化に留まらず、「データの準備」から「モデルの変換」もサポートされるようになり、SageMakerの守備範囲がグッと広がったアップデートだと感じた
  • この投稿はその中でもママリのプロダクションですぐに活用できそうな5つのアップデートについて内容をまとめたよ

こんにちは!

CTOの島田(@tatsushim)です。 先月11/1「AWS dev day」に登壇させていただきました。 そのときの資料はこちらです。

現場で用いたSageMakerについて発表させていただいたのですが、私の発表の翌月にre:Inventがあり、SageMakerも大きくアップデートがありました。

5つのアップデート

1. データ準備サポートツールの追加( Amazon SageMaker Ground Truth )

  • 「この画像は犬の画像であるか、そうでないか」を分類するタスクがあるとします。これを機械学習によって分類するためには、まずはじめに「この画像は犬ある」というラベルが付いた画像と「この画像は犬ではない」とラベルが付いた画像が必要です。
  • こうした状況で、データ(この例では画像)に対してラベル付けを支援するのがAmazon SageMaker Ground Truthで、利用するメリットは下記の2つです。
    • ①: ラベリングツールがAmazon SageMaker Ground Truthで提供されるため、ラベルをつけるツールの購入・自作・管理が不要
    • ②: S3にラベル付けしたいデータをアップロードして、Amazon SageMaker Ground Truthでラベルをつけると結果がS3にあがるため、データの管理が明確
  • また、一部のデータを人の手でラベル付けした上で、その元データから自動で付与するような機能も存在しています。

2. Gitのインテグレーション

  • SageMaker上でGitリポジトリを登録しておけば、ノートブックインスタンス起動時にリポジトリがgit cloneされるようになりました。
  • 今まではコンソールからGitを利用するか、Jupyter Notebookで書いたコードを手動でGit管理する必要がありましたが、JupyterLabのGit extension設定がデフォルトでされる形になるので、視覚的な管理が可能になりました。

3. 学習・推論用コンテナのアップデート

  • TensorflowコンテナがPython3に対応しました。
    • (日本語処理をしてる側からすると嬉しいアップデート!)
  • scikit-learnのコンテナが追加されました。
    • ただしほとんどのアルゴリズムで分散学習に対応してないため、学習は単一インスタンスで行うことになると思います。

4. 学習ジョブモニタリングのサポート

  • 学習時のモデルの精度をグラフ化できるようになりました。
    • 正規表現でルールを書いて、標準出力から精度を抽出する必要があります。
  • ビルトインアルゴリズムの場合は最初から設定されているので正規表現は不要です。
  • 注意点としては、1分おきのメトリクスになっている点です。現状の仕様ではこれは1分未満はできないそうです。

5. 推論時にGPUの部分的な利用をサポート( Amazon Elastic Inference )

  • GPUリソースをEC2やSageMakerのインスタンスに一部割り当てることができるサービスのようです。
    • (最初何言ってるかわからなかった)
  • イメージとしては、PythonでボトルネックになってるところをCythonで書くみたいな感じで、コードとしてGPUを使用する箇所を明記することで、そこだけGPUを利用してくれるようです。
  • こちらにサンプルコードがありますので、イメージとしてはこちらをご覧になっていただくのが良いかと思います。
  • 画像分類の推論をリアルタイムで処理したいニーズには便利です。

終わりに

他にも強化学習、DeepRacer、AWS Marketplace for Machine Learningなど触れたい部分はたくさんあるのですが、今回は比較的すぐに実応用可能なアップデートに絞って内容を共有させていただきました。
機械学習の分野でますます活用が増えていくであろうSageMakerには今後も注目ですね。
以上、島田(@tatsushim)がお送りしました!
今年も、ここまで1日も切らさずにコネヒトアドベントカレンダーは続いております。ここまで継続してくれているメンバーに感謝です。
明日は富田(@tommykw)さんのターンです!

Kotlin IDE Pluginに共通で定義管理できるplugin-common.xmlが出来ていた

$
0
0
f:id:tommy_kw:20181223172957p:plain

はじめに

本記事はコネヒト Advent Calendar 2018の24日目のエントリーです!

qiita.com

メリークリスマス!Androidエンジニアの富田です。今回はKotlin IDE PluginのKontributeに関する小話で、plugin-common.xmlが生まれてちょっとだけめんどくさい作業が減ったよという内容を紹介します。

Kotlin IDE PluginのKontributeって?

以下のようなCode InspectionIntentionなどの機能についてのKontributeを表します。 f:id:tommy_kw:20181223105545g:plaingithub.com

詳しい内容については割愛させていただきますが、Kotlin IDE PluginやKontributeについて興味を持った方はぜひ、しらじさんの下記資料をご覧ください! photos.google.com

Kontributeする上でここが煩わしかった

github.com

改めて上記のPRを見ていただくと、複数のplugin.xmlが存在することに気づきます。Kotlin IDE Pluginを開発する上でIntelliJ IDEAとAndroid Studioに対応しなければならないため設定情報(今回はInspection情報)を複数のplugin.xmlに記述する必要がありました。

gist.github.com

以前は上記の設定を下記全てのplugin.xmlに追加していました。ファイル数が多いため自動で追加するGradleタスクがないのかなと探してみたものの、結局なさそうだったのでどうしたものかなと悩んでいました。

  • plugin.xml
  • plugin.xml.173
  • plugin.xml.181
  • plugin.xml.183
  • plugin.xml.as31
  • plugin.xml.as32

KotlinConf 2018にて質問してみた

今年10月に開催されたKotlinConf 2018にて、JetBrainsの方に自動で生成するGradleタスクはありますか?と質問したところ、ないですよという回答を頂きました。それから引き続き愚直にコピペを繰り返していると、10/22にplugin.xmlがリファクタリングされて、plugin-common.xmlが生まれていたことに気づきました!

github.com

各plugin.xmlに以下のようにplugin-common.xmlをincludeすることで共通化されます。Gradleタスクを用いて自動で生成することしか考えていなかったので、なるほど!と勉強になりました! gist.github.com

さらにidea/src/META-INF以下で管理されていたplugin.xmlなどのリソース周りはidea/resources/META-INF以下に移動されていました。移行スクリプトってこう書くのねとコードを読むだけでも面白かったので興味のある方はぜひ! github.com

plugin-common.xmlが生まれてどうなったの?

github.com上記は先月出したPRになりますが、plugin-common.xmlだけ設定していることがわかります。煩わしい作業が減ってちょっと楽になりましたね!

まとめ

簡単にではありますが、最近のKontribute事情を紹介しました。やっぱりわからないことはカジュアルに聞かないとダメだなと反省しつつ、引き続きKontributeを続けてアウトプットしていきます!

qiita.com

明日最終日のコネヒト Advent Calendar 2018はいとしょさんになります!お楽しみに!

コネヒトで実践しているチームビルディングのワークショップ4選

$
0
0

はじめに

本記事は コネヒト Advent Calendar 2018の25日目のエントリーになります。遂に最終回!メリークリスマス!

こんにちは。アルバルク東京🏀を応援している @itoshoです。バスケットボールと言えばチームスポーツ!と言うわけで、今日はいつもと趣向を変えてチームビルディングにフォーカスを当てたいと思います。

コネヒトでは開発手法として、スクラムを導入しているのですが、チーム一丸となって「スクラム」を組んで、開発を進めていくためには、チームビルディングが不可欠です。

僕は約1年前からスクラムマスターをやらせてもらっているのですが、チームビルディングをしていくにあたって、最初はとても苦労しました。*1それは、チームビルディングに「銀の弾丸」はなく、組織 / 現場毎に課題や状況の変数が異なるため、教科書通りにやってみても上手くいかないケースが多いからだと考えています。*2

それでも1年間続けてみて、ある程度形になってきた部分もあるので、本エントリーでは書籍を読んだり、勉強会に参加したり、他社さんの事例を聞いたりして、実際に僕がコネヒトで実践しているチームビルディングのワークショップを4つ紹介したいと思います。なお、それぞれのワークショップ単体でも一つの記事が書けるほど奥深いワークショップですので、今回は概要のみに留めさせていただきます。

KPT

最初に紹介するのはKPT(読み方: ケプト、ケーピーティー)です。こちらは日本のスクラム開発現場でも多く取り入れられている手法ですので、ご存の方も多いかもしれません。

KPTは振り返りのためのフレームワークで、流れとしては、まず最初に「Keep」としてよかったことや今後も続けたいことを挙げます。次に「Problem」として、よくなかったことを挙げます。そして、最後にKeepをよりよくする、もしくはProblemを改善する「Try」を挙げます。なお、挙がったTryを全て取り組むのは難しいことが多いため、取り組むTryは話し合って決めます。

KPTはフレームワークに沿えば、比較的容易にプロセス改善のPDCAを回すことができ、また導入している現場も多いため、振り返りをしたことがない現場へ最初に導入するワークショップとして非常にお勧めです。

コネヒトでの利用シーン

  • コネヒトでは最もよく利用されているワークショップで、主にスプリントの振り返りとして活用されています。
  • また、みらい会議*3という全従業員が参加するような開発以外の会議でも活用されています。

注意点

  • 取り組むTryについて、コネヒトでは多数決で決める*4ことが多いのですが、合議制で必ずしもよいとは限りません。ですので、Tryの優先度をきちんとチームで見極める必要があります。
  • これはKPTに問題があるわけではないのですが、毎回同じ方法で振り返りをしていると飽きたり、惰性で行なったりするようになってしまいます。ですので、コネヒトでは気分転換に違うワークショップを取り入れたり、KPT自体をカスタマイズしています。

様子

学習マトリックス

次に紹介するのは、学習マトリックスという方法です。KPTと似ているのですが、名前の通りアウトプットがマトリックスとして表現されるのが特徴的です。

こちらも振り返りのためのフレームワークで、流れとしては、最初に「Good」として、よかったことを挙げます。2つ目に「Change」として、変えたほうがよいことを挙げます。3つ目に「Idea」として新しいアイディアを挙げます。そして、最後に「Thanks」としてメンバーなどに感謝したいことを挙げます。

プロセス改善のPDCAを回すという意味では、KPTと同様ですが、斬新なアイディアを出しやすいことと、メンバーに感謝を伝えられるので、場が暖まりやすいワークショップでもあります。

コネヒトでの利用シーン

  • KPTがマンネリ化している時の振り返りのワークショップとして利用されることが多いです。
  • 具体的には Connehito Marchéという社外向けの勉強会の振り返りによく利用されています。勉強会の振り返りは、普段のスプリントでの振り返りとは異なり、日々継続的に改善していくものではないので、労いや感謝の言葉を伝える「締め」の場にもなっています。

注意点

  • 場が暖まりやすいワークショップなので、ややもすれば「なんとなくやった感」や「なんかいい感じ」で終わることがあります。ですので、やりっ放しにせず、きちんと次のアクションが打てるようにしましょう。
  • KPTに比べると、あまり事例が多くない(少なくとも日本では)ので、振り返りに慣れていないと少し苦労するかもしれません。少なくとも、ファシリテーターは何故学習マトリックスを利用するのかを語れるようにしておくとよいと思います。

様子

ドラッカー風エクササイズ

3つ目に紹介するのはドラッカー風エクササイズです。ちなみに、ドラッカー風のドラッカーはかの有名な ピーター・ドラッカーさんから取られています。ドラッカー風エクササイズは一言で言うと、期待値調整と相互理解のためのワークショップです。

コネヒトでは 原案) を少しアレンジして運用しており、具体的には、ワークショップの参加メンバーは以下の質問に答えながらワークショップを進めていきます。

  1. 自分の得意なこと
  2. 自分が期待されていること
  3. ◯◯さんに期待していること(チームメンバー全員)

これらの質問に答えることで、みんなが思っていることと自分が思っていることのギャップを認識することが出来ます。そして、チームとしてそのギャップを埋めていくことがこのワークショップの目的です。

コネヒトでの利用シーン

  • コネヒトではまだお互いのことがあまり分かっていない新チームの結成時や新規プロジェクトの開始時によく利用されています。
  • チームビルディングとの文脈ではないので本エントリーでは触れませんが、インセプションデッキの作成と同じくらいのタイミングで実施するのが個人的には好きです。

注意点

  • 率直な発言を引き出すために、比較的心理的安全性の高さが求められるので、ファシリテーターは楽しくワイワイ出来るような場作りに努める必要があります。
  • また、やりっ放しにならないようにこのワークショップで出た付箋などは普段から見えるところに置いておきましょう。

様子

スタート・ストップ・コンティニュー

最後に紹介するのは、スタート・ストップ・コンティニューです。実はこのワークショップはまだ1回しか試したことがないのですが、けっこう面白かったので最後に取り上げたいと思います。コネヒトでは振り返りのワークショップとして導入しましたが、それ以外のシーンでも活用出来るのではないかと考えています。

元ネタは僕が大好きなNetflixなのですが*5、コネヒトでは個人にフォーカスした振り返りとして実施しました。

具体的には下記の3つの項目をチームメンバー全員にフィードバックします。

  1. 始めて欲しいこと
  2. 止めて欲しいこと
  3. とてもうまくいっているので続けて欲しいこと

一緒に頑張ったチームメンバーから率直なフィードバックを貰うことで、次の仕事に活かすのが狙いです。

コネヒトでの利用シーン

  • 先述の通りまだ1回しか試していないのですが、とある開発チームの最後の振り返りに利用しました。
  • Netflixでは相手に改善して欲しいことがあれば、上長ではなく本人に面と向かって言うという文化が根付いていて素晴らしいなと思うので、コネヒトでも利用頻度を上げていきたい。

注意点

  • チームメンバーが充分にラポールを形成していたり信頼関係を築いていたりする必要があるので、プロジェクト初期では避けたほうが無難です。
  • つまり、ドラッカー風エクササイズより高い心理的安全性が必要になります。個人的な工夫としては、チームメンバーに遠慮がないことと思いやりがないことは違うよ、というようなことを事前に伝えています。

まとめ

さて、ここまで主にファシリテーターとして僕がよく実践しているワークショップを4つ紹介してきましたが、コネヒトではこれ以外のワークショップもたくさん実践しています。それは、コネヒトの開発メンバーが日々のプロセス改善をジブンゴト化しているからであり、その時々の状況にあった方法を模索しているからです。

冒頭でも述べたようにチームビルディングに「銀の弾丸」はありませんし、極論ですが、僕はチームビルディングの「How」は何でもいいと思っています。大切なのは、何故その「How」を取り入れるのか?その背後にどういう課題や問題意識があるのか?をきちんと自分で語れることだと思います。ただ有名な会社がやっているから真似してみたとか、教科書に載っていたから採用してみただけでは意味がありません。*6ですので、思考停止せず、自分たちに合った「How」を「Why」から考えることがよりよいチームをつくるための最初の「一歩」だと僕は考えています。

というようなことを、僕はスクラムマスターの経験を通じて、今年学ぶことが出来たので、2019年もコネヒトはよりよい開発組織になれるように引き続き試行錯誤していきたいと思います!

参考サイト / 文献

*1:今も試行錯誤の日々ですが、特に最初は慣れていなかったので大変でした。

*2:僕自身の力不足もあると思いますが…!

*3:コネヒトのちょっと先の未来についてみんなで課題抽出と解決案の検討を行う会議のこと。

*4:カラーコードドットという方法を採用しています。

*5:Netflix社が具体的にどういう方法で実践しているかは不明。ご存知の方がいましたら教えてください…!

*6:もちろん、最初の一歩として参考にするのはGoodだと思います。

忘年会コンテンツをFirebaseとHerokuを使って3日で実装しました

$
0
0

こんにちは、CTO室エンジニアの安達 (@dachi_023) です。少し時間が経ってしまいましたが、弊社の2018年忘年会で実施した催し物についての話をします。

やったこと

社員同士で写真をたくさん撮った人の勝ちというサービスを作りました。

サービス名は写真を撮る擬音「パシャリ」と競技的な意味で「オリンピック」をくっつけて パシャりんピックとなりました。もともと、社内で「〜ピック」みたいなオリンピックをもじった名前をつける文化があり、そこに乗っかりました。

コンセプト

ご歓談タイムをバージョンアップする

たくさんの人と写真を撮る、という行為を選んだ理由ですが、ただゲーム性があって内輪で盛り上がれるだけなのではなくて、 一緒に働く人たちと美味しいお酒を飲み、美味しいものを食べながらのご歓談タイムをもっと良い形にできるのでは?と思ったからです。

  • 社内のメンバー全員が一斉に集まるタイミングは貴重
  • 同じメンツで話し込んじゃったりして、いろんな人と話せなかったなぁとなりがち
  • そこで、自然といろんな人と話せる機会を作れるような企画がいいのではないか?

上記のような考えから忘年会と相性が良さそう!となり、採用されました。

f:id:dachi023:20190123223620j:plain

開発について

パシャりんピックを実現するために必要なものは2つです。

  • 写真を撮ったり見たりするもの
  • 最後に集計して結果発表するもの

開発体制など

  • メンバー:エンジニア2名
  • 与えられた期間:約3日

インフラ

メンバーは私ともう1名でしたが、得意なことがそれぞれ異なったので (私はJSだし、もう1名はPHPなので) システムを完全に分けて、それぞれ得意技かつ並行で進めることにしました。ので、インフラもそれぞれがやりやすいように分割しました。

Firebase

  • コネヒトの社員のみがログイン・閲覧できる
  • なにかで使えるかもなので写真をクラウドストレージにアップロードできる
  • 最後に順位をつけて表彰したいので誰が誰と撮ったかをDBに格納できる
  • 上記を実現するwebサービスを公開する場所がある

これらの要件を1サービスでサクッと実現できるためFirebaseを選びました。本当は無料枠でどうにかなる予定でしたが、忘年会前日の夜に実装をミスって無料枠を食いつぶしてしまったので結局課金しました...。

f:id:dachi023:20190123161736p:plain
Firebaseの開発メニュー。AuthもDBもStorageもHostingもあるので全部Firebaseでできる

Heroku

  • Dockerコンテナが使える
  • Firebaseからデータを吸い上げて集計処理ができる
  • 慣れていて、とにかくやりたいことをサクッと実現できる

HerokuはPaaSサービスでもかなり使い勝手がよい素敵なサービスです。対応している言語も多く、弊社でもチャットボットなどのツールでの実績があったりなどして「使いやすい・慣れてる」というのが大きな理由になりました。ちなみに、Firebaseからデータを取り出してくるのはFirebase SDKがあるのでどこからやってもサクッとできちゃいます。

f:id:dachi023:20190123183221p:plain
Herokuなら無料!

コード管理

GitLab

コネヒトではGitHubを使っていますが今回はGitLabを使いました。GitLabちゃんと使ったことないから試しに使ってみるか!という思いと、本当はGitHubのorgにリポジトリを置きたかったけど置くと忘年会のサプライズコンテンツなのにバレちゃうよね、という理由からでした。

結局git pushくらいしかしてないのでGitLabの良さを発見できなかったのですがその後に個人開発で使ってみたりなどしているので、とっかかりとしては良かったかな〜と今は思っています。

構成図

全体で見てみるとこんな感じになりました。

f:id:dachi023:20190123185827p:plain

フロントエンドの実装

技術選定

  • material-ui
  • firebase
  • react
  • styled-components

今回は3日間という長くはない期間の中でいかにちゃんと動くものが作れるか、という状況だったのでとにかく乗っかれるものには乗っかって体験づくりにフォーカスできるようにしました。なので、なるべく手に馴染んでいる技術を選ぼうということで私の場合は上記のような構成になりました。

f:id:dachi023:20190123195040p:plain
こんな感じで自分の撮った写真で画面が埋まっていく

やってみてどうだったか

f:id:dachi023:20190123223025j:plain
パシャパシャしている様子
f:id:dachi023:20190124132747j:plain
写真を撮るとスクリーンに映した画面に流れてくる

想像以上に盛り上がりました!

  • 参加者:約50名
  • 歓談タイム:約40分
  • 撮影総枚数:約550枚

ご歓談コンテンツとして受け入れられたようで、がんばって作ってよかったなぁエンジニア日和だなぁ、と感動しつつ忘年会を終えることができました。積極的に写真を撮って盛り上げてくれたみなさんにとても感謝しています。

後日談

一緒に制作してくれたエンジニアの @o0h_が振り返りページを作ってくれました!このページで自分以外の撮影した写真を眺めたりできるようになりました。

f:id:dachi023:20190124144712p:plain
優勝はCEOでした (笑)

さいごに

はじめて忘年会をハックしてみましたが楽しかったです。作るのはもちろんですが、目の前で自分がつくったもので楽しんでいるのを見れたのが最高でした!

DroidKaigi 2019に行ってきました!

$
0
0

f:id:tommy_kw:20190211202916p:plain

はじめに

こんにちは!Androidエンジニアの富田です。先日開催されたAndroidカンファレンスのDroidKaigi 2019に参加しましたので、簡単に参加した感想を共有したいと思います。

カンファレンス全般について

カンファレンスへの支援

f:id:tommy_kw:20190209075031j:plain
オープニングでコネヒトを紹介していただく

DroidKaigiは5回も開催されている大規模なAndroidカンファレンスですが、今年初めてコネヒトはサポーター枠として支援させていただきました。僕がコネヒトにジョインして2年半で初めてAndroidカンファレンスに支援することができたので、とても感慨深かったです。

f:id:tommy_kw:20190209085232j:plain
カンファレンスアプリに記念コントリビュート
最早毎年恒例となっているカンファレンスアプリですが、昨年に引き続き、今年もtakahiromさんが開発リーダーとしてカンファレンスアプリの開発からリリースまで担当されていました。そんなカンファレンスアプリですが、約140名の方がカンファレンスアプリにコントリビュートされており、僕も簡単なIssueにコントリビュートさせていただきました!たくさんのPRがあったにも拘わらず、圧倒的なスピードでのレビューありがとうございました。

セッションの同時通訳

昨年くらいのDroidKaigiから海外の登壇者も増えてグローバルな大規模Androidカンファレンスになった印象です。海外のスピーカーのセッションだと英語になるので、どうしても聴講者数が日本語セッションと比べて少なくなりやすいです。ですが、今回からいくつかの英語セッションで同時通訳が採用されて、聴講者数が増えたと思いますし、逆に海外からの参加者の方も同時通訳を利用して日本語セッションを気兼ねなく聴講することができたと思いますので、素敵な取り組みだったと思います。

簡単にフィードバックしやすいアンケート

各セッションに対するフィードバックはとても重要なものだと考えます。なぜならフィードバックをもらって刺激を受けたり、さらに改善に繋げることができるからです。ただ、アンケートするの忘れてしまったり、ちょっとめんどくさくなってアンケートをやらないなどのご経験は誰にでもあるのではないでしょうか?今回のDroidKaigiのアプリUIはその課題をうまく解決できていたと思います。

セッションが終わるとアンケートリンクが表示される簡単にアンケートに答えやすいUI
f:id:tommy_kw:20190209080406j:plainf:id:tommy_kw:20190209080452j:plain

またアプリだけでなく、セッションとセッションの間の休憩時間が20分と長くなっていて、その隙間時間に余裕を持ってアンケートに回答することができました。各セッションの司会者の方がアンケートについてのリマインドをして下さったおかげて全てのアンケートに回答することができました。全体を通してもとてもアンケートの回答率が高かったのでないでしょうか。

心地よい疲労感

正直にお伝えすると、昨年までのDroidKaigiでは疲れて寝そうになってしまうことが少しだけありました。体力にあまり自信のない僕にとって、1日8セッションくらいを聴講することはちょっとハードなことです。ですが、今年のDroidKaigiでは眠気に襲われることもなく、心地よい疲労感に包まれながら楽しむことができました。振り返ってみると、以下のジャンルのセッションを聴講しました。

  • Flutter
  • Gradle
  • Server-side Kotlin
  • アーキテクチャー
  • TensorFlow
  • Jetpack
  • マルチモジュール
  • Androidプラットフォーム
  • Dex R8
  • Android Studio設定
  • Codelabs

Androidのカンファレンスではありますが、本当にジャンルが豊富であることがわかります。この豊富なジャンルのおかげで全く飽きなかったことや、Codelabsで実際に手を動かし、コードを書いていたことも大きな要因かなと思います。Codelabsは今まで一度もトライしたことなかったので、新鮮で本当に面白かったです。以下がCodelabsのリファクタリングに関する内容になっていますので、ご興味のある方はご覧ください。

github.com

セッションやカンファレンスアプリについて

DroidKaigiのスタッフの皆さんのおかげで、すでにDroidKaigiのセッション動画が公開されています。また、まとめ記事もありますので気になる方はご覧ください。今回は特に気になったセッションやカンファレンスアプリについて紹介させていただきます。

www.youtube.comqiita.comqiita.com

Server-side Kotlin for Frontend: 複雑なAndroidアプリ開発に対するアプローチ @qsonaさん

FiNCさんのKotlinを用いたBFFの紹介で、BFFとは、ClientとBackend Serverの間にServerを配置するパターンです。コネヒトで運営しているママリでも画面によっては、APIを10個くらい叩いている画面が存在します。そのような画面においてBFFは有効で、AWSサーバ間との通信であれば10msくらい*1でレスポンスが返ってきて、クライアント側では1つAPIを叩くだけで必要なレスポンスを取得することができます。ただ、BFFのサーバを挟むことによって管理対象が増えるため適切な設計が必要となります。こちらのセッションでは、FiNCさんの貴重な導入事例が紹介されていますので、ご興味のある方はぜひご覧ください。

All About Test of Flutter @kikuchyさん

docs.google.com

実はFlutterを全く触ったことがなかったのですが、ユニットテスト、Widgetテスト、結合テストとわかりやすく説明していただきセッションが終わった頃には、「なんかテストが書けるような気がする!」という思いになっていました。とはいえ、FlutterもDartも全く触ったことがなかったので、DroidKaigi後にGoogle Codelabsで簡単なアプリを触ってみました。

codelabs.developers.google.comcodelabs.developers.google.com

Dartの文法に関しては、こちらもkikuchyさんの資料で勉強させていただきました。 qiita.com

改めて、kikuchyさんの登壇資料のユニットテスト、Widgetテスト、結合テストまで一通り試してみるとめちゃくちゃ理解しやすかったです。なんだか、FlutterやDartを好きになりました。テストの書き方はわかったのですが、実際のアプリではどんな風にテストを書いているんだろうとふと考え、メルカリさんのカンファレンスアプリで勉強させていただきました!ご興味のある方はこちらも覗いてみると良いかもしれません。

github.com

Android Studio設定見直してみませんか? @shirajiさん

shiraji.hatenablog.com

僕が見た中で一番盛り上がっていたセッションで、スピーカーと聴講者が一体になって楽しむことができた聴講者参加型のセッションでした。Android Studio設定の便利機能をたくさん紹介していただき、早速利用させてもらっています。さらにどうやって機能実装しているんだろうと気になることばかりだったので、IDEやPlugin周りのコードを漁ってみようと思いました。

カンファレンスアプリ

github.com

カンファレンスアプリは知見の塊です。実際のコードやPRやIssueを覗いてみると参考になる情報がたくさん詰まっています。今回はその中で気になったPRを紹介します。

メモリーリークの対応ってどうやっているか気になりませんか?こちらのPRではRecyclerViewの利用に関するメモリーリーク対応でした。 github.com

gzip対応することによってトラフィック量を減らすことができたというまさにawesomeな内容でした。 github.com

Android Studioで、変数名に「favorited」、「okhttp」、「ktor」を利用するとIDEのスペルチェッカーに引っ掛かりTypoしてますよと警告される経験はありますよね。.idea/dictionaries以下に辞書ファイルを定義することによって警告を制御することができるという内容でした。 github.com

build.gradleでリソース変数のresValueをうまく利用されていてとても参考になりました。 github.com

PR自体はSafeArgsに関する内容ですが、初期化のタイミングについてコメントされており、改めて初期化のタイミングを意識しないといけないなと考えさせられる内容でした。 github.com

他にもたくさん参考になるPRがありますが、 awesomeラベルが貼ってあるPRもあるのでそれらを見るだけでも面白いと思います。ご興味のある方はご覧ください。

最後に

運営の皆さん、登壇された皆さん、参加者の皆さんのおかげで今年も楽しい時間を過ごすことができました!Flutterを全く触ってこなかったのですが、DroidKaigiのおかげでFlutter、Dartが好きになりました!DroidKaigiに参加させてもらってたくさんの知見を得ることができたので、今度はそれをプロダクトに反映してユーザに還元していきたいなと思っています。それではありがとうございました!

*1:サーバーの処理にかかる時間に依存しますが、ネットワーク間でかかる時間は長くみても10ms以内

入門監視を詠んで、「監視の民主化」に本気で向き合おうと思った話

$
0
0

こんにちは!待ちに待った2月です。
何を待っていたか? フットボールネーション(13) (ビッグコミックス)ブルーピリオド(4) (アフタヌーンコミックス)BLUE GIANT SUPREME(7) (ビッグコミックススペシャル)が発売される月ということになります。
嬉しい〜!の金城(@o0h_)です。

https://cdn-mamari.imgix.net/item/500x0_5c6a9464-96b0-4fc9-8ee2-0034ac110002.jpg.jpg

さて。
(ほぼ)ちょうど1ヵ月前に出た「入門 監視」は、いろいろな方面で話題になりました。
既に色々な書評やまとめが出回っていて、反響の大きさが感じられますね!

www.oreilly.co.jp

弊社でも、会社の書籍購入補助を利用して即予約 & 入手をしました。
この本からは非常に多くの学びや示唆を得られたと感じています。

先日、その内容・感じたことを、社内LT会で共有しました。
発表内容を踏まえつつ、読後に自分なりに考えさせられたことをまとめてみたいと思います。
ただしスライドに含まれる全ての内容を扱うと広範になりすぎるため、今回は「組織」側面のトピックに絞って取り上げます。

また、本稿では「入門 監視」に関する「まとめ」はあえて避けていきます。
その代り、その内容を踏まえて痛感した、我々のチームにおける「これまでの失敗」と「何を反省したか」を記します。
(そのため、既に一読されている方が対象になるかもしれません。)

TL; DR

  • この本を読んで、「監視の民主化」をしたい!と非常に強く感じた。
    うちのチームは、少なくとも形式的にはアラートへの対応を全員でやっているが、見えない壁があった。
  • 「監視をできるようにする」ために必要なのは、「知っている人」「慣れている人」からの歩み寄りが大事だと思う。
  • 「監視はスキル」。誰でも出来るように、インプットとトレーニングを用意する。

発表資料

こちらが、発表した内容です。
公開に当たり、実際に利用した資料を一部編集しています。

「入門 監視」を読んだ背景

ママリで年末に発生したとある問題は、とても厄介に感じる面がありました。
「初動で問題を除去するに至らなかったこと」「問題の解消に数時間を要したこと」「結果的に原因の特定に至ったが、綱渡り的な『アイディア』頼りであったこと」などが、「厄介だった」と感じられる主な要因です。

この事象は、チームの実情に関する多くの学びを残すものとなりました。
もちろん、これまでだって「しっかりサービスを守っていこう」「問題が生じ際には、ちゃんと対応していこう」という意識で一生懸命取り組んできています。
しかしながら、それでも「足りない」ものがあると気付かされました。

今回の件は単なる個別的な「障害対応」に留まらない、より抽象的・本質的な今のチームの課題を物語っていると個人的には感じられたのです。
大げさでなく「サービスの運用・監視についての1つの天井にぶちあたった」という印象があります。

結果として「もっと根本的・全体的な、姿勢や仕組みづくり不可避だな」という想いに至りました。
その最中に、「そういえば!1月に、面白そうなタイトルの本が出るんだった」という事が思い出されます。
それが、「入門 監視」です。

この本は、「何かやり方を変えなければならない」と感じ実際に方策を練ってみるも、「これで本当に変わっていけるのだろうか?」とモヤモヤしていた私にとって、非常にシンプルで筋肉質なヒントを与えてくれました。

コネヒトの「監視」の歴史

今回の話を進めるにあたっては、コネヒトにおける監視の状況を共有する必要があります。
なので、ちょっと寄り道をさせてください。

入社当初のプロダクトチーム

2015年当時、エンジニアは

  • CTO(サーバーサイド・インフラ)
  • 後のリードエンジニア(サーバーサイド・モバイルクライアント)

の2名がいるのみでした*1
そこに私が、サーバーサイドエンジニアとしてジョインした形です。

サービスはしっかり伸ばしていたし、インフラも安定させられていたし、ユーザーに見える影響を及ぼすような目立った障害もほとんどなく。
少ない人数で「よくやっていた」のだと思います*2
ただ、見方を変えたら「このサイズだからこそ」という面もあるのではないでしょうか。

  • サービス開発開始から変わっていない面子が、一緒に数年来やっている
  • (サーバーサイドに関しては)相互のコードレビューを通して、どちらも「知らないコード」は1行もない
  • フルAWS構成にした上で、AWSのサポートをゴリゴリに使っている
  • ディレクターポジションはProduct Ownerの1人のみで、距離を意識することが無い

これらのパラメーターは、「スピード感を持ってうまくやる」ために、かなりのアドバンテージを生み出していたはずです。*3

この輪の中に私が加わったわけですが、そこで起こる状況としては次のようになります。

  • 「教育」や「組織(開発チーム)」という面では、かなりふわふわしている
    • 独立・自律した個人の集合という状況
  • 他方で、「新参者」が普段コミュニケーションをとる相手は「全てを知っている」メンバーのみ
    • 何につけても「的を射ている」、自サービスに関しての「不完全」性が低い
    • 全体にとって「必要なこと」は、自分の視界の届く範囲(n=2なのだから!)で行われている

つまり、コチラが意識をするせざるにかかわらず、環境が「猛スピードでキャッチアップさせてくれる」ように出来ていると言っても過言ではありません。

「監視」の領域に足を踏み込んだ

その上で、新規加入したメンバーとしては「手薄な部分を強化したい」という役割があります。
個人的な興味関心で歩み寄っていったのが「パフォーマンス向上」や「サービス品質向上」といった領域でした。
その一環として、スロークエリを潰していったり、アプリケーションエラーを減らしていったりの「負債解消」にワクワクしながら取り組んでいきました。

当時あまり活用されていた印象はありませんでしたが「Sentry*4を色々眺めてみる」ようなことをしたり、
インフラ担当であるCTOと一緒にCloudWatch Alarmをいじってみたり、
少し経ってからは外形監視に手を出したりもしています*5

「やりたい!!」と言って手を挙げた時に背中を押してくれる環境は尊いものです。
ただ、「言えばできるんだから、見つけない・言わないのは甘えでしょ」と責任をメンバーに押し付けるのは決して正しくありません。

その点、私の場合は幸運でした。
「明らかに足りていない」「やるべき課題が目の前に転がっている」状況に放り込まれたようなものだったからです。
そういう意味で、当時の「小さいチーム」に下駄を履かせてもらっていたと感じます。

そこからスタートして、今に至るまで「チームの中でSentryに1番長く触っている」という自負がありますし、また弊社における「アプリケーションエンジニア」としての在籍期間は今や最長となっています。
そうした背景から、私は自ずと「障害対応に慣れている」・・言い換えると、相対的には「たぶん最も効率的に対応が行える」「問題切り分け〜対応完了までのハードルを1番低く感じている」という立場になっていたんだと感じました。

変動していく組織の中で「誰が」やれるのか、という問題

f:id:o0h:20190219000029p:plain

この「実は自分の立場が特殊なのかもしれない」というのは、恥ずかしながら「入門 監視」を読んで気付かされた点でもありました。

上記の状況から、実は勝手に「監視の現場」のようなものに、私は足を踏み入れていた状況です。
では、そんな下駄の履かせ方は、「新しくチームに入ってきた人、何人目まで通用するのかな?」という問題があります。

監視は全員でやるもの(ってか、やろうと思えばできるでしょ?)

他の多くの書評エントリーでも触れられている通り、「監視は(SREやインフラに限定されず)全員でやるもの」というのが、「入門 監視」の唱えているテーマの1つでもあります。
しかしながら、個人的には、正直これについてあまり目新しさを感じはしませんでした。
なぜなら、実際に「SREや、専任インフラがいない」という状況で立ち振る舞ってきため、
既に自己の経験をもって「アプリケーションエンジニアこそ監視をやるべき」と胸を張ってそのメリットを主張できるからです。

いかんせん、アプリケーションエンジニアは、他のロールと比べて、本来的に持っているドメイン知識やメトリクスの裏に透けて見えるユーザー行動への感受性が違いすぎるのです。

例えば、我々にいわせれば、
「急にRDSのコネクション数が上がったよ」という1つの情報だけを以て
「さっきリリースした /hoge/fugaエンドポイントのAPIで既存キャッシュのライフサイクルがアカンくなったかも知らん」「じゃあユーザー的に、アプリケーションの起動までは問題ないかもだけど○○の機能に遷移したときに、全員とまでは言わずとも、10回に1回くらい読み込みが遅くなってる可能性があるな」・・
というところまで直感するに足る要素が含まれています。

これこそ、「ユーザーとインフラの中間に立っている」「サービスとシステムの間に立っている」という、我々アプリケーションエンジニアの経験値からくるものです。
自身はアプリケーションサーバーに身を置きながら、ロードバランサからデータベースまで俯瞰できているようなもので、サービスの「見えている範囲カバレッジ」は非常に高いでしょう。
有している「判断材料が多い」「総合性が高い」という点で、とても有利なのです。
これはロールのもたらす特性です。

私にとっては、この「見え方」が当たり前の世界でしたので、
「普段、サービス開発に携わっている身からしたら、1つもしくは複数のメトリクスを手繰り寄せて、何が起きているかをイメージする」
という態度は、何も特別なものでないと感じていました。
ゆえに、「監視は全員でやろう」は同意しかないし、枯れた視点だったのです。

その上で、だからこそ、「入門 監視」で触れられていた 手順書というコンセプトは非常に衝撃をもたらしました。

手順書というコンセプトと、「スキル」としての監視

これは、 特定のサービスについて以下のような質問に答えるように書かれたものと説明されています。

  • これはなんのサービスで、何をするものか。
  • 誰が責任者か。
  • どんな依存性をもっているか。
  • インフラの構成はどのようなものか。
  • どんなメトリクスやログを送っていて、それらはどういう意味なのか。
  • どんなアラートが設定されていて、その理由は何なのか。

(『P38 3.1.2 手順書を書こう』)

本書の「付録A」にサンプルが紹介されているのですが、例えば以下のようなものです。

アラート: 記事の作成時間が長すぎる
このアラートは、ユーザーの記事作成時間が1秒を超えた時に発報されます。
直近の不正なデプロイか、PostgreSQLのパフォーマンスに問題がないか確認してください。

ここに書かれている内容は、日常において私が「想像している」と感じていることに相違ありません。
今まで「アプリ書いてりゃイメージつくようなるっしょ」と決めつけていた内容が、「形式知化し、チームメンバーにインストールするべき事柄」と書かれていたのです!

私にとってそれは、

お前がそれを『当たり前』と呼んでいる限り、お前がチームの癌になるし、少なくともお前が望んているような有機的で自律的な監視・運用を行えるチームになんてならないぞ

と、Mike Julian氏と @dblmkt 氏が語りかけているような気すらしました。

「アプリケーションエンジニアが監視もやっているんだから、うちは監視が役割になったりなんて、していないよ」という私の思い込みとは裏腹に、
監視が「スキル」になりきらずに、属人性の高い、実質的な「役割」化されて偏っていたといえます。

関連して思い出すのは、件の障害の振り返りミーティングを年末に実施した際に受けた発言です。
私が「これから監視体制を見直していきたい点・やり方」の草案を共有すると、サーバーサイドエンジニアの同僚から

障害対応の可能な人員を増やしていくにあたって、『あるメトリクスが増減したときにそれをどう読み解くか」というのを言語化・共有できないか

という指摘がありました。
その時は、正直に言ってあまりピンと来ていませんでした。

しかし、この「手順書」のやり方を見たら、確かに「誰でもできる!というには難易度が高いのかも知れない」と気付かされます。
それを他人に配布していくには、シンプルな方法で、的確にやっていく必要がありそうだ・・というオチでした。 私の「何となく」は、「アーキテクチャからサービスの提供内容や機能といった立体的な理解が必要」なスキルのようなものだったのです。

なんで、私が老害に!?

f:id:o0h:20190218235902p:plain

繰り返しになりますが、
私がこれをできたのは「いろいろなものを実際に自分の手触りとして覚えてきたから」に過ぎません。

いま、コネヒトのエンジニアは、インフラ・クライアントサイド(ネイティブ、Web)・サーバーサイドで10名を超えています。
サーバーサイドのプロダクトに限っても、「全てのレポジトリに触れたことがある」のは私を含め2名に留まります。
社内ツールも数に含めると、全て触れているのは「たまたま古くからいて、PHPが好きだったので」という理由で私が該当するのみというのが現状です。
ここだけを切り取ってみても、「今までのやり方を見直してみるべきだ」という黄色信号が点灯しているように思います。

おそらく、もう「何でも屋」はこの組織に入ってこないでしょう。
もちろんWeb系エンジニアは領域横断のハードルが低いので、スキルやポテンシャル的に「何でもできる」人材は少なくないはずです。
ただし、「社内のあらゆるプロジェクト(リポジトリ)に馴染みがある」という状況が生まれるか?というと、全く別の論点です。

では、そうした未来において
自分のような「環境が下駄を履かせてくれる」恩恵を受けながら「カンシチョットデキル」人員が発生し得るのでしょうか?

持論ですが、監視や障害対応は「知識」と「実務経験値」の総合格闘技だと思っています。
性質としてはデバッギングなどと近いでしょう。
「ここが怪しい」とか「これで切り分けよう」などというのは、
深い知識があるか、身体で覚えているかというパラメータに大きく左右されます。

そこで、そもそも「知識」のカバー範囲が広く「実務経験値がある」メンバーが前線に立ち続ける*6というのは・・・・どんな状況を招くでしょう。

これが、私がスライド中で、あえて「老害」などという極めて強い言葉を用いて表現したかった状況であります。

私はずっと「サービスの安定性は十分に高いが、チームとしての監視・障害対応のレベルは決して十分でない」と感じながら過ごしていました。
この状況は、とても皮肉なことに、「私こそが、アクションして打破していくべき課題だった」ということに、「入門 監視」を通じて気付かされたのです。
正当な進化の道筋に、自分が立ちはだかっているのだと感じました。

さて、気づいてしまえばやるべき事は1つです。
いま「先頭」っぽいところにいる自分が、仲間たちと手を取りこの先の旅路に就くことです。

監視を「スキル」化し、「民主化」していくために

f:id:o0h:20190219000328p:plain

ここまで(そしてスライド中でも)何度も「スキル」という単語を使っていますが、
これには次のようなニュアンスがあります。

役割(ロール)」の対立軸としてのスキル

監視アンチパターン「役割としての監視」に対して、「スキルとしての監視」を推奨しています。
アプリケーションエンジニア、ネットワークエンジニア、データベースエンジニア・・・サービスの開発運用には色々な「役割」がついて回るものです。
本書では、 監視の旅へ進むに当たって、皆が監視について責任を持つ事を主張してください。と語られます。
大前提、監視とは「サービスが動いているかを監視する」ことに他なりません*7
そして、サービスとは、複層的で複雑な構造の上に成り立つものなのです。
「特定の誰か1人」隅々まで全容を把握するのは非現実的でしょう。

そのため、チームの全員が「一定度以上できるようにする」事が不可欠になります。

「サービス全体が正常に動いている」というのがどのような状態であるかを共通理解とし、
飛んできたアラートと、それが意味する状況についても共通理解をした上で、
自身の主たる守備領域における「原因探索」もしくは「影響の考察」を行い、
これらの情報を綜合していくことで効率的で有機的な対応が成立するでしょう。

習得可能な事柄としてのスキル

スキルという単語は、「教養や訓練を通して獲得される、実務を遂行可能とする能力」と説明されます。
本書において、監視が「スキル」と表現されているのは個人的には非常に希望であり、他方でプレッシャーのようなものを覚えました。

すなわち、「監視」とは「チームとして、明確に、各メンバーが実行可能になるように支援し引き上げるべき対象」ということになります。
例えば「CakePHPを使っているチーム」において、「一緒にレポジトリをいじるメンバーが、CakePHPを使いこなせるようにしていく」のは、もはや義務であるといって過言ではないでしょう。また、周りのメンバーもそのように支援し、協力していくはずです。

「チームにとって必要なスキル」というのは、習得する努力は必須です。
それと同様に 「やれる人」から支援を行い適切なレベルデザインを行い・・・という意味でも「できるようにする」のは使命だと思っています。
まして、「監視」というのは「各領域のプロフェッショナルが協力して行う」べきものです。
インフラやオペレーションに近い職務を担う人が「たまたま監視にも親しみがあった」というだけでは、監視が一部の人の「特殊スキル」になってしまいます。
(今のコネヒトも黄信号です。)
これを、ちゃんと「取得できる」「取得させる」スキルへと転化していくことが、重要なのではないでしょうか。

最後に: 「入門 監視」はどのような本だったか

f:id:o0h:20190219031519p:plain

私はこれまで、実際にプロダクトの「監視」をやってきました。
重要な障害対応にも取り組んだし、CloudWatchのダッシュボードも作りました。アプリケーションの健全性のようなものをレポーティングしたことだってあります。

それでもなお、この一冊を読んで「私(たち)は、監視というものに入門する必要がある」と感じています。
それは、「監視とは何を目的としたものか」を定義し、「ユーザー(との接点であるサービス)にどのような効果をもたらすか」のゴールを掲げることに他なりません。
1つの方向を向くことをスタート地点とし、「民主化」された監視を実現していきたいのです。

現状のチームにおいても、「できていること」や「伸ばすべき芽」はあると感じています。
きっと、世の中一般の「偏差値50」を高く超えている点もあることでしょう。
また、本書の内容は一部「極端かもしれない」と感じたり「これはすぐには真似できなそうだ」と感じられる部分もゼロではありません。なので、単純な猿真似を目指さず、本質的な理解に迫りたいと考えています。
総じて、活かすとこは活かしつつ、反省すべきは反省しながら、ウチはウチとして、強力な安心監視マインド&体制を作っていきたい所存です。
やらなければ・正さなければならない事が何個もあるなかで、我々は「スキルとしての監視」に取り組んでいきたいと思います。

多くの方の書評記事・感想レポートにもありますが、
改めて、私個人としても「全(クライアントサイド|サーバーサイド|インフラ)エンジニアやテックリード、SREが1度読んでみてほしい!!」と感じられた一冊でした。
もし「読もうかどうか迷っている」という方がいましたら、ぜひ手にとって見ることをオススメします!!

f:id:o0h:20190219000728p:plain

蛇足

なお、ただいま「PagerDutyをすごく使いこなしている方」の話を聞いてみたい!と所望しています。
DM・メンション、もしくはWantedlyなどなどコンタクトをお待ちしております・・・!

*1:当時のなんとなくの様子はインフラエンジニアがサービスの0→1を創る際に意識した、たった1つのこと - コネヒト開発者ブログでも言及されています。2015年当時。

*2:そういう所を選んで転職してきたのですが!

*3:キャリア上、私も「実質1人チーム」のような現場を経験したことがありますが、ある側面においては「摩擦0」でコトに取り組める理想状態でもありました

*4:エラートラッキングツール。 http://sentry.io

*5:こういうのとか http://tech.connehito.com/entry/2016/09/21/163000

*6:自己弁護ではないですが実際問題として、難しいのは、ユーザーに提供しているサービスである以上はユーザーへの悪影響を最小限に留める努力が必要不可欠です。なので、「できる人が居合わせたなら、その人がやる」というのはとても合理的です

*7:コレ自体も非常に感銘を受けた言葉なのですが、長くなりすぎるので本稿では掘り下げません!!

AmazonAurora カスタムエンドポイントのフェールオーバー時の挙動についての検証

$
0
0

こんにちは。インフラエンジニアの永井(shnagai)です。

昨年11月にリリースされたAmazon Auroraのカスタムエンドポイントを運用していて、先日ある検証環境でフェールオーバーが起きた際に考慮していなかった事態が起きたので、仕様を確認するがてらカスタムエンドポイントのタイプ別にフェールオーバー時の挙動をまとめてみました。

カスタムエンドポイントについては下記をご参照ください。 自由にAuroraインスタンスを組み合わせて、用途別にAuroraのエンドポイントを管理出来る機能で、これまで泣く泣く続けていたmysqlのbinlogレプリ運用から解放されるようなうれしさがあります。 docs.aws.amazon.com

起きた事象

Auroraクラスタにフェールオーバーが発生した際に、当然リードレプリカがマスター昇格します。その際に、カスタムエンドポイントのノードが0になりカスタムエンドポイントへのDB接続が不可となりました。

これは、下記環境の説明にあるようにREADER TYPEでカスタムエンドポイントを作成していたので、登録していたリーダーインスタンスがREADER TYPEの条件不一致になりメンバから外れたのが原因でした。 リーダーエンドポイントだと、よくあるLBのSorry設定のように、ノードが0になればマスターが一時的にメンバに入りノード0を防ぐような挙動をしてくれますがカスタムエンドポイントではそのような挙動はありません。 今回の検証では、リードレプリカに降格したインスタンス(旧ライターインスタンス)が、自動的にカスタムエンドポイントに登録するような設定を見つけるのがゴールとなります。

問題が起きたカスタムエンドポイントの環境

  • Auroraクラスタで、ライターインスタンス1台、リーダーインスタンス1台構成で運用
  • カスタムエンドポイントは下記条件で作成し運用
    • READER TYPE
    • メンバシップルール内の[今後追加されたインスタンスをこのクラスターにアタッチ]はDisable ※この設定はAuroraレプリカを追加する際に意図せずエンドポイントに追加されるのを防ぐ意図で入れたのですがこれが仇になりました。。
    • 静的リストで、リーダーインスタンス1台を登録

Auroraのカスタムエンドポイントの主な設定値

はじめに前提知識としてAuroraのカスタムエンドポイントに主な設定値の内容を確認しておきます。 主な設定値は2つです

タイプ指定

Any or READERでカスタムエンドポイントのルールを指定する

type説明
READER読み取り専用の Aurora レプリカである DB インスタンスのみが、READER カスタムエンドポイントの一部となることができる
ANY読み取り専用の Aurora レプリカと読み取り/書き込みのプライマリインスタンスの両方が ANY カスタムエンドポイントの一部となることができる

メンバーシップルール

  • 静的リストか除外リストを用いて、カスタムエンドポイントに所属するインスタンスを指定する
  • [今後追加されたインスタンスをこのクラスターにアタッチ]するか否かを選択する ※今回の検証ではここが肝だった

検証

4つのパターンからフェイルオーバー時に降格したマスターノードがカスタムエンドポイントのメンバに自動的に追加される設定を探りました。

検証

  • テスト用のAuroraクラスターを作成
  • クラスタには、1台のライターノード(test-custom-endpoint)と1台のリーダーインスタンス(test-custom-endpoint-ap-northeast-1c)を用意
  • 4パターンのカスタムエンドポイントを作成し、フェイルオーバー時の挙動を確認

結果

②の構成でカスタムエンドポイントを作ることで、フェイルオーバー時に降格したインスタンスがカスタムエンドポイントに追加されることが確認出来ました。

NoTYPE追加インスタンスのアタッチ予想結果
READERDisableメンバいなくなるメンバいなくなる
READEREnableメンバいなくなる or 降格したインスタンスがメンバイン降格したインスタンスがメンバイン
ANYDisableそのまま(昇格したライターのみ)そのまま
ANYEnableそのまま or 降格したインスタンスがメンバインそのまま

最終的にどんな構成にすればいいのか

カスタムエンドポイントを使いたいよくあるケースは下記のようなパターンかと思います。

  • マスターにはサービスからの書き込みトラフィックが流れる
  • 複数台あるレプリカを束ねるカスタムエンドポイントにサービスの読み取りトラフィックが流れる
    • フェイルオーバー時は、このサービス用のカスタムエンドポイントのいずれかがマスタ昇格
  • 分析用にAuroraのレプリカを作ってそこは分析のSQLだけが流れるような構成

下記のような構成を取ることで、カスタムエンドポイントの本来の良さを生かしてAuroraレプリカへのトラフィック分散が出来るのではないかと思います。(さらばbinlogレプリ)

※カスタムエンドポイントはGUIから作るとAny typeになるので、READER typeのエンドポイントを作るにはAWS CLI等からの作成が必要

サービス用のカスタムエンドポイント

READER type + 新規インスタンスのアタッチ有り + 所属するリードレプリカのFailOver優先度を0(最優先)にしこの中からフェイルオーバー時のマスター昇格が行われるようにする

分析用のカスタムエンドポイント

READER type + 新規インスタンスのアタッチ無し + 所属するリードレプリカのFailOver優先度を15(優先度最も低い)にしてフェイルオーバー時のマスタ昇格は行われないようにする

f:id:nagais:20190218163533j:plain

参考までに画面キャプチャ

f:id:nagais:20190218163647p:plainf:id:nagais:20190218163659p:plain

f:id:nagais:20190218163715p:plainf:id:nagais:20190218163723p:plain

f:id:nagais:20190218163740p:plainf:id:nagais:20190218163749p:plain

f:id:nagais:20190218163801p:plainf:id:nagais:20190218163812p:plain

コネヒトでは変化を恐れずに良いものを取り入れながらサービスの信頼性向上をミッションに一緒に働く仲間を探しています。 少しでも興味もたれた方は、是非気軽にオフィスに遊びにきていただけるとうれしいです。

www.wantedly.com


React HooksとContextAPIでFluxをやってみる

$
0
0

f:id:dachi023:20190226162905p:plain

CTO室エンジニアの安達 (@dachi_023) です。React v16.8で待ちに待ったHooksが (20日前に) リリースされました。そんなHooksを使ってFluxやる時ってどうするんだろう?と思ったので調べて写経してみました。

reactjs.org

書いたコード

create-react-app して出てきたものをいじって作りました。Flux化するまでに書いたコードだけを見たい場合は コミットログが分かりやすいかもしれません。

github.com

余談: 実際書いてみて「Hooksちゃんと理解してなかったなぁ、9割くらい写経だとしても覚えるために書くというのは良いことだ」と感じられました。

やってみる

  • お題: +1 / -1 ができるカウンターの実装
  • useReducer() とContextでStoreをつくる
  • Actionの発行 → dispatch → Stateの更新 → 再描画 をやる

Context

ContextがStateを管理するための入れ物 & 伝搬役になります。とりあえず createContext() して返します。今回はdispatchも同じContext内で管理します。

import{ createContext } from 'react'exportdefault createContext({
  count: 0,
  dispatch: null})

Reducer

Actionを受け取って新しいStateを返します。Actionの中身は redux-utilities/flux-standard-actionと同様です。Reducerの定義は Reactのドキュメントにも書いてありますが (state, action) => newStateです。

exportdefaultfunction CounterReducer(state, action) {switch (action.type) {case'increment':
      return{ count: state.count + 1 }case'decrement':
      return{ count: state.count - 1 }default:
      return state
  }}

ActionCreator

外部通信やビジネスロジックがないのでほぼ無意味な感じになってますが前述したflux-standard-actionに倣ってActionを生成して dispatch() します。

exportfunction increment(dispatch) {
  dispatch({
    type: 'increment',
    payload: {}})
}exportfunction decrement(dispatch) {
  dispatch({
    type: 'decrement',
    payload: {}})
}

Component

作ったものをつなげていきます。

App.js

useReducer() にCounterReducerとStateの初期値を渡してstateとdispatchを取り出しProviderに突っ込めばStateの生成と値の伝搬作業が完了します。

import React, { useReducer } from 'react'import Counter from './Counter'import CounterContext from './contexts/CounterContext'import CounterReducer from './reducers/CounterReducer'import'./App.css'exportdefaultfunction App() {const[state, dispatch] = useReducer(CounterReducer, { count: 0 })
  return (
    <div className="App">
      <header className="App-header">
        <CounterContext.Provider value={{ ...state, dispatch }}>
          <Counter />
        </CounterContext.Provider>
      </header>
    </div>
  )
}

Counter.js

の処理でProviderにセットしたStateを useContext() で取り出し表示します。Stateと一緒に入れてあるdispatchを取り出してクリックイベントに仕込めばStateの更新処理までが完了です。

import React, { useContext } from 'react'import CounterContext from './contexts/CounterContext'import{ increment, decrement } from './actions/CounterActions'exportdefaultfunction Counter() {const{ count, dispatch } = useContext(CounterContext)
  return (
    <>
      <h2>{count}</h2>
      <button onClick={() => increment(dispatch)}>Increment</button>
      <button onClick={() => decrement(dispatch)}>Decrement</button>
    </>
  )
}

できあがったのがこれ

ちゃんと増えたり減ったりするようになりました!

f:id:dachi023:20190226160647g:plain

まとめ

  • 今までのClassベースのComponentとは書きっぷりがだいぶ異なるので最初とっつきづらいのかもなと思いました、1回でも真面目にやると「なんだ全然できるじゃん!」という感じですが。
  • 複雑なことしないのであればFluxライブラリなど使わずにHooksで実装しちゃってもいいかもしれないですね。結構使えそうじゃないかな?と思ってます。

参考記事

Slack Block Kitを使って既存ツールをカッコよくしてみた

$
0
0

こんにちは、 BLUE GIANT SUPREME (7) (ビッグコミックススペシャル)を読みました。金城(@o0h_)です。
読後、へーしゃで称賛が発生していました。

f:id:o0h:20190303130444p:plain
こちら、社長と私です

そんな感じで色々にSlackを利用している身のものですが、先月「新しい機能をリリースしたよ!」という発表がありました。
「Block Kit」です。

Block Kitは、「Slack投稿の表現力を上げる」「ユーザーと、より気の利いたインタラクションをつなぐことを支援する」ための新UI(のためのAPI)です。
これを利用すると、いつものSlackの投稿がとても高機能になります。

実際に触ってみたので、使い方やハマったポイントなどを共有していきます。

https://cdn-mamari.imgix.net/authorized/5c7ccc81-7170-439c-8949-0034ac110003.jpg

Hello! Block Kit

例えば、実際にBlock Kitでできること = 「いち投稿上でやり得ること」は、次のようなイメージになります

f:id:o0h:20190303135424p:plain
サムネイル画像を埋め込んだり、2列組ブロックを使ったり、ButtonやContext Menu等の操作用UIをくっつけたり・・

f:id:o0h:20190303135156p:plain
コンテンツのグルーピングのための区切り線を使ったり、「本文」と「副文」を別々に扱ったり、プライマリな操作UIをつけたり

今までより、かなり出来ることが増えたな!というのが伝わってくるのではないでしょうか。

私は、この新リリースをSlack Platform BlogのRSSフィードが流れてきたので知る事になりました。
未読でしたら、一度ぜひ目を通してみていただく事をお勧めします。

medium.com

リリース後、Slackチームは積極的にBlock Kitの宣伝をしている印象を受けます。
「Block party」を皮切りに、ちょっと観点を変えながらこの歓迎すべき新機能についての説明エントリーをあげていますね。
実際に読んでみて個人的に感じたのは、

というような、少しずつステップアップしているような内容になっているのかなーということです。

具体的に、何なんですか?

機能概要みたいなところは、2月のPHP勉強会東京でも個人的にLTをさせていただいたところです。
よろしければ、発表資料もご覧ください。
発表に使った資料@Speaker Deck

Block Kitは、一言で言えば 「layout block」と「block element」の集合として、投稿を定義していくAPIと言えると思います。
Elementは、Blockに梱包するサブ要素です。
そして、これらの要素にいろいろな「Type」があるため、すご〜い!いろんな事ができるんだね!!という結果が導かれるわけです。
Blockは、投稿系のAPI(例えば chat.postMessage)に拡張されたフィールド blocksに配列として注入することでハンドリングされます。

イメージを具体化してみましょう。
Slackが Block Partyに合わせてBlock KitのUIビルダー「Block Kit Builder」を提供しています。
いくつかテンプレートがあり、そのうちの1つが「Search Results」です。
実際に組み立てられたUIは、以下のようになります。

f:id:o0h:20190303140051p:plain
Example message for seeing top search results and browsing additional info.

これらが、「Block」&それに属する「Element」で構成されているわけです。
このようなアウトラインとなります。

[{"type": "section", "accessory": {"type": "overflow"}},
    {"type": "divider" },
    {"type": "section", "accessory": {"type": "image"}},
    {"type": "context", "elements": [{"type": "image"}, {"type": "plain_text"}]},
    {"type": "divider" },
    {"type": "section", "accessory": {"type": "image"}},
    {"type": "context", "elements": [{"type": "image"}, {"type": "plain_text"}]},
    {"type": "divider" },
    {"type": "section", "accessory": {"type": "image"}},
    {"type": "context", "elements": [{"type": "image"}, {"type": "plain_text"}]},
    {"type": "divider" },
    {"type": "actions", "elements": [{"type": "button"}]}]

sectionimagebuttonといった「要素」があることが、何となく見て取れるでしょう。

実画面との対応について、一部を示します。 *1

f:id:o0h:20190303142952p:plain

こうしてみると、「いかにリッチな表現ができるようになったのか」がわかりやすいのではないでしょうか。

使ってみた

折角こんなに面白そうなので、実際に試してみることにしました。
当ブログでも何度か紹介している社内ツールをいじってみます。

tech.connehito.comtech.connehito.com

  • ツールの概要
    • ナレッジやユビキタスその他を、Slack上から簡単に出し入れできる機能を提供するツール
  • 今回やること
    • 「検索」系の機能の改修
    • Before
      • 該当したアイテムが、セレクトメニュー(Attaching interactive message menus | Slack)に一覧表示される
      • ユーザーが任意のアイテムを選択
      • メッセージ本体の更新による結果表示
    • After
      • 該当したアイテムが、sectionブロックとdividerブロックによりサブジェクト+スニペット形式で表示される
      • show moreボタンの設置と、呼応して該当アイテムのコンテンツを追加投稿する

動作例

これが、以前の実装です

https://user-images.githubusercontent.com/907122/53692227-90e59380-3dcf-11e9-8bca-f94633d9ba68.gif

Block Kitを使って、ちょっとかっこよくしてみました

サーバーの処理遅延で、二重応答しているのはご愛嬌・・・💁

「表示する」ボタンを押す前に、一覧で表示される内容はスニペットです。先頭200文字程度で削っています。
コネヒトでの実際の利用動向を見ると、多くのものは「何かのURL」や「1文、もしくは2,3文程度の説明」であるものが多いので、実は文字数制限を加えた上での表示でも十分に事足ります。
今回の改修により、「わざわざユーザーの操作をせずに、一瞥して情報確認終わり!」という体験を得られやすくなりました。
また、section.accessoryによって「このブロックに対する操作」を明示したインタラクションが可能になったので、この「省略しつつ一覧表示」に踏み込めました。

総論として、Blocksの登場で、これまでよりも格段に「複数の情報の集合を適切に表示する」というのが容易になります。
確かに、今回の例に上げた程度の機能なら「今までのAPIでもほぼ同じことができたのでは」とも思います。それは実際に作ってみてから感じました。
ですが、Slack側から示された道によってインスピレーションが湧いた!!!というのは大きいです。
そういった背景も含めて「やりやすさ」が支援されたのではないでしょうか。

実装について

投稿メッセージにBlockを組み込むことに関しては、Block Builderを利用しながら感覚を掴むのが良いと感じます。
インタラクションに関する実装に関して、いくつか気づいたことやハマった点をまとめてみます。

  1. リクエストの受信
  2. 「なんの操作をしたか」は action_idにセットする
  3. blocksフィールドがあるとtextフィールドが無視される
  4. blocksのエラー内容が凄く親切
  5. リンク切れ画像を指定すると送信エラーとなる
  6. URLを含む投稿でも情報が自動展開されない
リクエストの受信

Interactive Componentsの例に漏れず、Slack App側で設定したエンドポイントに対してリクエストが送信されてきます。
その内容が、 type:block_actionsになっています。

実は、送信されてくるPayloadについてもBlock Kit Builderから知ることができます。
プレビューに表示されたボタンやメニューを操作してみてください。
すると、 Show Payloadボタンが現れます。

Buttonの操作時のPayloadを表示している様子

「なんの操作をしたか」は action_idにセットする

ユーザーインタラクションを求めるElementは、 action_idというフィールドを持っています。

api.slack.com

これは、「なんの操作をしたか」の識別子です。例えばHTMLのフォームで言えばname属性に当たります。
先ほど紹介した社内ツールの例では、「表示する」ボタンのaction_idは view-documentとしました。
同じくelement(Buttonや、Select Menuなら option objectのそれぞれ)にvalueをもたせられますので、これらを組み合わせて「document:211に対するview-documentをリクエストされた」といった判断ができるわけです。

blocksフィールドがあるとtextフィールドが無視される

これまで、 attachmentstextは共存可能でしたが、もしblocksが存在していると「本文」が表示されなくなるようです。*2
デスクトップアプリのNotificationにはtextのコンテンツが表示されるので、少し不思議な感じもするのですが。

例えば、Testツールから試してみた内容と実際に受信した内容が次のとおりです。 f:id:o0h:20190303154530p:plainf:id:o0h:20190303153839p:plain

blocksのエラー内容が凄く親切

コンテンツのバリデーションまでしっかり行った上で、「どこがおかしいか」を返してくれます。 f:id:o0h:20190303153946p:plain

リンク切れ画像を指定すると送信エラーとなる

Image Block、Image elementのいずれでも同様です。
Block(image)の場合、downloading image failedという内容でエラーとなります。
ただし、section.accessoryにimageを含めて取得失敗が生じた場合、Slackの返すエラー内容が少しあやふやなものになるので、注意が必要です。

f:id:o0h:20190303154128p:plain

今回、「ヒットしたアイテムに画像が含まれていたら表示する」という実装をしていたためにこの挙動は悩まされました。
最終的に、「投稿失敗時にエラーの内容を解釈し、該当するBlockを除去して再投稿」というリトライ機構を入れています。

URLを含む投稿でも情報が自動展開されない

これまでは、例えばchat.postMessagetextにURLを含めていた場合、画像や動画といったメディアであればそのコンテンツが表示されたらり、WebサイトであればOGPから情報が表示されていました。
Block Kitを利用すると、これらの情報が展開されないようです。
場面によってはしんどいかも知れません。

Block Kitの歩き方

実装において参考にしたリソースを列挙します。

  • Messaging for Slack apps | Slack
    • このタイミングで「メッセージ」全般に関して取り扱うセクションが登場しています。
    • 前提として、「今までのattachmentsやinteractive messagesで扱っていた領域を刷新しようとしている」点を抑えておくべきです。
    • すなわち、セクション自体は「New」なのですが、言及されているコンテンツが「すべて新しいこと」ではないということです。私は、「今まで○○で出来たとと何が違うの?」という発想で読もうとしてしまったため、無用に混乱していました。
    • 参考 : 以前のドキュメント An outmoded introduction to messages | Slack
  • Introducing Block Kit | Slack
    • api.slack.com 上にある、「Block Kitのトップページ」とでも言うべきページです。各種リソースへのリンクがまとまっています
    • なお、個人的には、とっかかりとして読むならこちらの記事よりも先述のBlock party – Slack Platform Blog – Mediumをオススメします。少しイメージを沸かせてからが良いのかな、と。
  • Block Kit Builder
    • Block Kitに実際に触ってみれるプレイグラウンドとして、非常にありがたいものです
    • Block Kit Builderは、ゼロから始めるタイミングでも実際になにか作ってみよう!というタイミングでも、最大の武器になると思います
  • Reference: Message layout blocks | Slack / Reference: Block elements | Slack及び Reference: Message composition objects | Slack
    • 実際に「Block KitのAPIリファレンス」として情報を求めるなら、これらのページになります
    • 「Block」と「Element」のリファレンスです
    • と、オマケ的にはなりますが「Object」も併記してみました。
      • Text ObjectやOption Object(セレクトメニューの中のオプション)はどうすればいいのか?はこちらを参照してください

「Block Party」のエントリーをまず読んで、その後にBuilderでUIやリクエスト内容を確認し、Block/Elementの詳細を確認しながら実際に投稿APIを叩いてみる・・・・みたいな流れが、最速でBlock Kitデビューを飾るための道かな?というのが所感です。

おわりに

基本的に「Slackで出来ることが増えると日常業務の革新につながる可能性がある」と思っているので、Slackは、私にとって大好きなおもちゃ箱でもあります!
今回言及したツールとは別に、個人的に作ってみているアプリケーションもあるので、Block Kitと仲良くなっていきたいな!と思っています。

*1:テキストデータについては、「blockのためのelement」ではなく、より横断的なレイヤーにある Message composition objectsにその定義が属しています

*2:探しているのですが、API Reference上での言及を見つけられていません。。。情報をお持ちでしたら、ぜひ聞かせてください!

「やさしいかんしのご提案」をしました 〜コネヒトなりの「監視の民主化」入門〜

$
0
0

こんにちは! @o0h_です。
3月は・・・王様ランキング!!!!おめでとうございます🎉

王様ランキング 1巻

https://cdn-mamari.imgix.net/authorized/5c92686d-9b58-410f-8b54-0037ac110003.jpg

さて、唐突に本題なのですが
先日、入門監視を読んで思ったこと・感じたことを当ブログに投稿しました。

tech.connehito.com

今回は、ちょっとした続編のようなものになります。

先の記事では、自分自身に生じた内省や「べき論」「目指すべき地点」を中心に取り扱いました。
具体的な「私や他のメンバーが取るアクション」や「変更されていく内容」についてはスコープにしておりません。

当然、こうもデカい口を叩いた以上は、実践をしていく必要があります。
でないと・・・ダサダサ君になってしまいますよね。
そんな訳で、「実際に組織を変えていくぞ」と、その最初の一歩目として 監視の民主化に向けたキックオフを行いました。*1

先日のブログのような内容が「概念」「抽象」だとするなら、こちらは「実践」「具体」に相当するものでもあります。
折角ですので、私と同じような課題感を持った人と共闘すべく、この場で公開してみます!

あくまで社内向けに企画・作成した内容なので、「内輪ならコンテキストがあるから、ちゃんと伝わるだろうけどさ」な部分も少なくありません。
それでも、今回の内容はある程度の一般性を保てているのではないか〜なんて考えています。

ざっと、このような内容になります。

  1. 前半は「監視をどういう風にしたいか」についても再度整理する内容です
    • これまでも、この命題についてアンオフィシャルだったり一部のメンバーに限定した議論をする場は設けていたものの、オフィシャル&エンジニア全員に対して共有する場がなかったので。
    • 先のブログ記事に掲載したスライドも、昼休みの自由参加LT会 で話したものです。ゆえに「オフィシャルな発信・共有」とは呼べません。
    • コネヒトの開発陣に対して、明確に「変えていくぞ」「巻き込むぞ」という姿勢を打ち出そうという魂胆があります
  2. 「モニタリングのための基礎の基礎」のような部分を、改めて言語化・共有しました。
    • 先述の記事でもチラッと触れていますが、本当に形式知化・民主化していくためには「自分の中にあることを、当たり前化していないか?と全て疑う」くらいの気概が重要になるのだと感じました
    • そのため、本当に初歩の「リクエストを投げてからレスポンスを受け取るまで」を一連の流れとして捉える試みをしています
  3. Cloud Watchの利用方法
    • ここまでが概論・マインドの話で、ここで初めて具体的な「使い方」の話まで混ぜ込んでいます
    • 弊社で最も利用されているメトリクス収集ツールの1つがCloud Watchです。
      そのため、「まずはコレが使えないと話ができない」状態になってしまっています。
      それは同時に、「問題を自分ごと化する」のを遠ざける要因となります。とても良くない
    • そこで、「ツールを知ってもらう」「実際に画面を見てみる」という試みをしました

今回の話は、これから推し進めようとしている「監視の抜本的な叩き直し」という大きな流れの中での、イントロ + ちょっと入り口の扉を叩く!くらいのイメージかな〜と捉えています。

私は、ここから始めていく一連の取り組みを「やさしいかんし」と呼ぶことにしました。
平仮名表記なのは、やさしさ(易しさ、優しさ)を雑に演出しているからです。

個人的には「監視とか障害対応って、なんか怖い。いかつい」みたいな世界が早く滅びてくれることを祈っておりますので。真に怖いのは開発であり、監視は湿布みたいなものでありたい。

スライド中でも触れていますが、現実としてコネヒトのやり方は「理想的な監視」にはまだまだ遠いように思っています。
例を挙げれば、「入門 監視」によると、アラートはちゃんとユーザー視点で考えられるべきとされています。それに対して、まだまだ「OSレイヤーでのアラート」等に頼らざるを得ません。*2
きっと、実現すると「今より良い」世界にたどり着けるでしょう。

そうした現状を一旦素直に認めつつも、「今のメンバーを鑑みて、さらに現状のモニタリングのデザインを踏まえた上で、即時的効果を望める取り組み」があると考えています。
それが「手順書の整備・共有」と「監視のためのトレーニング」です。
前者は「監視の理解を深める」もとであり、後者は「情報にアクセスできる」ための整備です。

できること、怖くないことが増えてくればマインドも変わっていくと期待できます。
逆に言えば、色々なかけたピースを積み上げていって、全員のマインドが変わるくらいまで徹底的に「やさしく」していきたいなーという所存です。

ともすれば、「役割」としての監視というのは、メンバーに対しても「口うるさい」存在になって行くかもしれません。
どうも不幸だよな、と感じます。

それよりかは、アラートや障害対応はもちろん、「モニタリング」を身近かつ実際的なものとして捉えて、例えば開発メンバーが自主的に「ちょっとラグかったからクエリチューニングかけといたわwww」なんて取り組みが行き交うような現場の方が、活き活きとプロダクトを愛でられるのではないでしょうか。

監視は「安心」のためのいち手段です。
安心があるところには、余裕や平和が生まれます。
メンバーとして関わるなら、自分もメンバーもストレスが少なく楽しめる現場を望みます。
そういった理想への手伝いという意味も込めて、やれることがたくさんあるんだなぁと感じています。

もちろん、この話は一朝一夕で成立するものでもないし、根気はいると思うのですが、
まぁ丁寧にやっていければたどり着けるんじゃないかなーっていうことで、
ときには勢いに任せつつ、どんどん他人を巻き込んで大きなうねりを作っていくぞ!!という気持ち。

appendix

この「監視ブーム」に後押しされる形で、モニタリングや障害対応についての理解を深めてくれる情報が多く共有されてきています。
個人的に、ここ最近で気になった・刺さったものを列挙してみます。
どれも鋭い考察だったり、深い気づきを与えてくれる内容です。

もし、当エントリーに少しでも感じるところがあったようでしたら、
(きっとココよりも、もっと面白いので!)ぜひ、ご覧になってください。

We're hiring!

(めっちゃくちゃ久しぶりに採用情報を貼ったな・・・!)

そんな感じで、「サービス良くするためにまぁ色々やってみたいよ!」系のPHPerさんがいらっしゃいましたら、WantedlyでもTwitterでもお気軽に絡んでください〜 www.wantedly.com

I'm looking for..!

こっちは私の、個人的な課題感です。だれか助けてください・・・


それでは!金城がお送りしました。

*1:先日、弊社にて開催した勉強会での私の発表内容もこの内容を想起しながらまとめたものになります

*2:緊急的にすべてを作り変えるほどは、「コネヒトの現状の監視の脆さ」は差し迫った驚異ではありません。プロダクトチームを含め、より今後アグレッシブに動いていくための、またHR方面での変化に耐えうる基礎を築くための投資だと考えています

PHPerKaigi 2019にシルバースポンサーとして協賛いたします!

$
0
0

こんにちは。サーバーサイドエンジニアの 高野 (@fortkle) です。
さて、今日はイベント協賛の告知をさせてください!

PHPerKaigi 2019に協賛いたします!

タイトルにもある通り、PHPerKaigi 2019にシルバースポンサーとして協賛いたします。
コネヒトではメインプロダクトである「ママリ」を始めとして開発のメイン言語としてPHPを活用しており、フレームワークとしてはCakePHPを採用しています。

phperkaigi.jp

イベント概要

PHPerKaigiはどんなイベントか、公式サイトから拝借すると

PHPerKaigi(ペチパーカイギ)は、PHPer、つまり、現在PHPを使用している方、過去にPHPを使用していた方、これからPHPを使いたいと思っている方、そしてPHPが大好きな方たちが、技術的なノウハウとPHP愛を共有するためのイベントです。

という 過去・現在・未来PHPerに向けたお祭りのようです! 他のカンファレンスと同様に公募トークがありつつ、数人で特定のテーマについてディスカッションするInteractive Round Tableや、アンカンファレンスなどちょっと違ったことも企画されているとのこと!

タイムテーブルもすでに発表されているので興味がある方は要チェックです!

タイムテーブル | PHPerKaigi 2019 - fortee.jp

3日間にかけて行われる大規模なイベントなのでどのトークを聞こうか迷っちゃいますね。 個人的には、設計やアーキテクチャの話と、PhpStorm/コードリーディングまわりの話と最終日のLTが気になっています!

最後に

ここまで読んでくださった皆様、ありがとうございました。
そして、 PHPerチャレンジ中の皆様、お目当てのPHPerトークンはこちらです!

#EnjoyPHPWithConnehito

それでは!

コネヒトではPHPerを積極採用中です!

www.wantedly.com

新米マネージャーが1on1で実践していること

$
0
0

f:id:itosho525:20190409183944p:plain

こんにちは。サーバーサイドエンジニアの @itoshoです。

Bリーグ(日本のプロバスケットボールリーグ)がシーズン佳境を迎え、週末はDAZN漬けの毎日を送っています🏀*1

というわけで、今日はバスケの1on1の話…ではなくミーティングの方の1on1の話をしたいと思います。僕は半年ほど前からプレイングマネージャーのようなポジションでマネジメント業務をしており、その中で1on1ミーティングも定期的*2に実施しています。

1on1については導入企業も増えてきており、事例も広く公開されてるようになってきましたが、まだまだ現場の個別具体的なノウハウは世に出てきていないと個人的には感じています。そこでこの記事では半年間の振り返りと知見の共有を兼ねて、僕が1on1で実施した取り組みを4つ紹介させていただきます。

なお、前職等でも多少のマネジメント経験はありますが、ガッツリやるのは初めて+コネヒトでは初めてのマネジメント経験になるので新米マネージャーという表現をさせていただいております。

1. 1on1の目的を共有

まず、初回の1on1では目的の共有を行いました。一口に1on1と言っても、社長が実施する1on1と直属の上長が実施する1on1は役割が違います。また、個々人が1on1に対して抱いているイメージや期待値も様々です。ですので、最初にそのギャップを埋めるために僕が想定している1on1の目的やイメージなどを伝えるようにしました。

具体的には以下の目的でやるよ!ということを共有しました。

## 1on1の目的
- 設定した目標を達成するための支援 
- 生き生きと働ける(≒その人が100%の力を発揮出来る)ようにするための支援
  - もやもやしていることや本当はやりたいこと何でもいいので話してください
- よろず相談
  - 会社関係なくキャリアのお悩みとかあれば(話したい人はプライベートの話でもOK)

また、これは雰囲気というかただのイメージの共有ですが、野球で例えると僕(メンター)は監督やコーチではなくキャッチャーでメンバー(メンティー)はピッチャーだよということを伝え、1on1はキャッチボールをするような場であることもセットで共有しました。

2. 1on1シートの作成

目的の共有と併せて、面談シートのような1on1シートを作成しました。個人的に1on1では雑談も大切だと思っているので、あまりガチガチにやりたくないと思っています。とは言え、やってる感だけ出して、目標の達成支援が出来ていないなら、それはメンバーの貴重な時間をいたずらに奪っているだけなので、トラッキングも兼ねて1on1の数日前に1on1シートを用意して事前に話したいことなどを書いてもらうようにしていました。また、僕からも気付いたことがあれば積極的に書くようにしていました。ただ、1on1を受ける側からすると準備のコストが高いと1on1が億劫になってしまうこともあるので事前に書くのは任意にしていました。

1on1シートのフォーマットは何度かアップデートを行い、現在は以下のような形で運用しています。

## YYYYMMDD: 第X回

### お話
- 事前に話したいことがあれば書いておいてください!

### プチ振り返り&フィードバック

#### よかったこと
- 最近よかったことや上手くいったことをお互い書くコーナー

#### よくなかったこと
- 最近よくなかったことや改善したほうがよいことをお互い書くコーナー

### Todo
- メンターの宿題を書くコーナー

簡単に説明すると、最初のお話枠は何でもよいので話したいトピックがあれば書いてもらっています。2つ目のプチ振り返り&フィードバック枠は日頃からカジュアルにフィードバック出来る場があったほうが良いかなと思い、メンバーが自分の行動でよかったと思うことやよくなかったと思うことを書き、僕はその人を傍から観察して、よかったと思うことやよくなかったと思うことを書くようにしています。基本的にはポジティブなフィードバックが多めですが、お互いに書き、それを共有することで期待値調整や認識齟齬の早期解消を行っています。最後のToDo枠は1on1の過程で発生した僕がやるべきタスクを忘れないようにメモします。ここで書いたタスクは次の1on1で進捗を報告したり、対応したタイミングで共有したりしています。

3. フィードバックワークの実施

コネヒトではOKRによる目標設定をしているのですが、その過程で中間振り返りを実施するタイミングがあります。そこで目標達成のためにいつも1on1より長めに時間を確保し、目標の振り返りと併せてワークショップ形式でフィードバックを行いました。

いわゆる、ジョハリの窓に近いようなワークなのですが、目的としては、

## フィードバックワークの目的
- 自身の振り返りと他者の振り返りを掛け合わせることで、気付きと学びを得る。
- そして、行動を変える一歩を踏み出すための後押しをする。

というのを掲げ、以下のような流れでワークを行いました。

## フィードバックワークの流れ

### 1. メンバーが以下の内容を付箋に書く
- 目標を意識して移せた行動や言動
- 目標を意識していたが出来なかった行動や言動

### 2. 僕が以下の内容を付箋に書く
- 目標に沿っていたと思う行動や言動
- もう少し目標に沿わせられたと思う行動や言動

### 3. それぞれの付箋を発表する
- 発表された付箋をメンバーが以下の画像のような四象限にマッピングする

### 4. マッピングされた付箋をみながら質問し合う
- 何故出来ないか深掘りしたりどうすれば出来るようになるか考えたり

### 5. 最後に今後注力したいポイントを1つ決める
- 決めたものは1on1シートに記載する

f:id:itosho525:20190409154121p:plain

やってみた所感としては、対面でやるフィードバックよりもコトに向かいやすい(僕のフィードバック力不足に依るところも多いですが)点が非常に良いなと感じました。

4. オフサイトでの実施

普段の1on1はオフィス内*3で行っているのですが、たまにカフェなどのオフサイトでも1on1を実施しています。もちろん、オフィス外なのでコンフィデンシャルな話は出来ませんが、いい意味で仕事っぽくない雰囲気になり、いつもと違う話が構造的にもやりやすいので時々オフサイトでやるのは良いなと思います。ちなみに事前に苦手な飲み物がないかどうかを確認しておくことも地味に大切です。

まとめ

このようにまとめると、ややもすればいい感じに1on1をやっているようにみえるかもしれませんが、まだまだ勉強不足で試行錯誤の毎日です。それでも、僕は1on1の質はメンバーのことを考えている量に比例すると思っているので、これからも日々努力を積み重ねていきたいと思っています。冒頭にも述べましたが、1on1の現場の個別具体的なノウハウはまだまだ世に出てきていないと感じています。それは最適解が会社や職種、個人、はたまたフェーズなどの変数によって大きく異なることに起因するのも原因の一つだと思います。しかし、だからこそ様々な事例を知ることも重要だと思うので、またノウハウが溜まってきたタイミングで定期的に共有を行っていきたいと考えています。この記事が誰かのためになれば幸いです。

*1:ちなみに当方、アルバルク東京のブースターです。

*2:基本的には隔週1回30分のペースで実施していますが、頻度は各人の状況や時期に応じて適宜見直しています。

*3:オフィスで実施する場合も、会議室っぽくないスペースかつ対面にならない場所を選ぶことが多いです。

Droidcon Boston 2019に行ってきました!

$
0
0

f:id:tommy_kw:20190411215936j:plain

こんにちは!

Androidエンジニアの富田です。4/8、4/9にDroidcon BostonというAndroidエンジニア向けのカンファレンスがボストンで開催されました。国内のAndroidカンファレンスのブログは比較的多いと思うのですが、一方海外に目を向けると日本語ブログが少なく、どんなカンファレンス内容か気になることはないでしょうか?今回はDroidcon Bostonに参加してきましたので、気づきやナレッジを共有します。

Droidcon Bostonって?

www.droidcon-boston.com

Droidconとは、Androidエンジニア向けのグローバルなカンファレンスで、開発者同士のつながりを深めたり、技術の知見を共有するカンファレンスです。今回参加した開催地はボストンですが、それだけではなくニューヨークやロンドンなどでも開催されている大規模なカンファレンスです。

僕はDroidconに一度も参加したことがなかったのですが、DroidKaigiの登壇者、かつDroidcon Bostonスタッフでもある@droid_singhさんから‏幸運にもDroidcon Bostonのチケットを頂きましたので、初参加させて頂きました!色んな縁があるのだなとしみじみ感じたので、日々徳を積んでいこうと心に誓いました。

カンファレンス全般

Droidcon Bostonは2017年からスタートして、今年で第3回目となります。トラックは2つあり、トータル27トークセッションと4つのワークショップがありました。DroidKaigiと比べると参加者は若干少なく規模も小さめでしたが、立ち見をすることなくどのセッションでも座って落ち着いて見ることができました。

マルチトラックイベントにおいて、気になるセッションや時間を有効活用してセッションをみたいものですよね。そんな時に役立つのがカンファレンスアプリです。全体のスケジュール確認はもちろんのこと、気になるセッションが始まる前のプッシュ通知がくるので重宝しました。キャプチャではわからないのですが、カンファレンス当日には、アプリの最下部に「JUMP TO CURRENT」というボタンが表示され、それをタップすると進行中のセッションにスクロールされるようになっていました。こちらのカンファレンスアプリのソースコードも公開されているので、気になる方はご覧ください!

f:id:tommy_kw:20190413155603g:plain

カンファレンスの楽しみといえば無料でいただけるグッズですよね。ピンバッチやシールなど頂き、さらにこんな可愛いTシャツを頂きました!

f:id:tommy_kw:20190411215854j:plain
Droidcon Boston Tシャツ

また、全体を通して全てのセッションでライブスケッチを行なっていることに気づきました。下記のセッションを見ていただくと、登壇者の横に大きなボードがあるのがわかります。セッション開始と同時に下書きなしでセッション内容を描き始めます。

f:id:tommy_kw:20190411220750j:plain
Building @ speed of thoughtのセッション

そして実際に出来上がったスケッチがこちらです!60分枠のセッションがほとんどだったのですが、限られた時間でこのクオリティって...本当すごいですよね!セッション自体を見るのはもちろんですが、ライブスケッチを見るだけでも楽しめます。

f:id:tommy_kw:20190411221230j:plain
巨大なライブスケッチ

セッション一覧

セッション内容にはJetpack、Kotlin、テスト、Firebase、Flutter、Coroutine、RxJava、ML、アーキテクチャなど様々なジャンルで構成されていました。セッション一覧スライドに関しては以下のGithubにて管理されており、今年のセッションスライドだけでなく、20172018年分のセッションスライドもキャッチアップできるようになっています。ご興味ある方はぜひご覧ください!ここからは特に気になったセッションを3つ紹介します。

github.com

Do the Loco-MotionLayout: Building animations with MotionLayout

@mikescamellさんによるMotionLayoutの紹介です。MotionLayoutがどのように機能するか基礎についてサンプルコードを基に体系的に学ぶことができます。MotionSceneとは何か、またそれを利用して状態とレイアウトから分離する方法、トランジションのトリガーとなるクリックとスワイプの利用方法、KeyAttributesを利用してアニメーションの微調整方法などまで言及されていました。

f:id:tommy_kw:20190413151129g:plain
サンプルアプリ

Destination navigation: You’re going to love the transition

github.com

@emmaxさんによるNavigationアーキテクチャコンポーネントの入門紹介です。Android開発を加速するJetpackの一つであるのNavigationの利用方法について説明になります。基本利用からSafe Args、Conditional Navigation、Deep Link、テスト方法などまで言及されていました。

Leveling Up As An Android Dev

github.com

@moyheenさんによるAndroidエンジニアのキャリアについての紹介です。Android向けの技術カンファレスなので技術的な内容のセッションは多いですが、このセッションではキャリアについて紹介されています。Androidエンジニアの各レベルで求められていることって意外とわからないものですよね。今回紹介されていた内容は以下の通りです。

  • ジュニアエンジニア
  • ミドルエンジニア
  • シニアエンジニア
  • リードエンジニア
  • マネジメント
  • その他(GDEなど)

各レベルで何をすべきか、そして今のレベルを把握することによって、次のレベルに前進するための情報を得ることができます。

最後に

ひょんなことからDroidcon Bostonに参加させてもらったのですが、グローバルなカンファレンスであり、かつ豊富なジャンルのセッションでとても刺激的でした。スライド一覧を見ていただくと興味のある内容もあると思いますのでぜひご覧ください!また、Droidconはボストンだけでなく、様々な地域で開催されているため、Droidcon Bostonをきっかけに他のDroidconにも参加して行きたいと思います。以上になります、ありがとうございました!

imgix導入でコンテンツダウンロード量を85%削減した話

$
0
0

こんにちは。インフラエンジニアの永井(@shnagai)です。

今回は、imgixという画像変換に対応したCDNを導入して、コンテンツダウンロードの削減を実現した話について書こうと思います。

imgixとは

はじめに、imgixって何と思われる方も多いかと思いますので簡単に特徴を紹介します。

  • クエリパラメータで、画像のリサイズや圧縮が出来るCDNサービス
  • S3をバックエンドに指定出来るので、画像のコピー等が不要でそのまま使える
  • バックエンドはFastlyが使われているので高速配信
  • 国内だと、日経や一休で採用実績あり
  • コストは、標準プランだとCDN Bandwidth: 8¢/GB + Master images accessed $3/1000

imgix • Real-time image processing and image CDN

導入した背景

ママリが運営しているメディアサイトや記事関連のwebviewにおいて、PCサイズの大きめ画像をどのデバイスにおいても配信していたため、コンテンツダウンロード量が大きくなりモバイル回線で見た時のユーザ体験を損ねていました。

速いは正義ということで、速度改善の第一弾としてimgixの導入を決めました。 Lighthouseのスコアでも画像系の指摘が多くスコアが伸び悩んでいたのでこれを一つのKPIとして導入作業を進めました。

  • Properly size images 20s…
  • Serve images in next-gen formats 15s…

今回の移行で行ったこと

CloudFrontから配信していたサイズの大きな画像をimgixからの配信に切り替え、コンテンツダウンロード量を削減するために、移行と同時にクエリパラメータによる画像圧縮とリサイズ、フォーマット変更を行いました。

基本的なパラメータを下記にまとめたのでご参考までに。

内容パラメータ備考
サイズ圧縮q=値 or auto=compress 動的に圧縮率を変更可能, autoの場合はデフォルトで75%の圧縮率
リサイズ w=値,h=値 動的にリサイズ可能
※fitパラメータで、縦横比維持、トリミング、また顔のズーム等にも対応しています。
画像フォーマット変更auto=format対応ブラウザ配信時にwebp対応

気になる方は、公式ドキュメントに細かく書かれているのでこちらをご覧ください。

下記のように、パラメータを付与するだけで一枚のオリジン画像から簡単にリサイズすることが出来ます。 ほぼ劣化なしにリサイズや圧縮出来る点がimgixの強みだなと個人的には感じています。

元画像 209KB

リサイズ画像(auto=format,compress&q=90&w=400) 32KB

導入後の成果

画像の最適化だけではスコアが劇的に上がるということはないのですが、下記を見ていただくとわかる通り画像系の課題が多かった関係で、一定のスコア向上を実現できました。

特に、今回の狙いだったコンテンツダウンロードサイズの削減が実現出来たことで、モバイル回線でママリを使ってくれるユーザのユーザ体験向上に寄与できた点が一番大きかったです。

コストに関しては細かくは書けないのですが、画像圧縮の結果配信量が減ったのでその分コストカットも実現出来ました。

Lighthouseの結果

そもそものスコアが低いという話はありますが、導入結果としてわかりやすいので参考として貼っておきます。

スコアという意味では、まだまだ改善の余地があるのでフロントエンドエンジニアと協力してより速さとその先にある快適なユーザ体験を追求していきたいと思っているのでまだ途上です。

  • 記事タブのwebview
項目CloudFrontimgix差分
モバイル トータルコンテンツダウンロードサイズ 5551KB 807KB 85%減
パフォマンススコア6374+11
コンテンツの初回ペイント1.0s0.9s-0.1s
意味のあるコンテンツの初回ペイント 3.4s1.0s-2.4s
速度インデックス4.7s4.1s-0.6s
CPUの初回アイドル6.7s6.0s-0.7s
インタラクティブになるまでの時間 8.1s6.7s-1.4s
入力の推定待ち時間460ms190ms-270ms
  • 記事ページ
項目CloudFrontimgix差分
モバイル トータルコンテンツダウンロードサイズ 3682KB 1739KB 50%減
パフォマンススコア2944+15
コンテンツの初回ペイント1.7S1.4s-0.3s
意味のあるコンテンツの初回ペイント 1.7s1.4s-0.3s
速度インデックス10.7s6.0s-4.7s
CPUの初回アイドル15.3s11.0s-4.3s
インタラクティブになるまでの時間 21.9s13.3s-8.6s
入力の推定待ち時間160ms140ms-20ms

導入メリット

導入メリットとして、下記が上げられます。

  • エンドユーザには、コンテンツダウンロードサイズの削減によるユーザ体験の向上を提供
  • アプリケーション的には、よく画像アップロードトリガで走らせたりする画像リサイズ処理をCDN側にオフロード出来る
  • コスト面でも、契約にはよりますがリサイズ等による配信量軽減によるコストダウン
  • 画像のリサイズを人力で行っているようなケースの場合は、その作業もすべてクエリパラメータベースに置き換えることが出来ます

注意点

最後に、imgix導入を検討する上で注意しておいた方がよい点についてもまとめておきます。

料金体系

Imgixは、Master Image数+帯域での課金になります。 Master Imageとはオリジナルのイメージ数のことで、これが無限に増えていくようなユーザアップロード用途で使うと思わぬコスト増を招く可能性があるので事前に検証してコスト計算しておくのがおすすめです。

TLS1.2未対応ブラウザへの対応

TLS1.1以前のSSL通信はサポート外なので、Androidのwebview標準ブラウザだと画像が表示されません。セキュリティ観点から世の中的には少なくなってきていますが、動作確認時にチェックするのがベターです。

サポートや営業とのやりとりは英語が必須

日本の代理店はないので、ボリュームディスカウントの交渉やテクニカルサポートはすべて英語です。ただ、とても親切に対応してくれるのであまりネックにはなりませんでした。

最後に

既に導入していた @akasakasに色々と情報をもらいスムーズに移行を進められたので、この場を借りてお礼を言いたいと思います。ありがとうございました。

コネヒトでは変化を恐れずに良いものを取り入れながらサービスの信頼性向上をミッションに一緒に働く仲間を探しています。 少しでも興味もたれた方は、是非気軽にオフィスに遊びにきていただけるとうれしいです。

www.wantedly.com


AWS Glueを用いてETL環境を構築したお話(RDS for MySQL → S3)

$
0
0

はじめに

こんにちは。2019年3月にMLエンジニアとしてJOINした野澤(@takapy0210)です。

最近はThe Mentalistという海外ドラマにお熱です。犯罪コンサルタントとして活躍する主人公の歯に衣着せぬ物言いやテンポの良さなど、見ていて爽快ですし一つ一つの作品が短いので気軽に楽しめます。(心理学に興味があると楽しさ倍増です)

前置きが長くなりましたが、初めてコネヒト開発者ブログに登場です。テンポ良くいきたいと思いますので、どうぞよろしくお願いします!

今回は機械学習基盤アップデートの一環としてAWS Glueを用いてETLしてみた話について、苦労したポイントなどを中心にお話できればと思います。

導入背景

コネヒトではママリというコミュニティサービスを運営しており、ユーザが投稿する質問に対する検閲フィルタとして機械学習が用いられています。

詳細は弊社CTOのスライドをご覧ください。

現在、モデルの更新が継続的にできていない(≒検閲フィルタのアップデートができていない)という課題があり、機械学習基盤のアップデートを実施しています。
その一環として「RDS for MySQLからデータ抽出 → 機械学習しやすい形へ加工 → S3に保存」のように良い感じでETLしたいよね!という話になり、AWS Glueに白羽の矢が立った次第です。

結論

AWS Glueを用いることでRDSに保存されているデータを抽出・加工し、それをtsv形式でS3に保存することができました。

以下その内訳です。

  • データ件数:約700万件
  • Job実行時間:5分
  • 出力tsvデータ:約3GB

結果としてはやりたいことが実現できた訳ですが、思っていたより複雑で学習コストがかかるな〜という印象を受けました。
(初見が難しいだけで、一度設定できれば以降はスムーズにいけそう感!はありました)

次項から、Glueの説明や設定方法、MySQLからのデータ抽出方法などについて述べていきます。

AWS Glueとは

AWSが提供する完全マネージド型 ETL (抽出、変換、ロード) サービスです。
公式ドキュメントはこちら

f:id:taxa_program:20190417115301p:plain
AWS Glueのアーキテクチャ図

言葉の定義について

上図を見ても分かるようにいろんなワードが出てきます。それぞれの定義が曖昧になり兼ねないので、一度整理しておきます。

  • Data Stores
    データを永続的に保存する(している)リポジトリ。S3バケットやRDS。本記事ではRDSを示す。

  • Data Source
    Job(Script)への入力として使用されるData Stores。 本記事ではRDSを示す。

  • Data Target
    データの書き込み先のData Stores。本記事ではS3を示す。

  • Data Catalog
    AWS Glue 環境を管理するためのテーブル定義、Crawler、接続情報などを管理するサービスの総称。

  • Crawler
    Data Storesに接続しデータのスキーマを判断し、Data Catalog にメタデータテーブルを作成するサービス。

  • Job
    ETL 作業を実行するために必要なビジネスロジック。プロパティ(Scriptのファイル名や保存先、接続情報)で構成される。このJobの作成時にData SourceとData Targetを指定する。 JobはApache Spark ETL ジョブPython シェルジョブの2種類から選択することができ、スケジュール起動/イベント起動が可能。

  • Script
    Jobに含まれるETLの実行処理スクリプト。S3に保存される。

構築したアーキテクチャ

今回構築したアーキテクチャの概要図です。

冒頭でも述べましたが、今回の目的はRDSに保存されている情報をGlueを使って抽出・加工し、それを.tsv形式でS3に保存することです。

f:id:taxa_program:20190417123456p:plain
今回構築したアーキテクチャ概要図

構築手順

今回は下記手順で構築しました。

  1. サブネットの作成
  2. セキュリティグループの作成
  3. Glue接続情報のIAMロール作成
  4. Glue接続情報の作成&接続テスト
  5. CrawlerのIAMロール作成
  6. Crawlerの作成&実行
  7. S3バケットの作成
  8. JobのIAMロール作成
  9. Jobの作成&実行

Glue接続情報とはData Storesへ接続するためのプロパティ情報です。これを元にClawlerを作成していきます。 そしてこのClawlerを実行してRDSのメタ情報を取得し、取得したメタ情報を元にJobでクエリを発行する、という流れです。

ここで押さえておきたい事としては、

  • Glueを利用する際には、最低限として「接続情報」「Crawler」「Job」の3つが必要だということ
  • そしてそれぞれに対してIAMロールが必要(接続情報用、Crawler用、Job用)だということ

だと思います。

構築する際のポイント

上記手順の中でも苦労したポイントについてお話します。大別すると2点です。

  • Glueには自己参照ルールが必要だった(セキュリティグループの話)
  • RDSを用いたユースケースがなかった(Jobの話)

Glueには自己参照ルールが必要だった件

手順「4. Glue接続情報の作成&接続テスト」で接続情報を作成しようとしたときに、適切なセキュリティグループを確認できません。JDBCの接続タイプを変更し、接続の追加を再試行しますというエラーメッセージが表示されました。

f:id:taxa_program:20190417150236p:plain
接続情報作成時のエラー

上記を解消するために、セキュリティグループに関しては下記のように設定する必要があります。

  • Glue 側のセキュリティグループ
    自己参照ルールにて TCP の全ポートからのインバウンドアクセスを許可する必要がある

  • Data Stores(RDS)側のセキュリティグループ
    Glueから3306ポートにアクセスできるようにする必要がある

今回の場合は、

  1. RDSにアタッチするセキュリティグループ(SG-A)とGlueにアタッチするセキュリティグループ(SG-B)を作成する。(新規作成しなくても良い。2つのSGを分けることが重要)
  2. SG-Aのインバウドルールに「TCP、ポート:3306、ソース:SG-B」を追加する。
  3. SG-Bのインバウドルールに「TCP、ポート:0-65536、ソース:SG-B」を追加する。(こちらが自己参照ルール)

という手順で設定しました。

RDS for MySQLを用いたユースケースがなかった件

冒頭でも述べましたが、GlueのJobはApache Spark ETL ジョブPython シェルジョブの2種類から選択することができます。

今回は「学習コストが低い」「分散処理するほどの大量データではない」などの観点から、Pythonシェルジョブを用いることにしました。

知の宝庫であるインターネットを駆使してユースケースを探しましたが、RDSからデータを取得するユースケースは見当たらず・・・。
公式ドキュメントなどにRedShiftを利用した事例はいくつかありました)

AWS サポートの力も借りつつ試行錯誤した結果、MySQL用のライブラリを外部よりインポートすることで実現できたので、次項でその手順をご紹介できればと思います。

PythonShellジョブからMySQLを利用する手順

Python Shellで外部のライブラリを使用したい場合はeggファイル利用する必要があります。
下記が大まかな手順です。

  1. eggファイルを作成
  2. 作成したeggファイルをS3にアップロード
  3. eggファイルをジョブに連携

こうすることで、JobからMySQLが利用可能になります。
(eggファイルの作成は、ローカルでも任意のインスタンス上でも可能ですが、python2.7がインストールされている必要があります)

1. git cloneで下記のPyMySQLライブラリをコピー

これは任意の場所にcloneすればOKです。

$ git clone https://github.com/PyMySQL/PyMySQL 

2. 任意の場所にpackage作成用のディレクトリを作成

$ mkdir package
$ cd package

3. packageを作成(python2.7.15で実行)

$ pip install PasteScript
$ paster create -t basic_package pymysql

設定項目は、全てデフォルトで進めました。

4. ソースコードを配置

1.でgit clone したディレクトリのpymysqlディレクトリの内容を、2.で作成したpackageディレクトリ配下にすべてコピーします。

$ cp -pr<git cloneしたパス>/PyMySQL/pymysql/* <2.でpackageディレクトリを作成したパス>/package/pymysql/pymysql/

※__init__.pyについては、上書き保存します。

この時点で、ディレクトリ構成は下記のようになると思います。

f:id:taxa_program:20190417184915p:plain
ディレクトリ構成

5. eggファイルを作成

packageディレクトリの配下(setup.pyファイルが作成されているディレクトリ)で、以下コマンドを実行します。
これでeggファイルが作成されます。

$ ls
-> pymysql  pymysql.egg-info  setup.cfg  setup.py 

$ python setup.py  bdist_egg
$ ls
-> build  dist  pymysql  pymysql.egg-info  setup.cfg  setup.py 

6. distディレクトリの下に、eggファイルが出来ていることを確認

$ cd dist
$ ls
-> pymysql-0.1.dev0-py2.7.egg

下記のようなeggファイルが作成されていれば問題ありません。

f:id:taxa_program:20190417185007p:plain
ディレクトリ構成

以上でインポートするeggファイルの作成は終了です。

7. 作成したeggファイルをs3にアップロード

CLIを使わずとも、マネジメントコンソール上からアップロードしても問題ありません。

$ aws s3 cp ./pymysql-0.1.dev0-py2.7.egg <s3パス>/pymysql-0.1.dev0-py2.7.egg

8. GlueのPython Shell Jobを設定

マネジメントコンソール上でジョブの作成を行います。 Pythonライブラリパスに 7.でアップロードした.eggファイルを指定してジョブを作成します。

f:id:taxa_program:20190417185200p:plain
Job作成時にPythonライブラリパスを指定

以上でMySQLが利用できるPythonShellジョブの作成は終了です。

スクリプト

参考までに、今回作成したスクリプトを公開します。 (一部、値をマスクしています)

import boto3
import sys
import csv
import pymysql.cursors
import pandas as pd
import re
from io import StringIO, BytesIO

connection = pymysql.connect(
    host='XXXXXXXXXX.rds.amazonaws.com',
    user='user',
    db='dbname',
    password='password',
    charset='utf8mb4',
    cursorclass=pymysql.cursors.DictCursor
    )

sql = "SELECT column1, column2 FROM table WHERE 0 = 0 ORDER BY column1 desc"
df = pd.read_sql(sql=sql, con=connection)

# Delete tab char
df['column1'] = df['column1'].apply(lambda x: x.replace("\t",""))

# Replace CR char
df['column1'] = df['column1'].apply(lambda x: x.replace("\n"," "))

# Convert DF to TSV format
csv_buffer = BytesIO()
df.to_csv(csv_buffer, sep='\t', encoding="UTF8") #TSV出力# output to S3 as CSV file
bucket = "s3-bucket"
key = "hoge/hogehoge.tsv"
s3 = boto3.resource('s3')
obj = s3.Object(bucket, key)
s3response = obj.put(Body=csv_buffer.getvalue())

最後に

テンポ良くいくつもりが盛りだくさんになってしまいました。

現段階ではGlueを用いてRDSからデータ抽出するユースケースがネット上にないと思うので、この記事が一人でも多くの方の参考になれば幸いです!

PHPフレームワークのバージョンアップを支える技術

$
0
0

GWいかがでしたでしょうか?
私はひたすらに「何もしないぞ!」を徹底した結果、漫画を読んで「色々な世界を旅して」「色々な出会いと別れを繰り返して」過ごしました。

その中でも、「子供はわかってあげない」を久しぶりに読み返し、

人は教わったことなら教えられるんだよ

からの

僕は誰にも教わってないんだ。・・・だから教えるのが難しいの当たり前なんだなって思って・・・少し楽になったかな

というくだりにグッと来ました。
「教えられることがある」や「教えてくれる」というのは、それだけで尊いものだな〜というリスペクトを忘れないようにしようと思うのと同時に、自分や他人の「持てるもの・持てないものを見極めて、許したり奮ったりしてけたらな」とも思いました。
なんにせよ、他人に教えられる人はすごい!🎉

子供はわかってあげない(上) (モーニング KC)

さて、こんにちは、サーバーサイドやっております 金城 (@o0h_)です。

今回は、「PHPフレームワークのマイナーアップデートをしようとしたら少し大変だったので、工夫したこと・やったこと」のお話をします。

TL;DR

  • CIの活用 / (ユニット)テストを日頃から充実させておく
  • Migration GuideやPRに目を通して、影響範囲を予想する。対応イメージを考える
  • ツールによる自動対応が可能なモノは積極的に活用する
  • 「どっかで何かが起きた」ときのgit-bisect
  • リグレッションテストの計画と実施

https://cdn-mamari.imgix.net/item/500x0_5cd98323-e73c-4933-8afd-0036ac110002.jpg.jpg

コネヒトのサーバーサイドアプリケーションは、原則として「コマメに依存パッケージのアップデートをする」戦術を採っています。
が、ママリのメインとなるバックエンドアプリケーション (api)は諸々の事情で更新が遅れていました。
具体的に言えば、CakePHPの 3.6.xで稼働させており、 3.7.xに移行できていなかったという状況。

3月末に私がチラッと手出しをしかけていたものを、本気を出した @supermanner によってマージ可能な状態まで持っていってくれた・・・!ということで、夢が叶いつつあります。

この「CakePHPの移行」をケーススタディとしつつ、「フレームワークのバージョンアップ面倒くさいよねどうやろっか」はあるある話だとも思うので、なるべく問題を一般化して振り返ってみたいと思います。

1. CIの活用 / テストを日頃から充実させておく

ある程度の単体テストが充実していれば、細かな修正などについては原則として「CIが通ればOK」「テストで保証しにくい、外部システムとの連携部分だけ目で確認する」といった方針が取れます。 それと同時に、静的解析などの活用も「安心できるコード」を支えてくれるので、積極的に扱っていきたいところです。
例えば phpstan-deprecation-rulesは、廃止予定となったメンバ等の利用を検知してくれます。

github.com

また、静的な解析だけでは難しいルール違反も、テストカバレッジを高めておけば動的に「機械が弾いてくれる」状態を実現できます。
一例としては、「引数によってはメソッドの利用方法が推奨されなくなっている」場合などです。

実際に、CakePHPでは「メソッド自体は有効だが、アクセサとしての利用が非推奨/ミューテータとしての利用だけが認められるようになったため、引数無しでのコールをE_DEPRECATEDを発火する」といった変更も多々行われています*1
こうした場合には、「テスト実行時に実際にエラーとなる」状態が担保されていると検知も簡単です。

2. 変更内容を確認する

多くの場合、バージョンごとの「変更内容」がまとめられていると思います。 CakePHPの場合、「パッチバージョンの場合は公式ブログ(Bakery)を見る」「マイナーバージョンの場合はMigration Guideを見る」ことで、その内容を簡単にキャッチアップすることができます。

例: CakePHP3.7.6の場合
https://bakery.cakephp.org/2019/04/09/cakephp_376_released.html

例: CakePHP 3.7.xの場合
https://book.cakephp.org/3.0/en/appendices/3-7-migration-guide.html

これらの内容に目を通すことで、「自分の利用しているアプリケーションに関係ありそうな変更はあるか」「deprecatedやnew featureはあるか」といったイメージが掴めますし、それに応じて「どのくらい大変そうかな?」というザックリとした"覚悟"もできると思います。
*2

CakePHPでは、3.7/3.8については「4.xに向けて大きな変更をしない、廃止予定のコードやAPIの整備を進めていく」という流れで動いています。*3

4.xへのアップグレードは、これらの「廃止予定となっている内容を利用していなければ、スムーズに行えるようにする」と説明されているので、今の段階から少しずつ着実に対応していこうというのは大きなモチベーションとなるわけです。

3. 自動修正ツールの積極的な活用

CLIツールの利用

「大きなロジックの変更ではないが、地味に面倒・・・」という修正は、フレームワークのアップデートにつきものです。
例えば、3.7.0から「テストケース中で利用するFixtureの宣言は、snake_caseではなくCamelCaseで行うように」という変更が入りました

Throw warning when using underscored fixture names. · cakephp/cakephp@f86a585 · GitHub

すると、ほぼ全部のテストクラスが対象となるので、手でいじるのがめちゃくちゃ面倒くさい・・・・・・・・
嬉しいことに、こうした変更に対して「CLIからワン・コマンドで自動修正してくれる」というツールがあります。

Cakeのコアメンバーであるdereuromark氏が独自にメンテナンスしているupgrade toolはその1つです。 github.com

また、個人的に最近注目しているのはrectorというツールです。 getrector.org

これについては、昨年のConnehito Advent Calendar中でも @fortkle が触れていました。

fortkle.hatenablog.com

現在、rectorはsnake -> camelの変更に対応しているので、気の遠くなるような作業もほんの数分足らずで終了することができました・・・

f:id:o0h:20190513230542p:plain
当該のコミットの様子。これを手でやっていたら大変・・

他にも、php-cs-fixerなどのツールも、便利に利用することができると思います。
これらの自動整形ツールは、間違いなく人間のストレスを軽減しますし、また作業内容の確実性の担保という意味で実装者・レビュアー双方に対して安心感を提供することになります。

開発用ツールの気軽な導入のために

便利そうなツールを発見し、いざ導入しようとすると依存パッケージのコンフリクトによって阻まれることもあります。
勝手なイメージですが、php-parserなどはよく衝突するのではないでしょうか・・・・

そうした場合に便利なのが、 composer-bin-pluginです。

github.com

これは、「vendorやcomposer.lockを、任意の名前空間ごとに独立させて扱ってしまおう」というもので、
例えば「phpstanの実行に必要なvendor」「rectorの実行に必要なvendor」とった具合に、互いを隔離して利用することが可能です。

具体的なユースケースとしては、dereuromark氏がCakePHP3.6リリース時に投稿しているエントリーにて言及があります。

CakePHP 3.6 is coming – DerEuroMark

また、先日のPHP勉強会@東京のLTにて個人活動として紹介もさせていただいたので、よろしければ御覧ください。

what-is-composer-bin-plugin - Speaker Deck

IDEの活用

先程、「今回のアップデートは、主にDeprecatedへの対応となる」という言及をしました。
その際に大活躍したのがPhpStormです。
「deprecatedと思われる機能を一括検索する」という機能を備えています。

Code > Run Inspection By Nameから Deprecated(PHP|General)を実行すると・・・一網打尽です!

f:id:o0h:20190513231452p:plain

Jet Brainsの記事も併せて御覧ください。

www.jetbrains.com

4. git-bisectの利用

「PJ全体」「多くのファイルを一括して」変更を行っていくと、思わぬ箇所でエンバグしていることもあります。

git-bisectの利用は、「大雑把にかつ的確に問題箇所を特定する」のに役立つかもしれません。

git-scm.com

これは、「最新〜ある地点のコミット」という限界範囲を決めた上で、「ここは正しい・・・ここはおかしい・・・ここは正しい・・・」とyes/noをマークしていきながら、二分探索により最終的に「問題が初めて生じた地点」を発見していくというものです。

5. リグレッションテストの計画と実施

最終的には、「ユーザー観点に立って」「実施に操作をして」、提供されるべき機能が失われていないか・壊れていないかをチェックします。 どんな項目をチェックするか?というのを、実際に練っておくことで、より安心してリリースを迎える事ができます。

コネヒトにはQA専任のチームなどは持っていないので、アプリケーション開発者が自ら&相談しながら項目の洗い出しを行います。
中心になるのは、「主要・重要な機能」「今回の変更内容によって影響が考えられる機能」といった観点でしょう。

f:id:o0h:20190513232702p:plain

コードレビューやテストコードだけでは見えてきづらい部分についても、人の目によって不安を払拭することができます。

まとめ

「コネヒトでスムーズにライブラリやフレームワークの更新を行うために気を遣っていること」を紹介しました。
大方針としては、 安心感を担保するために、使えるものを積極的に使うという表現に集約されると思います。
「自動化ツール(CIやコマンドツール,IDE)の活用」や「人の目を介す箇所の意義設定・デザイン」というのは、あくまでそうした目的を果たすための手段!と言えるのではないでしょうか。

とりわけ、「CIで保証できる範囲・内容を広げておく」「便利なツールを探し、積極的に使う」というのは、対象のフレームワークや言語に限らず共通している価値観だと考えています。
もし手法の未確立や効率化不足がおこると、アップデート作業というのはとても億劫になってしまいます。
更に、「前回の更新から大きく日が開いてしまっている」という状況は、ますます億劫さを加速します。

そうなってしまう前に、チョコチョコとアップデートを行ってみる!というのはいかがでしょうか。

*1:例えば https://github.com/cakephp/cakephp/blob/3.7.7/src/Validation/ValidationSet.php#L65など

*2:余力があれば、実際のコミットも探して内容を見てみる・納得できるようにしてみる、というのも大きな学びになると思います。個人的には、Bakeryにパッチバージョンのリリース情報が掲載されたタイミングで、「ここで言及されている内容はどのようなコード修正になるのだろうか」というのを追うようにしています

*3:内容についてはRoadmapに詳しいです

CodeBuildを使ったECSへのコンテナデプロイ

$
0
0

こんにちは。インフラエンジニアの永井(shnagai)です。

今回は、CodeBuildでのECSデプロイについて書いてみました。 普段、TravisCIを使ってメインサービスのECSのデプロイを行っているのですが、新規開発するにあたりCodeBuildを使ったECSのデプロイを組んでみたのでその内容をまとめています。

内容はざっくり下記4項目について書いてます。

  • CodeBuildのみで行うECSへのコンテナデプロイの構成図
  • 他のCIサービスと比べた時のCodeBuildの良さ
  • CodeBuildの設定でハマった点
  • デプロイフロー

CodeBuildのみで行うECSへのコンテナデプロイの構成図

CodePipelineを使ったECSへのデプロイをする選択肢もあるのですが、これだと運用フローに大きく変更が入るので今回は、現在使っているecs-deployを使ったECSデプロイを移植する形にしました。 全体のデプロイフローとしては下記のような形になっています

f:id:nagais:20190617171151j:plain

他のCIサービスと比べた時のCodeBuildの良さ

個人的に感じた、CodeBuildによるコンテナビルドの良さについてまとめてみました。

プロジェクトの並列度を考えなくて良い

一般的なCIサービスだと契約プランによって並列度には制限あると思います。 従量課金で何プロジェクトでも並列で動かすことが出来るのはCodeBuildならではだと思います!

Dockerイメージビルド時のローカルキャッシュが設定一つで有効化出来る

コンテナをフルビルドするするとめちゃくちゃ遅いですよね。。 もちろんCIサービスでもレイヤキャッシュをバックアップしてごにょごにょすることでキャッシュすることは出来るのですが、CodeBuildだと設定一つですごく簡単に、DockerBuild時のキャッシュ設定で出来るます。 これは、革命的かと思います。

プロジェクトのアーティファクトから下記設定をすることで、Dockerのレイヤキャッシュが有効になります。

項目
キャッシュタイプLOCAL
ローカルキャッシュオプションLOCAL_DOCKER_LAYER_CACHE

※ただ、ローカルキャッシュというだけあって、ビルドによりキャッシュが効いたり効かなかったりまちまちだなという印象です。裏側のアーキテクチャがわからないですが、これはビルドを多数繰り返すことで複数ホストにキャッシュが出来て解決されるものなのか、また別の理由なのかは運用しながら探っていければと思っています。

参考までに、検証時に試したキャッシュ利用有無でのビルド速度の違いです。 f:id:nagais:20190617171539p:plain

DockerのBUILDKITも使える

Dockerビルド高速化における切り札とも言える、BUILDKITもランタイムのDockerが18.06以上なのでサポートされています。 ローカルのビルドはBUILDKIT前提なのだけど、CIサービスが対応してないからデプロイにかかるビルドは遅いみたいな悩みともおさらば出来ます!

buildspec.ymlに下記を記述することで利用可能になります。

DOCKER_BUILDKIT: "1"

IAM Roleで権限をコントロール出来るので、鍵の管理が不要に

IAM Roleでプロジェクト毎に必要な権限を管理出来ます。 CIのプロジェクト毎に鍵の登録をするような運用がなくなるのがgoodだなと思います。

CloudWatchEventsのトリガにCodeBuildのイベントを指定出来るので通知も簡単に書ける

TravisCIでは、エラーハンドリングをしながらSlackを呼び出すことで通知を実装していました。

CodeBuildだと、下記のようなカスタムイベントパターンを指定することで、CodeBuildのステータスをトリガにLambdaを呼び出せます。 プロジェクトの状態検知はこちらに寄せることが出来るので、簡単に通知をすることが出来ます。

このイベントを受け取りLambdaをキックすることで、Slackに飛ばす運用をしています。

{
  "source": [
    "aws.codebuild"
  ],
  "detail-type": [
    "CodeBuild Build State Change"
  ],
  "detail": {
    "build-status": [
      "FAILED",
      "IN_PROGRESS",
      "SUCCEEDED"
    ],
    "project-name": [
      "トリガに使いたいproject-name",
    ]
  }
}

イメージ

f:id:nagais:20190617175251p:plain

CodeBuildの設定でハマった点

CodeBuildは、s3でホストしている静的コンテンツ配信サイトの自動更新には使っていたのですが、久々に触ったら下記の点が変わっていたので少しハマりしました。

ランタイムの指定方法が変わっていた

これまでだと、CodeBuildのランタイム環境は、例えばjsのビルドに使う環境だとaws/codebuild/nodejs:10.1.0というようにプロジェクト側に指定する形だったのですが、今回プロジェクトを作る中で、 aws/codebuild/standard:2.0-1.10.0といったような standardイメージしか選択出来ないようになっていました。

トラブルシューティングにあるくらいメジャーなエラーだったのですが、、、下記サンプルのように、buildspec.ymlの中でランタイムを指定することに気づかずハマりました。

Troubleshooting CodeBuild - AWS CodeBuild

phases:
  install:
    runtime-versions:
      docker: 18
  build:
    commands:
      - echo docker tag replace started
      - ...

プロジェクトの発火条件になるGitHubのイベント設定

CodeBuildはイベントタイプ+細かな条件を指定してプロジェクトを発火出来るのですが、下記の設定にたどりつくまで色々と試行錯誤しました。

これはCodePipelineだとブランチ指定した設定しか出来なかったのを自分の中で引きずっていたというのが大きいのですが、CodeBuildではもう少し細かい発火条件が出来るのを知るまでに少し時間がかかりました。

  • masterへのpush時にプロジェクトを発火させたい場合は下記のような設定をします。

f:id:nagais:20190617172341p:plain

  • tag push時にプロジェクトを発火させたい場合は下記のような設定をします。

f:id:nagais:20190617172401p:plain

デプロイフロー

参考までに現在のこのプロジェクトのデプロイフローは下記のようになっています。

① GithubのPRベースで開発

② masterマージ時に、code buildの[StgProject]が発火して下記要領でステージングへのデプロイを実施

  • Dockerイメージのビルド
  • ECRの該当リポジトリに対して、latestというタグでpush
  • ecs-deploy(shellで書かれたツール)により、対象サービスの更新を行う

③ ステージング環境にてデプロイした変更に問題がないことを確認

④ 本番デプロイするために現在のコードに対してtagを打つ

⑤githubのtag push時に、code buildの[prdProject]が発火して下記要領で本番へのデプロイを実施

  • ECRにあるイメージをタグ名リプレイスしてコピー
    • latestrelease, releaserelease-1gen,release-1genrelease-2gen
    • aws cliのecr batch-get-image, ecr put-imageを利用
  • ecs-deploy(shellで書かれたツール)により、対象サービスの更新を行う

⑥ 本番にて動作確認のテストを行う

⑦ やばいとなった時は、 ecs-emergency-rollback.shにて緊急ロールバック(release-1genイメージ使ったロールバック)を行う

コネヒトでは一緒に成長中のサービスを支えるために働く仲間を探しています。 少しでも興味もたれた方は、是非気軽にオフィスに遊びにきていただけるとうれしいです。

AWSやDockerを駆使してサービスの信頼性を向上させるエンジニア募集 - コネヒト株式会社のインフラエンジニア中途の求人 - Wantedly

GreenkeeperからDependabotに移行しました

$
0
0

f:id:dachi023:20190618154616p:plain

こんにちは、安達 (@dachi_023) です。ちょうど1年前くらいにGreenkeeperを入れた話を書いたんですが、今回はそこから更にDependabotに移行した話をします。

導入にあたって

コネヒトではこれまでGreenkeeperを使って複数のリポジトリでパッケージのバージョン管理をしていましたが、それらのすべてを廃止してDependabotに移行しました。

なぜDependabotを選んだのか

GitHub傘下になったよの記事を読んで気になったのでお試しで使いはじめたのがきっかけで、Greenkeeperを使っていた時に物足りないなーと感じていた部分がDependabotでは解消されていて、乗り換えたほうが効率いいなと思ったのでGreenkeeperを解約してすべてDependabotにしました。

Dependabotの良いところ

  • 複数言語をサポートしているため、言語ごとにツールを選定する必要がない
  • 設定ファイルは必須ではなく、GUIの設定だけでも動作する
  • GitHubのPull Requestに対してAssignee, Label, Reviewerが設定できる
  • セキュリティアップデートは即時投げてくれる

複数言語のサポート

言語ごとに良さそうなツールを探してきて権限を渡して設定ファイルを作ってリポジトリに置いておく、みたいなのはしなくて良くなりそうかなと思ってます。あのツールじゃないと出来ないことがあるんだ、とかそういうのがなければ全部Dependabotに寄せておけば管理も楽で良さそうです。

f:id:dachi023:20190610151632p:plainf:id:dachi023:20190618122219p:plain

設定ファイルは不要

設定ファイルは書けますが、設定画面が提供されているので必須ではないです。ただし、各パッケージでバージョン指定をしたい場合はGUIでは指定できないようです。

f:id:dachi023:20190610152206p:plain

Assignee, Label, Reviewer

https://github.com/pulls/assignedを見て自分がボールを持っているレビューがあるかを確認しているのでAssigneeを設定できる機能がついているのが個人的にはとても嬉しいです。

セキュリティアップデート

セキュリティパッチを含むバージョンが公開されたら随時飛んでくる、というセキュリティ意識が高まる素敵な機能です。セキュリティアップデートだけPR作ってくれる、とかも可能です。

所感

機能自体には満足していますが、週ごとや月ごとにまとめて飛んでくるようにしてるとCIのジョブキューが詰まるのでそこだけ注意が必要かもなと思いました。

リンク

監視の民主化に向けて「モニタリングツール多くない?」という話をしました

$
0
0

こんにちは、サーバーサイドやっております 金城 (@o0h_)です。
最近の癒やしは「幸せカナコの殺し屋生活」です。仕事でも趣味でも何でもいいと思いますが、「私は生きているんだな!」という気持ちを抱えて育んでいくのが大事だな、と改めて気付かされます。

sai-zen-sen.jp

Tl;DR

  1. モニタリングツール増えがち問題; システムが複雑なんだ、しゃーない
  2. 「多すぎるツール」が監視ビギナーのハードルを上げていないかな。下げたい・・・!
  3. 「なぜ複数のツールが必要なのか」の肌感を共有したい
  4. まずは「最初の1つ目」のツールを習得して、次第に使えるツールを増やしていくのが良いのではないか

前置き

「殺し屋」の話をしたので「監視」の話をしたいのですが、コネヒトでは継続的に「監視をもっとできるよーにしよーね!」という取り組みを進めて行っております。
それにはどうしても他人を1人でも多く「巻き込んでいく」部分が必要で、上長とも相談をしながら、対社内に向けての発信を持続的に行っています。

これまでに表明した内容・実施した内容についても過去に当ブログで述べています。 tech.connehito.com

tech.connehito.com

こうした一連の取り組みの狙いの1つには、もちろん「チーム全体の啓蒙・意識付け」というニュアンスも多々ありますが、具体的な形式知化やインプットを通じて最終的には以下の状態の実現を目的としています。

f:id:o0h:20190630203821p:plain

そのためには、スキルやナレッジ的な「できる」とマインド的な「できる」の両方が揃っている必要があります。 「障害対応をできる」「監視=問題検知をできる」ためには、状況を分析する力・理解が欠かせません。
その前提に立つと「ツールを使いこなそう」というのは必須なのですが、同時に厄介な問題もはらんでいるように感じます。

  1. 「見たこともないツール」に対して、どのようにキャッチアップしていいかわからない
    • 能力的な意味での「できない」問題
  2. 他人が障害対応している様子を見ても、名前も知らない&何のためかも分からないツールが多数出てきて、何を学べばいいのかわからない
    • 態度的な意味での「できない」問題

一点目に関しては、個別的なツールのハンズオン形式等でのインプットを行うことでフォローしています。
二点目に関しては、これらを緩和するために「なぜ監視ツールは多いのか」という話を改めて噛み砕き、意味付けを行いました。それが今回の内容となります。

モニタリングツール多くない?問題

おそらく、うまくやっても「数が増える」ものだと思っています。 これは何故か?というと、そもそも「監視しようとしている対象が複雑」だからだと思っています。

モニタリングツールの目的は、大きく分けて

  • アラート用: 大まかな状態(=ヤバそうさ)を知る
  • 調査用: 事細かに情報を提供・享受する

の2種に分かれるのではないでしょうか。
そして、我々が日々向き合っている「システム」というのは、そもそもが複雑なものです。
大小様々なコンポーネントが、相互に絡み合ってできています。

f:id:o0h:20190701213703p:plain
前回の勉強会で利用した資料より、「Webサービスってこんなに複雑」の図
すると、「観察箇所」が増えてきますので、「適切な情報を取り出す」ために「必要な種類が増える」のは自然な事だとも言えます。

・・・そうはいっても、何でもかんでも道具が氾濫してきては、それを触れるようにするだけでも大変な苦労です。
現場に導入すべきツールは、どのくらいが適切か?「入門監視」の言葉を引用します。

f:id:o0h:20190701213646p:plain

ひっくり返して言えば、「必要な情報にアクセスするために必要なら、必要」「それがなくても困らないものは冗長」ということになるのではないでしょうか。

導入しているツールの棚卸しをする

コネヒトでは、ママリに関するモニタリング・データトラッキング等の用途で、様々なツールが導入されています。
主目的はシステム監視ではないが「困ったときに役に立つ」くらいのものまで含めると、こんな一覧ができます*1

f:id:o0h:20190701214554p:plain

これらをすべて完全に理解し、全く別の目的で・・・「なにかしようと思ったときの絶対的な正解はコレ!」と使い分けていくのは、大変に難しいことです。
監視や障害対応に慣れていないメンバーからすると、この「なんかムッチャあるぞ」という事自体が、1つの嫌な壁にもなると思います。
「どのような目的のものか」「どのような立ち位置にあるのか」をイメージしやすくするだけでも、支援になるのではないか?と考えました。

f:id:o0h:20190701214501p:plain

このように「立ち位置」「分析観点」でざっくりとマッピングしてみました。
・・・我ながら、ものすごく強引で語弊があるなぁ〜と思います。
この図表の目的は、「正しさ」よりも「ツールって位置づけがあるのね」という体感を皆に得てもらう事にありました。
「得意分野」が違うツールを組み合わせることで、置かれている状況をより立体的に捉えることができる。そういう理解へ繋ぐための足がかりとして、「扱っている情報や、その内容の扱い方が違う」ということだけを訴えられれば、ひとまずOKです。

ツールは組み合わせて使うもの

入門監視では、監視を組むにあたって「アラートはユーザー視点での監視をしよう」ということを訴えていました。
これは、例えば「CPUの利用率がどのくらいか」という情報よりも「リクエストを送ってから画面表示が完了するまでに0.5秒遅い」のような、end-to-endで「困ったことになっていないか」を主軸にして動こうということになります。

例えば「Mixpanel」「Google Analytics」といった「ユーザー行動のトラッキング」というのは、極めて「ユーザー視点」に近いものと言えます。*2
これらのツールがどうして役に立つか?は、入門監視の第5章「ビジネスを監視する」を覗いてみてください。

さて、実際の現場では「ユーザーの投稿が減ったから、何かしないと!」という情報だけでは困るわけです。背景にある「なぜ」を迅速に正しく切り分けていく必要があります。
そのようなときに、Cloud WatchやDBレイヤーの監視ツールなどが役に立って来るわけです。

f:id:o0h:20190701215632p:plain

どうしても、複数のツールをうまく組み合わせて行かないと障害時の対応や情報収集は頓挫してしまいます。
「問題箇所の特定」は、経験値から来る嗅覚に頼ってドライブしていく部分も大いにあると思います。そのハンディを埋める=「経験の差」を埋めるために「複数のレイヤーのツールに馴染んでおく」というのは効果的なのではないか?というのが個人的な意見です。

総括: ツールたくさんあるけど頑張ろうね!

f:id:o0h:20190701220125p:plain

システムの「複雑」さに合わせて監視も「複雑」になっていくのは、ある程度は已むを得ない・・といった話もしました。
しかしながら、パラドックスのような言い方ですが、個々のツールの組み合わせが「複雑である」システムに対して「単純に・明瞭に」現状を分析することを後押しするのです。
必ずしも「全部のツールを抑える」といった必要は全く無いので、もし「監視ってちょっとわからないな〜」という人がいたら、まずは「1つ目のツール」と仲良くなってみてください。
すると、「何がわかって・何がわからないか」という事がわかってくるはずです。
そうやって一歩一歩踏み出していくことで、いつの間にか「いろんなツールを自然に使える」ようになっているのではないかな〜!と思います。 チーム内の熟練者が、メンバーの一歩目二歩目を後押ししてあげられると良いですよね!

幸せカナコの殺し屋生活 1 (星海社COMICS)

幸せカナコの殺し屋生活 1 (星海社COMICS)

*1:それでも一部ですが・・

*2:スライド中はCloudWatchを1次情報として思考を深めていますが、実際には、より「エンド」からのアラートが出来るのが理想だと思います

Viewing all 376 articles
Browse latest View live