Kubernetes 可観測性
ログ、メトリクス、トレースを使用したKubernetesアプリケーションの監視と可観測性を学びます。
目次
可観測性の3本柱
┌─────────────────────────────────────────────────────────────┐
│ 可観測性の3本柱 │
├─────────────────────────────────────────────────────────────┤
│ │
│ Logs(ログ) │
│ └── 何が起きたか │
│ └── イベント、エラー、デバッグ情報 │
│ └── ツール: Fluentd, Loki, CloudWatch Logs │
│ │
│ Metrics(メトリクス) │
│ └── どれくらいか │
│ └── CPU、メモリ、リクエスト数、レイテンシ │
│ └── ツール: Prometheus, Grafana, CloudWatch │
│ │
│ Traces(トレース) │
│ └── どこで起きたか │
│ └── リクエストの流れ、サービス間の依存関係 │
│ └── ツール: Jaeger, Zipkin, X-Ray │
│ │
└────────────────────────────────────────────── ───────────────┘
ログ管理
kubectlでのログ確認
# Podのログ
kubectl logs pod-name
# 特定コンテナのログ
kubectl logs pod-name -c container-name
# リアルタイムフォロー
kubectl logs -f pod-name
# 過去N行
kubectl logs --tail=100 pod-name
# 時間範囲
kubectl logs --since=1h pod-name
kubectl logs --since-time=2024-01-01T00:00:00Z pod-name
# 前のコンテナのログ(再起動後)
kubectl logs pod-name --previous
# ラベルセレクターで複数Pod
kubectl logs -l app=idp-server --all-containers
Fluentd/Fluent Bit
# Fluent Bit DaemonSet
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: fluent-bit
namespace: logging
spec:
selector:
matchLabels:
app: fluent-bit
template:
metadata:
labels:
app: fluent-bit
spec:
serviceAccountName: fluent-bit
containers:
- name: fluent-bit
image: fluent/fluent-bit:2.2
resources:
limits:
memory: 200Mi
requests:
cpu: 100m
memory: 100Mi
volumeMounts:
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
- name: config
mountPath: /fluent-bit/etc/
volumes:
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
- name: config
configMap:
name: fluent-bit-config
---
apiVersion: v1
kind: ConfigMap
metadata:
name: fluent-bit-config
namespace: logging
data:
fluent-bit.conf: |
[SERVICE]
Flush 1
Log_Level info
Daemon off
Parsers_File parsers.conf
[INPUT]
Name tail
Tag kube.*
Path /var/log/containers/*.log
Parser docker
DB /var/log/flb_kube.db
Mem_Buf_Limit 5MB
Skip_Long_Lines On
Refresh_Interval 10
[FILTER]
Name kubernetes
Match kube.*
Kube_URL https://kubernetes.default.svc:443
Kube_CA_File /var/run/secrets/kubernetes.io/serviceaccount/ca.crt
Kube_Token_File /var/run/secrets/kubernetes.io/serviceaccount/token
Merge_Log On
K8S-Logging.Parser On
K8S-Logging.Exclude On
[OUTPUT]
Name es
Match *
Host elasticsearch
Port 9200
Index kubernetes
Type _doc
parsers.conf: |
[PARSER]
Name docker
Format json
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%L
構造化ログの推奨
// アプリケーションログ(JSON形式)
{
"timestamp": "2024-01-15T10:30:00.123Z",
"level": "INFO",
"service": "idp-server",
"traceId": "abc123",
"spanId": "def456",
"message": "Token issued",
"clientId": "my-app",
"userId": "user123",
"responseTime": 45
}
メトリクス
Metrics Server
# Metrics Serverのインストール
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
# リソース使用状況の確認
kubectl top nodes
kubectl top pods
kubectl top pods -l app=idp-server --containers
Prometheus Stack
# Prometheus Operator(helm)
# helm install prometheus prometheus-community/kube-prometheus-stack
# ServiceMonitor
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: idp-server
namespace: monitoring
labels:
release: prometheus
spec:
selector:
matchLabels:
app: idp-server
namespaceSelector:
matchNames:
- production
endpoints:
- port: management
path: /actuator/prometheus
interval: 30s
アプリケーションメトリクス
# Spring Boot Actuatorの設定
# application.yml
management:
endpoints:
web:
exposure:
include: health,info,metrics,prometheus
metrics:
tags:
application: idp-server
export:
prometheus:
enabled: true
Grafanaダッシュボード
┌───────────────────────────────────────────────── ────────────┐
│ IDサービス ダッシュボード │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Request Rate │ │ Error Rate │ │
│ │ 1,234 req/s │ │ 0.5% │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ P95 Latency │ │ Pod Count │ │
│ │ 45ms │ │ 5/10 │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Token発行数 (時系列) │ │
│ │ ▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ │ │
│ │ ████████████████████████████████████████ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
重要なメトリクス
| カテゴリ | メトリクス | 説明 |
|---|---|---|
| RED | Request Rate | リクエスト数/秒 |
| RED | Error Rate | エラー率 |
| RED | Duration | レスポンスタイム |
| USE | Utilization | CPU/メモリ使用率 |
| USE | Saturation | キュー長 |
| USE | Errors | システムエラー |
分散トレーシング
OpenTelemetry
# OpenTelemetry Collector
apiVersion: opentelemetry.io/v1alpha1
kind: OpenTelemetryCollector
metadata:
name: otel-collector
spec:
mode: deployment
config: |
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
batch:
timeout: 1s
send_batch_size: 1024
exporters:
jaeger:
endpoint: jaeger-collector:14250
tls:
insecure: true
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [jaeger]
Spring Bootでの設定
# application.yml
spring:
application:
name: idp-server
management:
tracing:
sampling:
probability: 1.0 # 100%サンプリング(本番では調整)
# 依存関係(build.gradle)
# implementation 'io.micrometer:micrometer-tracing-bridge-otel'
# implementation 'io.opentelemetry:opentelemetry-exporter-otlp'
トレースの可視化
┌─────────────────────────────────────────────────────────────┐
│ リクエストトレース │
├─────────────────────────────────────────────────────────────┤
│ │
│ [Gateway] │
│ ├─ 5ms HTTP GET /authorize │
│ │ │
│ [idp-server] │
│ ├─ 2ms Validate client │
│ ├─ 3ms Check session │
│ │ └─ [Redis] 1ms GET session:abc123 │
│ ├─ 5ms Authenticate user │
│ │ └─ [PostgreSQL] 3ms SELECT user │
│ ├─ 2ms Generate tokens │
│ └─ 1ms Store authorization │
│ └─ [PostgreSQL] 1ms INSERT authorization │
│ │
│ Total: 18ms │
│ │
└─────────────────────────────────────────────────────────────┘