Skip to content

Traefik(RKE2 内置)HTTP/HTTPS 配置、原理与高并发生产落地手册

  • 日期:2026-08-05
  • 环境:RKE2 v1.35.6 内置 Traefik(Rancher hardened-traefik v3.7.4,DaemonSet,hostPort 80/443),集群 uat1(192.168.122.31)
  • 内容:HTTP/HTTPS 分别如何配置 → 实现原理 → 最佳实践 → 高并发生产落地

1. 认识现状:RKE2 内置 Traefik 长什么样

bash
kubectl -n kube-system get ds rke2-traefik -o jsonpath='{.spec.template.spec.containers[0].args}'

本集群实际启动参数(精简):

text
--entryPoints.web.address=:8000/tcp            # HTTP  容器 8000 ↔ hostPort 80
--entryPoints.websecure.address=:8443/tcp      # HTTPS 容器 8443 ↔ hostPort 443
--entryPoints.traefik.address=:8080/tcp        # 管理/ping 入口(不对外)
--entryPoints.metrics.address=:9100/tcp        # Prometheus 指标入口
--api.dashboard=true --ping=true --metrics.prometheus=true
--providers.kubernetescrd                      # 监听 IngressRoute 等 CRD
--providers.kubernetescrd.ingressClass=traefik # 只认 ingress.class=traefik 注解!
--providers.kubernetesingress                  # 兼容标准 Ingress
--entryPoints.websecure.http.tls=true          # websecure 入口强制 TLS

要点:

  • DaemonSet + hostPort:每个节点 80/443 由本机 Traefik Pod 直接占用,节点 IP 即入口;
  • 两种路由资源都能用:标准 Ingress 和 Traefik CRD IngressRoute(功能更强,推荐);
  • CRD 路由必须带注解 kubernetes.io/ingress.class: traefik,否则被忽略(典型踩坑点)。

2. HTTP / HTTPS 分别配置

2.1 纯 HTTP(80)

yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: web-http
  namespace: default
  annotations:
    kubernetes.io/ingress.class: traefik
spec:
  entryPoints:
    - web                      # 只挂 80
  routes:
    - match: Host(`app.ai-ear.cn`)
      kind: Rule
      services:
        - name: web
          port: 80

2.2 HTTPS(443)——证书 Secret + IngressRoute TLS

bash
# ① 准备证书(DigiCert/自签/cert-manager 签发均可)
kubectl -n default create secret tls app-tls --cert=app.crt --key=app.key
yaml
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: web-https
  namespace: default
  annotations:
    kubernetes.io/ingress.class: traefik
spec:
  entryPoints:
    - websecure                # 只挂 443
  tls:
    secretName: app-tls        # ② 引用证书;多个域名可配多条 route + 多个 secret,按 SNI 自动选证书
  routes:
    - match: Host(`app.ai-ear.cn`)
      kind: Rule
      services:
        - name: web
          port: 80

后端 Pod 仍是明文 HTTP(集群内 TLS 终止于 Traefik),这是最常见模式;端到端加密见 5.4。

2.3 HTTP 自动跳转 HTTPS(生产必配)

方式一(推荐):入口级重定向,改 HelmChartConfig 追加参数,所有挂在 web 入口的域名统一跳转:

yaml
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
  name: rke2-traefik
  namespace: kube-system
spec:
  valuesContent: |-
    additionalArguments:
      - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
      - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
      - "--entrypoints.web.http.redirections.entrypoint.permanent=true"   # 301 永久跳转

方式二:路由级,用 redirectScheme middleware 针对单个域名跳转:

yaml
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: redirect-https
  namespace: default
spec:
  redirectScheme:
    scheme: https
    permanent: true
---
# 在 HTTP IngressRoute 的 route 上引用:
#   middlewares:
#     - name: redirect-https

2.4 收紧 TLS 安全策略(TLSOption)

yaml
apiVersion: traefik.io/v1alpha1
kind: TLSOption
metadata:
  name: default              # 固定名 default 即该命名空间的默认 TLS 策略
  namespace: default         # TLSOption 按命名空间生效,需与引用它的路由同 ns
spec:
  minVersion: VersionTLS12   # 禁掉 TLS1.0/1.1;纯内网可上 VersionTLS13
  sniStrict: true            # SNI 不匹配任何路由证书时直接拒绝
  cipherSuites:              # 仅 minVersion=TLS1.2 时有效;TLS1.3 套件不可配
    - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
    - TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
    - TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256

2.5 HSTS 与安全响应头

yaml
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
  name: security-headers
  namespace: default
