Kubernetes環境とアプリケーションの相関トレーシング

# はじめに
この投稿では、Kubernetesの流動的なアプリ実行環境において、New Relic APMでどのようにアプリケーションの稼働情報のトレースを行うかについて解説します。

# 背景と目的
サービス需要に応じた柔軟なリソースのアロケーションを実現する半面、流動的にアプリケーションの稼働環境が切り替わるKubernetes環境。

同環境において、アプリケーションのエラートレースに求められるのはエラーの内容を追うだけでなく、当該アプリケーションがどこで稼働しているかを的確に把握することです。アプリの稼働環境がどのホスト、どのポッド、どのコンテナなのかを把握することで、デバッグやトラブルシューティングを迅速に行うことができます。

New Relicでは、監視対象のアプリケーションが稼働するサーバ or コンテナを検知する機能がデフォルトでありますが、これはあくまでリアルタイムの稼働情報。エラーを出したアプリが10分前、30分前の障害時に同じ環境にあったとは限りません。

しかし、KuberenetesのDownward APIとNew Relic Agent APIを組み合わせることで、New Relic APM Agentが取集するアプリケーションのメトリクスに、Kubernetesのオーケストレーションレイヤ情報(Pod、Host IP、Namespace etc…)をカスタムパラメータとして付与することができます。

これによって、例えばどのPod、どのホスト上のアプリケーションがエラーを起こしたかをエラー内容とともに記録し、把握することができます。

次項からは同設定の要素技術を解説しつつ、流動的なKubernetes環境におけるNew Relic APMを用いたアプケーションエラートレース方法について解説していきたいと思います。

