ADOT Collectorを使ってAmazon Managed Prometheusにメトリクスを飛ばし、Amazon Managed Grafanaでメトリクスを確認する

AWSブログ[AWS Distro for OpenTelemetry の Amazon EKS アドオンを使用したメトリクスとトレースの収集](https://aws.amazon.com/jp/blogs/news/metrics-and-traces-collection-using-amazon-eks-add-ons-for-aws-distro-for-opentelemetry/)のメトリクス収集部分を確認したかったので、実際に実機確認した時のメモ。

## やりたいこと

[こちら](https://aws.amazon.com/jp/blogs/news/metrics-and-traces-collection-using-amazon-eks-add-ons-for-aws-distro-for-opentelemetry/)のAWSブログにある構成に近いものを作って、EKS内にPrometheusを作らずにManaged Prometheusにメトリクスを飛ばし、Amazon Managed Grafanaでメトリクスを確認する。

![1655691812323.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/767b48cd-de99-0a32-cdc3-da615753a9b6.png)




## 前提条件
以下を満たしている必要がある。
- EKSのクラスターのk8sバージョンが1.19以降
- cert-managerを導入済み、かつversionが1.6**未満**
- EKSのAddon Manager用のRBAC設定

また、Amazon Managed PrometheusとAmazon Managed Grafanaが準備できている必要がある。こちらの準備方法は付録に記載した（大したこと書いてないけど）。

EKSは普通に作れば1.19以降なので割愛。
RBACに関しては[こちら](https://amazon-eks.s3.amazonaws.com/docs/addons-otel-permissions.yaml)にManifestが用意されているので、これをそのままapplyすると良い。

cert-managerはhelmが用意されているので、こちらでインストールすると良い。
https://cert-manager.io/docs/installation/helm/
自環境だと1.7.0だったため、ダウングレードを実施した。
```
$ helm list -n cert-manager
NAME        	NAMESPACE   	REVISION	UPDATED                             	STATUS  	CHART              	APP VERSION
cert-manager	cert-manager	1       	2022-02-04 11:26:40.968231 +0900 JST	deployed	cert-manager-v1.7.0	v1.7.0
$ helm upgrade -n cert-manager cert-manager jetstack/cert-manager --version v1.5.5
$ helm list -n cert-manager
NAME        	NAMESPACE   	REVISION	UPDATED                             	STATUS  	CHART              	APP VERSION
cert-manager	cert-manager	2       	2022-06-20 11:45:15.434281 +0900 JST	deployed	cert-manager-v1.5.5	v1.5.5
```


なお、古いChartのバージョンは[ここ](https://artifacthub.io/packages/helm/cert-manager/cert-manager)で確認した。\
また、新規にインストールする人はhelm install実行時に`--set installCRDs=true`をつけることをお忘れなく。


## ADOT Addonのインストール
ADOT Addonはawsコマンドでインストールする。
```
aws eks create-addon --addon-name adot --addon-version v0.45.0-eksbuild.1 --cluster-name $CLUSTER_NAME
```
実行直後は`"status": "CREATING"`が表示されるので、これが`ACTIVE`に変わるのを待つ(2、3分くらい待つ)。
確認のためのコマンドは以下。
```
aws eks describe-addon --addon-name adot --cluster-name $CLUSTER_NAME
```
なお、前提条件のRBACを設定していないと、以下のようなエラーになる。
```json
        "status": "CREATE_FAILED",
        "addonVersion": "v0.45.0-eksbuild.1",
        "health": {
            "issues": [
                {
                    "code": "AccessDenied",
                    "message": "customresourcedefinitions.apiextensions.k8s.io \"opentelemetrycollectors.opentelemetry.io\" is forbidden: User \"eks:addon-manager\" cannot patch resource \"customresourcedefinitions\" in API group \"apiextensions.k8s.io\" at the cluster scope"
                }
            ]
        },
```

## ADOT Collectorのインストール
メトリクスの収集はADOT Collectorというコンポーネントが実施する（下図）。


![1655694115888.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/eb77f296-b5d0-f43a-02ca-8ffa73cf1065.png)
※引用元：https://aws.amazon.com/jp/blogs/news/metrics-and-traces-collection-using-amazon-eks-add-ons-for-aws-distro-for-opentelemetry/

これは`OpenTelemetryController`というカスタムリソース(Addon追加時にインストールされる)で定義した情報を元にメトリクスを収集する。
```
$ kubectl api-resources  | grep OpenTelemetryCollector
opentelemetrycollectors           otelcol,otelcols                       opentelemetry.io/v1alpha1                          true         OpenTelemetryCollector
```
OpenTelemetryControllerで定義されたManifestが以下で公開されている。\
https://github.com/aws-observability/aws-o11y-recipes/blob/main/sandbox/eks-addon-adot/otel-collector-xray-prometheus-complete.yaml

このManifestではAWS X-Rayにトレースを送るTrace PipelineとManaged Prometheusにメトリクスを送るMetrics Pipelineが用意されているそうだ。\
中身を見ると、Prometheusのスクレイプ設定が入っていた。\
元ネタのブログで興味深い記述として、
>メトリクスパイプラインの Prometheus Receiver は、Prometheus サーバーの最小限の代替となることを目的としており、Prometheus クライアントライブラリでインストルメントされたマイクロサービスからメトリクスをスクレイピングすることができます。

とあり、Prometheusを立ててremote writeしなくても、Managed Prometheusにメトリクスを送れるようだ。

REGIONとWORKSPACEを置き換えれば動くようなので、sedで置き換える。WORKSPACEにはAMPのWorkspace IDを設定する。

```
wget https://raw.githubusercontent.com/aws-observability/aws-o11y-recipes/main/sandbox/eks-addon-adot/otel-collector-xray-prometheus-complete.yaml
sed -i "s/REGION/us-east-1/g" otel-collector-xray-prometheus-complete.yaml
sed -i "s/WORKSPACE/ws-xxxxx/g" otel-collector-xray-prometheus-complete.yaml
```
上記のManifestは`kind: OpenTelemetryCollector`が稼働するNamespaceが`aws-otel-eks`となっていたため、当該Namespaceを作成してopentelemetrycollectorをデプロイする。
```
kubectl create ns aws-otel-eks
kubectl apply -f otel-collector-xray-prometheus-complete.yaml
```

デプロイ後、リソースは以下の用に表示される。
```
$ kubectl get opentelemetrycollector.opentelemetry.io/observability -n aws-otel-eks
NAME            MODE         VERSION   AGE
observability   deployment   0.45.0    50s
```
ただし、このタイミングではManifest内で指定していた`aws-otel-collector`というServiceAccountがないため、Podの起動に失敗する。
```
$ kubectl get all  -n aws-otel-eks
NAME                                         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/observability-collector              ClusterIP   10.100.232.27   <none>        2000/UDP   6m58s
service/observability-collector-headless     ClusterIP   None            <none>        2000/UDP   6m58s
service/observability-collector-monitoring   ClusterIP   10.100.7.243    <none>        8888/TCP   6m58s

NAME                                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/observability-collector   0/1     0            0           6m59s

NAME                                                DESIRED   CURRENT   READY   AGE
replicaset.apps/observability-collector-d4c8b8d6d   1         0         0       7m
```
そのため、[こちら](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/adot-iam.html)のページを参考に必要な権限を持ったServiceAccountを作成する。\
※[ヘルパースクリプト](https://github.com/aws-observability/aws-o11y-recipes/blob/main/sandbox/eks-addon-adot/adot-irsa.sh)を見逃していたので以下の手順でやっているが、ヘルパースクリプトを流す方が早いかもしれない。

```
eksctl create iamserviceaccount \
    --name aws-otel-collector \
    --namespace aws-otel-eks \
    --cluster ${CLUSTER_NAME} \
    --attach-policy-arn arn:aws:iam::aws:policy/AmazonPrometheusRemoteWriteAccess \
    --attach-policy-arn arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess \
    --attach-policy-arn arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy \
    --approve \
    --override-existing-serviceaccounts
```
なお、自分の環境ではServiceAccountが存在しないにも関わらず、以下のように表示されて作成が上手く行かなかった。
```
2022-06-20 16:22:00 [ℹ]  1 iamserviceaccount (aws-otel-eks/aws-otel-collector) was excluded (based on the include/exclude rules)
2022-06-20 16:22:00 [!]  metadata of serviceaccounts that exist in Kubernetes will be updated, as --override-existing-serviceaccounts was set
2022-06-20 16:22:00 [ℹ]  no tasks
```
この場合、`eksctl delete iamserviceaccount`を実行して、再度createすると成功する。

作成した結果がこちら。
```
$ kubectl get sa -n aws-otel-eks
NAME                      SECRETS   AGE
aws-otel-collector        1         88s
default                   1         31m
observability-collector   1         30m
```
ServiceAccount作成後、ReplicaSetを削除して、Podの再作成を促す。
```
kubectl delete replicaset.apps/observability-collector-d4c8b8d6d 
```

これでADOT Controllerが起動した。
```
$ kubectl get all  -n aws-otel-eks
NAME                                          READY   STATUS    RESTARTS   AGE
pod/observability-collector-d4c8b8d6d-8wjbt   1/1     Running   0          38s

NAME                                         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/observability-collector              ClusterIP   10.100.232.27   <none>        2000/UDP   32m
service/observability-collector-headless     ClusterIP   None            <none>        2000/UDP   32m
service/observability-collector-monitoring   ClusterIP   10.100.7.243    <none>        8888/TCP   32m

NAME                                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/observability-collector   1/1     1            1           32m

NAME                                                DESIRED   CURRENT   READY   AGE
replicaset.apps/observability-collector-d4c8b8d6d   1         1         1       42s
```
AWSブログの図の通りであれば、既にメトリクスはManaged Prometheusに届いており、Managed Grafanaからも見れるはずだ。

## 動作確認
Amazon Grafanaにログインして、メトリクスが取れているか確認する。\
左のExploreから`kubelet_node_name`でクエリを発行すると、ノード名が取得できた。
![1655717168849.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/43fd728b-8fec-2e30-f7f9-b624b6267dd4.png)



## 付録：Amazon Managed Prometheus、Amazon Managed Grafanaの準備
### Amazon Managed Prometheusの準備
AMPにアクセスし、「ワークプレイスを作成」で作成するだけ。\
なお、メトリクスのストレージ的な機能しか持っていないので、expression browserは使用できない。\
（試しに/graphにアクセスしてみたが、`{"message":null}`が返ってくるだけだった）

### Amazon Managed Grafanaの準備

Amazon Managed Grafanaを使うにはAWS SSOもしくはSAMLが必要となる。
AWS SSOは敷居が高いので、Auth0の無料アカウントを使ってSAMLにて設定した。
SAMLの利用に関しては[こちら](https://dev.classmethod.jp/articles/login-with-auth0-saml-for-amazon-managed-grafana/)を参考にした。
参考にしたサイトが詳しいので設定方法は割愛する。

設定してログインすると、このような画面が表示される。
![1655716334404.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/c034f4ed-b145-8776-fe93-a4404c4faa46.png)

初期設定ではダッシュボードは空である。\
左のAWSのアイコンからData sourcesをクリックし、ServiceでAMPを選択、RegionsでAMPのworkspaceがあるリージョンを選択すると、AMPのworkspaceが表示されるのでAddして初期設定は終了となる。
![1655716477174.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/dea4426d-12d0-e6f5-e116-383c1aba900b.png)