Amazon Web Services ブログ

AWS X-Ray を使った Istio 仮想サービスのトレースの可視化

この記事は Sourav Paul による“Ship and visualize your Istio virtual service traces with AWS X-Ray”(2020/12/07投稿)を翻訳したものです。

分散トレースは、リクエストがシステムコンポーネントの中をどのように通過するのかを追跡したり、呼び出したサイトで主要なパフォーマンス指標をキャプチャすることで、分散システムの実行時のパフォーマンスインサイトを導き出すメカニズムです。このメカニズムはトラフィックの健全性とともに動的なサービスの依存関係を表し、サービスのオーナーやクラスター管理者が、アプリケーションの状況を迅速に可視化、パフォーマンスのボトルネックの特定、サービスの課題をプロアクティブに対処することに役立ちます。

しかしながら、トレーシングプラットフォームがもたらすメリットにもかかわらず、分散トレースの技術スタックをプロダクションレディにセルフマネージドできるようなるまでには、かなりのエンジニアリング作業が必要です。分散トレースのセットアップには少なくとも共通して次の手順が必要です。

  • 計測アプリケーションコード(手動または計測ライブラリ)を使用して、サービス間の呼び出し全体でトレース関連のヘッダを伝播します。
  • アプリケーションからコレクタエンドポイントまでのトレースをエクスポートするためのライブラリをパッケージ化および設定します。
  • トレースを受信し、永続レイヤーに転送できるコレクタをデプロイします。
  • トレースの永続化のためにデータストアをデプロイします。
  • API とUI 可視化コンポーネントをデプロイして、オペレータが永続化されたトレースにクエリし、実用的なインサイトを抽出できるようにします。

アプリケーション開発者は常にコードを計測して、ヘッダを使ってトレースコンテキストを伝播する必要がありますが、Istio のようなサービスメッシュを使用すると、一般的なトレースバックエンド用のエクスポータをサービスプロキシに埋め込めるため、アプリケーション開発者の負担を軽減します。サービスプロキシはアプリケーションプロセスの側で常駐し、すべてのネットワーク通信を傍受します。全ての送受信リクエストのスパンを自動的にパブリッシュできるようにプロキシを設定できます。このアプローチの利点は次の通りです。

  • アプリケーションは適切なコンテキストの伝播のみを担当し、サービスメッシュプロキシは設定されたコレクタエンドポイントにトレースをパブリッシュすることを担当します。
  • サービスメッシュ管理者は、サービスメッシュのコントロールプレーンの設定の一部として、トレースエージェント関連の設定を 1 か所で適用できます。

それでも、Open Zipkin のような一般的なオープンソースのトレースバックエンドの永続化と UI 可視化レイヤーを設定するには、データストアと Spark の依存関係を設定して微調整する必要があります。このため、多くの DevOps 作業に時間を費やします。

セルフマネージドのデプロイから AWS に移行されるお客様は、フルマネージドソリューションを使うことで、差別化につながらない重労働のエンジニアリング作業をオフロードする方法を探します。分散トレースに関しては、フルマネージドで提供される AWS X-Ray を使うことで DevOps チームを忙しい作業から解放し、イノベーションに集中できるようになります。

分散トレースに加えて、重要な本番システムではメトリクスやログ収集のような他のテレメトリ関連にも対処しなければいけません。多くの場合、これらのソリューションには独自のエージェント/コレクタの実装が存在するため、エージェントとコレクタが運用環境に導入されますが、それぞれ独自の仕様とプロトコル要件があり、他のバックエンドをサポートするためには簡単に移植できない可能性があります。Prometheus によってメトリクスが取り込まれ、Elasticsearch にログが送信され、Open Zipkin にトレースが送信される本番環境について考えてみてください。EMF カスタムメトリクスベースの CloudWatch Logs の取り込みを導入するには、すでに複雑に入り混じったその環境に追加エージェントが必要です。これは Cloud Native Computing Foundation (CNCF) の下でのオープンソースイニシアチブである OpenTelemetry プロジェクトにおける中心の問題で、テレメトリデータの生成、処理、取り込みに関する標準仕様とリファレンス実装を提供することで解決しようとしています。OpenTelemetry Collector サブプロジェクトは単一の統合されたベンダーに依存しないコレクタアーキテクチャで、受け取った標準メトリクス、ログ、トレースを複数のソースから受け取ることができ、受信データを変換/拡充でき、複数のバックエンドにエクスポートする複雑なデプロイもシンプルにできます。

この記事では、Istio 上で動作している既存の Open Zipkin 計測アプリケーションを AWS に移行し、AWS X-Ray のマネージドな体験を楽しむ方法を紹介します。このソリューションでは OpenTelemetry Collector プロジェクトが提供する柔軟性を活用し、Open Zipkin フォーマットされたスパンを AWS X-Ray セグメントに変換します。

