首页
/ Traefik Kubernetes 服务暴露实战:从首个 HTTP 服务到路径路由与 TLS 加密

Traefik Kubernetes 服务暴露实战:从首个 HTTP 服务到路径路由与 TLS 加密

2026-09-05 22:44:01作者:牧宁李

本篇指南聚焦于 Traefik 在 Kubernetes 上暴露服务的基础能力:如何使用 whoami 演示应用完成第一个 HTTP 服务的暴露、基于 URL 路径进行多服务路由、以及用自签名证书为入口开启 TLS。读完本文,你可以独立在集群中选择 Gateway API(HTTPRoute)或 Traefik 自有 CRD(IngressRoute)两种路由方式完成服务暴露与加密,并理解 Traefik Provider 在源码层面是如何把这些资源转换成动态路由配置的。

前置条件

开始之前,请确保环境中具备以下条件(对应原文档 basic.md 的 Prerequisites 部分):

  • 一个已安装 Traefik 的 Kubernetes 集群;
  • 已配置好、可与集群交互的 kubectl
  • Traefik 已通过 Kubernetes Setup 指南 部署完成(该指南演示了用官方 Helm chart 安装,并配置了 web/websecure 入口点、Dashboard 认证与 Gateway 监听器)。

路由方式上,本指南提供两条可互换的路径,读者可按需二选一:

  • Gateway API:Kubernetes 社区标准,跨发行版可移植;
  • IngressRoute CRD:Traefik 自有资源,功能最完整,支持 Traefik 路由表达式与内建 ACME。

暴露第一个 HTTP 服务

首先用 traefik/whoami 演示镜像(一个回显请求元信息的调试应用)暴露一个最简单的 HTTP 服务。该 Deployment 创建 2 个副本以演示负载均衡,并配套一个选择 app: whoami 的 Service:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoami
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: whoami
  template:
    metadata:
      labels:
        app: whoami
    spec:
      containers:
      - name: whoami
        image: traefik/whoami
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: whoami
  namespace: default
spec:
  selector:
    app: whoami
  ports:
  - port: 80

保存为 whoami.yaml 并应用:

kubectl apply -f whoami.yaml

接下来创建路由。下面分别给出 Gateway API 与 IngressRoute 两种写法。

方式一:使用 Gateway API(HTTPRoute)

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: whoami
  namespace: default
spec:
  parentRefs:
  - name: traefik-gateway  # 该 Gateway 由 Traefik 启用 Gateway API 时自动创建
  hostnames:
  - "whoami.docker.localhost"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: whoami
      port: 80

保存为 whoami-route.yaml 并应用:

kubectl apply -f whoami-route.yaml

要点说明:

  • parentRefs.name: traefik-gateway 指向 Traefik 开启 Gateway API provider 后自动创建的 Gateway 资源,它是 HTTPRoute 与监听器之间的桥梁;
  • hostnames 决定该路由匹配的 Host 头;
  • rules[].matches 中的 PathPrefix 匹配路径前缀,backendRefs 指向同命名空间内的 Service whoami:80

方式二:使用 IngressRoute CRD

apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: whoami
  namespace: default
spec:
  entryPoints:
    - web
  routes:
  - match: Host(`whoami.docker.localhost`)
    kind: Rule
    services:
    - name: whoami
      port: 80

保存为 whoami-ingressroute.yaml 并应用:

kubectl apply -f whoami-ingressroute.yaml

