はじめに
東京工科大学のCDSL所属,有田海斗です!
研究室では,普段はログサーバにてELK Stack(Kibana,Elasticsearch,Logstash,Filebeat)を使いログの一元管理をしております.
しかし,運用中のテクニカルレポート検索サイトでは,テクニカルレポート検索サイトからログサーバへのアクセスをファイアウォールによって制限しているため,Push型のアーキテクチャであるFilebeatではログの送信をすることができません.そのため,ログサーバからテクニカルレポート検索サイトにログを取ってくるPull型のアーキテクチャのソフトウェアを使う必要がありました.そのためEmbulkを使うことになりました.
環境
Kubernetes(ディストリビューション:K3s、バージョン:v1.29.3)
Docker(バージョン:28.2.1)
Elasticsearch(バージョン:8.5.1)
Embulk (バージョン:0.9.25)
手順
(1)EmbulkのDockerイメージを作成する
最初にDockerを使ってイメージを作成します.
Dockerfile
# EmBulkの実行にはJavaが必要なため、Javaが含まれているベースイメージを使う
FROM openjdk:8-jre-slim AS builder
# 作業ディレクトリを設定
WORKDIR /usr/src/app
# install curl
RUN apt-get update && \
apt-get install -y curl && \
rm -rf /var/lib/apt/lists/*
# install jruby
RUN curl --create-dirs -o "./jruby-complete-9.4.5.0.jar" -L "https://repo1.maven.org/maven2/org/jruby/jruby-complete/9.4.5.0/jruby-complete-9.4.5.0.jar"
RUN chmod +x ./jruby-complete-9.4.5.0.jar
# Embulkをダウンロード
RUN curl --create-dirs -o ./embulk.jar -L "https://github.com/embulk/embulk/releases/download/v0.9.25/embulk-0.9.25.jar"
# configファイルをliquid形式にして持ってくる
COPY ./config.yml ./config.yml.liquid
# install Ruby gems
RUN java -jar embulk.jar gem install embulk -v 0.9.25 # Embulk と同じバージョンを指定
RUN java -jar embulk.jar gem install msgpack -v 1.3.1
# Embulkのプラグインをインストール
RUN java -jar embulk.jar gem install embulk-input-sftp
RUN java -jar embulk.jar gem install embulk-output-elasticsearch
RUN java -jar embulk.jar gem install embulk-parser-regex
# ----------------------------------
# マルチステージビルド
FROM openjdk:8-jre-alpine
WORKDIR /app
COPY --from=builder /usr/src/app/embulk.jar ./embulk.jar
COPY --from=builder /usr/src/app/config.yml.liquid ./config.yml.liquid
COPY --from=builder /root/.embulk /root/.embulk
# 変数の定義+embulkの実行
ENTRYPOINT ["/bin/sh", "-c", "export INDEX_NAME=$(date +%Y%m%d) && java -jar /app/embulk.jar run /app/config.yml.liquid"]
config.yml
in:
type: sftp
host: {{ env.HOST }}
port: 22
user: {{ env.USER }}
password: {{ env.PASSWORD }}
user_directory_is_root: false
timeout: 600
path_prefix: /var/log/containers
last_path: /app/last_path.yml
verbose: true
parser:
type: regex
charset: UTF-8
columns:
- {name: timestamp, type: timestamp, format: "%Y-%m-%dT%H:%M:%S.%N%z"}
- {name: stream, type: string}
- {name: flag, type: string}
- {name: message, type: string}
delimiter: "\n"
regex: ^(?<timestamp>\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d+Z)\s+(?<stream>\w+)\s+(?<flag>\w+)\s+(?<message>.*)$
out:
type: elasticsearch
nodes:
- {host: Elasticsearchのホスト名を入力, port: Elasticsearchのポート番号を入力}
index: {{ env.INDEX_NAME }}
mode: insert
index_type: log
config.ymlのpath_prefix: /var/log/containers
にログファイルがあるディレクトリを指定してください.
config.ymlのparser:
にログのパースについて記入してください.
config.ymlのnodes: - {host: Elasticsearchのホスト名を入力, port: Elasticsearchのポート番号を入力}
にElasticsearchのホスト名とポート番号をそれぞれ記入してください.
(1-1) docker buildする.
docker build イメージ名 .
(1-2) イメージを確認する.
docker images
(1-3) 自分のDocker hub上のレジストリにpushします.
docker push イメージ名
実際の出力
cdsl@embulk-test:~/embulk/embulk-doktor$ docker build -t aritatut/embulk-test:latest .
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 1.68kB 0.0s
=> [internal] load metadata for docker.io/library/openjdk:8-jre-alpine 0.6s
=> [internal] load metadata for docker.io/library/openjdk:8-jre-slim 0.6s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 2B 0.0s
=> [builder 1/12] FROM docker.io/library/openjdk:8-jre-slim@sha256:53186129237fbb8bc0a12dd36da6761f4c7a2a20233c 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 32B 0.0s
=> [stage-1 1/6] FROM docker.io/library/openjdk:8-jre-alpine@sha256:f362b165b870ef129cbe730f29065ff37399c0aa8bca 0.0s
=> CACHED [builder 2/12] WORKDIR /usr/src/app 0.0s
=> CACHED [stage-1 2/6] WORKDIR /app 0.0s
=> [builder 3/12] RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/* 4.6s
=> [stage-1 3/6] RUN mkdir -p /path 0.3s
=> [builder 4/12] RUN curl --create-dirs -o "./jruby-complete-9.4.5.0.jar" -L "https://repo1.maven.org/maven2/o 2.4s
=> [builder 5/12] RUN chmod +x ./jruby-complete-9.4.5.0.jar 0.2s
=> [builder 6/12] RUN curl --create-dirs -o ./embulk.jar -L "https://github.com/embulk/embulk/releases/download 2.6s
=> [builder 7/12] COPY ./config.yml ./config.yml.liquid 0.0s
=> [builder 8/12] RUN java -jar embulk.jar gem install embulk -v 0.9.25 # Embulk と同じバージョンを� 14.9silder 9/12] RUN java -jar embulk.jar gem install msgpack -v 1.3.1 10.9s
=> [builder 9/12] RUN java -jar embulk.jar gem install msgpack -v 1.3.1 10.9s
=> [builder 10/12] RUN java -jar embulk.jar gem install embulk-input-sftp 13.8s
=> [builder 11/12] RUN java -jar embulk.jar gem install embulk-output-elasticsearch 14.0s
=> [builder 12/12] RUN java -jar embulk.jar gem install embulk-parser-regex 11.2s
=> [stage-1 4/6] COPY --from=builder /usr/src/app/embulk.jar ./embulk.jar 0.1s
=> [stage-1 5/6] COPY --from=builder /usr/src/app/config.yml.liquid ./config.yml.liquid 0.0s
=> [stage-1 6/6] COPY --from=builder /root/.embulk /root/.embulk 0.1s
=> exporting to image 0.1s
=> => exporting layers 0.1s
=> => writing image sha256:bc3378adbb07624b8a42883ebfd535b6c4def7edb556a071db8cea2621cc6ca1 0.0s
=> => naming to docker.io/aritatut/embulk-test:latest
cdsl@embulk-test:~/embulk/embulk-doktor$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
aritatut/embulk-test latest 6c02ab1cc80c 33 seconds ago 141MB
cdsl@embulk-test:~/embulk/embulk-doktor$ docker push aritatut/embulk-test:latest
The push refers to repository [docker.io/aritatut/embulk-test]
b46f1ad84e07: Pushed
803ae0535452: Pushed
da9331e83f70: Pushed
78c803688264: Pushed
3c5291230fa0: Mounted from aritatut/embulk-fixedip
edd61588d126: Mounted from aritatut/embulk-fixedip
9b9b7f3d56a0: Mounted from aritatut/embulk-fixedip
f1b5933fe4b5: Mounted from aritatut/embulk-fixedip
latest: digest: sha256:56b5e6b1463c274abb919ada40d994a34aaddddf0b08fb4808e002b087478a78 size: 1991
(2)EmbulkをK3sで立てる
イメージを自分のリポジトリにpushできたので,K3sにコンテナを作成していきましょう
embulk-cron.yml
apiVersion: batch/v1
kind: CronJob
metadata:
name: embulk
spec:
schedule: "*/5 * * * *"
concurrencyPolicy: Forbid
jobTemplate:
spec:
template:
spec:
containers:
- name: embulk
image: イメージ名
resources:
limits:
memory: "1200Mi"
requests:
memory: "1000Mi"
env:
- name: JAVA_OPTS
value: "-Xmx1g"
- name: HOST
value: 対象のホスト名
- name: USER
value: 対象のユーザ名
- name: PASSWOR
value: 対象のパスワード
restartPolicy: OnFailure
backoffLimit: 2
images:
に先ほど作成したembulkのイメージ名を入力しましょう.
resources:
のlimits
,requests
と環境変数のJAVA_OPTS
は収集対象のログの量にかなり依存すると思うので,適切に設定を行ってください.
環境変数のHOST
とUSER
,PASSWORD
はログを収集する対象のホスト名,ユーザ名,パスワードを入れてください.
あとはschedule:
の間隔など目的に合わせて設定をしてください.
Podのvolue
の指定やPV,PVCも使う目的に合わせて適切に設定をしてください.
(2-1) 設定が終わったらapplyをする.
kubectl apply -f embulk-cron.yml
(2-2) Cronjobが作成できているか確認.
kubectl get cronjob
(2-3) Podが作成できているか確認.
kubectl get pods
実際の出力
cdsl@ls-master:~/embulk-doktor$ kubectl apply -f embulk-worker1.yml -n embulk
cronjob.batch/embulk created
cdsl@ls-master:~/embulk-doktor$ kubectl get cronjob -n embulk
NAME SCHEDULE TIMEZONE SUSPEND ACTIVE LAST SCHEDULE AGE
embulk */5 * * * * <none> False 0 <none> 14s
cdsl@ls-master:~/embulk-doktor$ kubectl get pods -n embulk
NAME READY STATUS RESTARTS AGE
embulk-29203285-rjfkt 0/1 Completed 0 91s
(3)結果
このようにElastichsearch(Kibana)でログが表示されていれば成功です!
Embulkのconfigを使用するのにConfigMapを設定していなかったり,公開鍵認証ではなくパスワード認証だったり,いろいろ改善の余地はありそうですが,最低限テクニカルレポート検索サイトからログサーバにログを送信できるようになりました.
他の人の参考になれば幸いです.