読む時間 12 分
完了までの時間 45 分
完了コスト(見積もり) $ 0.686
学習レベル Expert (400)
利用サービス

Amazon Elastic Kubernetes Service (EKS)

Amazon Elastic Container Registry (ECR)

AWS X-Ray

Amazon EC2

AWS CloudFormation

AWS IAM

ソリューションの概要

コレクタのアーキテクチャはプラガブルなレシーバー、プロセッサ 、エクスポータで構成されており、それらを組み合わせることでパイプラインを形成できます。 メトリックやトレースイベントはレシーバーを介してパイプラインに入り、0以上のプロセッサ を通過し、最後に1つ以上のエクスポータを介してパイプラインは終了します。レシーバーはソースデータ形式のワイヤプロトコルを実装しています。例えば、opentelemetry-collector プロジェクトの zipkin レシーバーは JSON 形式の Zipkin v1 または v2 スパンを OpenTelemetry 内部の表現にデコードするエンドポイントを公開しています。一方、エクスポータはターゲットバックエンド用にワイヤ転送プロトコルを実装しています。コレクタリポジトリは Zipkin 、Jaeger 、Prometheus 、Kafka などのような一般的なオープンソースのバックエンドのエクスポータもホストしています。また、 OpenCensus や OTLP のようなオープン形式にエクスポータも提供します。opentelemetry-collector-contrib リポジトリは商用ベンダーの実装のためのコンパニオンリポジトリです。例えば、Contrib リポジトリの中の awsxrayexporter モジュールはパイプイプラインで受け取った内部トレーススパンを AWS X-Ray のセグメントドキュメントに変換し、設定された AWS X-Ray エンドポイントにドキュメントをポストします。

このアーキテクチャでは、Contrib プロジェクトからベンダー実装を参照することにより、新しいコンポーネントをコレクタバイナリにリンクできます。コレクタイメージは、任意の数のバックエンドとレシーバーに接続した1つ以上のパイプライン構成を使用して、スタンドアロンの Kubernetes の Deployment としてデプロイできます。

このソリューションでは、Zipkin スパンをコレクタエンドポイントにパブリッシュする Istio がセットアップされた EKS クラスターにカスタムコレクタのバイナリをデプロイする必要があります。そのコレクタは、スパンを取り込み、AWS X-Ray にエクスポートする単一のパイプライン定義として設定されます。また、コレクタログ内のスパンの内部表現を簡単に表示できるようにロギングエクスポータも設定されます。

この執筆時点の Istio プロキシ( Istio version 1.7.4)内に組み込まれた Zipkin トレーサーは OpenTelemetry semantic conventions に準拠していません。そのため、AWS X-Ray で正しく属性を識別できるようにするためには、いくつかのスパン属性を OpenTelemetry リソース属性に変換する必要があります。このソリューションで使われるパイプラインはopentelemetry-collector リポジトリの zipkin レシーバーモジュールと opentelemetry-collector-contrib リポジトリのawsxrayexporterモジュール をセットアップします。opentelemetry-collector-contrib リポジトリがフォークされ、変換のテストを追加するために、フォークしたリポジトリ内に新しくistio-build ブランチを作成します。otelcol-custom-istio-awsxray リポジトリ内のメンテナンスされたコレクタバイナリプロジェクトは、そのフォークされたリポジトリからカスタム変換を取り出します。

詳細

Collector Contrib のカスタマイズ

awsxrayexporter モジュールのトレースID のマッピングロジックは、Trace ID フィールドのインメモリキャッシュの導入によってアップデートされました。AWS X-Ray では、トレースが開始されたときのエポックタイムを秒単位で埋め込むために、セグメントドキュメントにtrace_id が必要です。一方、Istio の Zipkin tracertraceId フィールドとしてランダムに生成された128 bit のユニークな識別子であることを想定しています。現状のデフォルトの挙動では、上位32 bit が許可されたエポックウィンドウ内にあるかどうかをチェックし、トレース ID をエポックセクションにマップします。上位32 bit が許可されたウィンドウの外にある場合、エクスポータはスパンをドロップします。拡張機能では有効なウィンドウの外側のエポックを含む Trace ID を取得し、セグメントの開始時間からエポックを計算してアップデートします。このエポックは同じトレース内で発生する後のセグメントのためにキャッシュされます。もしセグメントの開始時間が見つからなかったら、現在のエポックが取得され、あとで参照するためにキャッシュされます。キャッシュの TTL のデフォルト値は60秒ですが、デモのデプロイしたようにエクスポータの設定を使用して設定できます。

