KubernetesでElasticsearch、Fluentd、Kibana(EFK)のログスタックを設定する方法
序章
Kubernetesクラスタで複数のサービスとアプリケーションを実行する場合、一元化されたクラスタレベルのログスタックを使用すると、ポッドによって生成された大量のログデータをすばやく並べ替えて分析できます。 人気のある集中型ロギングソリューションの1つは、 E lasticsearch、 F luentd、および K ibana(EFK)スタックです。
Elasticsearch は、分析だけでなく、フルテキストおよび構造化された検索を可能にする、リアルタイムの分散型のスケーラブルな検索エンジンです。 大量のログデータのインデックス作成と検索に一般的に使用されますが、さまざまな種類のドキュメントの検索にも使用できます。
Elasticsearchは通常、Elasticsearchの強力なデータ視覚化フロントエンドおよびダッシュボードであるKibanaと一緒にデプロイされます。 Kibanaを使用すると、Webインターフェイスを介してElasticsearchログデータを探索し、ダッシュボードとクエリを作成して、質問にすばやく回答し、Kubernetesアプリケーションに関する洞察を得ることができます。
このチュートリアルでは、 Fluentd を使用して、ログデータを収集、変換し、Elasticsearchバックエンドに送信します。 Fluentdは人気のあるオープンソースのデータコレクターであり、Kubernetesノードにセットアップしてコンテナーログファイルを調整し、ログデータをフィルター処理して変換し、Elasticsearchクラスターに配信してインデックスを作成して保存します。
まず、スケーラブルなElasticsearchクラスターを構成して起動し、次にKibana Kubernetes ServiceandDeploymentを作成します。 結論として、FluentdをDaemonSetとして設定し、すべてのKubernetesワーカーノードで実行されるようにします。
前提条件
このガイドを開始する前に、次のものを利用できることを確認してください。
-
ロールベースのアクセス制御(RBAC)が有効になっているKubernetes1.10+クラスター
- クラスターにEFKスタックをロールアウトするのに十分なリソースがあることを確認し、そうでない場合は、ワーカーノードを追加してクラスターをスケーリングします。 3ポッドのElasticsearchクラスター(必要に応じてこれを1にスケールダウンできます)と、単一のKibanaポッドをデプロイします。 すべてのワーカーノードはFluentdポッドも実行します。 このガイドのクラスターは、3つのワーカーノードとマネージドコントロールプレーンで構成されています。
-
The
kubectl
ローカルマシンにインストールされ、クラスターに接続するように構成されたコマンドラインツール。 インストールについてもっと読むことができますkubectl
公式ドキュメント。
これらのコンポーネントを設定したら、このガイドを開始する準備が整います。
ステップ1—名前空間を作成する
Elasticsearchクラスターをロールアウトする前に、まず名前空間を作成し、そこにすべてのロギングインストルメンテーションをインストールします。 Kubernetesでは、ネームスペースと呼ばれる「仮想クラスター」抽象化を使用して、クラスターで実行されているオブジェクトを分離できます。 このガイドでは、 kube-logging
EFKスタックコンポーネントをインストールする名前空間。 この名前空間を使用すると、Kubernetesクラスターの機能を失うことなく、ログスタックをすばやくクリーンアップして削除することもできます。
まず、を使用してクラスター内の既存の名前空間を調査します kubectl
:
- kubectl get namespaces
Kubernetesクラスタにプリインストールされている次の3つの初期ネームスペースが表示されます。
OutputNAME STATUS AGE
default Active 5m
kube-system Active 5m
kube-public Active 5m
The default
名前空間には、名前空間を指定せずに作成されたオブジェクトが格納されます。 The kube-system
名前空間には、Kubernetesシステムによって作成および使用されるオブジェクトが含まれます。 kube-dns
, kube-proxy
、 と kubernetes-dashboard
. この名前空間をクリーンに保ち、アプリケーションやインストルメンテーションのワークロードで汚染しないようにすることをお勧めします。
The kube-public
名前空間は、認証されていないユーザーであっても、クラスター全体で読み取りおよびアクセスできるようにするオブジェクトを格納するために使用できる、もう1つの自動的に作成された名前空間です。
を作成するには kube-logging
名前空間、最初にというファイルを開いて編集します kube-logging.yaml
nanoなどのお気に入りのエディターを使用する:
- nano kube-logging.yaml
エディター内に、次の名前空間オブジェクトYAMLを貼り付けます。
kind: Namespace
apiVersion: v1
metadata:
name: kube-logging
次に、ファイルを保存して閉じます。
ここでは、Kubernetesオブジェクトのを指定します kind
として Namespace
物体。 詳細については Namespace
オブジェクトについては、Kubernetesの公式ドキュメントの名前空間ウォークスルーを参照してください。 オブジェクトの作成に使用されるKubernetesAPIバージョンも指定します(v1
)、そしてそれに与える name
, kube-logging
.
作成したら kube-logging.yaml
名前空間オブジェクトファイル、を使用して名前空間を作成します kubectl create
とともに -f
ファイル名フラグ:
- 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—ElasticsearchStatefulSetを作成する
ロギングスタックを格納する名前空間を作成したので、さまざまなコンポーネントの展開を開始できます。 まず、3ノードのElasticsearchクラスターをデプロイすることから始めます。
このガイドでは、3つのElasticsearchポッドを使用して、可用性の高いマルチノードクラスターで発生する「スプリットブレイン」の問題を回避します。 大まかに言うと、「スプリットブレイン」とは、1つ以上のノードが他のノードと通信できず、複数の「スプリット」マスターが選出されたときに発生するものです。 3つのノードでは、1つが一時的にクラスターから切断された場合、他の2つのノードは新しいマスターを選択でき、最後のノードが再参加を試みている間、クラスターは機能し続けることができます。 詳細については、Elasticsearchおよび投票構成でのクラスター調整の新時代を参照してください。
ヘッドレスサービスの作成
まず、ヘッドレスKubernetesサービスを作成します。 elasticsearch
これにより、3つのポッドのDNSドメインが定義されます。 ヘッドレスサービスは、ロードバランシングを実行したり、静的IPを使用したりしません。 ヘッドレスサービスの詳細については、公式のKubernetesドキュメントを参照してください。
というファイルを開きます elasticsearch_svc.yaml
お気に入りのエディターを使用する:
- nano elasticsearch_svc.yaml
次のKubernetesサービス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
次に、ファイルを保存して閉じます。
を定義します Service
と呼ばれる elasticsearch
の中に kube-logging
名前空間、そしてそれに与える app: elasticsearch
ラベル。 次に、 .spec.selector
に app: elasticsearch
サービスがポッドを選択するように app: elasticsearch
ラベル。 Elasticsearch StatefulSetをこのサービスに関連付けると、サービスはElasticsearchポッドを指すDNSAレコードを返します。 app: elasticsearch
ラベル。
次に設定します clusterIP: None
、サービスをヘッドレスにします。 最後に、ポートを定義します 9200
と 9300
これらは、REST APIとの対話、およびノード間通信にそれぞれ使用されます。
を使用してサービスを作成します 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には、ポッドの再スケジュールと再起動の間でデータを永続化するための安定したストレージが必要です。 StatefulSetワークロードの詳細については、KubernetesドキュメントのStatefulsetsページを参照してください。
というファイルを開きます elasticsearch_statefulset.yaml
お気に入りのエディターで:
- nano elasticsearch_statefulset.yaml
StatefulSetオブジェクト定義をセクションごとに移動し、ブロックをこのファイルに貼り付けます。
次のブロックに貼り付けることから始めます。
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
このブロックでは、次のように呼ばれるStatefulSetを定義します es-cluster
の中に kube-logging
名前空間。 次に、それを以前に作成したものと関連付けます elasticsearch
を使用したサービス serviceName
分野。 これにより、StatefulSet内の各ポッドに次のDNSアドレスを使用してアクセスできるようになります。 es-cluster-[0,1,2].elasticsearch.kube-logging.svc.cluster.local
、 どこ [0,1,2]
ポッドに割り当てられた整数の序数に対応します。
3を指定します replicas
(ポッド)とを設定します matchLabels
セレクター app: elasticseach
、次にミラーリングします .spec.template.metadata
セクション。 The .spec.selector.matchLabels
と .spec.template.metadata.labels
フィールドは一致する必要があります。
これで、オブジェクトの仕様に進むことができます。 前のブロックのすぐ下にある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.1vCPUが保証され、最大1 vCPUまでバーストできることを指定するフィールド(これにより、最初の大量の取り込みを実行するとき、または負荷の急増に対処するときのポッドのリソース使用量が制限されます)。 予想される負荷と利用可能なリソースに応じて、これらの値を変更する必要があります。 リソースのリクエストと制限の詳細については、公式の KubernetesDocumentationを参照してください。
次に、ポートを開いて名前を付けます 9200
と 9300
それぞれRESTAPIとノード間通信用。 指定します volumeMount
と呼ばれる data
名前の付いたPersistentVolumeをマウントします data
パスのコンテナに /usr/share/elasticsearch/data
. このStatefulSetのVolumeClaimsは、後のYAMLブロックで定義します。
最後に、コンテナにいくつかの環境変数を設定します。
cluster.name
:Elasticsearchクラスターの名前。このガイドでは次のようになります。k8s-logs
.node.name
:ノードの名前。.metadata.name
フィールド使用valueFrom
. これはに解決されますes-cluster-[0,1,2]
、ノードに割り当てられた序数によって異なります。discovery.seed_hosts
:このフィールドは、ノード検出プロセスをシードするクラスター内のマスター適格ノードのリストを設定します。 このガイドでは、以前に構成したヘッドレスサービスのおかげで、ポッドには次の形式のドメインがありますes-cluster-[0,1,2].elasticsearch.kube-logging.svc.cluster.local
、したがって、この変数をそれに応じて設定します。 ローカル名前空間KubernetesDNS解決を使用して、これを次のように短縮できますes-cluster-[0,1,2].elasticsearch
. Elasticsearchディスカバリーの詳細については、公式のElasticsearchドキュメントを参照してください。cluster.initial_master_nodes
:このフィールドは、マスター選出プロセスに参加するマスター適格ノードのリストも指定します。 このフィールドでは、ノードをノードで識別する必要があることに注意してくださいnode.name
、ホスト名ではありません。ES_JAVA_OPTS
:ここではこれをに設定します-Xms512m -Xmx512m
これは、JVMに512MBの最小および最大ヒープサイズを使用するように指示します。 クラスタのリソースの可用性とニーズに応じて、これらのパラメータを調整する必要があります。 詳細については、ヒープサイズの設定を参照してください。
貼り付ける次のブロックは次のようになります。
. . .
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
このブロックでは、メインの前に実行されるいくつかのInitコンテナを定義します elasticsearch
アプリコンテナ。 これらの初期化コンテナはそれぞれ、定義された順序で最後まで実行されます。 Init Containersの詳細については、公式の KubernetesDocumentationを参照してください。
最初の名前 fix-permissions
、実行します chown
Elasticsearchデータディレクトリの所有者とグループを次のように変更するコマンド 1000:1000
、ElasticsearchユーザーのUID。 デフォルトでは、Kubernetesはデータディレクトリを次のようにマウントします root
、Elasticsearchにアクセスできなくなります。 この手順の詳細については、Elasticsearchの「本番環境での使用とデフォルトに関する注意事項」を参照してください。
2番目の名前 increase-vm-max-map
、コマンドを実行して、オペレーティングシステムのmmapカウントの制限を増やします。これは、デフォルトでは低すぎるため、メモリ不足エラーが発生する可能性があります。 この手順の詳細については、公式のElasticsearchドキュメントを参照してください。
次に実行する初期化コンテナは increase-fd-ulimit
、を実行します ulimit
開いているファイル記述子の最大数を増やすコマンド。 この手順の詳細については、Elasticsearchの公式ドキュメントの「本番環境での使用とデフォルトに関する注意事項」を参照してください。
注: Elasticsearch 本番環境での使用に関する注意には、パフォーマンス上の理由からスワッピングを無効にすることも記載されています。 Kubernetesのインストールまたはプロバイダーによっては、スワッピングがすでに無効になっている場合があります。 これを確認するには、 exec
実行中のコンテナに入れて実行します cat /proc/swaps
アクティブなスワップデバイスを一覧表示します。 そこに何も表示されない場合、スワップは無効になっています。
これで、メインのアプリコンテナーと、コンテナーOSを調整するためにその前に実行されるInitコンテナーを定義したので、StatefulSetオブジェクト定義ファイルに最後の部分を追加できます。 volumeClaimTemplates
.
以下に貼り付けます volumeClaimTemplate
ブロック:
. . .
volumeClaimTemplates:
- metadata:
name: data
labels:
app: elasticsearch
spec:
accessModes: [ "ReadWriteOnce" ]
storageClassName: do-block-storage
resources:
requests:
storage: 100Gi
このブロックでは、StatefulSetを定義します volumeClaimTemplates
. Kubernetesはこれを使用して、ポッドのPersistentVolumesを作成します。 上記のブロックでは、名前を付けています data
(これは name
で参照します volumeMount
s以前に定義された)、そしてそれに同じものを与える app: elasticsearch
StatefulSetとしてラベルを付けます。
次に、そのアクセスモードを次のように指定します。 ReadWriteOnce
、これは、単一のノードによって読み取り/書き込みとしてのみマウントできることを意味します。 ストレージクラスを次のように定義します do-block-storage
このガイドでは、デモ目的でDigitalOceanKubernetesクラスターを使用しているためです。 この値は、Kubernetesクラスターを実行している場所に応じて変更する必要があります。 詳細については、 PersistentVolumeのドキュメントを参照してください。
最後に、各PersistentVolumeのサイズを100GiBにすることを指定します。 制作のニーズに応じて、この値を調整する必要があります。
完全なStatefulSet仕様は、次のようになります。
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の設定に問題がなければ、ファイルを保存して閉じます。
次に、を使用してStatefulSetをデプロイします kubectl
:
- kubectl create -f elasticsearch_statefulset.yaml
次の出力が表示されます。
Outputstatefulset.apps/es-cluster created
StatefulSetは、次を使用して展開されるときに監視できます。 kubectl rollout status
:
- 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...
すべてのポッドがデプロイされたら、REST APIに対してリクエストを実行することで、Elasticsearchクラスターが正しく機能していることを確認できます。
これを行うには、最初にローカルポートを転送します 9200
港へ 9200
Elasticsearchノードの1つ(es-cluster-0
)使用 kubectl port-forward
:
- kubectl port-forward es-cluster-0 9200:9200 --namespace=kube-logging
次に、別のターミナルウィンドウで、 curl
REST APIに対するリクエスト:
- 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つのポッドレプリカで構成されるデプロイメント。 本番環境のニーズに応じてレプリカの数をスケーリングでき、オプションで LoadBalancer
デプロイメントポッド間でリクエストを負荷分散するためのサービスのタイプ。
今回は、同じファイルにサービスとデプロイメントを作成します。 というファイルを開きます kibana.yaml
お気に入りのエディターで:
- nano 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
次に、ファイルを保存して閉じます。
この仕様では、と呼ばれるサービスを定義しました kibana
の中に kube-logging
名前空間、そしてそれに与えた app: kibana
ラベル。
また、ポートからアクセスできるように指定しました 5601
を使用します app: kibana
ラベルを使用して、サービスのターゲットポッドを選択します。
の中に Deployment
仕様では、と呼ばれるデプロイメントを定義します kibana
1つのポッドレプリカが必要であることを指定します。
を使用します docker.elastic.co/kibana/kibana:7.2.0
画像。 この時点で、独自のプライベートまたはパブリックのKibanaイメージを使用するように置き換えることができます。
ポッドに対して少なくとも0.1vCPUを保証し、1vCPUの制限までバーストすることを指定します。 これらのパラメータは、予想される負荷と利用可能なリソースに応じて変更できます。
次に、 ELASTICSEARCH_URL
Elasticsearchクラスターのエンドポイントとポートを設定するための環境変数。 Kubernetes DNSを使用すると、このエンドポイントはそのサービス名に対応します elasticsearch
. このドメインは、3つのElasticsearchポッドのIPアドレスのリストに解決されます。 Kubernetes DNSの詳細については、サービスとポッドの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ノードにもう一度転送します。 を使用してKibanaポッドの詳細を取得します kubectl get
:
- 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ポッドが呼び出されていることを確認します 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ウェルカムページが表示された場合は、KibanaをKubernetesクラスターに正常にデプロイしています。
これで、EFKスタックの最後のコンポーネントであるログコレクターであるFluentdのロールアウトに進むことができます。
ステップ4—FluentdDaemonSetの作成
このガイドでは、FluentdをDaemonSetとして設定します。これは、Kubernetesクラスター内の各ノードで特定のポッドのコピーを実行するKubernetesワークロードタイプです。 このDaemonSetコントローラーを使用して、クラスター内のすべてのノードにFluentdロギングエージェントポッドをロールアウトします。 このロギングアーキテクチャの詳細については、Kubernetesの公式ドキュメントの「ノードロギングエージェントの使用」を参照してください。
Kubernetesでは、にログを記録するコンテナ化されたアプリケーション stdout
と stderr
ログストリームをキャプチャして、ノード上のJSONファイルにリダイレクトします。 Fluentd Podは、これらのログファイルを調整し、ログイベントをフィルタリングし、ログデータを変換して、ステップ2でデプロイしたElasticsearchログバックエンドに送信します。
コンテナログに加えて、Fluentdエージェントは、kubelet、kube-proxy、DockerログなどのKubernetesシステムコンポーネントログを調整します。 Fluentdロギングエージェントによって調整されたソースの完全なリストを確認するには、ロギングエージェントの設定に使用されるkubernetes.confファイルを参照してください。 Kubernetesクラスタへのログインの詳細については、Kubernetesの公式ドキュメントの「ノードレベルでのロギング」を参照してください。
と呼ばれるファイルを開くことから始めます fluentd.yaml
お気に入りのテキストエディタで:
- nano fluentd.yaml
繰り返しになりますが、Kubernetesオブジェクト定義をブロックごとに貼り付けて、コンテキストを提供します。 このガイドでは、Fluentdメンテナが提供するFluentdDaemonSet仕様を使用します。 Fluentdメンテナが提供するもう1つの役立つリソースは、 KuberentesFluentdです。
まず、次のServiceAccount定義を貼り付けます。
apiVersion: v1
kind: ServiceAccount
metadata:
name: fluentd
namespace: kube-logging
labels:
app: fluentd
ここでは、というサービスアカウントを作成します fluentd
FluentdポッドがKubernetesAPIにアクセスするために使用します。 で作成します kube-logging
名前空間ともう一度ラベルを付けます app: fluentd
. Kubernetesのサービスアカウントの詳細については、Kubernetesの公式ドキュメントのポッドのサービスアカウントの設定を参照してください。
次に、以下を貼り付けます ClusterRole
ブロック:
. . .
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: fluentd
labels:
app: fluentd
rules:
- apiGroups:
- ""
resources:
- pods
- namespaces
verbs:
- get
- list
- watch
ここでは、と呼ばれるClusterRoleを定義します fluentd
付与する get
, list
、 と watch
の権限 pods
と namespaces
オブジェクト。 ClusterRolesを使用すると、ノードなどのクラスタースコープのKubernetesリソースへのアクセスを許可できます。 ロールベースのアクセス制御とクラスタロールの詳細については、Kubernetesの公式ドキュメントのRBAC認証の使用を参照してください。
次に、次のように貼り付けます ClusterRoleBinding
ブロック:
. . .
---
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
このブロックでは、 ClusterRoleBinding
と呼ばれる fluentd
をバインドします fluentd
ClusterRoleから fluentd
サービスアカウント。 これにより、 fluentd
ServiceAccountにリストされている権限 fluentd
クラスターの役割。
この時点で、実際のDaemonSet仕様の貼り付けを開始できます。
. . .
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluentd
namespace: kube-logging
labels:
app: fluentd
ここでは、DaemonSetという名前を定義します fluentd
の中に kube-logging
名前空間とそれに与える 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
ここでは、 app: fluentd
で定義されたラベル .metadata.labels
次に、DaemonSetに fluentd
サービスアカウント。 また、 app: fluentd
このDaemonSetによって管理されるポッドとして。
次に、 NoSchedule
Kubernetesマスターノードの同等の汚染に一致する許容範囲。 これにより、DaemonSetもKubernetesマスターにロールアウトされます。 マスターノードでFluentdPodを実行したくない場合は、この許容値を削除してください。 Kubernetesの汚染と許容範囲の詳細については、Kubernetesの公式ドキュメントの「汚染と許容範囲」を参照してください。
次に、ポッドコンテナの定義を開始します。これを呼び出します。 fluentd
.
Fluentdメンテナから提供された公式v1.4.2Debianイメージを使用します。 独自のプライベートまたはパブリックFluentdイメージを使用する場合、または別のイメージバージョンを使用する場合は、 image
コンテナ仕様のタグ。 Dockerfileとこのイメージのコンテンツは、Fluentdのfluentd-kubernetes-daemonsetGithubリポジトリで入手できます。
次に、いくつかの環境変数を使用してFluentdを構成します。
FLUENT_ELASTICSEARCH_HOST
:これを前に定義したElasticsearchヘッドレスサービスアドレスに設定しました:elasticsearch.kube-logging.svc.cluster.local
. これは、3つのElasticsearchポッドのIPアドレスのリストに解決されます。 実際のElasticsearchホストは、このリストで返される最初のIPアドレスである可能性があります。 クラスター全体にログを分散するには、FluentdのElasticsearchOutputプラグインの構成を変更する必要があります。 このプラグインの詳細については、 Elasticsearch OutputPluginを参照してください。FLUENT_ELASTICSEARCH_PORT
:これを以前に構成したElasticsearchポートに設定しました。9200
.FLUENT_ELASTICSEARCH_SCHEME
:これをhttp
.FLUENTD_SYSTEMD_CONF
:これをdisable
関連する出力を抑制するsystemd
コンテナに設定されていません。
最後に、次のセクションに貼り付けます。
. . .
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のメモリを保証します。 予想されるログ量と使用可能なリソースに応じて、これらのリソース制限とリクエストを調整できます。
次に、マウントします /var/log
と /var/lib/docker/containers
を使用してコンテナへのホストパス varlog
と varlibdockercontainers
volumeMounts
. これらは volumes
ブロックの最後に定義されます。
このブロックで定義する最後のパラメーターは terminationGracePeriodSeconds
、これにより、Fluentdは受信時に30秒で正常にシャットダウンします。 SIGTERM
信号。 30秒後、コンテナは SIGKILL
信号。 のデフォルト値 terminationGracePeriodSeconds
は30秒であるため、ほとんどの場合、このパラメーターは省略できます。 Kubernetesワークロードを正常に終了する方法の詳細については、Googleの「 Kubernetesのベストプラクティス:graceで終了する」をご覧ください。
Fluentdの仕様全体は次のようになります。
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の設定が完了したら、ファイルを保存して閉じます。
次に、を使用してDaemonSetを展開します kubectl
:
- 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
DaemonSetがを使用して正常にロールアウトされたことを確認します kubectl
:
- 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
.
左側のナビゲーションメニューでDiscoverをクリックします。
次の設定ウィンドウが表示されます。
これにより、Kibanaで探索するElasticsearchインデックスを定義できます。 詳細については、Kibanaの公式ドキュメントでインデックスパターンの定義を参照してください。 今のところ、 logstash-*
Elasticsearchクラスター内のすべてのログデータをキャプチャするワイルドカードパターン。 入る logstash-*
テキストボックスで、次のステップをクリックします。
その後、次のページに移動します。
これにより、Kibanaがログデータを時間でフィルタリングするために使用するフィールドを構成できます。 ドロップダウンで、 @timestamp フィールドを選択し、インデックスパターンの作成をクリックします。
次に、左側のナビゲーションメニューでDiscoverを押します。
ヒストグラムグラフといくつかの最近のログエントリが表示されます。
この時点で、KubernetesクラスターでEFKスタックを正常に構成してロールアウトできました。 Kibanaを使用してログデータを分析する方法については、Kibanaユーザーガイドを参照してください。
次のオプションのセクションでは、stdoutに数値を出力する単純なカウンターポッドをデプロイし、そのログをKibanaで検索します。
ステップ5(オプション)—コンテナログのテスト
特定のポッドの最新のログを探索する基本的なKibanaのユースケースを示すために、連続番号をstdoutに出力する最小限のカウンターポッドをデプロイします。
ポッドを作成することから始めましょう。 というファイルを開きます counter.yaml
お気に入りのエディターで:
- nano 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']
ファイルを保存して閉じます。
これは、と呼ばれる最小限のポッドです counter
を実行します while
ループ、数字を順番に印刷します。
を展開します counter
ポッドを使用 kubectl
:
- kubectl create -f counter.yaml
ポッドが作成されて実行されたら、Kibanaダッシュボードに戻ります。
Discover ページで、検索バーに次のように入力します kubernetes.pod_name:counter
. これにより、名前が付けられたポッドのログデータがフィルタリングされます counter
.
次に、のログエントリのリストが表示されます。 counter
ポッド:
いずれかのログエントリをクリックすると、コンテナ名、Kubernetesノード、名前空間などの追加のメタデータを表示できます。
結論
このガイドでは、KubernetesクラスターでElasticsearch、Fluentd、およびKibanaをセットアップおよび構成する方法を示しました。 各Kubernetesワーカーノードで実行される単一のロギングエージェントポッドで構成される最小限のロギングアーキテクチャを使用しました。
このロギングスタックを本番Kubernetesクラスターにデプロイする前に、このガイド全体に示されているように、リソースの要件と制限を調整することをお勧めします。 X-Pack を設定して、組み込みの監視およびセキュリティ機能を有効にすることもできます。
ここで使用したロギングアーキテクチャは、3つのElasticsearchポッド、1つのKibanaポッド(負荷分散されていない)、およびDaemonSetとしてロールアウトされたFluentdポッドのセットで構成されています。 本番ユースケースに応じて、この設定を拡張することをお勧めします。 ElasticsearchとKibanaスタックのスケーリングの詳細については、Elasticsearchのスケーリングを参照してください。
Kubernetesでは、ユースケースにより適した、より複雑なロギングエージェントアーキテクチャも使用できます。 詳細については、Kubernetesドキュメントのログアーキテクチャを参照してください。