GKE上のOpenTelemetry DemoアプリケーションをさくっとElasticでAPM・ログ・インフラ+eBPFプロファイリング監視する

# はじめに
こちらのOpenTelemetry Demoを使うと、簡単にKubernetes上でアプリケーションを動かして、そしてElasticオブザーバビリティ機能を色々試すことができます。
https://opentelemetry.io/docs/demo/kubernetes-deployment/

本記事はGKEを使い、そのやり方をまとめました。

# 手順

## GKEクラスタ作成とOtel Demoアプリのデプロイ
以下でGKEクラスタ作ります。Otel Demoアプリのデプロイは上のDemoアプリドキュメントの通りに行います。
```:sh
CLUSTER_NAME=nobu-test-cluster
REGION=us-east4
gcloud container clusters create $CLUSTER_NAME --region=$REGION
gcloud components install gke-gcloud-auth-plugin
gcloud container clusters get-credentials $CLUSTER_NAME --region=$REGION
kubectl get namespaces

helm repo add open-telemetry https://open-telemetry.github.io/opentelemetry-helm-charts
helm install $CLUSTER_NAME open-telemetry/opentelemetry-demo
kubectl get deployments
```
## Elastic Cloudへの接続情報を取得
KibanaのAPM画面からAdd dataをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/46de42f3-5fd5-4a1f-08a5-878a29879717.png)

OTEL_EXPORTER_OTLP_ENDPOINT と OTEL_EXPORTER_OTLP_HEADERSの値をコピーしてメモしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/17ea9390-ae5d-5ad5-476e-bdf70adfaf9e.png)

## DemoアプリのOTel CollectorにElasticへの接続を反映
以下のHelmのvaluesファイルを作成してください。メモしておいたURLとトークンを下の`<ELASTIC_APM_SERVER_URL>`と`<ELASTIC_APM_SECRET_TOKEN>`へ置き換えてください。(トークンは: Authorization: "Bearer QlXHQrkIEFY6IMiNCl"　のような形となります。)
```:my-values-file.yaml
default:
  envOverrides:
    - name: OTEL_RESOURCE_ATTRIBUTES
      value: service.name=$(OTEL_SERVICE_NAME),service.namespace=opentelemetry-demo,deployment.environment=sample-GKE

opentelemetry-collector:
  config:
    exporters:
      otlphttp/elastic:
        endpoint: "<ELASTIC_APM_SERVER_URL>"
        headers:
        # Elastic APM Server secret token
          Authorization: "Bearer <ELASTIC_APM_SECRET_TOKEN>" 

    service:
      pipelines:
        traces:
          receivers: [otlp]
          processors: [batch]
          exporters: [otlphttp/elastic]
        metrics:
          receivers: [otlp]
          exporters: [logging, otlphttp/elastic]
        logs: 
          receivers: [otlp]
          exporters: [logging, otlphttp/elastic]
```

以下のコマンドで上記の設定をKubernetesに反映させます。
```:sh
helm upgrade $CLUSTER_NAME open-telemetry/opentelemetry-demo --values my-values-file.yaml
```

数分すれば、以下のようにAPM画面でデータが確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/e6ce2af8-e105-3f9f-2a17-05bd5b5af4a0.png)


# Elastic Agentのインストール
上記にてOpenTelemetryのテレメトリーはElasticに取り込むことができました。
さらにElastic Agentを監視対象のKubernetesクラスタのDaemonsetとしてインストールすることで、Kubernetesの各種メトリクスや、コンテナログを収集することができます。

Elastic Agentのインストールは、Fleet機能で集中管理するタイプと、スタンドアロンで集中管理しないタイプがあります。今回はさくっとできるスタンドアロンでの手順です。以下のドキュメントを参照しています。
https://www.elastic.co/guide/en/fleet/current/running-on-kubernetes-standalone.html

その前に、Kubernetes用のダッシュボードなどのアセットをElastic Cloud側にインストールするため、以下のIntegrationsのKubenretesのSettingsからアセットをインストールしてください。（これは一度だけの作業です）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/c3ef07e9-0815-0d67-4c12-063d9e1bc7fa.png)

その後、Elastic Agentのインストール手順を実施していきます。
Kubernetesのメトリック収集のために以下を実施
```
git clone https://github.com/kubernetes/kube-state-metrics.git
kubectl apply -k kube-state-metrics
```

Elastic AgentをKubernetesに入れるためのデプロイメントファイルをダウンロードします。
```
curl -L -O https://raw.githubusercontent.com/elastic/elastic-agent/8.11/deploy/kubernetes/elastic-agent-standalone-kubernetes.yaml
```
ダウンロードしたファイルを開き、以下の部分のES_USERNAME, ES_PASSWORD, ES_HOSTに値を入れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/cd722659-098e-97f1-0b6a-e50bd9da0a3b.png)

ES_HOSTに入れるURLはこちらから取得できます。ESのユーザーは手っ取り早くやるならElastic Cloudのデプロイメントを作成した時に表示されたelasticユーザーとそのパスワードを使うことができます。（その他のやり方としてCloud IDやAPIキーを使うことも可能です）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/aee89ed5-b881-de99-5710-e912fb30fede.png)

以下でElastic AgentをDaemonsetとしてデプロイします。
```
kubectl create -f elastic-agent-standalone-kubernetes.yaml
kubectl -n kube-system get pods
```

無事にデプロイが成功したら、データが取り込まれるので、ElasticのDashboardメニューから色々なKubernetesのダッシュボードにメトリックスが表示されるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/2869bfaa-9ba1-4bee-c93f-5b704c3b602a.png)

## APMからログの相関を見る
Elastic Agentを入れると、自動的にOpenTelemetryで収集している情報と紐づきが行われます。

例えば、APM（アプリ）の各サービスのInfrastructureタブからそれが属するPodやk8sのノード（Host)の情報を見ることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/66753449-5a9b-cfee-9e64-b1a00023d060.png)

**Podのメトリクス**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/812a0b26-23d1-3a61-935a-110237f3d3e8.png)

**Hostのメトリクス**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/2473f3b6-6482-4c85-805f-9c039d34503b.png)

**Hostのログ**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/5cc1521d-d8ae-287e-725d-0a399eda1307.png)

**コンテナログ**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/0ad0b228-3b85-c190-897b-9379e31790ce.png)

**APMトレースから、コンテナログに飛ぶこともできます**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/9c009fa2-00c4-ba36-bbf0-6c5dbef33696.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/d6c9df2f-9e2b-f557-4615-5279cac40ccd.png)

 ## eBPF Profiling
必要に応じてUniversal Profilingの機能も簡単にインストールできました。
Universal Profilingメニューで表示される手順を実施するだけです。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/7b45bccb-a330-7e00-f7c8-fb7e22174f78.png)

```
helm repo add elastic https://helm.elastic.co

helm install --create-namespace -n=universal-profiling universal-profiling-agent \
--set "projectID=1,secretToken=qsaJN8eynrQxQQea" \
--set "collectionAgentHostPort=xxxxxxx.profiling.us-west1.gcp.cloud.es.io:443" \
--set "version=8.11.1" \
--version=8.11.1 \
elastic/pf-host-agent

kubectl -n universal-profiling get pods
```
詳しくは解説しませんが、このようにKubernetesのホスト・コンテナ両方のプロセスのスタックトレースを低負荷で取得できます。それにより、CPUを使っているプロセスとその内部のコード箇所まで追うことが可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109197/f37be6c9-2886-e842-66a7-25e8225f6682.png)

以上