KubernetesでElasticsearch、Fluentd、Kibana(EFK)ログスタックを設定する方法

前書き

Kubernetesクラスターで複数のサービスとアプリケーションを実行する場合、集中化されたクラスターレベルのログスタックを使用すると、Podによって生成された大量のログデータをすばやく分類して分析できます。 人気のある集中ログソリューションの1つは、 E lasticsearch、 F luentd、および K ibana(EFK)スタックです。

  • Elasticsearch *は、フルテキスト検索と構造化検索、および分析を可能にする、リアルタイムで分散されたスケーラブルな検索エンジンです。 通常、大量のログデータのインデックス作成と検索に使用されますが、さまざまな種類のドキュメントの検索にも使用できます。

Elasticsearchは一般に、Elasticsearchの強力なデータ視覚化フロントエンドおよびダッシュボードである* Kibana *と一緒にデプロイされます。 Kibanaを使用すると、Webインターフェースを介してElasticsearchログデータを探索し、ダッシュボードとクエリを作成して質問にすばやく回答し、Kubernetesアプリケーションの洞察を得ることができます。

このチュートリアルでは、* Fluentd *を使用してログデータを収集、変換し、Elasticsearchバックエンドに送信します。 Fluentdは人気のあるオープンソースのデータコレクターであり、Kubernetesノードに設定してコンテナーログファイルを追跡し、ログデータをフィルター処理して変換し、それをElasticsearchクラスターに配信します。

まず、スケーラブルなElasticsearchクラスターを構成して起動してから、Kibana Kubernetes Service and Deploymentを作成します。 最後に、FluentdをDaemonSetとして設定し、すべてのKubernetesワーカーノードで実行されるようにします。

前提条件

このガイドを始める前に、次のものが利用可能であることを確認してください。

  • 役割ベースのアクセス制御(RBAC)が有効になっているKubernetes 1.10+クラスター

  • クラスターにEFKスタックを展開するのに十分なリソースがあることを確認し、ワーカーノードを追加してクラスターをスケーリングしない場合。 3ポッドのElasticsearchクラスター(必要に応じてこれを1に縮小できます)と、単一のKibanaポッドをデプロイします。 すべてのワーカーノードもFluentdポッドを実行します。 このガイドのクラスターは、3つのワーカーノードと管理されたコントロールプレーンで構成されています。

  • ローカルマシンにインストールされ、クラスターに接続するように設定された `+ kubectl `コマンドラインツール。 ` kubectl +`のインストールの詳細については、https://kubernetes.io/docs/tasks/tools/install-kubectl/ [公式ドキュメント]をご覧ください。

これらのコンポーネントをセットアップしたら、このガイドから始める準備ができました。

手順1-名前空間の作成

Elasticsearchクラスターを展開する前に、すべてのロギングインスツルメンテーションをインストールするネームスペースを作成します。 Kubernetesでは、ネームスペースと呼ばれる「仮想クラスター」抽象化を使用して、クラスターで実行されているオブジェクトを分離できます。 このガイドでは、EFKスタックコンポーネントをインストールする「+ kube-logging +」名前空間を作成します。 この名前空間により、Kubernetesクラスターの機能を失うことなく、ログスタックをすばやくクリーンアップおよび削除することもできます。

まず、 `+ kubectl +`を使用してクラスター内の既存のネームスペースを調査します。

kubectl get namespaces

Kubernetesクラスターにプリインストールされている次の3つの初期ネームスペースが表示されます。

OutputNAME          STATUS    AGE
default       Active    5m
kube-system   Active    5m
kube-public   Active    5m

`+ default `名前空間には、名前空間を指定せずに作成されたオブジェクトが格納されます。 「 kube-system 」名前空間には、「 kube-dns 」、「 kube-proxy 」、「 kubernetes-dashboard +」など、Kubernetesシステムで作成および使用されるオブジェクトが含まれます。 この名前空間をクリーンな状態に保ち、アプリケーションとインストルメンテーションのワークロードで汚染しないようにすることをお勧めします。

`+ kube-public +`名前空間は、認証されていないユーザーも含めて、クラスター全体で読み取りおよびアクセスできるオブジェクトを保存するために使用できる別の自動作成された名前空間です。

`+ kube-logging `名前空間を作成するには、まずnanoなどのお気に入りのエディターを使用して ` kube-logging.yaml +`というファイルを開いて編集します。

nano kube-logging.yaml

エディター内で、次の名前空間オブジェクトYAMLを貼り付けます。

kube-logging.yaml

kind: Namespace
apiVersion: v1
metadata:
 name: kube-logging

次に、ファイルを保存して閉じます。

ここでは、Kubernetesオブジェクト「+ kind」が「+ Namespace」オブジェクトであることを指定します。 + Namespace +`オブジェクトの詳細については、Kubernetesの公式ドキュメントのhttps://kubernetes.io/docs/tasks/administer-cluster/namespaces-walkthrough/[Namespaces Walkthrough]を参照してください。 また、オブジェクトの作成に使用されるKubernetes APIバージョン( `+ v1 +)を指定し、それに + name +、 `+ kube-logging +`を付けます。

`+ kube-logging.yaml `名前空間オブジェクトファイルを作成したら、 ` -f `ファイル名フラグを指定した ` kubectl create +`を使用して名前空間を作成します。

kubectl create -f kube-logging.yaml

次のような出力が表示されるはずです。

Outputnamespace/kube-logging created

その後、ネームスペースが正常に作成されたことを確認できます。

kubectl get namespaces

この時点で、新しい `+ kube-logging +`名前空間が表示されるはずです。

OutputNAME           STATUS    AGE
default        Active    23m
kube-logging   Active    1m
kube-public    Active    23m
kube-system    Active    23m

これで、Elasticsearchクラスターをこの分離されたロギングネームスペースにデプロイできます。