エクスポータの設定はキャッシュプロバイダーの設定も許可されるようにアップデートされています。現在の実装はプロセス内のスレッドセーフキャッシュに基づいたシンプルな TTL が使われており、キャッシュ同期の問題を回避するためにコレクタのインスタンスが1つ必要です。大規模なクラスター内のテレメトリの取り組みを複数のコレクタインスタンスで負荷分散できるようにするために、実装を拡張し、プロセス内もしくは Amazon ElastiCache for Redis のような外部にクラスターキャッシュを導入できます。

次の変更セットはスパンの upstream_cluster 属性を参照しています。Istio プロキシが生成したスパンは常に、トラフィックの方向に関係なく、 span.kindCLIENT に設定定されます。エクスポータと X-Ray サービスは span.kind が SERVER に設定されたものを着信トラフィックとして認識するため、この挙動は混乱を生みます。(この span.kind の動作は他のバックエンドを混乱させる可能性があり、またカスタムコレクタはアップストリームでリリースできるようになるまでそのようなバグを回避できます。)この場合、 upstream_cluster 属性を紐解くことで解決しています。この属性はスパンが着信トラフィックまたは発信トラフィックかどうか、またサービスポートや、リモート/ローカルサービスの FQDN など、その他の詳細情報をキャプチャします。例えば、クライアントからアップストリームサービスへの発信トラフィックの upstream_cluster 属性値はoutbound|9080||productpage.default.svc.cluster.local
のようになります。サーバーサイドでは、着信トラフィックに対応する upstream_cluster 属性値は inbound|9080|http|productpage.default.svc.cluster.local のようになります。

変更の詳細についてはフォークされたリポジトリの istio-build ブランチを参照してください。

Collector builder

カスタムコレクタのバイナリは otelcol-custom-istio-awsxray プロジェクトを通じてビルドされています。このプロジェクトはこちらで用意されている手順に基づいてモデル化されています。プロジェクトはコレクタ Contrib リポジトリから awsxrayexporter モジュールを取り込みますが、モジュールのアップストリームバージョンを直接参照する代わりに istio-build ブランチ からローカルにチェックアウトされたバージョンでモジュールリンクを置き換えます。

イメージをビルドし、タグ付けし、選択したリモートレジストリにプッシュし、コレクタをデプロイし、Istio をインストールします。そしてサンプルアプリケーションをデプロイして、AWS X-Ray に流れるトレースフローを確認します。

チュートリアル

前提条件

このチュートリアルでは、次の前提条件が必要です。

  • AWS アカウント
  • IAM ユーザー
  • ワークステーション
    • ECR や EKS などのサービスを操作するための AWS CLI v2
    • ソリューションリポジトリをクローンするための git
    • コレクタイメージをビルドするための Docker エンジン
    • EKS のコントロールプレーンの操作、コントローラーや istio サービスメッシュをデプロイするために、サーバーバージョンと互換性がある kubectl
  • このチュートリアルでは、Istio サービスメッシュ、分散トレースの概念、および AWS X-Ray に関する基本的な知識があることを前提としております。

EKSクラスターの作成

このセクションでは、IAM のセットアップと EKS クラスターを作成します。

  1. IAM コンソールにログインします。
  2. CloudFormation テンプレートの起動に使用するロールを作成します。
    このロールは CloudFormation テンプレートで作成された EKS クラスターへの管理者権限が付与されます。このデモでは、AdministratorAccess パーミッションが付与された admin という名前のロールが作成されます。新しいロールは Require MFA が有効になっておりますので、注意してください。

  3. ロールが作成できたら、新しいロールを参照するように CLI プロファイル (~/.aws/credentials) をアップデートしてください。もし MFA が必要な場合は、assume ロールを使う IAM ユーザーの MFA デバイスシリアルも追記してください。
  4. コンソールから新しいロールを引き受けます。

  5. ローカルのワークスペースに otelcol-custom-istio-awsxray リポジトリをクローンします。
    cd ~
    mkdir -p github.com/iamsouravin
    cd github.com/iamsouravin
    git clone https://github.com/iamsouravin/otelcol-custom-istio-awsxray.git
  6. CloudFormation のコンソールに移動します。
  7. Create Stack を選択します。
  8. Create stack ページでは Specify template にある Upload a template file を選択し、Choose file ボタンをクリックします。
  9. ワークスペースにクローンされたファイルの中か docs/examples/base-cfn.yaml テンプレートファイルを選択します。
  10. スタックの名前を入力します。このデモでは otelcol-custom-istio-awsxray-demo としています。パラメータを確認または更新します。
  11. Configure stack options ページではデフォルト値のままにします。
  12. Review ページでは選択内容を確認し、スタックによってIAM リソースが作成される場合があることを承認します。
  13. スタックの作成を開始するためにCreate stack をクリックします。
  14. スタックの作成に時間が掛かるため、このタイミングで、休憩をとったり、好きな飲み物を楽しむ時間としてください。
  15. スタックが作成されたらターミナルに切り替え、クラスターに接続できるように以下のコマンドでローカルの kubeconfig ファイルを更新します。
    aws eks update-kubeconfig --name tracing-cluster --region us-east-1 --profile admin-role

  16. クラスターへ接続ができること、またノードが準備できていることを確認します。
    kubectl cluster-info
    kubectl get nodes

