Kubernetesの1PodでAppとfluentdコンテナを動かしてBigQueryに送る

(2018-03-13)

Logging AgentをNodeレベルのDaemonSetとして動かすのではなく、Podの中にSidecar Containerとして動かす。その分リソースは食うけど、独自の設定で動かせる。

アプリケーション

https://github.com/sambaiz/go-logging-sample

Goで定期的にログを出すサンプルコードを書いたのでこれを使う。 viperで設定を持ち、 zapでログを出力する。 あとSIGINTを拾ってSync()してGraceful Shutdownするようにしている。

Golangの高速なロガーzapとlumberjackでログを出力してrotateさせる - sambaiz-net

multistage-buildでビルドして、GKEで動かすのでContainer Registryに上げる。

$ docker build -t go-logging-sample .
$ docker tag go-logging-sample gcr.io/<project_id>/go-logging-sample:v1 
$ gcloud docker -- push gcr.io/<project_id>/go-logging-sample

Fluentdの設定

fluent-plugin-bigqueryプラグインを使う。

projectとdataset、パーティションの日付分割テーブルに入れる場合は、auto_create_tableできないのでtableも作成しておく。

fluentdの設定はConfigMapで持つ。

apiVersion: v1
kind: ConfigMap
metadata:
  name: fluentd-config
data:
  fluent.conf: |
    <source>
      @type tail
      format json
      path /var/log/app.log
      pos_file /var/log/app.log.pos
      tag bigquery 
    </source>

    <match bigquery>
      @type bigquery

      method load

      <buffer time>
        @type file
        path /var/log/bigquery.*.buffer
        timekey 1d
        flush_at_shutdown true
      </buffer>

      auth_method	compute_engine

      project <project-name>
      dataset <dataset-name>
      table <table-name>$%Y%m%d
      fetch_schema true 
      ignore_unknown_values true	  
    </match>

プラグイン入りのfluentdイメージもビルドして上げる。

FROM fluent/fluentd:v1.1-onbuild

RUN apk add --update --virtual .build-deps \
        sudo build-base ruby-dev \

 # cutomize following instruction as you wish
 && sudo gem install \
        bigdecimal fluent-plugin-bigquery:1.2.0 \

 && sudo gem sources --clear-all \
 && apk del .build-deps \
 && rm -rf /var/cache/apk/* \
           /home/fluent/.gem/ruby/*/cache/*.gem

EXPOSE 24284
$ touch fluent.conf
$ mkdir plugins
$ docker build -t fluentd-bigquery .
$ docker tag fluentd-bigquery gcr.io/<project_id>/fluentd-bigquery:v1 
$ gcloud docker -- push gcr.io/<project_id>/fluentd-bigquery

Podの設定

ConfigMapのVolumeと、ログが書かれるVolumeを定義し、 これを各コンテナでマウントする。

apiVersion: v1
kind: Pod
metadata:
  name: something-collector
spec:
  containers:
  - name: collector
    image: gcr.io/<project_id>/go-logging-sample:v1
    env:
    - name: SAMPLE_LOG_PATH
      value: /var/log/app.log
    volumeMounts:
    - name: varlog
      mountPath: /var/log
  - name: fluentd
    image: gcr.io/<project_id>/fluentd-bigquery:v1
    volumeMounts:
    - name: varlog
      mountPath: /var/log
    - name: config-volume
      mountPath: /fluentd/etc
  volumes:
  - name: varlog
    emptyDir: {}
  - name: config-volume
    configMap:
      name: fluentd-config

動かす

BigQueryの権限が付いたGKEのクラスタにデプロイ。

$ gcloud container clusters get-credentials <cluster-name> --zone <zone> --project <project-name>
$ kubectl config current-context
gke_***

$ kubectl create -f fluentd-configmap.yaml
$ kubectl create -f something-collector-pod.yaml

立ち上がらないときは-cでコンテナのnameを指定してログを見る。

$ kubectl logs something-collector -c fluentd

OptionのUse Legacy SQLのチェックを外して標準SQLでBigQueryに入っていることを確認した。

SELECT
  *
FROM
  `<dataset-name>.<table-name>` 
WHERE
  _PARTITIONTIME BETWEEN 
  TIMESTAMP_TRUNC(TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 7 * 24 HOUR),DAY)
  AND 
  TIMESTAMP_TRUNC(CURRENT_TIMESTAMP(),DAY);