nariのエンジニアリング備忘録

SRE/Devops/AWS/自動化/IaC/Terraform/Go/DDD など

2021の振り返り/2022の抱負

はじめに

こんにちは。もうこの季節ですね。今年に関しては暦さんサイドのバグな気がしています、 nari/wapper です。

去年は準備の年と評したようですが、今年も特に大きな変化もなく同じく仕込みの年って感じでしたが、その中でも様々なカテゴリにて色々とイベントはあったので振り返って行こうかなと思います。

↓2021年のやつ

fukubaka0825.hatenablog.com

時系列で振り返る

1~3月

  • 業務では、プライバシープロジェクトで、データライフサイクルとひたすら格闘
  • プライベートでは、最近日本語版がでたスタンフォード大学のコンピューターサイエンス入門講義であるCS50を教材に、友達と一緒に勉強会したりしてました
    • かなり基礎的な内容が中心でしたが、技術英語の勉強にもなったし完結にまとまっていて良い復習にもなったしでかなりよかったです

cs50.harvard.edu

4~6月

  • 業務ではPairsのバッチ基盤をAWS EC2からFargateへの移行と格闘
  • プライベートでは、ひたすら英語に熱中

(なんかブログにするとか言ってるけど結局してません。すみません。)

7~9月

  • 障害対応に関する各社の悩みをぶつけ合うグッドなクローズドの勉強会に参加したり

  • 自分のしがないラジオでのエピソードをきっかけにWeb企業でSREをやっているという方のいい話を聞いて、アウトプットしてきてよかったなぁとしみじみしたりしてました

  • プライベートでは麻雀🀄️しかうってませんでした

10~12月

  • 一年半ぶりにSRE Lounge #13をオンライン開催して、登壇したり

  • AWS ML Specialtyをとったり

  • ポストモーテム読書会を開催したり

fukubaka0825.hatenablog.com

  • 来年から頑張っていきたいと思っているPolicy as Code/OPA/Rego/Conftest周りを勢いでアウトプットしたりしていました

fukubaka0825.hatenablog.com

カテゴリー別に振り返る

業務

業務的には、SRE業務とともにデータ基盤/ML基盤/プライバシープロジェクトでのお仕事が多かったし、それによってかなり視野もスキルも広げられた一年でした。目の前の仕事と向き合うことで成長できる - そーだいなるらくがき帳にも書かれていることですが、会社のMUSTに対して能動的に適切な課題発見/解決をして120点の働きをしていれば成長していけんだよなみたいなのを実感した年でした(まぁ私はまだ独身で可処分時間が無限にあるので、今のうちに技術なりナレッジの知見をプライベートでも貯めとく必要はもちろんあるしもうちょい頑張りたいけどね。)。

また、人間のWillってMustをがむしゃらにやることで容易に変化するよねみたいなのも感じました。まぁこれって弊社がMustに対しての詳細なHowは個人に裁量がかなりあるしチームのサポートも手厚いので、Willとの共通部分を能動的にでかくしていける環境ってのもうまくワークしてる要因だったりするのでそんな汎用的な話でもないかもしれません。

また、社内でプライバシープロジェクトについて発表したり、AWS(主にネットワーク)+Terraformワークショップを開いたり、ポストモーテム読書会+警察したり、その他にもチーム内外の信頼性に関するナレッジのベースラインを上げるような動きが結構できてたんじゃないかなと思います。これは私の強みでもあり弱みでもありますが、様々な領域のプロジェクトに広く関わりながらキャッチアップし必要ならメンバーへのナレッジシェア/オンボーディングをしつつ結果を出し、そこで得た知識を組織の共有知にしていくみたいなアプローチが得意でそれを評価してもらっている感じがします。

ただ一方でこれといった自信のある専門性のある一領域があるかと言われるとないしCSの知識も貧弱で、日本語という母国語によるコミュニケーションに依存した立ち回り/仕事の仕方によって評価されているのは課題です。そこにテコ入れすべく来年からは業務でもプライベートでも特定領域にディープダイブして、技術者として自信をつけていきたいです。

来年からは、eurekaで2年やってきたSRE的な業務(来年はEKSへのプラットフォーム移行/Policy as Code中心)も引き続き行いながら、MLOpsの方に集中していきながら、兼ねてから必要だと思っていたdata engineering/探索的データ分析/feature engineering/modelingも並行してキャッチアップして将来的にMLコンポーネントの開発から運用まで一気通貫でできる人間になりたいと思っています。(あと統計と数学も復習しないと。)ずっとPure SREから離れる気はないですが、一旦Data/ML側の人間として3、4年はやって視野・やれることを広げていきたいと思っています。

また、去年弊社SRE Teamの状態がとにかく人を取らないといけない状態、、、と前の振り返りでいってたようですが、今年は大学時代からのマブダチの二人をリファラルすることに成功して、さっそく戦力としてどんどん活躍して行ってくれてます。ありがとうogadyMoneyForest。これからも頑張っていきましょう。

今度はリファラルだけでなく、弊社メンバーのアウトプットに共鳴して外部から応募してきてくれる人をとれるように頑張っていきたいです。

弊社に興味ある方は、Meetyもやってるんでこちらも是非

meety.net

自己学習/対外アウトプット

ブログ/登壇/競プロ/OSS活動

ブログはdev.to/はてブ/mediumに3本(2本は英語にも翻訳してpublish)。去年より少ないし、相変わらず年末にしかやってない。さすがにもう少し本数あげたいし、来年は久々に技術書書きたいですね。

登壇もSRE Loungeで一回だけ、、

競プロは、けんちょんさんのアルゴリズム・データ構造本を一通り読んだだけで結局AtCoderデビューできず、、OSS活動も全然できませんでした。たるんでるので来年は頑張りたい。

www.amazon.co.jp

インプット/資格

  • 本は技術書を中心に5、6冊くらいしか読んでいないような気がします(MLOps系1冊/データエンジニアリング系2冊/Kubernetes・EKS1冊/ML1冊/アルゴリズムとデータ構造1冊/SREの探求)。その他勉強会/カンファレンス資料なんかは、週一のチーム勉強会でチェックしたいものはどんどんチェックしていけているので助かっています。それにしても、もうちょっと来年はインプットしたい。後は技術分野以外の本に関してもインプットしていきたいところ。
  • あとは、CS50の受講したり、AWS ML Specialty取得したりができたのはなかなか視野が広がるいい機会でした。

英語

4月〜6月の3ヶ月くらい(麻雀に吸い込まれてしまう前)はひたすら一日2~3時間くらい勉強してました。(弊社は福利厚生でBizamatesを規定回数こなしている限りは無料なので、毎日受けてました) そこから麻雀以外に手につかない時期をへて、11月からまた復帰して一日30~60分くらいゆるゆると発音/瞬間英作文を中心にやって行っています。後述するHololive/Nijisanjiの海外勢VTuberの配信を垂れ流しながら作業するといいリスニングの勉強にもなっておすすめです。その他にも弊社グループで実施されていたメンター制度みたいなやつに応募して、隔週くらいで英語でメンタリングしてもらったりしてました。おかげさまで英語のカジュアル面談とか急に振られてもなんとかこなせるようになったり、英語話者の同僚と英語でquick callでやりとりしながら不自由なく業務進行できたりしました。

来年も一旦これくらいの勉強を継続して、来年は定量的なスコアで結果を出していきたいと思います。(TOEIC/IELTS) そして、ゴテゴテになってる英語学習のTips周りのブログを出したいとも思っています。

その他にも英語でアウトプットしていく機会もどんどん増やしていきたい。(最近は技術ブログはなるべく英語でも出すようにできているので、こちらも継続したいです)

  • 最近の英語関連のツイートだとこれが印象的でしたね。これから、トップレベルの人材に囲まれて働くには英語は必要条件にますますなりそうだし、弊社でもMatch Group各社との連携は日に日に多くなって(外資ではあるので...)重要性がましていく予感がするのでやっていきたい。

コミュニティ運営

  • SRE Loungeが去年の5月から約1年半ぶりに開催。おかげさまで結構好評でしたが、結果一回だけの開催になってしまったのでもう少し頻度上げたい...

sre-lounge.connpass.com

  • 来年は、けっこう大きなことを秘密裏に動いているのでお楽しみに。

プライベート

健康面

  • 去年から引き続き5kgくらい太りました。
  • ここ3年くらいで40kgくらい太ったし、ちょっと運動しても痩せる気配がないので、来年はパーソナルジムに通ってなんとかする予定です。なんとかしないとやばい。

ワーケーション

  • 今年は京都、新宿、北海道、千葉、岐阜のホテルを転々としてました。引き続きhotelpassを使用。
  • コロナ真っ只中だったので、なかなか満喫できず歯痒かったりしましたが、拠点を定期的に変えるのはかなりリフレッシュできましたし、これを許してくれている会社に感謝
  • 最近はサウナ目当てで岐阜までこしてきて、大垣サウナを毎週堪能しています。さすが水の都とよばれているだけあって水風呂のクオリティがピカイチ。しかも接客のホスピタリティが群を抜いていい!是非皆さんにも来ていただきたい。

sauna-ikitai.com

