日記マン

動画広告プロダクトしてます。Go, Kubernetesが好きです。

12月振り返り

まさかの一年ではなく今月に限定して振り返ってみる。。

  • 実務と関係あること
    • Go言語のランタイムの動作理解(netpoller周り)
    • Kubernetesの拡張性 AdapterパターンとOperatorパターン
    • システムパフォーマンス
    • 継続的プロファイリング
    • プロダクトを継続させるための考え方
  • ただの興味
    • Rustの async-std

実務と関係あること

Go言語のネットワークI/O実装(netpoller)と非同期I/O(e.g. epoll)

Go言語はどうやってネットワークI/Oを実現しているか興味があって調べた。
同時に1万のネットワークI/O待ちが起きたとしてもI/O待ちのOSスレッドが1万立ち上がるわけではないその理由が言えるようになりたかった。
結論から言うと、Goランタイム上で実装されているスケジューラとnetpollerが良い感じに同時I/O実行を少ないスレッドで行えるようにしている。
Goではネットワーク通信するプログラミングをすると、同期的なコードブロックが行われるが、
これはepollの監視にソケットを登録しgoroutineを切り替える。
そのgoroutineはソケットが read ready になったら復帰する。
これらの過程で、カーネルレベルの非同期I/O実装(Linuxではepoll(7))といったGo言語に限らないテクニックを知れたのもよかった。

  • [x] ブログにアウトプットする

i101330.hatenablog.com

AdapterパターンとOperatorパターン

Kubernetesがコンテナオーケストレーションツールの中で群を抜いて人気な理由の一つに優れた拡張性があると思う。
AdapterパターンとOperatorパターンはKubernetesをエコシステムの立ち位置とさせる重要なデザインパターンだ。

↓Custom MetricsをどうやってHPAのターゲットにしているんだ?をまとめた良記事
qiita.com

kube-apiserver には拡張領域 aggregation layer があり、そのプラガプルを活かすAdapterパターン。
一方Operatorパターンの言葉の定義はいまいちあやふやな理解(界隈的にもまだ未熟では)
独自Kubernetesリソースを定義できる Custom Resource Definitation + 独自コントローラを実行できる Custom Controller を活かして、
ステートフルアプリケーション(DB等)を運用するのを Operator と名付けているイメージ。
ただ、これは立ち上げだけをするのか、リストア・リカバリを自動で行うまでをするのか、
みたいな最低限どこまで機能があってOperatorと名付けられるのかがよくわからない(し、界隈的にもまだ未熟?)

  • [ ] 構築済みのPrometheusをAdaptしCustomMetricsでスケールさせる

ってやつ宿題にしようかな。

「詳解システムパフォーマンス」

いい本を買った!分厚い本だがとにかく内容が濃く面白いし読みやすい!

詳解 システム・パフォーマンス

詳解 システム・パフォーマンス

2章でパフォーマンス分野におけるメソドロジ(方法論)外観に触れ、
各章でチューニング対象ごとにそのメソドロジを持って「パフォーマンスのどこが問題になるか?・どこから手をつけ始めるとよいか?」を解説してくれる。
3章ではオペレーティングシステム、5章ではアプリケーションを題にして解説してくれる。
そのあとの6-10章で、CPU・メモリ・ファイルシステム・ディスク・ネットワーク といったリソース毎に焦点をあて、仕組みの紹介・どこに問題が起きるか・メソドロジといった流れで解説が行われる。
Brendan先生はテクニカルライティングにも優れたお人なんだろう、というのは本を読んで思うのはもちろん、彼のブログからも読み取れる。

www.brendangregg.com

GoアプリケーションをProfilingする

おかげで12月の大半はとにかくProfilingに関心が強かった!
Goはとにかくプロファイリング周辺も強力なツールが揃っている。これは活かさないわけにはいかない。
pprof UIには感銘を受けた。 プロファイルデータは protobuf で定義しているためGoに限らず言語問わずのプロファイリングエコシステムを築いている。
↓ @rakyll お姉さんのアウトプットにとにかく夢中になって掘り下げている。
medium.com

↓GoアプリケーションのProfilingを実行しパフォーマンスを分析、コードを修正し改善するワークショップ

github.com

継続的プロファイリング(Continuous Profiling) というアツいキーワードを知った。
業務でもプロダクション環境のアプリケーションに対しプロファイリングをしてより詳細な状態分析をしているがとても体験が良い。
これまではシフトライト(静的検査 + CI(テスト) + CD(リリース)) を身に付けてきたが
シフトレフト(本番環境からのフィードバックを分析する)も身に付けておきたい。
↓conprofには期待したい。コードも読んでみて勉強になる。

github.com

jvns.ca

プロダクトの成長を継続させる考え方

大半ベンチャーの寿命は5年で終わるというが、ゼロイチの初速はよくてもイチヒャクに育てる難しさにつまづいてるケースが多いと思う。
自分自身もいまそれを思いっ切り体験している。
この複雑な問題への整理・切り分け・改善する難しさを特に身にしみた一年だった。
ちゃんとやりきって、そしてこの取り組みをこのブログでも言語化するところまでを目標にしたい。

ただの興味

Rustの非同期I/Oランタイム async-std

今年の5月に車輪本を買ってRustをたまーに勉強している。
型システムがしっかりしていて(やっぱり代数的データ型ある言語は強い。)それでいて動的ディスパッチによる抽象コストが無く、
さらにガベージコレクションによるランタイム上のメモリ管理ではなく、メモリ管理(含めてリソース管理)が引き起こす問題を静的検査ルール(所有権・ライフタイム・借用)で解決する言語デザインが魅力的な言語だと思う。
そんなRustも長い間、非同期処理周りがかなり試行錯誤中だったみたいだが、ついに ver. 1.39 から async/await 構文が安定化した!
そして注目の非同期処理I/Oランタイム期待の新星 async-std がアナウンスされた!

async.rs

Goの goroutine scheduling + netpoller からインスパイアを受けたデザインで、個人的にも親近感がある。
Go畑で goroutine scheduling + netpoller の恩恵を受けまくっている身としては、Rustの言語デザイン上でそれ同等の恩恵を受けられるのはワクワクする!

まとめ

12月も業務では絶賛システムのリプレイス実行中だが、一部機能から段階的にリリースしてきている。
そこで本番環境で動くシステムの監視もやり始め、メトリクス・ログから状態を把握し、より詳細な分析にプロファイリングも実施するなどしている。
この辺りは別途ブログでアウトプットしたいと考えている。
可観測性の確保・パフォーマンス可視化・適切に把握・チューニングする、といった分野に対し今まで苦手意識もあったが、
Brendanのパフォーマンス本を片手に果敢に取り組んでいけてると思う。(というか夢中になった)
アンテナを貼りながら知識を増やしていくことはもちろん、それだけでは「言うが易し」なので、コンスタントに実行してアウトプットを増やしていきたいと思う。