Share
Embed
Transcript
53 slides
-
この講義のコンセプト ▶ 誰に n サイボウズの開発・運⽤・品質保証に関わるメンバー ▶ 何を学んでもらうか n オブザーバビリティの重要性や⽤途 n
ログ・メトリクス・トレース n 出⼒する際の決まり事や注意点 n 収集したデータの活⽤⽅法 2 -
オブザーバビリティの実現に必要な物 ▶ データ(テレメトリー)の収集 n 3つの柱:ログ、メトリクス、トレース n 第4の柱:プロファイル ▶ 収集したデータを活⽤するツール n
検索、分析、可視化ツール n アラート通知ツール 5 -
9 ビジネス ü ユーザーの利⽤状況を 分析し、ビジネス上の 意志決定に利⽤ ü 従量課⾦ 運⽤ ü
障害時のアラート ü 問題箇所の発⾒ ü オートスケーリング ü プログレッシブデリバ リーの実現 開発・テスト ü 性能測定 ü デバッグ ü ユーザーの利⽤状況に 応じた機能の改善 ü Flaky Testの発⾒ ü テスト時間の分析 オブザーバビリティの⽤途 -
オブザーバビリティを⽀える3本柱 ▶ ログ n 発⽣したイベントの詳細情報をタイムス タンプとともに記録 ▶ メトリクス n 統計情報を時系列で記録
▶ トレース n 呼び出された処理やかかった時間を記録 11 logs metrics traces -
ログ ▶ ログとは n プログラムが何かを実⾏したり、何かが発⽣したときのイベントを記 録するもの ▶ ログの種類 n アクセスログ
n アプリケーションログ・システムログ n 監査ログ 13 -
ログの集め⽅ 14 App Container Runtime App Agent Agent ファイルに ログを出⼒
ファイルに ログを出⼒ 標準出⼒/ 標準エラー出⼒ ストレージ に保存 ファイルからログを読む。 必要に応じてローテーション -
構造化ログの出⼒例 ▶ JSON形式 16 {"severity":"INFO", "logged_at":"2023-05-15T04:47:09.882Z", "caller":"zap/options.go:212", "message":"finished unary call
with code OK", "service":"sample", "utsname":"sample-57cfb5bf75-hbgjr", "grpc.start_time":"2023-05-15T04:47:09Z", "system":"grpc", "span.kind":"server", "grpc.service":"sample.v2beta2.Clusters", "grpc.method":"Join", "grpc.code":"OK", "grpc.time_ms":4.534} time="2023-05-15T04:50:27Z" level=info msg="Reconciliation completed" application=argocd/worker dedup_ms=0 dest-name= dest-namespace=worker dest-server="https://kubernetes.default.svc" diff_ms=49 fields.level=2 git_ms=16 health_ms=4 live_ms=9 settings_ms=0 sync_ms=0 time_ms=125 ▶ logfmt形式 -
ログ出⼒のライブラリ ▶ ファイルや標準出⼒・標準エラー出⼒に出⼒ ▶ 各⾔語で⽤意されているライブラリを使う n Java: logback n Go:
zapなど ▶ ログ出⼒はパフォーマンスやファイル書き込みなどで注意す べき点が多いので、⾃作は避けよう。 17 -
ログのレベル ログレベル ⽤途 CRITICAL 即座に終了するような致命的なエラーが発⽣した。 ERROR データベースやファイルに書き込めないなど、リクエストの処理またはプロセス⾃体が続 ⾏不可能になる問題が発⽣した。 スタックトレースとか、ソフトウェアが実⾏したアクションの結果など、問題の診断情報 を⼗分に出⼒する。
WARN 処理を打ち切る必要がなく、今のところ正常に続⾏できるが、将来的に問題につながり得 る事象が発⽣した。将来何か問題があったとき、真っ先に⾒返してほしいログ。 潜在的な問題。リソースがキャパシティに近いとか。何かアクションが必要な物。 INFO 正常な動作の軌跡。サーバが起動したとかリクエストが来たとか。 外界に影響を与える処理は info ログを出す。繰り返し処理の開始・終了時に info ログを 出す。 nice-to-haveなインフォメーション。”Service started”とか”Listening on port 5050”とか。 DEBUG 関数の出⼊りの記録や⽂字列解析の途中結果など、デバッグ⽤の情報。 productionでは通常無効化しておき、問題が起きたときに有効化する。 18 -
LogQLの例 23 {job=~"argocd/.*"} |= "Reconciliation completed" | logfmt | time_ms
> 1000 | line_format "{{.application}}: {{.time_ms}}" n {label="value"} でラベルによる絞り込み。=~ で正規表現指定 n |= で grep による絞り込み n logfmt や json で構造化ログをパースして絞り込み n line_format で指定した形式でログを表⽰ -
メトリクス ▶ メトリクスとは n アプリケーションやシステムの挙動に関する様々な統計情報 n ⼀定周期で統計情報を収集し、時系列データとして記録する ▶ メトリクスによって分かること n
現在のアプリケーションの状態 n 過去のある時点でアプリケーションがどのような状態だったか n ある期間内に状態がどのように変化したか 26 -
メトリクス収集の仕組み 27 App Push Gateway Agent OS Exporter App Service
Agent Agent ジョブの完了時など にメトリクスをpush サーバーやOSに関する 情報などを収集 ストレージ に保存 周期的(Necoでは30秒)にAPI を実⾏してメトリクスを収集 -
メトリクスのフォーマット ▶ アプリケーションに対してHTTPで"/metrics"のAPIを実⾏す るとテキスト形式のメトリクスを返す ▶ Prometheus形式がデファクトスタンダード n 数多くのOSSがこのフォーマットでメトリクスを出している n DatadogやNew
RelicなどのベンダーツールもPrometheus⽅式をサ ポートしている n 各⾔語向けのライブラリが⽤意されている 28 -
Prometheus形式のメトリクス例 29 # HELP http_server_api_requests_total A counter for requests to
the wrapped handler. # TYPE http_server_api_requests_total counter http_server_api_requests_total{code="200",method="get"} 157 http_server_api_requests_total{code="500",method="get"} 16 http_server_api_requests_total{code="200",method="post"} 21 http_server_api_requests_total{code="500",method="post"} 3 # HELP http_server_request_duration_seconds A histogram of latencies for requests. # TYPE http_server_request_duration_seconds histogram http_server_request_duration_seconds_bucket{handler="/api/v1/todo",method="get",le="0.25"} 99 http_server_request_duration_seconds_bucket{handler="/api/v1/todo",method="get",le="0.5"} 190 http_server_request_duration_seconds_bucket{handler="/api/v1/todo",method="get",le="1"} 343 http_server_request_duration_seconds_bucket{handler="/api/v1/todo",method="get",le="2.5"} 343 http_server_request_duration_seconds_bucket{handler="/api/v1/todo",method="get",le="5"} 343 http_server_request_duration_seconds_bucket{handler="/api/v1/todo",method="get",le="10"} 343 http_server_request_duration_seconds_bucket{handler="/api/v1/todo",method="get",le="+Inf"} 343 http_server_request_duration_seconds_sum{handler="/api/v1/todo",method="get"} 157.30460066099994 http_server_request_duration_seconds_count{handler="/api/v1/todo",method="get"} 343 ラベル 値 メトリクス名 -
メトリクスとして出⼒する情報の例 ▶ インフラ n コンテナごとのCPUやメモリ、ディスクの使⽤量 n Kubernetesのリソースに関する情報 ▶ アプリケーション n
リクエスト数、エラーの数、キャッシュヒット率、CPUやI/Oを利⽤ する処理にかかる時間、リモート呼び出しの処理の回数や時間など n そのほか有⽤な物はなんでも出しておくのがおすすめ 30 -
メトリクス名の付け⽅ ▶ 名前の付け⽅ n https://prometheus.io/docs/practices/naming/ 31 http_server_request_duration_seconds_bucket チーム名や製品名などメトリクスを分類するための プレフィックスを付ける(例: kintone_ap_,
mysql_) 必要に応じてサフィックスを付ける 総カウント数→total ヒストグラム→bucketなど 必要に応じて単位を付ける seconds, bytesなど メトリクスの内容を表す 名前を付ける -
ラベル設計の注意点 ▶ ⾼いカーディナリティのラベルを避ける。 n 分析時の性能劣化やデータ容量の肥⼤化を引き起こす可能性がある。 ▶ メトリクスにセンシティブな情報を含めない。 33 http_server_requests_total{method="GET", userid="0000830"}
HTTPのメソッドは、GET, POST, DELETEなど決まった ものしかないのでカーディナ リティが低い。 ユーザーIDは⾮常に種類が多く カーディナリティが⾼い。 またセンシティブなデータ。 -
メトリクスの値 ▶ メトリクスの値は単⼀の浮動⼩数点で表現する n 例:リクエスト数、エラー数、処理時間、データサイズ n 静的な情報を表現するときは値に1を指定する。 n ステータスを表現する場合は、1/0でtrue/falseを指定する。 34
kintone_info{version="23.2.0"} 1 kintone_status{status="healthy"} 1 kintone_status{status="unhealthy"} 0 -
35 Histogram 観測値の集計データ 例: HTTPリクエストサ イズや、リクエストの レイテンシー Gauge 現在の値を⽰す 例:
ディスクの使⽤量、 CPUの使⽤率 Counter 増加する値を⽰す 例: APIのリクエスト数 の累計、パケットの合 計受信サイズ メトリクスのタイプ -
メトリクス設計の⽅法論 ▶ RED(Request Rate, Request Error Rate, Request Duration) n
リクエストにおけるエラーの割合とかかった時間。 n サービスの利⽤ユーザーへの影響が分かりやすい指標。 ▶ USE(Utilization, Errors, Saturation) n リソースの利⽤率、エラー数、飽和状態の割合。 n データベースやメッセージキューなどに適した指標。 ▶ The Four Golden Signals(Latency, Traffic, Errors, Saturation) n ユーザー向け、⾮ユーザー向けのどちらにも使える指標。 36 -
メトリクスの分析 ▶ NecoではGrafana (VictoriaMetrics)を利⽤してメトリクスの 分析をおこなう。 ▶ 活⽤例 n 特定の条件にマッチしたときにアラートを発⾏ n
メトリクスを集計してパフォーマンスの分析 n SLI/SLOの計算に利⽤ 37 -
PromQLの例 38 # APIのリクエストにかかった時間の99パーセンタイルをverbごとに集計 histogram_quantile(0.99, sum by (verb, le) (
rate(apiserver_request_duration_seconds_bucket{}[5m]) ) ) n histogram_quantile で分位数(パーセンタイル)を計算 n sum で合計値を計算 n rate で秒間あたりの変化数を計算 -
トレースとは ▶ 呼び出しの記録 n いつ、どの処理が呼ばれ、どれくらいの時間がかかったかの記録 ▶ 分散トレースとは n 複数のコンポーネントにまたがったトレース 41
Nginx Kintone Slash MySQL -
トレースとスパン 42 Span Nginx Kintone Slash MySQL Span /api Span
/auth Span /items Span /auth Span SELECT Span SELECT Span INSERT time Trace スパン 作業や操作の単位 トレース 複数のスパンで構成 されるリクエストの 開始から終了までの単位 -
トレースデータの集め⽅ 43 App Collector App App ストレージ に保存 APIを実⾏してスパン 情報を書き込み
トレースIDが同⼀の複数のスパン を1つのトレースとして扱う -
トレースデータのフォーマット ▶ OpenTelemetry Protocol(OTLP) n https://opentelemetry.io/docs/specs/otel/protocol/otlp/ ▶ 通信にはHTTPまたはgRPCを利⽤。 ▶ 各⾔語向けのOpenTelemetryクライアントライブラリが⽤意
されている。 n https://opentelemetry.io/docs/instrumentation/ 44 -
スパンデータの例 45 { "resource_spans": [ { "resource": { "attributes": [
{ "key": "service.name", "value": { "stringValue": "my.service" } } ] }, "scope_spans": [ { "spans": [ { "traceId": "5B8EFFF798038103D269B633813FC60C", "spanId": "EEE19B7EC3C1B174", "parentSpanId": "EEE19B7EC3C1B173", "name": "I'm a server span", "startTimeUnixNano": 1544712660000000000, "endTimeUnixNano": 1544712661000000000, "kind": 2, "attributes": [ { "key": "my.span.attr", "value": { "stringValue": "some value" } サービス名などコンポーネント に固有の情報 トレースやスパンを識別するた めのID、開始時間と終了時間、 その他スパンに関する様々な情 報を含める -
Attributesに何を含めるべきか ▶ ResourceのAttributes n サービス名やnamespace, バージョン情報など n Conventions n https://opentelemetry.io/docs/specs/otel/resource/semantic_conventions/
▶ SpanのAttributes n HTTPのステータスコード、メソッド、URL、クライアントIPなど n Conventions n https://opentelemetry.io/docs/specs/otel/trace/semantic_conventions/ 46 -
コンテキストに含める情報 ▶ コンテキストはチームをまたがってやりとりするため、仕様 を定めておくことが⼤事。 ▶ W3C Trace Context n https://www.w3.org/TR/trace-context/
48 # {version}-{trace_id}-{span_id}-{trace_flags} traceparent: 00-80e1afed08e019fc1110464cfa66635c-7a085853722dc6d2-01 -
サンプリング ▶ すべてのトレース情報を記 録すると量が膨⼤になる。 ▶ ⾼レイテンシーやエラーが 発⽣したものと、正常なト レースからランダムにサン プリングしたものだけを記 録する。
49 https://opentelemetry.io/docs/concepts/sampling/