カスタムコレクタバイナリのビルド

このステップではカスタムコレクタバイナリをビルドします。

  1. ビルドスクリプトスクリプト(bin/build.sh) は docker ビルドを実行する前にフォークされた Collector Contrib リポジトリをローカルにクローンして、プロジェクトのディレクトリにある awsxrayexporter モジュールをコピーします。タグ引数(-t)を指定してビルドを起動します。
    ビルドにかかる時間はインターネット帯域幅、ビルドするマシンコア、ボリュームタイプ(SSD or HDD)などの様々な要因に依存します。

インストールとテスト

このステップではカスタムコントローラバイナリ、Istio 、サンプルアプリをインストールして、end-to-end のインテグレーションテストを実施します。

  1. 生成されたマニフェストファイル(docs/examples/otelcol-custom-istio-awsxray-manifest.yaml)を開き、イメージタグが新しく構築されたイメージを参照していることを確認します。
  2. リモートの Docker レジストリにログインし、イメージをプッシュします。
  3. デモ目的のため、プロキシによって生成されるトレースのサンプリングレートはデフォルトで100%に設定しています。この設定は docs/examples/tracing.yaml の中にあります。これは本番環境向けの設定ではありません。通常、本番環境においてはサンプリングレートを1%より低い値に設定します。
  4. インストーラスクリプト (bin/install-components.sh)を実行して、以下の内容を実行します。
    • クラスターにコレクタをインストールします。
    • Istio の1.7.4 リリースバージョンをダウンロードし、インストールします。
    • 自動プロキシインジェクションを有効にするために default のネームスペースをラベル付けします。
    • Istio サンプルディレクトリから書籍情報アプリをインストールして、公開します
  5. スクリプトの出力から /productpag のゲートウェイURLを取得します。
  6. プロダクトページの URL をブラウザで開いて何回か再読み込みしてください。すると3つの異なるバージョン間でレビューセクションが切り替わっていることに気づくかと思います。また、ダミーユーザーの認証情報を使用して、ログインやログアウトをしばらく繰り返してください。
  7. もしブラウザでページがロードされなかったら、ELB が EC2 インスタンスをターゲットとして登録しているところかもしれません。数分待つか、EC2 コンソールでロードバランサーの登録状況を確認してください。
  8. AWS X-Ray のコンソールに移動して、サービスマップの視覚化を確認します。
  9. traces ペイン を開き、個々のセグメントをドリルダウンします。
  10. Bookinfo アプリケーションによって公開された API エンドポイントに対して Postman やプレーンの curl などのクライアントを使うことで、サービスマップの中でトレースリンクがアップデートされるのを確認できます。
    • http://{{ISTIO_INGRESS_HOST}}/api/v1/products
    • http://{{ISTIO_INGRESS_HOST}}/api/v1/products/0
    • http://{{ISTIO_INGRESS_HOST}}/api/v1/products/0/reviews
    • http://{{ISTIO_INGRESS_HOST}}/api/v1/products/0/ratings

クリーンアップ

今後の課金が発生しないように全てのリソースを削除します。

  1. アンインストールスクリプト(bin/uninstall-components.sh) を実行、インストールスクリプトによってインストールされたコンポーネントをアンインストールします。
  2. ECR は空でないリポジトリを削除することができません。otelcol-custom-istio-awsxray リポジトリにプッシュしたイメージを削除してください。
    aws ecr batch-delete-image --repository-name otelcol-custom-istio-awsxray --image-ids imageTag=0.1.0 --region us-east-1
  3. 最後に CloudFormation コンソールのスタックを削除することで残ったリソースをクリーンアップします。

結論

この記事では、AWS 上で、Istio サービスメッシュから生成されたトレースをマネージドなバックエンドとして AWS X-Ray を活用する追加オプションを説明しました。このソリューションのデモは OpenTelemetry コレクタプロジェクトがどのように新しいインテグレーションの可能性を切り開き、DevOps チームに対して、特定の組織の要件に基づいてパーツを選択し、カスタマイズできる完全な柔軟性を提供しています。コミュニティがテレメトリデータを収集する標準的なアプローチに移行するにつれ、様々なプロダクト間の整合性が向上し、よりシームレスなインテグレーションをサポートし、この記事で示したカスタマイズの大部分が不要になります。このインテグレーションを紹介できることを嬉しく思っております。お客様がこのソリューションを活用、拡張していくことを楽しみにしております。

翻訳はソリューションアーキテクト多田 慎也が担当しました。原文はこちらです。