Traefik 在 Kubernetes 中使用 MiddlewareTCP CRD 配置 TCP 流量中间件
MiddlewareTCP 是 Traefik 中 TCP 中间件在 Kubernetes CRD 体系下的落地形态,它让用户以 kubectl apply 声明式资源的方式,在 IngressRouteTCP 的每条 TCP 路由上挂载 ipAllowList(来源 IP 白名单)、inFlightConn(并发连接数限制)等中间件,实现对经过 Traefik 的四层流量进行安全与限流控制。读完本文,你将掌握 MiddlewareTCP 资源的结构与注册前提、如何在 IngressRouteTCP 中正确引用它,以及它与 Provider Namespace、Kubernetes Namespace 之间的关系。
什么是 MiddlewareTCP
在 Traefik 的动态配置模型中,中间件被挂载到路由上,用于在流量被转发给后端服务之前对请求/连接进行加工处理(如做鉴权、改写头、限流等)。对于 TCP(四层)流量,Traefik 提供了一套独立的 TCP 中间件,其完整概念与列表参见 TCP Middleware Overview。
MiddlewareTCP 正是这套 TCP 中间件的 CRD(Custom Resource Definition)实现。它把 TCP 中间件的能力以 Kubernetes 原生对象的形式暴露出来,结构定义在 middlewaretcp.go:
type MiddlewareTCP struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata"`
Spec MiddlewareTCPSpec `json:"spec"`
}
type MiddlewareTCPSpec struct {
// InFlightConn defines the InFlightConn middleware configuration.
InFlightConn *dynamic.TCPInFlightConn `json:"inFlightConn,omitempty"`
// Deprecated: please use IPAllowList instead.
IPWhiteList *dynamic.TCPIPWhiteList `json:"ipWhiteList,omitempty"`
// IPAllowList defines the IPAllowList middleware configuration.
IPAllowList *dynamic.TCPIPAllowList `json:"ipAllowList,omitempty"`
}
从源码结构可以清晰看到,MiddlewareTCP 的 spec 目前支持三个子块:
spec 字段 |
作用 | 状态 |
|---|---|---|
ipAllowList.sourceRange |
根据客户端 IP 允许/拒绝连接(IP 白名单) | 推荐使用 |
inFlightConn.amount |
限制单个 IP 允许的最大并发连接数 | 可用 |
ipWhiteList.sourceRange |
IP 白名单的旧命名 | 已废弃,请改用 ipAllowList |
需要特别留意的是:这三个子块在类型定义上直接复用了动态配置结构体 dynamic.TCPInFlightConn、dynamic.TCPIPWhiteList 与 dynamic.TCPIPAllowList(见 tcp_middlewares.go)。也就是说,CRD 只是把静态/文件配置中的同一条 TCP 中间件定义换成了 Kubernetes 对象的写法,底层语义完全一致。
前置条件:先安装 Traefik Kubernetes CRDs
在创建任何 MiddlewareTCP 对象之前,必须先在你的 Kubernetes 集群中安装 Traefik 的 Kubernetes CRD 定义。安装后,集群才会注册 MiddlewareTCP 这一 kind,以及其他 Traefik 专属资源(如 IngressRouteTCP、IngressRouteUDP、TLSOption 等)。
安装 CRD 通常通过
kubectl apply应用 Traefik 官方提供的 CRD 清单完成,具体文件与完整命令见当前仓库的 Kubernetes 参考文档docs/content/reference/install-configuration/providers/kubernetes-crd.md。仓库中也包含可直接用于集成测试的 CRD 清单,例如 01-traefik-crd.yml 与 00-experimental-v1.5.1.yml,可作为学习对象结构时的参考。
CRD 一旦注册,Kubernetes API Server 就会对 MiddlewareTCP 对象执行 OpenAPI 校验,例如 inFlightConn.amount 的字段约束要求最小值不小于 0(对应源码中的 +kubebuilder:validation:Minimum=0 标注),从源头避免写入非法配置。
配置示例:MiddlewareTCP + IngressRouteTCP
下面的示例展示了 TCP 中间件在 Kubernetes 下的完整闭环:先声明一个只允许本机与内网来源 IP 连接的 MiddlewareTCP,再通过 IngressRouteTCP 把它挂到一条基于 SNI 匹配的 TCP 路由上。
# MiddlewareTCP:定义中间件本身
apiVersion: traefik.io/v1alpha1
kind: MiddlewareTCP
metadata:
name: ipallowlist
spec:
ipAllowList:
sourceRange:
- 127.0.0.1/32
- 192.168.1.7
# IngressRouteTCP:在 TCP 路由上引用中间件
apiVersion: traefik.io/v1alpha1
kind: IngressRouteTCP
metadata:
name: ingressroutebar
spec:
entryPoints:
- web
routes:
- match: HostSNI(`example.com`)
kind: Rule
services:
- name: whoami
port: 80
middlewares:
- name: ipallowlist
namespace: foo
解析这个示例,可以梳理出几条关键信息:
- 资源分组与版本:两类资源均属于
traefik.io/v1alpha1API 组。IngressRouteTCP的routes[].match使用HostSNI(...)表达式,这也是 TCP 路由最典型的匹配方式(四层没有 HTTP Host 头,只能基于 TLS SNI 或原始 TCP 属性路由)。 - 中间件通过名称引用:
middlewares数组里的每一项是一个ObjectReference,包含name与可选的namespace两个字段(对应 objectreference.go)。引用时namespace指的是 MiddlewareTCP 资源所在的 Kubernetes Namespace。 - 命名空间默认值:省略
namespace时,Traefik 会默认把它解析为与当前IngressRouteTCP同 Namespace 下的同名中间件。
跨 Provider 命名空间提示
MiddlewareTCP 的文档专门强调了一个极易混淆的概念:Kubernetes Namespace 与 Provider Namespace 不是一回事。Kubernetes 资源引用中的 namespace 字段,含义始终是该资源所在集群里的命名空间;而 Provider Namespace 是 Traefik Provider 体系内的概念——它表示中间件定义来自哪个 Provider(例如 foo@docker 表示来自 Docker Provider 的 foo 中间件)。
因此请注意这两条规则:
- 当中间件定义来自其他 Provider(如文件、Docker)时,在资源引用中指定
namespace没有意义,该字段会被忽略。因为其他 Provider 根本没有 Kubernetes 命名空间的概念,此时只需在引用名后面用@标注来源 Provider。 - 当你要引用 CRD Provider 自己管理的 Middleware 时,必须把资源所在的 Kubernetes Namespace 拼进资源名中——因为 Traefik 在内部处理时会自动追加 namespace。从实现上看,CRD Provider 在构建中间件键时调用
makeMiddlewareTCPKeys(见 kubernetes_tcp.go),内部通过resolveReference结合 IngressRoute 自身所在的 namespace 与跨命名空间策略(CrossProviderNamespaces/AllowCrossNamespace)解析出形如<namespace>-<name>的中间件引用。
这种命名空间的内部自动拼接,正是示例中 MiddlewareTCP 名为 ipallowlist、被引用时却需要 namespace: foo(或名称形如 foo-ipallowlist)的根本原因。
支持的具体中间件与用法
MiddlewareTCP 对应的 TCP 中间件目前只有两类(一个已废弃的旧名等价类),两者的详细配置说明如下。更多场景的组合参考仍以 TCP Middleware Overview 为准。
| 中间件 | 用途 | 领域 |
|---|---|---|
| InFlightConn | 限制允许的最大并发连接数,防止服务被高负载压垮 | 安全、请求生命周期 |
| IPAllowList | 限制允许的客户端 IP | 安全、请求生命周期 |
IPAllowList:按客户端 IP 过滤连接
iPAllowList 依据客户端 IP 决定是否放行连接,典型用法是只允许可信来源(如公司出口 IP、运维网段)访问数据库、内部 RPC 等不对外暴露的 TCP 服务。
apiVersion: traefik.io/v1alpha1
kind: MiddlewareTCP
metadata:
name: test-ipallowlist
spec:
ipAllowList:
sourceRange:
- 127.0.0.1/32
- 192.168.1.7
| 字段 | 说明 | 默认值 | 是否必填 |
|---|---|---|---|
sourceRange |
允许的 IP 列表;通过 CIDR 记法支持 IP 段(如 192.168.1.0/24),也支持不带掩码的单 IP(如 192.168.1.7,等价于 /32 或 /128) |
无 | 是 |
该中间件的运行期实现位于 ip_allowlist.go,其构造器 New 接收 dynamic.TCPIPAllowList 配置,与 CRD 中 spec.ipAllowList 解出的配置一一对应。
废弃提示:旧版本中该能力叫
ipWhiteList(见 ip_whitelist.go 与类型定义中的Deprecated注释)。新配置请一律使用ipAllowList,两者功能等价。
InFlightConn:限制并发连接数
inFlightConn 用于主动防止后端服务被瞬时大流量压垮:当已建立的并发连接数达到上限时,新的连接会被中间件直接关闭。
apiVersion: traefik.io/v1alpha1
kind: MiddlewareTCP
metadata:
name: test-inflightconn
spec:
inFlightConn:
amount: 10
| 字段 | 说明 | 默认值 | 是否必填 |
|---|---|---|---|
amount |
允许的最大并发连接数。当已有 amount 条连接打开时,中间件会关闭新来的连接 |
0 | 是 |
amount 的最小取值在 CRD 校验层被约束为 0(源码 +kubebuilder:validation:Minimum=0)。在运行期,inflight_conn.go 的 New 会把 config.Amount 装载进计数器的 maxConnections 字段,逐连接维护计数并在超限时拒绝服务。
与其他配置来源的关系
值得强调的是,MiddlewareTCP 并非唯一声明 TCP 中间件的途径。同一套配置在 Traefik 的不同 Provider 下有等价的写法(详见 TCP Middleware Overview):
- 静态/动态配置文件:在
tcp.middlewares.<name>.ipAllowList或tcp.middlewares.<name>.inFlightConn下声明(TOML/YAML); - 容器标签:通过
traefik.tcp.middlewares.foo-ip-allowlist.ipallowlist.sourcerange=...之类的标签声明并挂载; - Consul Catalog:以
traefik.tcp.middlewares...为前缀的 Tag 声明; - Kubernetes:即以本文的
MiddlewareTCP+IngressRouteTCP方式声明。
无论走哪条路径,最终都会被汇聚为同一份 dynamic.TCPMiddleware 动态配置(类型定义见 tcp_middlewares.go),因此 MiddlewareTCP 学到的一切字段语义,都可以平移到其他 Provider 场景中使用。这也解释了为何其 spec 能直接复用 dynamic 包中的结构体类型。
总结
MiddlewareTCP是 Traefik TCP 中间件的 CRD 形态,前置条件是集群中已安装 Traefik Kubernetes CRDs;- 其
spec当前支持ipAllowList、inFlightConn与已废弃的ipWhiteList,分别对应来源 IP 白名单与并发连接数限制两类安全能力; - 在
IngressRouteTCP.routes[].middlewares中通过name+namespace(可选)引用;namespace指 Kubernetes Namespace,与其他 Provider 无关,引用跨 Provider 的中间件时该字段会被忽略; - 由于 Traefik 内部自动追加 Namespace,CRD Provider 场景下的中间件引用名实际会被解析为
<namespace>-<name>的形式,理解这一点有助于排查"引用不到中间件"的常见问题。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00