Fedora ServerでのGrafana LokiとPromtailの構築:ELKより軽量な集中ログ管理

Fedora tutorial - IT technology blog
Fedora tutorial - IT technology blog

深夜に各サーバーへSSHしてgrepログ調査を行う悪夢

約半年前、管理対象のFedora Serverノードが15台に達した頃から悪夢が始まりました。深夜にアプリケーションが500エラーを吐くたび、お決まりのデバッグ手順が繰り返されます。ターミナルを立ち上げ、各ノードにSSH接続し、journalctl -u app.service -fを実行するか、目を皿のようにして/var/log/nginx/access.logの行を1行ずつgrepする日々でした。

1〜2台のサーバー管理ならこれでも問題ありません。しかし数十台規模になると、手動デバッグでは複数サービス間のエラーの相関関係を見落としやすくなります。私たちのチームもELK stack(Elasticsearch、Logstash、Kibana)の導入を検討しました。しかし、Elasticsearchだけでもログのインデックス作成待ちのためにJVMヒープで4GB〜8GBのRAMを占有してしまいます。小規模なVPS群にとって、このリソース消費はあまりに贅沢すぎました。

本番環境で6ヶ月間運用した結果、Loki + Promtail + Grafanaの組み合わせがこの課題を完璧に解決してくれました。軽量な設定、極めて少ないメモリ消費量、そして即座にログを検索できる環境が手に入ります。

LokiとPromtailの仕組みとは?

Grafana Lokiは、Prometheusの中核となる設計思想を共有しています。Elasticsearchのようにログテキストの全文をインデックス化する代わりに、Lokiはメタデータ(ラベル)のみをインデックス化します。生のログデータ自体はgzipやsnappy形式でチャンクに圧縮され、ローカルディスクやオブジェクトストレージに直接保存されます。

アーキテクチャを構成する3つの要素

  • Promtail: 各Fedoraノード上でバックグラウンド動作するエージェント。/var/log/配下のファイル監視やsystemd journalからの直接読み取りを行い、ラベル(host=fedora-node-01、job=systemd-journalなど)を付与してHTTP POST経由でLokiにログを送信します。
  • Loki: Promtailからのデータストリームを受け取り、チャンクを圧縮・保存し、LogQL言語によるクエリ処理を担う中央集権ノードです。
  • Grafana: 視覚的なダッシュボード。Lokiをデータソースとして接続し、検索、エラートレースのフィルタリング、頻度グラフの描画を行います。

ラベルのみをインデックス化する仕組みのおかげで、Lokiのリソース消費量は非常に控えめです。私たちのシステムでは1日あたり400万〜500万行のログを着実に処理していますが、LokiのRAM使用量は320MB〜380MB程度にとどまっています。

実践:Fedora Serverでのログ基盤構築

Fedora Serverは最新のカーネル、完全なsystemd環境、そして常にアップデートされたパッケージ群を備えています。以下に、ゼロからの構築手順を解説します。

ステップ1:Grafanaのインストール

Fedoraに公式のGrafanaリポジトリを追加します:

sudo tee /etc/yum.repos.d/grafana.repo << 'EOF'
[grafana]
name=grafana
baseurl=https://rpm.grafana.com
repo_gpgcheck=1
enabled=1
gpgkey=https://rpm.grafana.com/gpg.key
sslverify=1
sslcacert=/etc/pki/tls/certs/ca-bundle.crt
EOF

sudo dnf install -y grafana
sudo systemctl daemon-reload
sudo systemctl enable --now grafana-server

ポート3000でリッスンしているか確認します:

sudo ss -tulpn | grep 3000

ステップ2:LokiとPromtailのバイナリインストール

GrafanaはGitHub上でスタンドアロンのLinuxバイナリを提供しています。systemdで一元管理するため、バイナリを直接/usr/local/bin/にダウンロードします:

LOKI_VERSION="v3.0.0"
sudo dnf install -y unzip curl

# Lokiバイナリのダウンロードと解凍
curl -fsSL -o /tmp/loki.zip "https://github.com/grafana/loki/releases/download/${LOKI_VERSION}/loki-linux-amd64.zip"
sudo unzip -q -o -d /usr/local/bin/ /tmp/loki.zip
sudo chmod 755 /usr/local/bin/loki-linux-amd64
sudo ln -sf /usr/local/bin/loki-linux-amd64 /usr/local/bin/loki

# Promtailバイナリのダウンロードと解凍
curl -fsSL -o /tmp/promtail.zip "https://github.com/grafana/loki/releases/download/${LOKI_VERSION}/promtail-linux-amd64.zip"
sudo unzip -q -o -d /usr/local/bin/ /tmp/promtail.zip
sudo chmod 755 /usr/local/bin/promtail-linux-amd64
sudo ln -sf /usr/local/bin/promtail-linux-amd64 /usr/local/bin/promtail

ステップ3:Lokiサーバーの設定

