ログのファイル出力による課題
コンテナはもちろん,Kubernetesではコンテナではログは標準出力/標準エラー出力に
出力することがベストプラクティスの1つです.
一方で,既存アプリを流用する場合でコンテナネイティブにアプリを改修できていないときなど
ログをファイル出力している場合も多々あります.
このようにログをファイル出力しているとpodが停止したときにログが失われてしまいます.
ログ出力先を永続化できていたとしても
kubectlコマンドでログを参照できないので不便です.
ストリーミングサイドカーコンテナ(Streaming Sidecar Container)
これを解決するのがストリーミングサイドカーコンテナです.
ログファイルを標準出力に読み出すコンテナを対象アプリと同一podに梱包します.
これによってkubernetesクラスタ標準のログ収集の仕組みに
対象ファイルも適用することができます.
(ストリーミングサイドカーコンテナ概要図: kubernetesドキュメントより)
図では1つのストリーミングサイドカーコンテナしか記載されていませんが,
もし複数のログファイルを出力しているのであれば
ログファイルの数だけサイドカーコンテナを作成する必要があります.
kubectlおよびsternでの標準出力ログ確認
実際にGKE上にアプリをデプロイし,ストリーミングサイドカーで
ログファイルの内容を取得できることを確認してみましょう.
クラスタを作成し,そのクラスタに公式ドキュメント記載の
2つの異なるフォーマットでカウントアップしてファイルに追記するpodをデプロイします.
$ gcloud container clusters create eval-logging
...
$ kubectl create -f https://raw.githubusercontent.com/kubernetes/website/master/content/en/examplesdmin/logging/two-files-counter-pod-streaming-sidecar.yaml
pod "counter" created
podの構成は以下の通りです.
ログファイルのディレクトリをvolume mountすることで
コンテナ間でファイルを共有しています.
$ curl https://raw.githubusercontent.com/kubernetes/website/master/content/en/examples/admin/logging/two-files-counter-pod-streaming-sidecar.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)" >> /var/log/1.log;
echo "$(date) INFO $i" >> /var/log/2.log;
i=$((i+1));
sleep 1;
done
volumeMounts:
- name: varlog
mountPath: /var/log
- name: count-log-1
image: busybox
args: [/bin/sh, -c, 'tail -n+1 -f /var/log/1.log']
volumeMounts:
- name: varlog
mountPath: /var/log
- name: count-log-2
image: busybox
args: [/bin/sh, -c, 'tail -n+1 -f /var/log/2.log']
volumeMounts:
- name: varlog
mountPath: /var/log
volumes:
- name: varlog
emptyDir: {}
このcountコンテナは標準出力にはなにも出力していないので
ログを参照しようとしても何も出力されません.
$ kubectl logs counter count
$
一方で,count-log-1, count-log2 コンテナはログファイルを
標準出力に出力しているのでログが参照できます.
特に,1つのpodの複数のコンテナログを参照する場合はsternを使うと便利です.
$ stern counter
+ counter › count
+ counter › count-log-2
+ counter › count-log-1
...
counter count-log-2 Wed Dec 19 13:32:47 UTC 2018 INFO 12
counter count-log-1 12: Wed Dec 19 13:32:47 UTC 2018
counter count-log-2 Wed Dec 19 13:32:48 UTC 2018 INFO 13
counter count-log-1 13: Wed Dec 19 13:32:48 UTC 2018
counter count-log-2 Wed Dec 19 13:32:49 UTC 2018 INFO 14
counter count-log-1 14: Wed Dec 19 13:32:49 UTC 2018
counter count-log-2 Wed Dec 19 13:32:50 UTC 2018 INFO 15
counter count-log-1 15: Wed Dec 19 13:32:50 UTC 2018
counter count-log-2 Wed Dec 19 13:32:51 UTC 2018 INFO 16
counter count-log-1 16: Wed Dec 19 13:32:51 UTC 2018
counter count-log-2 Wed Dec 19 13:32:52 UTC 2018 INFO 17
counter count-log-1 17: Wed Dec 19 13:32:52 UTC 2018
counter count-log-2 Wed Dec 19 13:32:53 UTC 2018 INFO 18
counter count-log-1 18: Wed Dec 19 13:32:53 UTC 2018
...
GKEにおけるStackdriver Loggingでの確認
上記ログの確認は標準出力に出力された内容の確認でした.
マネージドなKubernetesクラスタでは自動的にログをバックエンドに転送してくれます.
GKEであれば Stackdriver Loggingです.
これを確認してみます.
GCPのダッシュボード画面からLoggingを選択し,
表示する対象として,GKEコンテナを選択すると先程確認したログが
Stackdriver Loggingでも確認できます.
また,ログレベル(DEBUG, INFO, ERROR)やラベルでのフィルタリングも可能です.
まとめ
ログを標準出力/標準エラー出力に出さずファイル出力するアプリに対し
ストリーミングサイドカーコンテナを利用することで
kubernetesクラスタのロギングの仕組みを適用する方法をGKEにおいて確認しました.
今回は検証しませんでしたが,kubernetesクラスタのロギングの仕組みを利用しない場合は
ストリーミングサイドカーコンテナから直接ロギングバックエンドに転送する方法も
公式ドキュメントには記載されています.
利用する機会は多くはないかもしれませんが
対象アプリに応じて適切なロギングの仕組みを適用していく必要がありそうです.