概要
k8s で fluentd を使ってログを収集する場合多くのケースで DaemonSet の仕組みが使われます
DaemonSet は簡単に言えば各 Pod に自動で 1 つコンテナを作成するための定義です
DaemonSet が定義されていると新規でノードが追加された際に自動でログ収集用の fluentd が起動するといった感じです
環境
- macOS 10.13.6
- minikube v0.28.2
- fluent/fluentd-kubernetes-daemonset:elasticsearch (v0.12)
事前作業
ElasticSearch の構築
別の VM に構築しています
方法は何でも OK です
k8s 上に構築したコンテナからエンドポイントにアクセスできるようにしましょう
Kibana の構築 (任意)
確認に使うだけなので任意です
直接 ElasticSearch の API がコールできるのであればそれでも OK です
fluentd の DaemonSet の作成
fluentd が公式で出している定義を流用します
仕組みとしては logging driver は使わずに dockerd が動作しているホストのコンテナログが出力されるパス (/var/lib/docker/containers
) をマウントしてそこに出力されるログを ElasticSearch に送ります
namespace や label は変更しても問題ないと思います
- vim fluentd-ds.yaml
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: fluentd
namespace: kube-system
labels:
k8s-app: fluentd-logging
version: v1
kubernetes.io/cluster-service: "true"
spec:
template:
metadata:
labels:
k8s-app: fluentd-logging
version: v1
kubernetes.io/cluster-service: "true"
spec:
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
containers:
- name: fluentd
image: fluent/fluentd-kubernetes-daemonset:elasticsearch
env:
- name: FLUENT_ELASTICSEARCH_HOST
value: "192.168.99.1"
- name: FLUENT_ELASTICSEARCH_PORT
value: "9200"
- name: FLUENT_ELASTICSEARCH_SCHEME
value: "http"
- name: FLUENT_UID
value: "0"
resources:
limits:
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
terminationGracePeriodSeconds: 30
volumes:
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
変更するべきは env の部分だけです
ここの IP や Port を外部に構築した ElasticSearch のものに変更すれば OK です
公式だとそれ以外にも env のありましたが不要なので削除しました
kubectl create -f fluentd-ds.yaml
kubectl get all -n kube-system -l k8s-app=fluentd-logging
NAME READY STATUS RESTARTS AGE
pod/fluentd-zhnnj 1/1 Running 0 1m
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE
daemonset.apps/fluentd 1 1 1 1 1 <none> 1m
こんな感じで fluentd のコンテナが DaemonSet の仕組みで起動してきます
テスト用のコンテナ作成
ログを出力し続けるコンテナを適当に作成します
動作確認なので Deployment からではなく直接 Pod を作成します
- vim counter-pod.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)"; i=$((i+1)); sleep 1; done']
kubectl create -f counter-pod.yaml
kubectl get po
NAME READY STATUS RESTARTS AGE
counter 1/1 Running 0 29s
動作確認
Kibana があればそれを見てみましょう
インデックス (logstash-*
) を作成し
タイムスタンプのフィールド (@timestamp
) を作成し
Disvoery で dockercontainer_id
で絞り込めばログが確認できると思います
インデックス名は logstash-2018.09.03
という感じで日付形式で来るようになっています
fluent.conf の設定はここが参考になると思います
トラブルシューティング
fluentd コンテナが立ち上がったときにログ用のパスがマウントできないエラーが発生しました
2018-09-03 00:05:58 +0000 [error]: unexpected error error_class=Errno::EACCES error=#<Errno::EACCES: Permission denied @ rb_sysopen - /var/log/fluentd-containers.log.pos>
どうやら fluent ユーザに権限がないために上記のエラーになっているようです
fluentd-ds.yaml に FLUENT_UID
の値を 0 に設定することで対応できました
同じような現象に関しての issue が Github にもありました
https://github.com/fluent/fluentd-docker-image/issues/90
お掃除
kubectl delete po counter
kubectl delete ds fluentd -n kube-system
最後に
kubernetes 上に DaemonSet の仕組みを使って fluentd コンテナを作成してみました
これを作成しておけば
今回は ElasticSearch に向かってログを投げましたが、他にもいろいろなログ集約のサービスに投げれるようです
仕組みとしてはコンテナログのファイルを監視しているだけなので標準出力/標準エラーにログを吐くコンテナであれば kubernetes 上に立てるだけでログが ElasticSearch に送られます
実は今回 minikube 上で実現しています
kubernetes 上でも同じようにできるので minikube にしました
minikube にはアドオンで「efk」というアドオンがあり実はこれを使ってもできます
が、これは e (elasticsearch) と f (fluentd) と k (kibana) のコンテナをすべて minikube 上に展開します
今回の構成は e と k は外部のホストに構築しています
なので kubernetes 上にあるのは f だけになります
f はどうしても k8s になければいけないコンテナになります
普通は e と k は別ホストにあると思うのでそれを想定して動作させてみました
0 件のコメント:
コメントを投稿