spec:
  headers:
    stsSeconds: 63072000           # HSTS 2 年
    stsIncludeSubdomains: true
    stsPreload: true
    customResponseHeaders:
      X-Content-Type-Options: nosniff
      X-Frame-Options: DENY

3. 实现原理

3.1 静态配置 vs 动态配置

内容来源修改方式
静态配置entryPoints、providers、api、metrics、log启动参数(Helm chart 渲染进 DaemonSet args)HelmChartConfig/kube-system/rke2-traefik → RKE2 自动重装 chart
动态配置Router(路由匹配)、Middleware(加工)、Service(负载均衡)、TLSOptionK8s CRD(IngressRoute/Middleware/...)kubectl apply,热加载零重启

RKE2 用 HelmChart rke2-traefik 管 chart,HelmChartConfig 是官方唯一正确的自定义入口——不要直接改 DaemonSet/HelmChart,会被 RKE2 调谐覆盖。

3.2 一条请求的生命周期

text
Client ──TLS(SNI 选证书)──▶ Node:443(hostPort)──▶ Traefik 容器:8443(websecure entryPoint)
   │                                                   │
   │              ┌────────────────────────────────────┘
   │              ▼
   │      Router 匹配:Host(`app.ai-ear.cn`) && PathPrefix(`/api`)
   │      (多条命中时按 rule 长度算优先级,长的优先)
   │              │
   │              ▼
   │      Middleware 链:redirectScheme → headers → rateLimit → ...
   │              │
   │              ▼
   │      Service(加权负载均衡,默认轮询)
   │      后端列表来自 EndpointSlice——直接负载到 Pod IP,不经过 kube-proxy/ClusterIP
   │              │
   └──────────────┴──▶ 后端 Pod:80

关键点:

  • TLS 终止:证书在 Traefik 侧按 SNI 选择并解密;tls.secretName 只对引用它的路由生效,多证书共存互不影响;
  • 直连 Pod:kubernetesCRD provider 监听 EndpointSlice,Traefik 直接 RR 到 Pod,少一跳 NAT,且能感知就绪探针——未 Ready 的 Pod 自动摘流;
  • ingressClass 过滤:--providers.kubernetescrd.ingressClass=traefik 意味着 IngressRoute/Middleware 的生效范围受 kubernetes.io/ingress.class 注解控制,多 ingress 控制器共存时互不干扰;
  • 热加载:CRD 变更秒级生效,不重载进程、不断现有连接。

3.3 为什么 404 不代表故障

Traefik 收到请求但没有任何 Router 命中时返回内置 404 page not found(集群里没有任何 Ingress/IngressRoute 时访问 80/443 就是这个)——说明监听、协议栈都正常,只是没路由。判断层次:ping 8080 通 = 进程活;404 page not found = 无路由;业务 404(带应用特征) = 路由通、后端问题。

4. 最佳实践清单

  1. 统一用 IngressRoute(CRD),放弃标准 Ingress:tls 选项、middleware、灰度权重(Weighted Round Robin)只有 CRD 能完整表达;
  2. 所有 CRD 带 kubernetes.io/ingress.class: traefik 注解;
  3. 生产强制 HTTPS:入口级 301 跳转 + minVersion: VersionTLS12 + HSTS;
  4. 证书自动化:上 cert-manager(kubernetesingress provider 已开,cert-manager.io/cluster-issuer 注解的标准 Ingress 可直接签);手工证书注意 2.2 的 secret 与路由同 namespace;
  5. dashboard 不裸奔:必须 IngressRoute 显式暴露 + basicAuth/forwardAuth,用完即删(参考《uat1 集群 Traefik dashboard 访问》);
  6. 不要把管理入口(8080/9100)暴露到 web/websecure;metrics 走独立入口只给 Prometheus 抓;
  7. 变更后验证:kubectl -n kube-system port-forward <pod> 8080:8080/api/http/routers 确认路由状态 enabled

5. 高并发生产落地

5.1 入口拓扑:两种形态

形态适用要点
DaemonSet + hostPort(RKE2 默认,本集群现状)节点固定、有外部 L4 LB/VIP前面挂 F5/HAProxy/keepalived VIP,负载到所有节点 80/443;天然每节点一个实例,无单点
Deployment + Service LB云上(ELB/NLB)副本数 3+,跨 AZ 反亲和

裸金属/内网集群推荐前者:外部 LB 健康检查打 Traefik 的 ping 入口(本集群 --ping=true 在 8080,GET /ping 返回 200),LB 只把流量发给健康节点。

若 LB 是 L4(TCP)且需要真实客户端 IP:LB 侧开 PROXY protocol,Traefik 侧配置信任 LB 网段: --entrypoints.web.proxyProtocol.trustedIPs=<LB网段>--entrypoints.websecure.proxyProtocol.trustedIPs=<LB网段>,否则拿到的是 LB 的 IP,影响 rateLimit/日志/审计。