なお、Sample Applicationとして、New Relic社のCray Smith氏が作成した[Node.jsアプリケーション](https://github.com/smithclay/newrelic-k8s-guestbook)を使用します。

# Downward APIの定義
[Kubernetes Downward API](https://kubernetes.io/docs/tasks/inject-data-application/environment-variable-expose-pod-information/)によって、コンテナが自身の稼働するクラスターやポッドに関する情報を取得できるようになります。Downward APIでは環境変数を介して、コンテナにポッドの情報などを渡すことが可能です。

設定方法はアプリケーションマニフェストファイルのenvセクションに環境変数として登録したいオーケストレーションレイヤの情報を追記します。今回はKubernetesノード名、ホストIP、ポッド名、ポッドネームスペース、ポッドIP、およびポッドサービスの各情報をコンテナ上のアプリケーションが認識できるように追記します。

```yaml:k8s/guestbook-all-in-one.yaml
        env:
        - name: K8S_NODE_NAME
          valueFrom:
            fieldRef:
              fieldPath: spec.nodeName
        - name: K8S_HOST_IP
          valueFrom:
            fieldRef:
              fieldPath: status.hostIP
        - name: K8S_POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: K8S_POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: K8S_POD_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        - name: K8S_POD_SERVICE_ACCOUNT
          valueFrom:
            fieldRef:
              fieldPath: spec.serviceAccountName
```

# New Relic Agent APIの設定
次にNew Relic エージェントAPIを用いて、カスタムパラメータの設定を行います。[Sample Application](https://github.com/smithclay/newrelic-k8s-guestbook)はNode.jsで書かれているため、今回は[New Relic Node.jsエージェントAPI](https://newrelic.nissho-ele.co.jp/support/docs/agent/nodejs-agent/supported-features/nodejs-agent-api)を使用した場合の例を記載します。

下記のコードをアプリケーションファイルに追記することで、監視対象アプリケーション内の全トランザクショントレースに、カスタムパラメータとしてDownward APIで指定した値を付与します。newrelic.addCustomParameters（）は、Kuberenetesのメタデータですべてのexpress.js Webの変換（およびエラー）をアノテーションするために使用されます。

```js:node-redis/index.js
var CUSTOM_PARAMETERS = {
    'K8S_NODE_NAME': process.env.K8S_NODE_NAME,
    'K8S_HOST_IP': process.env.K8S_HOST_IP,
    'K8S_POD_NAME': process.env.K8S_POD_NAME,
    'K8S_POD_NAMESPACE': process.env.K8S_POD_NAMESPACE,
    'K8S_POD_IP': process.env.K8S_POD_IP,
    'K8S_POD_SERVICE_ACCOUNT': process.env.K8S_POD_SERVICE_ACCOUNT,
    'K8S_POD_TIER': process.env.K8S_POD_TIER
};

app.use(function(req, res, next) {
  newrelic.addCustomParameters(CUSTOM_PARAMETERS);
  next();
});
```

#　APM Error Analyticsによるエラートレース
上記設定を施したアプリケーションを、Kubernetes上にデプロイします。
APM Error Analytics画面でエラーの内容を見てみると、アトリビュートとしてPodの情報やホストの情報が表示されるようになりました。

￼![スクリーンショット 2017-12-19 12.49.59.png](https://qiita-image-store.s3.amazonaws.com/0/150903/ebc6385d-40b0-2d89-c7e5-244e59070fe6.png)

また、APM Error Profileでは、さまざまなアトリビュートを使用して、エラーに関する特異分布が機械学習により自動的にプロファイルされます。これにより、Kubernetes上の特定のポッド、またはホストにおいてどの程度エラーが発生しているかどうかを表示してくれます。

![スクリーンショット 2017-12-20 10.51.42.png](https://qiita-image-store.s3.amazonaws.com/0/150903/59124519-e7f0-922e-eefb-625c3b8710af.png)
￼
これらのパラメータにより、アプリケーションエラー時においてインフラストラクチャやクラスタ起因のエラーを迅速に把握することができます。

#INSIGHTS NRQLによるグラフ描画
次に、New RelicのダッシュボードサービスINSIGHTSを使用して、グラフ描画を行います。
INSIGHTSでは、APM Agent経由で送られたカスタムパラメータ付きのメトリクスをもとに、NRQLと呼ばれるコマンドを用いて、グラフの描画が可能です。

例えば、ポッド名ごとにアプリケーショントランザクションのパフォーマンスを確認したい場合、次のカスタムNRQL（New Relic Query Language）クエリをInsights上で実行するだけでグラフを描画することが出来ます。

```sql:NRQL
SELECT percentile(duration, 95) from Transaction where appName='newrelic-k8s-node-redis' and name='WebTransaction/Expressjs/GET//'FACET K8S_POD_NAME TIMESERIES auto
```
￼![スクリーンショット 2017-12-20 12.16.37.png](https://qiita-image-store.s3.amazonaws.com/0/150903/468faa5b-3202-43c6-a5cc-04ec6ab6f566.png)

# 番外1. INFRASTURCTUREでもKubernetesを監視する
本投稿の本筋とは外れますが、New Relicにはリソース監視のサービスとしてINFRASTRUCTUREがあります。KubernetesのMasterやWorkerホストのモニタリングはもちろん、コンテナ単位でのモニタリングも可能です。Daemonsetを用いることで、各ホストに対して自動的にインストールを行うことができます。手順は下記の通りです。

## ①. kubernetes gitのインストール
```
 $ git clone https://github.com/kubernetes/kubernetes.git
```

## ②. New Relic INFRASTRUCTURE configの作成 
```
$ cd kubernetes/examples/newrelic-infrastructure/
$ vi nrconfig.env
  #--REQUIRED--
  # Put your license key in this variable
  export NRIA_LICENSE_KEY=“自身のNew Relic ライセンスキー”
```

## ③. kubernetsにconfigを作成
```
$cp newrelic-config-template.yaml newrelic-config.yaml
$kubectl create -f newrelic-config.yaml
```

## ④. Daemonsetの作成
```
$ kubectl create -f newrelic-infra-daemonset.yaml
```

## ⑤. INFRASTRUCTURE画面で確認
New Relic INFRASTRUCTURE画面にて、ホストが表示されることを確認します。

![スクリーンショット 2017-12-20 11.27.04.png](https://qiita-image-store.s3.amazonaws.com/0/150903/2223ae81-a888-a1b9-7d4c-d8addf6126f8.png)

次に『Processes』タブにてホスト上の各コンテナのリソース状況を確認します。『GROUP BY』機能でcontainerNameを指定することで、コンテナ単位でグラフを描画することができます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/150903/eaee41b5-ac04-ed5c-136a-484e230d6ebe.png)
￼
# 番外2. INSIGHTSでKubernetes統合ダッシュボード作成
こちらも本稿の本筋の解説とは外れますが、New Relic INSIGHTSのダッシュボード機能によって、ここまで可視化してきたKubernetesのモニタリング情報を一枚絵にまとめて表示してみたいと思います。

Kubernetes環境内のホストやコンテナ単位でのリソース使用状況、同環境上で稼働するアプリケーションのメトリクス、Pod単位のError数といった、Kuberenetes上の様々なレイヤの情報をINSIGHTSで一元的に表示します。

INFRASTRUCTUREからはKubernetes環境内のホスト及びコンテナのリソース使用状況を取得、APMからは同Kubernetes環境上で稼働するアプリケーションの各種メトリクスを取得、またINSIGHTSのNRQLを用いてpod名単位で表示させたエラーメトリクスをグラフ化し、ダッシュボードに載せました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/150903/b9b8aa28-29fc-2cd1-ee72-d7796296584d.png)

# おわりに
New RelicにおけるKubernetes上のアプリケーションエラートレースから派生し、コンテナやホストのリソースモニタリング、これらを一元的に可視化するダッシュボードについて記述しました。モノリシックな環境とは異なるモニタリングアプローチが必要なKuberenetes環境において、New Relicで同環境をモニタリングするための一助になれば幸いです。