麻雀

  • 6/21から10/19までほぼほぼ麻雀しかしてなかったんじゃないかくらいひたすら雀魂で段位戦やってました。4ヶ月で500東風+500半荘打って、結果雀豪3までいって2に落ちました。

  • 本当はこのまま麻雀勉強して鬼打ちして魂天いくまでやりたかったですが、仕事以外何も手につかなくなったので泣く泣く封印し、Mリーグ観戦にとどめることとしました。人生あがったら再開したいです。

saki.sapk.ch

f:id:st5818129:20211228230323p:plain

  • また、麻雀関連で一番記憶に残ってるイベントとしては、日本プロ麻雀協会の渋川難波さんのYoutubeチャンネル上での本出版イベントに参加し、無事東風にて渋川さんより順位上をとって本をプレゼントいただき、その際に「未来の雀王より」と表紙裏にサインとともにコメントいただいたら、本当に翌々月に雀王におなられになるという、、最速の未来予知が炸裂したのがハイライトでした。

VR/VTuber

  • 去年から引き続き、隔週くらいでVR活動をHEAD of VRboxpや私が今年リファラルしたogadyやHEAD of AIのyu81などとVRChatとかでわちゃわちゃ遊んでます
  • 登壇もほぼほぼこれからもwapperという私のアバターの姿でおこなっていくことでしょう
    • haritora/haritoraXでフルトラになったりもしてました
    • Twitter wapperアカウントも作って、そちらは英語で発信して行っています
  • あとはHololive enからはじまり、ひたすらNijisanjiからいろんなVTuberまでひたすらみまくってました。私の押しはHololive enならNinomae Ina'nis、Nijisanji enならMillie Parfait、Nijisanji jpなら舞元力一、箱外ならピーナッツくんです。というかもうNijisanjiに関しては箱推しになってしまって、大体のイベントを追うようになってしまいました。Nijisanjiはいいぞ、みんな沼に落としたい。
  • 私もwapperとして英語で麻雀配信できるように、あわよくばそのまま大人気VTuberになりnijisanji enに入れるように英語も動画配信も頑張りたいです(???)

hub.vroid.com

まとめ/2021の抱負

今年もテクノロジー/麻雀/VR/英語/ワーケーション/サウナ/リファラルとトピックがとっ散らかってますね。ただ、去年と比較するとちょっとはウィズコロナ/アフターコロナな生活にも慣れてアクティブに色々楽しめたし成長できたんじゃないでしょうか。

来年は

  • さすがに、パーソナルジムに通って痩せる(とりあえず70kgまで戻す)
  • 英語学習は継続して、来年はとりあえずToeic900over、IELTS7.0取得する。(いつか英語オンリーでお仕事する準備)
  • CKA/CKADを取得する
  • AtCoder始める始める詐欺をしているので、来年こそはじめて緑までいく
  • OS/システムコールなど低レイヤーに強くなる
  • 週一くらい出社したくなってきた+オフラインで飲みたい人間が無限にキューイングされてるので、関東に一旦拠点を戻そうかな
  • 業務はSREとしてPlatform EKS移行+Policy as Codeの導入/普及に邁進し、ひと段落したらMLOpsに集中していく
  • 楽天証券講座開いて投資をはじめる(n回目)
  • 麻雀とポーカーにはのめり込みすぎない
  • カンファレンス関連では、秘密裏に色々仕込んでいっているのでお楽しみに

という感じですかね。特にダイエットはほんまにやらんともう直ぐ死んじゃうかもしれない。

てな感じ来年も頑張るぞ!みなさん良いお年を!

Terraformのレビューを自動化するために、Conftestを導入してGithub ActionsでCIまで設定してみる

f:id:st5818129:20211225154739p:plain

English Version:

dev.to

はじめに

メリークリスマス。eureka, inc. でSREをやっているnari/wapperです。

こちらは Calendar for terraform | Advent Calendar 2021 - Qiita として書きたかったものを成仏させるために書いています。(登録するのを忘れていました....)

弊社SRE Teamでは、自分たち自身がボトルネックにならないための活動方針推して、来年の大きなキーワードの一つにマイクロサービスレディを掲げる予定です。(マイクロサービス化していくわけではない)

詳しくは以下のSRE Team責任者の marnie0301 (@marnie0301) | Twitterの発表をご覧ください

speakerdeck.com

それに伴い、Production Readiness checkとともに、移譲容易性/Self Serviceを促進するのに重要なピースとなるPolicy as Codeの運用をConftestで試し始めてみたので、そのお話を備忘録的に書いていこうかなと思います。

今回はTerraformのresource tagのルール(AWS reousrce)をRegoでポリシーを書きつつそのポリシー自体のテストまで書いて、その自動実行CIをGithub Actionsで整備する流れで紹介していきます。 (Conftest(Rego)の記述の話は多いけど、CI周りの設定まわりがあまり落ちていなく、何点かハマりポイントがあったので、これから試す方がはまらないように備忘録を残しておきたいと言うのがこの記事を書いている一番大きなモチベーションです)

対象読者

  • Policy as Code気になってはいたけど始めるきっかけが欲しかった人
  • ConftestをGithub ActionsのCIに落とし込む具体例が知りたい人

OPA/Rego/Conftestとは

また今年は、25日間ひたすらOPA/Regoについて書く 狂気的な 素敵なアドベントカレンダーがあったりしてとても参考になるので是非そちらを一通り読むことをお勧めします。

adventar.org

Regoでポリシールールを記述して、ルール自体のテストも記述しながらCIへ組み込んでいくまで

ここからのサンプルコードはこちらにすべて置いております:

github.com

今回はterraformで作成するリソースが最低限のtag(name/owner/description)を持っていて、かつdata store resourceだった場合にdataという名前のtagにdataの重要性(high/middle/low)が設定されていることを確認するポリシールールを書いてみたいと思います。terraform planの結果をjsonに変換したものを入力値として、それを今から書くRegoのポリシールールでテストできるように、かつそのポリシールール自体もテストできるようにしていきます。(説明していくサンプルはAWSの使用を想定しています)

Conftest(OPA/Rego)のセットアップ

  • Mac OS ユーザーであればbrewで簡単にいれることができます。その他のOSのユーザーもそれぞれのREADMEを参考に導入をすることができます。
brew install conftest

# opaもいれておく
brew install opa
  • EditorのPluginに関しては、IntelliJならopa pluginVSCodeなら opa plugin が使えます
    • 他のEditorでもあると思うので探して入れてみてください

前提知識: Terraform plan 結果の構造

f:id:st5818129:20211228204336p:plain

