Mais conteúdo relacionado
Semelhante a 趣味と仕事の違い、現場で求められるアプリケーションの可観測性 (20)
Mais de LIFULL Co., Ltd. (20)
趣味と仕事の違い、現場で求められるアプリケーションの可観測性
- 3. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
目次
5.おまけ(時間があれば)
4.アプリケーションの可観測性の勘所
3.仕事のアプリケーションで求められるもの
2.趣味のアプリケーションでやりがちなこと
1.紹介
- 4. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
- 株式会社LIFULL 相原 魁
- ソフトウェアエンジニア スペシャリスト(Platform Engineering, SRE)
- 仕事ではKubernetesをベースとした内製PaaS KEELを開発・運用
- 趣味では主にRustを書いています
- 全文検索ライブラリ
- 分散検索エンジン
- eBPF
自己紹介
- 5. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
- 株式会社LIFULL 相原 魁
- ソフトウェアエンジニア スペシャリスト(Platform Engineering, SRE)
- 仕事ではKubernetesをベースとした内製PaaS KEELを開発・運用
- 趣味では主にRustを書いています
- 全文検索ライブラリ
- 分散検索エンジン
- eBPF
自己紹介
可観測性のプラットフォームも開発する立場
分散システムを開発する中で可観測性に注力
- 6. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
「したい暮らしに、出会おう。」をコンセプトに掲げ、簡単で便利な住まい探しをお手伝いする不動産・住宅情報の総合サービスです。
物件の探しやすさや住まいに関する情報の見つけやすさ、検討がしやすくなるように、様々な機能や情報を拡充していきます。
今後も、ユーザーに寄り添いながら、ともに理想の住まい探しを実現します。
- 7. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
LIFULLの内製PaaS KEEL
- コマンドを1発叩くだけで完璧なアプリケーション実行環境が手に入る内製PaaS
- デプロイ、セキュリティ、可観測性、信頼性、パフォーマンス
- コードジェネレータを中心とした開発者体験の提供
- Pull Requestを作成するとプレビューできる機能やLint, Content Trustまで備える
- https://www.lifull.blog/archive/category/Kubernetes
- 8. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
本日のゴール
可観測性に優れたアプリケーションを実装できるようになる
※少しWebに寄った話になります
※後でリファレンスとして使えるよう説明的な資料にしているので今全てを理解する必要はないです
- 10. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
func doSomething() *RetVal {
retval, err := maybeError()
if err != nil {
log.Printf("an error occurred: %+v", err)
}
return retval
}
エラーをとりあえずでロギングするだけ
- 11. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
func doSomething() *RetVal {
retval, _ := maybeError()
return retval
}
そもそもエラーをハンドリングをしない
- 12. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
fn doSomething() RetVal {
let result: Result<RetVal> = maybeError();
let retval = result.unwrap();
retval
}
Rustだったらunwrap()するだけとか
- 14. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
func doSomething() *RetVal {
start := time.Now()
retval := maybeSlow()
elapsed := time.Since(start)
log.Printf("maybeSlow took: %s", elapsed)
return retval
}
実行時間の計測をログで頑張る
- 15. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
func doSomething() *RetVal {
retval := maybeSlow()
return retval
}
そもそも実行時間を気にしない
- 16. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
func main()
retval, err := doSomething()
if err != nil {
fmt.Fprintf(os.Stderr, "%+v", err)
}
}
func doSomething() (*RetVal, error) {...}
折角もらったエラーを適当に標準エラーする
- 19. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
趣味と仕事の違い
- 開発者である自分自身だけが未来永劫メンテナンスし続けるわけではない
- 実装に詳しくない人が状況を判断できる必要がある
ソースコードを読むことも書き換えることもなく必要な情報を取得できる
- 20. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
可観測性
- 可観測性(observability)とは、システムの外部出力を観測することでシステムの内部状態を推
測可能かどうかの尺度である。
- 引用: 状態空間 (制御理論)#可観測性
- microservicesの流行などによってシステムの構成が複雑化して重要性が増してきている
- 22. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
Metrics
Traces Logs
- 特にフォーマットのないテキストデータ
- 出力方法
- アプリケーションからファイルに書き込む
- アプリケーションから標準出力・標準エラーする
- 26. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
Metrics
Traces Logs
- インデックス付きの数値データ
- OpenMetricsで標準化が進んでいる
- 数値データであるためLogsと比較して安価
- 出力方法
- エージェントが外部から観測して出力
- アプリケーション内で計測して出力
- 27. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
余談: OpenMetrics
- Prometheusというモニタリングシステムを参考に標準化されたフォーマット
- summary, gauge, counter, statesetといったいくつかのデータタイプでMetricsを表現
- エージェントあるいはアプリケーションがこのフォーマットに従って出力する
- Datadogをはじめ多くのモニタリングシステムがサポート
- 28. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
CPU, Memory Usage
- Linuxでは /proc から取得することができる
- /proc はプロセスの情報を持つ擬似ファイルシステム
- /proc/<PID>/statでは14, 15個目がCPUに関する情報
- 実際はエージェントが勝手に収集してくれていることが大半
- 29. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
アプリケーションのエラー数
- アプリケーション内部のエラー数のカウンタ
- Logsでも表現できるがコストの観点からMetricsであるとよい
引用: kubernetes/autoscaler
- 30. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
Garbage Collectorに関する情報
pp GC.stat
#{:count=>13,
# :heap_allocated_pages=>50,
# :heap_sorted_length=>69,
# :heap_allocatable_pages=>19,
# :heap_available_slots=>20383,
# :heap_live_slots=>20256,
# :heap_free_slots=>127,
# :heap_final_slots=>0,
# :heap_marked_slots=>17090,
# :heap_eden_pages=>50,
# :heap_tomb_pages=>0,
# …}
- ランタイム内に持っているGCの情報
- アプリケーション内で収集して出力する
- 31. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
ミドルウェアの各種情報
- ミドルウェアによって出力されているMetrics
- e.g. ngx_http_stub_status_module
- エージェントが収集しに行って出力する
- ミドルウェア自身が直接出力するケースも増えてきている
- 32. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
余談: Prometheus Exporter
- Metricsを出力するためのPrometheus用のエージェント
- PrometheusのMetrics表現はOpenMetricsと互換性があるため広く利用できる
- OSSとして多くのPrometheus Exporterが存在する
- MySQL Server Exporter
- Redis Exporter
- NGINX Prometheus Exporter
- cAdvisor
- 利用するミドルウェアに対応するPrometheus Exporterを探すことができる
- EXPORTERS AND INTEGRATIONS
- 33. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
インデックスとカーディナリティ
- MetricsはラベルというKey-Valueを元にインデックスする
- ラベルの数が多いとカーディナリティが高くなりコスト増
- e.g. {uri=”/items/1”}, {uri=”/items/2”}, … {uri=”/items/9999”}
- こういった詳細な情報の表現はLogsの方が向く
- 34. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
Metrics
Traces Logs
- 依存関係を持つメタデータの有向非巡回グラフ
- Spanというデータ構造の集合からなる
- OpenTelemetryで標準化が進んでいる
- 計測も保存も比較的コストが高い
- サンプリング(間引き)をすることが一般的
- 出力方法
- アプリケーション内で計測して出力
- 35. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
余談: OpenTelemetry
- OpenTracingとOpenCensusが統合されて生まれたプロジェクト
- OpenTracingはTracesの標準化をしていたプロジェクト
- OpenCensusはTracesとMetricsの収集を補助するライブラリ
- OpenTracingはベンダー中立にPropagationするための仕様を策定していた
- 39. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
Span
- 開始・終了のタイムスタンプとKey-Valueのラベル等を持つ
- 0つ以上の親となるSpanを持つことができる
引用: OpenTracing Specification
- 40. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
Propagation
- アプリケーションをまたいだ依存関係を持つことができる
- アプリケーション間の依存関係はHTTPヘッダで引き回す
- W3C Trace Context
- traceparent Header
- trace-id
- parent-id
- sampled
- microservicesの依存関係を可視化することができる
- 41. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
func doSomething() *RetVal {
start := time.Now()
retval := maybeSlow()
elapsed := time.Since(start)
log.Printf("maybeSlow took: %s", elapsed)
return retval
}
実行時間の計測をログで頑張る
再掲
- 42. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
func doSomething() *RetVal {
start := time.Now()
retval := maybeSlow()
elapsed := time.Since(start)
log.Printf("maybeSlow took: %s", elapsed)
return retval
}
実行時間の計測をログで頑張る
maybeSlowが複雑な依存関係を持つ場合Metricsだけでは調査しづらい
Tracesも収集することで依存関係のボトルネックを探せるようにしたい
再掲
- 43. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
OpenMetricsとExemplars
- OpenMetricsは外部のデータに対する参照を持つことができる
- ExemplarsというKey-Value
- MetricsとTracesを関連付けることができる
引用: Exemplars | Grafana Labs
- 44. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
ここまでのまとめ
- 実装に詳しくない人が状況を判断できるよう可観測性が重要
- 可観測性には3つの性質の違う主要なシグナルがある
- Logs: 自由度が高くフォーマットを持たないテキストデータ
- Metrics: 詳細な情報を安価に表現するインデックスつきの数値データ
- Traces: 複雑な依存関係を表現できるメタデータの有向グラフ
- それぞれ補完しあう関係にあるため組み合わせて使う
- Metricsはコストが安いが詳細情報や依存関係を持てない
- Logsは詳細情報を持てるがコストが高い
- Tracesは依存関係を持てるが表現が限定的でコストが少し高い
- 45. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
余談: 周辺エコシステム
- Logs
- Grafana Loki, ElasticSearch
- Amazon CloudWatch Logs
- Cloud Logging
- Metrics
- Prometheus(Cortex)
- Amazon CloudWatch
- Cloud Monitoring
- Traces
- Grafana Tempo, Jaeger
- AWS X-Ray
- Cloud Trace
- All-in-one
- Datadog
- NewRelic
- Grafana(?)
- OSSのObservability Platform
- Loki, Cortex, TempoのGrafana Labsが開発
OpenMetrics, OpenTelemetry含め殆どがCNCF周りのもの
- 46. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
余談: CNCF
- > Cloud Native Computing Foundationは、オープンソースでベンダー中立プロジェクトのエコシ
ステムを育成・維持して、このパラダイムの採用を促進したいと考えてます。 私たちは最先端
のパターンを民主化し、これらのイノベーションを誰もが利用できるようにします。
(https://github.com/cncf/toc/blob/main/DEFINITION.md)
引用: CNCF Landscape
- 48. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
ケーススタディ: レスポンス速度の遅延
1.どうやらレスポンス速度が遅くなっているらしいと監視から通知を受け取る
2.まずはMetricsからどんなアプリケーションのどのリクエストが遅延したか確認
foo Applicationの /bar が遅延していた
3.次はLogsでfoo Applicationの /bar でエラーログが出力されていないかどうかを確認
このリクエストはrequestid=bazでこのrequestidにエラーログはなかった
4.Tracesでrequestidを調べるとMySQLにクエリしていてその速度が遅延していた
5.MySQLに関するMetricsを確認すると同時間帯に接続数が増大していた
- 50. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
エラーハンドリング
指針
1. エラーをどう取り扱うかは呼び出し元に決めさせる
- Logs, Metricsはエラーを起点とすることが多い
- エラーハンドリングを正しくしていないと出力しづらい
2. 必要なコンテキストを付与する
- 51. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
func doSomething() *RetVal {
retval, err := maybeError()
if err != nil {
log.Printf("an error occurred: %+v", err)
}
return retval
}
エラーをとりあえずでロギングするだけ
再掲
- 52. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
func doSomething() *RetVal {
retval, _ := maybeError()
return retval
}
そもそもエラーをハンドリングをしない
再掲
- 53. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
fn doSomething() RetVal {
let result: Result<RetVal> = maybeError();
let retval = result.unwrap();
retval
}
Rustだったらunwrap()するだけとか
再掲
- 55. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
func doSomething() (*RetVal, error) {
retval, err := maybeError()
if err != nil {
return nil, xerrors.Errorf("failed to execute maybeError: %w", err)
}
return retval, nil
}
指針
1. エラーをどう取り扱うかは呼び出し元に決めさせる
2. 必要なコンテキストを付与する
①
② 独自のエラー型・例外でラップするなど
- 56. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
余談: 例外を乱用しない
- 例外でラップする例を挙げたが例外は乱用してはならない
- フロー制御として使うにはコストが高い
- 例外はあくまで”例外”であるため普段起こりうるフローでは利用しない
- Replacing Throwing Exceptions with Notification in Validations
- エラーハンドラ
- 57. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
Logs
指針
1. ユーザの個人情報など秘匿情報を記録しない
- 秘匿情報が記録されたログは閲覧者が制限される
- 可観測性が満たされない
2. どのイベントに紐づくログであるかを記録する
3. 分析のしやすいフォーマットにする
- 58. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
HTTPのURIに秘匿情報を含めない
- アクセスログにそのままpasswordが記録されてしまう
GET /secrets?password=foobar HTTP/1.1
Host: example.com
User-Agent: curl/7.58.0
Accept: */*
指針: ユーザの個人情報など秘匿情報を記録しない
- 59. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
外部からの入力をそのままログにしない
- パラメータとしてユーザの電話番号を受け取っていた場合ログに出力されてしまう
def validation(parameters)
parameters.each do |parameter|
if rules[parameter[:key]].valid?(parameter[:value])
STDERR.puts "#{parameter[:value]} is invalid"
end
end
end
指針: ユーザの個人情報など秘匿情報を記録しない
- 60. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
func main()
retval, err := doSomething()
if err != nil {
fmt.Fprintf(os.Stderr, "%+v", err)
}
}
func doSomething() (*RetVal, error) {...}
折角もらったエラーを適当に標準エラーする
再掲
- 61. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
HTTPサーバならRequestIDを含める
- 慣例的にHTTPではX-Request-Idというヘッダでリクエストを一意に識別する
- 最前段のHTTPサーバで発行して、各HTTPクライアントはそれを引き回す
- これをアクセスログやエラーログに含めておくとリクエストをまとめて検索できる
指針: どのイベントに紐づくログであるかを記録する
- 62. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
ログの出力元やStack Traceを含める
- ソースコードのどこで原因となるイベントが発生したかを調べられる必要がある
- Stack Traceはデータ量が大きい反面、情報量が多い
- ログを見た後、詳細な調査が必要なエラーでStack Traceを出力することが多い
- 前述の通り呼び出し元がエラーを受け取りStack Traceを出力する
指針: どのイベントに紐づくログであるかを記録する
- 63. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
必要に応じてJSONで出力する
- 主要なLogsのObservability PlatformはJSONをParseする機能を備えている
- HTTPサーバのアクセスログなどログを元に分析する場合はJSONが好ましい
- syslogやLTSVなどその他のフォーマットもあるがPlatformのサポートが厚いのはJSON
指針: 分析のしやすいフォーマットにする
- 64. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
余談: ログレベル(持論)
- ログレベルとは対象のログの深刻度を示すもの
- 一般に以下のようなログレベルが採用されることが多い
- DEBUG
- INFO
- WARN
- ERROR
- CRITICAL
- ログは前述の通りコストが高いため無視されるログは必要がない
- 不用意にログレベルを増やすと無視されるログを増やすことに繋がる
- 全てのエラーは等しく対応をすべきだとして以下のみから始めることが多い
- DEBUG
- INFO
- ERROR
- 65. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
Metrics
指針
1. USEメソッド
- Utilization
- Saturations
- Errors
2. REDメソッド
- Rate
- Errors
- Duration
- 66. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
USEメソッド
Worker Worker
Worker
Master
- Brendan Greggによって提唱されたMetrics収集の方法論
- あるリソースに対してUtilization, Saturations, Errorsを収集する
- 各リソースのMetricsの例示は The USE Method を参照
- ハードウェアリソースはエージェントが既に収集していることが多い
- エージェントの不足分やソフトウェアリソースをUSEメソッドに従って収集する
- 古典的なTCPサーバで考えた場合
- Utilization: ActiveなWorker数 / 総Worker数
- Saturations: Backlogに積まれたIn-QueueなConnection数
- Errors: ECONNREFUSEDが返った数
ECONNREFUSED
- 68. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
REDメソッド
- USEメソッドがリソース単位であることに対してREDメソッドはサービス単位
- REDメソッドの適用先はより限定的
- It is fair to say this method only works for request-driven services(The RED Method)
- あるサービスに対してRate, Errors, Durationを収集する
- microservicesの場合はデータストア含む依存するサービスに対して収集を考える
- 検索エンジンで考えた場合
- Rate: 検索エンジンに対するRequests per second
- Errors: レスポンスのエラー数
- Duration: レスポンスのレイテンシ
- 69. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
func doSomething() *RetVal {
start := time.Now()
retval := maybeSlow()
elapsed := time.Since(start)
log.Printf("maybeSlow took: %s", elapsed)
return retval
}
実行時間の計測をログで頑張る
再掲
- 70. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
func doSomething() *RetVal {
start := time.Now()
retval := maybeSlow()
elapsed := time.Since(start)
log.Printf("maybeSlow took: %s", elapsed)
return retval
}
実行時間の計測をログで頑張る
この手のものはMetricsとして管理してコストを安くしたい
再掲
- 71. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
出力の方法
- アプリケーションがOpenMetrics形式でMetricsを出力する
- Prometheusのクライアントライブラリを入れるなど
- アプリケーションのMetricsをエージェントが収集して出力する
- nginxの/nginx_statusをNGINX Prometheus Exporterが出力するなど
- 72. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
メソッドに従うことのメリット
- Metricsは収集した後に監視・可視化をするが、処理を共通化させやすい
- 抜け漏れなくMetricsを収集することができる
- これらはあくまで指針であるためアプリケーション固有のものは別途収集する
- Garbage Collectorの情報
- アプリケーションの状態
- ランタイム固有のグリーンスレッドの数
- 74. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
- CPUの使用率にPod間の偏りが存在する(Sticky Session下での過負荷など)
- cgroupで設定したlimits.memoryまでメモリを使い切れていない
- メトリクスの収集に失敗している
- NetworkのReceiveでパケットが落とされている
- NetworkのTransmitでパケットが落とされている
- Podがrestartを短時間に繰り返している
- Podがスケジュール待ちなど不正な状態が継続している
- PodのHealthCheckが失敗している
- 全てのPodのHealthCheckが失敗している
- PodがImageの取得に失敗するなどして待機状態になっている
- Podのメモリが不足し始めている
- Nodeのリソース不足などが原因でPodが大量に退避させれている
- Podがスケールアウトの限界に近付いている
- Podのエラーレートが増加している
- Podの特定のURIのエラーレートが増加している
and more...
- 77. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
余談: OpenTelemetry
- OpenTracingとOpenCensusが統合されて生まれたプロジェクト
- OpenTracingはTracesの標準化をしていたプロジェクト
- OpenCensusはTracesとMetricsの収集を補助するライブラリ
- OpenTracingはベンダー中立にPropagationするための仕様を策定していた
再掲
- 78. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
余談: OpenTelemetry
- OpenTracingとOpenCensusが統合されて生まれたプロジェクト
- OpenTracingはTracesの標準化をしていたプロジェクト
- OpenCensusはTracesとMetricsの収集を補助するライブラリ
- OpenTracingはベンダー中立にPropagationするための仕様を策定していた
再掲
OpenTelemetryもOpenCensusに引き続き各言語向けにライブラリを提供
- 80. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
OpenTelemetry SDKの機能
- OpenMetrics, OpenTracing(OpenTelemetry)に準拠したMetrics, Tracesの出力
- Prometheusのクライアントライブラリを別途入れる必要なし
- 各種クライアントの自動Metrics, Traces収集, 自動Propagation
- HTTPクライアント
- DBクライアント
- とりあえずOpenTelemetryを入れるだけで外部IOへのTracesは概ね完了
- IOを伴わない部分のTracesは後から考えれば十分
- 個別でSpanを埋める対応が必要となる
- Metricsは自身での追加のMetricsの収集が必要
- Log Data ModelでログのサポートもあるがSDK側は未実装が多い
- 将来はこれだけでLogsまで任せられる可能性も
- 81. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
HTTPサーバならRequestIDを含める
- 慣例的にHTTPではX-Request-Idというヘッダでリクエストを一意に識別する
- 最前段のHTTPサーバで発行して、各HTTPクライアントはそれを引き回す
- これをアクセスログやエラーログに含めておくとリクエストをまとめて検索できる
指針: どのイベントに紐づくログであるかを記録する
再掲
- 82. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
HTTPサーバならRequestIDを含める
- 慣例的にHTTPではX-Request-Idというヘッダでリクエストを一意に識別する
- 最前段のHTTPサーバで発行して、各HTTPクライアントはそれを引き回す
- これをアクセスログやエラーログに含めておくとリクエストをまとめて検索できる
指針: どのイベントに紐づくログであるかを記録する
再掲
OpenTelemetry導入後は代わりにtrace-idを利用することができる
- 83. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
まとめ
エラーハンドリング
1. エラーをどう取り扱うかは呼び出し元に決めさせる
2. 必要なコンテキストを付与する
Logs
1. ユーザの個人情報など秘匿情報を記録しない
2. どのイベントに紐づくログであるかを記録する
3. 分析のしやすいフォーマットにする
Metrics
1. USEメソッド
2. REDメソッド
Traces
1. とりあえずOpenTelemetryを使っておく
- 84. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
最後に
- 可観測性は実装に詳しくない人が状況を判断するために必要
- 仕事の現場では自身だけがメンテナンスし続けるわけにはいかない
- 指針に従ってPrimary Signalsを収集することで可観測性を向上させることができる
- それぞれは補完しあうためどれも欠けてはならない
可観測性やパフォーマンスのような非機能要件こそ腕の見せ所
可観測性に優れたアプリケーションを実装しましょう
CNCFでも可観測性(Observability)は大きなトピックで投資価値は十分あると思います
- 86. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
プロファイラ
- プログラム実行中の関数の呼び出し回数や実行時間などを計測するためのソフトウェア
- 実行時にオーバーヘッドを伴うものが多く開発時に利用することが一般的
- プログラムのボトルネックを特定できる
- 代表的なソフトウェア
- Linux perf
- Valgrind
- google/pprof
- Go
- V8’s sample-based profiler(google/pprof-nodejs)
- Node.js
引用: https://github.com/google/pprof
- 87. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
sample-based profiler
- 統計的なアプローチで精度と引き換えにオーバーヘッドを最小化するプロファイラ
- google/pprof
- V8’s sample-based profiler(google/pprof-nodejs)
- 定期的にコールスタックを読んで収集する
- Event profilerは精度が高い一方でイベント数が多くオーバーヘッドが大きい
- Linux perfは両方に対応している
- 88. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
継続的プロファイリング
- プロファイラはオーバーヘッドが大きく開発時しか利用できなかった
- sample-based profilerと言えどもオーバーヘッドはある
- それらを利用した継続的プロファイリングを提供するサービスが開始
- Cloud Profiler
- Datadog Continuous Profiler
- 継続的プロファイリングでは1分間に10秒間だけのようにプロファイリングする
- Tracesと比較して個別で対応することなく関数のボトルネックを探すことができる
- プロファイリングはネットワークを跨ぐことはできないためその点でTracesは有用
- 可観測性を更に向上させるSignalの一つとなりつつある
- 89. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
eBPF
- eBPFはLinuxカーネルにおけるJavaScriptのようなもの
- JavaScriptと同様にサンドボックスなVM上で稼働する
- JavaScriptがHTMLにすることと同様にLinuxカーネルのイベントに処理をアタッチする
- C言語でeBPFプログラムを記述するとそれがカーネル空間で安全に実行される
- ユーザ空間に渡す必要がないから高速
- 様々なイベントに対応していて可観測性に対して大きな力を持つ
- kprobe/kretprobe: カーネルの関数呼び出し・終了
- uprobe/uretprobe: バイナリの任意のオフセットの関数の呼び出し・終了
- 可観測性の他にセキュリティ分野でも注目されていてCNCFの熱いトピックの一つ
- アプリケーションに影響を与えることなく危険なsyscallの実行を監視したり
- 90. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
PyroScope
- オープンソースの継続的プロファイリングのプラットフォーム
- Cloud Profiler他と同様にgoogle/pprofなどを使いながら継続的プロファイリングをする
- eBPFのサポートもありより小さいオーバーヘッドでの実行が期待できる
- ※ 現時点ではbccに依存していていくつかの問題がある
- 興味があれば: BPF Portability and CO-RE
- 91. Copyright© LIFULL Co.,Ltd. All Rights Reserved.
LIFULLの内製PaaS KEEL
- コマンドを1発叩くだけで完璧なアプリケーション実行環境が手に入る内製PaaS
- デプロイ、セキュリティ、可観測性、信頼性、パフォーマンス
- コードジェネレータを中心とした開発者体験の提供
- Pull Requestを作成するとプレビューできる機能やLint, Content Trustまで備える
- https://www.lifull.blog/archive/category/Kubernetes
再掲