Nya Candy

Nya Candy

aka. Nya Crypto FSD(Fish Stack Developer) working at @rss3 with friends, Cɾყρƚσ Adventurer. candinya.eth
misskey

私は独自のログ収集技術を持っています

cover

本文同步发布于 糖菓・部落

サーバーが増えるにつれて、各サーバー上で実行されるコンテナがますます雑多になり、ログの収集が猫にとって悩みの種になってしまいました。普段は管理を便利にするために docker を使用しており、k8s を理解できなかったためにクラスターを構築していないので、ログの収集は少し気まずいことになっています。docker や docker-compose に付属の log コマンドを使ってクエリを実行する場合、元のサーバーに接続し、サービスディレクトリに入って、長いコマンドを入力し、成功した後には大量の出力の中から必要な部分を探さなければならず、うっかり見つけた内容が新しいログに上書きされてしまうこともあり、あまり優雅ではありません。そこで、実行ログを迅速かつ便利に収集し、必要に応じてクエリや整理を行うことができるソリューションを探し始めました。ちょうど最近、Grafana と Loki を研究しており、公式が開発した docker ログプラグインを見つけたので、使用した設定ファイルやコマンドを記録するためにもう一つ記事を書こうと思います。必要な友達が同様の問題を迅速に解決できるようにするためです。

使用時は、使用状況に応じて関連する設定ファイルを調整し、サンプル設定による干渉を避けてください。

Grafana + Loki の準備#

統合起動ファイルの準備#

Loki は実際にログを収集するサーバーと理解でき、Grafana はサーバーからデータをクエリするフロントエンドと理解できます。両者は相互に独立しているが相互に関連しており、同じローカルネットワーク環境にデプロイすることも、分けてパブリックネットワークを介して接続することもできます。ここでは、純粋にログを収集する特化したシナリオを使用しているため、直接docker-composeで関連して起動しました。

また、このサーバーはログ収集専用であり、他のサービスと 443 ポートを共有する必要がないため、Caddy の設定も一緒に書きました。

docker-compose.ymlファイルは以下の通りです:

version: '3.4'
services:

  loki:
    image: grafana/loki
    container_name: grafana-loki
    command: -config.file=/etc/loki/local-config.yml
    networks:
      - internal_network
    volumes:
      - ./config/loki.yml:/etc/loki/local-config.yml
      - ./data/loki:/tmp/loki

  grafana:
    depends_on:
      - grafana-db
      - loki
    image: grafana/grafana
    container_name: grafana
    networks:
      - internal_network
      - external_network
    volumes:
      - ./config/grafana.ini:/etc/grafana/grafana.ini
    restart: unless-stopped

  grafana-db:
    image: postgres:15-alpine
    restart: always
    container_name: grafana-db
    volumes:
      - ./data/db:/var/lib/postgresql/data
    environment:
      POSTGRES_USER: grafana
      POSTGRES_PASSWORD: password
      POSTGRES_DB: grafana
      POSTGRES_INITDB_ARGS: "--encoding='UTF8' --lc-collate='C' --lc-ctype='C'"
    networks:
      - internal_network

  caddy:
    image: caddy
    restart: always
    ports:
      - "443:443"
    networks:
      - internal_network
      - external_network
    volumes:
      - ./config/Caddyfile:/etc/caddy/Caddyfile
      - ./ssl:/ssl:ro
      - ./data/caddy/data:/data
      - ./data/caddy/config:/config

networks:
  internal_network:
    internal: true
  external_network:

公開されている唯一のポートは Caddy の 443 ポートであり、CDN で強制 HTTPS を有効にして、80 ポートへのリクエストが発生しないようにしています。

各サービスの設定の準備#

設定ファイルを統一して config ディレクトリに配置し、管理を容易にします。

Grafana#

grafana の設定ファイルgrafana.iniは以下の通りです:

[database]
type = postgres
host = grafana-db:5432
name = grafana
user = grafana
password = password

Loki#

loki の設定ファイルloki.ymlは以下の通りです:

auth_enabled: false

server:
  http_listen_port: 3100
  grpc_listen_port: 9095

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

query_range:
  results_cache:
    cache:
      embedded_cache:
        enabled: true
        max_size_mb: 100

schema_config:
  configs:
    - from: 2020-10-24
      store: boltdb-shipper
      object_store: filesystem
      schema: v11
      index:
        prefix: index_
        period: 24h

ruler:
  alertmanager_url: http://localhost:9093

analytics:
  reporting_enabled: false

# 参见 https://grafana.com/docs/loki/latest/configuration/
# 可以开启 S3 存储,暂时没必要就不管了

alertmanager_urlが何に設定すべきか分からず、ログ収集サービスとしてアラートのニーズを考慮していないため、サンプル値をそのまま保持しています。

auth_enabledという設定項目に注意が必要です。このフィールドの意味は、異なる領域のリクエストヘッダーを設定することで、複数の組織が同じ loki サービスを共有することを実現することです。これを有効にすると、HTTP 呼び出しでX-Scope-OrgIDを使用してリクエストを発信する組織を区別する必要があります。データを送信したり取得したりする際には、常にこれを持参する必要があります。しかし、ここでは単独使用であり、データ共有に関する問題はないため、このオプションは無効にしています。

loki 自体は HTTP 認証チェックを持っていないため、認証リクエストヘッダーをフロントエンドのリバースプロキシプログラムの設定に記述することをお勧めします。例えば、ここでは Caddy の設定ファイルに配置し、パブリックトラフィックからのリクエストに対してのみ認証チェックを要求し、Grafana が内部ネットワーク接続を使用する場合は検証を必要としません。

