loki-logging について
loki-loggingは、Grafana Lokiでログを集約・検索するプラットフォームやアプリケーションの運用者向けスキルです。Docker・KubernetesでのデプロイとLogQL分析を扱います。
主な機能
- 01Promtailによるログ収集
- 02ラベルとLogQLを使ったログ検索
- 03Grafanaでのログとダッシュボード表示
- 04記録ルールとアラートの設定
- 05収集、検索、メモリ問題の調査
活用シーン
- 01Kubernetes環境のログ集約
- 02ラベルによるアプリケーションログの絞り込みと分析
- 03Grafanaダッシュボードでのログ確認
- 04ログのエラー率に基づくアラート設定
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ bagelhole/ devops-security-agent-skills --skill loki-loggingインストール後、Claude Code で/loki-loggingを入力して読み込まれたか確認します。
詳細
Grafana Loki
Prometheus に着想を得たロギングシステムである Grafana Loki を使用して、ログを集約およびクエリします。
このスキルを使用する場面
次のような場合にこのスキルを使用します。
- コスト効率の高いログ集約を実装する
- Kubernetes 環境向けのロギングを構築する
- ログを Grafana ダッシュボードと統合する
- ラベルベースのフィルタリングでログをクエリする
- ELK より軽量な代替手段を求める
前提条件
- Docker または Kubernetes
- 可視化用の Grafana
- Promtail またはその他のログ転送ツール
アーキテクチャの概要
┌─────────────┐ ┌──────────┐ ┌──────────┐
│ Application │────▶│ Promtail │────▶│ Loki │
└─────────────┘ └──────────┘ └──────────┘
│
▼
┌──────────┐
│ Grafana │
└──────────┘
Docker のデプロイ
# docker-compose.yml
version: '3.8'
services:
loki:
image: grafana/loki:2.9.0
ports:
- "3100:3100"
volumes:
- ./loki-config.yaml:/etc/loki/local-config.yaml
- loki-data:/loki
command: -config.file=/etc/loki/local-config.yaml
promtail:
image: grafana/promtail:2.9.0
volumes:
- ./promtail-config.yaml:/etc/promtail/config.yaml
- /var/log:/var/log:ro
- /var/lib/docker/containers:/var/lib/docker/containers:ro
command: -config.file=/etc/promtail/config.yaml
grafana:
image: grafana/grafana:10.2.0
ports:
- "3000:3000"
volumes:
- grafana-data:/var/lib/grafana
- ./grafana/provisioning:/etc/grafana/provisioning
environment:
- GF_AUTH_ANONYMOUS_ENABLED=true
- GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
volumes:
loki-data:
grafana-data:
Loki の設定
# loki-config.yaml
auth_enabled: false
server:
http_listen_port: 3100
common:
path_prefix: /loki
storage:
filesystem:
chunks_directory: /loki/chunks
rules_directory: /loki/rules
replication_factor: 1
ring:
kvstore:
store: inmemory
schema_config:
configs:
- from: 2020-10-24
store: boltdb-shipper
object_store: filesystem
schema: v11
index:
prefix: index_
period: 24h
storage_config:
boltdb_shipper:
active_index_directory: /loki/index
cache_location: /loki/cache
shared_store: filesystem
limits_config:
reject_old_samples: true
reject_old_samples_max_age: 168h
max_query_series: 5000
max_query_parallelism: 2
chunk_store_config:
max_look_back_period: 168h
table_manager:
retention_deletes_enabled: true
retention_period: 168h
Promtail の設定
# promtail-config.yaml
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
# System logs
- job_name: system
static_configs:
- targets:
- localhost
labels:
job: varlogs
__path__: /var/log/*.log
# Docker container logs
- job_name: docker
docker_sd_configs:
- host: unix:///var/run/docker.sock
refresh_interval: 5s
relabel_configs:
- source_labels: ['__meta_docker_container_name']
regex: '/(.*)'
target_label: 'container'
- source_labels: ['__meta_docker_container_log_stream']
target_label: 'stream'
# Application logs with parsing
- job_name: application
static_configs:
- targets:
- localhost
labels:
job: application
__path__: /var/log/app/*.log
pipeline_stages:
- json:
expressions:
level: level
message: message
timestamp: timestamp
- labels:
level:
- timestamp:
source: timestamp
format: RFC3339
Kubernetes のデプロイ
# Using Helm
helm repo add grafana https://grafana.github.io/helm-charts
helm install loki grafana/loki-stack \
--namespace monitoring \
--create-namespace \
--set grafana.enabled=true \
--set promtail.enabled=true
Promtail DaemonSet
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: promtail
namespace: monitoring
spec:
selector:
matchLabels:
app: promtail
template:
metadata:
labels:
app: promtail
spec:
containers:
- name: promtail
image: grafana/promtail:2.9.0
args:
- -config.file=/etc/promtail/promtail.yaml
volumeMounts:
- name: config
mountPath: /etc/promtail
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
volumes:
- name: config
configMap:
name: promtail-config
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
LogQL クエリ
基本的なクエリ
# All logs from a job
{job="application"}
# Filter by label
{job="application", level="error"}
# Multiple labels
{namespace="production", container="api"}
# Regex match
{job=~"app.*"}
ログパイプライン
# Filter by content
{job="application"} |= "error"
# Exclude content
{job="application"} != "debug"
# Regex filter
{job="application"} |~ "user_id=[0-9]+"
# JSON parsing
{job="application"} | json | level="error"
# Line format
{job="application"} | json | line_format "{{.level}}: {{.message}}"
メトリクスクエリ
# Count logs per second
count_over_time({job="application"}[5m])
# Rate of errors
rate({job="application", level="error"}[5m])
# Sum by label
sum by (level) (count_over_time({job="application"}[5m]))
# Top services by error count
topk(5, sum by (service) (count_over_time({level="error"}[1h])))
集計
# Average log line length
avg_over_time({job="application"} | unwrap line_length [5m])
# Percentile of numeric field
quantile_over_time(0.95, {job="application"} | json | unwrap response_time [5m])
# Error percentage
sum(rate({job="application", level="error"}[5m]))
/
sum(rate({job="application"}[5m])) * 100
パイプラインのステージ
# promtail-config.yaml
pipeline_stages:
# Parse JSON logs
- json:
expressions:
level: level
message: msg
trace_id: trace_id
# Extract with regex
- regex:
expression: 'user_id=(?P<user_id>\d+)'
# Add labels from parsed fields
- labels:
level:
user_id:
# Modify timestamp
- timestamp:
source: timestamp
format: '2006-01-02T15:04:05.000Z'
# Filter logs
- match:
selector: '{level="debug"}'
action: drop
# Add static labels
- static_labels:
environment: production
# Modify log line
- template:
source: message
template: '{{ ToUpper .Value }}'
Grafana との統合
データソースの設定
# grafana/provisioning/datasources/loki.yaml
apiVersion: 1
datasources:
- name: Loki
type: loki
access: proxy
url: http://loki:3100
isDefault: false
jsonData:
maxLines: 1000
ダッシュボードパネル
{
"title": "Application Logs",
"type": "logs",
"datasource": "Loki",
"targets": [
{
"expr": "{job=\"application\"} | json",
"refId": "A"
}
],
"options": {
"showTime": true,
"showLabels": true,
"wrapLogMessage": true
}
}
記録ルール
# loki-rules.yaml
groups:
- name: error_rates
interval: 1m
rules:
- record: job:log_errors:rate5m
expr: |
sum by (job) (rate({level="error"}[5m]))
アラート
# loki-alerts.yaml
groups:
- name: log_alerts
rules:
- alert: HighErrorRate
expr: |
sum(rate({level="error"}[5m])) > 10
for: 5m
labels:
severity: critical
annotations:
summary: "High error rate in logs"
description: "Error rate is {{ $value }} errors/second"
よくある問題
問題:メモリ使用量が多い
問題:Loki のメモリ消費量が多すぎる 解決策:max_query_series を減らし、クエリの時間範囲を制限します
問題:ログが表示されない
問題:Promtail がログを転送していない 解決策:positions ファイルを確認し、ファイルパスを検証し、ラベル設定を確認します
問題:クエリのタイムアウト
問題:LogQL クエリがタイムアウトする 解決策:より具体的なラベルフィルターを追加し、時間範囲を短縮します
問題:取り込みレートの上限
問題:ログが破棄される 解決策:limits_config の per_stream_rate_limit を増やします
ベストプラクティス
- 意味のあるラベルを使用します(カーディナリティが高くならないようにします)
- ログの内容を調べる前に、ラベルでフィルタリングします
- Promtail で収集時にログを解析します
- 適切な保持期間を設定します
- よく使うクエリには記録ルールを使用します
- 大規模なデプロイでは適切なマルチテナンシーを実装します
- Loki 自体のメトリクスを監視します
- パフォーマンス向上のためにチャンクキャッシュを使用します
関連スキル
- prometheus-grafana - メトリクスの監視
- elk-stack - 代替ロギングシステム
- alerting-oncall - アラート管理
コメント
Markdown 対応