(https://speakerdeck.com/ryokbt/terraformfalserebiyuwoconftestdezi-dong-hua-suru?slide=20 参考)

このような構造をしており、このデータをinputとしてその内容をチェックするようなロジックをRegoで書いていきます。

ConftestでTerrafom resource tag ルールを書いてみる

  • まず、main.regoでエントリーポイントを記述していきます。
# policy/main.rego


package main //❶

import data.tags_validation //❷

#####################################
# Policy as Code Rules
#####################################
deny_tags_contain_minimum_set[msg] {
   # Only target resources that have been changed/added.
    changeset := resources_not_no_op_action[_] //❸

    not tags_validation.contain_proper_keys(changeset.change.after.tags)

    msg := sprintf("Invalid tags (missing minimum required tags: name,owner,description) for the following resource: %v", [changeset.address]) //❹
}

deny_data_store_data_tag_is_proper[msg] {
   # Only target resources that have been changed/added.
    changeset := resources_not_no_op_action[_]

   # Only when resource_type is a data source/store type that can contain sensitive information
    tags_validation.is_data_tag_required_target_resource(changeset.type)

    tags_validation.not_has_proper_data_tag(changeset.change.after.tags.data)

    msg = sprintf("data tag needs to be set to one of [low,high,middle] resource: %v", [changeset.address])
}

#####################################
# Utils
#####################################

resources_not_no_op_action= {resource | resource := input.resource_changes[_]; resource.change.actions[_] != "no-op"} //❺

resources_with_type(resources, type) = all {
    all := [item | item := resources[_]; item.type == type]
}

❶ ポリシーには必ず package 句が必要です。名前空間を分割するために任意のパッケージ名をつけることができます。

❷ import句で別の名前空間をimportしてきてそちらのリソースを使うことができます。tags_validationという名前空間の方でリソース独自のロジックを書いてそれをmain側で使用していきます

❸ ここで、actionが"no-op"でないリソースにリソースを絞り、それらのリソースをイテレーション([_]で記述する)で回してポリシー違反のリソースがないチェックします。これで新しく変更/追加があったリソースのみを対象とすることができます。また、この操作は基本どのポリシールールでも使用するので、共通の関数にして切り出しています。

❹ 同一ルール内では複数の評価式を記述でき、それらはANDで評価されるので、全てがtrueとなった場合のみdeny/violationと判定されてこのそれぞれのポリシールール用のエラーメッセージ配列にエラーメッセージが登録されテスト実行時に出力されます。

❺ RegoではPythonでおなじみの内包表記が使えるようになっています。文法としては [<結果として返す値> | <ルール>] となっていて、ルールに当てはまるリソースだけを返します。

  • 次にmainで使っていた、tags_validationロジックを記述していきます
# policy/tags.rego

package tags_validation

minimum_tags = {"name", "owner", "description"}

contain_proper_keys(tags) {
   # Subtract the key list of the given tags from the minimum tag list, and if there is no more left, you have the minimum tag.
    keys := {key | tags[key]}
    leftover := minimum_tags - keys
    leftover == set()
}

not_has_proper_data_tag(value) { // ❶
    value != "low"  
    value != "middle"
    value != "high"
}

is_data_tag_required_target_resource(type) { // ❷
    type == "aws_dynamodb_table"
}

is_data_tag_required_target_resource(type) {
    type == "aws_s3_bucket"
}

❶ 同一ルール内での評価式はANDになるので"low"でも"middle"でも"high"でもない場合にtrueが返ります

❷ 同一ルール内での評価式はANDで評価されるので、ORの論理を記述したい場合はis_data_tag_required_target_resourceのように同名の複数の処理を書くことで実現が可能です。

ConftestでRegoで書いたルール自体のテストを書いて、実行してみる

  • まずmain.regoのテストを書いていきます。こちらはGoなどと同様に${test_target_file_name}_test.regoという風な命名をします。
# policy/main_test.rego

package main

#####################################
# Tests of Policy as Code Rules
#####################################

...

test_tags_contain_minimum_set {
    plan := `                    // ❶
      resource_changes:
        - name: case normal
          address: module.one
          type: aws_security_group_rule
          change:
            actions:
              - create
            after:
              tags:
                name: hoge
                owner: piyo
                description: for test
    `

    input := yaml.unmarshal(plan)
    deny_tags_contain_minimum_set == set() with input as input // ❷
}

...

❶ test用のinputは、公式などではjsonで記述されていますが、jsonのメンテナンスはつらいので、yamlで記述管理してjsonに変換して使うと良さそうです。

❷ ルールのテストはこのように記述することができます。配列のメッセージ内容までチェックしなくていい場合は、そのエラーメッセージ配列が空なのか、そうじゃないのかをチェックするだけでも良さそうです。

# tag_rest.rego

package tags_validation

test_contain_proper_keys {
    tags := {"name": "test", "owner": "hoge", "description": "normal test"}
    contain_proper_keys(tags) // ❶
}

...

❶ mainのルール側で使っている関数のユニットテストはこのようにおこない、trueがかえればpassと判断されます

  • ここで書いたテストは、以下のコマンドで簡単に実行が可能です
# カレントディレクトリ配下のConftestのルールに対するテストを実行します
conftest verify ./

Conftestを実行するCIをGithub Actionで整備する

Conftest/Regoで書いたポリシールール自体のfmt/verifyのCIの設定

  • Regoで記述してConftestのコード自体のfmt/verifyのCIをまず設定します
name: conftest-fmt-and-verify-all

on:
  pull_request:
    branches: [ main ]
    paths:
      - 'policy/**'
env:
  CONFTEST_VERSION: 0.28.3
jobs:
  terraform:
    name: fmt-all
    runs-on: ubuntu-latest
    defaults:
      run:
        shell: bash
    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Install conftest
        run: |
          wget -O - 'https://github.com/open-policy-agent/conftest/releases/download/v${{ env.CONFTEST_VERSION }}/conftest_${{ env.CONFTEST_VERSION }}_Linux_x86_64.tar.gz' | tar zxvf -
          ./conftest --version

      - name: conftest fmt
        run: |
          git add . && ./conftest fmt ./ && git diff --exit-code ./.    // ❶

      - name: conftest verify
        run: |
          ./conftest verify ./   // ❷

❶ terraformのvalidationのようなフラグがまだないので、conftest fmtの結果で差分が出たらテストが落ちるようにしています

❷ ここで先ほど書いたRegoで記述したポリシールールのテストを実行しています

Conftest testでTerraform plan結果をテストするCIの設定

  • 最後に、GIthub Action CIで記述したConftestのポリシールールで、Terraformコードを自動でチェックするようにしてみます
name: tf-plan-apply

on:
  pull_request: 
    branches: [ main ]

env:
  TF_VERSION: 1.0.0
  CONFTEST_VERSION: 0.28.3
  WORKING_DIR: ./
jobs:
  terraform:
    name: aws-eureka-pairs-etc-s3
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v2

      - name: Install conftest
        run: |
          wget -O - 'https://github.com/open-policy-agent/conftest/releases/download/v${{ env.CONFTEST_VERSION }}/conftest_${{ env.CONFTEST_VERSION }}_Linux_x86_64.tar.gz' | tar zxvf -
          ./conftest --version //❶

      - name: Setup Terraform
        uses: hashicorp/setup-terraform@v1
        with:
          terraform_wrapper: false //❷
          terraform_version: ${{ env.TF_VERSION }}
          cli_config_credentials_token: ${{ secrets.YOUR_CRED_NAME}}

      - name: Terraform Init ${{ env.WORKING_DIR }}
        working-directory: ${{ env.WORKING_DIR }}
        run: terraform init

      - name: Terraform Plan ${{ env.WORKING_DIR }}
        if: github.event_name == 'pull_request'
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        working-directory: ${{ env.WORKING_DIR }}
        id: plan
        run: terraform plan -out=tfplan -no-color -lock=false -parallelism=50

      - name: Convert terraform plan result to json formmat
        if: github.event_name == 'pull_request'
        id: convert
        working-directory: ${{ env.WORKING_DIR }}
        run: terraform show -json tfplan > tfplan.json

      - name: conftest test
        if: github.event_name == 'pull_request'
        id: conftest
        run: ./conftest test --no-color ${{ env.WORKING_DIR }}/tfplan.json //❸

❶ 個人の公開している、Actionsできちんとメンテナンスされているものがなかったのでwgetでconftestをインストールするようにしています。

❷ 公式のhashicorp/setup-terraform を使っていると、デフォルトだとこの値がtrueになっていてplan結果が適切なjsonでshowできないのでfalseにしなければいけないことには注意が必要です。

❸ ここで先ほど記述したポリシールールでterraform plan結果をtestしていきます。使用するポリシーの読み込みは、デフォルトではpolicy/をみにいきます。別のディレクトリを参照させたい場合は、-pで渡して設定することができます。

終わりに

Conftest/OPA/Rego周りをいじってみての率直な感想としては、型信者なのでデータ定義でスキーマが欲しいなぁとか思ったり、論理評価の癖がかなり強くかつ表現力もかなり豊かなので、裏を返せばわかりやすくシンプルに書こうとしないとすぐにチームでメンテできなくなりそう、、と言う感じなので適切な設計/コード規約とともにメンテナビリティを意識して運用していきたいですね。

あとはなんといっても自分のコーディングスタイル的にもPolicy as Code自体のテストが簡単に書けるのは大きい。自信を持って、Regoのコードをがしがし変更/追加/リファクタしていけます。

また、ディレクトリ構成の戦略もいまだに各社模索していそうな雰囲気を感じるのでここらへんも試行錯誤しながらいい感じのところに落とし込んでいきたいです。

今後はEKSへのPlatform移行とともにKubernetes Manifestにも適応していったり、GitHub - open-policy-agent/gatekeeper: Gatekeeper - Policy Controller for Kubernetes の導入を検討したり、かなりPolicy as Codeを推し進めていきたいと考えているので、ここら辺やっていきたい方は是非弊社で一緒にやっていきましょう〜

Meetyもやってるのでお気軽のどうぞ!: 

meety.net

参考文献

EKS/Kubernetesで画像カテゴリ分類のGPU推論環境をProduction Readyにするまで

f:id:st5818129:20211220020232p:plain

こちらは Eureka Advent Calendar 2021の12/20の記事となります.

English Version:

medium.com

はじめに

こんにちは、エウレカSREチームのnari/wapperと申します👋

最近は、データライフサイクル・プライバシープロジェクト/データプラットフォームの移行/審査サービスのMLシステムのインフラなどを担当したりしています(Site Reliability Engineerなのかわからなくなってきた)

その中で今回は、審査サービスにおける画像カテゴリ分類モデルを、EKSで本番環境にリリースした話を紹介したいと思います。 EKS Clusterの本番環境設定のポイントは、セキュリティ項目も含めてたくさんありますが、今回はGPU推論環境ならではのポイントにフォーカスしてみたいと思います。

対象読者

  • Kubernetesに関する基礎知識(Cluster/Pod/Deploymentなど)をお持ちの方
  • EKS/Kubernetesを使ったGPU推論の本番環境構築方法に興味がある人

どうGPU推論環境を本番リリースしていくか

1. EKS GPU環境のk8sノード/コンテナを設定する

この章の概要のアーキテクチャは以下の通りです。(⚠︎これはあくまで私の理解であり、正しいことを保証するものではありません)

f:id:st5818129:20211220020333p:plain

1.1 ノードの設定(Nvidia Driver/Nvidia container runtime/Amazon EKS optimized accelerated Amazon Linux AMIs and MNG)

今回は、一旦AWSが提供しているmanagedな機能をフルで使っていくことにしました。

  • Amazon EKSに最適化されたAmazon Linux AMIを使用する
  • GPUインスタンスと最適化AMIを指定してMNG(Managed Node Group)を作成する
    • Terraform example

        # FYI https://www.terraform.io/docs/providers/aws/r/eks_node_group.html
        resource "aws_eks_node_group" "node" {
          ...
          capacity_type        = "AL2_x86_64_GPU"  # Amazon EKS optimized accelerated Amazon Linux AMI
          instance_types       = ["g4dn.xlarge"]   # GPU instance
          ...
        } 
      

1.2 Nvidia device pluginをノードに導入する

Nvidia device pluginをDaemonSetとして、kubectlでインストールします。(適宜node collctorなどの設定は変更します)

# You can also copy https://github.com/NVIDIA/k8s-device-plugin/blob/master/nvidia-device-plugin.yml and manage it
# Modify node collector/tolerance/affinity if needed
kubectl apply -f https://raw.githubusercontent.com/NVIDIA/k8s-device-plugin/v0.9.0/nvidia-device-plugin.yml

1.3 CUDA/PytorchコンテナのDockerfileを作成し、それをDeploymentとして作成する

PytorchやCUDAなどの機械学習ライブラリ周りで最も難しいことの1つは、互換性考慮しながらどのバージョンのどのツールをインストールするかをコントロールすることです。

今回は、データサイエンティストが使っているPytorchのバージョンにCUDA環境を互換性がある形に合わせていく必要がありました。(詳しくは https://pytorch.org/get-started/previous-versions/ )

最終的に、そのバージョンのPytorchが動作する、PythonとCUDAの環境をまとめてベースイメージとして管理することにしたところ、かなり管理が簡単になりました。( 参考: https://github.com/qts8n/cuda-python/blob/master/runtime/Dockerfile および https://github.com/docker-library/python/blob/master/3.9/bullseye/Dockerfile)

2. CPU推論ワークロードとGPU推論ワークロードを分離する

既に審査サービスでは、テキスト分類のためのCPU推論モデルのワークロードが存在していました。(詳しくはこちら: https://medium.com/eureka-engineering/aws-solution-days-ai-machine-learning-day-tokyo-で登壇しました-45563b66d10 )

そして、この画像分類GPU推論モデルを、既存のテキスト分類のCPU推論ワークロードに影響を与えることなくリリースする必要がありました。

そこで、Node AffinityをつかってCPUモデルはCPU用のMNGに、nvidia.com/gpuのlimits・requestsの設定でGPUモデルはGPU用のMNGに配置することで、ワークロードを完全に分離することでこのリリースを実現することができました。

次の図は、その概要図になります。 f:id:st5818129:20211220020505p:plain

3. DatadogでGPUモニタリングの設定をする

f:id:st5818129:20211220020521j:plain

f:id:st5818129:20211220020627p:plain

4. ポッドとノードのスケール戦略を決定する(負荷テスト/キャパシティプランニング)

  • ポッドスケール戦略

    • HPA(horizontal pod scaler: Horizontal Pod Autoscaling | Kubernetes)を使用
    • GPUの使用率でスケーリングするか、CPUの使用率でスケーリングするか決定

      • ステージ環境での負荷テスト
      • 負荷テスト環境
      • GPUの使用率が飽和する前にCPUの使用率が飽和するという結果になったので、CPUの使用率を基準にHPAを設定することにしました。 f:id:st5818129:20211220020557p:plain
    • キャパシティプランニング

      • 最大リクエスト数での負荷テストを行い、最初に配置するサーバーのスペックを決定しました。

        • 以下は、vegetaでのコマンドと結果の例です。
          -> % nappa curl -v -XPOST https://example.com/ping -d '{
              "image_url": "hoge"
          }' | vegeta attack -format=json -duration=300s -rate=2/s | tee results.bin | vegeta report
          Requests      [total, rate, throughput]         30, 3.10, 3.07
          Duration      [total, attack, wait]             9.759s, 9.667s, 92.698ms
          Latencies     [min, mean, 50, 90, 95, 99, max]  86.44ms, 140.245ms, 105.532ms, 211.702ms, 260.299ms, 489.439ms, 489.439ms
          Bytes In      [total, mean]                     2460, 82.00
          Bytes Out     [total, mean]                     3870, 129.00
          Success       [ratio]                           100.00%
          Status Codes  [code:count]                      200:30
          Error Set:
        
      • また、以下のようにvegetaはHTMLで結果を可視化することもできます。

         -> % nappa curl -v -XPOST https://example.com -d '{
              "image_url": "hoge"
         }' | vegeta attack -format=json -duration=10s -rate=1/s | tee results.bin
         cat results.bin | vegeta report -type="hist[0,100ms,200ms,300ms]"
         cat results.bin | vegeta plot > plot.html
      

      f:id:st5818129:20211220124624p:plain

  • ノードスケール戦略

    • Cluster Autoscalerを使用しています(https://github.com/kubernetes/autoscaler/tree/master/cluster-autoscaler)
      • アクセラレータの設定をラベリングして、Cluster AutoscalerがGPU optimizeのプロセスを考慮して適切にスケールダウン/アップできるようにします

          label = {
              "k8s.amazonaws.com/accelerator" = "nvidia-tesla-t4" #g4dn gpu REF: https://github.com/kubernetes/autoscaler/blob/7e5f8f0045c195376d773fc64998e2f8b7566316/cluster-autoscaler/cloudprovider/aws/aws_cloud_provider.go#L41
            }
        
      • それ以外については、GPUノードのスケーリングのための特別な設定のために必要なし

        • Cluster Autoscalerはとても優れたツールで、Affinity/toleranceやGPU/CPU/メモリの要求/使用率などの設定に従って適切にノードをスケーリングしてくれます
  • これらすべての設定の結果は次のようになります

f:id:st5818129:20211220020809p:plain

今後の展望

1.審査サービスのMLパイプラインのモダナイゼーション

審査サービスでの機械学習ワークフローはかなり手作業ベースになっています。具体的に言うと、データサイエンティストがローカルのノートブックでデータ収集、データクリーニング、モデルトレーニング、評価を実行を通してモデルを作成し、データサイエンティストとSRE/MLOpsエンジニアがそれらを本番環境のAPIエンドポイントとしてリリースしていきます。

この再現性のかなり乏しいフローは、管理するモデル数の上昇に対してスケールするとはあまり言い難い作りになっています。そこで、kubeflowや他のMLパイプライン管理ツールなどを用いて自動化パイプラインを構築することで、信頼性とリリースサイクルどちらも向上させながらスケールする状態に持っていきたいです。

f:id:st5818129:20211220020840p:plain

2. feature storeの導入

また、ML学習時とオンライン提供時でデータソースが異なることによるデータの不整合によって起こる問題を減少させるため、オンライン・オフラインどちらでも複数の特徴セットに対して共通の処理を可能とするfeature storeを導入したりして行けたらなと思っています。 (feature storeは推薦ドメインですでに採用済みだったりします: https://medium.com/eureka-engineering/vertex-ai-mlops-b74cdff19681)

f:id:st5818129:20211220020851p:plain

(https://valohai.com/machine-learning-pipeline/ から引用)

We are hiring SRE/MLOps Engineers!!

絶賛SREもMLOps Engineerも募集中ですので、もし少しでもエウレカやMatch Groupに興味がありましたら是非Twitter DMまでお願いします!

twitter.com

Meetyも開いてますので、こちらでも是非気軽にお話ししましょう〜

meety.net

2020の振り返り/2021の抱負

はじめに

こんにちは。都内でエンジニアをしている nariです。

去年に引き続き、今年2020の振り返りをして行こうかなと思います。

一言で言って仕舞えば、withコロナでのリモート生活(3月から一度も出社していない)のリズムが掴めず、最後の最後に掴みはじめた順応/準備の一年だったという感じですね。

全然成果が当初の期待値には達してないですが、向き合い来年の糧にするためにつらつら書いて行こうと思います。

↓去年の記事

fukubaka0825.hatenablog.com

時系列で振り返る

1月

SRE NEXT開催したり、転職活動したり、業務ではUSプロジェクトの進行したりIaC推進したりしてました。

特にSRE NEXTでは様々な人から多くのものを学べたり転職の転機になったり、自分の人生全体でもとても大きな出来事となりました。

2月

私のweb系への転職のきっかけとなったしがないラジオに出演し、web転職から今楽しく働けているのはお二人のおかげですという話ができた。

話し足りなかったしSRE担ってからの話もしたいのでまた遊びに行きたい。

3,4月

Web developer -> SREへのロールチェンジ。

転職。Pairsが好きだったのでマジ嬉しかった。お金も結構上がった。そこらへんの生々しい話が聞きたい人は密をさけながら飲みに行きましょう。

www.wantedly.com

5月

SRE Lounge、初のオンライン開催をしました。

初のファシリと全体コーディネイターをやりました。結構念入りに計画して様々なメンバーにサポートしてもらい、及第点の出来にはできたと思います。

しかしもともとこの勉強会自体において懇親会でのコネクションが非常に重要な要素だったので、これはちょっとオンラインになってからはやり方をがらっとかえんと運営のモチベーションも保てないなと思いました。案の定これっきり2020の開催はなし。

6,7,8月

仕事以外生産的なことは何かした記憶がない。体がずっと重かった。

去年から引き続きニューヨークを筆頭にしぬほどお笑い芸人のYouTubeとアニメや漫画をみていました。後加藤純一の配信。生きる希望。

今年みて一番よかったアニメは映画だけどリズと青い鳥、漫画はぶっちぎりでチェンソーマン。

9,10,11月

1年半くらいすんでいたギークハウス新宿からgoodroomのホテルパスを使ってワーケーション勢になりました。

www.goodrooms.jp

温泉入り放題のホテルがあったり。しかもGOTOでほぼ半額で止まれたりしました。最高。これにかこつけて京都行ったり福岡いったりしました。

最近は新宿にべったり。由縁という宿が雰囲気含め最高です。

来年は北海道に長期滞在しようかなとぼんやり考えてます。

12月

Oculus Quest 2をなんとなく買って、Vの民になりました。これが大当たり。

Amazon.co.jp: Oculus Quest 2—完全ワイヤレスのオールインワンVRヘッドセット—64GB: ゲーム

fitxrというソフトで運動不足解消 and 自律神経も安定。VR Fitness最強。 VRChatの表現からクリエイティブの力の吸収。活力を取り戻しました。

カテゴリー別に振り返る

業務

基本Go/Terraformかいてプロセス全体の最適化(主にSelf-Service化だったり、Infra Develiry Process刷新だったり)をがんばった。

そのほかにもPairs Engage基盤fargate移行、AWS ECR vulnerability scan and workflow作成、BotOps徹底、ポストモーテムTemplate/PlayBook(RunBook)導入したり障害対応システム復旧したり結構色々やった。ほかにやりたいことも無限にあるので切実に仲間を求めている。。

求人の詳細は以下の記事の終わりを参照。

medium.com

去年までの自分なら全てのタスクにアウトプットした記事を引用しているはずだが、そこまでの活力が今年はでなかった。。。

Security/Privacyの案件に後半半年くらいはだいぶ張り付いていたので、この観点でのデータへのアプローチはだいぶ勘所を掴んだ感じがある。ここら辺もっと深掘りしていきたい思いがある。 あと検証用のめちゃくちゃSQL書いた。今までで一番SQLを書いたとしかもしれない。

自己学習/対外アウトプット

ブログ/登壇/OSS活動/英語

ブログは5本...(去年は60本)お世辞にも多いとは言えない。

その他も全くと言っていいほど頑張れていないですね。

現在の弊社SRE Teamの状態がとにかく人を取らないといけない状態なので、自分が頑張って人を連れてくることも来年の大きな主眼の一つとなりそうです。

コミュニティ運営

SRE NEXTは大成功でしたが、SRE Loungeに関してはたったの一回の開催という結果になってしまいました。

chaspyさんとも飲みながら話したりしましたが、新たなスタイルを確立して行こうと運営メンバーと話をしています。

定期的な小規模イベント(SRE Loungeなど)、OBSの勉強をしはじめていて、配信を楽しむことで自分のインセンティブにしようと思っています。運営、登壇者のインセンティブ設計は開催しながら練っていく予定。

大規模イベント(SRE NEXTなど)についてはまだ全然自分の中で考えがまとまっていないです。

cloudnative daysさんが面白い試みをしていましたが、そういう試行錯誤の結果を参考にし、小規模イベントを継続開催しながら色々試行して行こうと思っています。

プライベート

健康面

とにかくフルリモートになってから家から出ないし動かない。体はどんどん重くなっていってました。

先述のようにここはVR Fitnessにすくわれた。12月から1日1時間を目安にやるようにしているが、整い方が半端ない。

ホテルパスでいつでも温泉に入れるのもでかい。全人類ホテルパスとOculus Quest買って使ってくれ。

仮想空間での表現との出会い

楽器をやめて、前職のクリエイター支援の会社をやめ、クリエイティブに触れる時間が大幅に減少したので、いつのまにか無意識に活力がゼロになっていた。

フジロックは中止だし、こんなに音楽ライブに行かない年も久々なくらいいけず、かなり乾いていた。

そんなときに、みんなVRChat上でギターリストMiyaviさんのLiveを筆頭にVRChat上でのカオスともとれる各々の斬新な表現に魅了された。音楽liveに関してはビジュアルは現実を超えれるので、課題は音。クラブにいった時の低温に殺される感覚とか、そこらへんの表現をどう組み込むかだと思います。どんどんアーティストがVR空間上でliveしたり表現していく世の中になってほしい。

自分自身のライフスタイルや職業選択の志向性である、時間と空間の制約を受けないという点がクリエイティブに結びついたこの感覚がすごく気持ちがよくてしっくりきたので、来年はもっと追い求めてみたいです。

リアル/仮想空間問わずいろんなものに触発されながら、VRChat上でアバターなりワールドなりちまちま作っていくことで表現欲的に精神安定につながりそうです。

まとめ and 2021の抱負

こう振り返ってみると今年は順応/準備の年でした。お笑い芸人とアニメと漫画に生かされ、ホテルパス(温泉)とVRに救われた一年だった。

あと転職は成功だった、成長産業でデータとトラフィックに溺れられてやりがいもあるし、なにより従業員のスループット最大化を目指してサポートをたくさんしてくれるとてもいい会社です。

12月くらいからようやくアフターコロナのリモート生活のリズムを掴みはじめた(遅い...)のと、忘れかけていたプライベートの充実の重要性を再認識できたので、来年は今年とは違い飛躍の年にできそうです。というかします!

業務、対外活動(登壇、コミュニティ運営、採用etc)、健康管理(ダイエット)、仮想空間での表現をそれぞれ頑張りたいです。後あわよくばお金周りのお勉強と英語も。 業務では特に、意思決定の質と量をもとめられているので、そこを意識しつつアプリ/データレイヤー改善をメインにふかぼっていく年へ。

それぞれ定量的な目標値を宣言したいところですが、無理はせずマイペースにギアを上げていきたいので今年は宣言しないこととします。(自分の中の目安となる目標値はざっくりあるが)

ここまで駄文読んでいただきありがとうございました。それではみなさま良いお年を!

AWS DynamoDB exportとAthena CreateTable/ExecuteQueryを定期的に実行するLambdaでお手軽データ解析基盤を手に入れる

はじめに

お久しぶりです。都内でエンジニアをしている nariです。 年末年始なので今年やったことをつらつら備忘録としてためておきたいと思います。 (これ一個で終わっちゃうかも。ご容赦)

作った動機

ある案件でDynamoDBに対してある程度複雑なクエリで抽出したい要件がでてきました。 しかし

  • そもそも本番Data Storeに解析クエリを投げるのはよくない
  • DQL(DynamoDB Query Language)の表現(unix timeの扱いetc)が貧弱/毎回解析用にIndexをはるのがつらい

ので、お手軽解析環境をStream/Batchの同期タスクをお守りすることなく手に入れたい思いから作成しました。 今回は、ちょうど今年リリースされたしたDynamo export to s3のという神機能を使って作成していきます。

全体像

f:id:st5818129:20201231152615p:plain

サンプルコードは以下

github.com

サンプルコード解説

Terraform側

DynamoDB table/export先のS3 bucket/Athena database/Athena execute result store用のS3 bucketを作成する

# ./terraform/dynamodb.tf

resource "aws_dynamodb_table" "sample" {
  name         = "sample_dynamodb_table"
  billing_mode = "PAY_PER_REQUEST"
  hash_key     = "id"

  attribute {
    name = "id"
    type = "S"
  }

  attribute {
    name = "name"
    type = "S"
  }

  point_in_time_recovery {
    enabled = true //①
  }
}
  • ① export to s3の機能を使うのにPITRが必須なのでtrueにしておきます
#./terraform/export_s3.tf

resource "aws_s3_bucket" "sample_export" {
  bucket        = "sample-export"
  acl           = "private"
  force_destroy = "false"

  versioning {
    enabled = true
  }

  lifecycle_rule {
    enabled = true
    expiration {
      days = 90 //②
    }
    noncurrent_version_expiration {
      days = 1
    }
  }


  server_side_encryption_configuration {
    rule {
      apply_server_side_encryption_by_default {
        kms_master_key_id = "arn:aws:kms:ap-northeast-1:99999999999999:key/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" //③
        sse_algorithm     = "aws:kms"
      }
    }
  }
}


# enforce public access block on bucket
# reapply on next tf apply if disabled
resource "aws_s3_bucket_public_access_block" "sample_export" {
  bucket = aws_s3_bucket.sample_export.bucket

  block_public_acls       = true
  block_public_policy     = true
  ignore_public_acls      = true
  restrict_public_buckets = true
}
  • ② 個人情報を含む場合、こういったDataLake移行のレイヤーでも、Dataのライフサイクルを最初から意識して解析側やステークホルダーと握って設定するのが吉です。また、Query Resultを保存する S3 bucketにも同様のサイクルや後述する暗号化を適応する必要があることにも注意してください。
  • ③ 暗号化も各会社の基準によるところですが、重要度が高いものに関してはmanaged kms keyで暗号化するのが賢明だと思います。(内部からの漏洩も対策しておく)

Serverless Framework側

DynamoDB exportとAthena CreateTable/ExecuteQueryを実行するLambdaとCloudWatch Eventを作成する

#./conf/sample.yml

sample_dynamodb_table:
  cron:
    rate: rate(30 days)  //④
    enabled: true
  dynamo:
    arn: "arn:aws:dynamodb:ap-northeast-1:99999999999:table/xxxxxxxxxxxxxxxxxxxxxxxx"
  s3:
    name: "sample-bucket"
  kms:
    arn: "arn:aws:kms:ap-northeast-1:99999999999999:key/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
  athena:
    enabled: true
    database_name: "sample-db"
    query_result_output_bucket_name: "sample-result-bucket"
    table_name: "sample-table"
    table_schema: "struct<id:struct<s:string>,name:struct<s:string>>" //⑤
  • ④ ap-northeast-1で1GBあたり$0.114 per GB (20201231時点)なので、頻度はお財布と相談してください
  • Dynamo table export データがこのようにネストされた構造をもっているので、Athena(Glue)で表現しようとするとこれだけ複雑になってします。こちらはid,nameをattributeにもつ場合の例。どのtableもこの形式なので参考にしてみてください
# ./src/module/export_handler.go

func (s *exportHandler) Run() error {
    sess := session.Must(session.NewSession())
    dynamoCli, err := NewDynamoCli(sess)
    if err != nil {
        log.Error(err)
        return err
    }
    exportID, err := dynamoCli.ExportToS3(s.Event.DynamoTableArn, s.Event.S3BucketName, s.Event.KmsArn)
    if err != nil {
        log.Error(err)
        return err
    }
    if s.Event.AthenaEnabled {
        athenaCli, err := NewAthenaCli(sess)
        if err != nil {
            log.Error(err)
            return err
        }
        newLocation := fmt.Sprintf("s3://%s/AWSDynamoDB/%s/data/", s.Event.S3BucketName, exportID)
        outputLocation := fmt.Sprintf("s3://%s/output/", s.Event.AthenaQueryResultOutputBucketName)
        //⑥ 
        if err := athenaCli.CreateTableIfNotExists(s.Event.AthenaDatabaseName, s.Event.AthenaTableName, s.Event.AthenaTableSchema, newLocation, outputLocation); err != nil {
            log.Error(err)
            return err
        }
        if err := athenaCli.ChangeLocation(s.Event.AthenaDatabaseName, s.Event.AthenaTableName, newLocation, outputLocation); err != nil {
            log.Error(err)
            return err
        }
    }
    return nil
}
  • ⑥ 初回はCreateTableをして、初回移行は新しくexportしたobject pathでtable locationを変更しにいきます。これによって、同じtable名で、ある程度の鮮度のデータを解析できるようになります。

Athenaでの引き方

  • 以下のようなsqlでコンソールから引けるようになりました。redashとつなげていつでも解析できるようにすることもできます。
SELECT 
    item.id.s as id,
    item.name.s as name
FROM 
    "sample_db"."sample_table" 

終わりに

これで、実行間隔分の反映ラグ(1日おきなら、最大1日分の反映ラグが発生してします)が発生するものの、それくらいのデータ鮮度を許容できる場合簡単にDynamoDBをSQLで解析できるようになりました。 皆さんもDynamoDBに検証/解析用のちょっと複雑なクエリを投げたくなったらこういう感じでさくっとAthenaで解析する方向にシフトしてみてください。

参考文献

SRE NEXT 2020を一運営スタッフとして振り返ってみる

f:id:st5818129:20200127002406p:plain

はじめに

こんにちは。都内でWeb Developerをやってる@nariです。

先日2020/01/25に、日本初のSREカンファレンス「SRE NEXT」が開催されました。

sre-next.dev

以下のツイートで、参加者にブログを書くまでがSRE NEXT!!とか自分で煽っておきながらお前(運営スタッフ)が書かないでどうするんだと言う感じなので、やむなしで書いている振り返り記事がこちらになります。 (参加者やスピーカーの皆さん本当に多くの参加レポありがとうございます。コミュニティカンファレンスらしい盛り上がりで最高)

今回は僕が手伝い始めてからカンファレンス当日までを、一運営メンバーとして振り返っていこうと思います。

手伝い始めるきっかけ

【増枠】SRE Lounge #10 - connpass に参加した時に、丁度SRE Lounge運営スタッフ主体でSRE NEXTというカンファレンスの開催決定が宣言されました。 運用改善や基盤への思いがずっと強かったのもあって、これは絶対に手伝いたいという思いが強すぎて気がつくとtwitterで主催者のかつひささん (@katsuhisa__) | Twitterさんに運営やらせてくださいとリプライを送っていました。

そんなこんなで8月くらいからメンバーとしてjoinさせてもらったのですが、振り返ってみると、SREでもない、しかもメンバーに知り合いもいない何処の馬の骨ともわからんやつをよくホイホイと入れたなという感じが凄いですね。katsuhisa氏の肝っ玉よ。。

で、お前は何をやれたの

途中参加の人間、しかも中には誰も知っている人がいない状態の自分がまずやるべきことは、浮いているタスクを自分で見つけてこなしていくことで信頼関係を構築することだと考えました。

手が回っていなかったTwitterなどの広報、チケットサイト、動画コンテンツ準備のタスクをひたすらこなして言ったり、必要な要件や情報を得るためにコアスタッフを捕まえてどんどんコミュニケーションを取っていくことを重視していました。

コミュニティのコアスタッフの経験が一切なかったのとガムシャラにタスクを取りすぎ+業務の繁忙期という状況になって、チケット公開でちょっとやらかしてkatsuhisaさんにフォローしてもらったり、多々粗相はあったとは思いますがある程度価値は発揮できたし信頼関係も構築できたかなと思っています。

後は、途中で僕の前職の同僚(@Buzz)と先輩(@ogady)を運営メンバー誘って、自分が抱えすぎたタスクをうまく割振れたのも爆発せずに済んだ要因だと考えています。。@Buzzと@ogadyはありがとうね

ここからは、それぞれやってことをトピックごとに少し振り返ります。

イベントチケット/参加者管理

だいたいチケット周りは一人で担当しました。 イベントチケットサイトとして採用したEventbriteのUIやシステムの不安定さには手を焼かれましたが、機能要件は完璧に満たしていたので、まぁサービス選定は間違ってなかったのかなと振り返ってみて思います。 詳しいここら辺の選定/オペレーションの話はどっかでまとめると思います。

一般参加者人数の意思決定に関しましては、とにかく参加者が快適であることを優先しました。後100人くらいにはチケットを売れたかもしれませんが、それで参加者の満足度が下がっては意味がありませんので、そこの意識は常に徹底して経理周りをすべてやっている@ogmさんなどと相談して決定しました。今回はこれでよかったと思っています。

オープニング動画/セッション紹介動画作成取りまとめ/スポンサー動画作成

当初は私がオープニング動画/セッション紹介動画も作ろうと思っていましたが、動画関連のサービスのエンジニアといえど動画制作の経験はありませんでしたので、クオリティの保証ができないということで外部に委託しました。

そこでお願いしたCrevo様並びに担当クリエイターさんには、低予算(初回なのでお金がない)にも関わらず本当によく対応していただきました。本当に感謝!

「セッション紹介動画を毎セッションの前に流す」案に関しては、発表お立ち台のない会場で雰囲気にあわないのではないか?などの意見がありましたが、僕が登壇者だったらテンション上がるし参加者としてもスペシャリティを感じてくれると判断し、作成し流すことに決めました。

こんな無理なお願いにも関わらず、本番は最高の音響オペレーションをしてくれた@okash1n,@Ryoter,@H.M,@sogaoh氏には本当に感謝しても感謝しきれません。こちらにも感謝の意を今一度表させていただきます!

結構動画系は評判良くて嬉しくて懇親会のお酒がめちゃくちゃ美味かったです。

Twitter運用

とにかく参加者の満足度が下がるようなことが起きて欲しくない一心で事前注意を繰り返し共有すること、みんなで盛り上げていこうと言う意識は徹底していました。

注意事項をひたすら繰り返しメールとともに案内する、ここはしつこいくらいの方がいいと判断し徹底して行いました。(会場、受付混雑回避施策のヨガ、チケット譲渡、QRコードの用意の案内、その他注意事項)

また、イベント開催前からイベントの雰囲気作りは始まっていると思っているので、ひたすら#srenextタグで呟いてくれるツイートは捕捉していいねリツイートしてみんなで作るカンファレンスなんだ、と言う意識を共有することは大切にしていました。

課題としてはマーケティング面で、少し絵力のないツイートばかりで、もう少しツイート構成を工夫できればよかったなと思ってます。(まぁ1ヶ月前には売り切れてしまったので、宣伝のプライオリティが落ちたと言うのもあるのですが)

あとはとにかくSRE NEXTでエゴサーチして、参加予定者がどういう所に不満を持っているかをキャッチするのは毎日やってました。そこからサイトの情報の掲載の仕方を変えたり、個別でフォローするCSライクなこともやっていました。(もちろん直接くるDMの対応も)

参加型アンケートをスポンサーブースへの誘導施策として実施

最終的に100人くらいの人に参加いただけたので、ある程度は成功したかな?(段取りの面でめちゃくちゃ反省がありますが、@saitotaq氏に救われましたありがとう。)次回があるなら、もうちょっと凝った誘導施策をやりたいですね、スポンサーのためにも。

リアクションも結構あった。

当日の反省/振り返り

細かい自分のタスクに対するKPTは多々ありますが、そちらは運営内のシートや振り返り会で細かくやりたいと思います。 自分の全体としての大きな問題としては、

  • 初の大きなカンファレンスの運営スタッフ(ボランティアスタッフは何度かやっていますが)かつ臨機応変な動きが必要となる遊撃隊という立ち位置で、度々適切でない問題提起の仕方をしてしまった(感情が丸出し、解決方法の提案とセットではない)

これがすごく反省です。こればっかりは経験値不足でしゃあないって感じですが、ケーススタディ的に色々こういう問題が起きたらどうするかを想定して学んだりはしていけるはずだし、今回で自身も成長しているはずなので次回以降はもっと柔軟に冷静に対応できるようになります。

SRE NEXTの課題とこれから

TLを追っていても肯定的なツイートが多く、イベントとしては大成功だったとは思いますが、こういう時こそ冷静に課題とこれからについて整理したいと思います。

組織の設計、あり方 

第一回ということもあり、良くも悪くも皆何でも屋で、タスクをゴリゴリ進めていくベンチャースタイルの運営方法でした。

しかし、これからの組織やカンファレンス規模拡大を考えると、この体制は再検討しなければならないと思っています。 継続的にひたすら雑多にタスクをこなすことが美となってしまうと、スペシャリティを持った人間のスポット起用といった選択肢が取りづらくなってしまいます。

ですのでコアスタッフという一律の扱いを僕はやめるべきだと思っています。ある程度Roleを明記したりそれに基づいてチーム編成を考えたり、そういった組織設計を次のステップに進む時にまず初めに考えなければならないですね。

まぁしんどい雑用もたくさんあるんで、そこは皆でやっていくしかないのはそれはそうと言うやつですし、仕事じゃないのである程度奉仕の精神に支えられているのは間違い無いので、そこをどう「俺はこんなに仕事しているのになんであいつはやっていないのだ」と言う負の感情に向かわないように仕組みを作るかが重要だなとおもっております。

カンファレンスとしての方向性

国内でどんどんTokyoだけでないコミュニティの発展を後押ししていくことを重視するのか、それともSREconが無視できない国際カンファレンスとして成長させるのか、SREcon Asia/PacificをTokyoに誘致してまずパイプを作ることに注力するのか。色んな選択肢がありメンバーそれぞれの嗜好があると思っています。ここをきちんと定めるのも、組織設計の再検討とともに初めにやるべきだと考えます。

私のこれからのSRE NEXTとの関わり方

僕のこれからのSRE NEXTとの関わり方として、マーケティングやコンテンツの責任者をやっていきたいと思っています。(海外対応のカンファレンスにしていくならそこにも尽力したい)しかしセッション選定に関しましては、僕の現在のエンジニアリング力では一切説得力がないです。

私は現在絶賛SREへ転職活動中で、1月中にはどこにいくかは決めようと思っています。 (決まったら皆様には改めて報告させていただきます。)

新天地で自分のSREとしてのスキルやスペシャリティを磨きつつ、個人でもアメリカの通信大学でCS学んだりLeetCodeひたすら解いたりして根底の力も伸ばしながら僕の目指す理想のSREになっていき、SRE Lounge/NEXTというコミュニティとともに成長しつつ還元していきたいと思ってます。

最後に

本当に参加者やスポンサーの皆様にはお世話になりましたし、おかげさまで素晴らしいイベントになったと思います。ありがとうございました!今後とも前向きに継続検討しておりますので、よろしくお願いします。

売り切れて参加できなかったよ、、と言う人は多くの人が書いていただいている参加レポや、こちらの資料まとめの記事などを参考にしていただくとどんなイベントかわかりやすいと思いますし、良質な情報ばかりだと思います!(後ほど公式からもまとめて共有します) また、全てではないですが、セッション動画公開予定なのでそちら楽しみにしていてください。

また、スタッフ(当日、コア問わず)の皆さんも言わずもがな最高でした。SREらしい柔軟な動きを皆さんができていて、皆さんのおかげで最高のイベントになったと思います!最後にめちゃくちゃCoolなスタッフの全体写真のツイートを貼ってこの記事は終わりにします。(なおこの写真には僕は載ってない笑)

メインフレームを保守するSIerからWeb Developerにジョブチェンジして、もうすぐ1年経つので振り返る

はじめに

こんにちは!都内でWeb Developerをやっているnariと申します。 現在はアーティスト支援系サービスをGo/AWS/Terraformで開発しています。

今年一年の振り返りはさらっとTwitterで済ませてしまおうと#2019年を振り返るハッシュタグに便乗して上記のようなツイートをしてみたところ、案外多くのリアクションをいただけたので別途記事でも書くかということでこの記事を書いております。

また、今年2月から現職にお世話になっていて、来年の1月末で某金融系SIに所属するメインフレームを保守するSIerからWeb系企業の開発者として転職して丸一年経つということで、そちらもまとめて振り返ってしまおうという感じになってます。(雑)

この記事で書かないこと

  • 抽象的なSIとWeb企業の比較談義

ひたすら私具体的にやってきたこと/それをやった理由を棚卸するだけの記事になります。ご了承ください。

なぜ転職したか

  • ビジネスサイド(銀行)、運用部隊(データセンター)との折衝にひたすら工数を取られる当時の状況に疑問を感じ、devopsを体系的に学びたかった
  • 当時PMとしてキャリアを積んでいく路線だったが、設計/実装/運用を知らないものにエンジニアリングのマネジメントはできないと判断し、全てが効率的に学べるのがWeb業界だと感じた
  • 現職はアーティスト支援をメインの思想として掲げており、音楽やカルチャーが大好きで演者としての人生も考えていた自分にマッチした

結果的にアプリ〜インフラ、設計〜運用まで幅広く経験することができており、ジョブチェンジして正解だったなと思っています。

今年一年で何をしてきたか

業務

GoでのAPI開発

とりあえずJava/Rubyを少し書いていたくらいで、Goが何もわからないので、簡単なWebアプリをMVCで作ってそれをClean Architectureにリファクタする中で基本のお作法を覚えました。正直DIだのDIPだのまじ意味ワカンねぇなってなりましたが、色んな文献を読み実装する中で徐々に自分の中に落とし込めた気がします。

qiita.com

OpenAPI仕様管理ツール(Apicurio,Stoplight)を比較検討を導入し、既存のAPI仕様をドキュメント管理ツールでの管理から移行したりもしました。

qiita.com

qiita.com

それからは、メインプロダクト(動画納品サービス)とショップリコメンドシステム(ポイントモール)のAPI開発を通して、実践的なGoの書き方/generater/testの書き方を学んでいきました。また、チームの流れとしてClean ArchitectureでDI可能な方向にリファクタリングしていくなかで、基本的なレイヤードアーキテクチャデザインパターンも学んでいきました。

AWS上でインフラ全体を設計し、IaC(インフラのコード化)する経験

こちらは、ショップリコメンドシステム(ポイントモール)を構築するにあたって、新規にAWS上にインフラを構築できるということで、先輩と二人でビジネス的な要件に合わせ全体を設計し、TerraformでIaCしながら実装しました。 以下のように、この案件で非常に広範囲のインフラ構築の経験が積めました。

  • http serverをdeployするための基本的なインフラ(VPC, ALB, S3, RDS,Nginx)
  • 急激なアクセス増加に合わせて、低コストでスケールするアプリケーションサーバー(ECS on EC2,ECR, SpotInstance, CloudWatch Event, Lambda)
  • 顧客影響のあるFatalなアラート時は、Slack通知後に電話(Amazon Connect, CloudWatch Event, Lambda, SNS)
  • レスポンスタイムの要求がシビアになっていくことが見込まれていたので、マスターとは別にアプリがやりとりするデータソースとしてRedisを選択し、List/Hash/String(json)型のパフォーマンス計測で比較検討しデータ設計(Elasticache)
  • 親システムとのマスター同期のための非同期ジョブの実行管理(Step Functions)
  • AthenaでもBig Queryでも解析できるログ基盤構築(Fluentd,Kinesis firehose,S3)
  • 仮説検証を高速で行えるようなCI/CDの整備(AWS CodePipeline,Gitops)

もともと「AWS?何それわからん。。IaCなんてよりわからん。。」だったのが短期間でここまで実装し経験を積めたのは、事前にAWS SAAを取得し頭の中に目次を作り、技術書典6でTerraform入門本の名著「Pragmatic terraform on AWS」を購入しプライベートで色々いじっていたのが効いたと思います。

qiita.com

qiita.com

qiita.com

qiita.com

IaC啓蒙

サービスとして、グローバル展開をするということで従来のGUI管理では限界がきているのは目に見えていたので、自身もう上記の案件でノウハウのあったTerraformの勉強会を開催しました。

qiita.com

こちらの具体的なお話は、SRE Advent Calendar 2019の22日目に書いています。

qiita.com

これからも継続して実施していけたらと思っています。

ChatOps導入

チャットツールにインターフェースを集約し、メンバー操作の履歴をシェアするChatOpsの思想が好きで、AWSリソースを操作するのにクレデンシャルに煩わずスラッシュコマンドで呼び出せるSlackBotを作成し、導入したりしました。

speakerdeck.com

共通検索基盤事前調査・設計(Pending)

弊社のアーティストサービスでは、アーティスト/曲/リリースといったデータ検索をネイティブアプリ/Webアプリでももちろんできるのですが、双方精度とレイテンシーに問題がありました。 ですので、Elasticsearch(形態解析とユーザー定義辞書のメンテ)とGo製のAPIで双方の問題を解決するというプロジェクトをやっていましたが、USプロジェクトの方が優先度が高くなりPendingの状態となりました。

qiita.com

AWS上のステージング・開発環境のリソースのIaCとアカウント移行

こちらはterraform Advent Calendar 2019 15日目の方に詳しく書かせていただきましたので、そちらをお読みいただければと思います。

qiita.com

手動デプロイをCD as a serviceに委譲(WIP)

こちらはまだWIPの状況ですが、手動デプロイをCircleCIとGitopsのよるデプロイのコントロールに以降しようとしており、AWS Codeシリーズとの比較検証は大枠の設計は終えています。来年落ち着き次第こちらも記事にしたいと思っています。

USチームとの折衝/調整/会議のファシリテート

もともと英語のReading/Writingはまぁまぁ不自由なくできる方だったのですが、Speaking/Listeningにかなり苦手意識がありました。しかし、ここ三ヶ月ほどUSチームと週一でmeetingしたり定常的にChatでやりとりしたり、プライベートでもシャドーイングやDMM英会話のレッスンを受けたりすることでかなり苦手意識がなくなり、ビジネス上での意思疎通くらいなら不自由なくできるようになってきました。これからも継続して英語力はブラッシュアップしていきます。

技術発信支援

もともと入社当時は弊社のアウトプットはお世辞にも活発な状況とは言えなかったので、まず自身が週一でアウトプットし、社内外でシェアすることでアウトプットしていく流れを作ろうとしました。

その結果個人的には社内表彰をされたりもしました。

しかし、それだけではアウトプットの文化作りという面ではあまり上手く行きませんでした。(特に他の人がアウトプットをし始めるとかはなかった)

そこで12月からはアドベントカレンダーのチャンスを生かし、普段アウトプットしていないが書いた記事を読んでみたい人に声をかけまくって、記事を書いてもらいました。その際、アイデアが出てこないという人とは壁打ちしたり、構成に自信がないという人はreviewをしたりしながら、アウトプット/知の共有の楽しさを伝えていきました。

結果Qiita Organizationのメンバーは当初の2倍以上になり、「書いてよかったし、これからも継続して書いていきたい」という声を聞くことができました。継続的に支援し、これからも多くの人が知の共有の大切さに気がつくきっかけを作れればと思っています。

qiita.com

プライベート

1月にギークハウスに引っ越した(2020/01/02 追記)

25年間ずっと実家暮らしだったんですが、もうそろそろ外に出ないとなと思ったのもあって思い切って引っ越しました。 ギークハウスを選んだ理由は、ちょうど技術者として生きていく決意(転職)とともに住む環境もガラッと変えてしまった方がいいと思ったからです。 最初は西新宿の方に2ヶ月くらい住んで、その後代々木の方でずっとお世話になっています。

みんなで開発合宿したり、突然のLT大会で情報共有したり、おうちハックしたりエンジニアにとって最高の環境です。自分にないものを持っている人がたくさんいて、その人々と知のシェアリングができている感じが現代っぽくてとても好きです。 結婚したり同棲する人ができたりするまでは、シェアハウスでフラフラしたいと思ってます。

以下はみんなで作ったシェアハウスの鍵を開けるシステム

鍵システムの紹介と、Go/ラズパイ/Mackerelを使ったおうちハックの勧め記事 qiita.com

AWS SAA(認定ソリューションアーキテクト アソシエート)取得

入社当初クラウドなんもわからん、、チームメンバーの言ってることが全然わからん。。だったので、とりあえず冒険の地図を得る感覚でAWS SAAを取得しました。今振り返ると、入社直後にとったのは英断だったと思います。みなさん是非とってみてください。

qiita.com

モデリング会立ち上げ

ちょうどチームとしてもClean Architectureでリファクタしていくという流れだったのもあり、そもそもの根本のモデリングを学びたくモデリング会を立ち上げました。

geekhouse-shinjuku.connpass.com

fukubaka0825.hatenablog.com

非常に得るものも多く常に定員の2倍くらい応募のくるイベントでしたが、3回ほど行った後Developer Productivity/IaC/SREという領域に興味がかなり移行してしまい、しばらく行えていません。 どこかで再開したいと思っています。。

Gopher道場卒業

Gopher道場とは、Go Conの主催者でもあるtenntenn氏が定期的に開催している体系的にGoをみっちり学べる勉強会です。 課題を提出し無事選考を通り1ヶ月講義と課題をこなし、最後にLTをしてGopher君Tシャツをもらい卒業しました。

gopherdojo.connpass.com

qiita.com

結果、Table Drivenテストやエラーハンドリングについて特に理解を深め、現場にも持ち帰り導入できたし、何よりGoを学ぶ熱量が高い仲間ができたので非常に有益でした。

技術書典7で技術同人誌初執筆

私はギークハウス新宿というシェアハウスに住んでいるのですが、仲良くさせてもらっている住人(@wamisnetや@samuraikun(元住居人))など技術書執筆経験者が非常に多く、技術書典6に参加し感化されたのもあって技術書典7に参加し技術書を頒布することとしました。

非常に多くのトピックを扱いすぎたり、なかなか執筆のエンジンがかからなかったりで非常に苦労しましたが、住人のサポートのおかげで記事のアウトプットでは得られない経験がたくさんできたので非常によかったです。

fukubaka.booth.pm

note.com

技術書典8は出られないですが、技術書典9では何かしら書くつもりでいます。

SRE NEXTの運営メンバーに加わった

9月に参加したSRE Lounge #10でSRE NEXTなる日本初のSRE Conferenceが開催されるということ知り、昔からdevops/基盤に関する関心が強かったこともあって居てもたっても居られず、気がついたら主催者のkatsuhisaさんTwitterのリプで「是非お手伝いさせてください!」と送っていました。 そうして、運営メンバーとして参加させていただくこととなりました(何処の馬の骨かわらない僕を入れてくれたことに感謝!)

sre-next.dev

私が具体的に何をやっているかというと、Twitter運用/ブログ記事作成/イベントチケット管理/動画制作の取りまとめ などなどをやっていっています。

ちなみにSRE NEXT 2020は2020/01/25開催ですが、もう一般チケットは全てSOLD OUTしてしまっています。

しかし非常にハイレベルはセッションばかりなので、参加できない方も後からスライドをチェックしたりしながら活用していただければと思います。 参加者の方はスタッフ一同、急ピッチで準備進めており、素晴らしいイベントにしますので当日はよろしくお願いいたします。

記事をたくさん書いた

数えたら、はてなブログ、Qiita、note、medium合わせて今年で54記事書いていました。Qiitaで何個かバズったりして、合計2000いいねを超えたりしました。

f:id:st5818129:20191231184833p:plain

一方、アウトプットが散らばってしまいとても見辛い状況になってしまったので、年末に自身のキャリアとアウトプットを集約したポートフォリオサイトを整備しました。

www.fukubaka0825.dev

来年も質を向上させながら継続していきます。

来年一年何をしていきたいか

業務

SRE/Platformerとしての経験を積みたい

現在はいちWeb Developerとしてアーリーな時期のプロダクトにSREの種を植えていっている(IaC,CDなど)状態ですが、片手間ではなく体系的にSREを学び実践していきたいと考えています。(弊社だとこれからUS展開などで開発の方により一層リソースを割かざるおえない)

というのも、もともとドラマーであることも起因しているのか、ビジネス成功可能性を最大化する基盤/開発者の生産性向上への興味関心が何よりも強く、DeveloperとしてというよりSREのスペシャリストとして勝負していきたい思いが強くなったからです。

ですので、グローバルサービスのSREを募集している企業様がありましたらぜひお声がけください。必死でキャッチアップし食らい付き、お役に立つ自信はあります。

プライベート

OSS活動を活発に

最近Goで一つツールを作ったり、terraform-aws-providerやtfnotifyなどへコントリビュートしたりしていますが、この流れをより加速させていきたいです。

qiita.com

qiita.com

具体的には、OSSへのコントリビュートは最低月1で、OSSツールは2ヶ月に一回作成し、50スター以上の皆に愛されるツールを最低1つ作ることを目標とします。

アウトプット改善

質を高める

社内ではreviewしたり壁打ちしたりしている立場ですが、正直自分のアウトプットに関して少し限界が見えているなと思っています。 ですので、この機会にカックさん(有名なブログメンター)のメンタリングを受けたりしながら一旦自分のスタイルを再構築したいと思っています。

英語のアウトプットを増やす

現状、英語用のtwitterアカウントも英語記事用のmediumもうまく活用できてるとは言えないので、これからmediumには最低月2回記事を載せ、twitterも日常の勉強内容をつぶやいていこうと思っています。

登壇を増やす

今年の登壇回数は二回と、お世辞にも多いとは言えませんでした。 記事を量産できたのはいい点ですが、アウトプットの場としてこちらの割合も上げていきたいです。(最低でも月一回LTする)

また、大型カンファレンス(Go Con,SRE Con,SRE NEXT)などのCFPにもプロポーザルをどんどん出していきたいです。国際的なカンファレンスでの登壇を目標に頑張ります。

CS (Computer Science)力の強化

文系卒developerあるあるですが、CSの素養がきちんとあるとは言えない状況です。 将来的にはCSの学位か博士を取っていきたいですが、当面はまずアルゴリズムとデータ構造は螺旋本、ネットワークに関してはネスぺを取得するなどなど書籍や資格勉強で補填していきながら、業務の中でブラッシュアップさせていきたいと思います。

最後に

Global ServiceのSREを募集している企業様、是非お話を聞かせていただきたいです。TwitterのDMからご連絡お待ちしております。