Đa số team mới setup ELK đều rơi vào một trong hai cực: hoặc dựng 3 cluster Kibana riêng cho dev, staging, prod (đắt và lệch version), hoặc nhét tất cả dashboard vào space default rồi cuộn tay đi tìm (rối). Spaces là điểm cân bằng. Một cluster, nhiều “namespace” UI, mỗi namespace có saved object riêng, RBAC riêng, feature toggle riêng.
Đây là bài 13 trong series Kibana từ A đến Z. Bài này bạn sẽ làm được:
- Hiểu space khác gì index, khác gì cluster
- Tạo space dev, staging, prod và copy dashboard giữa các space
- Hạn chế feature (ẩn Dev Tools ở prod) để giảm bán kính rủi ro
- Gán role chỉ truy cập 1 space, kết hợp với RBAC bài 12
- Tránh pitfall data view shared và pitfall search nhầm space
Phần 1: Space là gì, không là gì
Tóm tắt nhanh:
| Tầng | Vai trò |
|---|---|
| Cluster | Process Elasticsearch và Kibana. Cấp hạ tầng. |
| Space | Namespace UI trong Kibana. Saved object có scope theo space. |
| Index | Data trong ES. KHÔNG bị space cô lập. |
Quan trọng: space không cô lập data. Nếu user có quyền read trên app-logs-*, dù ở space nào cũng đọc được index đó. Space chỉ cô lập Kibana saved object: dashboard, visualization, data view, lens, map, machine learning job (tính theo cấu hình).
Khi cần cô lập data thì dùng DLS (bài 14) hoặc tách index. Đừng kỳ vọng space tự giấu data.
Sơ đồ:
+----------------------- Cluster --------------------+
| |
| Index: app-logs-*, nginx-*, audit-* (chung) |
| |
| +---- Kibana ----+ |
| | +-- Space 'default' -- dashboards, dataviews |
| | +-- Space 'dev' -- dashboards (dev only) |
| | +-- Space 'prod' -- dashboards (prod only) |
| | +-- Space 'security' -- audit dashboard |
| +----------------+ |
+-----------------------------------------------------+
Phần 2: Tạo space đầu tiên
Vào Stack Management plus Spaces plus Create space.
Các field cần điền:
- Name: hiển thị trên UI. Ví dụ
dev,staging,prod. - URL identifier: phần xuất hiện trong URL, ví dụ
kibana.example.com/s/dev/app/discover. Mặc định Kibana sinh từ name, có thể override. - Avatar: chữ và màu. Đặt khác biệt rõ ràng để dev không bấm nhầm.
- Feature visibility: tick các feature bật trong space. Tắt feature ở đây chỉ ẩn UI, không phải gỡ quyền (vẫn cần role).
- Solution view: Classic, Observability, Security, hay Search. Để Classic cho space dev/prod multi-purpose.
Một pattern an toàn cho prod space: tắt Dev Tools, Console, Advanced Settings. User không vô tình chạy DELETE /app-logs-*.
Tạo qua API:
curl -s -u "$KB_USER:$KB_PASS" \
-H "kbn-xsrf: true" \
-H "Content-Type: application/json" \
-X POST "$KB_URL/api/spaces/space" \
-d '{
"id": "prod",
"name": "Production",
"description": "Production dashboards. Read-only for non-platform.",
"color": "#D94040",
"initials": "PR",
"disabledFeatures": ["dev_tools", "advancedSettings"]
}'
List feature id để biết tắt được cái gì:
curl -s -u "$KB_USER:$KB_PASS" \
"$KB_URL/api/features"
Phần 3: URL routing và default space
Mặc định Kibana redirect login về space cuối user vừa vào. Có 3 cách chuyển space:
- Click avatar góc trên trái plus Change current space.
- Sửa URL:
/s/<space-id>/app/.... Không có prefix/s/<id>/nghĩa là spacedefault. - Set default space qua user profile: Stack Management plus Users plus click user plus Default space.
Nếu user chỉ có quyền 1 space, Kibana auto redirect vào space đó sau login. Đây là pattern để tạo “Kibana riêng cho từng team”: tạo space team-payments, tạo role chỉ có quyền team-payments, login auto vào đó, không thấy space khác.
Phần 4: Copy saved object giữa các space
Use case kinh điển: build dashboard ở dev, test xong copy sang prod.
GUI
- Vào space nguồn (
dev). - Stack Management plus Saved objects.
- Tick object cần copy (dashboard + dependencies).
- Click Copy to space.
- Chọn space đích, tick Include related objects, chọn:
- Create new objects with random IDs: tách bạch, không đè cái cũ
- Check for existing objects: cập nhật bản hiện có
- Copy.
API
curl -s -u "$KB_USER:$KB_PASS" \
-H "kbn-xsrf: true" \
-H "Content-Type: application/json" \
-X POST "$KB_URL/s/dev/api/spaces/_copy_saved_objects" \
-d '{
"spaces": ["prod"],
"objects": [
{ "type": "dashboard", "id": "<DASHBOARD_ID>" }
],
"includeReferences": true,
"createNewCopies": false,
"overwrite": true
}'
Lưu ý: URL có prefix /s/dev/ để chỉ rõ space nguồn. Endpoint là API của space dev, trong body chỉ định space đích.
Resolve conflict
Nếu cùng ID nhưng nội dung khác, response 200 nhưng có field successResults[].destinationId mới, và errors[] cho object conflict. Có 2 chiến lược:
overwrite: true: ghi đè bản đích bằng nguồn.createNewCopies: true: sinh ID mới, dashboard ở đích vẫn còn cùng tên nhưng ID khác. Dùng khi muốn tách bạch.
Trong workflow dashboard-as-code (bài 22), pattern phổ biến: source of truth là NDJSON trong git, copy giữa space chỉ làm trong giai đoạn promotion thủ công.
Phần 5: Data view dùng chung hay riêng
Mặc định data view tạo trong 1 space chỉ thấy ở space đó. Nhưng Kibana có khái niệm shared data view: data view có namespaces: ["*"] thấy ở mọi space.
Cách tạo shared data view:
- Tạo data view ở space
default. - Stack Management plus Data Views plus click data view.
- Phần Spaces, chọn All spaces.
Hoặc API:
curl -s -u "$KB_USER:$KB_PASS" \
-H "kbn-xsrf: true" \
-H "Content-Type: application/json" \
-X POST "$KB_URL/api/spaces/_update_objects_spaces" \
-d '{
"objects": [
{ "type": "index-pattern", "id": "<DV_ID>" }
],
"spacesToAdd": ["*"]
}'
Khi nào shared, khi nào tách:
- Shared khi data view trỏ vào index pattern toàn cluster (
app-logs-*) và mọi team cần truy cập như nhau. - Tách khi mỗi space có data view riêng với
runtimeFieldMapkhác nhau, hoặc team không nên thấy field cluster level.
Pitfall: bật shared cho data view có runtime field nặng. Một lần ở dự án trước, runtime field painless để tính request_duration_p99 chạy được trong space dev (vài trăm doc), bật shared sang space prod (vài triệu doc) thì Discover treo 30s mỗi query. Fix: tạo bản copy data view ở space prod, gỡ runtime field, dùng index field thay thế.
Phần 6: RBAC theo space
Bài 12 đã giới thiệu Kibana feature privileges có scope theo space. Mẫu role cho dev team chỉ vào space dev:
curl -s -u "$ES_USER:$ES_PASS" \
-H "Content-Type: application/json" \
-X PUT "$ES_URL/_security/role/dev_space_user" \
-d '{
"cluster": [],
"indices": [
{
"names": ["dev-logs-*"],
"privileges": ["read", "view_index_metadata"]
}
],
"applications": [
{
"application": "kibana-.kibana",
"privileges": ["feature_discover.all", "feature_dashboard.all", "feature_visualize.all"],
"resources": ["space:dev"]
}
]
}'
Có thể gắn nhiều applications entry để cấp quyền khác nhau cho từng space. Ví dụ cùng 1 role: feature_discover.all ở space dev, feature_discover.read ở space prod.
"applications": [
{
"application": "kibana-.kibana",
"privileges": ["feature_discover.all"],
"resources": ["space:dev"]
},
{
"application": "kibana-.kibana",
"privileges": ["feature_discover.read"],
"resources": ["space:prod"]
}
]
Phần 7: Pattern thiết kế space cho team
Pattern 1: theo môi trường
- default (admin)
- dev
- staging
- prod
Mỗi space có data view trỏ vào pattern index riêng (dev-app-logs-*, staging-app-logs-*, prod-app-logs-*).
Phù hợp: 1 product, nhiều env.
Pattern 2: theo team
- default (platform)
- team-payments
- team-onboarding
- team-search
Mỗi team có space riêng, data view chỉ trỏ vào index của họ. RBAC khoá user team-payments chỉ thấy space của mình.
Phù hợp: monorepo / nhiều team chia sản phẩm.
Pattern 3: lai
- default (platform)
- team-payments-dev
- team-payments-prod
- team-onboarding-dev
- team-onboarding-prod
Trade-off: số space nhân lên nhanh. Kibana hỗ trợ unlimited space nhưng quản lý saved object cross-space sẽ vất hơn. Cân nhắc dùng tag thay vì nhân space khi số space quá nhiều.
Pattern 4: chỉ 1 space (default)
Hợp lệ với team nhỏ (under 10 dev), 1 sản phẩm. Đừng over-engineer. Khi nào dashboard quá nhiều hoặc team đông lên hãy chia.
Phần 8: Pitfall hay gặp
Pitfall 1: alert rule không tự theo space
Alert rule có scope theo space, nhưng connector (Slack, Email) là cluster level. Khi copy dashboard từ space dev sang prod, alert rule liên kết KHÔNG được copy tự động. Phải tạo lại rule ở space prod.
Pitfall 2: search nhầm space
User có quyền trên cả dev và prod. Tạo dashboard ở dev, gửi URL chia sẻ kèm prefix /s/dev/.... Đồng nghiệp click vào, làm việc một lúc rồi nhầm tưởng đang ở prod. Fix: avatar màu sắc khác biệt rõ rệt, prepend tên môi trường vào title dashboard ([DEV] Error overview).
Pitfall 3: tag không có scope theo space đúng cách
Tag là cross-space resource. Tag compliance ở space default không tự nhân ra space khác. Khi copy dashboard có gắn tag, cần copy cả tag (tag cũng là saved object). Nhớ tick Include related objects khi copy.
Pitfall 4: feature visibility nhầm với role
Tắt Dev Tools trong space settings KHÔNG đồng nghĩa với gỡ quyền. User có role feature_dev_tools.all vẫn vào được Dev Tools qua URL trực tiếp /s/<space>/app/dev_tools mặc dù menu bị ẩn. Muốn thực sự khoá thì phải gỡ feature privilege khỏi role.
Phần 9: Audit space (cleanup định kỳ)
Mỗi quý chạy script kiểm tra space “ma”:
curl -s -u "$KB_USER:$KB_PASS" \
"$KB_URL/api/spaces/space" | jq '.[] | {id, name, disabledFeatures}'
Cho từng space, đếm saved object:
for sid in dev staging prod; do
count=$(curl -s -u "$KB_USER:$KB_PASS" \
"$KB_URL/s/$sid/api/saved_objects/_find?type=dashboard&per_page=1" \
| jq '.total')
echo "$sid: $count dashboards"
done
Space có dưới 3 dashboard và không có user gắn role là ứng viên xoá. Xoá space cũng xoá toàn bộ saved object scope theo space đó. Confirm với team trước khi xoá.
Cheatsheet
| Việc | Cách |
|---|---|
| Tạo space | POST /api/spaces/space hoặc Stack Management plus Spaces |
| Tắt feature space | field disabledFeatures lúc tạo space |
| Copy saved object | POST /s/<src>/api/spaces/_copy_saved_objects |
| Share data view nhiều space | POST /api/spaces/_update_objects_spaces với spacesToAdd: ["*"] |
| RBAC scope space | resources: ["space:<id>"] trong role |
| Switch space qua URL | /s/<id>/app/<app> |
| Default space cho user | Stack Management plus Users plus Default space |
| Audit dashboard mỗi space | /s/<id>/api/saved_objects/_find?type=dashboard |
Lời kết
Spaces là tầng cô lập rẻ và linh hoạt. Đừng vội dựng 3 cluster Kibana khi 3 space đã đủ. Tận dụng feature visibility plus RBAC theo space để giảm bán kính rủi ro ở prod, và copy saved object có kiểm soát để dashboard không loạn.
Bài 14 sẽ quay lại security ở tầng data: API keys nâng cao với Document-Level Security và Field-Level Security. Bạn sẽ thấy một key có thể chỉ đọc document có tenant id cụ thể, hoặc che hết field PII trước khi trả về user, giúp đáp ứng SOC2 và GDPR.