Hướng dẫn triển khai lên môi trường thực tế
Tài liệu này dẫn từng bước dựng hệ thống giám sát (Access Hub, Collector, Agent) trên máy thật. Mọi khóa cấu hình, cổng, cờ và mã thoát dưới đây lấy từ mã hiện tại (internal/config, cmd/collector, deploy/systemd, deploy/dev). Kiến trúc và lý do thiết kế xem 01 và 09.
Trước khi bắt đầu
appendonly yes và maxmemory-policy noevictionvm-raw và vm-long, cùng vmalert cho rollupMonitoring Collector trong Access Hub (secrets/hub.token)secrets/admin.token)make build)0. Đọc trước: điều gì đã sẵn sàng, điều gì chưa
| Thành phần | Trạng thái | Hệ quả khi triển khai |
|---|---|---|
Agent Linux (.deb, .rpm, install.sh, tar) | Mã và gói xong, kiểm thử cục bộ. Chưa thử trên ma trận distro thật, chưa ký | Thử trên 1 máy mỗi distro trước khi cài hàng loạt. Gói chưa có chữ ký, install.sh đòi khóa công khai hoặc --allow-unsigned (mục 9.4) |
| Agent Windows (MSI, Authenticode) | Chưa làm (AGT-7, giai đoạn 2) | Chưa cài được Windows agent |
| Collector (ingest, worker, admin) | COL-1 đến 7 xong, đã kiểm thử với Redis và VictoriaMetrics thật | Chưa có image Docker, chưa có gói .deb. Triển khai bằng binary tĩnh và systemd (mục 6) |
Collector: luật ngưỡng (COL-8), reload, renew | Luật ngưỡng và POST /internal/v1/reload/rules xong. Chống nhiễu (COL-9: silence, flapping, group_down, reload/silences, reload/settings) xong, cần HUB-13 phía Access Hub. Renew token trả 503 | Cấu hình đổi bằng cách sửa tệp rồi khởi động lại cuốn chiếu |
| Access Hub phía monitoring (HUB-1 đến 18) | Chưa xây | Chưa có API /api/v1/monitoring/collector/*, chưa có trang Agents, chưa có bộ tạo License. Xem mục 8 |
| Bus NATS JetStream | Chưa làm | Bus giữa ingest và worker là Redis Streams |
Hệ quả quan trọng: vì Access Hub chưa có phần monitoring, hiện chưa thể chạy đầu-cuối thật (enroll agent, đồng bộ registry, nhận alert). Có thể dựng sẵn toàn bộ hạ tầng (Redis, VictoriaMetrics, Collector, LB) và kiểm tra bằng mockhub như môi trường dev, sau đó chờ HUB-* để nối vào Access Hub thật. Đừng đưa mockhub vào production.
1. Sơ đồ triển khai mẫu (production nhỏ)
flowchart LR
AG[Agent nhieu may] -->|HTTPS 443| LB[LB TLS agents.example.com]
LB --> I1[collector ingest 1]
LB --> I2[collector ingest 2]
I1 --> R[(Redis master va replica)]
I2 --> R
R --> W1[collector worker 1]
R --> W2[collector worker 2]
W1 --> VR[(vm-raw 30 ngay)]
W2 --> VR
VA[vmalert] --> VR
VA --> VL[(vm-long 400 ngay)]
W1 -->|HTTPS| HUB[Access Hub]
W2 -->|HTTPS| HUB
HUB -->|HTTPS noi bo, admin token| AD[collector admin]
AD --> R
AD --> VR
AD --> VLVai trò tiến trình collector: ingest (nhận dữ liệu agent, đẩy vào bus), worker (đọc bus, ghi VictoriaMetrics, phát hiện agent mất kết nối, gửi sự kiện cho Access Hub), admin (API nội bộ cho Access Hub). Mỗi tiến trình một collector_id riêng. Có thể gộp (roles: [all]) cho hệ thống rất nhỏ, nhưng khi tách vai trò thì bắt buộc có Redis (registry, presence, bus, outbox dùng chung).
2. Kích thước tài nguyên
Con số khởi điểm, hiệu chỉnh sau khi đo tải thật (xem 08).
| Quy mô | Số máy giám sát | Node collector | Redis | VictoriaMetrics |
|---|---|---|---|---|
| Nhỏ | đến 1.000 | 2 ingest + 2 worker + 1 admin, mỗi tiến trình 0,5 đến 1 vCPU, 512 MB | 1 master + 1 replica, 2 vCPU, 4 GB, đĩa SSD | 1 máy cho vm-raw và vm-long: 4 vCPU, 16 GB, SSD 200 GB |
| Vừa | đến 10.000 | ingest x 3 đến 4, worker x 4, admin x 2 | Sentinel 3 node, 8 GB | vm-raw và vm-long tách máy, SSD 1 TB |
| Lớn | trên 10.000 | Theo 08 | Sentinel hoặc Cluster | Cụm VictoriaMetrics hoặc nhiều instance |
Quy đổi tham khảo: agent đẩy khoảng 4 lần mỗi phút (mỗi 30 giây mỗi lô, giới hạn mặc định metrics_per_minute: 4, metrics_burst: 10). Mỗi agent tối đa 500 series (ingest.limits.max_series).
Hệ điều hành khuyến nghị: Ubuntu 22.04 hoặc 24.04 LTS, hoặc Rocky, Alma 9. Đồng bộ thời gian bắt buộc (chrony hoặc systemd-timesyncd): collector từ chối mẫu cũ hơn 24 giờ hoặc vượt tương lai 5 phút (max_point_age, max_point_future), lệch đồng hồ làm mất dữ liệu.
3. Mạng, tên miền, tường lửa
- Tên miền công khai riêng cho agent, ví dụ
agents.example.com(không dùng chung tên miền giao diện Access Hub). Cấp chứng chỉ TLS từ CA công khai (Let's Encrypt hoặc CA doanh nghiệp mà mọi máy agent tin cậy). Nếu dùng CA nội bộ, đặtca_filetrongagent.yaml(gói cài đã có khóa này). - Tên nội bộ cho API admin và cho Redis, VictoriaMetrics.
- Tường lửa (mặc định chặn, chỉ mở các luồng sau):
| Từ | Đến | Cổng | Mục đích |
|---|---|---|---|
| Internet (các máy agent) | LB | 443/tcp | Agent đẩy dữ liệu (/agent/v1/*) |
| LB | collector ingest | 8443/tcp (hoặc cổng riêng mỗi node) | Chuyển tiếp |
| LB | collector ops của ingest | 9100/tcp | Kiểm tra sức khỏe chủ động /readyz |
| collector (mọi role) | Redis | 6379/tcp | Registry, bus, outbox |
| worker, admin | vm-raw 8428, vm-long 8429 | tcp | Ghi, đọc, xóa |
| vmalert | vm-raw, vm-long | tcp | Rollup |
| worker, ingest, admin | Access Hub | 443/tcp | Sự kiện, đồng bộ registry, tra cứu |
| Access Hub | collector admin | 9101/tcp | API nội bộ, qua TLS hoặc mạng riêng |
| Prometheus của bạn (tùy chọn) | collector ops | 9100/tcp | Thu /metrics của collector |
Không bao giờ mở Redis, VictoriaMetrics, admin (9101), ops (9100) ra Internet. VictoriaMetrics bản OSS không có xác thực, phải đặt sau mạng riêng hoặc thêm proxy xác thực.
4. Redis (hoặc Valkey)
Dùng một instance riêng cho collector, không dùng chung Redis của Access Hub (registry, bus và outbox cần noeviction, còn cache của Access Hub thường cho phép loại bỏ).
Mẫu /etc/redis/redis-accesshub.conf (đối chiếu deploy/dev/redis/master.conf.tmpl):
bind 10.0.0.10 # IP nội bộ, không 0.0.0.0
port 6379
protected-mode yes
dir /var/lib/redis-accesshub
save 900 1
save 300 100
save 60 10000
appendonly yes
appendfsync everysec
appenddirname "appendonlydir"
aof-load-truncated yes # nạp được AOF bị cụt đuôi thay vì từ chối khởi động
aof-use-rdb-preamble yes # AOF rewrite dùng phần đầu RDB, nạp nhanh hơn
maxmemory 4gb # dưới RAM máy khoảng 20 phần trăm
maxmemory-policy noeviction
tcp-keepalive 60
requirepass <mat-khau-dai-ngau-nhien> # tốt nhất trong tệp include 0600
masterauth <cung-mat-khau> # trên replicaYêu cầu và lý do:
appendonly yes: outbox sự kiện (gửi Access Hub) và bus nằm trong Redis, độ bền của chúng phụ thuộc AOF. Không tắt.save ...(RDB snapshot) giữ bật song song với AOF:dump.rdblà nguồn khôi phục thứ hai khi AOF hỏng (mục 4.2). Không đặtsave "".aof-load-truncated yes,aof-use-rdb-preamble yes: ghi rõ dù là mặc định của Redis 7, để không ai vô tình tắt.maxmemory-policy noeviction: không được loại bỏ khóa registry, bus, outbox. Khi đầy, ghi lỗi (ingest trả 503, agent đệm WAL) tốt hơn mất dữ liệu lặng lẽ.- Hệ thống:
sysctl vm.overcommit_memory=1(ghi vào/etc/sysctl.d/), tắt Transparent Huge Pages. - Replica:
replicaof <master> 6379. Có replica chưa phải HA tự động. Muốn failover tự động dùng Sentinel (chưa được collector hỗ trợ trực tiếp, collector nối mộtredis.addr, nên đặt Sentinel kèm VIP hoặc proxy, xem 08). - TLS Redis: đặt
redis.tls.enabled: true,ca_file,server_name(tùy chọncert_file,key_file).insecure_skip_verifychỉ dùng dev. - Tiền tố khóa
redis.prefix(mặc địnhah:). Dùng chung một Redis cho nhiều môi trường thì đặt tiền tố khác nhau. - Sao lưu: chép
dump.rdbvà thư mục AOF định kỳ. Mất Redis không mất dữ liệu nghiệp vụ (registry nạp lại từ Access Hub), nhưng mất sự kiện trong outbox chưa gửi.
Kiểm tra: redis-cli -h 10.0.0.10 -a "$PASS" ping trả PONG, INFO persistence có aof_enabled:1.
4.1 Unit systemd cho Redis: kiểm tra AOF trước khi khởi động, không lặp crash vô hạn
Sự cố 2026-10-02 (máy dev mirror production): đĩa đầy làm hỏng tệp appendonly.aof.*.incr.aof. Redis 7 từ chối nạp AOF hỏng, unit có Restart=on-failure, RestartSec=2 và không có giới hạn khởi động nên redis-master crash-loop khoảng 7 giờ, ingest không ghi được bus. Từ bản này unit Redis có ba lớp bảo vệ:
ExecStartPre=chạydeploy/redis/aof-preflight.sh(cài thànhredis-aof-preflight) trên thư mục dữ liệu Redis.StartLimitIntervalSec=600,StartLimitBurst=5: tối đa 5 lần khởi động trong 10 phút, sau đó unit chuyểnfailedvà dừng hẳn.RestartSec=5.OnFailure=accesshub-unit-failed@%n.service: ghi một dòngCRITICAL(sysloguser.crit, thẻaccesshub-unit-failed) kèm lệnh cần chạy. Watchdog của Access Hub vẫn cảnh báo qua trạng thái collector.
Hành vi của preflight (aof-preflight.sh <dir> [appenddirname]):
| Tình huống | Hành động | Khởi động Redis |
|---|---|---|
redis-check-aof báo AOF hợp lệ | Không làm gì | Có |
AOF hỏng, phần đuôi hỏng (diff) không quá AOF_FIX_MAX_PCT (mặc định 5) phần trăm kích thước tệp hỏng | Chép cả thư mục sang appendonlydir.bak-<thời điểm>, rồi redis-check-aof --fix (tự trả lời y), kiểm tra lại | Có |
AOF hỏng nặng, hoặc không chép được bản sao lưu (đĩa đầy), hoặc --fix không thành công | Đổi tên thư mục sang appendonlydir.damaged-<thời điểm>, tạo appendonlydir mới có tệp base là bản chép dump.rdb (đã qua redis-check-rdb) | Có, từ snapshot RDB mới nhất |
AOF hỏng và không có dump.rdb hợp lệ | Không đụng gì, thoát lỗi | Không (unit dừng sau 5 lần, có dòng CRITICAL) |
Không có manifest AOF nhưng có dump.rdb | Tạo appendonlydir từ dump.rdb như trên | Có |
Không có AOF và không có dump.rdb | Không làm gì (máy mới) | Có |
Preflight không bao giờ xóa dữ liệu, chỉ chép và đổi tên. Lý do phải tạo AOF từ dump.rdb thay vì chỉ dời AOF đi: với appendonly yes, Redis 7 không thấy AOF sẽ bỏ qua dump.rdb và khởi động rỗng (đã thử với 7.0.15), rồi lần save sau ghi đè dump.rdb bằng dữ liệu rỗng. Nhật ký preflight nằm trong journal của unit Redis (lọc chữ redis-aof-preflight), dòng hỏng có mức crit. Các thư mục .bak-*, .damaged-* không tự dọn: kiểm tra xong thì xóa tay để lấy lại đĩa.
Production với gói redis-server của distro ([email protected] đọc /etc/redis/redis-accesshub.conf), thêm drop-in thay vì sửa unit gốc:
sudo install -m 0755 deploy/redis/aof-preflight.sh /usr/local/bin/redis-aof-preflight
sudo install -m 0644 deploy/systemd/[email protected] /etc/systemd/system/
sudo mkdir -p /etc/systemd/system/[email protected]
sudo tee /etc/systemd/system/[email protected]/10-accesshub-hardening.conf <<'CONF'
[Unit]
StartLimitIntervalSec=600
StartLimitBurst=5
OnFailure=accesshub-unit-failed@%n.service
[Service]
Environment=AOF_FIX_MAX_PCT=5
ExecStartPre=/usr/local/bin/redis-aof-preflight /var/lib/redis-accesshub
Restart=on-failure
RestartSec=5
TimeoutStartSec=600
CONF
sudo systemctl daemon-reloadPreflight chạy cùng User= và sandbox của unit Redis nên cần quyền ghi vào thư mục dữ liệu (ReadWritePaths của unit gốc phải gồm /var/lib/redis-accesshub). Tăng TimeoutStartSec nếu AOF lớn nhiều GB (kiểm tra và chép tốn thời gian). Bản system unit của [email protected] chỉ cần bỏ --user trong thông báo. Drop-in này chưa được diễn tập trên máy production thật, thử trên máy thử trước.
4.2 Runbook khôi phục Redis khi AOF hỏng
Dấu hiệu: unit Redis failed hoặc activating (auto-restart), journal có Bad file format reading the append only file hoặc dòng AOF CORRUPTED của preflight, ingest /readyz 503, monitoring:check-collectors của Access Hub báo collector lỗi.
Trường hợp thường gặp, preflight tự xử lý: xem journal, xác nhận Redis đã lên, so DBSIZE với trước sự cố, kiểm tra replica (INFO replication có master_link_status:up). Dữ liệu ghi sau lần save cuối cùng (tối đa vài phút theo save 300 100) chỉ còn trong appendonlydir.damaged-*.
Xử lý tay (cách đã dùng ngày 2026-10-03, trước khi có preflight):
- Giải phóng đĩa trước (nguyên nhân gốc là đĩa đầy):
df -h, dọn đến khi còn trên 20 phần trăm trống. - Dừng unit Redis. Đổi tên thư mục AOF hỏng, không xóa:
mv appendonlydir appendonlydir.corrupt-$(date +%Y%m%d). - Kiểm tra snapshot:
redis-check-rdb dump.rdbphải báoRDB looks OK. - Khởi động Redis với AOF tắt để nạp
dump.rdb: sửa tạmappendonly notrong conf rồi start unit (hoặc chạy tayredis-server <conf> --appendonly no). Kiểm traDBSIZE. - Bật lại AOF khi đang chạy:
redis-cli CONFIG SET appendonly yes. Redis viết AOF mới từ dữ liệu trong bộ nhớ; chờINFO persistencecóaof_rewrite_in_progress:0vàaof_last_bgrewrite_status:ok. - Trả conf về
appendonly yes, restart unit. Kiểm traDBSIZE, replica nối lại, ingest hết lỗi Redis,php artisan monitoring:check-collectorsbáo 0 vấn đề. - Muốn cứu thêm dữ liệu sau snapshot: chép thư mục
.damaged-*(hoặc.corrupt-*) sang máy thử, chạyredis-check-aof --fixtrên bản chép rồi xem các lệnh còn đọc được. Thường không cần: registry nạp lại từ Access Hub, chỉ outbox chưa gửi là có thể mất.
Unit đã dừng do giới hạn khởi động: sau khi sửa, systemctl reset-failed <unit> && systemctl start <unit> (user unit thêm --user).
5. VictoriaMetrics và vmalert
Hai instance: vm-raw giữ mẫu thô, vm-long giữ rollup (docs/04-data-model.md). Tải bản victoria-metrics-prod và vmalert-prod từ trang phát hành chính thức của VictoriaMetrics, kiểm tra checksum, cài vào /usr/local/bin. Tạo user victoriametrics không đăng nhập.
/etc/systemd/system/vm-raw.service (đối chiếu deploy/systemd/accesshub-vm-raw.service):
[Unit]
Description=VictoriaMetrics vm-raw, raw samples 30d
After=network-online.target
Wants=network-online.target
[Service]
User=victoriametrics
ExecStart=/usr/local/bin/victoria-metrics-prod \
-storageDataPath=/var/lib/vm-raw \
-retentionPeriod=30d \
-httpListenAddr=10.0.0.20:8428 \
-memory.allowedPercent=40 \
-selfScrapeInterval=30s
Restart=on-failure
RestartSec=3
TimeoutStopSec=60
LimitNOFILE=65535
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/var/lib/vm-raw
ProtectKernelTunables=yes
ProtectControlGroups=yes
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
[Install]
WantedBy=multi-user.targetvm-long.service tương tự: -storageDataPath=/var/lib/vm-long, -retentionPeriod=400d, -httpListenAddr=10.0.0.20:8429.
/etc/systemd/system/vmalert.service:
[Unit]
Description=vmalert rollup vm-raw to vm-long
After=vm-raw.service vm-long.service
Wants=vm-raw.service vm-long.service
[Service]
User=victoriametrics
ExecStart=/usr/local/bin/vmalert-prod \
-datasource.url=http://10.0.0.20:8428 \
-remoteWrite.url=http://10.0.0.20:8429 \
-rule=/etc/accesshub-collector/vmalert/rules.yml \
-notifier.blackhole \
-evaluationInterval=1m \
-httpListenAddr=127.0.0.1:8880
Restart=on-failure
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
[Install]
WantedBy=multi-user.targetTệp luật rollup sinh từ chính binary collector đã cài: /usr/local/bin/collector -rollup-rules > /etc/accesshub-collector/vmalert/rules.yml (5 phút và 1 giờ, avg, min, max, last, cho mọi chỉ số trong catalog nhúng của đúng phiên bản đó; bản dev dùng deploy/dev/gen-vmalert-rules.sh). Xem kỹ đầu ra trước khi đặt. Mỗi lần nâng cấp collector có thêm chỉ số, sinh lại tệp và nạp lại vmalert (systemctl reload vmalert hoặc kill -HUP, hoặc curl -X POST http://<vmalert>/-/reload); kiểm tra curl -s http://<vmalert>/api/v1/rules không có lastError. Không giữ tệp luật cũ: chỉ số mới sẽ không có rollup và biểu đồ khoảng dài của chỉ số đó trống sau 7 ngày (collector chỉ đọc lại vm-raw khi khoảng còn trong 30 ngày).
Cấu hình collector (vai trò admin) phải có cả tsdb.url (vm-raw) và tsdb.long_url (vm-long): khi thiếu long_url, API series chỉ nhận khoảng tối đa 31 ngày và luôn đọc vm-raw.
Retention theo gói (Q17, ADR 0016) chạy ở vai trò admin, bật mặc định:
tsdb:
retention:
enforce: true # xóa vật lý dữ liệu ngoài retention của gói (đọc luôn bị cắt dù tắt)
dry_run: false # true: chỉ ghi log những ngày sẽ xóa (nên bật vài ngày khi triển khai lần đầu)
sweep_interval: 1h
first_seen: 24h # chờ trước lần xóa đầu với công ty mới thấy
force_merge: true # gọi /internal/force_merge cho phân vùng tháng vừa bị xóa, tối đa 1 lần mỗi ngàyNếu đặt proxy trước VictoriaMetrics, phải cho collector đi qua /api/v1/label/*/values, /api/v1/export, /api/v1/admin/tsdb/delete_series và /internal/force_merge ở cả vm-raw và vm-long. Theo dõi ahc_retention_last_sweep_timestamp_seconds (cảnh báo nếu cũ hơn 3 giờ), ahc_retention_errors_total, ahc_retention_days_deleted_total và mục retention của GET /internal/v1/status. force_merge ghi lại cả phân vùng tháng: chừa IO và dung lượng trống bằng cỡ phân vùng lớn nhất. Xóa là không hoàn tác: sao lưu vmbackup hằng ngày là cách duy nhất để khôi phục khi Access Hub gửi nhầm chính sách.
Lưu ý vận hành:
- Đĩa: dự trù dung lượng theo số series x độ phủ x retention. Theo dõi
vm_free_disk_space_bytes; VictoriaMetrics cần trống tối thiểu 20 phần trăm đĩa để merge. - VictoriaMetrics ẩn 30 giây gần nhất khỏi truy vấn (
-search.latencyOffset), nên giá trị "mới nhất" trễ tới 30 giây là bình thường. - Collector ghi bằng
/api/v1/import(JSON line), không phải remote-write. Xóa dữ liệu công ty hoặc máy chủ dùng/api/v1/admin/tsdb/delete_seriescủavm-rawvàvm-long; nếu đặt proxy phía trước VictoriaMetrics thì không được chặn đường dẫn này. - Sao lưu: dùng
vmbackuphoặc snapshot (/snapshot/create) theo lịch, chép ra ngoài. Khôi phục bằngvmrestore. Đây là dữ liệu duy nhất của hệ thống giám sát không thể tái tạo từ Access Hub. - Nhiều
vmalerttrùng lặp gây ghi trùng rollup (vô hại nhưng tốn): chỉ chạy một, hoặc hai instance HA có cùng-rulevà-remoteWrite.urlđã hỗ trợ dedupe (-dedup.minScrapeIntervalởvm-long).
6. Collector
6.1 Cài binary
Trên máy build (Go đã cài, xem go.mod) hoặc trong CI:
git checkout <tag-phat-hanh>
make build # tạo ./bin/collector, CGO_ENABLED=0, nhúng phiên bản bằng ldflags
./bin/collector -version
sha256sum bin/collector > bin/collector.sha256Nếu máy build không có make, chạy tương đương: CGO_ENABLED=0 go build -trimpath -ldflags "-s -w" -o bin/collector ./cmd/collector. Chép binary sang các node, kiểm checksum, đặt /usr/local/bin/accesshub-collector (root:root, 0755). Giữ phiên bản cũ kế bên (accesshub-collector-<phien-ban>, liên kết tên ngắn) để quay lui nhanh.
Tạo user và thư mục:
sudo useradd --system --no-create-home --shell /usr/sbin/nologin accesshub-collector
sudo install -d -o root -g accesshub-collector -m 0750 /etc/accesshub-collector /etc/accesshub-collector/secrets /etc/accesshub-collector/tls6.2 Bí mật
Mỗi bí mật một tệp 0640 (chủ root, nhóm accesshub-collector), không đặt trong repo, không in log:
| Tệp | Nội dung | Ghi chú |
|---|---|---|
secrets/redis.password | Mật khẩu Redis | |
secrets/hub.token | Token dịch vụ của user có vai trò Monitoring Collector trong Access Hub | Có khi HUB-2 xong (mục 8) |
secrets/admin.token | Token bảo vệ API admin | Tối thiểu 24 ký tự, sinh: openssl rand -base64 36 |
Biến môi trường AHC_* (xem mục 6.6) ghi đè YAML, có dạng _FILE cho token và mật khẩu.
6.3 Cấu hình từng vai trò
Khóa chưa liệt kê dùng mặc định trong internal/config/config.go. Khóa lạ trong YAML là lỗi (KnownFields), nên gõ sai sẽ bị báo ngay khi -check.
/etc/accesshub-collector/ingest.yaml (mỗi node ingest):
collector_id: prod-ingest-1 # duy nhất toàn hệ thống, hoặc đặt bằng AHC_COLLECTOR_ID
roles: [ingest]
log: { level: info, format: json }
ops:
listen: 10.0.1.11:9100 # LB phải tới được để kiểm tra /readyz
ingest:
listen: 10.0.1.11:8443 # HTTP thuần sau LB, hoặc kèm tls_cert_file và tls_key_file
public_url: https://agents.example.com
trusted_proxies: [10.0.1.0/24] # mạng của LB, để lấy IP thật từ X-Forwarded-For
checks_sync_interval: 1m # chu kỳ kéo check trung tâm từ Access Hub (COL-20)
limits:
max_body_bytes: 1048576
max_decoded_bytes: 8388608
max_series: 500
max_series_per_company: 0 # 0 = không giới hạn theo công ty; đặt khi một công ty có thể làm phình TSDB (tính theo từng node ingest)
hub:
base_url: https://hub.example.com
token_file: /etc/accesshub-collector/secrets/hub.token
timeout: 10s
redis:
addr: 10.0.0.10:6379
password_file: /etc/accesshub-collector/secrets/redis.password
prefix: "ah:"
shutdown:
drain_delay: 10s # /readyz trả 503 trước, để LB rút node rồi mới dừng nhận
grace: 25s/etc/accesshub-collector/worker.yaml (mỗi node worker):
collector_id: prod-worker-1
roles: [worker]
log: { level: info, format: json }
ops:
listen: 10.0.1.21:9100
hub:
base_url: https://hub.example.com
token_file: /etc/accesshub-collector/secrets/hub.token
redis:
addr: 10.0.0.10:6379
password_file: /etc/accesshub-collector/secrets/redis.password
tsdb:
url: http://10.0.0.20:8428
long_url: http://10.0.0.20:8429
alerting:
agent_interval: 30s # khớp chu kỳ agent. Ngưỡng mất kết nối = max(3 x agent_interval, down_min)
down_min: 90s
rules_sync_interval: 1m # chu kỳ kéo luật từ Access Hub (COL-8)
silences_sync_interval: 1m # chu kỳ kéo silence từ Access Hub (COL-9)
flap_transitions: 4 # số lần chuyển trạng thái để vào flapping, 0 tắt (COL-9)
flap_window: 30m
flap_stable: 30m
group_down: # gom sự cố diện rộng (COL-9), nhiều worker thì chỉ một worker bật
enabled: true
min: 5
ratio: 0.30
window: 60s
# companies: # ghi đè theo công ty khi Access Hub không đặt
# "<company_id>": {min: 8, ratio: 0.5, window: 120s}
rules_state_interval: 30s # chu kỳ snapshot trạng thái đánh giá
no_data_after: 5m # series im lặng quá mức này thì áp no_data
rules_dir: /var/lib/accesshub-collector/rules # snapshot tệp khi không dùng Redis
shutdown:
drain_delay: 0s
grace: 25s/etc/accesshub-collector/admin.yaml (1 hoặc 2 node):
collector_id: prod-admin-1
roles: [admin]
log: { level: info, format: json }
ops:
listen: 127.0.0.1:9100
admin:
listen: 10.0.1.31:9101 # chỉ mạng nội bộ Access Hub gọi tới được
token_file: /etc/accesshub-collector/secrets/admin.token
hub:
base_url: https://hub.example.com
token_file: /etc/accesshub-collector/secrets/hub.token
redis:
addr: 10.0.0.10:6379
password_file: /etc/accesshub-collector/secrets/redis.password
tsdb:
url: http://10.0.0.20:8428
long_url: http://10.0.0.20:8429API admin hiện chỉ chạy HTTP (không có tls_cert_file). Đặt nó trên mạng riêng hoặc đặt một reverse proxy TLS phía trước, đừng để bearer token đi qua mạng không tin cậy.
Các nhóm khóa tinh chỉnh (YAML): ingest.limits.* (giới hạn body, số điểm, tốc độ theo loại request), bus.{queue_per_shard,readers,block,claim_idle}, outbox.{backend,batch_max,flush_interval,backoff_min,backoff_max,retention}, redis.cache_ttl, worker.{shards,shard_count,shard_index} (nhiều worker dùng chung Redis phải đặt shard_count và shard_index riêng, xem docs/04), tsdb.{timeout,max_batch_samples,max_batch_wait,retry_max}, hub.{sync_interval,lookup_per_second}. Đổi mặc định khi có số liệu đo.
6.4 Kiểm tra cấu hình
sudo -u accesshub-collector /usr/local/bin/accesshub-collector -check -config /etc/accesshub-collector/worker.yaml
echo $? # 0 hợp lệ, 3 cấu hình sai (2 sai cú pháp dòng lệnh, 1 lỗi chung)Lưu ý cảnh báo: node chỉ có role ingest không cần tsdb, và sẽ không báo thiếu tsdb.url. Node worker hoặc admin thiếu tsdb.url bị cảnh báo.
6.5 Unit systemd
Dùng các unit mẫu deploy/systemd/accesshub-collector-{ingest@,worker@,admin}.service làm gốc, sửa cho máy thật: bỏ %h (đường dẫn home dev) thành /etc/accesshub-collector/... và /usr/local/bin/..., chuyển từ user unit sang system unit (thêm User=accesshub-collector, WantedBy=multi-user.target), bỏ phụ thuộc accesshub-mockhub.service. Ví dụ /etc/systemd/system/accesshub-collector-ingest.service:
[Unit]
Description=Access Hub Collector ingest (role ingest)
After=network-online.target
Wants=network-online.target
[Service]
User=accesshub-collector
Group=accesshub-collector
EnvironmentFile=-/etc/accesshub-collector/ingest.env
ExecStartPre=/usr/local/bin/accesshub-collector -check -config /etc/accesshub-collector/ingest.yaml
ExecStart=/usr/local/bin/accesshub-collector -config /etc/accesshub-collector/ingest.yaml
Restart=on-failure
RestartSec=3
TimeoutStopSec=45
LimitNOFILE=65535
NoNewPrivileges=yes
PrivateTmp=yes
PrivateDevices=yes
ProtectSystem=strict
ProtectHome=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
MemoryMax=1G
[Install]
WantedBy=multi-user.targetTimeoutStopSec phải lớn hơn shutdown.drain_delay + shutdown.grace (10 + 25 = 35 giây, đặt 45). Nhiều node cùng một máy thì dùng unit mẫu @ và tệp env riêng mỗi instance đặt AHC_COLLECTOR_ID, AHC_OPS_LISTEN, AHC_INGEST_LISTEN khác nhau.
Khởi động: systemctl daemon-reload && systemctl enable --now accesshub-collector-worker accesshub-collector-admin accesshub-collector-ingest (thứ tự: Redis và VictoriaMetrics trước, rồi worker và admin, cuối cùng ingest, rồi mới thêm vào LB).
6.6 Biến môi trường
AHC_CONFIG, AHC_ROLES, AHC_COLLECTOR_ID, AHC_LOG_LEVEL, AHC_OPS_LISTEN, AHC_HUB_URL, AHC_HUB_TOKEN (hoặc _FILE), AHC_TSDB_URL, AHC_TSDB_LONG_URL, AHC_REDIS_ADDR, AHC_REDIS_USERNAME, AHC_REDIS_PASSWORD (hoặc _FILE), AHC_REDIS_PREFIX, AHC_REDIS_DB, AHC_REDIS_TLS, AHC_REDIS_TLS_CA_FILE, AHC_INGEST_LISTEN, AHC_INGEST_TLS_CERT_FILE, AHC_INGEST_TLS_KEY_FILE, AHC_INGEST_PUBLIC_URL, AHC_ADMIN_LISTEN, AHC_ADMIN_TOKEN (hoặc _FILE), AHC_BUS_BACKEND, AHC_OUTBOX_BACKEND, AHC_OUTBOX_DIR.
Cổng mặc định: ops 127.0.0.1:9100 (/healthz, /readyz, /metrics), admin 127.0.0.1:9101, ingest :8443.
7. Load balancer cho agent
Yêu cầu: TLS 1.2 trở lên (khuyến nghị 1.2 và 1.3), HTTP/2 bật, tới tên miền agents.example.com, chuyển tiếp HTTP thuần tới các node ingest, thêm X-Forwarded-For và X-Forwarded-Proto, giới hạn body 1 MiB (bằng max_body_bytes), timeout đọc 30 giây, thử lại sang node khác khi lỗi kết nối, timeout, 503.
Kiểm tra sức khỏe chủ động vào http://<node>:9100/readyz (khác môi trường dev chỉ có kiểm tra thụ động). Dùng HAProxy, Nginx Plus, F5, hoặc LB của nhà cung cấp đám mây. /readyz trả 503 khi đang tắt êm (drain_delay), nên nâng cấp cuốn chiếu không rớt request.
Ví dụ HAProxy (đoạn chính):
frontend agents
bind :443 ssl crt /etc/haproxy/certs/agents.example.com.pem alpn h2,http/1.1 ssl-min-ver TLSv1.2
option forwardfor
http-request set-header X-Forwarded-Proto https
default_backend collector_ingest
backend collector_ingest
balance roundrobin
option httpchk GET /readyz
http-check expect status 200
default-server check port 9100 inter 3s fall 2 rise 2
timeout server 30s
retry-on conn-failure empty-response 503
retries 2
server ingest1 10.0.1.11:8443
server ingest2 10.0.1.12:8443Tham khảo thêm cấu hình Nginx dev ở deploy/dev/nginx/nginx.conf.tmpl (giới hạn body, timeout, proxy_next_upstream). Nếu Nginx OSS, kiểm tra thụ động (max_fails) là mức tối thiểu, chấp nhận được nhưng chậm phát hiện hơn.
Kiểm tra LB:
curl -sS -o /dev/null -w '%{http_code}\n' https://agents.example.com/agent/v1/config # không token: mong đợi 401 (không phải 502 hay timeout)
openssl s_client -connect agents.example.com:443 -servername agents.example.com </dev/null 2>/dev/null | openssl x509 -noout -dates -issuerĐặt nhắc hạn chứng chỉ ít nhất 30 ngày trước khi hết hạn. Hết hạn chứng chỉ là nguyên nhân hàng đầu khiến mọi agent mất tín hiệu cùng lúc.
8. Phía Access Hub
Phần monitoring trong Access Hub chưa được xây. Bảng dưới là những gì cần có khi HUB-* xong, để chuẩn bị sớm (chi tiết 06).
| Việc | Mục HUB | Trạng thái |
|---|---|---|
Bảng, model, API /api/v1/monitoring/collector/* (enroll, agents, seen, heartbeat, events) | HUB-1, 3, 4, 5 | Chưa |
Quyền monitoring.* và vai trò Monitoring Collector | HUB-2 | Chưa |
| Sinh License, giao diện Agents, lệnh cài | HUB-6, 7 | Chưa |
Client gọi admin API của collector (MonitoringCollectorClient) | HUB-8 | Chưa |
Khi làm xong, các bước triển khai phía Access Hub:
- Chạy migration trên môi trường thực (qua quy trình release thường lệ, sao lưu DB trước).
- Tạo user dịch vụ (không đăng nhập được), gán vai trò
Monitoring Collector, tạo token API, ghi vàosecrets/hub.tokencủa từng node collector. Mỗi node có thể dùng chung một token hoặc token riêng (khuyến nghị riêng để thu hồi từng node). - Cấu hình Access Hub trỏ tới collector: URL admin (
https://collector-admin.internal:9101) vàadmin.token. Đặt vào cài đặt hoặc.envcủa Access Hub (tên khóa do HUB-8 quy định), rồiphp artisan config:cachevàphp artisan queue:restart. - Đảm bảo Access Hub với MySQL read/write split đọc-sau-ghi đúng: sau enroll, bản ghi agent phải đọc từ node ghi (xem 06).
- Mở tường lửa hai chiều theo mục 3.
Trong thời gian chờ, đừng đặt hub.base_url trỏ Access Hub hiện tại: API monitoring chưa tồn tại, collector sẽ liên tục lỗi 404 và outbox đầy. Dùng mockhub chỉ trên dev.
9. Agent
9.1 Chuẩn bị
- Có
https://agents.example.comhoạt động (mục 7) và hạ tầng trả lời. - Có License dùng một lần (HUB-6). Mỗi token gắn công ty và có thể gắn máy chủ. Token không đi qua dòng lệnh.
- Kho chứa gói (Q2) và khóa ký (Q3) chưa được quyết định. Tạm thời tự host gói trên máy chủ HTTPS nội bộ (ví dụ
https://downloads.example.com/agent/) gồm các tệp:.deb,.rpm, tar,SHA256SUMS,latest,install.sh.
9.2 Dựng gói (trên máy build, từ mã nguồn của Agent)
git tag v1.0.0 # phiên bản lấy từ git describe (hoặc make package VERSION=v1.0.0)
make package # deb, rpm, tar.gz cho amd64 và arm64, install.sh và SHA256SUMS, vào dist/release (scripts/package.sh)Cần nfpm cài sẵn (go install github.com/goreleaser/nfpm/v2/cmd/[email protected]). Đặt SIGN_HOOK để ký SHA256SUMS khi đã có khóa (Q3). Kiểm tra gói trước khi đưa lên: dpkg-deb -I <tệp>.deb, dpkg-deb -c <tệp>.deb, rpm -qpi và rpm -qpl (máy có rpm).
9.3 Cài thử một máy (bắt buộc trước khi cài hàng loạt)
sudo ACCESSHUB_COLLECTOR_URL=https://agents.example.com \
ACCESSHUB_LICENSE_FILE=/root/license.token \
apt install ./accesshub-agent_1.0.0_amd64.debsudo ... dnf install ./accesshub-agent-1.0.0-1.x86_64.rpmGói tạo user accesshub-agent, thư mục /var/lib/accesshub-agent và /var/log/accesshub-agent, đặt /etc/accesshub-agent/agent.yaml, chỉ khi có URL và token thì enroll và khởi động. Không bao giờ khởi động dịch vụ khi chưa enroll. Enroll thủ công (khi không đặt biến lúc cài), đúng tài khoản dịch vụ, token qua stdin:
read -rs TOKEN
printf '%s\n' "$TOKEN" | sudo -u accesshub-agent accesshub-agent enroll --collector https://agents.example.com --token-stdin
unset TOKEN
sudo systemctl enable --now accesshub-agentXác minh: accesshub-agent status (mã thoát 0, đã enroll, lần gửi cuối gần đây, WAL gần 0), journalctl -u accesshub-agent -n 50, và accesshub-agent diag --output /tmp/diag.zip khi cần hỗ trợ (đã che bí mật). Mã thoát enroll: 5 bị từ chối (token sai, hết hạn, đã dùng), 6 không kết nối được (DNS, tường lửa, TLS).
Cài và giữ ca_file trong agent.yaml nếu LB dùng CA nội bộ. Không bao giờ đặt insecure_skip_verify: true ở production (agent in cảnh báo mỗi giờ).
9.4 Cài bằng install.sh (kênh tải có xác minh)
sudo ACCESSHUB_COLLECTOR_URL=https://agents.example.com \
ACCESSHUB_LICENSE_FILE=/root/license.token \
ACCESSHUB_DOWNLOAD_BASE=https://downloads.example.com/agent \
sh install.sh --pubkey release.pubScript tải gói đúng kiến trúc, kiểm SHA256SUMS và chữ ký, rồi kiểm checksum gói trước khi cài. Chưa có khóa ký (Q3) thì chỉ có --allow-unsigned (vẫn kiểm checksum nhưng SHA256SUMS nằm cùng nơi với gói, nên chỉ chống hỏng tệp, không chống bị thay thế). Đề nghị hoàn tất Q3 trước khi cài ngoài mạng tin cậy. --dry-run để thử không thay đổi gì.
9.5 Cài hàng loạt
| Cách | Khi nào | Ghi chú |
|---|---|---|
| Ansible, Salt, Puppet | Có sẵn quản lý cấu hình | Phân phối token từng máy qua kho bí mật (Vault, ansible-vault), ghi vào tệp 0600, rồi chạy install.sh hoặc apt/dnf install với ACCESSHUB_LICENSE_FILE |
| Cloud-init, image vàng | Máy mới sinh ra | Không nhúng credentials.json hay token vào image. License dùng một lần, truyền qua user-data hoặc metadata lúc khởi tạo |
| Lệnh một dòng từ giao diện | Quản trị viên tự cài | HUB-6 sẽ tạo lệnh kèm token |
| Windows GPO, Intune | Sau khi AGT-7 xong | Chưa có |
Làm theo lô nhỏ (5 đến 10 máy, rồi 10 phần trăm, rồi toàn bộ), sau mỗi lô kiểm tra mục 10. Collector giới hạn enroll theo IP nguồn (enroll_per_minute: 6, enroll_burst: 10, tính theo IP nguồn client); cài hàng trăm máy sau cùng một NAT sẽ chạm giới hạn này, hãy giãn thời gian hoặc nâng giá trị ingest.limits.enroll_* có kiểm soát.
9.6 Nâng cấp, gỡ agent
- Nâng cấp:
apt install ./accesshub-agent_<moi>.debhoặcdnf upgrade. Cấu hìnhagent.yamlđược giữ, thông tin đăng nhập giữ, dịch vụ tự khởi động lại nếu đang chạy. Trong lúc nâng cấp, dpkg có thể hỏi vềagent.yaml(postinstall có chỉnh tệp này), trả lời giữ bản hiện tại. - Gỡ:
apt remove(giữ dữ liệu) hoặcapt purge(xóa sạch). rpm không có purge: chạysudo accesshub-agent uninstall --purgetrướcdnf remove. Gỡ agent không báo collector: thu hồi trong Access Hub (hoặcDELETE /internal/v1/agents/{id}).
Khi collector nâng cấp, nâng collector trước, agent sau (collector hỗ trợ giao thức N và N-1).
10. Danh sách kiểm tra sau triển khai
Chạy lần lượt, dừng ở mục đầu tiên hỏng.
| # | Kiểm tra | Lệnh hoặc cách | Kết quả mong đợi |
|---|---|---|---|
| 1 | Đồng bộ thời gian mọi máy | timedatectl | System clock synchronized: yes |
| 2 | Redis | redis-cli -a "$PASS" ping, INFO persistence, INFO replication | PONG, aof_enabled:1, replica nối |
| 3 | VictoriaMetrics | curl -s http://10.0.0.20:8428/health, cổng 8429 | OK |
| 4 | vmalert | curl -s http://127.0.0.1:8880/api/v1/rules | Có nhóm luật rollup, không lỗi |
| 5 | Cấu hình collector | accesshub-collector -check -config <tệp> từng vai trò | Mã thoát 0 |
| 6 | Collector khởi động | curl -s http://<node>:9100/readyz | 200, mỗi node một collector_id |
| 7 | LB thấy ingest | Xem trạng thái backend trong LB | Mọi node ingest UP |
| 8 | TLS | openssl s_client (mục 7) | Chuỗi đầy đủ, hạn dài, tên khớp |
| 9 | Dừng 1 ingest | systemctl stop một node, lặp curl tới LB | Không 5xx, agent vẫn gửi |
| 10 | Giết 1 worker | kill -9 một worker giữa dòng dữ liệu | Không khoảng trống dữ liệu (worker còn lại nhận lô treo sau bus.claim_idle, 30 giây) |
| 11 | Agent thử | Mục 9.3 | accesshub-agent status ổn, series xuất hiện trong vm-raw với company_id, server_id |
| 12 | Dữ liệu đến VictoriaMetrics | curl -s 'http://10.0.0.20:8428/api/v1/export?match[]={__name__=~"ah_.*"}' (hoặc truy vấn qua admin API) | Có mẫu, nhãn company_id do collector gắn |
| 13 | Rollup | Chờ 10 phút, truy vấn vm-long | Có chuỗi rollup 5 phút |
| 14 | Mất liên lạc | Dừng agent thử quá ngưỡng (mặc định 90 giây) | Worker phát sự kiện agent_down, vào outbox (hoặc Access Hub nhận, khi có HUB-5) |
| 15 | Outbox | Metric outbox trên /metrics của worker (xem 10) | Không tăng dần |
| 16 | Hai công ty | Đẩy dữ liệu hai tenant, truy vấn chéo qua admin API | Không thấy dữ liệu công ty kia |
| 17 | Sao lưu thử | Khôi phục Redis và VictoriaMetrics vào máy thử | Đọc được |
devctl.sh smoke (mục 7 của 09) là mẫu kịch bản cho các kiểm tra 9, 10, 11, 12 trên dev; có thể chạy lại tương tự trên staging.
11. Giám sát chính hệ thống giám sát
- Thu
/metricscủa mọi tiến trình collector (cổng ops) vào Prometheus hoặc VictoriaMetrics riêng (không phảivm-rawcủa khách hàng). - Cảnh báo tối thiểu:
/readyzkhông 200 quá 2 phút; chứng chỉ LB còn dưới 30 ngày; Redis dùng bộ nhớ trên 80 phần trămmaxmemory; đĩavm-raw,vm-longdưới 25 phần trăm trống; outbox tăng liên tục 15 phút; ingest trả 503 tăng; số worker giảm; vmalert không đánh giá được. - Đặt một dead-man check bên ngoài (tự giám sát): nếu toàn bộ collector chết thì không ai báo, cần một kiểm tra từ hệ thống khác vào
https://agents.example.com. - Chi tiết metric: xem 10.
12. Sao lưu, nâng cấp, quay lui
| Việc | Cách làm |
|---|---|
| Sao lưu hằng ngày | vmbackup cho vm-raw và vm-long; sao chép dump.rdb và AOF của Redis; chép /etc/accesshub-collector (trừ bí mật, bí mật lưu ở kho riêng). Giữ bản sao ngoài máy và thử khôi phục hằng quý |
| Nâng cấp collector | Nâng worker và admin trước (cuốn chiếu từng node, đợi /readyz 200), rồi ingest từng node: rút khỏi LB (/readyz 503 tự động khi dừng êm), systemctl restart, đợi /readyz 200, cho vào lại. Giữ tối thiểu một node mỗi vai trò chạy |
| Quay lui | Đổi liên kết binary về phiên bản trước rồi restart. Không có migration dữ liệu phía collector nên quay lui an toàn, trừ khi phiên bản mới đã ghi định dạng bus hoặc registry mới (kiểm tra ghi chú phát hành) |
| Xoay token | Cấp token mới, ghi vào tệp bí mật, khởi động lại cuốn chiếu, thu hồi token cũ. Token admin: cập nhật đồng thời ở Access Hub và collector |
| AOF Redis hỏng | Preflight tự sửa đuôi nhỏ hoặc khởi động từ dump.rdb (mục 4.1); xử lý tay theo mục 4.2 |
| Mất Redis | Dựng lại Redis rỗng với cùng mật khẩu: registry nạp lại từ Access Hub (sau hub.sync_interval, mặc định 1 phút), agent tự đệm WAL trong lúc chờ. Mất các sự kiện chưa gửi trong outbox |
| Mất VictoriaMetrics | Khôi phục từ snapshot. Trong lúc mất, worker retry (tsdb.retry_max), bus đệm trong Redis, agent đệm WAL (50 MiB hoặc 24 giờ mặc định) |
| Thu hồi khẩn một agent | Thu hồi trong Access Hub hoặc DELETE /internal/v1/agents/{agent_id} với Authorization: Bearer <admin token> (idempotent, luôn 204, hiệu lực sau tối đa redis.cache_ttl, mặc định 15 giây) |
12.1 Chuyển từ VictoriaMetrics node đơn sang cụm (dàn ý, ADR 0017)
Chỉ làm khi COL-15 xong (janitor và purge chạy trên cụm, agentsim đã chạy trên cụm). Chưa có runbook đã diễn tập, các bước dưới đây là dàn ý và phải thử trên bản sao trước.
- Dựng cụm rỗng cho
vm-rawvàvm-long(mỗi cụm tối thiểu 3vmstorage, 2vminsert, 2vmselect,-replicationFactor=2), bật-dedup.minScrapeInterval(cần kiểm chứng) để ghi trùng giai đoạn chuyển không nhân đôi mẫu. - Ghi kép từ mốc T0. Worker ghi cả node đơn và cụm. Giai đoạn này cần mã collector hỗ trợ hai đích ghi (thuộc COL-15).
- Nạp lịch sử từ node đơn sang cụm bằng
vmctl vm-native(cách duy nhất tài liệu cụm chính thức nêu), theo khoảng[T0 - retention của kho, T0]: 30 ngày chovm-raw, 400 ngày chovm-long. Giữ nguyên nhãn, gồmah_day, không viết lại nhãn. Dùngvmbackuprồivmrestoređể đưa dữ liệu node đơn vào cụm chưa được kiểm chứng, không dùng. - Kiểm tra: so số series theo công ty giữa hai bên, so kết quả API
seriescủa vài công ty và vài chỉ số ở hai bên, chạy janitor ởdry_runtrên cụm (ahc_retention_*), thử xóa một server thử bằng purge. - Chuyển đọc và janitor sang cụm. Giữ ghi kép tối thiểu 7 ngày làm cửa sổ quay lui.
- Ngừng ghi vào node đơn. Giữ node đơn ở chế độ chỉ đọc và
vmbackupcuối cùng đến hết retention thô (30 ngày), rồi gỡ.
- Quay lui: trước bước 6 chỉ cần chuyển đọc và janitor về node đơn (nó vẫn nhận ghi kép). Sau bước 6 phải nạp ngược bằng
vmctltừ cụm. - Khoảng trống đồ thị: nếu bỏ bước 3 thì mọi đồ thị trước T0 mất (trống). Nếu chỉ nạp
vm-rawthì rollup trước T0 phải tạo lại bằng chế độ replay củavmalert(cần kiểm chứng) hoặc chấp nhận khoảng trống ởvm-long. Dữ liệu cũ chưa có nhãn ngày phải được chuyển xong ở node đơn trước bước 1 (ADR 0016 mục 4.6). - Thông báo cho khách chỉ cần nếu chấp nhận khoảng trống. Retention theo gói và ân hạn không đổi vì chúng nằm ở Access Hub và collector, không ở kho.
12.2 Chuyển một công ty giữa hai collector
Chỉ cần khi có collector thứ hai (cụm riêng cho khách rất lớn hoặc vùng khác, COL-18). Nâng hoặc hạ gói không gây chuyển, vì company_id và collector giữ nguyên.
| Lựa chọn | Cách làm | Hệ quả |
|---|---|---|
| 1. Không chuyển | Công ty ở lại collector hiện tại, gán collector đúng ngay lúc tạo công ty | Không mất dữ liệu, không việc thủ công. Khuyên dùng |
| 2. Chuyển, chấp nhận trống lịch sử | Đổi collector_id của agent (HUB-15), agent nhận collector_url mới. Dữ liệu cũ ở collector cũ hết hạn tự nhiên theo retention, rồi gọi DELETE /internal/v1/companies/{id}/data để xóa nốt | Đồ thị trước thời điểm chuyển trống ở collector mới. Dữ liệu cũ vẫn có trong ân hạn nếu chưa xóa nhưng Access Hub chỉ truy vấn collector hiện tại |
| 3. Chuyển và sao chép dữ liệu | Như 2, thêm vmctl vm-native với bộ chọn {company_id="..."} cho cả hai kho từ cụm cũ sang cụm mới (giữ nhãn ah_day), kiểm tra, rồi xóa dữ liệu công ty ở collector cũ bằng purge | Giữ lịch sử, tốn IO và cần cửa sổ thao tác. Trong lúc sao chép, thời điểm cuối có thể lệch vài phút (chạy lại phần chênh lệch sau khi đổi đích ghi) |
- Gỡ ghim License:
MonitoringLicense.collector_idghim License vào một collector. Khi công ty chuyển, License nào đã ghim phải được gỡ ghim (hoặc ghim lại collector mới) trước, nếu không agent enroll mới sẽ nhậnbinding_failed(HTTP 422) vì collector báo danh khác collector đã ghim. - Chính sách retention và ân hạn theo từng công ty do Access Hub trả (
GET /settings/{company_id}), nên collector mới áp đúng chính sách mà không cần chuyển trạng thái. - Sau khi chuyển phải kiểm tra cô lập: công ty khác trên collector cũ và mới không bị ảnh hưởng (kiểm thử hai tenant).
13. Bảo mật khi triển khai
- Mọi bí mật (mật khẩu Redis, token hub, token admin) nằm trong tệp 0640, nhóm
accesshub-collector, không có trong repo, nhật ký, lịch sử shell. Xoay định kỳ. - Collector chạy không root, sandbox systemd (xem unit),
MemoryMaxgiới hạn. - Giao tiếp ra ngoài: chỉ agent tới LB (443), collector tới Access Hub, không cho collector tự ra Internet nếu không cần.
- Agent chỉ đẩy ra, không mở cổng, không thực thi lệnh từ xa (ADR 0010).
- Mọi truy vấn và ghi TSDB có
company_iddo collector gắn, không tin nhãn do agent gửi. Mọi thay đổi code chạm vào đây phải có kiểm thử hai tenant. - Admin API chỉ sau mạng riêng, token tối thiểu 24 ký tự, xoay định kỳ. Không đưa cổng 9101 ra LB công khai.
- Tệp
credentials.jsoncủa agent (0600) là thông tin đăng nhập của máy, không chép ra ngoài, không đưa vào image. - Cập nhật hệ điều hành và
redis, VictoriaMetrics theo bản vá bảo mật. Chạygovulncheck ./...khi build collector.
14. Xử lý sự cố nhanh
| Triệu chứng | Nguyên nhân thường gặp | Xử lý |
|---|---|---|
| Collector thoát mã 3 lúc khởi động | YAML sai (khóa lạ, giá trị ngoài khoảng, thiếu collector_id) | accesshub-collector -check -config <tệp>, đọc dòng lỗi |
/readyz 503 sau khi khởi động | Redis hoặc TSDB không tới được, sai mật khẩu | Xem thân JSON của /readyz, kiểm tra mạng và mật khẩu |
| Agent báo enroll mã 5 | Token sai, hết hạn, hoặc dùng rồi; LB không chuyển tiếp /agent/v1/enroll | Cấp token mới, kiểm tra nhật ký ingest |
| Agent báo mã 6 | DNS, tường lửa 443, TLS (CA không tin cậy, chứng chỉ hết hạn) | accesshub-agent diag (có thử DNS, TCP, TLS, skew) |
| Mọi agent mất tín hiệu cùng lúc | Chứng chỉ LB hết hạn, LB chết, Redis mất | Mục 7, mục 4 |
Redis crash-loop hoặc unit failed, journal có Bad file format reading the append only file | AOF hỏng (thường do đĩa đầy) | Mục 4.2; giải phóng đĩa trước |
| Ingest 503 | Bus đầy (worker chậm hoặc chết), Redis đầy (maxmemory), TSDB chậm | Xem số worker, INFO memory, độ trễ ghi TSDB; thêm worker |
| Nhiều agent báo lệch đồng hồ | NTP hỏng | Sửa đồng bộ thời gian, dữ liệu cũ quá 24 giờ bị bỏ |
| Outbox tăng | Access Hub không nhận (chưa có HUB-5, token sai, rate limit) | Kiểm tra token và log Access Hub; trong lúc chờ, Redis giữ sự kiện |
| Dữ liệu rollup trống | vmalert dừng, sai -rule, vm-long hỏng | Xem :8880/api/v1/rules, log vmalert |
| Biểu đồ trễ khoảng 30 giây | VictoriaMetrics -search.latencyOffset | Bình thường |
Khi báo lỗi, đính kèm: collector -version, log JSON quanh thời điểm lỗi (có request_id), accesshub-agent diag từ máy liên quan (đã che bí mật).
15. Việc còn thiếu trước khi gọi là "production thật"
Để tránh hiểu nhầm, các điều sau chưa có và cần hoàn tất hoặc chấp nhận rủi ro:
- HUB-1 đến 18 (Access Hub phía monitoring), thiếu thì chưa có dữ liệu đầu-cuối thật.
- Windows agent và MSI (AGT-7), chữ ký Authenticode (Q3).
- Khóa ký gói và kho gói (Q2, Q3): hiện gói chưa ký.
- Image Docker, gói
.debcho collector, Helm chart (tùy chọn giai đoạn 3). - Collector:
renew; bus JetStream; giới hạn tốc độ và khử trùng inventory hiện theo từng node. - Sentinel hoặc Cluster tự động cho Redis chưa được kiểm chứng với collector.
- Kiểm thử tải lớn (1.000 đến 10.000 agent), kiểm thử lỗi cả máy và lỗi mạng giữa các máy (dev chạy một máy).
- Phê duyệt các quyết định kiến trúc đang chờ trong
docs/architecture/adr(0012 đến 0015), mức quan trọng, RTO và RPO.