限定 gateway 发布只处理 jvapi 规则

This commit is contained in:
hy 2026-04-23 17:01:03 +08:00
parent a059e76742
commit 3d66ed45ac
4 changed files with 75 additions and 0 deletions

View File

@ -103,6 +103,7 @@ TENCENT_SECRET_ID=
TENCENT_SECRET_KEY=
GATEWAY_CLB_LOAD_BALANCER_ID=
GATEWAY_CLB_LISTENER_IDS=
GATEWAY_CLB_ALLOWED_DOMAINS=
GATEWAY_CLB_POLL_SECONDS=2
GATEWAY_CLB_TASK_TIMEOUT_SECONDS=120
GATEWAY_CLB_DRAIN_SECONDS=0

View File

@ -118,6 +118,8 @@ TENCENT_SECRET_KEY = env_str("TENCENT_SECRET_KEY", "")
GATEWAY_CLB_LOAD_BALANCER_ID = env_str("GATEWAY_CLB_LOAD_BALANCER_ID", "")
# gateway 可能同时挂在 HTTP / HTTPS 等多个监听器下,这里统一允许逗号分隔配置。
GATEWAY_CLB_LISTENER_IDS = env_str_list("GATEWAY_CLB_LISTENER_IDS", [])
# gateway 发布时只保护这些域名规则;留空表示 listener 下匹配到的规则全部处理。
GATEWAY_CLB_ALLOWED_DOMAINS = env_str_list("GATEWAY_CLB_ALLOWED_DOMAINS", [])
# CLB 异步任务轮询间隔。
GATEWAY_CLB_POLL_SECONDS = env_float("GATEWAY_CLB_POLL_SECONDS", 2.0)
# CLB 摘流 / 恢复异步任务最长等待秒数。

View File

@ -6,6 +6,7 @@ from typing import Any
from core.config import (
DEPLOY_REGION,
GATEWAY_CLB_ALLOWED_DOMAINS,
GATEWAY_CLB_LISTENER_IDS,
GATEWAY_CLB_LOAD_BALANCER_ID,
GATEWAY_CLB_POLL_SECONDS,
@ -43,6 +44,7 @@ def gateway_clb_settings() -> dict[str, Any]:
return {
"loadBalancerId": GATEWAY_CLB_LOAD_BALANCER_ID,
"allowedDomains": list(GATEWAY_CLB_ALLOWED_DOMAINS),
"listenerIds": list(GATEWAY_CLB_LISTENER_IDS),
}
@ -193,15 +195,29 @@ def build_binding(listener: dict[str, Any], service: dict[str, Any], target: dic
return binding
def binding_allowed(binding: dict[str, Any], allowed_domains: list[str]) -> bool:
# 显式配置了允许域名后,只处理这些规则,避免发布时误伤当前不再使用的域名。
if not allowed_domains:
return True
domain = str(binding.get("domain") or "").strip().lower()
if not domain:
return False
return domain in {item.strip().lower() for item in allowed_domains if item.strip()}
def collect_service_bindings(listeners: list[dict[str, Any]], service: dict[str, Any]) -> list[dict[str, Any]]:
# 自动扫描当前实例在配置监听器里的全部绑定,避免只摘一条规则导致仍有流量漏进来。
bindings_by_key: dict[str, dict[str, Any]] = {}
allowed_domains = list(GATEWAY_CLB_ALLOWED_DOMAINS)
for listener in listeners:
for target in listener.get("Targets") or []:
if not target_matches_service(target, service):
continue
binding = build_binding(listener, service, target, rule=None)
if not binding_allowed(binding, allowed_domains):
continue
bindings_by_key[binding_key(binding)] = binding
for rule in listener.get("Rules") or []:
@ -209,6 +225,8 @@ def collect_service_bindings(listeners: list[dict[str, Any]], service: dict[str,
if not target_matches_service(target, service):
continue
binding = build_binding(listener, service, target, rule=rule)
if not binding_allowed(binding, allowed_domains):
continue
bindings_by_key[binding_key(binding)] = binding
return list(bindings_by_key.values())

View File

@ -44,6 +44,59 @@ class GatewayClbClientTests(unittest.TestCase):
class GatewayClbDiscoveryTests(unittest.TestCase):
@patch("monitors.yumi.tencent_clb.GATEWAY_CLB_ALLOWED_DOMAINS", ("jvapi.example.com",))
def test_collect_service_bindings_filters_by_allowed_domains(self) -> None:
listeners = [
{
"ListenerId": "lbl-http",
"Rules": [
{
"LocationId": "loc-a",
"Domain": "api.example.com",
"Url": "/",
"Targets": [
{
"InstanceId": "ins-gw-1",
"Port": 8080,
"Weight": 20,
"PrivateIpAddresses": ["10.0.0.1"],
}
],
},
{
"LocationId": "loc-b",
"Domain": "jvapi.example.com",
"Url": "/",
"Targets": [
{
"InstanceId": "ins-gw-1",
"Port": 8080,
"Weight": 10,
"PrivateIpAddresses": ["10.0.0.1"],
}
],
},
],
}
]
bindings = collect_service_bindings(
listeners,
{
"host": "gateway-1",
"service": "gateway",
"ip": "10.0.0.1",
"instanceId": "ins-gw-1",
"port": 8080,
},
)
self.assertEqual(
[(item["domain"], item["locationId"], item["weight"]) for item in bindings],
[("jvapi.example.com", "loc-b", 10)],
)
@patch("monitors.yumi.tencent_clb.GATEWAY_CLB_ALLOWED_DOMAINS", ())
@patch("monitors.yumi.tencent_clb.GATEWAY_CLB_LOAD_BALANCER_ID", "lb-test")
@patch("monitors.yumi.tencent_clb.GATEWAY_CLB_LISTENER_IDS", ("lbl-http", "lbl-https"))
@patch("monitors.yumi.tencent_clb.describe_gateway_targets")
@ -122,6 +175,7 @@ class GatewayClbDiscoveryTests(unittest.TestCase):
{("lbl-http", "loc-a", 20), ("lbl-http", "loc-b", 10)},
)
@patch("monitors.yumi.tencent_clb.GATEWAY_CLB_ALLOWED_DOMAINS", ())
def test_collect_service_bindings_ignores_other_targets(self) -> None:
listeners = [
{