ビデオ ソース: Station B「Docker&k8s チュートリアルの天井、Station B が教える絶対に最高のもの、Docker のすべてのコア知識を取得するための k8s 学習セットはここにあります」
学習中に先生の授業内容やテストノートを整理してみんなで共有してください。違反しているものは削除されます。よろしくお願いします。
概要投稿を添付してください: K8S+DevOps アーキテクト実践コース | 概要
EFK アーキテクチャのワークフロー
![](https://img-blog.csdnimg.cn/img_convert/5df752f5b5b4f797172e55430335840b.webp?x-oss-process=image/format,png)
- Elasticsearch は、オープンソースの分散型 Restful スタイルの検索およびデータ分析エンジンであり、その最下層はオープンソース ライブラリ Apache Lucene です。これは正確に次のように説明できます: 各フィールドのインデックス付けと検索が可能な分散型リアルタイム ドキュメント ストレージ、分散型リアルタイム分析検索エンジン、数百のサービス ノードを拡張可能、構造化または非構造化 PB レベルの構造をサポートデータ。
- Kibana Kibana は、Elasticsearch と連携するように設計されたオープンソースの分析および視覚化プラットフォームです。Kibana を使用すると、Elasticsearch インデックスに保存されているデータを検索、表示、操作できます。高度なデータ分析も簡単に実行でき、データをさまざまなチャート、表、地図で視覚化できます。
- Fluentd は 、ログの収集、処理、転送システムです。豊富なプラグイン システムを通じて、さまざまなシステムやアプリケーションからログを収集し、ユーザー指定の形式に変換し、ユーザーが指定したログ ストレージ システムに転送できます。Fluentd は、指定されたデータ ソースのセットからログ データを取得し、処理し (構造化データ形式に変換し)、Elasticsearch、オブジェクト ストレージ、kafka などの他のサービスに転送します。Fluentd は 300 を超えるログ ストレージと分析サービスをサポートしているため、この点で非常に柔軟です。主な動作手順は、まず Fluentd が複数のログソースからデータを取得し、構造化されたタグを付けて、一致するタグに従って複数の対象サービスにデータを送信します。
流暢な集中スピーキング
Fluentd アーキテクチャ
![](https://img-blog.csdnimg.cn/img_convert/6c97dc5a3d80c381572b7d1325c5933c.webp?x-oss-process=image/format,png)
k8s システムのログ収集ツールとして fluentd を使用することが推奨されるのはなぜですか?
- クラウドネイティブ: https://github.com/kubernetes/kubernetes/tree/master/cluster/addons/fluentd-elasticsearch
- ログファイルをJSON化する
![](https://img-blog.csdnimg.cn/img_convert/f74a7768a7e889305f7c8de05779ea50.webp?x-oss-process=image/format,png)
- プラグイン可能なアーキテクチャ設計
![](https://img-blog.csdnimg.cn/img_convert/3ea9a5bf763b36cc0991c3af421c8797.webp?x-oss-process=image/format,png)
- リソース占有量が非常に少ない C および Ruby 言語に基づいており、30 ~ 40MB、13,000 イベント/秒/コア
![](https://img-blog.csdnimg.cn/img_convert/3b2335ee950ff8e9c9ec4a11d635d9a6.webp?x-oss-process=image/format,png)
- 極めて高い信頼性 インメモリおよびローカル ファイルベースのキャッシュ 強力なフェイルオーバー
Fluentdイベントフローのライフサイクルと命令構成
Input -> filter 1 -> ... -> filter N -> Buffer -> Output
開始コマンド
$ fluentd -c fluent.conf
命令の紹介:
- source 、データ ソース、入力に対応します。source コマンドを使用して、必要な入力プラグインを選択して構成し、Fluentd 入力ソースを有効にし、source がイベントを fluentd のルーティング エンジンに送信します。さまざまな種類のデータ ソースを区別するには、type を使用します。次の構成では、指定されたファイルの追加入力を監視できます。
<source>
@type tail
path /var/log/httpd-access.log
pos_file /var/log/td-agent/httpd-access.log.pos
tag myapp.access
format apache2
</source>
- フィルター、イベント処理パイプライン (イベント処理フロー) フィルターを直列に接続してパイプラインを形成し、データを逐次処理し、最後に出力用のマッチングに渡すことができます。イベントの内容は次のように処理できます: <source> @type http port 9880 </source> <filter myapp.access> @type record_transformer <record> host_param “#{Socket.gethostname}” </record> </filter> フィルターデータを取得した後、組み込みの @type Record_transformer プラグインを呼び出し、新しいフィールド host_param をイベント レコードに挿入し、それを出力用の照合に渡します。
- labelコマンドはソースに@labelを指定することができ、このソースによってトリガーされたイベントは指定されたラベルに含まれるタスクに送信され、後続の他のタスクでは取得されません。<source>@type forward</source><source>### このタスクではラベルを @SYSTEM### として指定します。ラベルは <label @SYSTEM>### に送信され、次のフィルターと一致には送信されません。 @type tail@label @SYSTEMpath /var/log/httpd-access.logpos_file /var/log/td-agent/httpd-access.log.posttag myapp.accessformat apache2</source><フィルター アクセス。>@type Record_transformer< Record># …</record></filter><match >@type elasticsearch# …</match><label @SYSTEM>### は、<filter var.log .middleware の上の @type tail のソース イベントを受け取ります。>@type grep# …</filter><match >@type s3# …</match></label>
- match の場合、match 出力は「タグ」に一致するイベントを検索し、それらを処理します。match コマンドの最も一般的な使用法は、イベントを他のシステムに出力することです (したがって、match コマンドに対応するプラグインは「出力プラグイン」と呼ばれます) <source> @type http port 9880 </source> <filter myapp.access > @type record_transformer <record> host_param “#{Socket.gethostname}” </record> </filter> <match myapp.access> @type ファイルパス /var/log/fluent/access </match>
イベントの構造:
time: イベントの処理時間
タグ: イベントのソース (fluentd.conf で設定)
レコード: 実際のログ内容、json オブジェクト
たとえば、次の元のログ:
192.168.0.1 - - [28/Feb/2013:12:00:00 +0900] "GET / HTTP/1.1" 200 777
Fluentd エンジンによって処理されると、次のようになります。
2020-07-16 08:40:35 +0000 apache.access: {"user":"-","method":"GET","code":200,"size":777,"host":"192.168.0.1","path":"/"}
fluentdのバッファイベントバッファモデル
Input -> filter 1 -> ... -> filter N -> Buffer -> Output
![](https://img-blog.csdnimg.cn/img_convert/1f0a579afb3d1a04d7f7664f2481e4f0.webp?x-oss-process=image/format,png)
通常、各イベントのデータ量は非常に小さいため、データ転送の効率や安定性の理由を考慮すると、基本的に各イベントが処理された直後に出力側に書き込まれることはありません。そこで、fluentd は、データの主要部分であるバッファー モデルを確立しています。それは 2 つの概念があります。
- buffer_chunk: ローカルで処理され、宛先に送信されるイベントを保存するために使用されるイベント バッファ ブロック。各ブロックのサイズを設定できます。
- buffer_queue: チャンクを格納するキュー、長さは設定可能
設定できるパラメータは主に以下のとおりです。
- buffer_type、バッファタイプ、ファイルまたはメモリに設定可能
- buffer_chunk_limit、各チャンクブロックのサイズ、デフォルトは8MBです
- buffer_queue_limit、チャンク ブロック キューの最大長、デフォルトは 256
- flash_interval、チャンクをフラッシュする時間間隔
- retry_limit、チャンクブロック送信失敗時の再試行回数。デフォルトは17回で、その後チャンクデータは破棄されます。
- retry_wait、チャンク データの送信を再試行する時間間隔、デフォルトは 1 秒、2 回目の失敗が再送信される場合、間隔は 2 秒、次回は 4 秒など
一般的なプロセスは次のとおりです。
Fluentd イベントが継続的に生成され、チャンクに書き込まれるため、キャッシュ ブロックは大きくなり続けます。キャッシュ ブロックがbuffer_chunk_limit サイズに達するか、新しいキャッシュ ブロックがフラッシュ_インターバル時間間隔を超えて生成されると、キャッシュ ブロックはキャッシュの最後にプッシュされます。キューのサイズは、buffer_queue_limit によって決まります。
新しいチャンクがキューに入れられるたびに、キューの先頭のチャンク ブロックが構成されたストレージ バックエンドにすぐに書き込まれます。たとえば、Kafka が構成されている場合、データはすぐに Kafka にプッシュされます。
理想的な状況は、新しいキャッシュ ブロックがキャッシュ キューに入るたびに、すぐにバックエンドに書き込まれることです。同時に、新しいキャッシュ ブロックは引き続きキューに入れられますが、エンキュー速度は、このように、キャッシュ キューは基本的に空であり、キュー内には最大 1 つのキャッシュ ブロックが存在します。
ただし、実際の状況では、ネットワークなどの要因を考慮すると、キャッシュ ブロックをバックエンド ストレージに書き込むときに遅延や書き込み失敗が発生することが多く、キャッシュ ブロックのバックエンドへの書き込みに失敗すると、キャッシュ ブロックはそのまま残ります。 retry_wait 時間後に送信を再試行し、リトライ回数が retry_limit に達すると、キャッシュブロックが破壊されます (データが破棄されます)。
現時点では、キャッシュ キューには引き続き新しいキャッシュ ブロックが入っています。バックエンド ストレージに時間内に書き込まれていないキャッシュ ブロックがキュー内に多数ある場合、キューの長さがbuffer_queue_limit サイズに達すると、新しいイベントが発生します。拒否されると、fluentd はエラー、error_class=Fluent ::Plugin::Buffer::BufferOverflowError error="バッファ スペースにデータが多すぎます" を報告します。
もう 1 つの状況は、ネットワーク送信が遅いということです。新しいブロックが 3 秒ごとに生成されるが、バックエンドへの書き込みに 30 秒かかり、キューの長さが 100 の場合、各ブロックがデキューされるまでの時間は、さらに 10 秒になります。ブロックが到着すると、すぐにキューがいっぱいになり、例外が発生します。
実践1:業務アプリケーションログの収集と現場分析を実現する
目的: コンテナ内の nginx アプリケーションの access.log ログを収集し、ログ フィールドを JSON 形式に解析します。元のログ形式は次のとおりです。
$ tail -f access.log
...
53.49.146.149 1561620585.973 0.005 502 [27/Jun/2019:15:29:45 +0800] 178.73.215.171 33337 GET https
収集して次のように処理します。
{
"serverIp": "53.49.146.149",
"timestamp": "1561620585.973",
"respondTime": "0.005",
"httpCode": "502",
"eventTime": "27/Jun/2019:15:29:45 +0800",
"clientIp": "178.73.215.171",
"clientPort": "33337",
"method": "GET",
"protocol": "https"
}
アイデア:
- @tail プラグインを使用して、access.log ファイルを監視し、フィルターを使用して nginx ログ形式を分析するように fluent.conf を構成します。
- Fluentd サービスを開始する
- コンテンツを access.log ファイルに手動で追加する
- ローカル出力が期待どおりかどうかを観察する
流暢な.conf
<source>
@type tail
@label @nginx_access
path /fluentd/access.log
pos_file /fluentd/nginx_access.posg
tag nginx_access
format none
@log_level trace
</source>
<label @nginx_access>
<filter nginx_access>
@type parser
key_name message
format /(?<serverIp>[^ ]*) (?<timestamp>[^ ]*) (?<respondTime>[^ ]*) (?<httpCode>[^ ]*) \[(?<eventTime>[^\]]*)\] (?<clientIp>[^ ]*) (?<clientPort>[^ ]*) (?<method>[^ ]*) (?<protocol>[^ ]*)/
</filter>
<match nginx_access>
@type stdout
</match>
</label>
サービスを開始し、ファイルの内容を追加します。
$ docker run -u root --rm -ti 172.21.51.67:5000/fluentd_elasticsearch/fluentd:v2.5.2 sh
/ # cd /fluentd/
/ # touch access.log
/ # fluentd -c /fluentd/etc/fluent.conf
/ # echo '53.49.146.149 1561620585.973 0.005 502 [27/Jun/2019:15:29:45 +0800] 178.73.215.171 33337 GET https' >>/fluentd/access.log
正規表現の検証には次の Web サイトを使用してください: http://fluent.herokuapp.com
実践 2: Ruby を使用してログフィールドの変換とカスタム処理を実現する
<source>
@type tail
@label @nginx_access
path /fluentd/access.log
pos_file /fluentd/nginx_access.posg
tag nginx_access
format none
@log_level trace
</source>
<label @nginx_access>
<filter nginx_access>
@type parser
key_name message
format /(?<serverIp>[^ ]*) (?<timestamp>[^ ]*) (?<respondTime>[^ ]*) (?<httpCode>[^ ]*) \[(?<eventTime>[^\]]*)\] (?<clientIp>[^ ]*) (?<clientPort>[^ ]*) (?<method>[^ ]*) (?<protocol>[^ ]*)/
</filter>
<filter nginx_access>
@type record_transformer
enable_ruby
<record>
host_name "#{Socket.gethostname}"
my_key "my_val"
tls ${record["protocol"].index("https") ? "true" : "false"}
</record>
</filter>
<match nginx_access>
@type stdout
</match>
</label>
ConfigMap 構成ファイルのマウント使用シナリオ
始める前に、configmap の一般的なマウント シナリオを確認しましょう。
シナリオ 1: 単一のファイルを空のディレクトリにマウントする
ビジネス アプリケーションに application-1.conf という名前の構成ファイルがある場合、この構成をポッドの /etc/application/ ディレクトリにマウントする場合。
application-1.conf の内容は次のとおりです。
$ cat application-1.conf
name: "application"
platform: "linux"
purpose: "demo"
company: "luffy"
version: "v2.1.0"
設定ファイルは、k8s の configmap を通じて管理できますが、通常、設定ファイルを管理するには次の 2 つの方法があります。
- kubectl コマンドラインを使用して configmap を生成する
# 通过文件直接创建
$ kubectl -n default create configmap application-config --from-file=application-1.conf
# 会生成配置文件,查看内容,configmap的key为文件名字
$ kubectl -n default get cm application-config -oyaml
- yaml ファイルから直接作成する
$ cat application-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: application-config
namespace: default
data:
application-1.conf: |
name: "application"
platform: "linux"
purpose: "demo"
company: "luffy"
version: "v2.1.0"
# 创建configmap
$ kubectl apply -f application-config.yaml
demo-deployment.yaml ファイルを準備し、上記の configmap を /etc/application/ にマウントします。
$ cat demo-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo
namespace: default
spec:
selector:
matchLabels:
app: demo
template:
metadata:
labels:
app: demo
spec:
volumes:
- configMap:
name: application-config
name: config
containers:
- name: nginx
image: nginx:alpine
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: "/etc/application"
name: config
作成して表示するには:
$ kubectl apply -f demo-deployment.yaml
configmap ファイルの内容を変更し、ポッドが変更を自動的に感知するかどうかを観察します。
$ kubectl edit cm application-config
configmap ファイル全体が Pod に直接マウントされ、configmap が変更されると、Pod は自動的にそれを感知して Pod に取り込みます。
ただし、ポッド内のプロセスは自動的に再起動されないため、多くのサービスは内部リロード インターフェイスを実装して、最新の構成ファイルをプロセスにロードします。
シナリオ 2: 複数のファイルをマウントする
複数の構成ファイルがある場合は、それらをすべてポッド内にマウントし、すべて 1 つのディレクトリに置く必要があります。
$ cat application-1.conf
name: "application-1"
platform: "linux"
purpose: "demo"
company: "luffy"
version: "v2.1.0"
$ cat application-2.conf
name: "application-2"
platform: "linux"
purpose: "demo"
company: "luffy"
version: "v2.1.0"
次の 2 つの方法でも作成できます。
$ kubectl delete cm application-config
$ kubectl create cm application-config --from-file=application-1.conf --from-file=application-2.conf
$ kubectl get cm application-config -oyaml
ポッドが最新の変更を自動的に取得していることを確認します。
$ kubectl exec demo-55c649865b-gpkgk ls /etc/application/
application-1.conf
application-2.conf
この時点で、ポッド /etc/application の空のディレクトリにマウントされます。ポッドの既存のディレクトリにマウントする場合は、たとえば次のようにします。
$ kubectl exec demo-55c649865b-gpkgk ls /etc/profile.d
color_prompt
locale
デプロイメントのマウント ディレクトリを変更します。
$ cat demo-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo
namespace: default
spec:
selector:
matchLabels:
app: demo
template:
metadata:
labels:
app: demo
spec:
volumes:
- configMap:
name: application-config
name: config
containers:
- name: nginx
image: nginx:alpine
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: "/etc/profile.d"
name: config
ポッドを再構築する
$ kubectl apply -f demo-deployment.yaml
# 查看pod内的/etc/profile.d目录,发现已有文件被覆盖
$ kubectl exec demo-77d685b9f7-68qz7 ls /etc/profile.d
application-1.conf
application-2.conf
シナリオ 3 マウント サブパス
複数の構成ファイルを実装し、ポッド内の異なるディレクトリにマウントできます。例えば:
- application-1.conf は /etc/application/ にマウントされます
- application-2.conf は /etc/profile.d にマウントされます
configmap は変更されないままなので、デプロイメント ファイルを変更します。
$ cat demo-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: demo
namespace: default
spec:
selector:
matchLabels:
app: demo
template:
metadata:
labels:
app: demo
spec:
volumes:
- name: config
configMap:
name: application-config
items:
- key: application-1.conf
path: application1
- key: application-2.conf
path: application2
containers:
- name: nginx
image: nginx:alpine
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: "/etc/application/application-1.conf"
name: config
subPath: application1
- mountPath: "/etc/profile.d/application-2.conf"
name: config
subPath: application2
テストマウント:
$ kubectl apply -f demo-deployment.yaml
$ kubectl exec demo-78489c754-shjhz ls /etc/application
application-1.conf
$ kubectl exec demo-78489c754-shjhz ls /etc/profile.d/
application-2.conf
color_prompt
locale
コードをコピーする
subPath を使用してポッド内にマウントされたファイルは、元の ConfigMap の変更を自動的に認識しません。
ESサービスを導入する
導入分析
- es 実稼働環境では、es クラスターをデプロイします。通常、デプロイメントにはステートフルセットを使用します。
- デフォルトでは、es は elasticsearch ユーザーを使用してプロセスを開始します。es のデータ ディレクトリはホスト マシンのパスを通じてマウントされるため、ディレクトリのアクセス許可はホスト マシンのディレクトリのアクセス許可によって上書きされます。したがって、initContainer コンテナはes プロセスの開始前にディレクトリのアクセス許可を変更するために使用されます。init に注意してください。コンテナーは特権モードで開始する必要があります。
- Helm デプロイメントを使用する場合は、 https://github.com/helm/charts/tree/master/stable/elasticsearchを参照してください。
StatefulSet を使用してステートフル サービスを管理する
デプロイメントを使用して複数のレプリカ ポッドを作成する場合:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
namespace: default
labels:
app: nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: nginx-deployment
template:
metadata:
labels:
app: nginx-deployment
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
StatefulSet を使用してマルチレプリカ ポッドを作成する場合:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nginx-statefulset
namespace: default
labels:
app: nginx-sts
spec:
replicas: 3
serviceName: "nginx"
selector:
matchLabels:
app: nginx-sts
template:
metadata:
labels:
app: nginx-sts
spec:
containers:
- name: nginx
image: nginx:alpine
ports:
- containerPort: 80
ヘッドレスサービス ヘッドレスサービス
kind: Service
apiVersion: v1
metadata:
name: nginx
namespace: default
spec:
selector:
app: nginx-sts
ports:
- protocol: TCP
port: 80
targetPort: 80
clusterIP: None
$ kubectl -n default exec -ti nginx-statefulset-0 sh
/ # curl nginx-statefulset-2.nginx
デプロイと検証
es-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: es-config
namespace: logging
data:
elasticsearch.yml: |
cluster.name: "luffy-elasticsearch"
node.name: "${POD_NAME}"
network.host: 0.0.0.0
discovery.seed_hosts: "es-svc-headless"
cluster.initial_master_nodes: "elasticsearch-0,elasticsearch-1,elasticsearch-2"
es-svc-headless.yaml
apiVersion: v1
kind: Service
metadata:
name: es-svc-headless
namespace: logging
labels:
k8s-app: elasticsearch
spec:
selector:
k8s-app: elasticsearch
clusterIP: None
ports:
- name: in
port: 9300
protocol: TCP
es-statefulset.yaml
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: elasticsearch
namespace: logging
labels:
k8s-app: elasticsearch
spec:
replicas: 3
serviceName: es-svc-headless
selector:
matchLabels:
k8s-app: elasticsearch
template:
metadata:
labels:
k8s-app: elasticsearch
spec:
initContainers:
- command:
- /sbin/sysctl
- -w
- vm.max_map_count=262144
image: alpine:3.6
imagePullPolicy: IfNotPresent
name: elasticsearch-logging-init
resources: {}
securityContext:
privileged: true
- name: fix-permissions
image: alpine:3.6
command: ["sh", "-c", "chown -R 1000:1000 /usr/share/elasticsearch/data"]
securityContext:
privileged: true
volumeMounts:
- name: es-data-volume
mountPath: /usr/share/elasticsearch/data
containers:
- name: elasticsearch
image: 172.21.51.67:5000/elasticsearch/elasticsearch:7.4.2
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
resources:
limits:
cpu: '1'
memory: 2Gi
requests:
cpu: '1'
memory: 2Gi
ports:
- containerPort: 9200
name: db
protocol: TCP
- containerPort: 9300
name: transport
protocol: TCP
volumeMounts:
- name: es-config-volume
mountPath: /usr/share/elasticsearch/config/elasticsearch.yml
subPath: elasticsearch.yml
- name: es-data-volume
mountPath: /usr/share/elasticsearch/data
volumes:
- name: es-config-volume
configMap:
name: es-config
items:
- key: elasticsearch.yml
path: elasticsearch.yml
volumeClaimTemplates:
- metadata:
name: es-data-volume
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "nfs"
resources:
requests:
storage: 5Gi
es-svc.yaml
apiVersion: v1
kind: Service
metadata:
name: es-svc
namespace: logging
labels:
k8s-app: elasticsearch
spec:
selector:
k8s-app: elasticsearch
ports:
- name: out
port: 9200
protocol: TCP
$ kubectl create namespace logging
## 部署服务
$ kubectl apply -f es-config.yaml
$ kubectl apply -f es-svc-headless.yaml
$ kubectl apply -f es-sts.yaml
$ kubectl apply -f es-svc.yaml
## 等待片刻,查看一下es的pod部署到了k8s-slave1节点,状态变为running
$ kubectl -n logging get po -o wide
NAME READY STATUS RESTARTS AGE IP
elasticsearch-0 1/1 Running 0 15m 10.244.0.126
elasticsearch-1 1/1 Running 0 15m 10.244.0.127
elasticsearch-2 1/1 Running 0 15m 10.244.0.128
# 然后通过curl命令访问一下服务,验证es是否部署成功
$ kubectl -n logging get svc
es-svc ClusterIP 10.104.226.175 <none> 9200/TCP 2s
es-svc-headless ClusterIP None <none> 9300/TCP 32m
$ curl 10.104.226.175:9200
{
"name" : "elasticsearch-2",
"cluster_name" : "luffy-elasticsearch",
"cluster_uuid" : "7FDIACx9T-2ajYcB5qp4hQ",
"version" : {
"number" : "7.4.2",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "2f90bbf7b93631e52bafb59b3b049cb44ec25e96",
"build_date" : "2019-10-28T20:40:44.881551Z",
"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"
部署kibana
導入分析
- Kibana は Web ページをフロントエンドに公開する必要があるため、ingress を使用してドメイン名を構成し、kibana にアクセスできるようにします。
- Kibana はステートレス アプリケーションであり、Deployment を使用して直接開始できます。
- Kibana は es にアクセスする必要があります。k8s サービス検出を使用してこのアドレスhttp://es-svc:9200にアクセスするだけです。
デプロイと検証
efk/kibana.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: kibana
namespace: logging
labels:
app: kibana
spec:
selector:
matchLabels:
app: "kibana"
template:
metadata:
labels:
app: kibana
spec:
containers:
- name: kibana
image: 172.21.51.67:5000/kibana/kibana:7.4.2
resources:
limits:
cpu: 1000m
requests:
cpu: 100m
env:
- name: ELASTICSEARCH_HOSTS
value: http://es-svc:9200
- name: SERVER_NAME
value: kibana-logging
- name: SERVER_REWRITEBASEPATH
value: "false"
ports:
- containerPort: 5601
---
apiVersion: v1
kind: Service
metadata:
name: kibana
namespace: logging
labels:
app: kibana
spec:
ports:
- port: 5601
protocol: TCP
targetPort: 5601
type: ClusterIP
selector:
app: kibana
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: kibana
namespace: logging
spec:
rules:
- host: kibana.luffy.com
http:
paths:
- path: /
backend:
serviceName: kibana
servicePort: 5601
$ kubectl apply -f kibana.yaml
deployment.apps/kibana created
service/kibana created
ingress/kibana created
## 配置域名解析 kibana.luffy.com,并访问服务进行验证,若可以访问,说明连接es成功
Fluentd サービスのデプロイメント
導入分析
- Fluentd はログ収集サービスであり、kubernetes クラスター内の各ビジネス ノードにはログがあるため、daemonset モードでデプロイする必要があります
- リソースをさらに制御するには、daemonset に選択ラベルを指定します。さらにフィルタリングするには、fluentd=true を指定します。このラベルを持つノードのみが fluentd をデプロイします。
- ログ収集の場合、ディレクトリごとに収集してesに送信する必要があるログは収集後に終了するため、設定する項目が多くなりますが、構成ファイル全体をマウントするためにconfigmapを使用することにします。
導入サービス
efk/fluentd-es-config-main.yaml
apiVersion: v1
data:
fluent.conf: |-
# This is the root config file, which only includes components of the actual configuration
#
# Do not collect fluentd's own logs to avoid infinite loops.
<match fluent.**>
@type null
</match>
@include /fluentd/etc/config.d/*.conf
kind: ConfigMap
metadata:
labels:
addonmanager.kubernetes.io/mode: Reconcile
name: fluentd-es-config-main
namespace: logging
構成ファイル、fluentd-config.yaml、注:
- データソースソースの設定では、k8s はデフォルトでコンテナーの標準出力ログとエラー出力ログをホストにリダイレクトします。
- デフォルトでは、ログ形式を解析し、k8s 関連のメタデータ raw.kubernetes を取得するために、kubernetes_metadata_filterプラグインが統合されています 。
- 出力をes側のフラッシュ構成に一致させる
efk/fluentd-configmap.yaml
kind: ConfigMap
apiVersion: v1
metadata:
name: fluentd-config
namespace: logging
labels:
addonmanager.kubernetes.io/mode: Reconcile
data:
containers.input.conf: |-
<source>
@id fluentd-containers.log
@type tail
path /var/log/containers/*.log
pos_file /var/log/es-containers.log.pos
time_format %Y-%m-%dT%H:%M:%S.%NZ
localtime
tag raw.kubernetes.*
format json
read_from_head false
</source>
# Detect exceptions in the log output and forward them as one log entry.
# https://github.com/GoogleCloudPlatform/fluent-plugin-detect-exceptions
<match raw.kubernetes.**>
@id raw.kubernetes
@type detect_exceptions
remove_tag_prefix raw
message log
stream stream
multiline_flush_interval 5
max_bytes 500000
max_lines 1000
</match>
output.conf: |-
# Enriches records with Kubernetes metadata
<filter kubernetes.**>
@type kubernetes_metadata
</filter>
<match **>
@id elasticsearch
@type elasticsearch
@log_level info
include_tag_key true
hosts elasticsearch-0.es-svc-headless:9200,elasticsearch-1.es-svc-headless:9200,elasticsearch-2.es-svc-headless:9200
#port 9200
logstash_format true
#index_name kubernetes-%Y.%m.%d
request_timeout 30s
<buffer>
@type file
path /var/log/fluentd-buffers/kubernetes.system.buffer
flush_mode interval
retry_type exponential_backoff
flush_thread_count 2
flush_interval 5s
retry_forever
retry_max_interval 30
chunk_limit_size 2M
queue_limit_length 8
overflow_action block
</buffer>
</match>
デーモンセット定義ファイル、fluentd.yaml、注:
- ログに基づいてメタデータをクエリするには、k8s API にアクセスする必要があるため、rbac ルールを構成する必要があります。
- /var/log/containers/ ディレクトリをコンテナにマウントする必要があります
- fluentd の configmap 内の構成ファイルをコンテナーにマウントする必要があります
- fluentd ノードをデプロイする場合は、ラベル fluentd=true を追加する必要があります。
efk/fluentd.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: fluentd-es
namespace: logging
labels:
k8s-app: fluentd-es
kubernetes.io/cluster-service: "true"
addonmanager.kubernetes.io/mode: Reconcile
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: fluentd-es
labels:
k8s-app: fluentd-es
kubernetes.io/cluster-service: "true"
addonmanager.kubernetes.io/mode: Reconcile
rules:
- apiGroups:
- ""
resources:
- "namespaces"
- "pods"
verbs:
- "get"
- "watch"
- "list"
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: fluentd-es
labels:
k8s-app: fluentd-es
kubernetes.io/cluster-service: "true"
addonmanager.kubernetes.io/mode: Reconcile
subjects:
- kind: ServiceAccount
name: fluentd-es
namespace: logging
apiGroup: ""
roleRef:
kind: ClusterRole
name: fluentd-es
apiGroup: ""
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
labels:
addonmanager.kubernetes.io/mode: Reconcile
k8s-app: fluentd-es
name: fluentd-es
namespace: logging
spec:
selector:
matchLabels:
k8s-app: fluentd-es
template:
metadata:
labels:
k8s-app: fluentd-es
spec:
containers:
- env:
- name: FLUENTD_ARGS
value: --no-supervisor -q
image: 172.21.51.67:5000/fluentd_elasticsearch/fluentd:v2.5.2
imagePullPolicy: IfNotPresent
name: fluentd-es
resources:
limits:
memory: 500Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- mountPath: /var/log
name: varlog
- mountPath: /var/lib/docker/containers
name: varlibdockercontainers
readOnly: true
- mountPath: /fluentd/etc/config.d
name: config-volume
- mountPath: /fluentd/etc/fluent.conf
name: config-volume-main
subPath: fluent.conf
nodeSelector:
fluentd: "true"
securityContext: {}
serviceAccount: fluentd-es
serviceAccountName: fluentd-es
volumes:
- hostPath:
path: /var/log
type: ""
name: varlog
- hostPath:
path: /var/lib/docker/containers
type: ""
name: varlibdockercontainers
- configMap:
defaultMode: 420
name: fluentd-config
name: config-volume
- configMap:
defaultMode: 420
items:
- key: fluent.conf
path: fluent.conf
name: fluentd-es-config-main
name: config-volume-main
## 给slave1打上标签,进行部署fluentd日志采集服务
$ kubectl label node k8s-slave1 fluentd=true
$ kubectl label node k8s-slave2 fluentd=true
# 创建服务
$ kubectl apply -f fluentd-es-config-main.yaml
configmap/fluentd-es-config-main created
$ kubectl apply -f fluentd-configmap.yaml
configmap/fluentd-config created
$ kubectl apply -f fluentd.yaml
serviceaccount/fluentd-es created
clusterrole.rbac.authorization.k8s.io/fluentd-es created
clusterrolebinding.rbac.authorization.k8s.io/fluentd-es created
daemonset.extensions/fluentd-es created
## 然后查看一下pod是否已经在k8s-slave1
$ kubectl -n logging get po -o wide
NAME READY STATUS RESTARTS AGE
elasticsearch-logging-0 1/1 Running 0 123m
fluentd-es-246pl 1/1 Running 0 2m2s
kibana-944c57766-ftlcw 1/1 Running 0 50m
EFKの機能検証
検証アイデア
スレーブノードでサービスを起動し、同時にテストログを標準出力に出力し、kibanaに収集できるか確認する
テストコンテナを作成する
efk/テストポッド.yaml
apiVersion: v1
kind: Pod
metadata:
name: counter
spec:
nodeSelector:
fluentd: "true"
containers:
- name: count
image: alpine:3.6
args: [/bin/sh, -c, 'i=0; while true; do echo "$i: $(date)"; i=$((i+1)); sleep 1; done']
$ kubectl get po
NAME READY STATUS RESTARTS AGE
counter 1/1 Running 0 6s
キバナを構成する
kibana インターフェースにログインし、一連のスクリーンショットに従います。
![](https://img-blog.csdnimg.cn/img_convert/21454192e8f02286e8b7abe30d1c891c.webp?x-oss-process=image/format,png)
![](https://img-blog.csdnimg.cn/img_convert/0fcfad47e0cab42d43fa7204c438a5ed.webp?x-oss-process=image/format,png)
![](https://img-blog.csdnimg.cn/img_convert/9c5af6eceb24b5bab4b089d623ab551f.webp?x-oss-process=image/format,png)
![](https://img-blog.csdnimg.cn/img_convert/52c40a4f8623557f8f337bc680ee0f97.webp?x-oss-process=image/format,png)
ログ データは他のメタデータでフィルタリングすることもできます。たとえば、任意のログ エントリをクリックして、コンテナ名、Kubernetes ノード、名前空間などの他のメタデータを表示できます ( kubernetes.pod_name : counter など)。
これまでのところ、Kubernetes クラスターに EFK を正常にデプロイできました。ログ データ分析に Kibana を使用する方法については、Kibana ユーザー ガイド ドキュメントを参照してください: https://www.elastic.co/guide/en/kib