【解説】Kubernetesのロギング：fluentdとElasticSearch

#目次
1.はじめに & 便利な用語
2.Kubernetesのロギング構造
3.ログコレクター：fluentd‍
4.ロギングエンドポイント：ElasticSearch
5.フルスタックの例
     5-1. パイソン
     5-2. コンテナ
     5-3. Kubernetes
     5-4. EFK：ES
     5-5. EFK fluentd
     5.6. Kibana
6.まとめ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/8f496dcd-8bd2-2f27-53a5-1ea0872bc11e.png)


こちらは、英語記事を元に作成されました。[元の英語記事はこちら](https://www.metricfire.com/blog/logging-for-kubernetes-fluentd-and-elasticsearch)です。この記事を読んだ後にも、さらなる情報が欲しいという方は[MetricFire](https://try.metricfire.com/japan/?utm_source=blog&utm_medium=Qiita&utm_campaign=Japan&utm_content=Logging%20for%20Kubernetes%3A%20fluentd%20and%20ElasticSearch)がお助け出来るかもしれませんので、その際は[デモをご予約](https://calendly.com/metricfire-chatwithus/chat?utm_source=blog&utm_medium=Qiita&utm_campaign=Japan&utm_content=Logging%20for%20Kubernetes%3A%20fluentd%20and%20ElasticSearch)ください。

#1.はじめに & 便利な用語

この記事では、fluentdとElasticSearch（ES）を使用してKubernetes（k8s）のログを記録する方法に焦点を当てていきます。 マイクロサービスのアーキテクチャ、コンテナ、ロギングに関する役立つ情報が含まれ、 さらに、コードを共有し、それを実装する方法についても簡潔に説明しているので、独自のアプリへのログインを開始するときにコードを使用でき、参考にしてもらえると思います。

###知っておくと便利な用語

[マイクロサービスアーキテクチャ](https://en.wikipedia.org/wiki/Microservices)は、開発機能を自律的なサブチームに分割し、より生産的な開発プロセスを可能にします。サブチームは特定のタスクのみに関心があるため、結果として得られるソフトウェア（またはその一部）は「コンテナ化」されます。最も人気のあるコンテナ化ツールである[Docker](https://www.docker.com/)を使用すると、必要なすべての前提条件とコマンドを備えた独立したイメージを作成できます。イメージのおかげで、特別なマイクロサービス用に構築された独自の環境を持つ多くの異なるコンテナを持つことができます。

]Kubernetes](https://kubernetes.io/)（k8s）は、マイクロサービスを制御、監視、ロールアウト、保守、およびアップグレードするための最良のツールです。 K8sは、複数のコンテナ、アプリケーション、バージョンなどの管理に役立つオープンソースツールです。k8sに詳しくない場合は、[こちら](https://kubernetes.io/docs/concepts/)で詳細を確認できます。

ロギングを使用すると、ノードのライフサイクルとポッドの通信を制御できます。アプリ内のすべてのジャーナルのようなものです。ログのデータを分析して、問題の洞察、コードスニペットの効率を測定、異なるソフトウェアバージョンの生産性を比較することもできます。 fluentdとElasticSearchはどちらも、ロギングプロセスを容易にする優れたツールであり、アプリがスムーズに実行されるようにします。

# 2. Kubernetesのロギング構造

Kubernetesのロギングには、基本的なI / Oロギング、ノードレベルのロギング、クラスタレベルのロギングの3つの異なるレベルがあります。

###I / Oロギング
まず、基本的なI / Oロジックがあります。すべての高水準プログラミング言語には、ユーザーデータのprintとwriteをサポートする関数があるため、開発者は必要なすべての情報をスニペットから文書化できます。 k8sはこれらの基本的なデータストリームをサポートし、ログとして取得します。これらのストリームの2つは、stdout（ユーザーがprintするすべてのもの）とstderr（各エラーテキストの説明）です。そのようなロギングの結果には、kubectl logs CLIコマンドを介してアクセスし、ここでデータが収集され、簡単に調べることができます。

しかし、2、3個のアプリ用に1つのログ構造を構築する必要がある場合はどうなるでしょうか。ということで質問です。アプリケーションを備えたポッドがクラッシュした場合はどうなりますか？ 
残念ながら、基本的なロギングはこれらの質問に答えません。データは一時的です。クラッシュまたは再実行すると、以前のすべてのレコードが消去されます。

###ノードレベルのロギング
これらの問題に対処するには、ノードのログレベルで設定する必要があります。ノードとは、複数のポッドやコンテナなどの環境です。1つの特別なポッドを使用して、ノードへのロギングを普遍化することができます。ノード内のすべてのオブジェクトとやり取りできるため、垂直方向に固有のロギングシステムを作成することができます。

各ポッドからのデータは、単一のログストレージファイル（JSONファイル）に処理されます。これにより、再実行や突然のストップに対処できますが、最大容量にすぐに達する傾向があります。ノードレベルのログはstdout / stderrタイプのみをサポートしており、ノードごとに個別のログ設定が必要です。

###クラスタレベルのロギング
最後に、クラスタロギングレベルがあります。概念は他の2つのレベルと同じですが、k8にはクラスターロギングのサポートが組み込まれていないため、サイドコンポーネントを自分で作成または統合する必要があります。

![5de9c6ba5190952b7b2649e9_J2lqq0WWwXv2piPbpeBhCXx8-a2RPZnMyfD5EAIWiFBB_m3EG2XZixi5kGJ6Te8gLgJ6wLZOrq4ifcxVGcQbxGC1YOjqpSbk4JgwnTW4Y3wQQ9bjlJWMqSBT696jILOMHFxmUhj2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/ece16b11-e46b-db8d-f851-59f6eb0b8c95.png)

k8sはインスタントソリューションを提供しませんが、クラスターレベルでログを記録するためのツールをサポートします。 次のセクションでそれらを見ていきましょう。 現時点では、最も一般的なアプローチを理解することが重要です。各ノードにノードレベルのログエージェントを含めることで、クラスターレベルのログを実装できます。 ロギングエージェントは、ログをバックエンドに公開またはプッシュする専用ツールです。 通常、ロギングエージェントは、そのノード上のすべてのアプリケーションコンテナからのログファイルを含むディレクトリにアクセスできるコンテナです。

ロギングエージェントはすべてのノードで実行する必要があるため、DaemonSetレプリカ、マニフェストポッド、またはノード上の専用のネイティブプロセスとして実装するのが一般的です。

ということで、ここまで、ロギングの基本を説明したので、ロギングタスクを支援する2つの主要製品であるfluentdとElasticSearchを見てみましょう。

# 3.ログコレクター：[fluentd‍](https://www.fluentd.org/)

![5de9c6b94b9e5a773aa206ef_Plrn4MzvZvx1DoGecdTOGotAUMkmTC0SQ1wIBH6PYzxdUg8At7COCd_PLNPp-3MhbgA9Ql7b0_1u2vmI6SeKZ7dVWxvpItIK4ZoFOgOur7tIigCa2X1D8xExtysS2_jpP9xucJp-.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/560c5f23-9c52-3aa7-96a5-a13f307b6ae8.png)

Fluentdは、統合ログ層として理想的なソリューションです。 プロジェクトに必要なタイプのロガーを開いてダウンロードするだけです。 クラスタ内のすべてのノードからデータを収集する[KubernetesのDaemonSetツール](https://github.com/fluent/fluentd-kubernetes-daemonset)を使用します。

fluentdを使用すると、スニペットの準備が整い、Dockerイメージが安定して更新されます。さらに、事前定義されたElasticSearch（ES）サポートさえあります。 さらに、ES、MongoDB、Hadoop、Amazon Web Services、Google Cloud Platformなどのさまざまなエンドポイントレシーバーがあります。

ユーザーアプリケーションとk8sクラスターの2つの特別なノードであるkube-apiserverやkube-schedulerなどのクラスターコンポーネントの両方からfluentdはログを収集します。 このアプローチの主な利点は、データがJSONファイルに保存されないため、除外せずに保存されることです。 正確に保存される場所は、プロジェクトのニーズによって異なってきます。

Fluentdはk8sだけでなく、モバイルアプリやウェブアプリのログ、HTTP、TCP、nginx、Apache、さらにはIoTデバイスもすべてfluentdでログに記録できます。

# 4.ロギングエンドポイント：[ElasticSearch](https://www.elastic.co/)

![5de9c6babb83abf6dffe29c5_Vihy3iD3k42Q-zLJ0IODpfK9UY8xot5NljPSYjXavk0ehUcxnoLUKxcjUlEF3BI53bAa0O-Hkt3qJ28cZ3SKJuSxsglSdFUTzXn4TD7IFqNeclFkm7jBH_M1SVTWgHL0cnmBJPF3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/55020e5f-b713-3afe-7461-3afffaa48b45.png)

fluentdと同様に、ElasticSearch（ES）は多くのタスクを実行できます。すべてのタスクは検索を中心にしており、 Elastic companyによって開発および提供されるESは、印象的なデータ処理および転送機能を備えた、迅速なクエリセットエグゼキューターです。 ESは、ロギングおよびデータ表現のためのEKスタックの一部であり、 KはKibanaの略で、データのデモンストレーションに役立つ便利な視覚化ソフトウェアです。

ロギングには、ELKとEFKの2つの異なる具体的なスタックがあります。 1つ目は、Elasticドメイン製品であるLogstashです。ただし、このツールはESと電光で接続されているため、k8を直接サポートしていません。ここで、fluentdオープンソースプロジェクトが役に立ちます。k8s統合のいくつかの準備手順でLogstashを使用し、オーケストレーションのユースケースで両方のスタックをマージします。

では、なぜ他の出力リソースよりもElasticSearchを選択する必要があるのでしょうか。それには、多くの理由があります。

- ESは、難しい標準のDBMSルールや制約なしにデータを関係的に保持
- KibanaやLogstashのようなシンプルで強力なネイティブアドオンがある
- RESTful APIインターフェースがあり、基本的なSQL言語よりもはるかに優れており、使いやすい
- マルチスレッドアーキテクチャと強力な分析スキルを備えている
- GitHub、Netflix、Amazonなど多くの主要企業がESを使用

# 5.フルスタックの例
この例では、fluentd、ES、Kibana（視覚化ツールとして）を接続して、いくつかのサービスとポッドで正確なnamespaceを作成します。 また、単純な[Pythonフラスコ](http://flask.palletsprojects.com/)プロジェクトでnamespaceをテストします。

Python 3.7（および必要なすべてのサイドモジュール）でDockerコンテナーを作成します。 後でポッドのソースとしてコンテナを使用します。

このチュートリアルを正常に実装するには、PCに次のスタックが必要です。

- [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/)：Kubernetes CLIインターフェース
- [Minikube](https://kubernetes.io/docs/tasks/tools/install-minikube/)：実際のエンタープライズクラスタのすべてのワークロードをエミュレートするローカルk8sクラスタ
- [Docker](https://www.docker.com/)：コンテナー化のためのツール
- [Python](https://www.python.org/)：プログラミング言語; また、独立した仮想環境を作成するには、[virtualenv](https://docs.python-guide.org/dev/virtualenvs/)をインストールする必要があります。

さらに、kubectlの場合、PCには、仮想マシンを作成するためのツールである[Hypervisor](https://www.vmware.com/topics/glossary/content/hypervisor)がプリインストールされている必要があります。 または、UNIXベースのOSを使用している場合は、ベアメタルオプションを使用することもできます（Linuxには独自の[KVM](https://www.linux-kvm.org/page/Main_Page)機能があります）。

###5-1. Python

それでは、Pythonから始めましょう。 まず、必要なすべてのファイルを保存するためにプロジェクト全体のフォルダーを作成します。 次に、スクリプトを開発し、仮想環境を保存し、Docker用にすべてを作成するPythonアプリのサブフォルダーを作成します。

私たちのアプリケーションは非常にシンプルな[Simon Says](https://en.wikipedia.org/wiki/Simon_Says)ゲームになります：

最初のページ（またはエンドポイント）で、アプリは「サイモンが言う」に続いて現在の時刻を返します。
{host} / echoに行くと、この応答が繰り返されます。
繰り返しのためのメッセージは「取得」リクエストの「m」引数に含まれることに注意してください。 引数がない場合（具体的には「m」）、アプリは「サイモンが言う」フレーズを返します。
仮想環境を作成するには、Flaskライブラリを（pip installフラスコ経由で）インストールし、.pyファイルを作成します。

```
from flask import Flask
from flask import request
import datetime
import sys
app = Flask(__name__)
@app.route('/')
def hello():
	return "Simon says its {0}".format(datetime.datetime.now())
@app.route('/echo')
def echo():
    	return 'Simon says {0}'.format(request.args.get('m'))
	sys.stderr.write('Error, echo with no symbols!')
	sys.stdout.flush()
	return "Simon says, but you don't"
if __name__ == '__main__':
	app.run(host='0.0.0.0', port='3001')
```
コードはかなりシンプルです。 echoメソッドを見てみてください。 ここでは、stderrログを作成します。 最後にログの正確性をチェックするときに役立つはずです

これでテストできます。 このファイルを（python <file-name> .pyを介して）実行し、結果を調べます。 アプリとリクエストは機能するはずです。

独立したイメージも作成したいので、すべての要件を処理する必要があります。 サイドモジュールフラスコをインストールしたので、Python構成を処理する必要がある場合があります。 この目的のために、ターミナルで次の行を実行します：pip freeze> requirements.txt。 この行は、プロジェクトに必要なすべてのモジュールを含むファイルを作成します。 さあ、ここからはコンテナの時間です！

### 5-2. コンテナ

Dockerを使用している場合は、コンテナ設定に役立つDockerfileファイルと、Dockerが無視する必要のあるファイルとフォルダーを示すdockerignoreファイルを作成します。

Dockerfileから始めましょう（コードは次のとおりです）。

まず、Dockerにイメージがpython 3.7上にあることを伝えます。
現在のフォルダーをすべて、将来のイメージの/ usr / src / appパスにコピーします。
次に、要件の問題を処理するために（前の行で説明したのと同じ）作業ディレクトリを設定します。
最後に、3001ポートを公開し、すべてがpython <file-name> .pyコマンドで起動することを伝えます。

```
FROM python:3.7
COPY ./ /usr/src/app
WORKDIR /usr/src/app
RUN pip install -r requirements.txt
EXPOSE 3001
CMD ["python", "simon.py"]
```

次に、以下のような.dockerignoreファイルを作成します。
最初の行はテキストエディターに関するものです（私たちはVisual Studio Codeを使用しました）
次に、イメージでは不要な仮想環境とDockerfileを無視するとします。

```
/.vscode
/kub-env
Dockerfile
```
最後に、ターミナルを開いてDockerコンテナを作成します。

```
$ docker build -f Dockerfile -t log-simon:latest .
```

Dockerコンテナを作成すると、完全に独立したDockerイメージが作成されます。 実行するだけで結果を確認できるはずです。 次のコマンドを入力します：docker run -p 3001：3001 log-simon：latest。 そのコマンドを入力した後、ブラウザーでアプリを確認できます。 出力は、コードで取得したものとまったく同じになるはずです。

#5-3. Kubernetes

Minikubeクラスターを実行し（minikube startコマンドを使用）、プロジェクトのルートフォルダーに移動します。 k8sファイル用のフォルダーをもう1つ作成し、そこに移動します。

まず、すべての実験を基本的かつ重要なk8sノードから分離しましょう。 次の行を入力します：kubectl create namespace logging。 名前空間は、さまざまなk8sノードを区別する方法です。

次に、必要なすべてのリソースのデプロイをいくつか行います。Pythonを使用したDockerイメージ、fluentdノード（クラスター内のすべてのノードからすべてのログを収集します）DaemonSet、ES、およびKibana。 .yamlファイル、k8sオブジェクト、アーキテクチャの詳細については、[こちら](https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/)をご覧ください。

deployment.yamlファイルを作成し、次の行を貼り付けます。

```
apiVersion: v1
kind: Service
metadata:
  name: simon-service
spec:
  selector:
  	app: simon
  ports:
  - protocol: "TCP"
  	port: 3001
	targetPort: 3001
	nodePort: 32023
  type: LoadBalancer

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: simon
spec:
  selector:
	matchLabels:
	app: simon
  replicas: 2
  template:
	metadata:
  	labels:
	app: simon
	spec:
  	containers:
  	- name: log-simon
    	image: log-simon:latest
    	imagePullPolicy: Never
    	ports:
    	- containerPort: 3001
```
上記の行で混乱していますせんか。 ただ、2つのk8sエンティティを作成しただけです。

1つ目は、アプリとの対話を担当するサービスです。 アプリ「simon」と組み合わせています。 2番目（---行の後）は、simonアプリとその設定です。
デプロイをDockerイメージlog-simon：latestに接続し、2つのレプリカを作成しました。
最後に、ターミナルの次の行であるkubectl create -f deployment.yaml -n loggingを介してアプリを機能させました。
ターミナルでは、deployment.yamlに基づいてデプロイを作成し、それをロギングネームスペース専用にしました。

すべての[ポッド](https://kubernetes.io/docs/concepts/workloads/pods/pod/)と[サービス](https://kubernetes.io/docs/concepts/services-networking/service/)を取得して結果を確認できます。

```
$ kubectl get pods -o wide -n logging
```

出力は次のようになります。

| Name            | Ready | Status  | Restarts | Age  | IP | Node  |
|:---------------------|:------:|:-------:|:---------:|:-----:|:---:|:-----:|
| simon-69dc8c64c4-6qx5h|   1/1 | Running |     3    | 4h36m|  172.17.0.10|    minikube| 
| simon-69dc8c64c4-xzmwx  |   1/1 | Running |     3    | 4h36m|  172.17.0.10|    minikube| 

「simon」アプリの両方のレプリカ（またはポッド）が機能し、サービスを使用してそれらを確認できます。

```
$ kubectl get svc -o wide -n logging
```

| Name            | Type | CLUSTER-IP  | EXTERNAL-IP | PORT(S)  | Age | Selector  |
|:---------------------|:------:|:-------:|:---------:|:-----:|:---:|:-----:|
| simon-service  | LoadBalancer  |   10.96.145.153 | <pending> |        3001:32023/TCP  |  4h40m  |    app=simon

新しいポッドまたはサービスがある場合はいつでも同じ手順を実行できます。

注釈：
列「ポート」は、サービスが正確に格納される場所を説明します。 これを確認するには、minikube ipコマンドを実行して、クラスターの正確なIPアドレスを取得します。 次に、ポート（この場合は32023）を追加し、ブラウザでこのページにアクセスします。 結果は、最後にチェックした2回と同じになります。アプリは機能します。

### 5-4. EFK: ES

それでは、EFKスタックを作成していきましょう。 まず、バックエンドストレージエンジンであるElasticSearchから始めます。 このスキームは、前のコードスニペットに似ています。サービスとポッドを一つずつ、そしてelastic_search.yamlファイルを作成します。

```
apiVersion: apps/v1
kind: Deployment
metadata:
  name: elasticsearch
spec:
  selector:
	matchLabels:
  	component: elasticsearch
  template:
	metadata:
  	labels:
    	component: elasticsearch
	spec:
  	containers:
  	- name: elasticsearch
    	image: docker.elastic.co/elasticsearch/elasticsearch:7.4.1
    	env:
    	- name: discovery.type
      	value: single-node
    	ports:
    	- containerPort: 9200
      	name: http
      	protocol: TCP
    	resources:
      	limits:
        	cpu: 500m
        	memory: 4Gi
      	requests:
        	cpu: 500m
        	memory: 4Gi

---

apiVersion: v1
kind: Service
metadata:
  name: elasticsearch
  labels:
	service: elasticsearch
spec:
  type: NodePort
  selector:
	component: elasticsearch
  ports:
  - port: 9200
	targetPort: 9200
```

ここでもデプロイを作成しましたが、独自のDockerイメージの代わりに、次を使用しました：docker.elastic.co/elasticsearch/elasticsearch:7.4.1

EFKスタックでは、ポッドを1つだけ作成し、正確なリソース使用を委任し、ノードにサービスを作成しました。 コマンドkubectl create -f elastic_search.yaml -n loggingは、インストールされたローカルESクラスターで1つ以上のポッドとサービスを作成しました。

curl $（minikube ip）：<your-ES-port>を使用してコードを確認できます。<your-ES-port>はESサービスのポートです（この場合は32541）。 応答は以下のものに近いはずです：

```
{
  "name" : "elasticsearch-59bbd49f77-25vrm",
  "cluster_name" : "docker-cluster",
  "cluster_uuid" : "oSaNWO1fQcyCVJkskqR-kw",
  "version" : {
	"number" : "7.4.1",
	"build_flavor" : "default",
	"build_type" : "docker",
	"build_hash" : "fc0eeb6e2c25915d63d871d344e3d0b45ea0ea1e",
	"build_date" : "2019-10-22T17:16:35.176724Z",
	"build_snapshot" : false,
	"lucene_version" : "8.2.0",
	"minimum_wire_compatibility_version" : "6.8.0",
	"minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}
```

これでESの準備は完了です。

### 5-5. EFK: fluentd

EFKの略語によると、２つ目はF。ということで次はfluentdです。 2つのファイルを作成して適用していきます。 私たちのfluentdノードはクラスターからのすべてのログを保持する必要があるため、他のnamespace-kube-systemにインストールすることと さらに、[RBAC](https://en.wikipedia.org/wiki/Role-based_access_control)にいくつかのアクセスを許可する必要があります。 fluent-rbac.yamlを作成し、次のコンテンツを入力します。

```
apiVersion: v1
kind: ServiceAccount
metadata:
  name: fluentd
  namespace: kube-system

---

apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: fluentd
  namespace: kube-system
rules:
- apiGroups:
  - ""
  resources:
  - pods
  - namespaces
  verbs:
  - get
  - list
  - watch

---

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: fluentd
roleRef:
  kind: ClusterRole
  name: fluentd
  apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
  name: fluentd
  namespace: kube-system
```

上記のコードでは、いくつかのclusterRoleバインディングを許可し、ServiceAccountを作成しました。

次に、元のDockerイメージからfluentdをデプロイする必要があります。 fluentd.yamlファイルを作成し、次の行を貼り付けます。

```
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd
  namespace: kube-system
  labels:
	k8s-app: fluentd-logging
	version: v1
	kubernetes.io/cluster-service: "true"
spec:
  selector:
	matchLabels:
  	k8s-app: fluentd-logging
  template:
	metadata:
  	labels:
    	k8s-app: fluentd-logging
    	version: v1
    	kubernetes.io/cluster-service: "true"
	spec:
  	serviceAccount: fluentd
  	serviceAccountName: fluentd
  	tolerations:
  	- key: node-role.kubernetes.io/master
    	effect: NoSchedule
  	containers:
  	- name: fluentd
    	image: fluent/fluentd-kubernetes-daemonset:v1.3-debian-elasticsearch
    	env:
      	- name:  FLUENT_ELASTICSEARCH_HOST
        	value: "elasticsearch.logging"
      	- name:  FLUENT_ELASTICSEARCH_PORT
        	value: "9200"
      	- name: FLUENT_ELASTICSEARCH_SCHEME
        	value: "http"
      	- name: FLUENT_UID
        	value: "0"
    	resources:
      	limits:
        	memory: 200Mi
      	requests:
        	cpu: 100m
        	memory: 200Mi
    	volumeMounts:
    	- name: varlog
      	mountPath: /var/log
    	- name: varlibdockercontainers
      	mountPath: /var/lib/docker/containers
      	readOnly: true
  	terminationGracePeriodSeconds: 30
  	volumes:
  	- name: varlog
    	hostPath:
      	path: /var/log
  	- name: varlibdockercontainers
    	hostPath:
      	path: /var/lib/docker/containers
```

上記の行では、DaemonSetツールを作成し、hostPath構成を確認し、fluentdの可能な使用法を決定しました。

これで、2つのファイルを適用できます。 次の2行を続けて実行します：kubectl create -f fluentd-rbac.yamlとkubectl create -f fluentd.yaml。 結果はkube-system Namespaceのポッドで確認できます。

```
$ kubectl get pods -n kube-system
```

そのアウトプットは以下のようになります。

| Name            | Ready | Status  | Restarts | Age  |
|:---------------------|:------:|:-------:|:---------:|:-----:|
| coredns-5644d7b6d9-74sgc     |    1/1   |      Running  |  8      |             5d8h |
|coredns-5644d7b6d9-fsm8x       |    1/1    |     Running |   8   |                5d8h|
|etcd-minikube                  |                1/1  |      Running   | 2 |                  4h31m  |
|fluentd-npcwf                    |             1/1    |    Running |  5     |              14h   |
|kube-addon-manager-minikube   |   1/1      |   Running  |  8     |              5d8h|
|kube-apiserver-minikube      |           1/1     |   Running   | 2  |                 4h31m|
|kube-controller-manager-minikube| 1/1  |       Running   | 24   |              2d3h|
|kube-proxy-nm269       |            1/1     |    Running |   8     |              5d8h|
|kube-scheduler-minikube     |           1/1     |    Running  |  24 |                5d8h|
|storage-provisioner          |               1/1  |       Running  |  9   |                5d8h|

Fluentdが実行されています！ ESへの接続を確認するには、次のコマンドを使用します。

kubectlログfluentd-npcwf -n kube-system


Elasticsearch cluster => {：host => "elasticsearch.logging"、：port => 9200、：scheme => "http"}に対して開かれた接続から出力が始まる場合、すべて問題ありません。

### 5-6. Kibana

最後に、Kibanaを使用してログを視覚的に表現します。 次の行を含むkibana.ymlファイルを作成していきます。

```
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kibana
spec:
  selector:
	matchLabels:
  	run: kibana
  template:
	metadata:
  	labels:
    	run: kibana
	spec:
  	containers:
  	- name: kibana
    	image: docker.elastic.co/kibana/kibana:7.4.1
    	env:
    	- name: ELASTICSEARCH_URL
      	value: http://elasticsearch:9200
    	- name: XPACK_SECURITY_ENABLED
      	value: "true"
    	ports:
    	- containerPort: 5601
      	name: http
      	protocol: TCP

---

apiVersion: v1
kind: Service
metadata:
  name: kibana
  labels:
	service: kibana
spec:
  type: NodePort
  selector:
	run: kibana
  ports:
  - port: 5601
	targetPort: 5601
```
このコードでは、spec.template.spec.envノードという1つ大きな変更を加えて、以前と同じように展開/サービスソリューションを構築しました。 このノードでは、事前に定義されたポートでESサーバーをポイントするため、Kibanaがそれに接続します。

次に、exec kubectl create -f kibana.yaml -n loggingを実行すると、最終的にすべてのスタックを確認できます。

Kibanaのポートを見つけ（get podsコマンドを使用）、ブラウザーで実行します。

![5de9c6babb83ab1012fe29c6_sZbsRrXB0gGPqDnsDyVnnKN0loLMifT3xgezMV2dVuZrgDIR1xLvn1mOq7r7N2UBloL6-B8qBLpdyexYH0eksIrk-5HLiIEIX6FpOPI3FMtN6QJp7P41l2PwJbq7Qys38Aj7hfzH.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/9d8211b6-aec4-94f8-a923-f2544c0565d5.png)

これが私たちの視覚化できたものです。 左側のドロップダウンメニューで[管理]を見つけます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/dfdb97b9-eb41-b180-566c-5ff7ef3ee950.png)

Kibanaブロックの下の[Index Patterns]をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/978c4b70-1145-3b68-b947-47a9704223b7.png)

可能なインデックスがいくつか表示され、新しいインデックスを作成できます。 テキストボックスにlogstashと入力し、[Next Step]をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/6b421c93-a8db-ef87-9aa6-e97bea463ce3.png)


次に、ドロップダウンボックスで@timestampを選択し、[Create index pattern]をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/25165ba2-5ba6-ef8e-a2d1-576a30cf7b08.png)

インデックスlogstashの準備ができたので、ログはfluentdによって収集され、ESに送信され、Kibanaによって取得されます。 すべてが機能しているかどうかを確認してみましょう。左側のバーにある[Discover]をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/8e5e976c-ab51-5bfb-65c9-e27f5253e33d.png)


そしてここにあります！ 強力な視覚化機能と追跡機能を備えたスマートログストレージ。 次に、simonアプリのサービスに移動し、引数なしで/ echoエンドポイントにアクセスしてみます。 その後、Kibanaの検索ボックスに「simon」と入力し、[Update]をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/41617e3b-a0bb-d119-fb73-3d1d2707a810.png)

これは、simonアプリケーションのログです。 このオブジェクトを展開すると、この記事の冒頭でコード内に記述したテキストが見つかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614998/63e02c26-0930-48d6-2251-eac36744a1ba.png)

EFKスタックを使用したログ構造が準備でき、すべてのクラスターからのログが収集および処理されるため、アプリケーションをより簡単に追跡および維持できます。

# 6. まとめ

ロギングは、特にアプリケーションの状態など、多くの要素を制御する必要がある場合、プログラミングにおいて非常に強力で不可欠な手段です。そのため、ロギングアーキテクチャなしにk8sクラスターを想像することは不可能です。

もちろん、k8sはこの目的のための基本的な機能を提供しますが、ノードがクラッシュまたは再実行すると、貴重な情報を失うリスクがあります。ログを個別に処理および保存するのに役立つスタックは、ベースノードとしてクラスターの一部となり、これがfluentdおよびESが役立つ場所です。

これらのツールを使用すると、ユーザーはポッド/ノード/名前空間のログを制御できるだけでなく、すべてのクラスターを制御することもできます。さらに、ESとfluentdには、Kibanaのような強力な視覚化機能が含まれています。 ESとfluentdはデータを理解しやすくし、動的なフィルターと更新を備えています。スタックを一度設定すれば、データを失う心配はありません。

[MetricFire](https://try.metricfire.com/japan/?utm_source=blog&utm_medium=Qiita&utm_campaign=Japan&utm_content=Logging%20for%20Kubernetes%3A%20fluentd%20and%20ElasticSearch)がホストするGraphiteページで、他のオプションの詳細を確認してください。 [MetricFire](https://try.metricfire.com/japan/?utm_source=blog&utm_medium=Qiita&utm_campaign=Japan&utm_content=Logging%20for%20Kubernetes%3A%20fluentd%20and%20ElasticSearch)は時系列の監視を専門としていますが、Elasticsearchはログ監視領域を支配しています。[無料トライアル](https://www.hostedgraphite.com/accounts/signup-metricfire/?signup=japan&utm_source=blog&utm_medium=Qiita&utm_campaign=Japan&utm_content=Logging%20for%20Kubernetes%3A%20fluentd%20and%20ElasticSearch)で製品を試して時系列データを監視するか、[デモを予約](https://calendly.com/metricfire-chatwithus/chat?utm_source=blog&utm_medium=Qiita&utm_campaign=Japan&utm_content=Logging%20for%20Kubernetes%3A%20fluentd%20and%20ElasticSearch)して、効果的な監視ソリューションについて直接ご相談ください。