SDKの設定とリソース属性
目標
SDKを環境変数で設定し、リソース属性をセマンティック規約に合わせて確定し、KubernetesでインスタンスIDをDownward APIで注入します。最後に、スパン名のカーディナリティを検査するリンターを自分で作ります。
なぜ重要なのか
計装で最もやり直しがきかない決定が、リソース属性です。コードはいつでも直せますが、service.nameを変えた瞬間に、ダッシュボード、アラート、サービスグラフ、そして過去データとのつながりがすべて切れます。そのため、スパンを増やす前にこれを確定します。同じ理由で、名前の規約が重要です。deployment.environmentとdeployment.environment.nameは、人間の目には同じに見えますが、システムにとっては完全に別の2つの属性で、ダッシュボードの変数はそのうち片方しか読みません。スパン名も同様です。名前にIDが混ざると、バックエンドの集計ビューが丸ごと崩れますが、この事故はデプロイ直後ではなく、数週間後に「サービスグラフがおかしい」という形で発見されます。そのため、人の記憶ではなくCIで防ぐ必要があります。
ステップ
/root/otca-sdk/otel.envを作成し、OTEL_SERVICE_NAME=checkout-api、OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector.observability.svc:4317、OTEL_EXPORTER_OTLP_PROTOCOL=grpcを書いてください。1行に1つずつ、키=값の形式です(プレースホルダーはキーと値です)。- 同じファイルに
OTEL_RESOURCE_ATTRIBUTESを追加してください。値は、カンマでつないだservice.version=2.7.1、deployment.environment.name=prod、service.namespace=commerceです。古い名前のdeployment.environmentは使わないでください。 - 同じファイルに
OTEL_TRACES_SAMPLER=parentbased_traceidratio、OTEL_TRACES_SAMPLER_ARG=0.1、OTEL_PROPAGATORS=tracecontext,baggageを追加してください。 - 同じファイルに4つの上限を追加してください。
OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT=64、OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT=2048、OTEL_BSP_MAX_QUEUE_SIZE=4096、OTEL_BSP_MAX_EXPORT_BATCH_SIZE=512です。 /root/otca-sdk/deployment.yamlにDeploymentを書いてください。metadata.name: checkout-api、metadata.namespace: otca-sdkにします。最初のコンテナのenvに、POD_NAME(fieldRefmetadata.name)、POD_NAMESPACE(fieldRefmetadata.namespace)、OTEL_SERVICE_NAME=checkout-api、OTEL_EXPORTER_OTLP_ENDPOINT(4317を含む)、そしてOTEL_RESOURCE_ATTRIBUTESを入れてください。その値には、deployment.environment.name=prod、service.instance.id=$(POD_NAME)、k8s.namespace.name=$(POD_NAMESPACE)が含まれている必要があります。- ネームスペース
otca-sdkを作成し、ステップ5のマニフェストをクラスターに適用してください。 /root/otca-sdk/span-names.txtにスパン名を6行以上書いてください。そのうち最低4行はGET /...のようにHTTPメソッドで始まり、最低3行は:idプレースホルダーを含む必要があります。3桁以上連続する数字やUUIDは、1行も含まれていてはいけません。/root/otca-sdk/lint-span-names.shを作成してください。1つ目の引数で受け取ったファイルに、3桁以上連続する数字やUUID形式が含まれていたら、その行を出力して0以外のコードで終了し、なければ0で終了するようにします。
参考
- ステップ1–4は、すべて同じファイル
/root/otca-sdk/otel.envに書きます。exportプレフィックスは付けても付けなくてもかまいません。 - ステップ5の
OTEL_RESOURCE_ATTRIBUTESは、value: >-の折りたたみブロックで複数行に分けて書いてもかまいません。 - ステップ8の検証は、皆さんが作った
span-names.txt(通過する必要があります)と、採点側が作ったID・UUIDの一覧(ブロックする必要があります)の2種類で行われます。 - よくある間違い1: プロトコルは
grpcなのに、エンドポイントのポートを4318と書いてしまうことです。接続そのものが失敗します。 - よくある間違い2:
service.instance.idにPod名を文字列としてハードコードしてしまうことです。
サービス名とエンドポイント
/root/otca-sdk/otel.envを作成し、OTEL_SERVICE_NAME=checkout-api、OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector.observability.svc:4317、OTEL_EXPORTER_OTLP_PROTOCOL=grpcを書いてください。1行に1つずつ、키=값の形式です(プレースホルダーはキーと値です)。
SDKは環境変数だけで制御できます。そのため、計装の設定はコードではなくデプロイ用のマニフェストにあり、エンドポイントを変えるのにコードレビューは要りません。ポートとプロトコルは、必ず対応が合っている必要があります。
リソース属性を確定する
同じファイルにOTEL_RESOURCE_ATTRIBUTESを追加してください。値は、カンマでつないだservice.version=2.7.1、deployment.environment.name=prod、service.namespace=commerceです。古い名前のdeployment.environmentは使わないでください。
リソース属性は、このプロセスが出力するすべてのシグナルに付きます。複数ある場合はカンマでつなぎ、それぞれキー=値の形式です。環境属性の名前は最近の規約で変わったので、古い名前を使わないよう注意してください。
サンプラーとプロパゲーター
同じファイルにOTEL_TRACES_SAMPLER=parentbased_traceidratio、OTEL_TRACES_SAMPLER_ARG=0.1、OTEL_PROPAGATORS=tracecontext,baggageを追加してください。
サンプラー名にparentbasedが付いていてはじめて、親の判断に従います。付けないと、サービスごとに独立して確率判定を行い、トレースが途中で切れます。プロパゲーターはカンマで複数指定できます。
スパンのサイズとキューの上限
同じファイルに4つの上限を追加してください。OTEL_SPAN_ATTRIBUTE_COUNT_LIMIT=64、OTEL_ATTRIBUTE_VALUE_LENGTH_LIMIT=2048、OTEL_BSP_MAX_QUEUE_SIZE=4096、OTEL_BSP_MAX_EXPORT_BATCH_SIZE=512です。
属性の個数にはデフォルトの上限がありますが、値の長さにはありません。リクエスト本文がそのまま入ると、1つのスパンが数百KBになります。バッチスパンプロセッサーのキューサイズとバッチサイズも一緒に決めておきます。
Downward APIでインスタンス識別子を注入する
/root/otca-sdk/deployment.yamlにDeploymentを書いてください。metadata.name: checkout-api、metadata.namespace: otca-sdkにします。最初のコンテナのenvに、POD_NAME(fieldRef metadata.name)、POD_NAMESPACE(fieldRef metadata.namespace)、OTEL_SERVICE_NAME=checkout-api、OTEL_EXPORTER_OTLP_ENDPOINT(4317を含む)、そしてOTEL_RESOURCE_ATTRIBUTESを入れてください。その値には、deployment.environment.name=prod、service.instance.id=$(POD_NAME)、k8s.namespace.name=$(POD_NAMESPACE)が含まれている必要があります。
Pod名をハードコードすると、再起動のたびに誤った値が残ります。fieldRefでmetadata.nameとmetadata.namespaceを環境変数として受け取り、別の環境変数の中で括弧表記で参照すると、kubeletが置換してくれます。複数行の値は、折りたたみブロックで書くと読みやすくなります。
クラスターに適用する
ネームスペースotca-sdkを作成し、ステップ5のマニフェストをクラスターに適用してください。
先にネームスペースを作成してから、マニフェストを適用します。採点はクラスターに実際に入ったPodテンプレートを読むため、ファイルを直しただけで適用しないと合格しません。
低カーディナリティのスパン名リスト
/root/otca-sdk/span-names.txtにスパン名を6行以上書いてください。そのうち最低4行はGET /...のようにHTTPメソッドで始まり、最低3行は:idプレースホルダーを含む必要があります。3桁以上連続する数字やUUIDは、1行も含まれていてはいけません。
バックエンドはスパン名でグループ化して、レイテンシの統計とサービスグラフを作ります。名前に注文番号やUUIDが入ると、グループがリクエスト数だけできてしまいます。ルートはテンプレートで書き、具体的な値は属性で送ります。
スパン名リンター
/root/otca-sdk/lint-span-names.shを作成してください。1つ目の引数で受け取ったファイルに、3桁以上連続する数字やUUID形式が含まれていたら、その行を出力して0以外のコードで終了し、なければ0で終了するようにします。
スクリプトは、1つ目の引数として一覧ファイルを受け取ります。3桁以上連続する数字やUUID形式が含まれていたら、その行を出力して失敗で終了すればよいです。前のステップで作った一覧は、合格する必要があります。