本文介紹如何部署定製版 Sentry 容器,使 Sentry 控制台能夠讀取儲存在阿里雲中的應用資料。
前提條件
該功能目前處於灰階試用階段,請通過工單申請。
已有可用的 Sentry 自建環境,或具備部署 Sentry 服務的能力。
已安裝 Docker 和 Docker Compose。
背景資訊
原生 Sentry 服務的資料讀取鏈路依賴 ClickHouse 作為事件儲存、PostgreSQL 作為中繼資料存放區。為實現從 SLS 讀取資料,需要替換以下兩個核心組件:
組件 | 原始功能 | 定製版功能 |
Sentry Web | 從 PostgreSQL 讀取 Group、Nodestore 等資料 | 將部分資料來源重新導向至 SLS |
Snuba API | 從 ClickHouse 查詢事件數目據 | 將查詢引擎切換至 SLS |
定製版容器僅修改資料讀取邏輯,不影響 Sentry 控制台的介面和互動體驗。
步驟一:擷取定製版容器鏡像
阿里雲提供了適配 SLS 的定製版 Sentry 容器鏡像。
組件 | 鏡像地址 |
Sentry Web(SLS 定製版) |
|
Snuba API(SLS 定製版) |
|
步驟二:配置 SLS 訪問憑證
定製版容器需要訪問 SLS 讀取資料,需要配置 AccessKey 憑證。
建立 RAM 使用者並授權
登入 RAM 控制台,建立一個 RAM 使用者。
為該使用者授予以下許可權:
AliyunLogReadOnlyAccess(Log Service唯讀許可權)。
建立 AccessKey 並記錄 AccessKey ID 和 AccessKey Secret。
重要 建議使用 RAM 使用者的 AccessKey,避免使用主帳號 AccessKey。
步驟三:配置環境變數
在 Sentry 服務根目錄的 .env 檔案中添加以下配置:
# RUM 鏡像配置
SENTRY_RUM_IMAGE=sls-registry.cn-hangzhou.cr.aliyuncs.com/sentry/sentry:25.9.0-rum-251230
SNUBA_RUM_IMAGE=sls-registry.cn-hangzhou.cr.aliyuncs.com/sentry/snuba:25.9.0-rum-251230
SENTRY_RUM_BIND=9001
# SLS 配置
SLS_ENDPOINT=<endpoint>
SLS_ACCESS_KEY_ID=<your_access_key_id>
SLS_ACCESS_KEY_SECRET=<your_access_key_secret>
SLS_PROJECT=<your_sls_project>
SLS_LOGSTORE=logstore-rum
SLS_TTL=30
ENABLE_SLS_NODESTORE=true
USE_SLS_GROUP_STORAGE=true
參數說明
參數 | 說明 | 樣本 |
SLS_ENDPOINT | SLS 服務訪問網域名稱 |
|
SLS_ACCESS_KEY_ID | RAM 使用者 AccessKey ID |
|
SLS_ACCESS_KEY_SECRET | RAM 使用者 AccessKey Secret |
|
SLS_PROJECT | SLS Project 名稱(需要在控制台擷取RUM Service底層儲存的project) |
|
SLS_LOGSTORE | SLS Logstore 名稱,固定值 |
|
SLS_TTL | 資料查詢天數 |
|
ENABLE_SLS_NODESTORE | 啟用 SLS 儲存事件詳情 |
|
USE_SLS_GROUP_STORAGE | 啟用 SLS 儲存 Issue 彙總資訊 |
|
步驟四:建立 Docker Compose 覆蓋配置
在 Sentry 服務根目錄建立 docker-compose.override.yml 檔案:
services:
# ============================================
# Snuba API - RUM 版本
# ============================================
snuba-api-rum:
restart: unless-stopped
image: "${SNUBA_RUM_IMAGE}"
depends_on:
clickhouse:
condition: service_healthy
kafka:
condition: service_healthy
redis:
condition: service_healthy
environment:
SNUBA_SETTINGS: self_hosted
CLICKHOUSE_HOST: clickhouse
DEFAULT_BROKERS: "kafka:9092"
REDIS_HOST: redis
UWSGI_MAX_REQUESTS: "10000"
UWSGI_DISABLE_LOGGING: "true"
SENTRY_EVENT_RETENTION_DAYS:
# 配置
SLS_ENDPOINT: ${SLS_ENDPOINT:-cn-chengdu.log.aliyuncs.com}
SLS_ACCESS_KEY_ID: ${SLS_ACCESS_KEY_ID:-}
SLS_ACCESS_KEY_SECRET: ${SLS_ACCESS_KEY_SECRET:-}
SLS_PROJECT: ${SLS_PROJECT:-}
SLS_LOGSTORE: ${SLS_LOGSTORE:-logstore-rum}
SLS_TTL: ${SLS_TTL:-30}
USE_SLS_FOR_REFERRERS: sls
healthcheck:
test:
- "CMD"
- "/bin/bash"
- "-c"
- 'exec 3<>/dev/tcp/127.0.0.1/1218 && echo -e "GET /health HTTP/1.1\r\nhost: 127.0.0.1\r\n\r\n" >&3 && grep ok -s -m 1 <&3'
interval: "$HEALTHCHECK_INTERVAL"
timeout: "$HEALTHCHECK_TIMEOUT"
retries: $HEALTHCHECK_RETRIES
start_period: "$HEALTHCHECK_START_PERIOD"
# ============================================
# Web 服務 - RUM 版本
# ============================================
web-rum:
restart: unless-stopped
image: "${SENTRY_RUM_IMAGE}"
depends_on:
redis:
condition: service_healthy
kafka:
condition: service_healthy
pgbouncer:
condition: service_healthy
memcached:
condition: service_started
smtp:
condition: service_started
seaweedfs:
condition: service_started
snuba-api-rum:
condition: service_healthy
symbolicator:
condition: service_started
entrypoint: "/etc/sentry/entrypoint.sh"
command: ["run", "web"]
ulimits:
nofile:
soft: 4096
hard: 4096
environment:
PYTHONUSERBASE: "/data/custom-packages"
SENTRY_CONF: "/etc/sentry"
SNUBA: "http://snuba-api-rum:1218"
VROOM: "http://vroom:8085"
DEFAULT_CA_BUNDLE: "/etc/ssl/certs/ca-certificates.crt"
REQUESTS_CA_BUNDLE: "/etc/ssl/certs/ca-certificates.crt"
GRPC_DEFAULT_SSL_ROOTS_FILE_PATH_ENV_VAR: "/etc/ssl/certs/ca-certificates.crt"
COMPOSE_PROFILES:
SENTRY_EVENT_RETENTION_DAYS:
SENTRY_MAIL_HOST:
SENTRY_MAX_EXTERNAL_SOURCEMAP_SIZE:
# 配置
SLS_ENDPOINT: ${SLS_ENDPOINT:-cn-chengdu.log.aliyuncs.com}
SLS_ACCESS_KEY_ID: ${SLS_ACCESS_KEY_ID:-}
SLS_ACCESS_KEY_SECRET: ${SLS_ACCESS_KEY_SECRET:-}
SLS_PROJECT: ${SLS_PROJECT:-}
SLS_LOGSTORE: ${SLS_LOGSTORE:-logstore-rum}
SLS_TTL: ${SLS_TTL:-30}
ENABLE_SLS_NODESTORE: ${ENABLE_SLS_NODESTORE:-true}
USE_SLS_GROUP_STORAGE: ${USE_SLS_GROUP_STORAGE:-true}
volumes:
- "sentry-data:/data"
- "./sentry:/etc/sentry"
- "./geoip:/geoip:ro"
- "./certificates:/usr/local/share/ca-certificates:ro"
healthcheck:
test:
- "CMD"
- "/bin/bash"
- "-c"
- 'exec 3<>/dev/tcp/127.0.0.1/9000 && echo -e "GET /_health/ HTTP/1.1\r\nhost: 127.0.0.1\r\n\r\n" >&3 && grep ok -s -m 1 <&3'
interval: "$HEALTHCHECK_INTERVAL"
timeout: "$HEALTHCHECK_TIMEOUT"
retries: $HEALTHCHECK_RETRIES
start_period: "$HEALTHCHECK_START_PERIOD"
# ============================================
# Nginx - 雙連接埠配置
# ============================================
nginx:
ports:
- "$SENTRY_BIND:80/tcp"
- "${SENTRY_RUM_BIND:-9001}:81/tcp"
depends_on:
web:
condition: service_healthy
restart: true
web-rum:
condition: service_healthy
restart: true
relay:
condition: service_healthy
restart: true步驟五:配置 Sentry Python 檔案
修改 sentry/sentry.conf.example.py 檔案,在檔案末尾追加以下配置:
# ---------------------------------------------------------
# RUM NodeStore Configuration
# ---------------------------------------------------------
import os
# 擷取環境變數配置
_enable_sls_nodestore = os.environ.get("ENABLE_SLS_NODESTORE", "").lower() in ("true", "1", "yes")
_use_sls_group_storage = os.environ.get("USE_SLS_GROUP_STORAGE", "").lower() in ("true", "1", "yes")
_sls_endpoint = os.environ.get("SLS_ENDPOINT", "")
_sls_access_key_id = os.environ.get("SLS_ACCESS_KEY_ID", "")
_sls_access_key_secret = os.environ.get("SLS_ACCESS_KEY_SECRET", "")
_sls_project = os.environ.get("SLS_PROJECT", "")
_sls_nodestore_logstore = os.environ.get("SLS_LOGSTORE", "logstore-rum")
_sls_ttl = int(os.environ.get("SLS_TTL", "30") or 30)
if _enable_sls_nodestore and _sls_endpoint and _sls_access_key_id and _sls_access_key_secret and _sls_project:
SENTRY_NODESTORE = "sentry_nodestore_sls.SLSNodeStorage"
SENTRY_NODESTORE_OPTIONS = {
"endpoint": _sls_endpoint,
"access_key_id": _sls_access_key_id,
"access_key_secret": _sls_access_key_secret,
"project": _sls_project,
"logstore": _sls_nodestore_logstore,
"compression": True,
"retry_attempts": 3,
"retry_delay": 0.5,
"default_ttl_days": _sls_ttl or None,
}
print("=" * 70)
print("==> NodeStore: SLS (Direct Mode ONLY)")
print(f"==> SLS Endpoint: {_sls_endpoint}")
print(f"==> SLS Project: {_sls_project}")
print(f"==> SLS Logstore: {_sls_nodestore_logstore}")
print(f"==> TTL (days): {SENTRY_NODESTORE_OPTIONS['default_ttl_days']}")
print("=" * 70)
else:
print("=" * 70)
print("==> NodeStore: Django (Database)")
print("==> Data stored in PostgreSQL")
if not _enable_sls_nodestore:
print("==> Info: Set ENABLE_SLS_NODESTORE=true in .env.custom to use SLS")
elif not _sls_endpoint or not _sls_access_key_id:
print("==> Warning: SLS credentials not configured in .env.custom")
print("=" * 70)
# ---------------------------------------------------------
# RUM Group Search Configuration
# ---------------------------------------------------------
if _use_sls_group_storage and _sls_endpoint and _sls_access_key_id and _sls_access_key_secret and _sls_project:
SENTRY_SEARCH = "sentry.search.sls.backend.SLSGroupSearchBackend"
print("=" * 70)
print("==> Search Backend: SLS Group Search")
print(f"==> Backend: {SENTRY_SEARCH}")
print("=" * 70)
else:
print("=" * 70)
print("==> Search Backend: Snuba (Default)")
print(f"==> Backend: {SENTRY_SEARCH}")
if not _use_sls_group_storage:
print("==> Info: Set USE_SLS_GROUP_STORAGE=true to use SLS Group Search")
print("=" * 70)
# 清理臨時變數
del _enable_sls_nodestore, _use_sls_group_storage, _sls_endpoint, _sls_access_key_id, _sls_access_key_secret
del _sls_project, _sls_nodestore_logstore步驟六:配置 Nginx 雙連接埠
修改 nginx.conf 檔案,添加 RUM 版服務的連接埠監聽,支援雙環境訪問(連接埠 80 → 標準版,連接埠 81 → 阿里雲版):
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
reset_timedout_connection on;
keepalive_timeout 75s;
gzip off;
server_tokens off;
server_names_hash_bucket_size 64;
types_hash_max_size 2048;
types_hash_bucket_size 64;
client_body_buffer_size 64k;
client_max_body_size 100m;
proxy_http_version 1.1;
proxy_redirect off;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
proxy_next_upstream error timeout invalid_header http_502 http_503 non_idempotent;
proxy_next_upstream_tries 2;
# Docker default address pools
set_real_ip_from 172.17.0.0/16;
set_real_ip_from 172.18.0.0/16;
set_real_ip_from 172.19.0.0/16;
set_real_ip_from 172.20.0.0/14;
set_real_ip_from 172.24.0.0/14;
set_real_ip_from 172.28.0.0/14;
set_real_ip_from 192.168.0.0/16;
set_real_ip_from 10.0.0.0/8;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
proxy_set_header Connection '';
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Request-Id $request_id;
proxy_read_timeout 30s;
proxy_send_timeout 5s;
upstream relay {
server relay:3000;
keepalive 2;
}
# 標準版 Sentry
upstream sentry {
server web:9000;
keepalive 2;
}
# RUM 版 Sentry
upstream sentry_rum {
server web-rum:9000;
keepalive 2;
}
# RUM 資料轉寄到阿里雲 RUM(僅在啟用鏡像雙寫時使用)
upstream rum_forwarder {
# endpoint
server <endpoint>:80;
keepalive 2;
}
# ============================================
# RUM 轉寄路徑映射
# 根據 Sentry Project ID 映射到對應的阿里雲 RUM 服務
# ============================================
map $request_uri $forwarder_path {
# 預設轉寄路徑(請替換為實際的 workspace_name 和 rum_service_id)
default /rum/sentry/<workspace_name>/<rum_service_id>;
# 按專案 ID 配置不同的轉寄路徑樣本:
# "~^/api/1/envelope/" /rum/sentry/<workspace_name>/<rum_service_id_for_project_1>;
# "~^/api/2/envelope/" /rum/sentry/<workspace_name>/<rum_service_id_for_project_2>;
}
# 標準版 Sentry - 連接埠 80
server {
listen 80;
location /api/store/ {
proxy_pass http://relay;
}
location ~ ^/api/[1-9]\d*/ {
proxy_pass http://relay;
mirror /rum_mirror;
mirror_request_body on;
}
location = /rum_mirror {
internal;
proxy_pass http://rum_forwarder$forwarder_path$request_uri;
# endpoint
proxy_set_header Host <endpoint>;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Request-Id $request_id;
proxy_set_header Connection '';
proxy_read_timeout 5s;
proxy_send_timeout 5s;
proxy_connect_timeout 5s;
proxy_ignore_client_abort on;
}
location ^~ /api/0/relays/ {
proxy_pass http://relay;
}
location ^~ /js-sdk/ {
root /var/www/;
add_header Access-Control-Allow-Origin *;
}
location / {
proxy_pass http://sentry;
}
location /_assets/ {
proxy_pass http://sentry/_static/dist/sentry/;
proxy_hide_header Content-Disposition;
}
location /_static/ {
proxy_pass http://sentry;
proxy_hide_header Content-Disposition;
}
}
# RUM 版 Sentry - 連接埠 81
server {
listen 81;
location /api/store/ {
proxy_pass http://relay;
}
location ~ ^/api/[1-9]\d*/ {
proxy_pass http://relay;
mirror /rum_mirror;
mirror_request_body on;
}
location = /rum_mirror {
internal;
proxy_pass http://rum_forwarder$forwarder_path$request_uri;
# endpoint
proxy_set_header Host <endpoint>;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Request-Id $request_id;
proxy_set_header Connection '';
proxy_read_timeout 5s;
proxy_send_timeout 5s;
proxy_connect_timeout 5s;
proxy_ignore_client_abort on;
}
location ^~ /api/0/relays/ {
proxy_pass http://relay;
}
location ^~ /js-sdk/ {
root /var/www/;
add_header Access-Control-Allow-Origin *;
}
location / {
proxy_pass http://sentry_rum;
}
location /_assets/ {
proxy_pass http://sentry_rum/_static/dist/sentry/;
proxy_hide_header Content-Disposition;
}
location /_static/ {
proxy_pass http://sentry_rum;
proxy_hide_header Content-Disposition;
}
}
}步驟七:啟動服務
執行以下命令啟動服務:
docker compose -f docker-compose.yml -f docker-compose.override.yml up -d查看服務狀態:
docker compose ps確認 web-rum 和 snuba-api-rum 容器狀態為 Up (healthy)。
步驟八:驗證讀取功能
訪問 RUM 版 Sentry 控制台:
http://<your-host>:9001。進入已建立的專案,查看 Issues 列表。
確認是否能正常展示從 SLS 讀取的錯誤和事件數目據。
若 Issues 列表為空白,請檢查:
資料寫入是否正常。
SLS 訪問憑證是否正確配置。
容器日誌是否有錯誤資訊
查看容器日誌:
docker compose logs -f web-rum docker compose logs -f snuba-api-rum
訪問地址
環境 | 訪問地址 | 說明 |
標準版 Sentry |
| 官方鏡像,資料存放區在 ClickHouse |
RUM 版 Sentry |
| 定製版鏡像,資料存放區在 SLS |
常見問題
Q:替換定製版容器後,Sentry 控制台的功能是否有影響?
A:定製版容器僅修改資料讀取邏輯,控制台的介面、互動和功能與原生版本一致。
Q:是否支援同時讀取 ClickHouse 和 SLS 的資料?
A:目前的版本不支援混合讀取。定製版容器啟用後,所有事件數目據均從 SLS 讀取。
Q:如何復原到原生 Sentry 容器?
A:將 web-rum 和 snuba-api-rum 服務停止,使用標準版 Sentry(連接埠 9000)即可。
SLS 中的資料保留多長時間?
A:資料保留時間預設 30 天。