提到 Traefik,有些人可能并不熟悉,但是提到 Nginx,应该都耳熟能详。
暂且我们把 Traefik 当成和 Nginx 差不多的一类软件,待读完整篇文章,你就会对 Traefik 有不一样的认识。
本文主要带大家对 Traefik 有一个全面的认识,我将从下面几个方面作介绍。
本文基于 Traefik 2.5.3 进行介绍。
什么是 Traefik
Traefik 是一个开源的边缘路由网关,它简单易用并且功能全面。官方【1】的介绍是:Traefik is an [open-source](https://github.com/traefik/traefik) _Edge Router_ that makes publishing your services a fun and easy experience.
Traefik 原生支持多种集群,如 Kubernetes、Docker、Docker Swarm、AWS、Mesos、Marathon 等;并且可以同时处理许多集群。
Traefik 的核心概念及能力
Traefik 是一个边缘路由器,它会拦截外部的请求并根据逻辑规则选择不同的操作方式,这些规则决定着这些请求到底该如何处理。Traefik 提供自动发现能力,会实时检测服务,并自动更新路由规则。
从上图可知,请求首先会连接到 entrypoints
,然后分析这些请求是否与定义的 rules
匹配,如果匹配,则会通过一系列 middlewares
,再到对应的 services
上。
这就涉及到以下几个重要的核心组件。
Providers
Providers
是基础组件,Traefik 的配置发现是通过它来实现的,它可以是协调器,容器引擎,云提供商或者键值存储。
Traefik
通过查询 Providers
的 API
来查询路由的相关信息,一旦检测到变化,就会动态的更新路由。
Entrypoints
Entrypoints
是 Traefik
的网络入口,它定义接收请求的接口,以及是否监听 TCP 或者 UDP。
Routers
Routers
主要用于分析请求,并负责将这些请求连接到对应的服务上去,在这个过程中,Routers 还可以使用 Middlewares 来更新请求,比如在把请求发到服务之前添加一些 Headers。
Services
Services
负责配置如何到达最终将处理传入请求的实际服务。
Middlewares
Middlewares
用来修改请求或者根据请求来做出一些判断(authentication, rate limiting, headers, …),中间件被附件到路由上,是一种在请求发送到你的服务之前(或者在服务的响应发送到客户端之前)调整请求的一种方法。
部署 Traefik
Traefik 的部署方式有多种,这里主要采用 Helm
方式进行部署管理。
Helm 部署
环境:
kubernetes: 1.22.3
helm: 3.7.1
1、添加 traefik helm 仓库
$ helm repo add traefik https://helm.traefik.io/traefik
$ helm repo update
2、将 traefik 包下载到本地进行管理
$ helm search repo traefik
NAME CHART VERSION APP VERSION DESCRIPTION
traefik/traefik 10.6.0 2.5.3 A Traefik based Kubernetes ingress controller
$ helm pull traefik/traefik
3、部署 Traefik
默认的 value.yaml
[2] 配置文件配置比较多,可能需要花一定的时间去梳理,不过根据相关的注释还是可以很快的理解。
这里自定义一个配置文件 my-value.yaml
,如下:
service:
type: NodePort
ingressRoute:
dashboard:
enabled: false
ports:
traefik:
port: 9000
expose: true
web:
port: 8000
expose: true
websecure:
port: 8443
expose: true
persistence:
enabled: true
name: data
accessMode: ReadWriteOnce
size: 5G
storageClass: "openebs-hostpath"
path: /data
additionalArguments:
- "--serversTransport.insecureSkipVerify=true"
- "--api.insecure=true"
- "--api.dashboard=true"
进行部署,命令如下:
$ kubectl create ns traefik-ingress
$ helm install traefik -n traefik-ingress -f my-value.yaml .
这里部署使用的是默认的 value.yaml
[2] 配置文件。
然后可以看到部署结果,如下:
# kubectl get all -n traefik-ingress
NAME READY STATUS RESTARTS AGE
pod/traefik-77ff894bb5-qqszd 1/1 Running 0 6m26s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/traefik NodePort 10.108.170.22 <none> 9000:32271/TCP,80:31728/TCP,443:30358/TCP 6m26s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/traefik 1/1 1 1 6m26s
NAME DESIRED CURRENT READY AGE
replicaset.apps/traefik-77ff894bb5 1 1 1 6m26s
然后可以通过 NodePort
访问 Dashboard 页面,如下:
使用 Traefik
创建第一个路由规则
我们上面访问 Dashboard 是采用的 NodePort
的方式,既然已经把 Traefik
部署好了,为什么不使用路由网关的方式呢?
下面我们就来创建第一个路由网关来访问 Dashboard
。
Traefik 创建路由规则有多种方式,比如:
- 原生 Ingress 写法
- 使用 CRD IngressRoute 方式
- 使用 GatewayAPI 的方式
这里暂时介绍前面两种方式,关于 GatewayAPI 的方式在后续进行介绍。
原生 Ingress 路由规则
原生 Ingress 的路由规则,写法就比较简单,如下。
# cat traefik-ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: traefik-dashboard-ingress
annotations:
kubernetes.io/ingress.class: traefik
traefik.ingress.kubernetes.io/router.entrypoints: web
spec:
rules:
- host: traefik-web.coolops.cn
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: traefik
port:
number: 9000
创建路由规则,命令如下:
# kubectl apply -f traefik-ingress.yaml -n traefik-ingress
ingress.networking.k8s.io/traefik-dashboard-ingress created
现在就可以通过域名 http://traefik-web.coolops.cn:31728/dashboard/#/ 进行访问了(31728 是 80 端口的映射端口),如下:
使用 CRD 方式配置路由规则
在早期版本,Traefik 仅提供 kubernetes ingress 方式配置路由规则,社区认为采用开发一个自定义 CRD 的类型能够更好的提供 Kubernetes 的访问配置【3】。
IngressRoute
的配置方式也比较简单,如下:
# cat traefik-ingressRoute.yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: traefik-dashboard-route
spec:
entryPoints:
- web
routes:
- match: Host(`traefik-web2.coolops.cn`)
kind: Rule
services:
- name: traefik
port: 9000
部署命令如下:
# kubectl apply -f traefik-ingressRoute.yaml -n traefik-ingress
ingressroute.traefik.containo.us/traefik-dashboard-route created
然后就可以通过 [http://traefik-web2.coolops.cn:31728/dashboard/#/]
暴露 HTTP 服务
首先,部署一个简单的 whoami
[4] 应用,YAML 文件如下:
---
apiVersion: v1
kind: Pod
metadata:
name: whoami
labels:
app: whoami
spec:
containers:
- name: whoami
image: traefik/whoami:latest
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: whoami
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: whoami
type: ClusterIP
部署成功后,创建一个路由规则,使外部可以访问。
# cat ingressroute.yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: whoami-route
spec:
entryPoints:
- web
routes:
- match: Host(`whoami.coolops.cn`)
kind: Rule
services:
- name: whoami
port: 80
创建过后,就可以进行访问了,如下:
暴露 HTTPS 服务
上面的 whoami
应用,是通过 HTTP
进行访问的,如果要通过 HTTPS
进行访问,应该如何配置呢?
Traefik
支持 HTTPS 和 TLS,对于证书可以选择自有证书,也可以使用 Let’s Encrypt【5】自动生成证书。这里会分别介绍这两种方式。
自有证书配置 HTTPS
现在公司基本都会自己购买更安全的证书,那对于自有证书配置 HTTPS 就会使用更加频繁,这里主要介绍这种配置方式。
1、申请或者购买证书
我这里是在腾讯云申请的免费证书。
然后下载对应的证书,并上传到服务器上。
2、将证书文件保存为 Secret
# kubectl create secret tls whoami-tls --cert=1_whoami.coolops.cn_bundle.crt --key=2_whoami.coolops.cn.key
3、创建 IngressRoute 对象,使其可以通过 TLS 访问
# cat ingressroutetls.yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: whoami-route-tls
spec:
entryPoints:
- websecure
routes:
- match: Host(`whoami.coolops.cn`)
kind: Rule
services:
- name: whoami
port: 80
tls:
secretName: whoami-tls
创建完成后,就可以通过 https://whoami.coolops.cn:30358/ 进行访问了(30358 是 443 映射出来的端口)。
自动生成 HTTPS 证书
Traefik
除了使用自有证书外,还支持 Let's Encrypt
自动生成证书【6】。
要使用 Let's Encrypt
自动生成证书,需要使用 ACME
。需要在静态配置中定义 “证书解析器”,Traefik
负责从 ACME
服务器中检索证书。
然后,每个 "路由器" 被配置为启用 TLS,并通过 tls.certresolver 配置选项与一个证书解析器关联。
Traefik
的 ACME
验证方式主要有以下三种:
- tlsChallenge
- httpChallenge
- dnsChallenge
如果使用 tlsChallenge
,则要求 Let's Encrypt
到 Traefik 443
端口必须是可达的。如果使用 httpChallenge
,则要求 Let's Encrypt
到 Traefik 80
端口必须是可达的。如果使用 dnsChallenge
,则需要对应的 providers
[7]。
但是我们上面部署 Traefik
的时候并没有把 80 和 443 端口暴露出来,要测试 tlsChallenge
和 httpChallenge
的话就必须暴露,下面我们更改一下 my-value.yaml
,如下:
service:
type: NodePort
ingressRoute:
dashboard:
enabled: false
ports:
traefik:
port: 9000
expose: true
web:
port: 8000
hostPort: 80
expose: true
websecure:
port: 8443
hostPort: 443
expose: true
persistence:
enabled: true
name: data
accessMode: ReadWriteOnce
size: 5G
storageClass: "openebs-hostpath"
path: /data
additionalArguments:
- "--serversTransport.insecureSkipVerify=true"
- "--api.insecure=true"
- "--api.dashboard=true"
然后重新更新一下 Traefik
,命令如下:
helm upgrade traefik -n traefik-ingress -f my-value.yaml .
现在我们就可以直接通过 80 或 443 端口进行访问了。
1、tlsChallenge
上面已经介绍过,要使用 tlsChallenge
,必须能访问入口的 443 端口,现在我们入口已经放开,接下来就修改 Traefik
的 my-value.yaml
配置,如下:
......
deployment:
initContainers:
- name: volume-permissions
image: busybox:1.31.1
command: ["sh", "-c", "chmod -Rv 600 /data/*"]
volumeMounts:
- name: data
mountPath: /data
additionalArguments:
- "--serversTransport.insecureSkipVerify=true"
- "--api.insecure=true"
- "--api.dashboard=true"
- "--certificatesresolvers.coolops.acme.email=coolops@163.com"
- "--certificatesresolvers.coolops.acme.storage=/data/acme.json"
- "--certificatesresolvers.coolops.acme.tlschallenge=true"
PS:这里需要将 /data 目录权限给更改一下,默认是 0660, 权限太大是不允许的。
然后我们创建一个 ingressRoute
,如下:
# cat ingressrouteautotls.yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: whoami-route-auto-tls
spec:
entryPoints:
- websecure
routes:
- match: Host(`whoami3.coolops.cn`)
kind: Rule
services:
- name: whoami
port: 80
tls:
certResolver: coolops
这时候我们访问 https://whoami3.coolops.cn 是可以正常使用证书的,如下:
2、httpChallenge
下面再使用 httpChallenge
进行测试,修改 my-value.yaml
配置文件如下:
......
deployment:
initContainers:
- name: volume-permissions
image: busybox:1.31.1
command: ["sh", "-c", "chmod -Rv 600 /data/*"]
volumeMounts:
- name: data
mountPath: /data
additionalArguments:
- "--serversTransport.insecureSkipVerify=true"
- "--api.insecure=true"
- "--api.dashboard=true"
- "--certificatesresolvers.coolops.acme.email=coolops@163.com"
- "--certificatesresolvers.coolops.acme.storage=/data/acme.json"
- "--certificatesresolvers.coolops.acme.httpchallenge=true"
- "--certificatesresolvers.coolops.acme.httpchallenge.entrypoint=web"
更新 Traefik
过后,然后再创建一个 ingressRoute
进行测试,YAML 文件如下:
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: whoami-route-auto-tls-http
spec:
entryPoints:
- websecure
routes:
- match: Host(`whoami4.coolops.cn`)
kind: Rule
services:
- name: whoami
port: 80
tls:
certResolver: coolops
然后使用 https://whoami4.coolops.cn
,效果如下:
3、dnsChallenge
dnsChallenge
在使用上相对比较麻烦,因为需要配置对应的 provider
,不过它可以生成通配符证书,这里以阿里云 DNS【8】为例。
使用阿里 DNS 的前提是您的域名是在阿里云上面,不然在签署证书的时候会报错,如下:
Unable to obtain ACME certificate for domains \"*.coolops.cn\" : unable to generate a certificate for the domains [*.coolops.cn]: error: one or more domains had a problem:\n[*.coolops.cn] [*.coolops.cn] acme: error presenting token: alicloud: zone coolops.cn. not found in AliDNS for domain coolops.cn\n" providerName=coolops.acme
使用阿里云的 DNS 校验需要配置 3 个环境变量:ALICLOUD_ACCESS_KEY
、ALICLOUD_SECRET_KEY
、ALICLOUD_REGION_ID
,分别对应我们平时开发阿里云应用的时候的密钥,可以登录阿里云后台获取,由于这是比较私密的信息,所以我们用 Secret 对象来创建:
$ kubectl create secret generic traefik-alidns --from-literal=ALICLOUD_ACCESS_KEY=<aliyun ak> --from-literal=ALICLOUD_SECRET_KEY=<aliyun sk>--from-literal=ALICLOUD_REGION_ID=cn-beijing -n traefik-ingress
修改 Traefik 的 my-value.yaml,如下:
......
additionalArguments:
- "--serversTransport.insecureSkipVerify=true"
- "--api.insecure=true"
- "--api.dashboard=true"
- "--certificatesresolvers.coolops.acme.email=coolops@163.com"
- "--certificatesresolvers.coolops.acme.storage=/data/acme.json"
- "--certificatesresolvers.coolops.acme.dnschallenge=true"
- "--certificatesResolvers.coolops.acme.dnsChallenge.provider=alidns"
envFrom:
- secretRef:
name: traefik-alidns
更新 Traefik
过后,然后再创建一个 ingressRoute
进行测试,YAML 文件如下(由于 coolops.cn 不在阿里云上,所以换了一个域名):
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: whoami-route-auto-tls-dns
spec:
entryPoints:
- websecure
routes:
- match: Host(`whoami6.coolops.cn`)
kind: Rule
services:
- name: whoami
port: 80
tls:
certResolver: coolops
domains:
- main: "*.coolops.cn"
然后访问域名后,就可以看到证书签署 成功,如下:
中间件的使用
在介绍 Traefik
的核心概念的时候有提到一个请求匹配 Rules
后,会经过一系列的 Middleware
,再到具体的 Services
上。这个 Middleware
是什么呢?
Middleware
是 Traefik 2.0
之后新增的功能,用户可以根据不通的需求来选择不同的 Middleware 来满足服务,提高了定制化的能力。
Traefik 内置了很多不同功能的 Middleware,主要是针对 HTTP 和 TCP,HTTP 占大部分 [9],这里挑选几个比较常用的进行演示。
强制跳转 HTTPS
强制跳转 HTTPS 是经常会配置的功能,这里还是以上没的 whoami
应用为例。
1、创建一个 HTTPS 的 ingressRoute
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: whoami-route-auto-tls
spec:
entryPoints:
- websecure
routes:
- match: Host(`whoami3.coolops.cn`)
kind: Rule
services:
- name: whoami
port: 80
tls:
certResolver: coolops
2、定义一个跳转 HTTPS 的中间件
这里会用到 RedirectScheme
的内置中间件,配置如下:
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: redirect-https-middleware
spec:
redirectScheme:
scheme: https
3、定义一个 HTTP 的 ingressRoute,并使用 Middleware
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: whoami3-route
spec:
entryPoints:
- web
routes:
- match: Host(`whoami3.coolops.cn`)
kind: Rule
services:
- name: whoami
port: 80
middlewares:
- name: redirect-https-middleware
然后访问 http://whoami3.coolops.cn
就会被强制跳转到 https://whoami3.coolops.cn
。
去除请求路径前缀
有时候会遇到这么一个需求:
- 只有一个域名
- 相通过这个域名访问不同的应用
这种需求是非常常见的,在 NGINX
中,我们可以配置多个 Location
来定制规则,使用 Traefik
也可以这么做。
但是定制不同的前缀后,由于应用本身并没有这些前缀,导致请求返回 404
,这时候我们就需要对请求的 path
进行处理,还是以 whoami
应用为例。
1、创建一个带前缀的 ingressRoute
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: whoami7-route
spec:
entryPoints:
- web
routes:
- match: Host(`whoami7.coolops.cn`) && PathPrefix('/coolops')
kind: Rule
services:
- name: whoami
port: 80
我们现在访问是会返回 404
状态的。
2、定义去除前缀的中间件
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: prefix-coolops-url-middleware
spec:
stripPrefix:
prefixes:
- /coolops
3、修改上面的 ingressRoute,应用中间件
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: whoami7-route
spec:
entryPoints:
- web
routes:
- match: Host(`whoami7.coolops.cn`) && PathPrefix('/coolops')
kind: Rule
services:
- name: whoami
port: 80
middlewares:
- name: prefix-coolops-url-middleware
然后就可以正常访问了。
添加 IP 白名单
在工作中,有一些 URL 并不希望对外暴露,比如 prometheus、grafana 等的 url,这时候我们希望通过白名单 IP 来达到需求,就可以使用 Traefik
中的 ipWhiteList
中间件来完成。
1、定义白名单 IP 的中间件
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: ip-white-list-middleware
spec:
ipWhiteList:
sourceRange:
- 127.0.0.1/32
- 192.168.100.180
然后将中间件应用到对应的 Rules 上,就可以完成白名单功能。
除了上面的功能,Traefik 内置 Middleware 还支持很多其他功能,比如限流、认证鉴权等,可以通过引用【9】进行查看。
暴露 TCP 服务
Traefik 2.0 支持暴露 TCP,这里以 Redis 为例。
1、部署一个 Redis 服务
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
spec:
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis:5.0.14
ports:
- containerPort: 6379
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: redis
spec:
ports:
- port: 6379
targetPort: 6379
selector:
app: redis
2、暴露 Redis 端口
暴露 TCP 端口使用的是 SNI【10】,而 SNI 又是依赖 TLS 的,所以我们需要配置证书才行,但是如果没有证书的话,我们可以使用通配符 *
进行配置。
(1)、添加一个 redis 的 entrypoints
修改 Traefik
的部署文件 my-value.yaml
,添加如下内容:
ports:
traefik:
port: 9000
expose: true
web:
port: 8000
hostPort: 80
expose: true
websecure:
port: 8443
hostPort: 443
expose: true
redis:
port: 6379
containerPort: 6379
hostPort: 6379
additionalArguments:
- "--entryPoints.redis.address=:6379"
- "--serversTransport.insecureSkipVerify=true"
- "--api.insecure=true"
- "--api.dashboard=true"
- "--certificatesresolvers.coolops.acme.email=coolops@163.com"
- "--certificatesresolvers.coolops.acme.storage=/data/acme.json"
- "--certificatesresolvers.coolops.acme.httpchallenge=true"
- "--certificatesresolvers.coolops.acme.httpchallenge.entrypoint=web"
在启动参数中添加 --entryPoints.redis.address=:27017
用来指定 entrypoint。
(2)、创建 ingressRoute 进行对外暴露
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRouteTCP
metadata:
name: redis-traefik-tcp
spec:
entryPoints:
- redis
routes:
- match: HostSNI(`*`)
services:
- name: redis
port: 6379
然后可以使用客户端工具进行 Redis 的操作了。
# redis-cli -h redis.coolops.cn
redis.coolops.cn:6379> set a b
OK
redis.coolops.cn:6379> get a
"b"
redis.coolops.cn:6379>
灰度发布
Traefik2.0 以后的一个更强大的功能就是灰度发布,灰度发布我们有时候也会称为金丝雀发布(Canary),主要就是让一部分测试的服务也参与到线上去,经过测试观察看是否符号上线要求。
假设一个应用现在运行着 V1
版本,新的 V2
版本需要上线,这时候我们需要在集群中部署好 V2
版本,然后通过 Traefik
提供的带权重的轮询(WRR)
来实现该功能。
1、部署 appv1、appv2 应用
appv1.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: appv1
spec:
selector:
matchLabels:
app: appv1
template:
metadata:
labels:
use: test
app: appv1
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello v1 > /usr/share/nginx/html/index.html"]
ports:
- containerPort: 80
name: portv1
---
apiVersion: v1
kind: Service
metadata:
name: appv1
spec:
selector:
app: appv1
ports:
- name: http
port: 80
targetPort: portv1
appv2.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: appv2
spec:
selector:
matchLabels:
app: appv2
template:
metadata:
labels:
use: test
app: appv2
spec:
containers:
- name: nginx
image: nginx
imagePullPolicy: IfNotPresent
lifecycle:
postStart:
exec:
command: ["/bin/sh", "-c", "echo Hello v2 > /usr/share/nginx/html/index.html"]
ports:
- containerPort: 80
name: portv2
---
apiVersion: v1
kind: Service
metadata:
name: appv2
spec:
selector:
app: appv2
ports:
- name: http
port: 80
targetPort: portv2
2、创建 TraefikService
在 Traefik2.1 以后新增了一个 TraefikService
的 CRD 资源,我们可以直接利用这个对象来配置 WRR
。
apiVersion: traefik.containo.us/v1alpha1
kind: TraefikService
metadata:
name: app-wrr
spec:
weighted:
services:
- name: appv1
weight: 3
port: 80
kind: Service
- name: appv2
weight: 1
port: 80
kind: Service
3、创建 ingressRoute
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: app-ingressroute-canary
spec:
entryPoints:
- web
routes:
- match: Host(`app.coolops.cn`)
kind: Rule
services:
- name: app-wrr
kind: TraefikService
注意:这里配置的不是 Service
类型,而是 TraefikService
。
然后就可以通过访问 http://app.coolops.cn
来校验结果。
待 V2
测试没问题后,就可以将流量全切到 V2
了。
流量复制
在 Traefik 2.0
之后还引入了镜像服务
[11],它可以将请求的流量按规则复制一份发送给其他服务,并且会忽略这部分请求的响应。
这个功能在做一些压测或者问题复现的时候还是很有用。
这里依然以上没的 appv1 和 appv2 为例进行简单的演示。
1、创建 TraefikService,定义复制规则
apiVersion: traefik.containo.us/v1alpha1
kind: TraefikService
metadata:
name: app-mirror
spec:
mirroring:
name: appv1
port: 80
mirrors:
- name: appv2
percent: 50
port: 80
上面定义的意思是将请求到 appv1 的 50% 请求复制到 appv2。
2、创建 ingressRoute,进行效果演示
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: app-ingressroute-mirror
spec:
entryPoints:
- web
routes:
- match: Host(`mirror.coolops.cn`)
kind: Rule
services:
- name: app-mirror
kind: TraefikService
然后进行测试,效果如下:
发了 4 次请求,appv1 可以正常接收 4 次请求,appv2 可以收到 2 次请求,收到的响应是 appv1 的,并没有 appv2 的响应。
Kubernetes Gateway API
我们在上面创建路由规则要么使用 ingress
,要么使用 ingressRoute
,其实在 Traefik 2.4
以后支持 Kubernetes Gateway API
[12] 提供的 CRD
方式创建路由规则。
什么是 Gateway API?
Gateway API
【13】是一个由 SIG-NETWORK
社区管理的开源项目。它是 Kubernetes
中服务网络模型的资源集合。这些资源(GatewayClass、Gateway、HTTPRoute、TCPRoute、Service)旨在通过表达式的、可扩展的和面向角色的接口来发展 Kubernetes 服务网络,这些接口由许多供应商实现,并得到了广泛的行业支持。
- GatewayClass: GatewayClass 是基础结构提供程序定义的群集范围的资源。此资源表示可以实例化的网关类。一般该资源是用于支持多个基础设施提供商用途的,这里我们只部署一个即可。
- Gateway: Gateway 与基础设施配置的生命周期是 1:1。当用户创建网关时,GatewayClass 控制器会提供或配置一些负载平衡基础设施。
- HTTPRoute: HTTPRoute 是一种网关 API 类型,用于指定 HTTP 请求从网关侦听器到 API 对象(即服务)的路由行为。
使用 Gateway API
1、安装 Gateway API 的 CRD
Traefik Gateway provider 仅支持 v0.3.0 (v1alpha1).
kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v0.3.0" \
| kubectl apply -f -
2、创建 rbac,给 traefik 授权
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: gateway-role
rules:
- apiGroups:
- ""
resources:
- services
- endpoints
- secrets
verbs:
- get
- list
- watch
- apiGroups:
- networking.x-k8s.io
resources:
- gatewayclasses
- gateways
- httproutes
- tcproutes
- tlsroutes
verbs:
- get
- list
- watch
- apiGroups:
- networking.x-k8s.io
resources:
- gatewayclasses/status
- gateways/status
- httproutes/status
- tcproutes/status
- tlsroutes/status
verbs:
- update
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: gateway-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: gateway-role
subjects:
- kind: ServiceAccount
name: traefik
namespace: traefik-ingress
2、Traefik 开启 gateway api 支持
修改 my-value.yaml
文件,如下:
......
additionalArguments:
- "--entryPoints.redis.address=:6379"
- "--serversTransport.insecureSkipVerify=true"
- "--api.insecure=true"
- "--api.dashboard=true"
- "--certificatesresolvers.coolops.acme.email=coolops@163.com"
- "--certificatesresolvers.coolops.acme.storage=/data/acme.json"
- "--certificatesresolvers.coolops.acme.httpchallenge=true"
- "--certificatesresolvers.coolops.acme.httpchallenge.entrypoint=web"
- "--experimental.kubernetesgateway"
- "--providers.kubernetesgateway"
更新 Traefik,命令如下:
helm upgrade traefik -n traefik-ingress -f my-value.yaml .
4、通过 Gateway api 的方式暴露 traefik dashboard 应用
(1)、创建 GatewayClass
apiVersion: networking.x-k8s.io/v1alpha1
kind: GatewayClass
metadata:
name: traefik
spec:
controller: traefik.io/gateway-controller
(2)、创建 gateway
apiVersion: networking.x-k8s.io/v1alpha1
kind: Gateway
metadata:
name: http-gateway
namespace: traefik-ingress
spec:
gatewayClassName: traefik
listeners:
- protocol: HTTP
port: 8000
routes:
kind: HTTPRoute
namespaces:
from: All
selector:
matchLabels:
app: traefik
(3)、创建 HTTPRoute
apiVersion: networking.x-k8s.io/v1alpha1
kind: HTTPRoute
metadata:
name: whoami-gateway-api-route
namespace: traefik-ingress
labels:
app: traefik
spec:
hostnames:
- "traefik1.coolops.cn"
rules:
- matches:
- path:
type: Prefix
value: /
forwardTo:
- serviceName: traefik
port: 9000
weight: 1
(4)、现在就可以直接在浏览器访问了
GatewayClass
在集群中可以只创建一个,然后 Gateway
和 HTTPRoute
是需要对应的。
比如我这里要暴露 default 命名空间下的 whoami 应用,YAML 就应该如下:
apiVersion: networking.x-k8s.io/v1alpha1
kind: Gateway
metadata:
name: http-gateway
spec:
gatewayClassName: traefik
listeners:
- protocol: HTTP
port: 8000
routes:
kind: HTTPRoute
namespaces:
from: All
selector:
matchLabels:
app: whoami
---
apiVersion: networking.x-k8s.io/v1alpha1
kind: HTTPRoute
metadata:
name: whoami-gateway-api-route
labels:
app: whoami
spec:
hostnames:
- "whoami8.coolops.cn"
rules:
- matches:
- path:
type: Prefix
value: /
forwardTo:
- serviceName: whoami
port: 80
weight: 1
最后
Traefik
是一个功能比较强大的边缘网关,基本能满足绝大部分的场景需求,而且还有 Mesh
等工具,比较好用,有兴趣的朋友可以到官网 [14] 进行学习,也欢迎交流。
引用
[1] https://doc.traefik.io/traefik/
[2] https://github.com/traefik/traefik-helm-chart/blob/master/traefik/values.yaml
[3] https://doc.traefik.io/traefik/providers/kubernetes-crd/
[4] https://github.com/traefik/whoami
[5] https://letsencrypt.org/zh-cn/
[6] https://doc.traefik.io/traefik/https/acme/
[7] https://doc.traefik.io/traefik/https/acme/#tlschallenge
[8] https://go-acme.github.io/lego/dns/alidns/
[9] https://doc.traefik.io/traefik/middlewares/http/overview/
[10] https://doc.traefik.io/traefik/routing/routers/#configuring-tcp-routers
[11] https://doc.traefik.io/traefik/routing/services/#mirroring-service
[12] https://doc.traefik.io/traefik/providers/kubernetes-gateway/
[13] https://gateway-api.sigs.k8s.io/
[14] https://traefik.io/