ステップ2-Elasticsearch StatefulSetの作成

ロギングスタックを格納する名前空間を作成したので、さまざまなコンポーネントの展開を開始できます。 まず、3ノードのElasticsearchクラスターを展開します。

このガイドでは、3つのElasticsearchポッドを使用して、可用性の高いマルチノードクラスターで発生する「スプリットブレイン」問題を回避します。 高レベルでは、「スプリットブレイン」は、1つ以上のノードが他のノードと通信できず、複数の「スプリット」マスターが選出されるときに発生します。 3つのノードでは、1つが一時的にクラスターから切断された場合、他の2つのノードが新しいマスターを選出し、最後のノードが再参加を試みている間クラスターは機能を継続できます。 詳細については、https://www.elastic.co/blog/a-new-era-for-cluster-coordination-in-elasticsearch [Elasticsearchのクラスター調整の新時代]およびhttps://www.elasticを参照してください。 .co / guide / en / elasticsearch / reference / current / modules-discovery-voting.html [投票構成]。

ヘッドレスサービスの作成

まず、3つのポッドのDNSドメインを定義する「+ elasticsearch +」というヘッドレスKubernetesサービスを作成します。 ヘッドレスサービスは、ロードバランシングを実行したり、静的IPを使用したりしません。ヘッドレスサービスの詳細については、公式のhttps://kubernetes.io/docs/concepts/services-networking/service/#headless-services[Kubernetes documentation]をご覧ください。

お気に入りのエディターを使用して、「+ elasticsearch_svc.yaml +」というファイルを開きます。

nano elasticsearch_svc.yaml

次のKubernetesサービスYAMLに貼り付けます。

elasticsearch_svc.yaml

kind: Service
apiVersion: v1
metadata:
 name: elasticsearch
 namespace: kube-logging
 labels:
   app: elasticsearch
spec:
 selector:
   app: elasticsearch
 clusterIP: None
 ports:
   - port: 9200
     name: rest
   - port: 9300
     name: inter-node

次に、ファイルを保存して閉じます。

`+ kube-logging `名前空間で ` elasticsearch `と呼ばれる ` Service `を定義し、 ` app:elasticsearch `ラベルを付けます。 次に、サービスが ` app:elasticsearch `ラベルを持つポッドを選択するように、 ` .spec.selector `を ` app:elasticsearch `に設定します。 Elasticsearch StatefulSetをこのサービスに関連付けると、サービスは ` app:elasticsearch +`ラベルを持つElasticsearch Podsを指すDNS Aレコードを返します。

次に、 `+ clusterIP:None `を設定します。これにより、サービスがヘッドレスになります。 最後に、REST APIとの対話およびノー​​ド間通信にそれぞれ使用されるポート「+9200」と「9300」を定義します。

`+ kubectl +`を使用してサービスを作成します。

kubectl create -f elasticsearch_svc.yaml

次のような出力が表示されるはずです。

Outputservice/elasticsearch created

最後に、 `+ kubectl get +`を使用してサービスが正常に作成されたことを再確認します。

kubectl get services --namespace=kube-logging

以下が表示されるはずです。

OutputNAME            TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)             AGE
elasticsearch   ClusterIP   None         <none>        9200/TCP,9300/TCP   26s

これで、ヘッドレスサービスと、ポッド用の安定した `+ .elasticsearch.kube-logging.svc.cluster.local +`ドメインをセットアップしたので、次に進み、StatefulSetを作成します。

StatefulSetの作成

Kubernetes StatefulSetを使用すると、ポッドに安定したIDを割り当てて、安定した永続的なストレージを付与できます。 Elasticsearchでは、Podの再スケジュールと再起動の間でデータを保持するために安定したストレージが必要です。 StatefulSetワークロードの詳細については、Kubernetesドキュメントのhttps://kubernetes.io/docs/concepts/workloads/controllers/statefulset/[Statefulsets]ページを参照してください。

お気に入りのエディターで `+ elasticsearch_statefulset.yaml +`というファイルを開きます。

nano elasticsearch_statefulset.yaml

StatefulSetオブジェクト定義をセクションごとに移動して、このファイルにブロックを貼り付けます。

次のブロックに貼り付けることから始めます。

elasticsearch_statefulset.yaml

apiVersion: apps/v1
kind: StatefulSet
metadata:
 name: es-cluster
 namespace: kube-logging
spec:
 serviceName: elasticsearch
 replicas: 3
 selector:
   matchLabels:
     app: elasticsearch
 template:
   metadata:
     labels:
       app: elasticsearch

このブロックでは、 + kube-logging +`名前空間で `+ es-cluster +`というStatefulSetを定義します。 次に、 `+ serviceName +`フィールドを使用して、以前に作成した `+ elasticsearch +`サービスに関連付けます。 これにより、StatefulSetの各Podが次のDNSアドレスを使用してアクセスできるようになります: `+ es-cluster- [0,1,2] .elasticsearch.kube-logging.svc.cluster.local +、ここで、 `+ [0、 1,2] + `は、ポッドに割り当てられた整数の序数に対応します。

3つの + replicas +(ポッド)を指定し、 `+ matchLabels `セレクターを ` app:elasticseach `に設定し、それを ` .spec.template.metadata `セクションでミラーリングします。 ` .spec.selector.matchLabels `および ` .spec.template.metadata.labels +`フィールドは一致する必要があります。

これでオブジェクトの仕様に進むことができます。 前のブロックのすぐ下にあるYAMLの次のブロックに貼り付けます。

elasticsearch_statefulset.yaml

