4. ログの集約¶
本説明では Exastro IT Automation の各コンテナのログを集約する(Kubernetes環境における)手段の例を以下に記載します。
4.1. コンテナログについて¶
Exastroシステムでは、各コンテナのログ出力を標準出力で行っております。(The Twelve-Factor App の思想に基づく)
標準出力されたログは、Kubernetes環境の場合、コンテナがリスタートされたりすると標準出力されたログは削除されてしまいます、そのため、出力されたログを保存するには、その内容を別途保存する必要があります。
またKubernetes環境における、複数ノードで実行している場合は、その情報が各ノードに保存されているために、監視アプリケーションで監視する際に非常に扱いにくいものとなっております。
よって本説明では、監視アプリケーション等でも利用しやすいように、ノードごとに出力されたログを集約し、かつ、ファイル形式を JSON形式 で出力する方法の一例をあげたいと思います。
注釈
Kubernetesにおけるロギングのアーキテクチャについては、
4.2. ログの集約方法¶
本説明において、ログの集約方法に Fluent Bit を使用して、ログの集約を実施する例を説明します。
4.2.1. Fluent Bitインストール¶
Fluent Bitのインストールは、公式サイトに基づき、Helm charts を利用してインストールします。
公式サイト: Fluent Bit: Offcial Manual
4.2.2. 前提条件¶
本説明で使用する環境の前提条件は以下の通りとなります。
- 使用する helm cli は事前にインストールされていること
- 出力先のNFSサーバーとKubernetesが動作するサーバー間は、接続できる状態となっていること
- ログの集約先となるNFSサーバーのディレクトリは /var/PersistentVolume/ha-conf-k8s/exastro-logs とし、アクセス権がフルアクセスとなっていること
4.2.3. 事前準備¶
ログを集約するために、今回はNFSを用いた方法とし、出力先にKubernetesの永続ボリューム(PersistentVolume)を利用します。
永続ボリューム(PersistentVolume)の準備¶
事前準備として、出力先の永続ボリューム(PV)とリソースの要求(PVC)のmanifestを作成します。
1apiVersion: v1
2kind: PersistentVolumeClaim
3metadata:
4 name: pvc-exastro-logs
5spec:
6 accessModes:
7 - "ReadWriteMany"
8 resources:
9 requests:
10 storage: "10Gi"
11 storageClassName: ""
12 # volumeName: pv-exastro-logs
13---
14apiVersion: v1
15kind: PersistentVolume
16metadata:
17 name: pv-exastro-logs
18spec:
19 capacity:
20 storage: 20Gi
21 accessModes:
22 - ReadWriteMany
23 persistentVolumeReclaimPolicy: Retain
24 storageClassName: ""
25 nfs:
26 server: 192.168.172.1
27 path: /var/PersistentVolume/ha-conf-k8s/exastro-logs
28 claimRef:
29 name: pvc-exastro-logs
30 namespace: default
Fluent Bit: helm chart values.yamlの準備¶
helm chartsでインストールする際に使用する values.yaml は、以下のコマンドで抽出して、編集する
helm show values fluent/fluent-bit > fluentbit-values.yaml
Tip
Fluent Bitのhelmリポジトリ登録は以下のコマンドで実施できます。 helm show values を実行する前に1度だけ必要となります。
# Exastro システムの Helm リポジトリを登録
helm repo add fluent https://fluent.github.io/helm-charts
# リポジトリ情報の更新
helm repo update
出力された fluentbit-values.yaml を以下のように修正します。
1--- /home/runner/work/exastro-it-automation-docs-dev/exastro-it-automation-docs-dev/workspace/src/ja/2.4/share/ja/manuals/maintenance/literal_includes/fluentbit-values-org.yaml
2+++ /home/runner/work/exastro-it-automation-docs-dev/exastro-it-automation-docs-dev/workspace/src/ja/2.4/share/ja/manuals/maintenance/literal_includes/fluentbit-values.yaml
3@@ -298,9 +298,12 @@
4
5 priorityClassName: ""
6
7-env: []
8+# env: []
9 # - name: FOO
10 # value: "bar"
11+env:
12+ - name: TZ
13+ value: "Asia/Tokyo"
14
15 # The envWithTpl array below has the same usage as "env", but is using the tpl function to support templatable string.
16 # This can be useful when you want to pass dynamic values to the Chart using the helm argument "--set <variable>=<value>"
17@@ -329,9 +332,14 @@
18 # name: tcp
19 # nodePort: 30517
20
21-extraVolumes: []
22-
23-extraVolumeMounts: []
24+extraVolumes:
25+ - name: volume-exastro-logs
26+ persistentVolumeClaim:
27+ claimName: pvc-exastro-logs
28+
29+extraVolumeMounts:
30+ - name: volume-exastro-logs
31+ mountPath: /var/logs/fluentbit
32
33 updateStrategy: {}
34 # type: RollingUpdate
35@@ -346,7 +354,14 @@
36 # ingress:
37 # from: []
38
39-luaScripts: {}
40+# luaScripts: {}
41+luaScripts:
42+ record_date.lua: |
43+ function record_date(tag, timestamp, record)
44+ new_record = record
45+ new_record["record_date"] = os.date("%Y%m%d",timestamp)
46+ return 1, timestamp, new_record
47+ end
48
49 ## https://docs.fluentbit.io/manual/administration/configuring-fluent-bit/classic-mode/configuration-file
50 config:
51@@ -365,45 +380,45 @@
52 ## https://docs.fluentbit.io/manual/pipeline/inputs
53 inputs: |
54 [INPUT]
55- Name tail
56- Path /var/log/containers/*.log
57- multiline.parser docker, cri
58- Tag kube.*
59- Mem_Buf_Limit 5MB
60- Skip_Long_Lines On
61-
62- [INPUT]
63- Name systemd
64- Tag host.*
65- Systemd_Filter _SYSTEMD_UNIT=kubelet.service
66- Read_From_Tail On
67+ Name tail
68+ Path /var/log/containers/*.log
69+ Parser docker_no_time
70+ Tag <namespace_name>.<container_name>
71+ Tag_Regex (?<pod_name>[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*)_(?<namespace_name>[^_]+)_(?<container_name>.+)-
72+ Refresh_Interval 5
73+ Mem_Buf_Limit 5MB
74+ Skip_Long_Lines On
75
76 ## https://docs.fluentbit.io/manual/pipeline/filters
77 filters: |
78 [FILTER]
79- Name kubernetes
80- Match kube.*
81- Merge_Log On
82- Keep_Log Off
83- K8S-Logging.Parser On
84+ Name kubernetes
85+ Match exastro.*
86+ Merge_Log On
87+ Keep_Log Off
88+ K8S-Logging.Parser On
89 K8S-Logging.Exclude On
90+
91+ [FILTER]
92+ Name lua
93+ Match exastro.*
94+ # full path to the script
95+ script /fluent-bit/scripts/record_date.lua
96+ call record_date
97+
98+ [FILTER]
99+ Name rewrite_tag
100+ Match exastro.*
101+ Rule $record_date ^(.*)$ exastro-suite.$TAG.$record_date.log false
102+ Emitter_Name re_emitted
103
104 ## https://docs.fluentbit.io/manual/pipeline/outputs
105 outputs: |
106 [OUTPUT]
107- Name es
108- Match kube.*
109- Host elasticsearch-master
110- Logstash_Format On
111- Retry_Limit False
112-
113- [OUTPUT]
114- Name es
115- Match host.*
116- Host elasticsearch-master
117- Logstash_Format On
118- Logstash_Prefix node
119- Retry_Limit False
120+ Name file
121+ Format plain
122+ Match exastro-suite.exastro.*
123+ Path /var/logs/fluentbit/
124
125 ## https://docs.fluentbit.io/manual/administration/configuring-fluent-bit/classic-mode/upstream-servers
126 ## This configuration is deprecated, please use `extraFiles` instead.
127@@ -412,11 +427,16 @@
128 ## https://docs.fluentbit.io/manual/pipeline/parsers
129 customParsers: |
130 [PARSER]
131- Name docker_no_time
132- Format json
133- Time_Keep Off
134- Time_Key time
135- Time_Format %Y-%m-%dT%H:%M:%S.%L
136+ Name docker_no_time
137+ # Format json
138+ # Time_Keep Off
139+ # Time_Key time
140+ # Time_Format %Y-%m-%dT%H:%M:%S.%L
141+ Format regex
142+ Regex ^(?<time>[^ ]+) (?<stream>stdout|stderr) (?<logtag>[^ ]*) (?<log>.*)$
143+ Time_Keep Off
144+ Time_Key time
145+ Time_Format %Y-%m-%dT%H:%M:%S.%L%z
146
147 # This allows adding more files with arbitary filenames to /fluent-bit/etc/conf by providing key/value pairs.
148 # The key becomes the filename, the value becomes the file content.
注釈
helm show values で出力された内容をそのまま使用しているため、コメント化された内容もそのまま記載しています。
注釈
ログファイルは、json形式 で出力されるように設定しています。
ログファイル名は、ログローテーションを考慮して、日付+コンテナ名(namespace名含む)で出力されるように設定しています。
危険
rewrite_tag で、rewrite先が同じタグを継承すると永久ループとなり、サーバーが不安定になるので、rewriteのタグは違う内容となるように設定してください。
4.2.4. インストール¶
helmによるインストール手順は公式の手順に従ってインストールします。
注釈
公式の手順のまま実施しているため、namespaceは指定しておりません。
- PV, PVCのapply
kubectl apply -f fluentbit-pv.yaml
- Fluent Bit: インストール
helm upgrade --install fluent-bit fluent/fluent-bit -f fluentbit-values.yaml
- インストールされた Fluent Bit の確認
kubectl get po
NAME READY STATUS RESTARTS AGE fluent-bit-gx2c5 1/1 Running 0 22s fluent-bit-tgbls 0/1 ContainerCreating 0 22s fluent-bit-xhm6w 0/1 ContainerCreating 0 22s
kubectl get daemonset
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE fluent-bit 3 3 3 3 3 <none> 88m
4.2.5. 出力された内容を確認¶
インストール完了後、すぐに設定された内容で、NFSサーバーにログファイルが集約されます。
- 集約したログファイル一覧(例)
-rw-r--r-- 1 root root 156434 Mar 5 14:53 exastro-suite.exastro.mongo.20240305.log -rw-r--r-- 1 root root 514599 Mar 5 14:53 exastro-suite.exastro.platform-api.20240305.log -rw-r--r-- 1 root root 6931 Mar 5 14:51 exastro-suite.exastro.platform-job.20240305.log
- 集約したログファイルの内容(例)
{"stream":"stdout","logtag":"F","record_date":"20240301","log":"2024/03/01 16:40:09.098836 INFO (dumm) /app/controllers/internal_maintenance_mode_setting_controller.py(37) ### func:internal_get_maintenance_mode_setting"} {"stream":"stdout","logtag":"F","record_date":"20240301","log":"192.168.172.2 - - [01/Mar/2024:16:40:09 +0900] \"GET /internal-api/platform/maintenance-mode-setting HTTP/1.1\" 200 135 \"-\" \"python-requests/2.31.0\""} {"stream":"stdout","logtag":"F","record_date":"20240301","log":"192.168.172.2 - - [01/Mar/2024:16:40:09 +0900] \"GET /internal-api/platform/maintenance-mode-setting HTTP/1.1\" 200 135"} {"stream":"stdout","logtag":"F","record_date":"20240301","log":"2024/03/01 16:40:10.666816 INFO (dumm) /app/controllers/internal_maintenance_mode_setting_controller.py(37) ### func:internal_get_maintenance_mode_setting"} {"stream":"stdout","logtag":"F","record_date":"20240301","log":"192.168.172.2 - - [01/Mar/2024:16:40:10 +0900] \"GET /internal-api/platform/maintenance-mode-setting HTTP/1.1\" 200 135 \"-\" \"python-requests/2.31.0\""} {"stream":"stdout","logtag":"F","record_date":"20240301","log":"192.168.172.2 - - [01/Mar/2024:16:40:10 +0900] \"GET /internal-api/platform/maintenance-mode-setting HTTP/1.1\" 200 135"} {"stream":"stdout","logtag":"F","record_date":"20240301","log":"2024/03/01 16:40:12.326828 INFO (dumm) /app/controllers/internal_maintenance_mode_setting_controller.py(37) ### func:internal_get_maintenance_mode_setting"} {"stream":"stdout","logtag":"F","record_date":"20240301","log":"192.168.172.2 - - [01/Mar/2024:16:40:12 +0900] \"GET /internal-api/platform/maintenance-mode-setting HTTP/1.1\" 200 135 \"-\" \"python-requests/2.31.0\""} {"stream":"stdout","logtag":"F","record_date":"20240301","log":"192.168.172.2 - - [01/Mar/2024:16:40:12 +0900] \"GET /internal-api/platform/maintenance-mode-setting HTTP/1.1\" 200 135"} {"stream":"stdout","logtag":"F","record_date":"20240301","log":"2024/03/01 16:40:12.807144 INFO (dumm) /app/controllers/internal_maintenance_mode_setting_controller.py(37) ### func:internal_get_maintenance_mode_setting"} {"stream":"stdout","logtag":"F","record_date":"20240301","log":"192.168.172.2 - - [01/Mar/2024:16:40:12 +0900] \"GET /internal-api/platform/maintenance-mode-setting HTTP/1.1\" 200 135 \"-\" \"python-requests/2.31.0\""} {"stream":"stdout","logtag":"F","record_date":"20240301","log":"192.168.172.2 - - [01/Mar/2024:16:40:12 +0900] \"GET /internal-api/platform/maintenance-mode-setting HTTP/1.1\" 200 135"} {"stream":"stdout","logtag":"F","record_date":"20240301","log":"2024/03/01 16:40:12.836383 INFO (dumm) /app/controllers/internal_common_service_controller.py(153) ### func:internal_settings_system_config_list"} {"stream":"stdout","logtag":"F","record_date":"20240301","log":"192.168.172.2 - - [01/Mar/2024:16:40:12 +0900] \"GET /internal-api/platform/settings/common HTTP/1.1\" 200 223 \"-\" \"python-requests/2.31.0\""} {"stream":"stdout","logtag":"F","record_date":"20240301","log":"192.168.172.2 - - [01/Mar/2024:16:40:12 +0900] \"GET /internal-api/platform/settings/common HTTP/1.1\" 200 223"} {"stream":"stdout","logtag":"F","record_date":"20240301","log":"2024/03/01 16:40:12.858139 INFO (dumm) /app/controllers/internal_plan_service_controller.py(62) ### func:limits_get"} {"stream":"stdout","logtag":"F","record_date":"20240301","log":"192.168.172.2 - - [01/Mar/2024:16:40:12 +0900] \"GET /internal-api/platform/limits HTTP/1.1\" 200 239 \"-\" \"python-requests/2.31.0\""} {"stream":"stdout","logtag":"F","record_date":"20240301","log":"192.168.172.2 - - [01/Mar/2024:16:40:12 +0900] \"GET /internal-api/platform/limits HTTP/1.1\" 200 239"} {"stream":"stdout","logtag":"F","record_date":"20240301","log":"2024/03/01 16:40:15.921191 INFO (dumm) /app/controllers/internal_maintenance_mode_setting_controller.py(37) ### func:internal_get_maintenance_mode_setting"}
注釈
本説明では、ログファイルの削除に関する説明は行っておりません。
出力先の容量(ディスクサイズ)に合わせて、ログファイルの削除を行うことをお勧めします。