Caddy#

ここでは CDN プロバイダーのソースサーバー証明書を使用しており、Caddy に申請させる必要がないため、設定ファイルは以下の通りです:

example.com {
    tls /ssl/example.com/cert.pem /ssl/example.com/key.pem
    reverse_proxy grafana:3000
}
loki.example.com {
    tls /ssl/example.com/cert.pem /ssl/example.com/key.pem
    reverse_proxy loki:3100
    basicauth * {
        user $2a$14$QZIF1JLM9lFPjAl6PQzBDeANmB4Ssufc0qUnP9nI7QYnv.QevEzyi
    }
}
loki-grpc.example.com {
    tls /ssl/example.com/cert.pem /ssl/example.com/key.pem
    reverse_proxy loki:9095
    basicauth * {
        user $2a$14$QZIF1JLM9lFPjAl6PQzBDeANmB4Ssufc0qUnP9nI7QYnv.QevEzyi
    }
}

認証部分には BasicAuth を使用しており、ユーザー名とパスワードの方式です。パスワードは平文で保存されず、caddy のhash-password機能によって事前に計算されており、可能な限り安全性を高めています。

/srv # caddy hash-password
Enter password: 
Confirm password: 
$2a$14$QZIF1JLM9lFPjAl6PQzBDeANmB4Ssufc0qUnP9nI7QYnv.QevEzyi
/srv #

設定が完了したら、対応する SSL 証明書を指定された場所に配置し、証明書ファイルがないことによるエラーを避ける必要があります。

すべての設定が完了したら、docker-compose up -dコマンドを使用して起動できるはずです。

Loki データディレクトリの権限管理#

コンテナ内の Loki は root ユーザーとして起動されないため、Docker が設定した root 権限により Loki のアクセスが拒否されます。以下のようなコマンドを手動で実行して、Loki のデータディレクトリの権限をコンテナが使用できるように開放する必要があります:

chown -R 10001:10001 ./data/loki/

変更が完了したら、Loki コンテナを再起動してください。

Loki を Grafana のデータソースとして関連付ける#

デプロイされた Grafana に入り、デフォルトのユーザー名とパスワードadminでログインし、パスワードを変更した後、データソースの追加を開始できます。

上記の docker-compose 設定に基づいている場合、Loki を選択し、HTTP の URL にhttp://loki:3100を入力するだけで、保存してテストできます。この時点で Loki にはログがないため、ラベルが見つからないというエラーメッセージが表示されますが、心配しないでください。後でログが出現すれば大丈夫です。

サーバーの準備#

docker 環境を使用しているため、具体的なコマンドはここでは詳述しません。loki ログプラグインのインストールから直接始めます。

ここでは、Docker Driver Clientが提供するチュートリアルを参照しています。関連する内容は更新される可能性があるため注意してください。

loki-docker-driver プラグインのインストール#

データを loki に送信するためには、Docker のログを詳細なタグ情報を持つデータに変換し、Loki 互換のインターフェースを使用して上記のサーバーに送信するプラグインが必要です。このコマンドを使用してこのプラグインをインストールできます:

docker plugin install grafana/loki-docker-driver:latest --alias loki --grant-all-permissions

インストールが完了したら、docker plugin lsを使用してインストールされたプラグインを確認できます。

後でアップグレードが必要な場合は、元のリンクに記載されているコマンドを参照してアップグレードできます:
docker plugin disable loki --force
docker plugin upgrade loki grafana/loki-docker-driver:latest --grant-all-permissions
docker plugin enable loki
systemctl restart docker

次に、プラグインの具体的な設定を行うことができます。ホストマシン上のすべての docker ログを収集する必要があり、異なる組織を区別する必要がないため、/etc/docker/daemon.jsonファイルを設定し、以下の内容を書き込みます:

{
    "log-driver": "loki",
    "log-opts": {
        "loki-url": "https://user:[email protected]/loki/api/v1/push"
    }
}

設定が完了したら、docker プロセスを再起動して変更を有効にする必要があります。

この時点では、すべてのコンテナにリアルタイムで適用されるわけではなく、すでに作成されたコンテナのログシステムは固定されているため、新しく作成されたコンテナにのみ有効です。ログ収集が非常に急務である場合は、docker-compose up -d --force-recreateを使用してすべてのコンテナを再構築することを試みることができます。

Grafana でのクエリ#

設定が完了し、新しく作成されたコンテナが稼働してログを生成し始めたら、Grafana でクエリを実行できるはずです。単独使用であり、詳細な可視化のニーズがないため、ダッシュボードは設定せず、直接 Explore 機能に入ってインタラクティブなクエリを行います。

ログが表示されたら、ラベルを使用してソースをフィルタリングできます。このプラグインは、host compose_project compose_service container_name source filenameの 6 つのフィルタリングタグを提供します。その中で:

  • hostはログを発信したホストマシンのホスト名を指します。
  • compose_project compose_serviceまたはcontainer_nameはコンテナを特定するために使用できます。
  • sourceはログのソースが通常の出力stdoutかエラーログstderrかを示します。
  • filenameはログの元のファイルを指します(通常は重要ではありません)。

これらのタグを Grafana の時間制御と組み合わせて使用することで、特定のコンテナの実行ログを迅速にクエリできます。もうログが散らばって多すぎるという悩みはありません!

筛选出来的日志

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。