. . .
   spec:
     containers:
     - name: elasticsearch
       image: docker.elastic.co/elasticsearch/elasticsearch:7.2.0
       resources:
           limits:
             cpu: 1000m
           requests:
             cpu: 100m
       ports:
       - containerPort: 9200
         name: rest
         protocol: TCP
       - containerPort: 9300
         name: inter-node
         protocol: TCP
       volumeMounts:
       - name: data
         mountPath: /usr/share/elasticsearch/data
       env:
         - name: cluster.name
           value: k8s-logs
         - name: node.name
           valueFrom:
             fieldRef:
               fieldPath: metadata.name
         - name: discovery.seed_hosts
           value: "es-cluster-0.elasticsearch,es-cluster-1.elasticsearch,es-cluster-2.elasticsearch"
         - name: cluster.initial_master_nodes
           value: "es-cluster-0,es-cluster-1,es-cluster-2"
         - name: ES_JAVA_OPTS
           value: "-Xms512m -Xmx512m"

ここで、StatefulSetでポッドを定義します。 コンテナに「+ elasticsearch 」という名前を付け、「 docker.elastic.co/elasticsearch/elasticsearch:7.2.0 + `Dockerイメージを選択します。 この時点で、このイメージタグを変更して、独自の内部Elasticsearchイメージまたは別のバージョンに対応させることができます。 このガイドでは、Elasticsearch `+ 7.2.0 +`のみがテストされていることに注意してください。

次に、「+ resources +」フィールドを使用して、コンテナに少なくとも0.1 vCPUの保証が必要であり、最大1 vCPUをバーストできることを指定します(最初の大量取り込みを実行するとき、または負荷スパイクを処理するときにポッドのリソース使用を制限します) 。 これらの値は、予想される負荷と利用可能なリソースに応じて変更する必要があります。 リソースのリクエストと制限の詳細については、公式のhttps://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/[Kubernetes Documentation]をご覧ください。

次に、REST APIとノード間通信のために、それぞれポート「9200」と「9300」を開いて名前を付けます。 パス「+ / usr / share / elasticsearch / data 」のコンテナに「 data 」という名前のPersistentVolumeをマウントする「 data 」と呼ばれる「 volumeMount +」を指定します。 このStatefulSetのVolumeClaimsは、後のYAMLブロックで定義します。

最後に、コンテナにいくつかの環境変数を設定します。

  • + cluster.name +:Elasticsearchクラスターの名前。このガイドでは `+ k8s-logs +`です。

  • + node.name +:ノードの名前。これは、 `+ valueFrom `を使用して ` .metadata.name `フィールドに設定します。 これは、ノードに割り当てられた序数に応じて、「 es-cluster- [0,1,2] +」に解決されます。

  • + discovery.seed_hosts +:このフィールドは、ノード検出プロセスをシードするクラスター内のマスター適格ノードのリストを設定します。 このガイドでは、以前に設定したヘッドレスサービスのおかげで、ポッドには「+ es-cluster- [0,1,2] .elasticsearch.kube-logging.svc.cluster.local + `」という形式のドメインがあります。それに応じてこの変数。 ローカル名前空間Kubernetes DNS解決を使用して、これを `+ es-cluster- [0,1,2] .elasticsearch +`に短縮できます。 Elasticsearchディスカバリーの詳細については、公式のhttps://www.elastic.co/guide/en/elasticsearch/reference/7.x/discovery-settings.html[Elasticsearch documentation]をご覧ください。

  • + cluster.initial_master_nodes +:このフィールドは、マスター選出プロセスに参加するマスター適格ノードのリストも指定します。 このフィールドでは、ホスト名ではなく、 `+ node.name +`でノードを識別する必要があることに注意してください。

  • + ES_JAVA_OPTS +:ここでは、これを `+ -Xms512m -Xmx512m +`に設定し、512 MBの最小および最大ヒープサイズを使用するようJVMに指示します。 これらのパラメーターは、クラスターのリソースの可用性とニーズに応じて調整する必要があります。 詳細については、https://www.elastic.co/guide/en/elasticsearch/reference/current/heap-size.html [ヒープサイズの設定]を参照してください。

貼り付ける次のブロックは次のようになります。

elasticsearch_statefulset.yaml

. . .
     initContainers:
     - name: fix-permissions
       image: busybox
       command: ["sh", "-c", "chown -R 1000:1000 /usr/share/elasticsearch/data"]
       securityContext:
         privileged: true
       volumeMounts:
       - name: data
         mountPath: /usr/share/elasticsearch/data
     - name: increase-vm-max-map
       image: busybox
       command: ["sysctl", "-w", "vm.max_map_count=262144"]
       securityContext:
         privileged: true
     - name: increase-fd-ulimit
       image: busybox
       command: ["sh", "-c", "ulimit -n 65536"]
       securityContext:
         privileged: true

このブロックでは、メインの `+ elasticsearch +`アプリコンテナの前に実行されるいくつかのInitコンテナを定義します。 これらの初期化コンテナはそれぞれ、定義された順序で完了まで実行されます。 Init Containersの詳細については、公式のhttps://kubernetes.io/docs/concepts/workloads/pods/init-containers/[Kubernetes Documentation]をご覧ください。

最初の「+ fix-permissions 」という名前は、「 chown 」コマンドを実行して、Elasticsearchデータディレクトリの所有者とグループをElasticsearchユーザーのUIDである「+1000:1000」に変更します。 デフォルトでは、Kubernetesはデータディレクトリを「+ root +」としてマウントします。これにより、Elasticsearchからアクセスできなくなります。 この手順の詳細については、Elasticsearchの「https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html#_notes_for_production_use_and_defaults [本番環境での使用とデフォルトに関する注意事項]」をご覧ください。

2番目の「+ increase-vm-max-map +」という名前のコマンドは、オペレーティングシステムのmmapカウントの制限を増やすコマンドを実行します。デフォルトでは低すぎるため、メモリ不足エラーが発生します。 この手順の詳細については、公式のhttps://www.elastic.co/guide/en/elasticsearch/reference/current/vm-max-map-count.html[Elasticsearch documentation]をご覧ください。

次に実行するInit Containerは `+ increase-fd-ulimit `で、これは ` ulimit +`コマンドを実行して、開いているファイル記述子の最大数を増やします。 この手順の詳細については、公式のElasticsearchドキュメントの「https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html#_notes_for_production_use_and_defaults [プロダクションの使用とデフォルトに関する注意事項]」を参照してください。

メインアプリコンテナと、コンテナOSを調整するために実行される初期コンテナを定義したので、最後の部分をStatefulSetオブジェクト定義ファイルに追加できます: + volumeClaimTemplates +

次の `+ volumeClaimTemplate +`ブロックに貼り付けます:

elasticsearch_statefulset.yaml

. . .
 volumeClaimTemplates:
 - metadata:
     name: data
     labels:
       app: elasticsearch
   spec:
     accessModes: [ "ReadWriteOnce" ]
     storageClassName: do-block-storage
     resources:
       requests:
         storage: 100Gi

このブロックでは、StatefulSetの + volumeClaimTemplates +`を定義します。 Kubernetesはこれを使用して、ポッドのPersistentVolumeを作成します。 上記のブロックでは、 `+ data +(以前に定義した + volumeMount + sで参照する + name +)という名前を付け、StatefulSetと同じ `+ app:elasticsearch +`ラベルを付けます。

次に、そのアクセスモードを「+ ReadWriteOnce 」として指定します。これは、単一のノードによって読み取り/書き込みとしてのみマウントできることを意味します。 デモンストレーションの目的でDigitalOcean Kubernetesクラスターを使用するため、このガイドではストレージクラスを「 do-block-storage +」と定義します。 Kubernetesクラスターを実行している場所に応じて、この値を変更する必要があります。 詳細については、https://kubernetes.io/docs/concepts/storage/persistent-volumes/ [Persistent Volume]ドキュメントを参照してください。

最後に、各PersistentVolumeのサイズを100GiBにすることを指定します。 生産のニーズに応じてこの値を調整する必要があります。

完全なStatefulSet仕様は次のようになります。

elasticsearch_statefulset.yaml

apiVersion: apps/v1
kind: StatefulSet
metadata:
 name: es-cluster
 namespace: kube-logging
spec:
 serviceName: elasticsearch
 replicas: 3
 selector:
   matchLabels:
     app: elasticsearch
 template:
   metadata:
     labels:
       app: elasticsearch
   spec:
     containers:
     - name: elasticsearch
       image: docker.elastic.co/elasticsearch/elasticsearch:7.2.0
       resources:
           limits:
             cpu: 1000m
           requests:
             cpu: 100m
       ports:
       - containerPort: 9200
         name: rest
         protocol: TCP
       - containerPort: 9300
         name: inter-node
         protocol: TCP
       volumeMounts:
       - name: data
         mountPath: /usr/share/elasticsearch/data
       env:
         - name: cluster.name
           value: k8s-logs
         - name: node.name
           valueFrom:
             fieldRef:
               fieldPath: metadata.name
         - name: discovery.seed_hosts
           value: "es-cluster-0.elasticsearch,es-cluster-1.elasticsearch,es-cluster-2.elasticsearch"
         - name: cluster.initial_master_nodes
           value: "es-cluster-0,es-cluster-1,es-cluster-2"
         - name: ES_JAVA_OPTS
           value: "-Xms512m -Xmx512m"
     initContainers:
     - name: fix-permissions
       image: busybox
       command: ["sh", "-c", "chown -R 1000:1000 /usr/share/elasticsearch/data"]
       securityContext:
         privileged: true
       volumeMounts:
       - name: data
         mountPath: /usr/share/elasticsearch/data
     - name: increase-vm-max-map
       image: busybox
       command: ["sysctl", "-w", "vm.max_map_count=262144"]
       securityContext:
         privileged: true
     - name: increase-fd-ulimit
       image: busybox
       command: ["sh", "-c", "ulimit -n 65536"]
       securityContext:
         privileged: true
 volumeClaimTemplates:
 - metadata:
     name: data
     labels:
       app: elasticsearch
   spec:
     accessModes: [ "ReadWriteOnce" ]
     storageClassName: do-block-storage
     resources:
       requests:
         storage: 100Gi

Elasticsearchの構成に満足したら、ファイルを保存して閉じます。

次に、 `+ kubectl +`を使用してStatefulSetをデプロイします。

kubectl create -f elasticsearch_statefulset.yaml

次のような出力が表示されるはずです。

Outputstatefulset.apps/es-cluster created

`+ kubectl rollout status`を使用して、ロールアウトされるStatefulSetを監視できます。

kubectl rollout status sts/es-cluster --namespace=kube-logging

クラスターがロールアウトされると、次の出力が表示されるはずです。

OutputWaiting for 3 pods to be ready...
Waiting for 2 pods to be ready...
Waiting for 1 pods to be ready...
partitioned roll out complete: 3 new pods have been updated...

すべてのPodがデプロイされたら、REST APIに対してリクエストを実行して、Elasticsearchクラスターが正しく機能していることを確認できます。

これを行うには、まず、 + kubectl port-forward +`を使用して、Elasticsearchノードの1つ( `+ es-cluster-0 +)のポート `+ 9200 `にローカルポート ` 9200 +`を転送します。

kubectl port-forward es-cluster-0 9200:9200 --namespace=kube-logging

次に、別のターミナルウィンドウで、REST APIに対して「+ curl +」リクエストを実行します。

curl http://localhost:9200/_cluster/state?pretty

次の出力が表示されます。