セキュリティを高め、root権限でのプロセス実行を避けるために専用のシステムユーザーlokiを作成します:

sudo useradd --system --no-create-home --shell /sbin/nologin loki || true
sudo mkdir -p /etc/loki /var/lib/loki
sudo chown -R loki:loki /var/lib/loki

設定ファイル/etc/loki/loki-config.yamlを作成します:

sudo tee /etc/loki/loki-config.yaml << 'EOF'
auth_enabled: false

server:
  http_listen_port: 3100
  grpc_listen_port: 9096

common:
  instance_addr: 127.0.0.1
  path_prefix: /var/lib/loki
  storage:
    filesystem:
      chunks_directory: /var/lib/loki/chunks
      rules_directory: /var/lib/loki/rules
  replication_factor: 1
  ring:
    kvstore:
      store: inmemory

schema_config:
  configs:
    - from: 2024-01-01
      store: tsdb
      object_store: filesystem
      schema: v13
      index:
        prefix: index_
        period: 24h

limits_config:
  reject_old_samples: true
  reject_old_samples_max_age: 168h
EOF

Lokiのsystemdサービスを作成します:

sudo tee /etc/systemd/system/loki.service << 'EOF'
[Unit]
Description=Loki service
After=network.target

[Service]
Type=simple
User=loki
Group=loki
ExecStart=/usr/local/bin/loki -config.file=/etc/loki/loki-config.yaml
Restart=on-failure
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now loki

ステップ4:systemd journalとログファイルを読み取るPromtailの設定

Fedora上のPromtailは、中継用のrsyslogを設定することなくjournaldへ直接フックできます。

Promtailがjournalやログファイルを読み取れるようにするため、ユーザーpromtailをsystemd-journalグループとadmグループに追加します:

sudo useradd --system --no-create-home --shell /sbin/nologin promtail || true
sudo usermod -aG systemd-journal,adm promtail
sudo mkdir -p /etc/promtail /var/lib/promtail
sudo chown -R promtail:promtail /var/lib/promtail

収集設定ファイル/etc/promtail/promtail-config.yamlを作成します:

sudo tee /etc/promtail/promtail-config.yaml << 'EOF'
server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /var/lib/promtail/positions.yaml

clients:
  - url: http://127.0.0.1:3100/loki/api/v1/push

scrape_configs:
  - job_name: system
    static_configs:
      - targets:
          - localhost
        labels:
          job: varlogs
          host: fedora-server
          __path__: /var/log/*.log

  - job_name: journal
    journal:
      max_age: 12h
      labels:
        job: systemd-journal
        host: fedora-server
    relabel_configs:
      - source_labels: ['__journal__systemd_unit']
        target_label: 'unit'
      - source_labels: ['__journal_priority_keyword']
        target_label: 'level'
EOF

Promtailサービスを起動します:

sudo tee /etc/systemd/system/promtail.service << 'EOF'
[Unit]
Description=Promtail service
After=network.target

[Service]
Type=simple
User=promtail
Group=promtail
ExecStart=/usr/local/bin/promtail -config.file=/etc/promtail/promtail-config.yaml
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now promtail

ステップ5:Firewalldの設定

Fedora Serverではデフォルトでfirewalldが有効化されています。Grafana用のポート3000と、外部サーバーからログを受信する場合はLoki用のポート3100を開放します:

sudo firewall-cmd --permanent --add-port=3000/tcp
sudo firewall-cmd --permanent --add-port=3100/tcp
sudo firewall-cmd --reload

ステップ6:LogQLを使ったGrafanaでのログクエリ

ブラウザからhttp://<FedoraサーバーのIP>:3000にアクセスします。初期アカウントadmin / adminでログインし、新しいパスワードに変更します。

  1. Connections > Data sourcesに移動し、Add data sourceを選択してLokiをクリックします。
  2. URL欄にhttp://127.0.0.1:3100を入力し、Save & testをクリックします(正常に接続できれば緑色で表示されます)。
  3. Exploreメニューを開き、Data sourceにLokiを選択してクエリの作成を開始します。

運用時に役立つ実践的なLogQLクエリの例:

# 大小文字を区別せず、文字列 "error" を含む systemd-journal のログをすべて抽出
{job="systemd-journal"} |=? "error"

# SSHサービスのエラーのみを抽出
{unit="sshd.service", level="err"}

# 5分間ごとのNginxログにおけるHTTP 500エラーの発生レートをホスト別に算出
sum(rate({job="varlogs"} |= " 500 " [5m])) by (host)

軽量・高安定性で、中小規模の本番環境に最適

手動のSSH調査からLoki + Promtailの構成へと移行したことで、障害調査にかかる時間を20分以上から2分未満へと大幅に短縮できました。2 vCPU、2GB RAMの手頃なFedora VPS(月額5〜6ドル程度)であっても、メモリ不足に悩まされることなくGrafanaとLokiの両方が軽快に稼働しています。

Share: