Fluentd로 Slack 알림 연결하기 (Kubernetes + Minecraft 로그)

2026. 2. 11. 23:27k8s

소개
Kubernetes에서 특정 로그를 감지해 Slack으로 알림을 보내는 방법을 정리했습니다.
예시는 Minecraft 로그의 joined the game 이벤트를 Slack으로 전달하는 구성입니다.


1) Fluentd 이미지 준비

Slack 플러그인을 포함한 Fluentd 이미지를 만듭니다.

FROM fluent/fluentd:v1.16-1

USER root
RUN fluent-gem install fluent-plugin-slack --no-document

# Ruby 3.1 호환 shim
RUN mkdir -p /fluentd/plugins \
  && cat <<'RUBY' > /fluentd/plugins/uri_unescape.rb
require 'uri'
unless URI.respond_to?(:unescape)
  module URI
    def self.unescape(str)
      URI.decode_www_form_component(str)
    end
  end
end
RUBY

USER fluent

2) Kubernetes 설정 (ConfigMap + DaemonSet)

아래는 핵심 설정입니다.

포인트:

  • CRI 로그 포맷 파싱
  • joined the game만 필터링
  • 메시지를 barisein joined the game 형태로 정리
  • pos_file을 hostPath에 저장해서 중복 알림 방지
  • tag/filter/match 이름을 minecraft.alerm으로 통일
apiVersion: v1
kind: Namespace
metadata:
  name: mc-monitoring
---
apiVersion: v1
kind: Secret
metadata:
  name: slack-webhook
  namespace: mc-monitoring
type: Opaque
stringData:
  webhook_url: "https://hooks.slack.com/services/XXX/YYY/ZZZ"
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: fluentd-config
  namespace: mc-monitoring
data:
  fluent.conf: |
    <system>
      plugin_dir /fluentd/plugins
    </system>

    <source>
      @type tail
      path /var/log/containers/minecraft-*.log
      pos_file /fluentd/pos/fluentd.pos.minecraft
      tag minecraft.alerm
      read_from_head false
      <parse>
        @type regexp
        expression /^(?<time>[^ ]+) (?<stream>stdout|stderr) (?<flag>.) (?<log>.*)$/
        time_key time
        time_format %Y-%m-%dT%H:%M:%S.%N%z
      </parse>
    </source>

    <filter minecraft.alerm>
      @type grep
      <regexp>
        key log
        pattern /joined the game/
      </regexp>
    </filter>

    <filter minecraft.alerm>
      @type record_transformer
      enable_ruby true
      <record>
        message ${ (record["log"] || "").sub(/^.*\]:\s*/, "") }
      </record>
    </filter>

    <match minecraft.alerm>
      @type slack
      webhook_url "#{ENV['SLACK_WEBHOOK_URL']}"
      channel "#alerts"
      username "fluentd"
      icon_emoji ":rotating_light:"
      title "Minecraft Join"
      message_key message
    </match>
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: fluentd
  namespace: mc-monitoring
spec:
  selector:
    matchLabels:
      app: fluentd
  template:
    metadata:
      labels:
        app: fluentd
    spec:
      nodeSelector:
        kubernetes.io/hostname: dell
      containers:
        - name: fluentd
          image: registry.example.com/fluentd-slack:v1.16-1
          imagePullPolicy: Always
          securityContext:
            runAsUser: 0
            runAsGroup: 0
          env:
            - name: FLUENTD_OPT
              value: "-p /fluentd/plugins"
            - name: RUBYOPT
              value: "-r/fluentd/plugins/uri_unescape"
            - name: SLACK_WEBHOOK_URL
              valueFrom:
                secretKeyRef:
                  name: slack-webhook
                  key: webhook_url
          volumeMounts:
            - name: varlog
              mountPath: /var/log
            - name: dockercontainers
              mountPath: /var/lib/docker/containers
              readOnly: true
            - name: config
              mountPath: /fluentd/etc
            - name: pos
              mountPath: /fluentd/pos
      volumes:
        - name: varlog
          hostPath:
            path: /var/log
        - name: dockercontainers
          hostPath:
            path: /var/lib/docker/containers
        - name: config
          configMap:
            name: fluentd-config
        - name: pos
          hostPath:
            path: /var/lib/fluentd/pos
            type: DirectoryOrCreate

3) 적용

kubectl apply -f fluentd-slack.yaml
kubectl -n mc-monitoring rollout restart ds/fluentd

4) 결과 예시

Slack에 다음처럼 표시됩니다.

Minecraft Join
barisein joined the game

마무리

Fluentd는 로그 필터링/가공에 강해서 “운영 알림”에 잘 맞습니다.
필요하면 left the game도 추가하거나, 중복 알림 쿨다운도 쉽게 확장 가능합니다.