要点说明:

  • entryPoints 指定路由绑定的入口点,这里使用 HTTP 入口 web(80 端口);
  • match 使用 Traefik 路由表达式(Rule 语法),此处仅按 Host(\whoami.docker.localhost`)` 匹配;
  • services 直接引用集群内的 Service 及其端口。

验证服务是否生效

服务现在应可通过 http://whoami.docker.localhost/ 访问。用 Host 头模拟域名进行验证:

curl -H "Host: whoami.docker.localhost" http://localhost/

!!! 注意 如果此前按 Kubernetes Setup 指南 安装 Traefik,记得从 values.yaml 中移除 ports.web.redirections 块,否则请求会被 302 跳转到 HTTPS 入口点,导致下面的 HTTP 验证失败:

redirections:
  entryPoint:
    to: websecure

成功时输出类似:

Hostname: whoami-6d5d964cb-8pv4k
IP: 127.0.0.1
IP: ::1
IP: 10.42.0.18
IP: fe80::d4c0:3bff:fe20:b0a3
RemoteAddr: 10.42.0.17:39872
GET / HTTP/1.1
Host: whoami.docker.localhost
User-Agent: curl/7.68.0
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 10.42.0.1
X-Forwarded-Host: whoami.docker.localhost
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: traefik-76cbd5b89c-rx5xn
X-Real-Ip: 10.42.0.1

响应中的 X-Forwarded-*X-Real-Ip 头由 Traefik 注入,证明请求确实经过了代理转发到后端 whoami Pod(Hostname 显示 Pod 名)。

添加基于路径的路由规则

下一步按 URL 路径把流量分发到不同服务——这在 API 版本管理、前后端分离、微服务聚合等场景中非常常用。先部署一个代表 API 的第二个服务(通过 WHOAMI_NAME 环境变量把它标识为 "API Service"):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: whoami-api
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: whoami-api
  template:
    metadata:
      labels:
        app: whoami-api
    spec:
      containers:
      - name: whoami
        image: traefik/whoami
        env:
        - name: WHOAMI_NAME
          value: "API Service"
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: whoami-api
  namespace: default
spec:
  selector:
    app: whoami-api
  ports:
  - port: 80

保存为 whoami-api.yaml 并应用:

kubectl apply -f whoami-api.yaml

Gateway API:路径规则

更新已有的 HTTPRoute,将 /api 前缀指向 whoami-api,根路径 / 兜底到 whoami。注意 rules 的先后顺序:前缀规则在前、兜底规则在后:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: whoami
  namespace: default
spec:
  parentRefs:
  - name: traefik-gateway
  hostnames:
  - "whoami.docker.localhost"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /api
    backendRefs:
    - name: whoami-api
      port: 80
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: whoami
      port: 80

更新 whoami-route.yaml 文件后应用:

kubectl apply -f whoami-route.yaml

IngressRoute:路径规则

更新已有的 IngressRoute,用 Traefik 路由表达式组合 HostPath 条件:

apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: whoami
  namespace: default
spec:
  entryPoints:
    - web
  routes:
  - match: Host(`whoami.docker.localhost`) && Path(`/api`)
    kind: Rule
    services:
    - name: whoami-api
      port: 80
  - match: Host(`whoami.docker.localhost`)
    kind: Rule
    services:
    - name: whoami
      port: 80

保存为 whoami-ingressroute.yaml 并应用:

kubectl apply -f whoami-ingressroute.yaml

两条 routes 的区别在于第一条附加了 Path(\/api`)精确路径条件,第二条仅按 Host 匹配充当兜底路由。从源码结构看([crd/kubernetes_http.go](https://gitcode.com/GitHub_Trending/tr/traefik/blob/14bc52dd1f1d1c08cedd1da531a527fc04d79c19/pkg/provider/kubernetes/crd/kubernetes_http.go?utm_source=gitcode_repo_files) 中的loadIngressRouteConfiguration),IngressRoute 的每一条 route 都会生成一个独立的 Traefik Router,match字段直接成为 Router 的 Rule,并记录Priority;而 [gateway/kubernetes.go](https://gitcode.com/GitHub_Trending/tr/traefik/blob/14bc52dd1f1d1c08cedd1da531a527fc04d79c19/pkg/provider/kubernetes/gateway/kubernetes.go?utm_source=gitcode_repo_files) 中的 Gateway provider 则负责解析 HTTPRouterules/matches/backendRefs`,将其转换为等价的动态路由配置。两种写法最终都收敛到同一套动态配置模型上,这也是二者可以互换使用的底层原因。

测试路径路由

分别请求根路径和 /api 路径,验证流量被路由到了不同服务:

# 根路径应路由到主 whoami 服务
curl -H "Host: whoami.docker.localhost" http://localhost/

# /api 路径应路由到 whoami-api 服务
curl -H "Host: whoami.docker.localhost" http://localhost/api

针对 /api 的请求,响应中应能看到 "name":"API Service",证明路径路由生效:

{"hostname":"whoami-api-67d97b4868-dvvll","ip":["127.0.0.1","::1","10.42.0.9","fe80::10aa:37ff:fe74:31f2"],"headers":{"Accept":["*/*"],"Accept-Encoding":["gzip"],"User-Agent":["curl/8.7.1"],"X-Forwarded-For":["10.42.0.1"],"X-Forwarded-Host":["whoami.docker.localhost"],"X-Forwarded-Port":["80"],"X-Forwarded-Proto":["http"],"X-Forwarded-Server":["traefik-669c479df8-vkj22"],"X-Real-Ip":["10.42.0.1"]},"url":"/api","host":"whoami.docker.localhost","method":"GET","name":"API Service","remoteAddr":"10.42.0.13:36592"}

为服务启用 TLS

现在用自签名证书为本地开发环境开启 HTTPS。

创建自签名证书

生成自签名证书:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
  -keyout tls.key -out tls.crt \
  -subj "/CN=whoami.docker.localhost"

在 Kubernetes 中创建 TLS Secret:

kubectl create secret tls whoami-tls --cert=tls.crt --key=tls.key

!!! 重要(Gateway API 使用 TLS 的前置条件) 使用 Gateway API 处理 TLS 之前,必须在 Traefik 安装配置中定义 websecure 监听器(通常通过 Helm values 完成)。values.yaml 示例:

ports:
  web:
    port: 80
  websecure:
    port: 443
gateway:
  listeners:
    web:
      port: 80
      protocol: HTTP
      namespacePolicy:
        from: All
    websecure:
      port: 443
      protocol: HTTPS
      namespacePolicy:
        from: All
      mode: Terminate
      certificateRefs:
        - kind: Secret
          name: whoami-tls
          group: ""

完整的安装细节参见 Kubernetes Setup 指南。其中 mode: Terminate 表示 TLS 在 Traefik 内部终结,certificateRefs 指定终结 TLS 所用的证书 Secret,namespacePolicy.from: All 则允许任意命名空间的路由绑定该监听器。

Gateway API:切换至 HTTPS 监听器

更新 HTTPRoute,通过 sectionName 指向 websecure 监听器即可复用同一组路径规则:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: whoami
  namespace: default
spec:
  parentRefs:
  - name: traefik-gateway
    sectionName: websecure  # 指向 HTTPS 监听器
  hostnames:
  - "whoami.docker.localhost"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /api
    backendRefs:
    - name: whoami-api
      port: 80
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: whoami
      port: 80

更新 whoami-route.yaml 文件并应用:

kubectl apply -f whoami-route.yaml

IngressRoute:声明 TLS Secret

更新 IngressRoute:把入口点从 web 改为 websecure,并在 tls 字段引用前面创建的 Secret:

apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: whoami
  namespace: default
spec:
  entryPoints:
    - websecure  # 由 'web' 改为 'websecure'
  routes:
  - match: Host(`whoami.docker.localhost`) && Path(`/api`)
    kind: Rule
    services:
    - name: whoami-api
      port: 80
  - match: Host(`whoami.docker.localhost`)
    kind: Rule
    services:
    - name: whoami
      port: 80
  tls:
    secretName: whoami-tls  # 新增的 TLS 配置

更新 whoami-ingressroute.yaml 文件并应用:

kubectl apply -f whoami-ingressroute.yaml

从源码结构看(crd/kubernetes_http.go),tls.secretName 会被 getTLSHTTP 解析:provider 从集群中拉取该 TLS Secret,加载证书后写入对应 Router 的 dynamic.Router.TLS 配置;同文件中还可以看到,tls.certResolver(ACME 自动签发)与 tls.options(TLSOption)也是在这一阶段解析到 Router 上的——这正是后文"进阶"章节中 Let's Encrypt 能力的入口。

验证 HTTPS 访问

现在可以通过 HTTPS 访问服务。由于是自签名证书,需要跳过证书校验:

curl -k -H "Host: whoami.docker.localhost" https://localhost/

浏览器同样可以访问 https://whoami.docker.localhost/(自签名证书会触发浏览器安全警告,需手动接受)。

小结与下一步

本文完整复现了 basic.md 的三条主线:首个 HTTP 服务暴露(Gateway API 与 IngressRoute 双方案)、基于路径的多服务路由、以及用自签名证书开启 TLS,并在关键节点补充了 Traefik Kubernetes Provider 的源码级实现佐证:

掌握这些基础后,可以继续进入 进阶指南,学习:为路由添加中间件实现安全与访问控制、用 Let's Encrypt(IngressRoute)或 cert-manager(Gateway API)自动签发证书、为有状态应用配置粘性会话(sticky sessions),以及基于 IngressRoute 的多层路由(multi-layer routing)实现认证前置等高级模式。

登录后查看全文
热门项目推荐
相关项目推荐