MinIO Webhook机制访问日志记录
·
MinIO 的 “将事件发布至 Webhook” 功能简介
MinIO 的 “将事件发布至 Webhook” 功能,简单来说就是 对象存储里的事件通知机制。它的作用是让 MinIO 在特定操作发生时,自动通知你的外部系统(例如服务端 API、微服务、自动化流程等)。
MinIO 的 “将事件发布至 Webhook” 功能,简单来说就是 对象存储里的事件通知机制。它的作用是让 MinIO 在特定操作发生时,自动通知你的外部系统(例如服务端 API、微服务、自动化流程等)。
1. 基本概念
-
事件(Event):对象存储中的操作,如:
s3:ObjectCreated:*→ 对象创建(上传/复制)s3:ObjectRemoved:*→ 对象删除s3:ObjectAccessed:*→ 对象被访问(取决于配置)
-
Webhook:HTTP 接口(URL),MinIO 将事件信息以 POST 请求的方式发送给它。
-
用途:实现 实时响应、自动化处理和系统联动。
2. 作用场景
-
自动处理上传文件
- 用户上传文件到 MinIO → Webhook 收到事件 → 后端服务自动处理文件(如转码、生成缩略图)。
-
实时同步
- 上传/删除对象时,触发 Webhook 将操作信息同步到数据库或其他存储系统。
-
告警与监控
- 对特定操作(如删除敏感文件)触发 Webhook → 通知运维系统或发送 Slack/钉钉告警。
-
事件驱动架构(EDA)
- MinIO 作为事件源,将对象操作事件推送到微服务或消息队列,实现事件驱动设计。
3. 工作流程示例
用户上传文件 myphoto.jpg
│
▼
MinIO 触发事件 s3:ObjectCreated:Put
│
▼
POST 请求发送到 Webhook URL
│
▼
Web 服务收到 JSON payload
│
▼
自动处理(转码、入库、推送通知等)
Webhook payload 示例:
{
"version": "1",
"deploymentid": "7e137b2a-f438-44cb-91dc-58148d945542",
"time": "2026-05-20T03:55:23.858364371Z",
"event": "",
"trigger": "incoming",
"api": {
"name": "GetObject",
"bucket": "bucket",
"object": "repo.go",
"status": "OK",
"statusCode": 200,
"rx": 0,
"tx": 68,
"txHeaders": 524,
"timeToFirstByte": "1443873ns",
"timeToFirstByteInNS": "1443873",
"timeToResponse": "1503092ns",
"timeToResponseInNS": "1503092"
},
"remotehost": "222.173.127.34",
"requestID": "18B129D54B57D454",
"userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36 Edg/148.0.0.0",
"requestPath": "/bucket/e35f6b7b-0661-11f1-85ea-0242ac150003/repo.go",
"requestHost": "部署域名",
"requestQuery": {
"X-Amz-Algorithm": "AWS4-HMAC-SHA256",
"X-Amz-Credential": "minioadmin/20260520/r/s3/aws4_request",
"X-Amz-Date": "20260520T035518Z",
"X-Amz-Expires": "86400",
"X-Amz-Signature": "640853ac793171f59c002b8bd3052d73016866df484c5c32c0fc1d89b7487d03",
"X-Amz-SignedHeaders": "host",
"response-content-disposition": "attachment"
},
"requestHeader": {
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
"Accept-Encoding": "gzip, deflate, br, zstd",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
"Connection": "keep-alive",
"Cookie": "Hm_lvt_3f8ed946d171f676297a0",
"Sec-Ch-Ua": "\"Chromium\";v=\"148\", \"Microsoft Edge\";v=\"148\", \"Not/A)Brand\";v=\"99\"",
"Sec-Ch-Ua-Mobile": "?0",
"Sec-Ch-Ua-Platform": "\"Windows\"",
"Sec-Fetch-Dest": "document",
"Sec-Fetch-Mode": "navigate",
"Sec-Fetch-Site": "none",
"Sec-Fetch-User": "?1",
"Upgrade-Insecure-Requests": "1",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36 Edg/148.0.0.0",
"X-Amz-Signature-Age": "5858"
},
"responseHeader": {
"Accept-Ranges": "bytes",
"Content-Disposition": "attachment",
"Content-Length": "68",
"Content-Type": "application/octet-stream",
"ETag": "b338e1f20d5aa78824bb8e53d1cbd8fe",
"Last-Modified": "Tue, 10 Feb 2026 09:23:12 GMT",
"Server": "MinIO",
"Strict-Transport-Security": "max-age=31536000; includeSubDomains",
"Vary": "Origin,Accept-Encoding",
"X-Amz-Id-2": "cd12db15ea11a38dd85b2ac1cd0e7672a49d94ae8535078abcb6d6bd756cbab2",
"X-Amz-Request-Id": "18B129D54B57D454",
"X-Content-Type-Options": "nosniff",
"X-Ratelimit-Limit": "26413",
"X-Ratelimit-Remaining": "26413",
"X-Xss-Protection": "1; mode=block"
},
"tags": {
"GetObject": "name=repo.go,pool=1,set=1"
},
"accessKey": "accessKey"
}
4. 配置方式
在 MinIO 里,事件通知可通过以下方式配置:控制台 UI
minio 日志配置

部署接收日志服务
services:
minio-webhook:
image: registry.cn-qingdao.aliyuncs.com/lys_ns/app:minio-webhook
container_name: minio-webhook
ports:
- "8080:8080"
volumes:
- ./app:/app
- ./logs:/var/log/minio-webhook
restart: unless-stopped
app.py
import json
import logging
import os
from datetime import datetime, timezone
from flask import Flask, request
LOG_DIR = os.getenv("WEBHOOK_LOG_DIR", "/var/log/minio-webhook")
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("minio-webhook")
class DailyLogHandler(logging.FileHandler):
def __init__(self, log_dir):
self.log_dir = log_dir
os.makedirs(log_dir, exist_ok=True)
super().__init__(self._filename())
def _filename(self):
return os.path.join(self.log_dir, f"events-{datetime.now():%Y-%m-%d}.log")
def emit(self, record):
if self.baseFilename != self._filename():
self.close()
self.baseFilename = self._filename()
self.stream = self._open()
super().emit(record)
fh = DailyLogHandler(LOG_DIR)
fh.setFormatter(logging.Formatter("%(asctime)s %(message)s"))
logger.addHandler(fh)
app = Flask(__name__)
@app.route("/minio-webhook", methods=["POST"])
def minio_webhook():
event = request.json
log_entry = json.dumps({
"time": datetime.now(timezone.utc).isoformat(),
"requestPath": event.get("requestPath"),
"remotehost": event.get("remotehost"),
})
logger.info("%s", log_entry)
return "OK", 200
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080)

更多推荐




所有评论(0)