5.2 实例与资源

yaml
# HelmChartConfig valuesContent 片段
resources:
  requests:
    cpu: 500m
    memory: 512Mi
  limits:
    cpu: "2"              # 给上限但别卡死:Traefik 是纯网络 IO,突发吃 CPU
    memory: 1Gi
  • 单实例 hardened-traefik 在 2C 下约可扛 2~5 万 RPS(短连接 HTTPS 取下限,长连接/HTTP 取上限),容量规划按 50% 水位留余量;
  • Traefik 自动按 GOMAXPROCS 用满分配 CPU,不要给 100m 这种小 requests 让调度器把它挤到忙节点。

5.3 连接与超时调优(高并发核心)

yaml
# HelmChartConfig valuesContent 片段
additionalArguments:
  # ── 到后端的连接池(对性能影响最大)──
  - "--serversTransport.maxIdleConnsPerHost=500"      # 默认 200,后端少时不够,会产生大量 TIME_WAIT
  - "--serversTransport.idleConnTimeout=90s"
  - "--serversTransport.forwardingTimeouts.dialTimeout=10s"
  - "--serversTransport.forwardingTimeouts.responseHeaderTimeout=30s"
  - "--serversTransport.forwardingTimeouts.idleConnTimeout=90s"
  # ── 面向客户端侧 ──
  - "--entrypoints.web.transport.respondingTimeouts.readTimeout=0"   # 0=不限;有 SSE/WebSocket/长轮询必须为 0
  - "--entrypoints.web.transport.respondingTimeouts.writeTimeout=0"
  - "--entrypoints.web.transport.respondingTimeouts.idleTimeout=180s"  # 无 SSE 的纯短 API 可收紧到 30s
  # ── 优雅退出(滚动更新/节点维护不断流)──
  - "--entrypoints.web.transport.lifeCycle.requestAcceptGraceTimeout=10s"
  - "--entrypoints.web.transport.lifeCycle.graceTimeOut=60s"

配套的节点内核调优(hostPort 模式下调的是节点内核):

bash
# /etc/sysctl.d/99-traefik.conf(所有入口节点)
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.core.netdev_max_backlog = 65535
net.netfilter.nf_conntrack_max = 2097152          # conntrack 打满是高并发常见瓶颈
net.ipv4.ip_local_port_range = 10240 65535        # 到后端 Pod 的源端口池
net.ipv4.tcp_tw_reuse = 1
fs.file-max = 2097152
# 应用:sysctl --system;并确认 Traefik Pod ulimit nofile ≥ 65535(containerd 默认已较高)

5.4 端到端加密(可选高安全场景)

默认 Traefik→Pod 是明文。要求全链路加密时,用 ServersTransport 指定后端走 HTTPS + 信任内部 CA:

yaml
apiVersion: traefik.io/v1alpha1
kind: ServersTransport
metadata:
  name: mtls-backend
  namespace: default
spec:
  serverName: app.default.svc
  rootCAsSecrets:
    - internal-ca
  # insecureSkipVerify: true   # 应急才用,生产禁止
---
# IngressRoute service 引用:
#   services:
#     - name: web
#       port: 443
#       scheme: https
#       serversTransport: mtls-backend

代价:后端证书管理 + 后端加解密 CPU,内网高并发下一般不做。

5.5 韧性中间件(生产三件套)

本版本(v3.7.4)Middleware CRD 支持:rateLimit / inFlightReq / circuitBreaker / retry / buffering / compress / chain 等。

yaml
# ① 限流:保护后端不被突发打垮
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata: {name: api-ratelimit, namespace: default}
spec:
  rateLimit:
    average: 200          # 每秒平均 200 请求(按 sourceCriterion 维度,默认按客户端 IP)
    burst: 400
    period: 1s
---
# ② 并发闸:超过直接 503,比排队拖死强
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata: {name: api-inflight, namespace: default}
spec:
  inFlightReq:
    amount: 500
    sourceCriterion:
      requestHost: true
---
# ③ 熔断:后端 5xx 比例超阈值时快速失败
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata: {name: api-breaker, namespace: default}
spec:
  circuitBreaker:
    expression: ResponseCodeRatio(500, 600, 0, 600) > 0.30
    checkPeriod: 5s
    fallbackDuration: 15s
    recoveryDuration: 30s
---
# ④ 重试:只对幂等 GET 开
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata: {name: api-retry, namespace: default}
spec:
  retry:
    attempts: 3
    initialInterval: 100ms

chain middleware 组合后挂到路由:

yaml
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata: {name: api-chain, namespace: default}
spec:
  chain:
    middlewares:
      - {name: api-ratelimit}
      - {name: api-inflight}
      - {name: api-breaker}
      - {name: api-retry}

compress(gzip)对文本收益大,但高并发下吃 CPU——只给大响应文本接口开,别全局开。

5.6 灰度发布

IngressRoute 原生支持同一 match 下多 service 加权,做金丝雀:

yaml
routes:
  - match: Host(`app.ai-ear.cn`)
    kind: Rule
    services:
      - name: web-v1
        port: 80
        weight: 90
      - name: web-v2
        port: 80
        weight: 10        # 10% 流量进新版本

5.7 可观测性(高并发的眼睛)

  • 指标:独立入口 9100 已开,Prometheus 抓 http://<pod-ip>:9100/metrics,核心面板:
    • traefik_entrypoint_requests_total / ..._request_duration_seconds(入口 RPS、延迟)
    • traefik_service_requests_total{code=~"5.."}(按后端看 5xx)
    • traefik_entrypoint_open_connections(在途连接,配合内核参数看水位)
  • 访问日志:高并发下关闭或采样,全量 JSON 访问日志会成为磁盘/CPU 瓶颈;排障时临时开: --accesslog=true --accesslog.format=json --accesslog.filters.statuscodes=400-599(只记错误)
  • 告警:5xx 比例、P99 延迟、open_connections 接近上限、Pod CPU 超限。

5.8 滚动更新不断流

  1. 上节 lifeCycle.graceTimeOut=60s:收到 SIGTERM 后停止接新连接,等存量请求完成;
  2. 外部 LB 健康检查(8080/ping)配合:Traefik 退出期 ping 先失败,LB 提前摘流;
  3. 维护单节点时先 kubectl cordon/drain 或直接在 LB 上摘节点,再重启 Pod。

5.9 落地配置汇总(HelmChartConfig 完整示例)

yaml
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
  name: rke2-traefik
  namespace: kube-system
spec:
  valuesContent: |-
    additionalArguments:
      - "--entrypoints.web.http.redirections.entrypoint.to=websecure"
      - "--entrypoints.web.http.redirections.entrypoint.scheme=https"
      - "--entrypoints.web.http.redirections.entrypoint.permanent=true"
      - "--serversTransport.maxIdleConnsPerHost=500"
      - "--serversTransport.forwardingTimeouts.dialTimeout=10s"
      - "--serversTransport.forwardingTimeouts.responseHeaderTimeout=30s"
      - "--entrypoints.web.transport.respondingTimeouts.idleTimeout=180s"
      - "--entrypoints.websecure.transport.respondingTimeouts.idleTimeout=180s"
      - "--entrypoints.web.transport.lifeCycle.graceTimeOut=60s"
      - "--entrypoints.websecure.transport.lifeCycle.graceTimeOut=60s"
    resources:
      requests: {cpu: 500m, memory: 512Mi}
      limits:   {cpu: "2", memory: 1Gi}

注意:Rancher 纳管集群里该 HelmChartConfig 由 Rancher 创建(含 global.cattle.clusterId),在其 valuesContent合并追加即可,勿整段覆盖;改完 RKE2 的 helm-controller 会自动重渲染并滚动重建 Traefik Pod,用 kubectl -n kube-system rollout status ds/rke2-traefik 观察。

6. 验证与排障速查

bash
# 路由是否生效
kubectl -n kube-system port-forward <traefik-pod> 18080:8080
curl -s localhost:18080/api/http/routers | jq '.[] | {name, rule, status, service}'

# HTTPS 跳转/证书
curl -sI http://app.ai-ear.cn/ --resolve app.ai-ear.cn:80:192.168.122.31      # 301 → https
echo | openssl s_client -connect 192.168.122.31:443 -servername app.ai-ear.cn 2>/dev/null | openssl x509 -noout -subject -dates

# 压测(观察 5.7 指标)
# 关键水位:open_connections、5xx、P99、Pod CPU、节点 conntrack 用量
conntrack -C

7. 总结

  1. HTTP/HTTPS 分离 = 路由分别挂 web/websecure 入口,HTTPS 加 tls.secretName,跳转用入口级 redirection 或 redirectScheme middleware;
  2. 原理一句话:静态配置定入口,CRD 动态定路由,Traefik 按 SNI 终止 TLS、按 EndpointSlice 直连 Pod 做负载,热加载不断流;
  3. 高并发三板斧:连接池与超时调优 + 节点内核参数 + 限流/熔断/重试韧性中间件,辅以独立 metrics 入口做容量观测;
  4. RKE2 里一切定制走 HelmChartConfig,别手改 DaemonSet。