Output{
 "cluster_name" : "k8s-logs",
 "compressed_size_in_bytes" : 348,
 "cluster_uuid" : "QD06dK7CQgids-GQZooNVw",
 "version" : 3,
 "state_uuid" : "mjNIWXAzQVuxNNOQ7xR-qg",
 "master_node" : "IdM5B7cUQWqFgIHXBp0JDg",
 "blocks" : { },
 "nodes" : {
   "u7DoTpMmSCixOoictzHItA" : {
     "name" : "es-cluster-1",
     "ephemeral_id" : "ZlBflnXKRMC4RvEACHIVdg",
     "transport_address" : "10.244.8.2:9300",
     "attributes" : { }
   },
   "IdM5B7cUQWqFgIHXBp0JDg" : {
     "name" : "es-cluster-0",
     "ephemeral_id" : "JTk1FDdFQuWbSFAtBxdxAQ",
     "transport_address" : "10.244.44.3:9300",
     "attributes" : { }
   },
   "R8E7xcSUSbGbgrhAdyAKmQ" : {
     "name" : "es-cluster-2",
     "ephemeral_id" : "9wv6ke71Qqy9vk2LgJTqaA",
     "transport_address" : "10.244.40.4:9300",
     "attributes" : { }
   }
 },
...

これは、Elasticsearchクラスター + k8s-logs +`が3つのノードで正常に作成されたことを示します: `+ es-cluster-0 ++ es-cluster-1 +、および + es-cluster-2 + 。 現在のマスターノードは「+ es-cluster-0 +」です。

Elasticsearchクラスターが稼働しているので、Kibanaフロントエンドのセットアップに進むことができます。

手順3-Kibanaの展開とサービスの作成

KubernetesでKibanaを起動するには、「+ kibana 」というサービスと、1つのPodレプリカで構成される展開を作成します。 実稼働のニーズに応じてレプリカの数をスケーリングし、オプションでサービスの ` LoadBalancer +`タイプを指定して、展開ポッド全体でリクエストの負荷を分散できます。

今回は、同じファイルにサービスとデプロイを作成します。 お気に入りのエディターで `+ kibana.yaml +`というファイルを開きます:

nano kibana.yaml

次のサービス仕様を貼り付けます。

kibana.yaml

apiVersion: v1
kind: Service
metadata:
 name: kibana
 namespace: kube-logging
 labels:
   app: kibana
spec:
 ports:
 - port: 5601
 selector:
   app: kibana
---
apiVersion: apps/v1
kind: Deployment
metadata:
 name: kibana
 namespace: kube-logging
 labels:
   app: kibana
spec:
 replicas: 1
 selector:
   matchLabels:
     app: kibana
 template:
   metadata:
     labels:
       app: kibana
   spec:
     containers:
     - name: kibana
       image: docker.elastic.co/kibana/kibana:7.2.0
       resources:
         limits:
           cpu: 1000m
         requests:
           cpu: 100m
       env:
         - name: ELASTICSEARCH_URL
           value: http://elasticsearch:9200
       ports:
       - containerPort: 5601

次に、ファイルを保存して閉じます。

この仕様では、 `+ kube-logging `名前空間で ` kibana `というサービスを定義し、 ` app:kibana +`ラベルを付けました。

また、ポート「5601」でアクセスできるように指定し、「+ app:kibana +」ラベルを使用してサービスのターゲットポッドを選択します。

`+ Deployment `仕様では、 ` kibana +`というデプロイメントを定義し、1つのPodレプリカが必要であることを指定します。

`+ docker.elastic.co / kibana / kibana:7.2.0 +`イメージを使用します。 この時点で、独自のプライベートまたはパブリックKibanaイメージを代わりに使用できます。

ポッドに対して少なくとも0.1 vCPUを保証し、1 vCPUの制限までバーストすることを指定します。 これらのパラメータは、予想される負荷と利用可能なリソースに応じて変更できます。

次に、 `+ ELASTICSEARCH_URL `環境変数を使用して、Elasticsearchクラスターのエンドポイントとポートを設定します。 Kubernetes DNSを使用すると、このエンドポイントはサービス名「 elasticsearch +」に対応します。 このドメインは、3つのElasticsearchポッドのIPアドレスのリストに解決されます。 Kubernetes DNSの詳細については、https://kubernetes.io/docs/concepts/services-networking/dns-pod-service/#services [サービスとポッドのDNS]をご覧ください。

最後に、Kibanaのコンテナポートを「5601」に設定し、「+ kibana +」サービスがリクエストを転送します。

Kibanaの設定に満足したら、 `+ kubectl +`を使用してサービスとデプロイを展開できます。

kubectl create -f kibana.yaml

次のような出力が表示されるはずです。

Outputservice/kibana created
deployment.apps/kibana created

次のコマンドを実行して、ロールアウトが成功したことを確認できます。

kubectl rollout status deployment/kibana --namespace=kube-logging

次のような出力が表示されるはずです。

Outputdeployment "kibana" successfully rolled out

Kibanaインターフェースにアクセスするために、ローカルポートをKibanaを実行しているKubernetesノードにもう一度転送します。 `+ kubectl get +`を使用してKibanaポッドの詳細を取得します。

kubectl get pods --namespace=kube-logging
OutputNAME                      READY     STATUS    RESTARTS   AGE
es-cluster-0              1/1       Running   0          55m
es-cluster-1              1/1       Running   0          54m
es-cluster-2              1/1       Running   0          54m
kibana-6c9fb4b5b7-plbg2   1/1       Running   0          4m27s

ここでは、キバナポッドが「+ kibana-6c9fb4b5b7-plbg2 +」と呼ばれることを確認します。

ローカルポート「5601」をこのポッドのポート「5601」に転送します。

kubectl port-forward kibana-6c9fb4b5b7-plbg2 5601:5601 --namespace=kube-logging

次のような出力が表示されるはずです。

OutputForwarding from 127.0.0.1:5601 -> 5601
Forwarding from [::1]:5601 -> 5601

次に、Webブラウザで次のURLにアクセスします。

http://localhost:5601

次のKibanaウェルカムページが表示されたら、KubernetesクラスターにKibanaが正常にデプロイされています。

image:https://assets.digitalocean.com/articles/kubernetes_efk/kibana_welcome.png [Kibana Welcome Screen]

これで、EFKスタックの最終コンポーネントであるログコレクターFluentdの展開に進むことができます。

ステップ4-Fluentd DaemonSetの作成

このガイドでは、FluentdをDaemonSetとして設定します。これは、Kubernetesクラスター内の各ノードで特定のPodのコピーを実行するKubernetesワークロードタイプです。 このDaemonSetコントローラーを使用して、クラスター内のすべてのノードでFluentdログエージェントポッドを展開します。 このロギングアーキテクチャの詳細については、公式Kubernetesの「https://kubernetes.io/docs/concepts/cluster-administration/logging/#using-a-node-logging-agent [ノードロギングエージェントの使用]」を参照してください。 docs。

Kubernetesでは、 `+ stdout `および ` stderr +`にログを記録するコンテナ化されたアプリケーションのログストリームがキャプチャされ、ノード上のJSONファイルにリダイレクトされます。 Fluentd Podは、これらのログファイルを追跡し、ログイベントをフィルター処理し、ログデータを変換し、https://www.digitalocean.com/community/tutorials/how-to-set-でデプロイしたElasticsearchロギングバックエンドに発送します。 Elasticsearch-fluentd-and-kibana-efk-logging-on-kubernetes#step-2-%E2%80%94-creating-the-elasticsearch-statefulset [ステップ2]。

Fluentdエージェントは、コンテナログに加えて、kubelet、kube-proxy、DockerログなどのKubernetesシステムコンポーネントログを追跡します。 Fluentdロギングエージェントによって生成されたソースの完全なリストを表示するには、https://github.com/fluent/fluentd-kubernetes-daemonset/blob/master/docker-image/v0.12/debian-elasticsearch/conf/を参照してください。ロギングエージェントの設定に使用されるkubernetes.conf [+ kubernetes.conf +]ファイル。 Kubernetesクラスターでのロギングの詳細については、公式の「https://kubernetes.io/docs/concepts/cluster-administration/logging/#logging-at-the-node-level [ノードレベルでのロギング]」を参照してください。 Kubernetesのドキュメント。

お気に入りのテキストエディタで「+ fluentd.yaml +」というファイルを開くことから始めます。

nano fluentd.yaml

繰り返しになりますが、Kubernetesオブジェクト定義をブロックごとに貼り付けて、コンテキストを提供します。 このガイドでは、Fluentdメンテナーが提供するhttps://github.com/fluent/fluentd-kubernetes-daemonset/blob/master/fluentd-daemonset-elasticsearch-rbac.yaml[Fluentd DaemonSet spec]を使用します。 Fluentdメンテナーが提供するもう1つの役立つリソースは、https://docs.fluentd.org/v/0.12/articles/kubernetes-fluentd [Kuberentes Fluentd]です。

まず、次のServiceAccount定義を貼り付けます。

fluentd.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
 name: fluentd
 namespace: kube-logging
 labels:
   app: fluentd

ここでは、Fluentd PodsがKubernetes APIへのアクセスに使用する「+ fluentd 」というサービスアカウントを作成します。 これを「 kube-logging 」名前空間で作成し、もう一度「 app:fluentd +」というラベルを付けます。 Kubernetesのサービスアカウントの詳細については、公式Kubernetesドキュメントのhttps://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/ [ポッドのサービスアカウントの構成]を参照してください。

次に、次の `+ ClusterRole +`ブロックに貼り付けます:

fluentd.yaml

. . .
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
 name: fluentd
 labels:
   app: fluentd
rules:
- apiGroups:
 - ""
 resources:
 - pods
 - namespaces
 verbs:
 - get
 - list
 - watch

ここでは、 + pods`および + namespaces`オブジェクトに対する + get ++ list +、および `+ watch `権限を付与する ` fluentd`というクラスターロールを定義します。 ClusterRolesを使用すると、ノードなどのクラスタースコープのKubernetesリソースへのアクセスを許可できます。 役割ベースのアクセス制御とクラスター役割の詳細については、Kubernetesの公式ドキュメントのhttps://kubernetes.io/docs/reference/access-authn-authz/rbac/[RBAC認証の使用]をご覧ください。

ここで、次の `+ ClusterRoleBinding +`ブロックに貼り付けます:

fluentd.yaml

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

このブロックでは、 + fluentd + ClusterRoleを + fluentd +`サービスアカウントにバインドする `+ fluentd +`と呼ばれる `+ ClusterRoleBinding +`を定義します。 これにより、 `+ fluentd + ServiceAccountに `+ fluentd +`クラスターロールにリストされている権限が付与されます。

この時点で、実際のDaemonSet仕様の貼り付けを開始できます。

fluentd.yaml

. . .
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
 name: fluentd
 namespace: kube-logging
 labels:
   app: fluentd

ここでは、 `+ kube-logging `名前空間で ` fluentd `というDaemonSetを定義し、 ` app:fluentd +`ラベルを付けます。

次に、次のセクションに貼り付けます。

fluentd.yaml

. . .
spec:
 selector:
   matchLabels:
     app: fluentd
 template:
   metadata:
     labels:
       app: fluentd
   spec:
     serviceAccount: fluentd
     serviceAccountName: fluentd
     tolerations:
     - key: node-role.kubernetes.io/master
       effect: NoSchedule
     containers:
     - name: fluentd
       image: fluent/fluentd-kubernetes-daemonset:v1.4.2-debian-elasticsearch-1.1
       env:
         - name:  FLUENT_ELASTICSEARCH_HOST
           value: "elasticsearch.kube-logging.svc.cluster.local"
         - name:  FLUENT_ELASTICSEARCH_PORT
           value: "9200"
         - name: FLUENT_ELASTICSEARCH_SCHEME
           value: "http"
         - name: FLUENTD_SYSTEMD_CONF
           value: disable

ここでは、 `+ .metadata.labels `で定義されている ` app:fluentd `ラベルを照合し、DaemonSetに ` fluentd `サービスアカウントを割り当てます。 また、このDaemonSetが管理するポッドとして「 app:fluentd +」を選択します。

次に、Kubernetesマスターノードの同等の汚染に一致するように、「+ NoSchedule +」許容値を定義します。 これにより、DaemonSetもKubernetesマスターに確実にロールアウトされます。 マスターノードでFluentd Podを実行したくない場合は、この許容を削除します。 Kubernetesの汚染と許容の詳細​​については、Kubernetesの公式ドキュメントの「https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/[Taints and Tolerations]」を参照してください。

次に、 `+ fluentd +`と呼ばれるPodコンテナの定義を開始します。

Fluentdメンテナーが提供するhttps://hub.docker.com/r/fluent/fluentd-kubernetes-daemonset/[official v1.4.2 Debian image]を使用します。 独自のプライベートまたはパブリックFluentdイメージを使用する場合、または別のイメージバージョンを使用する場合は、コンテナ仕様の `+ image +`タグを変更します。 Dockerfileとこのイメージのコンテンツは、Fluentdのhttps://github.com/fluent/fluentd-kubernetes-daemonset/tree/master/docker-image/v1.4/debian-elasticsearch[fluentd-kubernetes-daemonset Github repoで入手できます。 ]。

次に、いくつかの環境変数を使用してFluentdを構成します。

  • + FLUENT_ELASTICSEARCH_HOST +:これを、先に定義したElasticsearchヘッドレスサービスアドレスに設定します: + elasticsearch.kube-logging.svc.cluster.local +。 これは、3つのElasticsearchポッドのIPアドレスのリストに解決されます。 実際のElasticsearchホストは、おそらくこのリストで最初に返されるIPアドレスです。 クラスター全体にログを配布するには、FluentdのElasticsearch Outputプラグインの構成を変更する必要があります。 このプラグインの詳細については、https://docs.fluentd.org/v1.0/articles/out_elasticsearch#hosts-(オプション)[Elasticsearch Output Plugin]をご覧ください。

  • + FLUENT_ELASTICSEARCH_PORT +:これを以前に設定したElasticsearchポートである `+ 9200 +`に設定します。

  • + FLUENT_ELASTICSEARCH_SCHEME +:これを `+ http +`に設定します。

  • + FLUENTD_SYSTEMD_CONF +:これを `+ disable `に設定して、コンテナに設定されていない ` systemd +`に関連する出力を抑制します。

最後に、次のセクションに貼り付けます。

fluentd.yaml

. . .
       resources:
         limits:
           memory: 512Mi
         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

ここでは、FluentDポッドに512 MiBのメモリ制限を指定し、0.1vCPUと200MiBのメモリを保証します。 予想されるログボリュームと利用可能なリソースに応じて、これらのリソース制限とリクエストを調整できます。

次に、 `+ varlog `と ` varlibdockercontainers `と ` volumeMounts `を使用して、 ` / var / log `と ` / var / lib / docker / containers `のホストパスをコンテナーにマウントします。 これらの「+ボリューム」はブロックの最後に定義されます。

このブロックで定義する最後のパラメーターは「+ terminationGracePeriodSeconds 」です。これにより、「 SIGTERM 」シグナルを受信すると、Fluentdが正常にシャットダウンできるようになります。 30秒後、コンテナには「 SIGKILL 」シグナルが送信されます。 ` terminationGracePeriodSeconds +`のデフォルト値は30秒​​であるため、ほとんどの場合、このパラメーターは省略できます。 Kubernetesのワークロードを正常に終了する方法の詳細については、Googleの「https://cloud.google.com/blog/products/gcp/kubernetes-best-practices-terminating-with-grace[Kubernetesベストプラクティス:猶予で終了]」を参照してください。

Fluentdの仕様全体は次のようになります。

fluentd.yaml

apiVersion: v1
kind: ServiceAccount
metadata:
 name: fluentd
 namespace: kube-logging
 labels:
   app: fluentd
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
 name: fluentd
 labels:
   app: fluentd
rules:
- apiGroups:
 - ""
 resources:
 - pods
 - namespaces
 verbs:
 - get
 - list
 - watch
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
 name: fluentd
roleRef:
 kind: ClusterRole
 name: fluentd
 apiGroup: rbac.authorization.k8s.io
subjects:
- kind: ServiceAccount
 name: fluentd
 namespace: kube-logging
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
 name: fluentd
 namespace: kube-logging
 labels:
   app: fluentd
spec:
 selector:
   matchLabels:
     app: fluentd
 template:
   metadata:
     labels:
       app: fluentd
   spec:
     serviceAccount: fluentd
     serviceAccountName: fluentd
     tolerations:
     - key: node-role.kubernetes.io/master
       effect: NoSchedule
     containers:
     - name: fluentd
       image: fluent/fluentd-kubernetes-daemonset:v1.4.2-debian-elasticsearch-1.1
       env:
         - name:  FLUENT_ELASTICSEARCH_HOST
           value: "elasticsearch.kube-logging.svc.cluster.local"
         - name:  FLUENT_ELASTICSEARCH_PORT
           value: "9200"
         - name: FLUENT_ELASTICSEARCH_SCHEME
           value: "http"
         - name: FLUENTD_SYSTEMD_CONF
           value: disable
       resources:
         limits:
           memory: 512Mi
         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

Fluentd DaemonSetの構成が完了したら、ファイルを保存して閉じます。

次に、 `+ kubectl +`を使用してDaemonSetをロールアウトします。

kubectl create -f fluentd.yaml

次のような出力が表示されるはずです。

Outputserviceaccount/fluentd created
clusterrole.rbac.authorization.k8s.io/fluentd created
clusterrolebinding.rbac.authorization.k8s.io/fluentd created
daemonset.extensions/fluentd created

`+ kubectl +`を使用してDaemonSetが正常に展開されたことを確認します。

kubectl get ds --namespace=kube-logging

次のステータス出力が表示されます。

OutputNAME      DESIRED   CURRENT   READY     UP-TO-DATE   AVAILABLE   NODE SELECTOR   AGE
fluentd   3         3         3         3            3           <none>          58s

これは、3つの「+ fluentd +」ポッドが実行されていることを示しています。これは、Kubernetesクラスター内のノードの数に対応しています。

Kibanaをチェックして、ログデータが適切に収集され、Elasticsearchに送信されていることを確認できます。

`+ kubectl port-forward `を開いたまま、 ` http:// localhost:5601 +`に移動します。

左側のナビゲーションメニューで[検出]をクリックします。

image:https://assets.digitalocean.com/articles/kubernetes_efk/kibana_discover.png [Kibana Discover]

次の構成ウィンドウが表示されます。

image:https://assets.digitalocean.com/articles/kubernetes_efk/kibana_index.png [Kibana Index Pattern Configuration]

これにより、Kibanaで探索したいElasticsearchインデックスを定義できます。 詳細については、Kibana公式ドキュメントのhttps://www.elastic.co/guide/en/kibana/current/tutorial-define-index.html [インデックスパターンの定義]を参照してください。 とりあえず、 `+ logstash-* `ワイルドカードパターンを使用して、Elasticsearchクラスター内のすべてのログデータをキャプチャします。 テキストボックスに「 logstash-* +」と入力し、[次のステップ]をクリックします。

その後、次のページに移動します。

image:https://assets.digitalocean.com/articles/kubernetes_efk/kibana_index_settings.png [Kibana Index Pattern Settings]

これにより、Kibanaがログデータを時間でフィルタリングするために使用するフィールドを構成できます。 ドロップダウンで、* @ timestamp フィールドを選択し、 Create index pattern *を押します。

次に、左側のナビゲーションメニューで[検出]をクリックします。

ヒストグラムグラフといくつかの最近のログエントリが表示されます。

image:https://assets.digitalocean.com/articles/kubernetes_efk/kibana_logs.png [Kibana Incoming Logs]

この時点で、KubernetesクラスターでEFKスタックの構成とロールアウトが正常に完了しました。 Kibanaを使用してログデータを分析する方法については、https://www.elastic.co/guide/en/kibana/current/index.html [Kibana User Guide]を参照してください。

次のオプションセクションでは、数値を標準出力に出力する単純なカウンターポッドをデプロイし、Kibanaでログを検索します。

ステップ5(オプション)-コンテナーロギングのテスト

特定のポッドの最新ログを調査する基本的なKibanaの使用例を示すために、連続番号を標準出力に出力する最小限のカウンターポッドを展開します。

ポッドを作成することから始めましょう。 お気に入りのエディターで `+ counter.yaml +`というファイルを開きます:

nano counter.yaml

次に、次のポッド仕様を貼り付けます。

counter.yaml

apiVersion: v1
kind: Pod
metadata:
 name: counter
spec:
 containers:
 - name: count
   image: busybox
   args: [/bin/sh, -c,
           'i=0; while true; do echo "$i: $(date)"; i=$((i+1)); sleep 1; done']

ファイルを保存して閉じます。

これは、「+ while」ループを実行し、数字を順番に出力する「+ counter +」と呼ばれる最小限のポッドです。

`+ kubectl `を使用して ` counter +`ポッドをデプロイします。

kubectl create -f counter.yaml

ポッドを作成して実行したら、Kibanaダッシュボードに戻ります。

  • Discover *ページから、検索バーに「+ kubernetes.pod_name:counter 」と入力します。 これは、 ` counter +`という名前のポッドのログデータをフィルターします。

次に、 `+ counter +`ポッドのログエントリのリストが表示されます。

image:https://assets.digitalocean.com/articles/kubernetes_efk/counter_logs.png [Kibanaのカウンターログ]

任意のログエントリをクリックして、コンテナ名、Kubernetesノード、ネームスペースなどの追加のメタデータを表示できます。

結論

このガイドでは、KubernetesクラスターでElasticsearch、Fluentd、Kibanaを設定および構成する方法を示しました。 各Kubernetesワーカーノードで実行される単一のログエージェントポッドで構成される最小限のログアーキテクチャを使用しました。

このロギングスタックを運用Kubernetesクラスターにデプロイする前に、このガイド全体で示されているリソース要件と制限を調整することをお勧めします。 また、https://www.elastic.co/guide/en/elasticsearch/reference/current/setup-xpack.html [X-Pack]をセットアップして、組み込みの監視およびセキュリティ機能を有効にすることもできます。

ここで使用したロギングアーキテクチャは、3つのElasticsearchポッド、単一のKibanaポッド(負荷分散されていない)、およびDaemonSetとして展開されたFluentdポッドのセットで構成されています。 実稼働ユースケースに応じて、このセットアップをスケーリングすることもできます。 ElasticsearchとKibanaスタックのスケーリングの詳細については、https://www.elastic.co/blog/small-medium-or-large-scaling-elasticsearch-and-evolving-the-elastic-stack-to-fit [ Elasticsearchのスケーリング]。

Kubernetesでは、ユースケースにより適した、より複雑なログエージェントアーキテクチャも使用できます。 詳細については、Kubernetesドキュメントのhttps://kubernetes.io/docs/concepts/cluster-administration/logging/[Logging Architecture]を参照してください。

Related