Kubernetes内のアプリログをSplunkに送る
はじめに
Kubernetesはロギングもホストとは諸々違います。
ただ、一つ変わらないことはSplunkに送ればなんでもできるということです。
ということでKubernetesのコンテナログの送信方法をまとめました。
使用するエージェント
Splunk OpenTelemetry Collector for Kubernetes(以下、Splunk Otel)を使います。
これはOpenTelemetry CollectorをKubernetes環境に使いやすくチューニング、機能追加したものです。
Helm Chartが用意されており様々な設定を自動化できます。可能な設定について詳細はこちら。
HEC準備
Splunk OtelではSplunkへはHECで送信するため、先に準備しておきます。
- ヘッダーメニューから 設定 > データ入力
- HTTPイベントコレクターの「新規追加」をクリック
適当に設定
名前:任意(「Otel」など)
ソースタイプ:自動
インデックス:そのまま - 払い出されたトークン値をメモしておく
Kubernetesのログ出力
代表的な以下方法について見てきます。
- 標準出力
- emptyDirへの出力
1. 標準出力
一般的に推奨される方法がこちらです。標準出力または標準エラー出力にログを出力します。
Splunk Otelはデフォルト設定で標準出力のログを取得することができます。
テスト用Pod
テスト用のPodを立ち上げて確かめてみましょう。busybox
を使い標準出力および標準エラー出力に5秒ごとにログを無限に吐きだします。
apiVersion: v1
kind: Namespace
metadata:
name: std-app
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: std-logger
namespace: std-app
spec:
replicas: 1
selector:
matchLabels:
app: std-logger
template:
metadata:
labels:
app: std-logger
spec:
containers:
- name: busybox
image: busybox
command:
- "/bin/sh"
- "-c"
- |
while true; do
echo "$(date '+%Y-%m-%d %H:%M:%S') - Standard Out Log!"
echo "$(date '+%Y-%m-%d %H:%M:%S') - Standard Error Log!" >&2
sleep 5;
done
標準出力、標準エラー出力を確認してみましょう。
kubectl logs -l app=std-logger -n std-app
2023-04-30 13:09:59 - Standard Out Log!
2023-04-30 13:09:59 - Standard Error Log!
2023-04-30 13:10:04 - Standard Out Log!
2023-04-30 13:10:04 - Standard Error Log!
Splunk Otelの設定
まずは設定用のyamlを用意します。splunk_log.yaml
とでもしておきます。
clusterName: <クラスター名>
logsEngine: otel
splunkPlatform:
logsEnabled: true
token: "<HECトークン>"
endpoint: "https://<ホスト名>:<HECポート>/services/collector"
index: "<index名>" #デフォルトはmain。変更したい場合は設定する。
insecureSkipVerify: true #Splunk Entepriseに送る場合にオレオレ証明書を使っている場合。
簡単に解説します。
cluseterName
:ログにメタデータとして埋め込むための任意のクラスター名
logsEngine
:otel
を指定することでfilelog receiverを使う(デフォルトはfluentd)
splunkPlatform
:HEC送信のための設定。URLなどの詳細はこちら。
次にHelmを使いクラスターにデプロイします。
helm repo add splunk-otel-collector-chart https://signalfx.github.io/splunk-otel-collector-chart
helm install my-splunk-otel-collector splunk-otel-collector-chart/splunk-otel-collector -f ./splunk_log.yaml
Splunk OpenTelemetry Collector is installed and configured to send data to Splunk Platform endpoint "https://<ホスト名>:<HECポート>/services/collector".
とメッセージが出ればPod作成成功です。
Otel Collectorがノードにデプロイされ、filelog receiverによりPodの標準出力、標準エラー出力の値がSplunkに送られ始めます。
それぞれの結果を見てみましょう。
標準出力
標準エラー出力
Splunk Otelのデフォルト設定によりメッセージ以外にも様々なメタデータを付与してくれています。sourcetypeはコンテナ名が使われるようです。
Kubernetesで標準出力と標準エラー出力は一つのファイルに出力されるので若干使いにくいのですが、さすがSplunk、きちんとフィールドで拾ってくれています。
補足:Splunk Otelで何をしているのか
生成されたOtelのコンフィグを確認すると以下の設定が確認できます。
receivers:
filelog:
include:
- /var/log/pods/*/*/*.log
service:
pipelines:
logs:
exporters:
- splunk_hec/platform_logs
processors:
- memory_limiter
- k8sattributes
- filter/logs
- batch
- resource
- resource/logs
- resourcedetection
receivers:
- filelog
- fluentforward
- otlp
Podの標準出力ログはノードの/var/log/pods/
配下に出力されます。そのため、コンフィグでターゲットのパスを/var/log/pods/*/*/*.log
としています。
(念のため、Splunk OtelはDaemonSetを使うので全ノードのログを取れます)
また、Pipelineのprocessorsで大量の定義を入れてくれて、これがメタデータの付与などを担っていることも分かります。助かりますね。
2. emptyDirへの出力
場合によっては標準出力ではなくemptyDirのログファイルに出力するケースもあります。
この場合、一般的な方法はsidercarでデプロイしてファイル取得かと思いますが、今のところSplunk Otelはsidecarによるデプロイはできません。
じゃあ代わりにどうするかというと、emptyDirはノードのディレクトリからも参照できますので、Splunk Otelからも直接参照する手を使います。
参考:
テスト用Pod
まずはemptyDirに出力するテスト用のPodを立ち上げます。
apiVersion: v1
kind: Namespace
metadata:
name: emptydir-app
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: emptydir-logger-app
namespace: emptydir-app
spec:
replicas: 1
selector:
matchLabels:
app: emptydir-logger-app
template:
metadata:
labels:
app: emptydir-logger-app
spec:
containers:
- name: busybox
image: busybox
command: ["/bin/sh"]
args: ["-c", "while true; do echo \"$(date '+%Y-%m-%d %H:%M:%S') - EmptyDir Sample Log!\" >> /logs/app.log; sleep 5; done"]
volumeMounts:
- name: logs-volume
mountPath: /logs
volumes:
- name: logs-volume
emptyDir: {}
emptyDirを使い/logsをマウントし/logs/app.logにログを吐きだします。
emptyDirはどこにあるのか
デフォルトでは/var/lib/kubelet/pods/
配下にPodごとのディレクトリが切られています。このディレクトリの位置はkubeletの設定により変更することもできますので、使っているk8s環境で変更されていないか念のため確認しておきましょう。
emptyDirとファイルは以下のようなパスに存在しています。
/var/lib/kubelet/pods/<PODのUID>/volumes/kubernetes.io~empty-dir/<Volume名>/<ファイル名>
さて、実際に吐き出されたログファイルはノードにSSHでアクセスすることで確認できます。
(普通はkubectl exec -it [テストpod名] -- cat /logs/app.log
で見れますが、今回はパスも確認したいのでSSHします)
今回はminikubeを使っていますので、minikubeの場合はminikube ssh
でアクセスできます。
lsしてみます。
sudo su
ls /var/lib/kubelet/pods/
すると、以下のようにPodのUIDの名前でディレクトリができていることが分かります。
197cd0de602d7cb722d0bd2daf878121 5175bba984ed52052d891b5a45b584b6 ebbe12ad-4db5-43a1-b2fe-492f113ecf0b
UIDはkubectl get pods <POD名> -o jsonpath='{.metadata.uid}'
で確認できます。
今回のテストPodで出力したファイルを確認してみます。
cat /var/lib/kubelet/pods/ebbe12ad-4db5-43a1-b2fe-492f113ecf0b/volumes/kubernetes.io~empty-dir/logs-volume/app.log
2023-04-30 13:31:07 - EmptyDir Sample Log!
2023-04-30 13:31:12 - EmptyDir Sample Log!
Splunk Otelの設定
それではSplunk Otelでログ取得します。
Helm Chartでマウントポイントを追加できますので以下のようにします。
clusterName: <クラスター名>
logsEngine: otel
splunkPlatform:
logsEnabled: true
token: "<HECトークン>"
endpoint: "https://<ホスト名>:<HECポート>/services/collector"
index: "<index名>" #デフォルトはmain。変更したい場合は設定する。
insecureSkipVerify: true #Splunk Entepriseに送る場合にオレオレ証明書を使っている場合。
#以降追加
agent:
extraVolumes:
- name: emptydirlogs
hostPath:
path: /var/lib/kubelet/pods/
extraVolumeMounts:
- name: emptydirlogs
mountPath: /tmp/emptyDirLogs
readOnly: true
logsCollection:
extraFileLogs:
filelog/sample-logger:
include: [/tmp/emptyDirLogs/*/volumes/kubernetes.io~empty-dir/logs-volume/app.log]
start_at: beginning
include_file_path: true
include_file_name: false
resource:
host.name: 'EXPR(env("K8S_NODE_NAME"))'
com.splunk.sourcetype: myLogOnEmptyDir
com.splunk.source: /logs/app.log
簡単に解説します。
agent.extraVolumes
、extraVolumeMounts
で/tmp/emptyDirLogsにマウントしています。
logsCollection.extraFileLogs.filelog/<任意の定義名>
でfilelog receiverの設定を直接書けます。特にsourcetypeは指定すべきです(Splunk側でのフィールド抽出定義のため)。
Splunk Otel先ほど既にデプロイ済みなので今度はupgradeしてみます。
helm upgrade my-splunk-otel-collector splunk-otel-collector-chart/splunk-otel-collector -f ./splunk_log.yaml
これによりemptyDirの中身をSplunkに送り始めます。
それでは結果を見てみましょう。
emptyDir
いいですね。問題なく取れています。
まとめ
Splunk OpenTelemetry Collector for Kubernetesを使えばKubernetes内のアプリログを簡単にSplunkに送信することができました。便利ですね。
今回はログでしたが、トレース、メトリクスを取得する方法はこちらにまとめています。
Discussion