Lambdaトレーシングのサブセクション
セットアップ

前提条件
Observability ワークショップインスタンス
Observability ワークショップは、多くの場合、Splunk が提供する事前設定済みの Ubuntu EC2 インスタンス上で実施されます。
ワークショップのインストラクターから、割り当てられたワークショップインスタンスの認証情報が提供されます。
インスタンスには以下の環境変数が既に設定されているはずです:
- ACCESS_TOKEN
- REALM
- これらはワークショップ用の Splunk Observability Cloud の Access Token と Realm です。
- これらは OpenTelemetry Collector によって、データを正しい Splunk Observability Cloud 組織に転送するために使用されます。
また、Multipass を使用してローカルの Observability ワークショップインスタンスをデプロイすることもできます。
AWS Command Line Interface (awscli)
AWS Command Line Interface、またはawscli
は、AWS リソースと対話するために使用される API です。このワークショップでは、特定のスクリプトがデプロイするリソースと対話するために使用されます。
Splunk が提供するワークショップインスタンスには、既に awscli がインストールされているはずです。
Terraform は、リソースを構成ファイルで定義することで、デプロイ、管理、破棄するための Infrastructure as Code(IaC)プラットフォームです。Terraform は HCL を使用してこれらのリソースを定義し、さまざまなプラットフォームやテクノロジのための複数のプロバイダーをサポートしています。
このワークショップでは、コマンドラインで Terraform を使用して、以下のリソースをデプロイします:
- AWS API Gateway
- Lambda 関数
- Kinesis Stream
- CloudWatch ロググループ
- S3 バケット
Splunk が提供するワークショップインスタンスには、既に terraform がインストールされているはずです。
ワークショップディレクトリ (o11y-lambda-workshop)
ワークショップディレクトリ o11y-lambda-workshop
は、今日使用する例の Lambda ベースのアプリケーションの自動計装と手動計装の両方を完了するための、すべての設定ファイルとスクリプトを含むリポジトリです。
git clone https://github.com/gkono-splunk/o11y-lambda-workshop.git
AWS
AWS の CLI では、サービスによってデプロイされたリソースにアクセスし管理するための認証情報が必要です。このワークショップでは、Terraform と Python スクリプトの両方がタスクを実行するためにこれらの変数を必要とします。
Terraform では、機密情報や動的データを.tf 設定ファイルにハードコーディングさせない、またはそれらの値をリソース定義全体で再利用できるようにするため、変数の受け渡しをサポートしています。
このワークショップでは、OpenTelemetry Lambda layer の適切な値で Lambda 関数をデプロイするため、Splunk Observability Cloud の取り込み値のため、そして環境とリソースを独自で即座に認識できるようにするための変数を Terraform で必要とします。
Terraform 変数(variable)は以下の方法で定義されます:
- 変数を main.tf ファイルまたは variables.tf に定義する
- 以下のいずれかの方法で変数の値を設定する:
- ホストレベルで環境変数を設定し、その定義と同じ変数名を使用して、接頭辞として TF_VAR をつける
- terraform.tfvars ファイルに変数の値を設定する
- terraform apply 実行時に引数として値を渡す
このワークショップでは、variables.tf と terraform.tfvars ファイルの組み合わせを使用して変数を設定します。
vi または nano のいずれかを使用して、auto または manual ディレクトリにある terraform.tfvars ファイルを開きます
vi ~/o11y-lambda-workshop/auto/terraform.tfvars
変数に値を設定します。CHANGEME プレースホルダーをインストラクターから提供された値に置き換えてください。
o11y_access_token = "CHANGEME"
o11y_realm = "CHANGEME"
otel_lambda_layer = ["CHANGEME"]
prefix = "CHANGEME"
- 引用符(")や括弧 ( [ ] ) はそのまま残し、プレースホルダー
CHANGEME
のみを変更してください。 - prefix は、他の参加者のリソースと区別するため、任意の文字列で設定する固有の識別子です。氏名やメールアドレスのエイリアスを使用することをお勧めします。
- prefix には小文字のみを使用してください。S3 のような特定の AWS リソースでは、大文字を使用するとエラーが発生します。
ファイルを保存してエディタを終了します。
最後に、編集した terraform.tfvars ファイルを他のディレクトリにコピーします。
cp ~/o11y-lambda-workshop/auto/terraform.tfvars ~/o11y-lambda-workshop/manual
- これは、自動計装と手動計装の両方の部分で同じ値を使用するためです
ファイル権限
他のすべてのファイルはそのままでよいですが、auto
とmanual
の両方にあるsend_message.pyスクリプトは、ワークショップの一部として実行する必要があります。そのため、期待通りに実行するには、適切な権限が必要です。以下の手順に従って設定してください。
これで前提条件が整いましたので、ワークショップを始めることができます!
自動計装
ワークショップの最初の部分では、OpenTelemetry による自動計装がどのようにして OpenTelemetry Collector に関数がどの言語で書かれているかを自動検出させ、それらの関数のトレースの取得を開始させるかを示します。
自動計装ワークショップディレクトリとコンテンツ
まず、o11y-lambda-workshop/auto
ディレクトリとそのファイルの一部を見てみましょう。ここにはワークショップの自動計装部分のすべてのコンテンツがあります。
auto
ディレクトリ
main.tf
ファイル
ワークショップの質問
- このテンプレートによってどの AWS リソースが作成されているか特定できますか?
- OpenTelemetry 計装がどこでセットアップされているか特定できますか?
- ヒント: Lambda 関数の定義を調べてください
- 以前に設定した環境変数によってどの計装情報が提供されているか判断できますか?
各 Lambda 関数の環境変数が設定されているセクションが見つかるはずです。
environment {
variables = {
SPLUNK_ACCESS_TOKEN = var.o11y_access_token
SPLUNK_REALM = var.o11y_realm
OTEL_SERVICE_NAME = "producer-lambda"
OTEL_RESOURCE_ATTRIBUTES = "deployment.environment=${var.prefix}-lambda-shop"
AWS_LAMBDA_EXEC_WRAPPER = "/opt/nodejs-otel-handler"
KINESIS_STREAM = aws_kinesis_stream.lambda_streamer.name
}
}
これらの環境変数を使用することで、いくつかの方法で自動計装を構成しています:
環境変数を設定して、データのエクスポート先となる Splunk Observability Cloud 組織を OpenTelemetry collector に伝えています。
SPLUNK_ACCESS_TOKEN = var.o11y_access_token
SPLUNK_ACCESS_TOKEN = var.o11y_realm
また、OpenTelemetry が関数/サービスを識別し、それが属する環境/アプリケーションを認識するのに役立つ変数も設定しています。
OTEL_SERVICE_NAME = "producer-lambda" # consumer関数の場合はconsumer-lambda
OTEL_RESOURCE_ATTRIBUTES = "deployment.environment=${var.prefix}-lambda-shop"
コード言語に基づいて、関数のハンドラーに自動的にトレースデータを取得するために適用する必要があるラッパーを OpenTelemetry に知らせる環境変数を設定しています。
AWS_LAMBDA_EXEC_WRAPPER - "/opt/nodejs-otel-handler"
producer-lambda
関数の場合、レコードを配置する Kinesis ストリームを関数に知らせるための環境変数を設定しています。
KINESIS_STREAM = aws_kinesis_stream.lambda_streamer.name
これらの値は、「前提条件」セクションで設定した環境変数、および、この Terraform 構成ファイルの一部としてデプロイされるリソースから取得されます。
また、各関数に Splunk OpenTelemetry Lambda layer を設定する引数も確認できるはずです
layers = var.otel_lambda_layer
OpenTelemetry Lambda layer は、Lambda 関数の呼び出し時に計測データを収集、処理、およびエクスポートするために必要なライブラリと依存関係を含むパッケージです。
すべての OpenTelemetry サポート言語のライブラリと依存関係を持つ一般的な OTel Lambda layer がありますが、関数をさらに軽量化するための言語固有の Lambda layer も存在します。
- 各 AWS リージョンの関連する Splunk OpenTelemetry Lambda layer ARN(Amazon Resource Name)と最新バージョンはこちらで確認できます
producer.mjs
ファイル
次に、producer-lambda
関数のコードを見てみましょう:
Lambda 関数のデプロイとトレースデータの生成
auto
ディレクトリの内容に慣れたところで、ワークショップ用のリソースをデプロイし、Lambda 関数からトレースデータを生成していきます。
main.tf
ファイルで定義されたリソースをデプロイするには、まず Terraform がそのファイルと同じフォルダで初期化されていることを確認する必要があります。
Lambda 関数とその他の AWS リソースをデプロイする
このディレクトリで Terraform を初期化したら、リソースのデプロイに進むことができます。
producer-lambda
URL (base_url
) にトラフィックを送信する
デプロイした Lambda 関数からトレースを取得し始めるには、トラフィックを生成する必要があります。producer-lambda
関数のエンドポイントにメッセージを送信し、それを Kinesis ストリームにレコードとして配置し、その後consumer-lambda
関数によってストリームから取得されるようにします。
send_message.py
スクリプトは、コマンドラインで入力を受け取り、JSON ディクショナリに追加し、while ループの一部として producer-lambda
関数のエンドポイントに繰り返し送信する Python スクリプトです。
重要
この場合は、ワークショップ進行役の一人に支援を求めてください。
Lambda 関数のログを表示する
次に、Lambda 関数のログを確認しましょう。
ログを注意深く調べてください。
ワークショップの質問
- OpenTelemetry が読み込まれているのが見えますか?
splunk-extension-wrapper
のある行に注目してください- splunk-extension-wrapperが読み込まれているのを見るために
head -n 50 producer.logs
またはhead -n 50 consumer.logs
の実行を検討してください。
Splunk APM、Lambda関数およびトレース
Lambda 関数は相当量のトレースデータを生成しているはずで、それを確認する必要があります。Lambda 関数のリソース定義で構成された環境変数と OpenTelemetry Lambda layer の組み合わせにより、Splunk APM で関数とトレースを表示する準備が整いました。
Splunk APM 概要で環境名を確認する
まず、Splunk APM が受信しているトレースデータからEnvironment
を認識していることを確認しましょう。これはmain.tf
の Lambda 関数定義で設定したOTEL_RESOURCE_ATTRIBUTES
変数の一部として設定したdeployment.name
です。これは先ほど実行したterraform apply
コマンドの出力の 1 つでもありました。
Splunk Observability Cloud で:
メモ
トレースが Splunk APM に表示されるまで数分かかる場合があります。環境のリストにあなたの環境名が表示されるまで、ブラウザの更新ボタンを押してみてください

環境のサービスマップを表示する
Environment ドロップダウンから環境名を選択したら、Lambda 関数のサービスマップを確認できます。
- APM 概要ページの右側にある
Service Map
ボタンをクリックします。これによりサービスマップビューに移動します。

producer-lambda
関数とそのレコードを配置するために Kinesis ストリームに対して行っている呼び出しが表示されるはずです。

ワークショップの質問
あなたのconsumer-lambda
関数はどうなっていますか?
Lambda 関数からのトレースを調査する
Traces
ボタンをクリックしてトレースアナライザーを表示します。

このページでは、producer-lambda
関数の OpenTelemetry Lambda layer から取り込まれたトレースを確認できます。

- リストからハイパーリンクされた
Trace ID
をクリックして、調査するトレースを選択します。

producer-lambda
関数が Kinesis ストリームにレコードを配置しているのが確認できます。しかし、consumer-lambda
関数のアクションが見当たりません!
これはトレースコンテキストが伝播されていないためです。このワークショップの時点では、Kinesis サービスはトレースコンテキスト伝播をすぐには対応していません。分散トレースは Kinesis サービスで止まっており、そのコンテキストがストリームを通じて自動的に伝播されないため、それ以上先を見ることができません。
少なくとも、今はまだ…
次のセクションでこの問題にどう対処するか見ていきましょう。しかしその前に、後片付けをしましょう!
クリーンアップ
この自動計装演習の一部としてデプロイしたリソースはクリーンアップする必要があります。同様に、producer-lambda
エンドポイントに対してトラフィックを生成していたスクリプトも、まだ実行中であれば停止する必要があります。以下の手順に従ってクリーンアップを行ってください。
send_message
の停止
全ての AWS リソースを破棄する
Terraform は個々のリソースの状態をデプロイメントとして管理するのに優れています。定義に変更があっても、デプロイされたリソースを更新することもできます。しかし、一からやり直すために、リソースを破棄し、このワークショップの手動計装部分の一部として再デプロイします。
以下の手順に従ってリソースを破棄してください:
このプロセスにより、私たちの活動の結果として作成されたファイルとディレクトリは残ります。それらについては心配する必要はありません。
手動計装
ワークショップの第 2 部では、OpenTelemetry による手動計装が計測データ収集を強化する方法を実演することに焦点を当てます。より具体的には、今回のケースでは、producer-lambda
関数からconsumer-lambda
関数にトレースコンテキストデータを伝播させることができるようになります。これにより、現在は自動コンテキスト伝播をサポートしていない Kinesis ストリームを介しても、2 つの関数間の関係を見ることができるようになります。
手動計装ワークショップディレクトリとコンテンツ
再度、作業ディレクトリとそのファイルの一部を確認することから始めます。今回は o11y-lambda-workshop/manual
ディレクトリです。ここにはワークショップの手動計装部分のすべてのコンテンツがあります。
manual
ディレクトリ
ワークショップの質問
このディレクトリと最初に始めた auto ディレクトリに何か違いがありますか?
auto
と manual
のファイルを比較する
見た目が同じように見えるこれらのファイルが実際に同じかどうか確認しましょう。
auto
と manual
ディレクトリの main.tf
ファイルを比較します:
diff ~/o11y-lambda-workshop/auto/main.tf ~/o11y-lambda-workshop/manual/main.tf
- 違いはありません!(違いがあるはずはありません。もし違いがあれば、ワークショップ進行役に支援を求めてください)
次に、producer.mjs
ファイルを比較してみましょう:
diff ~/o11y-lambda-workshop/auto/handler/producer.mjs ~/o11y-lambda-workshop/manual/handler/producer.mjs
ファイル全体を表示してその内容を調べたい場合は以下を実行します:
cat ~/o11y-lambda-workshop/handler/producer.mjs
- 必要な手動計装タスクを処理するために、いくつかの OpenTelemetry オブジェクトを関数に直接インポートしていることに注目してください。
import { context, propagation, trace } from "@opentelemetry/api";
最後に、consumer.mjs
ファイルを比較します:
diff ~/o11y-lambda-workshop/auto/handler/consumer.mjs ~/o11y-lambda-workshop/manual/handler/consumer.mjs
プロデューサー関数からのトレースコンテキスト伝播
以下のコードはプロデューサー関数内で次のステップを実行します:
- このトレース用のトレーサーを取得する
- コンテキストキャリアオブジェクトを初期化する
- アクティブスパンのコンテキストをキャリアオブジェクトに注入する
- Kinesis ストリームに配置しようとしているレコードを修正し、アクティブスパンのコンテキストをコンシューマーに運ぶキャリアを含める
...
import { context, propagation, trace, } from "@opentelemetry/api";
...
const tracer = trace.getTracer('lambda-app');
...
return tracer.startActiveSpan('put-record', async(span) => {
let carrier = {};
propagation.inject(context.active(), carrier);
const eventBody = Buffer.from(event.body, 'base64').toString();
const data = "{\"tracecontext\": " + JSON.stringify(carrier) + ", \"record\": " + eventBody + "}";
console.log(
`Record with Trace Context added:
${data}`
);
try {
await kinesis.send(
new PutRecordCommand({
StreamName: streamName,
PartitionKey: "1234",
Data: data,
}),
message = `Message placed in the Event Stream: ${streamName}`
)
...
span.end();
コンシューマー関数でのトレースコンテキスト抽出
以下のコードはコンシューマー関数内で次のステップを実行します:
producer-lambda
から取得したコンテキストをキャリアオブジェクトに抽出する- 現在のコンテキストからトレーサーを抽出する
- 抽出したコンテキスト内でトレーサーを使用して新しいスパンを開始する
- ボーナス:メッセージからの値を含むカスタム属性など、追加の属性をスパンに追加する!
- 完了したら、スパンを終了する
import { propagation, trace, ROOT_CONTEXT } from "@opentelemetry/api";
...
const carrier = JSON.parse( message ).tracecontext;
const parentContext = propagation.extract(ROOT_CONTEXT, carrier);
const tracer = trace.getTracer(process.env.OTEL_SERVICE_NAME);
const span = tracer.startSpan("Kinesis.getRecord", undefined, parentContext);
span.setAttribute("span.kind", "server");
const body = JSON.parse( message ).record;
if (body.name) {
span.setAttribute("custom.tag.name", body.name);
}
if (body.superpower) {
span.setAttribute("custom.tag.superpower", body.superpower);
}
...
span.end();
これでどのような違いが生まれるか見てみましょう!
Lambda関数のデプロイとトレースデータの生成
トレースデータを収集したい関数やサービスに手動計装を適用する方法がわかったので、Lambda 関数を再度デプロイして、producer-lambda
エンドポイントに対するトラフィックを生成していきましょう。
新しいディレクトリにいるので、ここでもう一度 Terraform を初期化する必要があります。
manual
ディレクトリにいることを確認します:
- 予想される出力は ~/o11y-lambda-workshop/manual です
manual
ディレクトリにいない場合は、次のコマンドを実行します:
cd ~/o11y-lambda-workshop/manual
次のコマンドを実行して、このディレクトリで Terraform を初期化します:
Lambda 関数とその他の AWS リソースをデプロイする
それでは、これらのリソースを再度デプロイしましょう!
見ての通り、base_url の最初の部分とログループ ARN 以外は、このワークショップの自動計装部分をこの同じ時点まで実行したときと出力は概ね同じはずです。
producer-lambda
エンドポイント (base_url) にトラフィックを送信する
もう一度、name
と superpower
をメッセージとしてエンドポイントに送信します。これはトレースコンテキストとともに、Kinesis ストリーム内のレコードに追加されます。
manual
ディレクトリにいることを確認します:
- 予想される出力は ~/o11y-lambda-workshop/manual です
manual
ディレクトリにいない場合は、次のコマンドを実行します:
cd ~/o11y-lambda-workshop/manual
send_message.py
スクリプトをバックグラウンドプロセスとして実行します:
nohup ./send_message.py --name CHANGEME --superpower CHANGEME &
次に、response.logs ファイルの内容を確認して、producer-lambdaエンドポイントへの呼び出しが成功しているか確認します:
重要
これが発生した場合は、ワークショップ進行役の一人に支援を求めてください。
Lambda 関数のログの確認
ログがどのようになっているか見てみましょう。
ログを注意深く調べてください。
ワークショップの質問
違いに気づきましたか?
consumer-lambda
ログからのトレース ID のコピー
今回は、consumer-lambda のロググループが、我々が伝播したtracecontext
とともに、メッセージをrecord
としてログに記録しているのが確認できます。
トレース ID をコピーするには:
Kinesis Message
ログの 1 つを見てみましょう。その中にはdata
ディクショナリがあります- ネストされた
tracecontext
ディクショナリを見るために、data
をより詳しく見てください tracecontext
ディクショナリ内には、traceparent
というキーと値のペアがありますtraceparent
キーと値のペアには、私たちが探しているトレース ID が含まれています-
で区切られた 4 つの値のグループがあります。トレース ID は 2 番目の文字グループです
- トレース ID をコピーして保存してください。 このワークショップの後のステップで必要になります

Splunk APM、Lambda関数とトレース、再び!
ログの外部でコンテキスト伝播の結果を確認するために、もう一度Splunk APM UIを参照します。
Splunk APM サービスマップで Lambda 関数を表示する
もう一度 APM で環境のサービスマップを確認してみましょう。
Splunk Observability Cloud で:
> 注意:トレースが Splunk APM に表示されるまで数分かかる場合があります。環境のリストにあなたの環境名が表示されるまで、ブラウザの更新ボタンを押してみてください
ワークショップの質問
- 今回は、伝播されたコンテキストによってリンクされた
producer-lambda
とconsumer-lambda
関数が見えるはずです!

トレース ID で Lambda トレースを調査する
次に、環境に関連するトレースをもう一度確認します。
- コンシューマー関数のログからコピーしたトレース ID を、Traces 下の
View Trace ID
検索ボックスに貼り付け、Go
をクリックします

メモ
トレース ID は、私たちが伝播したトレースコンテキストの一部でした。
最も一般的な 2 つの伝播規格について読むことができます:
- W3C
- B3
ワークショップの質問
私たちはどちらを使用していますか?
- 私たちの NodeJS 関数をサポートする Splunk Distribution of Opentelemetry JS は、デフォルトで
W3C
標準を使用しています
ワークショップの質問
ボーナス質問:W3C ヘッダーと B3 ヘッダーを混在させるとどうなりますか?

consumer-lambda
スパンをクリックしてください。
ワークショップの質問
あなたのメッセージからの属性を見つけることができますか?

クリーンアップ
いよいよワークショップの最後に来ました。後片付けをしましょう!
send_message
の停止
すべての AWS リソースを破棄する
Terraform は個々のリソースの状態をデプロイメントとして管理するのに優れています。定義に変更があっても、デプロイされたリソースを更新することもできます。しかし、一からやり直すために、リソースを破棄し、このワークショップの手動計装部分の一部として再デプロイします。
以下の手順に従ってリソースを破棄してください:
結論
Lambda Tracing ワークショップを終えたことをおめでとうございます!自動計装を手動のステップで補完して、producer-lambda
関数のコンテキストを Kinesis ストリーム内のレコードを介してconsumer-lambda
関数に送信する方法を見てきました。これにより、期待される分散トレースを構築し、Splunk APM で両方の関数間の関係をコンテキスト化することができました。

これで、2 つの異なる関数を手動でリンクしてトレースを構築することができます。これは、自動計装や第三者のシステムがコンテキスト伝播を標準でサポートしていない場合や、より関連性の高いトレース分析のためにカスタム属性をトレースに追加したい場合に役立ちます。
OpenTelemetry、Docker、K8sを実践で学ぶのサブセクション
EC2インスタンスへの接続
5 minutes
EC2 インスタンスへ接続
各参加者のために、AWS/EC2 に Ubuntu Linux インスタンスを用意しました。
インストラクターから提供された IP アドレスとパスワードを使用して、以下のいずれかの方法で EC2 インスタンスに接続してください:
- Mac OS / Linux
- Windows 10+
- 以前のバージョンの Windows
OpenTelemetryコレクターのデプロイ
10 minutes
OpenTelemetry コレクターのアンインストール
EC2 インスタンスには、すでに Splunk Distribution の OpenTelemetry コレクターの古いバージョンが
インストールされている可能性があります。先に進む前に、次のコマンドを使用してアンインストールしましょう:
curl -sSL https://dl.signalfx.com/splunk-otel-collector.sh > /tmp/splunk-otel-collector.sh;
sudo sh /tmp/splunk-otel-collector.sh --uninstall
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following packages will be REMOVED:
splunk-otel-collector*
0 upgraded, 0 newly installed, 1 to remove and 167 not upgraded.
After this operation, 766 MB disk space will be freed.
(Reading database ... 157441 files and directories currently installed.)
Removing splunk-otel-collector (0.92.0) ...
(Reading database ... 147373 files and directories currently installed.)
Purging configuration files for splunk-otel-collector (0.92.0) ...
Scanning processes...
Scanning candidates...
Scanning linux images...
Running kernel seems to be up-to-date.
Restarting services...
systemctl restart fail2ban.service falcon-sensor.service
Service restarts being deferred:
systemctl restart networkd-dispatcher.service
systemctl restart unattended-upgrades.service
No containers need to be restarted.
No user sessions are running outdated binaries.
No VM guests are running outdated hypervisor (qemu) binaries on this host.
Successfully removed the splunk-otel-collector package
OpenTelemetry collector のデプロイ
Linux EC2 インスタンスに、Splunk Distribution の OpenTelemetry コレクターの最新バージョンをデプロイしましょう。
これはcurl
を使用してコレクターバイナリをダウンロードし、特定の引数を指定して実行することで可能です。
これらの引数は、データを送信する realm、使用するアクセストークン、
およびデータを送信するデプロイメント環境をコレクターに指示します。
Splunk Observability Cloud におけるデプロイメント環境とは、システムまたはアプリケーションの個別のデプロイメントであり、同じアプリケーションの他のデプロイメントの設定と重複しない設定を行うことができます。
curl -sSL https://dl.signalfx.com/splunk-otel-collector.sh > /tmp/splunk-otel-collector.sh; \
sudo sh /tmp/splunk-otel-collector.sh \
--realm $REALM \
--mode agent \
--without-instrumentation \
--deployment-environment otel-$INSTANCE \
-- $ACCESS_TOKEN
Splunk OpenTelemetry Collector Version: latest
Memory Size in MIB: 512
Realm: us1
Ingest Endpoint: https://ingest.us1.signalfx.com
API Endpoint: https://api.us1.signalfx.com
HEC Endpoint: https://ingest.us1.signalfx.com/v1/log
etc.
詳細については、インストーラースクリプトを使用した Linux 用コレクターのインストール
を参照してください。
コレクターが実行中であることを確認
インスタンスでコレクターが正常に実行されていることを確認しましょう。
ステータスコマンドを終了するには、Ctrl + C を押します。
sudo systemctl status splunk-otel-collector
● splunk-otel-collector.service - Splunk OpenTelemetry Collector
Loaded: loaded (/lib/systemd/system/splunk-otel-collector.service; enabled; vendor preset: enabled)
Drop-In: /etc/systemd/system/splunk-otel-collector.service.d
└─service-owner.conf
Active: active (running) since Fri 2024-12-20 00:13:14 UTC; 45s ago
Main PID: 14465 (otelcol)
Tasks: 9 (limit: 19170)
Memory: 117.4M
CPU: 681ms
CGroup: /system.slice/splunk-otel-collector.service
└─14465 /usr/bin/otelcol
コレクターログの確認方法
journalctl
を使用してコレクターログを表示できます:
ログの監視を終了するには、Ctrl + C を押します。
sudo journalctl -u splunk-otel-collector -f -n 100
Dec 20 00:13:14 derek-1 systemd[1]: Started Splunk OpenTelemetry Collector.
Dec 20 00:13:14 derek-1 otelcol[14465]: 2024/12/20 00:13:14 settings.go:483: Set config to /etc/otel/collector/agent_config.yaml
Dec 20 00:13:14 derek-1 otelcol[14465]: 2024/12/20 00:13:14 settings.go:539: Set memory limit to 460 MiB
Dec 20 00:13:14 derek-1 otelcol[14465]: 2024/12/20 00:13:14 settings.go:524: Set soft memory limit set to 460 MiB
Dec 20 00:13:14 derek-1 otelcol[14465]: 2024/12/20 00:13:14 settings.go:373: Set garbage collection target percentage (GOGC) to 400
Dec 20 00:13:14 derek-1 otelcol[14465]: 2024/12/20 00:13:14 settings.go:414: set "SPLUNK_LISTEN_INTERFACE" to "127.0.0.1"
etc.
コレクターの設定
このコレクターが使用している設定はどこで見つけられるでしょうか?
その設定は/etc/otel/collector
ディレクトリにあります。コレクターをagent
モードで
インストールしたため、コレクター設定はagent_config.yaml
ファイルにあります。
.NETアプリケーションのデプロイ
10 minutes
前提条件
アプリケーションをデプロイする前に、インスタンスに.NET 8 SDK をインストールする必要があります。
sudo apt-get update && \
sudo apt-get install -y dotnet-sdk-8.0
Hit:1 http://us-west-1.ec2.archive.ubuntu.com/ubuntu jammy InRelease
Hit:2 http://us-west-1.ec2.archive.ubuntu.com/ubuntu jammy-updates InRelease
Hit:3 http://us-west-1.ec2.archive.ubuntu.com/ubuntu jammy-backports InRelease
Hit:4 http://security.ubuntu.com/ubuntu jammy-security InRelease
Ign:5 https://splunk.jfrog.io/splunk/otel-collector-deb release InRelease
Hit:6 https://splunk.jfrog.io/splunk/otel-collector-deb release Release
Reading package lists... Done
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
aspnetcore-runtime-8.0 aspnetcore-targeting-pack-8.0 dotnet-apphost-pack-8.0 dotnet-host-8.0 dotnet-hostfxr-8.0 dotnet-runtime-8.0 dotnet-targeting-pack-8.0 dotnet-templates-8.0 liblttng-ust-common1
liblttng-ust-ctl5 liblttng-ust1 netstandard-targeting-pack-2.1-8.0
The following NEW packages will be installed:
aspnetcore-runtime-8.0 aspnetcore-targeting-pack-8.0 dotnet-apphost-pack-8.0 dotnet-host-8.0 dotnet-hostfxr-8.0 dotnet-runtime-8.0 dotnet-sdk-8.0 dotnet-targeting-pack-8.0 dotnet-templates-8.0
liblttng-ust-common1 liblttng-ust-ctl5 liblttng-ust1 netstandard-targeting-pack-2.1-8.0
0 upgraded, 13 newly installed, 0 to remove and 0 not upgraded.
Need to get 138 MB of archives.
After this operation, 495 MB of additional disk space will be used.
etc.
詳細については、Ubuntu に.NET SDK または.NET Runtime をインストールする
を参照してください。
.NET アプリケーションの確認
ターミナルで、アプリケーションディレクトリに移動します:
cd ~/workshop/docker-k8s-otel/helloworld
このワークショップでは、シンプルな「Hello World」.NET アプリケーションを使用します。主要なロジックは
HelloWorldController.cs ファイルにあります:
public class HelloWorldController : ControllerBase
{
private ILogger<HelloWorldController> logger;
public HelloWorldController(ILogger<HelloWorldController> logger)
{
this.logger = logger;
}
[HttpGet("/hello/{name?}")]
public string Hello(string name)
{
if (string.IsNullOrEmpty(name))
{
logger.LogInformation("/hello endpoint invoked anonymously");
return "Hello, World!";
}
else
{
logger.LogInformation("/hello endpoint invoked by {name}", name);
return String.Format("Hello, {0}!", name);
}
}
}
.NET アプリケーションのビルドと実行
以下のコマンドを使用してアプリケーションをビルドできます:
MSBuild version 17.8.5+b5265ef37 for .NET
Determining projects to restore...
All projects are up-to-date for restore.
helloworld -> /home/splunk/workshop/docker-k8s-otel/helloworld/bin/Debug/net8.0/helloworld.dll
Build succeeded.
0 Warning(s)
0 Error(s)
Time Elapsed 00:00:02.04
ビルドが成功したら、次のように実行できます:
Building...
info: Microsoft.Hosting.Lifetime[14]
Now listening on: http://localhost:8080
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: /home/splunk/workshop/docker-k8s-otel/helloworld
実行したら、Ubuntu インスタンスへの SSH 接続を 2 つ目のターミナルで開き、curl を使用してアプリケーションにアクセスします:
curl http://localhost:8080/hello
名前を渡すこともできます:
curl http://localhost:8080/hello/Tom
次のステップに進む前に、Ctrl + C を押して Helloworld アプリを終了してください。
次のステップ
アプリケーションを OpenTelemetry で計装するために使用できる 3 つの方法は何でしょうか?

オプションの詳細については、Splunk Observability Cloud 用の.NET アプリケーションの計装
を参照してください。
OpenTelemetryで.NETアプリケーションを計装する
20 minutes
Splunk Distribution of OpenTelemetry のダウンロード
このワークショップでは、NuGet パッケージを使用せず、Splunk Distribution of OpenTelemetry を
手動でインストールします。
最新のsplunk-otel-dotnet-install.sh
ファイルをダウンロードすることから始めます。
これを使用して.NET アプリケーションを計装します:
cd ~/workshop/docker-k8s-otel/helloworld
curl -sSfL https://github.com/signalfx/splunk-otel-dotnet/releases/latest/download/splunk-otel-dotnet-install.sh -O
インストールプロセスの詳細については、Splunk Distribution of OpenTelemetry .NET の手動インストール
を参照してください。
ディストリビューションのインストール
ターミナルで、以下のようにディストリビューションをインストールします
sh ./splunk-otel-dotnet-install.sh
Downloading v1.8.0 for linux-glibc (/tmp/tmp.m3tSdtbmge/splunk-opentelemetry-dotnet-linux-glibc-x64.zip)...
注意:上記のコマンドを実行する際には、ARCHITECTURE 環境変数を含める必要がある場合があります:
ARCHITECTURE=x64 sh ./splunk-otel-dotnet-install.sh
計装の有効化
次に、OpenTelemetry 計装を有効化できます:
. $HOME/.splunk-otel-dotnet/instrument.sh
デプロイメント環境の設定
デプロイメント環境を設定して、データが Splunk Observability Cloud 内の独自の
環境に流れるようにしましょう:
export OTEL_RESOURCE_ATTRIBUTES=deployment.environment=otel-$INSTANCE
計装を使用したアプリケーションの実行
以下のようにアプリケーションを実行できます:
チャレンジ
Linux インスタンスから C#アプリケーションによってエクスポートされているトレースをどのように確認できるでしょうか?
答えを見るにはここをクリック
これを行う方法は 2 つあります:
dotnet run
コマンドの開始時にOTEL_TRACES_EXPORTER=otlp,console
を追加することで、トレースが OTLP 経由でコレクターに書き込まれるとともに、コンソールにも書き込まれるようになります。
OTEL_TRACES_EXPORTER=otlp,console dotnet run
- あるいは、コレクター設定にデバッグエクスポーターを追加し、それをトレースパイプラインに追加することで、トレースがコレクターログに書き込まれるようになります。
exporters:
debug:
verbosity: detailed
service:
pipelines:
traces:
receivers: [jaeger, otlp, zipkin]
processors:
- memory_limiter
- batch
- resourcedetection
exporters: [otlphttp, signalfx, debug]
アプリケーションへのアクセス
アプリケーションが実行中になったら、2 つ目の SSH ターミナルを使用して curl でアクセスします:
curl http://localhost:8080/hello
以前と同様に、Hello, World!
が返されるはずです。
トレースログを有効にした場合は、以下のようなトレースがコンソールまたはコレクターログに書き込まれているのを確認できるはずです:
info: Program[0]
/hello endpoint invoked anonymously
Activity.TraceId: c7bbf57314e4856447508cd8addd49b0
Activity.SpanId: 1c92ac653c3ece27
Activity.TraceFlags: Recorded
Activity.ActivitySourceName: Microsoft.AspNetCore
Activity.DisplayName: GET /hello/{name?}
Activity.Kind: Server
Activity.StartTime: 2024-12-20T00:45:25.6551267Z
Activity.Duration: 00:00:00.0006464
Activity.Tags:
server.address: localhost
server.port: 8080
http.request.method: GET
url.scheme: http
url.path: /hello
network.protocol.version: 1.1
user_agent.original: curl/7.81.0
http.route: /hello/{name?}
http.response.status_code: 200
Resource associated with Activity:
splunk.distro.version: 1.8.0
telemetry.distro.name: splunk-otel-dotnet
telemetry.distro.version: 1.8.0
service.name: helloworld
os.type: linux
os.description: Ubuntu 22.04.5 LTS
os.build_id: 6.8.0-1021-aws
os.name: Ubuntu
os.version: 22.04
host.name: derek-1
host.id: 20cf15fcc7054b468647b73b8f87c556
process.owner: splunk
process.pid: 16997
process.runtime.description: .NET 8.0.11
process.runtime.name: .NET
process.runtime.version: 8.0.11
container.id: 2
telemetry.sdk.name: opentelemetry
telemetry.sdk.language: dotnet
telemetry.sdk.version: 1.9.0
deployment.environment: otel-derek-1
Splunk Observability Cloud でのアプリケーションの確認
セットアップが完了したので、トレースがSplunk Observability Cloudに送信されていることを確認しましょう。アプリケーションが初回デプロイされた場合、データが表示されるまでに数分かかる場合があることに注意してください。
APM にナビゲートし、Environment ドロップダウンを使用してあなたの環境(つまりotel-instancename
)を選択します。
すべてが正しくデプロイされている場合、サービスのリストにhelloworld
が表示されるはずです:

右側のService Mapをクリックしてサービスマップを表示します。

次に、右側のTracesをクリックして、このアプリケーションでキャプチャされたトレースを確認します。

個別のトレースは以下のように表示されるはずです:

次のステップに進む前に、Ctrl + C を押して Helloworld アプリを終了してください。
アプリケーションのDocker化
15 minutes
このワークショップの後半では、.NET アプリケーションを Kubernetes クラスターにデプロイします。
しかし、どのようにそれを行うのでしょうか?
最初のステップは、アプリケーション用の Docker イメージを作成することです。これは
アプリケーションの「Docker 化」として知られており、プロセスはDockerfile
の作成から始まります。
しかし、まず重要な用語を定義しましょう。
重要な用語
Docker とは何ですか?
「Docker は、コンテナと呼ばれる緩い分離環境でアプリケーションをパッケージ化して実行する機能を提供します。分離とセキュリティにより、指定されたホスト上で同時に多くのコンテナを実行できます。コンテナは軽量で、アプリケーションの実行に必要なすべてを含んでいるため、ホストにインストールされているものに依存する必要がありません。」
ソース: https://docs.docker.com/get-started/docker-overview/
コンテナとは何ですか?
「コンテナは、アプリのコンポーネントごとの分離されたプロセスです。各コンポーネントは…独自の分離された環境で実行され、マシン上の他のすべてのものから完全に分離されています。」
ソース: https://docs.docker.com/get-started/docker-concepts/the-basics/what-is-a-container/
コンテナイメージとは何ですか?
「コンテナイメージは、コンテナを実行するためのすべてのファイル、バイナリ、ライブラリ、および設定を含む標準化されたパッケージです。」
Dockerfile
「Dockerfile は、コンテナイメージを作成するために使用されるテキストベースのドキュメントです。実行するコマンド、コピーするファイル、起動コマンドなどに関するイメージビルダーへの指示を提供します。」
Dockerfile の作成
/home/splunk/workshop/docker-k8s-otel/helloworld
ディレクトリにDockerfile
という名前のファイルを作成しましょう。
cd /home/splunk/workshop/docker-k8s-otel/helloworld
ファイルの作成には vi または nano を使用できます。vi を使用した例を示します:
新しく開いたファイルに以下の内容をコピー&ペーストします:
以下のテキストを貼り付ける前に、vi で「i」を押して挿入モードに入ってください。
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
USER app
WORKDIR /app
EXPOSE 8080
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["helloworld.csproj", "helloworld/"]
RUN dotnet restore "./helloworld/./helloworld.csproj"
WORKDIR "/src/helloworld"
COPY . .
RUN dotnet build "./helloworld.csproj" -c $BUILD_CONFIGURATION -o /app/build
FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./helloworld.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "helloworld.dll"]
vi での変更を保存するには、esc
キーを押してコマンドモードに入り、:wq!
と入力してからenter/return
キーを押します。
これはすべて何を意味するのでしょうか?詳しく見てみましょう。
Dockerfile の詳細解説
この例では、マルチステージ Dockerfile を使用しており、Docker イメージ作成プロセスを以下のステージに分けています:
- Base(ベース)
- Build(ビルド)
- Publish(パブリッシュ)
- Final(最終)
マルチステージアプローチはより複雑ですが、デプロイメント用により
軽量なランタイムイメージを作成することができます。以下では、
これらの各ステージの目的を説明します。
ベースステージ
ベースステージでは、アプリを実行するユーザー、作業ディレクトリを定義し、
アプリにアクセスするために使用されるポートを公開します。
これは Microsoft のmcr.microsoft.com/dotnet/aspnet:8.0
イメージをベースにしています:
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
USER app
WORKDIR /app
EXPOSE 8080
なお、mcr.microsoft.com/dotnet/aspnet:8.0
イメージには.NET runtime のみが含まれており、
SDK は含まれていないため、比較的軽量です。これは Debian 12 Linux
distribution がベースになっています。ASP.NET Core Runtime Docker イメージの詳細については
GitHubで確認できます。
Build ステージ
Dockerfile の次のステージは build ステージです。このステージでは、
mcr.microsoft.com/dotnet/sdk:8.0
イメージが使用されます。これも Debian 12 がベースになっていますが、
runtime だけでなく完全な.NET SDKが含まれています。
このステージでは.csproj
ファイルを build イメージにコピーし、その後dotnet restore
を使用して
アプリケーションが使用する依存関係をダウンロードします。
次に、アプリケーションコードを build イメージにコピーし、
dotnet build
を使用してプロジェクトとその依存関係を
.dll
バイナリのセットにビルドします:
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["helloworld.csproj", "helloworld/"]
RUN dotnet restore "./helloworld/./helloworld.csproj"
WORKDIR "/src/helloworld"
COPY . .
RUN dotnet build "./helloworld.csproj" -c $BUILD_CONFIGURATION -o /app/build
Publish ステージ
3 番目のステージは publish で、これは Microsoft イメージではなく build ステージイメージをベースにしています。このステージでは、dotnet publish
を使用して
アプリケーションとその依存関係を deployment 用にパッケージ化します:
FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./helloworld.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
Final ステージ
4 番目のステージは最終ステージで、これは base
ステージイメージをベースにしています(build と publish ステージよりも軽量)。publish ステージイメージからの出力をコピーし、
アプリケーションの entry point を定義します:
FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "helloworld.dll"]
Docker イメージのビルド
Dockerfile
ができたので、これを使用してアプリケーションを含む Docker イメージを
ビルドできます:
docker build -t helloworld:1.0 .
DEPRECATED: The legacy builder is deprecated and will be removed in a future release.
Install the buildx component to build images with BuildKit:
https://docs.docker.com/go/buildx/
Sending build context to Docker daemon 281.1kB
Step 1/19 : FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
8.0: Pulling from dotnet/aspnet
af302e5c37e9: Pull complete
91ab5e0aabf0: Pull complete
1c1e4530721e: Pull complete
1f39ca6dcc3a: Pull complete
ea20083aa801: Pull complete
64c242a4f561: Pull complete
Digest: sha256:587c1dd115e4d6707ff656d30ace5da9f49cec48e627a40bbe5d5b249adc3549
Status: Downloaded newer image for mcr.microsoft.com/dotnet/aspnet:8.0
---> 0ee5d7ddbc3b
Step 2/19 : USER app
etc,
これは、現在のディレクトリのDockerfile
を使用してhelloworld:1.0
のタグでイメージをビルドするよう Docker に指示します。
以下のコマンドで正常に作成されたことを確認できます:
REPOSITORY TAG IMAGE ID CREATED SIZE
helloworld 1.0 db19077b9445 20 seconds ago 217MB
Docker イメージのテスト
続行する前に、以前に開始したアプリケーションがインスタンス上で実行されていないことを確認してください。
Docker イメージを使用して以下のようにアプリケーションを実行できます:
docker run --name helloworld \
--detach \
--expose 8080 \
--network=host \
helloworld:1.0
注意:--network=host
パラメータを含めて、Docker コンテナが
インスタンス上のリソースにアクセスできるようにしています。これは後でアプリケーションが
localhost 上で実行されているコレクターにデータを送信する必要がある場合に重要です。
Docker コンテナが実行されていることを確認しましょう:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5f5b9cd56ac5 helloworld:1.0 "dotnet helloworld.d…" 2 mins ago Up 2 mins helloworld
以前と同様にアプリケーションにアクセスできます:
curl http://localhost:8080/hello/Docker
おめでとうございます。ここまで到達したということは、.NET アプリケーションの Docker 化に成功したということです。
Dockerfileに計装を追加する
10 minutes
アプリケーションを正常に Docker 化したので、次に OpenTelemetry による計装 を追加しましょう。
これは、Linux で実行しているアプリケーションを計装した際の手順と似ていますが、
注意すべきいくつかの重要な違いがあります。
Dockerfile の更新
/home/splunk/workshop/docker-k8s-otel/helloworld
ディレクトリのDockerfile
を更新しましょう。
Dockerfile で.NET アプリケーションがビルドされた後、以下の操作を行いたいと思います:
splunk-otel-dotnet-install.sh
をダウンロードして実行するために必要な依存関係を追加する- Splunk OTel .NET インストーラーをダウンロードする
- ディストリビューションをインストールする
Dockerfile のビルドステージに以下を追加できます。vi で Dockerfile を開きましょう:
vi /home/splunk/workshop/docker-k8s-otel/helloworld/Dockerfile
vi では「i」キーを押して編集モードに入ります
‘NEW CODE’とマークされている行を Dockerfile のビルドステージセクションに貼り付けてください:
# CODE ALREADY IN YOUR DOCKERFILE:
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["helloworld.csproj", "helloworld/"]
RUN dotnet restore "./helloworld/./helloworld.csproj"
WORKDIR "/src/helloworld"
COPY . .
RUN dotnet build "./helloworld.csproj" -c $BUILD_CONFIGURATION -o /app/build
# NEW CODE: add dependencies for splunk-otel-dotnet-install.sh
RUN apt-get update && \
apt-get install -y unzip
# NEW CODE: download Splunk OTel .NET installer
RUN curl -sSfL https://github.com/signalfx/splunk-otel-dotnet/releases/latest/download/splunk-otel-dotnet-install.sh -O
# NEW CODE: install the distribution
RUN sh ./splunk-otel-dotnet-install.sh
次に、以下の変更で Dockerfile の最終ステージを更新します:
- ビルドイメージから最終イメージに/root/.splunk-otel-dotnet/をコピーする
- entrypoint.sh ファイルもコピーする
OTEL_SERVICE_NAME
とOTEL_RESOURCE_ATTRIBUTES
環境変数を設定するENTRYPOINT
をentrypoint.sh
に設定する
最も簡単な方法は、最終ステージ全体を以下の内容で置き換えることです:
重要 Dockerfile の$INSTANCE
をあなたのインスタンス名に置き換えてください。
インスタンス名はecho $INSTANCE
を実行することで確認できます。
# CODE ALREADY IN YOUR DOCKERFILE
FROM base AS final
# NEW CODE: Copy instrumentation file tree
WORKDIR "//home/app/.splunk-otel-dotnet"
COPY --from=build /root/.splunk-otel-dotnet/ .
# CODE ALREADY IN YOUR DOCKERFILE
WORKDIR /app
COPY --from=publish /app/publish .
# NEW CODE: copy the entrypoint.sh script
COPY entrypoint.sh .
# NEW CODE: set OpenTelemetry environment variables
ENV OTEL_SERVICE_NAME=helloworld
ENV OTEL_RESOURCE_ATTRIBUTES='deployment.environment=otel-$INSTANCE'
# NEW CODE: replace the prior ENTRYPOINT command with the following two lines
ENTRYPOINT ["sh", "entrypoint.sh"]
CMD ["dotnet", "helloworld.dll"]
vi での変更を保存するには、esc
キーを押してコマンドモードに入り、:wq!
と入力してからenter/return
キーを押します。
これらすべての変更の後、Dockerfile は以下のようになるはずです:
重要 このコンテンツを自分の Dockerfile にコピー&ペーストする場合は、
Dockerfile の$INSTANCE
をあなたのインスタンス名に置き換えてください。
インスタンス名はecho $INSTANCE
を実行することで確認できます。
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
USER app
WORKDIR /app
EXPOSE 8080
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
ARG BUILD_CONFIGURATION=Release
WORKDIR /src
COPY ["helloworld.csproj", "helloworld/"]
RUN dotnet restore "./helloworld/./helloworld.csproj"
WORKDIR "/src/helloworld"
COPY . .
RUN dotnet build "./helloworld.csproj" -c $BUILD_CONFIGURATION -o /app/build
# NEW CODE: add dependencies for splunk-otel-dotnet-install.sh
RUN apt-get update && \
apt-get install -y unzip
# NEW CODE: download Splunk OTel .NET installer
RUN curl -sSfL https://github.com/signalfx/splunk-otel-dotnet/releases/latest/download/splunk-otel-dotnet-install.sh -O
# NEW CODE: install the distribution
RUN sh ./splunk-otel-dotnet-install.sh
FROM build AS publish
ARG BUILD_CONFIGURATION=Release
RUN dotnet publish "./helloworld.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
FROM base AS final
# NEW CODE: Copy instrumentation file tree
WORKDIR "//home/app/.splunk-otel-dotnet"
COPY --from=build /root/.splunk-otel-dotnet/ .
WORKDIR /app
COPY --from=publish /app/publish .
# NEW CODE: copy the entrypoint.sh script
COPY entrypoint.sh .
# NEW CODE: set OpenTelemetry environment variables
ENV OTEL_SERVICE_NAME=helloworld
ENV OTEL_RESOURCE_ATTRIBUTES='deployment.environment=otel-$INSTANCE'
# NEW CODE: replace the prior ENTRYPOINT command with the following two lines
ENTRYPOINT ["sh", "entrypoint.sh"]
CMD ["dotnet", "helloworld.dll"]
entrypoint.sh ファイルの作成
また、/home/splunk/workshop/docker-k8s-otel/helloworld
フォルダにentrypoint.sh
という名前のファイルを
以下の内容で作成する必要があります:
vi /home/splunk/workshop/docker-k8s-otel/helloworld/entrypoint.sh
次に、新しく作成したファイルに以下のコードを貼り付けます:
#!/bin/sh
# Read in the file of environment settings
. /$HOME/.splunk-otel-dotnet/instrument.sh
# Then run the CMD
exec "$@"
vi での変更を保存するには、esc
キーを押してコマンドモードに入り、:wq!
と入力してからenter/return
キーを押します。
entrypoint.sh
スクリプトは、計装に含まれる instrument.sh スクリプトが環境変数をコンテナ起動時に取得するために必要です。これにより、各プラットフォームに対して環境変数が正しく設定されることが保証されます。
「なぜ Linux ホスト上で OpenTelemetry .NET instrumentation を有効化したときのように、
Dockerfile に以下のコマンドを含めるだけではだめなのか?」と疑問に思うかもしれません。
RUN . $HOME/.splunk-otel-dotnet/instrument.sh
この方法の問題点は、各 Dockerfile RUN ステップが新しいコンテナと新しいシェルで実行されることです。
あるシェルで環境変数を設定しようとしても、後で見ることはできません。
この問題は、ここで行ったようにエントリポイントスクリプトを使用することで解決されます。
この問題についての詳細は、こちらのStack Overflow の投稿を参照してください。
Docker イメージのビルド
OpenTelemetry .NET instrumentation を含む新しい Docker イメージをビルドしましょう:
docker build -t helloworld:1.1 .
注:以前のバージョンと区別するために、異なるバージョン(1.1)を使用しています。
古いバージョンをクリーンアップするには、以下のコマンドでコンテナ ID を取得します:
次に、以下のコマンドでコンテナを削除します:
docker rm <old container id> --force
次にコンテナイメージ ID を取得します:
最後に、以下のコマンドで古いイメージを削除できます:
docker image rm <old image id>
アプリケーションの実行
新しい Docker イメージを実行しましょう:
docker run --name helloworld \
--detach \
--expose 8080 \
--network=host \
helloworld:1.1
以下を使用してアプリケーションにアクセスできます:
curl http://localhost:8080/hello
トラフィックを生成するために上記のコマンドを数回実行しましょう。
1 分ほど経過したら、Splunk Observability Cloud に新しいトレースが表示されることを確認します。
あなたの特定の環境でトレースを探すことを忘れないでください。
トラブルシューティング
Splunk Observability Cloud にトレースが表示されない場合は、以下のようにトラブルシューティングを行うことができます。
まず、コレクター設定ファイルを編集用に開きます:
sudo vi /etc/otel/collector/agent_config.yaml
次に、トレースパイプラインにデバッグエクスポーターを追加します。これにより、トレースがコレクターログに書き込まれるようになります:
service:
extensions: [health_check, http_forwarder, zpages, smartagent]
pipelines:
traces:
receivers: [jaeger, otlp, zipkin]
processors:
- memory_limiter
- batch
- resourcedetection
#- resource/add_environment
# NEW CODE: デバッグエクスポーターをここに追加
exporters: [otlphttp, signalfx, debug]
その後、コレクターを再起動して設定変更を適用します:
sudo systemctl restart splunk-otel-collector
journalctl
を使用してコレクターログを表示できます:
ログの追跡を終了するには、Ctrl + C を押します。
sudo journalctl -u splunk-otel-collector -f -n 100
K8sでOpenTelemetryコレクターをインストール
15 minutes
ワークショップパート 1 の振り返り
ワークショップのこの時点で、以下を正常に完了しました:
- Linux ホストに Splunk distribution of OpenTelemetry コレクターをデプロイ
- Splunk Observability Cloud にトレースとメトリクスを送信するよう設定
- .NET アプリケーションをデプロイし、OpenTelemetry で計装
- .NET アプリケーションを Docker 化し、o11y cloud にトレースが流れることを確認
上記のステップを完了していない場合は、ワークショップの残りの部分に進む前に以下のコマンドを実行してください:
cp /home/splunk/workshop/docker-k8s-otel/docker/Dockerfile /home/splunk/workshop/docker-k8s-otel/helloworld/
cp /home/splunk/workshop/docker-k8s-otel/docker/entrypoint.sh /home/splunk/workshop/docker-k8s-otel/helloworld/
重要 これらのファイルがコピーされたら、/home/splunk/workshop/docker-k8s-otel/helloworld/Dockerfile
を
エディターで開き、Dockerfile の $INSTANCE
をあなたのインスタンス名に置き換えてください。
インスタンス名は echo $INSTANCE
を実行することで確認できます。
ワークショップパート 2 の紹介
ワークショップの次の部分では、Kubernetes でアプリケーションを実行したいと思います。
そのため、Kubernetes クラスターに Splunk distribution of OpenTelemetry コレクターを
デプロイする必要があります。
まず、いくつかの重要な用語を定義しましょう。
重要な用語
Kubernetes とは何ですか?
「Kubernetes は、宣言的な設定と自動化の両方を促進する、コンテナ化されたワークロードとサービスを管理するためのポータブルで拡張可能なオープンソースプラットフォームです。」
Source: https://kubernetes.io/docs/concepts/overview/
Dockerfile に小さな修正を加えた後、アプリケーション用に以前ビルドした Docker イメージを
Kubernetes クラスターにデプロイします。
Helm とは何ですか?
Helm は Kubernetes 用のパッケージマネージャーです。
「最も複雑な Kubernetes アプリケーションだとしても、定義、インストール、アップグレード役立ちます」
Helm を使用したコレクターのインストール
プロダクト内ウィザードではなくコマンドラインを使用して、コレクターをインストールするための独自の
helm
コマンドを作成しましょう。
まず、helm リポジトリを追加する必要があります:ます。」
Source: https://helm.sh/
Helm を使用して K8s クラスターに OpenTelemetry コレクターをデプロイします。
Helm の利点
- 複雑性の管理
- 数十のマニフェストファイルではなく、単一の values.yaml ファイルを扱う
- 簡単な更新
- ロールバックサポート
- helm rollback を使用してリリースの古いバージョンにロールバック
ホストコレクターのアンインストール
先に進む前に、Linux ホストに先ほどインストールしたコレクターを削除しましょう:
\
curl -sSL https://dl.signalfx.com/splunk-otel-collector.sh > /tmp/splunk-otel-collector.sh;
sudo sh /tmp/splunk-otel-collector.sh --uninstall
Helm を利用して Collector をインストールする
ウィザードの代わりに、コマンドラインを利用して collector をインストールします。
まず初めに、Helm リポジトリに登録する必要があります
helm repo add splunk-otel-collector-chart https://signalfx.github.io/splunk-otel-collector-chart
リポジトリが最新であることを確認します:
helm チャートのデプロイメントを設定するために、/home/splunk
ディレクトリにvalues.yaml
という名前の新しいファイルを作成しましょう:
# swith to the /home/splunk dir
cd /home/splunk
# create a values.yaml file in vi
vi values.yaml
Press ‘i’ to enter into insert mode in vi before pasting the text below. “i"を押下すると vi はインサートモードになります。ペースト前に押下してください
そして、下記のコードをコピーしてください
logsEngine: otel
agent:
config:
receivers:
hostmetrics:
collection_interval: 10s
root_path: /hostfs
scrapers:
cpu: null
disk: null
filesystem:
exclude_mount_points:
match_type: regexp
mount_points:
- /var/*
- /snap/*
- /boot/*
- /boot
- /opt/orbstack/*
- /mnt/machines/*
- /Users/*
load: null
memory: null
network: null
paging: null
processes: null
vi での変更を保存するには、esc
キーを押してコマンドモードに入り、:wq!
と入力してからenter/return
キーを押します。
次のコマンドを使用してコレクターをインストールできます:
helm install splunk-otel-collector --version 0.111.0 \
--set="splunkObservability.realm=$REALM" \
--set="splunkObservability.accessToken=$ACCESS_TOKEN" \
--set="clusterName=$INSTANCE-cluster" \
--set="environment=otel-$INSTANCE" \
--set="splunkPlatform.token=$HEC_TOKEN" \
--set="splunkPlatform.endpoint=$HEC_URL" \
--set="splunkPlatform.index=splunk4rookies-workshop" \
-f values.yaml \
splunk-otel-collector-chart/splunk-otel-collector
NAME: splunk-otel-collector
LAST DEPLOYED: Fri Dec 20 01:01:43 2024
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Splunk OpenTelemetry Collector is installed and configured to send data to Splunk Observability realm us1.
コレクターが実行中であることを確認
以下のコマンドでコレクターが実行されているかどうかを確認できます:
NAME READY STATUS RESTARTS AGE
splunk-otel-collector-agent-8xvk8 1/1 Running 0 49s
splunk-otel-collector-k8s-cluster-receiver-d54857c89-tx7qr 1/1 Running 0 49s
O11y Cloud で K8s クラスターを確認
Splunk Observability Cloud で、Infrastructure -> Kubernetes -> Kubernetes Clustersにナビゲートし、
クラスター名($INSTANCE-cluster
)を検索します:

アプリケーションをK8sにデプロイ
15 minutes
Dockerfile の更新
Kubernetes では、環境変数は通常、Docker イメージに組み込むのではなく.yaml
マニフェストファイルで管理されます。そこで、Dockerfile から以下の 2 つの環境変数を削除しましょう:
vi /home/splunk/workshop/docker-k8s-otel/helloworld/Dockerfile
次に、以下の 2 つの環境変数を削除します:
ENV OTEL_SERVICE_NAME=helloworld
ENV OTEL_RESOURCE_ATTRIBUTES='deployment.environment=otel-$INSTANCE'
vi での変更を保存するには、esc
キーを押してコマンドモードに入り、:wq!
と入力してからenter/return
キーを押します。
新しい Docker イメージのビルド
環境変数を除外した新しい Docker イメージをビルドしましょう:
cd /home/splunk/workshop/docker-k8s-otel/helloworld
docker build -t helloworld:1.2 .
Note: we’ve used a different version (1.2) to distinguish the image from our earlier version.
To clean up the older versions, run the following command to get the container id:
Then run the following command to delete the container:
docker rm <old container id> --force
Now we can get the container image id:
Finally, we can run the following command to delete the old image:
docker image rm <old image id>
Docker イメージを Kubernetes にインポート
通常であれば、Docker イメージを Docker Hub などのリポジトリにプッシュします。
しかし、今回のセッションでは、k3s に直接インポートする回避策を使用します。
cd /home/splunk
# Export the image from docker
docker save --output helloworld.tar helloworld:1.2
# Import the image into k3s
sudo k3s ctr images import helloworld.tar
.NET アプリケーションのデプロイ
ヒント:vi で編集モードに入るには「i」キーを押します。変更を保存するには、esc
キーを押してコマンドモードに入り、:wq!
と入力してからenter/return
キーを押します。
.NET アプリケーションを K8s にデプロイするために、/home/splunk
にdeployment.yaml
という名前のファイルを作成しましょう:
vi /home/splunk/deployment.yaml
そして以下を貼り付けます:
apiVersion: apps/v1
kind: Deployment
metadata:
name: helloworld
spec:
selector:
matchLabels:
app: helloworld
replicas: 1
template:
metadata:
labels:
app: helloworld
spec:
containers:
- name: helloworld
image: docker.io/library/helloworld:1.2
imagePullPolicy: Never
ports:
- containerPort: 8080
env:
- name: PORT
value: "8080"
Kubernetes における Deployment とは?
deployment.yaml ファイルは、deployment リソースを定義するために使用される kubernetes 設定ファイルです。このファイルは Kubernetes でアプリケーションを管理するための基盤となります!deployment 設定は deployment の 望ましい状態 を定義し、Kubernetes が 実際の状態 がそれと一致するよう保証します。これにより、アプリケーション pod の自己修復が可能になり、アプリケーションの簡単な更新やロールバックも可能になります。
次に、同じディレクトリにservice.yaml
という名前の 2 つ目のファイルを作成します:
vi /home/splunk/service.yaml
そして以下を貼り付けます:
apiVersion: v1
kind: Service
metadata:
name: helloworld
labels:
app: helloworld
spec:
type: ClusterIP
selector:
app: helloworld
ports:
- port: 8080
protocol: TCP
Kubernetes における Service とは?
Kubernetes の Service は抽象化レイヤーであり、仲介者のような役割を果たします。Pod にアクセスするための固定 IP アドレスや DNS 名を提供し、時間の経過とともに Pod が追加、削除、または交換されても同じままです。
これらのマニフェストファイルを使用してアプリケーションをデプロイできます:
# create the deployment
kubectl apply -f deployment.yaml
# create the service
kubectl apply -f service.yaml
deployment.apps/helloworld created
service/helloworld created
アプリケーションのテスト
アプリケーションにアクセスするには、まず IP アドレスを取得する必要があります:
kubectl describe svc helloworld | grep IP:
その後、前のコマンドから返された Cluster IP を使用してアプリケーションにアクセスできます。
例:
curl http://10.43.102.103:8080/hello/Kubernetes
OpenTelemetry の設定
.NET OpenTelemetry 計装はすでに Docker イメージに組み込まれています。しかし、データの送信先を指定するためにいくつかの環境変数を設定する必要があります。
先ほど作成したdeployment.yaml
ファイルに以下を追加します:
重要 以下の YAML の$INSTANCE
をあなたのインスタンス名に置き換えてください。
インスタンス名はecho $INSTANCE
を実行することで確認できます。
env:
- name: PORT
value: "8080"
- name: NODE_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: "http://$(NODE_IP):4318"
- name: OTEL_SERVICE_NAME
value: "helloworld"
- name: OTEL_RESOURCE_ATTRIBUTES
value: "deployment.environment=otel-$INSTANCE"
完全なdeployment.yaml
ファイルは以下のようになります($INSTANCE
ではなくあなたのインスタンス名を使用してください):
apiVersion: apps/v1
kind: Deployment
metadata:
name: helloworld
spec:
selector:
matchLabels:
app: helloworld
replicas: 1
template:
metadata:
labels:
app: helloworld
spec:
containers:
- name: helloworld
image: docker.io/library/helloworld:1.2
imagePullPolicy: Never
ports:
- containerPort: 8080
env:
- name: PORT
value: "8080"
- name: NODE_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: "http://$(NODE_IP):4318"
- name: OTEL_SERVICE_NAME
value: "helloworld"
- name: OTEL_RESOURCE_ATTRIBUTES
value: "deployment.environment=otel-$INSTANCE"
以下のコマンドで変更を適用します:
kubectl apply -f deployment.yaml
deployment.apps/helloworld configured
その後、curl
を使用してトラフィックを生成します。
1 分ほど経過すると、o11y cloud でトレースが流れているのが確認できるはずです。ただし、より早くトレースを確認したい場合は、以下の方法があります…
チャレンジ
開発者として、トレース ID を素早く取得するか、コンソールフィードバックを見たい場合、deployment.yaml ファイルにどのような環境変数を追加できるでしょうか?
答えを見るにはここをクリック
セクション 4「.NET Application を OpenTelemetry で計装する」のチャレンジで思い出していただければ、OTEL_TRACES_EXPORTER
環境変数を使って trace を console に書き込むトリックをお見せしました。この変数を deployment.yaml に追加し、アプリケーションを再 deploy して、helloworld アプリから log を tail することで、trace id を取得して Splunk Observability Cloud で trace を見つけることができます。(ワークショップの次のセクションでは、debug exporter の使用についても説明します。これは K8s 環境でアプリケーションを debug する際の典型的な方法です。)
まず、vi で deployment.yaml ファイルを開きます:
次に、OTEL_TRACES_EXPORTER
環境変数を追加します:
env:
- name: PORT
value: "8080"
- name: NODE_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: "http://$(NODE_IP):4318"
- name: OTEL_SERVICE_NAME
value: "helloworld"
- name: OTEL_RESOURCE_ATTRIBUTES
value: "deployment.environment=YOURINSTANCE"
# NEW VALUE HERE:
- name: OTEL_TRACES_EXPORTER
value: "otlp,console"
変更を保存してからアプリケーションを再 deploy します:
kubectl apply -f deployment.yaml
deployment.apps/helloworld configured
helloworld の log を tail します:
kubectl logs -l app=helloworld -f
info: HelloWorldController[0]
/hello endpoint invoked by K8s9
Activity.TraceId: 5bceb747cc7b79a77cfbde285f0f09cb
Activity.SpanId: ac67afe500e7ad12
Activity.TraceFlags: Recorded
Activity.ActivitySourceName: Microsoft.AspNetCore
Activity.DisplayName: GET hello/{name?}
Activity.Kind: Server
Activity.StartTime: 2025-02-04T15:22:48.2381736Z
Activity.Duration: 00:00:00.0027334
Activity.Tags:
server.address: 10.43.226.224
server.port: 8080
http.request.method: GET
url.scheme: http
url.path: /hello/K8s9
network.protocol.version: 1.1
user_agent.original: curl/7.81.0
http.route: hello/{name?}
http.response.status_code: 200
Resource associated with Activity:
splunk.distro.version: 1.8.0
telemetry.distro.name: splunk-otel-dotnet
telemetry.distro.version: 1.8.0
os.type: linux
os.description: Debian GNU/Linux 12 (bookworm)
os.build_id: 6.2.0-1018-aws
os.name: Debian GNU/Linux
os.version: 12
host.name: helloworld-69f5c7988b-dxkwh
process.owner: app
process.pid: 1
process.runtime.description: .NET 8.0.12
process.runtime.name: .NET
process.runtime.version: 8.0.12
container.id: 39c2061d7605d8c390b4fe5f8054719f2fe91391a5c32df5684605202ca39ae9
telemetry.sdk.name: opentelemetry
telemetry.sdk.language: dotnet
telemetry.sdk.version: 1.9.0
service.name: helloworld
deployment.environment: otel-jen-tko-1b75
次に、別の terminal window で curl コマンドを使って trace を生成します。log を tail している console で trace id が表示されるはずです。Activity.TraceId:
の値をコピーして、APM の Trace 検索フィールドに貼り付けてください。
OpenTelemetryコレクター設定のカスタマイズ
20 minutes
デフォルト設定を使用して K8s クラスターに Splunk Distribution of OpenTelemetry コレクターを
デプロイしました。このセクションでは、コレクター設定をカスタマイズする方法をいくつかの例で
説明します。
コレクター設定の取得
コレクター設定をカスタマイズする前に、現在の設定がどのようになっているかを
どのように確認するのでしょうか?
Kubernetes 環境では、コレクター設定は Config Map を使用して保存されます。
以下のコマンドで、クラスターに存在する config map を確認できます:
kubectl get cm -l app=splunk-otel-collector
NAME DATA AGE
splunk-otel-collector-otel-k8s-cluster-receiver 1 3h37m
splunk-otel-collector-otel-agent 1 3h37m
なぜ 2 つの config map があるのでしょうか?
次に、以下のようにコレクターエージェントの config map を表示できます:
kubectl describe cm splunk-otel-collector-otel-agent
Name: splunk-otel-collector-otel-agent
Namespace: default
Labels: app=splunk-otel-collector
app.kubernetes.io/instance=splunk-otel-collector
app.kubernetes.io/managed-by=Helm
app.kubernetes.io/name=splunk-otel-collector
app.kubernetes.io/version=0.113.0
chart=splunk-otel-collector-0.113.0
helm.sh/chart=splunk-otel-collector-0.113.0
heritage=Helm
release=splunk-otel-collector
Annotations: meta.helm.sh/release-name: splunk-otel-collector
meta.helm.sh/release-namespace: default
Data
====
relay:
----
exporters:
otlphttp:
headers:
X-SF-Token: ${SPLUNK_OBSERVABILITY_ACCESS_TOKEN}
metrics_endpoint: https://ingest.us1.signalfx.com/v2/datapoint/otlp
traces_endpoint: https://ingest.us1.signalfx.com/v2/trace/otlp
(followed by the rest of the collector config in yaml format)
K8s でコレクター設定を更新する方法
Linux インスタンスでコレクターを実行した以前の例では、コレクター設定は
/etc/otel/collector/agent_config.yaml
ファイルで利用可能でした。その場合にコレクター設定を
変更する必要があれば、単純にこのファイルを編集し、変更を保存してから
コレクターを再起動すればよかったのです。
K8s では、少し異なる動作をします。agent_config.yaml
を直接変更する代わりに、
helm チャートをデプロイするために使用されるvalues.yaml
ファイルを変更することで
コレクター設定をカスタマイズします。
GitHubの values.yaml ファイルには、
利用可能なカスタマイズオプションが記載されています。
例を見てみましょう。
Infrastructure Events Monitoring の追加
最初の例として、K8s クラスターの infrastructure events monitoring を有効にしましょう。
これにより、charts の Events Feed セクションの一部として Kubernetes イベントを確認できるようになります。
cluster receiver は、kubernetes-events
monitor を使用して Smart Agent receiver で設定され、custom イベントを送信します。詳細についてはCollect Kubernetes eventsを参照してください。
これはvalues.yaml
ファイルに以下の行を追加することで実行されます:
ヒント:vi での開き方と保存方法は前のステップにあります。
logsEngine: otel
splunkObservability:
infrastructureMonitoringEventsEnabled: true
agent:
ファイルが保存されたら、以下のコマンドで変更を適用できます:
helm upgrade splunk-otel-collector \
--set="splunkObservability.realm=$REALM" \
--set="splunkObservability.accessToken=$ACCESS_TOKEN" \
--set="clusterName=$INSTANCE-cluster" \
--set="environment=otel-$INSTANCE" \
--set="splunkPlatform.token=$HEC_TOKEN" \
--set="splunkPlatform.endpoint=$HEC_URL" \
--set="splunkPlatform.index=splunk4rookies-workshop" \
-f values.yaml \
splunk-otel-collector-chart/splunk-otel-collector
Release "splunk-otel-collector" has been upgraded. Happy Helming!
NAME: splunk-otel-collector
LAST DEPLOYED: Fri Dec 20 01:17:03 2024
NAMESPACE: default
STATUS: deployed
REVISION: 2
TEST SUITE: None
NOTES:
Splunk OpenTelemetry Collector is installed and configured to send data to Splunk Observability realm us1.
その後、config map を表示して変更が適用されたことを確認できます:
kubectl describe cm splunk-otel-collector-otel-k8s-cluster-receiver
smartagent/kubernetes-events
が agent config に含まれていることを確認してください:
smartagent/kubernetes-events:
alwaysClusterReporter: true
type: kubernetes-events
whitelistedEvents:
- involvedObjectKind: Pod
reason: Created
- involvedObjectKind: Pod
reason: Unhealthy
- involvedObjectKind: Pod
reason: Failed
- involvedObjectKind: Job
reason: FailedCreate
これらの特定の変更が適用されるのは
cluster receiver config map なので、そちらを指定していることに注意してください。
Debug Exporter の追加
collector に送信される trace と log を確認して、
Splunk に送信する前に検査したいとします。この目的のために debug exporter を使用できます。これは
OpenTelemetry 関連の問題のトラブルシューティングに役立ちます。
values.yaml ファイルの下部に以下のように debug exporter を追加しましょう:
logsEngine: otel
splunkObservability:
infrastructureMonitoringEventsEnabled: true
agent:
config:
receivers: ...
exporters:
debug:
verbosity: detailed
service:
pipelines:
traces:
exporters:
- debug
logs:
exporters:
- debug
ファイルが保存されたら、以下のコマンドで変更を適用できます:
helm upgrade splunk-otel-collector \
--set="splunkObservability.realm=$REALM" \
--set="splunkObservability.accessToken=$ACCESS_TOKEN" \
--set="clusterName=$INSTANCE-cluster" \
--set="environment=otel-$INSTANCE" \
--set="splunkPlatform.token=$HEC_TOKEN" \
--set="splunkPlatform.endpoint=$HEC_URL" \
--set="splunkPlatform.index=splunk4rookies-workshop" \
-f values.yaml \
splunk-otel-collector-chart/splunk-otel-collector
Release "splunk-otel-collector" has been upgraded. Happy Helming!
NAME: splunk-otel-collector
LAST DEPLOYED: Fri Dec 20 01:32:03 2024
NAMESPACE: default
STATUS: deployed
REVISION: 3
TEST SUITE: None
NOTES:
Splunk OpenTelemetry Collector is installed and configured to send data to Splunk Observability realm us1.
curl を使用してアプリケーションを数回実行してから、以下のコマンドで agent collector の log を tail します:
kubectl logs -l component=otel-collector-agent -f
以下のような trace が agent collector の log に書き込まれているのが確認できるはずです:
2024-12-20T01:43:52.929Z info Traces {"kind": "exporter", "data_type": "traces", "name": "debug", "resource spans": 1, "spans": 2}
2024-12-20T01:43:52.929Z info ResourceSpans #0
Resource SchemaURL: https://opentelemetry.io/schemas/1.6.1
Resource attributes:
-> splunk.distro.version: Str(1.8.0)
-> telemetry.distro.name: Str(splunk-otel-dotnet)
-> telemetry.distro.version: Str(1.8.0)
-> os.type: Str(linux)
-> os.description: Str(Debian GNU/Linux 12 (bookworm))
-> os.build_id: Str(6.8.0-1021-aws)
-> os.name: Str(Debian GNU/Linux)
-> os.version: Str(12)
-> host.name: Str(derek-1)
-> process.owner: Str(app)
-> process.pid: Int(1)
-> process.runtime.description: Str(.NET 8.0.11)
-> process.runtime.name: Str(.NET)
-> process.runtime.version: Str(8.0.11)
-> container.id: Str(78b452a43bbaa3354a3cb474010efd6ae2367165a1356f4b4000be031b10c5aa)
-> telemetry.sdk.name: Str(opentelemetry)
-> telemetry.sdk.language: Str(dotnet)
-> telemetry.sdk.version: Str(1.9.0)
-> service.name: Str(helloworld)
-> deployment.environment: Str(otel-derek-1)
-> k8s.pod.ip: Str(10.42.0.15)
-> k8s.pod.labels.app: Str(helloworld)
-> k8s.pod.name: Str(helloworld-84865965d9-nkqsx)
-> k8s.namespace.name: Str(default)
-> k8s.pod.uid: Str(38d39bc6-1309-4022-a569-8acceef50942)
-> k8s.node.name: Str(derek-1)
-> k8s.cluster.name: Str(derek-1-cluster)
そして以下のような log エントリも確認できます:
2024-12-20T01:43:53.215Z info Logs {"kind": "exporter", "data_type": "logs", "name": "debug", "resource logs": 1, "log records": 2}
2024-12-20T01:43:53.215Z info ResourceLog #0
Resource SchemaURL: https://opentelemetry.io/schemas/1.6.1
Resource attributes:
-> splunk.distro.version: Str(1.8.0)
-> telemetry.distro.name: Str(splunk-otel-dotnet)
-> telemetry.distro.version: Str(1.8.0)
-> os.type: Str(linux)
-> os.description: Str(Debian GNU/Linux 12 (bookworm))
-> os.build_id: Str(6.8.0-1021-aws)
-> os.name: Str(Debian GNU/Linux)
-> os.version: Str(12)
-> host.name: Str(derek-1)
-> process.owner: Str(app)
-> process.pid: Int(1)
-> process.runtime.description: Str(.NET 8.0.11)
-> process.runtime.name: Str(.NET)
-> process.runtime.version: Str(8.0.11)
-> container.id: Str(78b452a43bbaa3354a3cb474010efd6ae2367165a1356f4b4000be031b10c5aa)
-> telemetry.sdk.name: Str(opentelemetry)
-> telemetry.sdk.language: Str(dotnet)
-> telemetry.sdk.version: Str(1.9.0)
-> service.name: Str(helloworld)
-> deployment.environment: Str(otel-derek-1)
-> k8s.node.name: Str(derek-1)
-> k8s.cluster.name: Str(derek-1-cluster)
ただし、Splunk Observability Cloud に戻ると、アプリケーションから trace と log が
もはやそこに送信されていないことに気づくでしょう。
なぜそうなったと思いますか?次のセクションで詳しく説明します。
Troubleshoot OpenTelemetry Collector Issues
20 minutes
前のセクションでは、debug エクスポーターをコレクターの設定に追加し、
トレースとログのパイプラインの一部にしました。期待通りに、debug 出力が
エージェントコレクターのログに書き込まれているのが確認できます。
しかし、トレースが o11y cloud に送信されなくなっています。なぜなのかを把握して修正しましょう。
コレクター設定を確認する
values.yaml
ファイルを通じてコレクター設定が変更された場合は、
config map を確認してコレクターに実際に適用された設定を確認することが役立ちます:
kubectl describe cm splunk-otel-collector-otel-agent
エージェントコレクター設定のログとトレースのパイプラインを確認しましょう。次のようになっているはずです:
pipelines:
logs:
exporters:
- debug
processors:
- memory_limiter
- k8sattributes
- filter/logs
- batch
- resourcedetection
- resource
- resource/logs
- resource/add_environment
receivers:
- filelog
- fluentforward
- otlp
...
traces:
exporters:
- debug
processors:
- memory_limiter
- k8sattributes
- batch
- resourcedetection
- resource
- resource/add_environment
receivers:
- otlp
- jaeger
- smartagent/signalfx-forwarder
- zipkin
問題がわかりますか?debug エクスポーターのみがトレースとログのパイプラインに含まれています。
以前のトレースパイプライン設定にあったotlphttp
とsignalfx
エクスポーターがなくなっています。
これが、もう o11y cloud でトレースが見えなくなった理由です。ログパイプラインについても、splunk_hec/platform_logs
エクスポーターが削除されています。
どのような特定のエクスポーターが以前含まれていたかをどのように知ったか?それを見つけるには、
以前のカスタマイズを元に戻してから、config map を確認して
トレースパイプラインに元々何が含まれていたかを見ることもできました。あるいは、
splunk-otel-collector-chart の GitHub リポジトリ
の例を参照することもでき、これにより Helm チャートで使用されるデフォルトのエージェント設定が分かります。
これらのエクスポーターはどのように削除されたのか?
values.yaml
ファイルに追加したカスタマイズを確認しましょう:
logsEngine: otel
splunkObservability:
infrastructureMonitoringEventsEnabled: true
agent:
config:
receivers: ...
exporters:
debug:
verbosity: detailed
service:
pipelines:
traces:
exporters:
- debug
logs:
exporters:
- debug
helm upgrade
を使ってコレクターにvalues.yaml
ファイルを適用したとき、
カスタム設定は以前のコレクター設定とマージされました。
これが発生すると、リストを含むyaml
設定のセクション、
例えばパイプラインセクションのエクスポーターのリストは、values.yaml
ファイルに
含めたもの(debug エクスポーターのみ)で置き換えられます。
問題を修正しましょう
既存のパイプラインをカスタマイズする場合、設定のその部分を完全に再定義する必要があります。
したがって、values.yaml
ファイルを次のように更新する必要があります:
logsEngine: otel
splunkObservability:
infrastructureMonitoringEventsEnabled: true
agent:
config:
receivers: ...
exporters:
debug:
verbosity: detailed
service:
pipelines:
traces:
exporters:
- otlphttp
- signalfx
- debug
logs:
exporters:
- splunk_hec/platform_logs
- debug
変更を適用しましょう:
helm upgrade splunk-otel-collector \
--set="splunkObservability.realm=$REALM" \
--set="splunkObservability.accessToken=$ACCESS_TOKEN" \
--set="clusterName=$INSTANCE-cluster" \
--set="environment=otel-$INSTANCE" \
--set="splunkPlatform.token=$HEC_TOKEN" \
--set="splunkPlatform.endpoint=$HEC_URL" \
--set="splunkPlatform.index=splunk4rookies-workshop" \
-f values.yaml \
splunk-otel-collector-chart/splunk-otel-collector
それからエージェント config map を確認します:
kubectl describe cm splunk-otel-collector-otel-agent
今度は、ログとトレースの両方について完全に定義されたエクスポーターパイプラインが表示されるはずです:
pipelines:
logs:
exporters:
- splunk_hec/platform_logs
- debug
processors:
...
traces:
exporters:
- otlphttp
- signalfx
- debug
processors:
...
ログ出力の確認
Splunk Distribution of OpenTelemetry .NETは、ログに使用するアプリケーション
(サンプルアプリでも使用している)から、トレースコンテキストで強化されたログを自動的にエクスポートします。
アプリケーションログはトレースメタデータで強化され、その後
OpenTelemetry Collector のローカルインスタンスに OTLP 形式でエクスポートされます。
debug エクスポーターによってキャプチャされたログを詳しく見て、それが発生しているかを確認しましょう。
コレクターログを tail するには、次のコマンドを使用できます:
kubectl logs -l component=otel-collector-agent -f
ログを tail したら、curl を使ってさらにトラフィックを生成できます。そうすると
次のようなものが表示されるはずです:
2024-12-20T21:56:30.858Z info Logs {"kind": "exporter", "data_type": "logs", "name": "debug", "resource logs": 1, "log records": 1}
2024-12-20T21:56:30.858Z info ResourceLog #0
Resource SchemaURL: https://opentelemetry.io/schemas/1.6.1
Resource attributes:
-> splunk.distro.version: Str(1.8.0)
-> telemetry.distro.name: Str(splunk-otel-dotnet)
-> telemetry.distro.version: Str(1.8.0)
-> os.type: Str(linux)
-> os.description: Str(Debian GNU/Linux 12 (bookworm))
-> os.build_id: Str(6.8.0-1021-aws)
-> os.name: Str(Debian GNU/Linux)
-> os.version: Str(12)
-> host.name: Str(derek-1)
-> process.owner: Str(app)
-> process.pid: Int(1)
-> process.runtime.description: Str(.NET 8.0.11)
-> process.runtime.name: Str(.NET)
-> process.runtime.version: Str(8.0.11)
-> container.id: Str(5bee5b8f56f4b29f230ffdd183d0367c050872fefd9049822c1ab2aa662ba242)
-> telemetry.sdk.name: Str(opentelemetry)
-> telemetry.sdk.language: Str(dotnet)
-> telemetry.sdk.version: Str(1.9.0)
-> service.name: Str(helloworld)
-> deployment.environment: Str(otel-derek-1)
-> k8s.node.name: Str(derek-1)
-> k8s.cluster.name: Str(derek-1-cluster)
ScopeLogs #0
ScopeLogs SchemaURL:
InstrumentationScope HelloWorldController
LogRecord #0
ObservedTimestamp: 2024-12-20 21:56:28.486804 +0000 UTC
Timestamp: 2024-12-20 21:56:28.486804 +0000 UTC
SeverityText: Information
SeverityNumber: Info(9)
Body: Str(/hello endpoint invoked by {name})
Attributes:
-> name: Str(Kubernetes)
Trace ID: 78db97a12b942c0252d7438d6b045447
Span ID: 5e9158aa42f96db3
Flags: 1
{"kind": "exporter", "data_type": "logs", "name": "debug"}
この例では、Trace ID と Span ID が
OpenTelemetry .NET 計装によってログ出力に自動的に書き込まれていることがわかります。これにより、
Splunk Observability Cloud でログとトレースを関連付けることができます。
ただし、Helm を使って K8s クラスターに OpenTelemetry collector をデプロイし、
ログ収集オプションを含める場合、OpenTelemetry collector は File Log receiver を使用して
コンテナーログを自動的にキャプチャすることを覚えておいてください。
これにより、アプリケーションの重複ログがキャプチャされることになります。例えば、次のスクリーンショットでは
サービスへの各リクエストに対して 2 つのログエントリーが表示されています:

これをどのように回避しますか?
K8s での重複ログの回避
重複ログをキャプチャしないようにするには、OTEL_LOGS_EXPORTER
環境変数をnone
に設定して、
Splunk Distribution of OpenTelemetry .NET が OTLP を使用してコレクターにログをエクスポートしないようにできます。
これは、deployment.yaml
ファイルにOTEL_LOGS_EXPORTER
環境変数を追加することで実行できます:
env:
- name: PORT
value: "8080"
- name: NODE_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: "http://$(NODE_IP):4318"
- name: OTEL_SERVICE_NAME
value: "helloworld"
- name: OTEL_RESOURCE_ATTRIBUTES
value: "deployment.environment=otel-$INSTANCE"
- name: OTEL_LOGS_EXPORTER
value: "none"
それから次を実行します:
# update the deployment
kubectl apply -f deployment.yaml
OTEL_LOGS_EXPORTER
環境変数をnone
に設定するのは簡単です。しかし、Trace ID と
Span ID はアプリケーションによって生成された stdout ログに書き込まれないため、
ログとトレースを関連付けることができなくなります。
これを解決するには、
/home/splunk/workshop/docker-k8s-otel/helloworld/SplunkTelemetryConfigurator.cs
で定義されている例のような、カスタムロガーを定義する必要があります。
次のようにProgram.cs
ファイルを更新することで、これをアプリケーションに含めることができます:
using SplunkTelemetry;
using Microsoft.Extensions.Logging.Console;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();
SplunkTelemetryConfigurator.ConfigureLogger(builder.Logging);
var app = builder.Build();
app.MapControllers();
app.Run();
その後、カスタムログ設定を含む新しい Docker イメージをビルドします:
cd /home/splunk/workshop/docker-k8s-otel/helloworld
docker build -t helloworld:1.3 .
それから更新されたイメージを Kubernetes にインポートします:
cd /home/splunk
# Export the image from docker
docker save --output helloworld.tar helloworld:1.3
# Import the image into k3s
sudo k3s ctr images import helloworld.tar
最後に、deployment.yaml
ファイルを更新してコンテナーイメージの 1.3 バージョンを使用する必要があります:
spec:
containers:
- name: helloworld
image: docker.io/library/helloworld:1.3
それから変更を適用します:
# update the deployment
kubectl apply -f deployment.yaml
これで重複したログエントリーが排除されたことがわかります。そして
残りのログエントリーは JSON としてフォーマットされ、span と trace ID が含まれています:

Summary
2 minutes
このワークショップでは、以下の概念についてハンズオンで体験しました:
- Linux ホストにSplunk Distribution of the OpenTelemetry Collectorをデプロイする方法。
- Splunk Distribution of OpenTelemetry .NETで.NET アプリケーションを計装する方法。
- .NET アプリケーションを「Docker 化」し、Splunk Distribution of OpenTelemetry .NETで計装する方法。
- Helm を使用して Kubernetes クラスターにSplunk Distribution of the OpenTelemetry Collectorをデプロイする方法。
- コレクター設定をカスタマイズして問題をトラブルシューティングする方法。
他の言語と環境で OpenTelemetry がどのように計装されるかを確認するには、
Splunk OpenTelemetry Examples GitHub リポジトリをご覧ください。
将来このワークショップを独自に実行するには、これらの手順を参照して、Splunk Show のSplunk4Rookies - Observability
ワークショップテンプレートを使用して EC2 インスタンスをプロビジョニングしてください。