Pod ログ収集のベストプラクティス¶
はじめに¶
コンテナ化されたマイクロサービスのデプロイでは、マイクロサービスはコンテナ内で実行されます。Pod は1つまたは密接に結合された一連のコンテナで構成され、Kubernetes における最小のスケジューリング単位です。
本稿では、Pod 内のログについて、DataKit を使用したログ収集の3つの方法を紹介します。
方法1¶
DataKit で Logfwd コレクターを有効にし、Logfwd を Sidecar モードで使用して業務コンテナのログを収集します。
1 Logfwd コレクターを有効にする¶
Kubernetes に DataKit が統合されていない場合は、Guance にログインし、「インテグレーション」→「Datakit」→「Kubernetes」の順に選択し、datakit.yaml ファイルを使用して DataKit を統合してください。
次に、datakit.yaml ファイルを編集し、logfwdserver.conf ファイルを DataKit の /usr/local/datakit/conf.d/log/ ディレクトリにマウントします。
datakit.yaml に以下の設定を追加します:
---
apiVersion: v1
kind: ConfigMap
metadata:
name: datakit-conf
namespace: datakit
data:
#### logfwdserver
logfwdserver.conf: |-
[inputs.logfwdserver]
## logfwd 受信側のリスニングアドレスとポート
address = "0.0.0.0:9531"
[inputs.logfwdserver.tags]
# some_tag = "some_value"
# more_tag = "some_other_value"
DaemonSet リソースに以下を追加します:
- mountPath: /usr/local/datakit/conf.d/log/logfwdserver.conf
name: datakit-conf
subPath: logfwdserver.conf
2 Pipeline をマウントする¶
datakit.yaml ファイルを編集し、pod-logging-demo.p ファイルを DataKit の /usr/local/datakit/pipeline/ ディレクトリにマウントします。
ConfigMap リソースに以下を追加します:
pod-logging-demo.p: |-
# ログ形式
#2021-12-01 10:41:06.015 [http-nio-8090-exec-2] INFO c.s.d.c.HealthController - [getPing,19] - - ping インターフェースを呼び出し
grok(_, "%{TIMESTAMP_ISO8601:time} %{NOTSPACE:thread_name} %{LOGLEVEL:status}%{SPACE}%{NOTSPACE:class_name} - \\[%{NOTSPACE:method_name},%{NUMBER:line}\\] - - %{GREEDYDATA:msg}")
default_time(time,"Asia/Shanghai")
DaemonSet リソースに以下を追加します:
- mountPath: /usr/local/datakit/pipeline/pod-logging-demo.p
name: datakit-conf
subPath: pod-logging-demo.p
注意: Pipeline を使用したログパース(切り出し)が不要な場合、この手順は省略できます。
3 DataKit を再起動する¶
4 Logfwd Sidecar によるログ収集¶
Logfwd イメージと業務イメージを同一 Pod にデプロイします。以下では log-demo-service:v1 を業務イメージとし、/data/app/logs/log.log ログファイルを生成します。logfwd が共有ストレージ方式でログファイルを読み取り、DataKit に転送します。pod-logging-demo.p を使用してログをパースし、日付でマルチラインマッチングを行います。
関連設定ファイルの例
apiVersion: apps/v1
kind: Deployment
metadata:
name: log-fwd-deployment
spec:
replicas: 1
selector:
matchLabels:
app: log-fwd-pod
template:
metadata:
labels:
app: log-fwd-pod
annotations:
spec:
nodeName: k8s-node2
containers:
- name: log-fwd-container
image: 172.16.0.238/df-demo/log-demo-service:v2
ports:
- containerPort: 8090
protocol: TCP
volumeMounts:
- mountPath: /data/app/logs
name: varlog
- name: logfwd
image: pubrepo.guance.com/datakit/logfwd:1.2.12
env:
- name: LOGFWD_DATAKIT_HOST
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: status.hostIP
- name: LOGFWD_DATAKIT_PORT
value: "9531"
- name: LOGFWD_ANNOTATION_DATAKIT_LOGS
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.annotations['datakit/logs']
- name: LOGFWD_POD_NAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.name
- name: LOGFWD_POD_NAMESPACE
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: metadata.namespace
volumeMounts:
- mountPath: /var/log
name: varlog
- mountPath: /opt/logfwd/config
name: logfwd-config
subPath: config
restartPolicy: Always
volumes:
- name: varlog
emptyDir: {}
- configMap:
name: logfwd-conf
name: logfwd-config
---
apiVersion: v1
kind: ConfigMap
metadata:
name: logfwd-conf
data:
config: |
[
{
"loggings": [
{
"logfiles": ["/var/log/log.log"],
"source": "log_fwd_demo",
"pipeline": "pod-logging-demo.p",
"multiline_match": "^\\d{4}-\\d{2}-\\d{2}",
"tags": {
"flag": "tag1"
}
}
]
}
]
logfwd-conf パラメーターの説明
logfiles: ログファイルのリスト。ignore: ファイルパスのフィルタリングに使用します。glob ルールに従い、いずれかのフィルター条件に一致した場合、そのファイルは収集されません。source: データソース。service: 追加するタグservice。空の場合は、デフォルトで$sourceが使用されます。pipeline: Pipeline を使用する場合、スクリプトのパスを指定します。character_encoding: エンコーディングを選択します。multiline_match: マルチラインマッチング。remove_ansi_escape_codes: ANSI エスケープコード(標準出力のテキスト色など)を削除するかどうか。値はtrueまたはfalse。tags: キーと値の形式でタグを定義します。必須項目ではありません。
環境変数の説明
LOGFWD_DATAKIT_HOST: DataKit のアドレス。LOGFWD_DATAKIT_PORT: Logfwd のポート番号。
5 ログを確認する¶
Guance にログインし、「ログ」を選択して、データソース log_fwd_demo を検索します。
方法2¶
DataKit はデフォルトで Pod の標準出力(Stdout)に出力されたログを収集します。ログ形式を特殊処理するために、通常は Pod をデプロイする Deployment コントローラーの YAML ファイルに Annotations を追加します。
以下は、Spring Boot マイクロサービスのプロジェクトを例にしたログ収集のサンプルです。JAR ファイルは log-springboot-demo-1.0-SNAPSHOT.jar で、ログは Logback を使用します。具体的な手順は以下の通りです:
1 logback-spring.xml を作成する¶
logback-spring.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<contextName>logback</contextName>
<!-- ログのルートディレクトリ - -
<property name="log.root.dir" value="./logs"/>
<!-- ログ出力形式 - -
<property name="log.pattern" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - - %msg%n" />
<!-- ログをコンソールに出力 - -
<appender name="Console" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${log.pattern}</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="Console"/>
</root>
</configuration>
2 イメージを作成する¶
Dockerfile は以下の通りです:
FROM openjdk:8u292
RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
RUN echo 'Asia/Shanghai' >/etc/timezone
ENV jar log-springboot-demo-1.0-SNAPSHOT.jar
ENV workdir /data/app/
RUN mkdir -p ${workdir}
WORKDIR ${workdir}
ENTRYPOINT ["sh", "-ec", "exec java ${JAVA_OPTS} -jar ${jar} "]
イメージを作成し、Harbor レジストリにプッシュします:
3 pod-log-service.yaml ファイルを作成する¶
pod-log-service.yaml
apiVersion: v1
kind: Service
metadata:
name: log-demo-service
labels:
app: log-demo-service
spec:
selector:
app: log-demo-service
ports:
- protocol: TCP
port: 8090
nodePort: 30053
targetPort: 8090
type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: log-demo-service
labels:
app: log-demo-service
spec:
replicas: 1
selector:
matchLabels:
app: log-demo-service
template:
metadata:
labels:
app: log-demo-service
annotations:
datakit/logs: |
[
{
"source": "pod-logging-testing-demo",
"service": "pod-logging-testing-demo",
"pipeline": "pod-logging-demo.p",
"multiline_match": "^\\d{4}-\\d{2}-\\d{2}"
}
]
spec:
containers:
- env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
name: log-service
image: <your-harbor>/log-demo-service:v1
ports:
- containerPort: 8090
protocol: TCP
restartPolicy: Always
volumes:
- name: ddagent
emptyDir: {}
Annotations パラメーターの説明
source: データソースservice: タグservicepipeline: Pipeline スクリプトのパスignore_status:multiline_match: 1行のログにマッチする正規表現。例では日付(例: 2021-11-26)で始まる行を1行のログとみなし、次の行がこの日付で始まらない場合は、その行は前のログの一部と見なします。remove_ansi_escape_codes: ANSI エスケープコード(標準出力のテキスト色など)を削除するかどうか。
4 Pipeline を設定する¶
datakit-default.yaml ファイルの ConfigMap リソースに pod-logging-demo.p セクションを追加します。
apiVersion: v1
kind: ConfigMap
metadata:
name: datakit-conf
namespace: datakit
data:
pod-logging-demo.p: |-
# ログ形式
#2021-12-01 10:41:06.015 [http-nio-8090-exec-2] INFO c.s.d.c.HealthController - [getPing,19] - - ping インターフェースを呼び出し
grok(_, "%{TIMESTAMP_ISO8601:time} %{NOTSPACE:thread_name} %{LOGLEVEL:status}%{SPACE}%{NOTSPACE:class_name} - \\[%{NOTSPACE:method_name},%{NUMBER:line}\\] - - %{GREEDYDATA:msg}")
default_time(time)
Pod-logging-demo.p を DataKit にマウントします。
- mountPath: /usr/local/datakit/pipeline/pod-logging-demo.p
name: datakit-conf
subPath: pod-logging-demo.p
5 ログを確認する¶
以下のコマンドを実行して Pod をデプロイします:
マイクロサービスにアクセスします:
Guance にログインし、「ログ」モジュールで log-demo-service と入力すると、ログが正常に表示されます。
方法3¶
Pod に Volume をマウントします。ボリュームタイプは hostPath を使用し、ログファイルをホストマシンにマウントします。その後、DaemonSet を使用して DataKit をデプロイし、同様に hostPath タイプの Volume をマウントすることで、DataKit が Pod 内のログファイルを収集できるようにします。




