mimir について
mimirは、PrometheusとOpenTelemetryのメトリクスを長期保存するチーム向けのGrafana Mimir導入・運用ガイドです。分散コンポーネント、オブジェクトストレージ、マルチテナント、クエリ、障害調査を扱います。
主な機能
- 01モノリシックとマイクロサービスの導入を解説
- 02オブジェクトストレージのバックエンド設定
- 03PrometheusとOTLPメトリクスの取り込み
- 04テナントとテナント別制限の設定
- 05クエリ、アラート、障害調査の案内
活用シーン
- 01メトリクス長期保存用にMimirを導入
- 02テナント分離とテナント別制限を設定
- 03OpenTelemetryメトリクスを取り込み検索
- 04ストレージ、取り込み、クエリの問題を調査
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ julianobarbosa/ claude-code-skills --skill mimirインストール後、Claude Code で/mimirを入力して読み込まれたか確認します。
詳細
Grafana Mimir スキル
Grafana Mimir の包括的なガイドです。Grafana Mimir は、Prometheus メトリクスを長期保存するための、水平スケーラブルで高可用性、マルチテナント対応の時系列データベースです。
Mimir とは?
Mimir は、Prometheus と OpenTelemetry のメトリクス向けのオープンソースで、水平スケーラブルかつ高可用性を備えたマルチテナント対応の長期ストレージソリューションです。次の特長があります。
- Prometheus の制約を克服 — スケーラビリティと長期保持を実現します
- デフォルトでマルチテナント対応 —
X-Scope-OrgIDヘッダーによるテナント分離を標準で備えています - オブジェクトストレージにデータを保存 — S3、GCS、Azure Blob Storage、または Swift に対応します
- 100% Prometheus 互換 — PromQL クエリ、リモートライトプロトコルに対応します
- LGTM+ Stack の一部 — ログ、Grafana、トレース、メトリクスを統合したオブザーバビリティを提供します
アーキテクチャの概要
コアコンポーネント
| コンポーネント | 目的 |
|---|---|
| Distributor | リクエストを検証し、ハッシュリングを介して受信メトリクスを Ingester にルーティングします |
| Ingester | 時系列データをメモリに保存し、オブジェクトストレージにフラッシュします |
| Querier | Ingester と Store-Gateway から PromQL クエリを実行します |
| Query Frontend | クエリ結果をキャッシュし、クエリを最適化して分割します |
| Query Scheduler | 公平性を確保するため、テナントごとのクエリキューを管理します |
| Store-Gateway | オブジェクトストレージ内の過去のメトリクスブロックへのアクセスを提供します |
| Compactor | 保存されたメトリクスデータブロックを統合し、最適化します |
| Ruler | レコーディングルールとアラートルールを評価します(オプション) |
| Alertmanager | アラートのルーティングと重複排除を処理します(オプション) |
データフロー
書き込みパス:
Prometheus/OTel → Distributor → Ingester → Object Storage
↓
Hash Ring
(routes by series)
読み取りパス:
Query → Query Frontend → Query Scheduler → Querier
↓
Ingesters (recent)
↓
Store-Gateway (historical)
デプロイモード
1. モノリシックモード(-target=all)
- すべてのコンポーネントを単一プロセスで実行します
- 最適な用途:開発、テスト、小規模環境(約 100 万時系列)
- 複数のインスタンスをデプロイして水平スケーリングできます
- 大規模環境には推奨されません(すべてのコンポーネントが一緒にスケーリングされます)
2. マイクロサービスモード(分散型)— 本番環境に推奨
# Using mimir-distributed Helm chart
distributor:
replicas: 3
ingester:
replicas: 3
zoneAwareReplication:
enabled: true
querier:
replicas: 3
queryFrontend:
replicas: 2
queryScheduler:
replicas: 2
storeGateway:
replicas: 3
compactor:
replicas: 1
Helm によるデプロイ
リポジトリを追加
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
分散型 Mimir をインストール
helm install mimir grafana/mimir-distributed \
--namespace monitoring \
--values values.yaml
事前構築済みの値ファイル
| ファイル | 目的 |
|---|---|
values.yaml | MinIO を使用した非本番環境でのテスト |
small.yaml | 約 100 万時系列(単一レプリカ、HA なし) |
large.yaml | 本番環境(約 1,000 万時系列) |
本番環境向けの値の例
# Deployment mode
mimir:
structuredConfig:
multitenancy_enabled: true
# Storage configuration
mimir:
structuredConfig:
common:
storage:
backend: azure # or s3, gcs
azure:
account_name: ${AZURE_STORAGE_ACCOUNT}
account_key: ${AZURE_STORAGE_KEY}
endpoint_suffix: blob.core.windows.net
blocks_storage:
azure:
container_name: mimir-blocks
alertmanager_storage:
azure:
container_name: mimir-alertmanager
ruler_storage:
azure:
container_name: mimir-ruler
# Distributor
distributor:
replicas: 3
resources:
requests:
cpu: 1
memory: 2Gi
limits:
memory: 4Gi
# Ingester
ingester:
replicas: 3
zoneAwareReplication:
enabled: true
persistentVolume:
enabled: true
size: 50Gi
resources:
requests:
cpu: 2
memory: 8Gi
limits:
memory: 16Gi
# Querier
querier:
replicas: 3
resources:
requests:
cpu: 1
memory: 2Gi
limits:
memory: 8Gi
# Query Frontend
query_frontend:
replicas: 2
resources:
requests:
cpu: 500m
memory: 1Gi
limits:
memory: 2Gi
# Query Scheduler
query_scheduler:
replicas: 2
# Store Gateway
store_gateway:
replicas: 3
persistentVolume:
enabled: true
size: 20Gi
resources:
requests:
cpu: 500m
memory: 2Gi
limits:
memory: 8Gi
# Compactor
compactor:
replicas: 1
persistentVolume:
enabled: true
size: 50Gi
resources:
requests:
cpu: 1
memory: 4Gi
limits:
memory: 8Gi
# Gateway for external access
gateway:
enabledNonEnterprise: true
replicas: 2
# Monitoring
metaMonitoring:
serviceMonitor:
enabled: true
ストレージの設定
重要な要件
- バケットは手動で作成する必要があります — Mimir はバケットを作成しません
- バケットは分ける必要があります — blocks_storage、alertmanager_storage、ruler_storage は同じバケットとプレフィックスを共有できません
- Azure:階層型名前空間を無効にする必要があります
Azure Blob Storage
mimir:
structuredConfig:
common:
storage:
backend: azure
azure:
account_name: <storage-account-name>
# Option 1: Account Key (via environment variable)
account_key: ${AZURE_STORAGE_KEY}
# Option 2: User-Assigned Managed Identity
# user_assigned_id: <identity-client-id>
endpoint_suffix: blob.core.windows.net
blocks_storage:
azure:
container_name: mimir-blocks
alertmanager_storage:
azure:
container_name: mimir-alertmanager
ruler_storage:
azure:
container_name: mimir-ruler
AWS S3
mimir:
structuredConfig:
common:
storage:
backend: s3
s3:
endpoint: s3.us-east-1.amazonaws.com
region: us-east-1
access_key_id: ${AWS_ACCESS_KEY_ID}
secret_access_key: ${AWS_SECRET_ACCESS_KEY}
blocks_storage:
s3:
bucket_name: mimir-blocks
alertmanager_storage:
s3:
bucket_name: mimir-alertmanager
ruler_storage:
s3:
bucket_name: mimir-ruler
Google Cloud Storage
mimir:
structuredConfig:
common:
storage:
backend: gcs
gcs:
service_account: ${GCS_SERVICE_ACCOUNT_JSON}
blocks_storage:
gcs:
bucket_name: mimir-blocks
alertmanager_storage:
gcs:
bucket_name: mimir-alertmanager
ruler_storage:
gcs:
bucket_name: mimir-ruler
制限の設定
mimir:
structuredConfig:
limits:
# Ingestion limits
ingestion_rate: 25000 # Samples/sec per tenant
ingestion_burst_size: 50000 # Burst size
max_series_per_metric: 10000
max_series_per_user: 1000000
max_global_series_per_user: 1000000
max_label_names_per_series: 30
max_label_name_length: 1024
max_label_value_length: 2048
# Query limits
max_fetched_series_per_query: 100000
max_fetched_chunks_per_query: 2000000
max_query_lookback: 0 # No limit
max_query_parallelism: 32
# Retention
compactor_blocks_retention_period: 365d # 1 year
# Out-of-order samples
out_of_order_time_window: 5m
テナントごとのオーバーライド(ランタイム設定)
# runtime-config.yaml
overrides:
tenant1:
ingestion_rate: 50000
max_series_per_user: 2000000
compactor_blocks_retention_period: 730d # 2 years
tenant2:
ingestion_rate: 75000
max_global_series_per_user: 5000000
ランタイム設定を有効にします。
mimir:
structuredConfig:
runtime_config:
file: /etc/mimir/runtime-config.yaml
period: 10s
高可用性の設定
Prometheus の重複排除向け HA Tracker
mimir:
structuredConfig:
distributor:
ha_tracker:
enable_ha_tracker: true
kvstore:
store: memberlist
cluster_label: cluster
replica_label: __replica__
memberlist:
join_members:
- mimir-gossip-ring.monitoring.svc.cluster.local:7946
Prometheus の設定:
global:
external_labels:
cluster: prom-team1
__replica__: replica1
remote_write:
- url: http://mimir-gateway:8080/api/v1/push
headers:
X-Scope-OrgID: my-tenant
ゾーンを考慮したレプリケーション
ingester:
zoneAwareReplication:
enabled: true
zones:
- name: zone-a
nodeSelector:
topology.kubernetes.io/zone: us-east-1a
- name: zone-b
nodeSelector:
topology.kubernetes.io/zone: us-east-1b
- name: zone-c
nodeSelector:
topology.kubernetes.io/zone: us-east-1c
store_gateway:
zoneAwareReplication:
enabled: true
シャッフルシャーディング
障害を分離するため、テナントのデータをインスタンスの一部に制限します。
mimir:
structuredConfig:
limits:
# Write path
ingestion_tenant_shard_size: 3
# Read path
max_queriers_per_tenant: 5
store_gateway_tenant_shard_size: 3
OpenTelemetry との統合
OTLP メトリクスの取り込み
OpenTelemetry Collector の設定:
exporters:
otlphttp:
endpoint: http://mimir-gateway:8080/otlp
headers:
X-Scope-OrgID: "my-tenant"
service:
pipelines:
metrics:
receivers: [otlp]
exporters: [otlphttp]
指数ヒストグラム(実験的機能)
// Go SDK configuration
Aggregation: metric.AggregationBase2ExponentialHistogram{
MaxSize: 160, // Maximum buckets
MaxScale: 20, // Scale factor
}
主なメリット:
- 最小値と最大値が明示されるため、推定が不要です
- 極端なパーセンタイルの精度が向上します
- ネイティブの OTLP 形式を保持します
マルチテナント
mimir:
structuredConfig:
multitenancy_enabled: true
no_auth_tenant: anonymous # Used when multitenancy disabled
テナントヘッダーを指定したクエリ:
curl -H "X-Scope-OrgID: tenant-a" \
"http://mimir:8080/prometheus/api/v1/query?query=up"
テナント ID の制約:
- 最大 150 文字
- 使用可能:英数字、
!-_.*'() - 使用禁止:単独の
.または..、__mimir_cluster、スラッシュ
API リファレンス
取り込みエンドポイント
# Prometheus remote write
POST /api/v1/push
# OTLP metrics
POST /otlp/v1/metrics
# InfluxDB line protocol
POST /api/v1/push/influx/write
クエリエンドポイント
# Instant query
GET,POST /prometheus/api/v1/query?query=<promql>&time=<timestamp>
# Range query
GET,POST /prometheus/api/v1/query_range?query=<promql>&start=<start>&end=<end>&step=<step>
# Labels
GET,POST /prometheus/api/v1/labels
GET /prometheus/api/v1/label/{name}/values
# Series
GET,POST /prometheus/api/v1/series
# Exemplars
GET,POST /prometheus/api/v1/query_exemplars
# Cardinality
GET,POST /prometheus/api/v1/cardinality/label_names
GET,POST /prometheus/api/v1/cardinality/active_series
管理エンドポイント
# Flush ingester data
GET,POST /ingester/flush
# Prepare shutdown
GET,POST,DELETE /ingester/prepare-shutdown
# Ring status
GET /ingester/ring
GET /distributor/ring
GET /store-gateway/ring
GET /compactor/ring
# Tenant stats
GET /distributor/all_user_stats
GET /api/v1/user_stats
GET /api/v1/user_limits
ヘルスと設定
GET /ready
GET /metrics
GET /config
GET /config?mode=diff
GET /runtime_config
Azure ID の設定
ユーザー割り当てのマネージド ID
1. ID を作成します:
az identity create \
--name mimir-identity \
--resource-group <rg>
IDENTITY_CLIENT_ID=$(az identity show --name mimir-identity --resource-group <rg> --query clientId -o tsv)
IDENTITY_PRINCIPAL_ID=$(az identity show --name mimir-identity --resource-group <rg> --query principalId -o tsv)
2. ノードプールに割り当てます:
az vmss identity assign \
--resource-group <aks-node-rg> \
--name <vmss-name> \
--identities /subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.ManagedIdentity/userAssignedIdentities/mimir-identity
3. ストレージのアクセス許可を付与します:
az role assignment create \
--role "Storage Blob Data Contributor" \
--assignee-object-id $IDENTITY_PRINCIPAL_ID \
--scope /subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Storage/storageAccounts/<storage>
4. Mimir を設定します:
mimir:
structuredConfig:
common:
storage:
azure:
user_assigned_id: <IDENTITY_CLIENT_ID>
ワークロード ID フェデレーション
1. フェデレーション資格情報を作成します:
az identity federated-credential create \
--name mimir-federated \
--identity-name mimir-identity \
--resource-group <rg> \
--issuer <aks-oidc-issuer-url> \
--subject system:serviceaccount:monitoring:mimir \
--audiences api://AzureADTokenExchange
2. Helm の値を設定します:
serviceAccount:
annotations:
azure.workload.identity/client-id: <IDENTITY_CLIENT_ID>
podLabels:
azure.workload.identity/use: "true"
トラブルシューティング
よくある問題
1. コンテナーが見つからない(Azure)
# Create required containers
az storage container create --name mimir-blocks --account-name <storage>
az storage container create --name mimir-alertmanager --account-name <storage>
az storage container create --name mimir-ruler --account-name <storage>
2. 認証に失敗する(Azure)
# Verify RBAC assignment
az role assignment list --scope /subscriptions/<sub>/resourceGroups/<rg>/providers/Microsoft.Storage/storageAccounts/<storage>
# Assign if missing
az role assignment create \
--role "Storage Blob Data Contributor" \
--assignee-object-id <principal-id> \
--scope <storage-scope>
# Restart pod to refresh token
kubectl delete pod -n monitoring <ingester-pod>
3. Ingester の OOM
ingester:
resources:
limits:
memory: 16Gi # Increase memory
4. クエリのタイムアウト
mimir:
structuredConfig:
querier:
timeout: 5m
max_concurrent: 20
5. カーディナリティが高い
mimir:
structuredConfig:
limits:
max_series_per_user: 5000000
max_series_per_metric: 50000
診断コマンド
# Check pod status
kubectl get pods -n monitoring -l app.kubernetes.io/name=mimir
# Check ingester logs
kubectl logs -n monitoring -l app.kubernetes.io/component=ingester --tail=100
# Check distributor logs
kubectl logs -n monitoring -l app.kubernetes.io/component=distributor --tail=100
# Verify readiness
kubectl exec -it <mimir-pod> -n monitoring -- wget -qO- http://localhost:8080/ready
# Check ring status
kubectl port-forward svc/mimir-distributor 8080:8080 -n monitoring
curl http://localhost:8080/distributor/ring
# Check configuration
kubectl exec -it <mimir-pod> -n monitoring -- cat /etc/mimir/mimir.yaml
# Validate configuration before deployment
mimir -modules -config.file <path-to-config-file>
監視する主要なメトリクス
# Ingestion rate per tenant
sum by (user) (rate(cortex_distributor_received_samples_total[5m]))
# Series count per tenant
sum by (user) (cortex_ingester_memory_series)
# Query latency
histogram_quantile(0.99, sum by (le) (rate(cortex_request_duration_seconds_bucket{route=~"/api/prom/api/v1/query.*"}[5m])))
# Compactor status
cortex_compactor_runs_completed_total
cortex_compactor_runs_failed_total
# Store-gateway block sync
cortex_bucket_store_blocks_loaded
サーキットブレーカー(Ingester)
mimir:
structuredConfig:
ingester:
push_circuit_breaker:
enabled: true
request_timeout: 2s
failure_threshold_percentage: 10
cooldown_period: 10s
read_circuit_breaker:
enabled: true
request_timeout: 30s
状態:
- Closed - 通常の動作
- Open - 障害が発生しているインスタンスへの転送を停止
- Half-open - クールダウン後に、試験的なリクエストを限定的に送信
外部リソース
注意事項
- X-Scope-OrgID によるマルチテナンシー:ヘッダーがない場合、テナント「fake」に警告なく書き込まれます。Loki と同じ落とし穴です。
- 保持期間はテナントごとに設定されます。グローバルな保持期間の環境変数はフォールバックにすぎず、テナントの設定ミスがあっても警告なく優先されます。
- Ingester のレプリケーション係数が 3 未満の場合、1 件の障害でデータが失われます。一部の Helm チャートではデフォルトが 1 です。そのまま本番環境に導入しないでください。
- クエリフロントエンドのキャッシュ TTL を変更すると、キャッシュ済みの結果がすべて無効になります。
query_range_results_cache_ttlを変更しても、既存のエントリーの有効期間は延長されません。 - マルチテナントのストレージパスは、S3 バケットのプレフィックスを共有します。tenant-1 が tenant-2 のパスを読み取れるように誤って許可するのは設定ミスですが、チャートでは防止されません。
distributor.ingestion-rate-limit-strategy: globalには、正常に動作する memberlist が必要です。警告なく発生する障害モードでは、調整が行われず、ディストリビューターごとの制限が適用されるため、意図したトラフィックの 10 倍まで許可されます。
コメント
Markdown 対応