Kibana
Elasticsearchと連携するオープンソースデータ可視化・探索ツール。豊富な可視化オプション、機械学習による異常検知、地理空間マッピング機能を提供。
監視サーバー
Kibana
概要
KibanaはElasticsearchと連携するオープンソースデータ可視化・探索ツールです。豊富な可視化オプション、機械学習による異常検知、地理空間マッピング機能を提供し、ELKスタック(Elasticsearch、Logstash、Kibana)の可視化コンポーネントとして高い採用率を誇ります。リアルタイムデータ分析とインタラクティブなダッシュボード作成により、企業のデータドリブン意思決定を支援します。
詳細
Kibanaは2013年にElastic社によって開発が開始され、現在ではELKスタックの可視化コンポーネントとして高い採用率を維持しています。機械学習統合、高度な分析機能、リアルタイム可視化により、エンタープライズ市場で継続的な成長を遂げており、バージョン8.x系列では更なる機能強化が図られています。
主要な技術的特徴
- リッチな可視化: 多様なチャートタイプとカスタマイズ可能なダッシュボード
- 機械学習統合: AI支援による異常検知とデータ分析
- 地理空間分析: 位置情報データの高度な可視化機能
- リアルタイム監視: ライブデータストリームの即座な可視化
- カスタムプラグイン: 拡張可能なアーキテクチャ
用途
- ログ分析とトラブルシューティング
- ビジネスメトリクス監視
- セキュリティ情報・イベント管理(SIEM)
- IoTデータ可視化
- E-commerce分析
メリット・デメリット
メリット
- 豊富な可視化: 多様なチャートとグラフィック表現
- Elasticsearch連携: シームレスなデータ統合
- 機械学習機能: 自動化された異常検知
- ユーザーフレンドリー: 直感的なインターフェース
- スケーラビリティ: 大規模データセットの処理能力
- オープンソース: 無料で高機能な可視化ツール
デメリット
- Elastic依存: ElasticsearchとのペアリングがCRITICAL
- リソース消費: 大量データ処理時の高いメモリ使用量
- 学習コスト: 高度な機能の習得に時間が必要
- ライセンス複雑性: 複数ライセンス体系の理解が必要
- パフォーマンス: 複雑なクエリでのレスポンス遅延
参考ページ
書き方の例
基本的なKibana設定
# kibana.yml
server.port: 5601
server.host: "0.0.0.0"
server.name: "kibana-server"
server.publicBaseUrl: "http://localhost:5601"
# Elasticsearch設定
elasticsearch.hosts: ["http://elasticsearch:9200"]
elasticsearch.username: "kibana_system"
elasticsearch.password: "your_password"
# セキュリティ設定
xpack.security.enabled: true
xpack.security.encryptionKey: "your_encryption_key_here"
xpack.security.session.idleTimeout: "1h"
# 監視設定
monitoring.ui.enabled: true
monitoring.kibana.collection.enabled: true
# 機械学習設定
xpack.ml.enabled: true
# 地理空間設定
map.includeElasticMapsService: true
map.tilemap.url: "https://tiles.example.com/{z}/{x}/{y}.png"
# アラート設定
xpack.actions.enabled: true
xpack.alerts.enabled: true
# 可視化設定
vis_type_vega.enabled: true
newsfeed.enabled: false
# パフォーマンス設定
server.maxPayloadBytes: 1048576
elasticsearch.requestTimeout: 30000
elasticsearch.pingTimeout: 3000
ダッシュボード作成の例
// Kibana Saved Object (ダッシュボード設定)
{
"version": "8.x.x",
"objects": [
{
"id": "web-analytics-dashboard",
"type": "dashboard",
"attributes": {
"title": "Web Analytics Dashboard",
"description": "Website traffic and performance metrics",
"panelsJSON": "[{\"version\":\"8.x.x\",\"gridData\":{\"x\":0,\"y\":0,\"w\":24,\"h\":15,\"i\":\"1\"},\"panelIndex\":\"1\",\"embeddableConfig\":{},\"panelRefName\":\"panel_1\"}]",
"timeRestore": true,
"timeTo": "now",
"timeFrom": "now-24h",
"refreshInterval": {
"pause": false,
"value": 30000
},
"kibanaSavedObjectMeta": {
"searchSourceJSON": "{\"query\":{\"match_all\":{}},\"filter\":[]}"
}
},
"references": [
{
"name": "panel_1",
"type": "visualization",
"id": "page-views-visualization"
}
]
}
]
}
可視化設定の例
{
"id": "page-views-visualization",
"type": "visualization",
"attributes": {
"title": "Page Views Over Time",
"visState": "{\"title\":\"Page Views Over Time\",\"type\":\"line\",\"params\":{\"grid\":{\"categoryLines\":false,\"valueAxis\":\"ValueAxis-1\"},\"categoryAxe\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":true,\"type\":\"line\",\"mode\":\"normal\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"showCircles\":true}]},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"auto\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}}]}",
"uiStateJSON": "{}",
"description": "",
"version": 1,
"kibanaSavedObjectMeta": {
"searchSourceJSON": "{\"index\":\"web-logs-*\",\"query\":{\"match_all\":{}},\"filter\":[]}"
}
}
}
Index Pattern設定
{
"id": "web-logs-*",
"type": "index-pattern",
"attributes": {
"title": "web-logs-*",
"timeFieldName": "@timestamp",
"fields": "[{\"name\":\"@timestamp\",\"type\":\"date\",\"searchable\":true,\"aggregatable\":true},{\"name\":\"ip\",\"type\":\"ip\",\"searchable\":true,\"aggregatable\":true},{\"name\":\"method\",\"type\":\"string\",\"searchable\":true,\"aggregatable\":true},{\"name\":\"url\",\"type\":\"string\",\"searchable\":true,\"aggregatable\":false},{\"name\":\"status\",\"type\":\"number\",\"searchable\":true,\"aggregatable\":true},{\"name\":\"response_time\",\"type\":\"number\",\"searchable\":true,\"aggregatable\":true},{\"name\":\"user_agent\",\"type\":\"string\",\"searchable\":true,\"aggregatable\":false}]",
"fieldFormatMap": "{\"response_time\":{\"id\":\"duration\",\"params\":{\"inputFormat\":\"milliseconds\",\"outputFormat\":\"humanizePrecise\"}}}",
"sourceFilters": "[{\"value\":\"user_agent\"}]"
}
}
Watcher設定(アラート)
{
"trigger": {
"schedule": {
"interval": "5m"
}
},
"input": {
"search": {
"request": {
"search_type": "query_then_fetch",
"indices": ["web-logs-*"],
"body": {
"query": {
"bool": {
"filter": [
{
"range": {
"@timestamp": {
"gte": "now-5m"
}
}
},
{
"range": {
"status": {
"gte": 500
}
}
}
]
}
}
}
}
}
},
"condition": {
"compare": {
"ctx.payload.hits.total": {
"gt": 10
}
}
},
"actions": {
"send_email": {
"email": {
"to": ["[email protected]"],
"subject": "High Error Rate Alert",
"body": "Error rate is above threshold. {{ctx.payload.hits.total}} errors in the last 5 minutes."
}
}
}
}
Docker Compose設定
version: '3.8'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.15.0
container_name: elasticsearch
environment:
- discovery.type=single-node
- xpack.security.enabled=false
- "ES_JAVA_OPTS=-Xms1g -Xmx1g"
ports:
- "9200:9200"
volumes:
- elasticsearch_data:/usr/share/elasticsearch/data
networks:
- elastic
kibana:
image: docker.elastic.co/kibana/kibana:8.15.0
container_name: kibana
environment:
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
- xpack.security.enabled=false
- xpack.monitoring.ui.enabled=true
ports:
- "5601:5601"
depends_on:
- elasticsearch
networks:
- elastic
volumes:
- ./kibana.yml:/usr/share/kibana/config/kibana.yml
logstash:
image: docker.elastic.co/logstash/logstash:8.15.0
container_name: logstash
volumes:
- ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
ports:
- "5044:5044"
- "9600:9600"
environment:
- "LS_JAVA_OPTS=-Xmx256m -Xms256m"
depends_on:
- elasticsearch
networks:
- elastic
volumes:
elasticsearch_data:
driver: local
networks:
elastic:
driver: bridge
カスタムVisualizationプラグイン
// Custom visualization plugin example
import { PluginInitializerContext } from '../../../core/public';
import { KibanaVisualizationPlugin } from './plugin';
export function plugin(initializerContext: PluginInitializerContext) {
return new KibanaVisualizationPlugin(initializerContext);
}
export class KibanaVisualizationPlugin {
constructor(initializerContext) {
this.initializerContext = initializerContext;
}
public setup(core, { visualizations, expressions, data }) {
// カスタム可視化の登録
visualizations.createBaseVisualization({
name: 'custom_heatmap',
title: 'Custom Heatmap',
icon: 'heatmap',
description: 'Custom heatmap visualization',
visConfig: {
defaults: {
colorSchema: 'Blues',
invertColors: false,
percentageMode: false
}
},
editorConfig: {
optionsTemplate: '<custom-heatmap-options></custom-heatmap-options>'
},
requestHandler: 'courier',
responseHandler: 'none',
visualization: CustomHeatmapVisualization
});
return {};
}
public start(core) {
return {};
}
public stop() {}
}
class CustomHeatmapVisualization {
constructor(element, vis) {
this.element = element;
this.vis = vis;
}
async render(visData, status) {
// カスタム可視化のレンダリングロジック
const container = d3.select(this.element);
// データ処理
const data = this.processData(visData);
// ヒートマップ描画
this.drawHeatmap(container, data);
}
processData(visData) {
// Elasticsearchからのデータを処理
return visData.tables[0].rows.map(row => ({
x: row[0],
y: row[1],
value: row[2]
}));
}
drawHeatmap(container, data) {
// D3.jsを使用したヒートマップ描画
const margin = { top: 50, right: 50, bottom: 50, left: 50 };
const width = 800 - margin.left - margin.right;
const height = 600 - margin.top - margin.bottom;
const svg = container.append('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom);
const g = svg.append('g')
.attr('transform', `translate(${margin.left},${margin.top})`);
// ヒートマップのセル描画
const colorScale = d3.scaleSequential(d3.interpolateBlues)
.domain(d3.extent(data, d => d.value));
g.selectAll('.cell')
.data(data)
.enter().append('rect')
.attr('class', 'cell')
.attr('x', d => d.x * 20)
.attr('y', d => d.y * 20)
.attr('width', 20)
.attr('height', 20)
.attr('fill', d => colorScale(d.value));
}
destroy() {
// クリーンアップ処理
}
}