微信公众号:运维开发故事,作者:乔克

提到Traefik,有些人可能并不熟悉,但是提到Nginx,应该都耳熟能详。

暂且我们把Traefik当成和Nginx差不多的一类软件,待读完整篇文章,你就会对Traefik有不一样的认识。

本文主要带大家对Traefik有一个全面的认识,我将从下面几个方面作介绍。
![image.png](https://img-blog.csdnimg.cn/img_convert/cdbfeebc199f50119f8fc961a745ca04.png#clientId=uf74e0467-b192-4&from=paste&height=415&id=u631e57c5&margin=[object Object]&name=image.png&originHeight=415&originWidth=766&originalType=binary&ratio=1&size=39431&status=done&style=none&taskId=u9ef58839-7941-4355-b996-103362d54b0&width=766)

本文基于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等;并且可以同时处理许多集群。

![image.png](https://img-blog.csdnimg.cn/img_convert/7de011507651dd29e7964210f9373203.png#clientId=u7a806467-43d8-4&from=paste&id=u3f8a0142&margin=[object Object]&name=image.png&originHeight=1501&originWidth=2875&originalType=url&ratio=1&size=602883&status=done&style=none&taskId=uebffb3ed-bbde-4cfb-88b1-c2561373153)

Traefik的核心概念及能力

Traefik是一个边缘路由器,它会拦截外部的请求并根据逻辑规则选择不同的操作方式,这些规则决定着这些请求到底该如何处理。Traefik提供自动发现能力,会实时检测服务,并自动更新路由规则。
![image.png](https://img-blog.csdnimg.cn/img_convert/cb12cced9ba7008cc07f9ca72f93168e.png#clientId=u7a806467-43d8-4&from=paste&id=u09dba5fd&margin=[object Object]&name=image.png&originHeight=1493&originWidth=3174&originalType=url&ratio=1&size=1408683&status=done&style=none&taskId=u90bf2b48-e6e2-4959-9475-9c34aabb826)

从上图可知,请求首先会连接到entrypoints,然后分析这些请求是否与定义的rules匹配,如果匹配,则会通过一系列middlewares,再到对应的services上。

这就涉及到以下几个重要的核心组件。

  • Providers
  • Entrypoints
  • Routers
  • Services
  • Middlewares

Providers

Providers是基础组件,Traefik的配置发现是通过它来实现的,它可以是协调器,容器引擎,云提供商或者键值存储。

Traefik通过查询ProvidersAPI来查询路由的相关信息,一旦检测到变化,就会动态的更新路由。

Entrypoints

EntrypointsTraefik的网络入口,它定义接收请求的接口,以及是否监听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: 9000expose: trueweb:port: 8000expose: truewebsecure:port: 8443expose: true
persistence:enabled: truename: dataaccessMode: ReadWriteOncesize: 5GstorageClass: "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 .

然后可以看到部署结果,如下:

# kubectl get all -n traefik-ingress
NAME                           READY   STATUS    RESTARTS   AGE
pod/traefik-77ff894bb5-qqszd   1/1     Running   0          6m26sNAME              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   6m26sNAME                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/traefik   1/1     1            1           6m26sNAME                                 DESIRED   CURRENT   READY   AGE
replicaset.apps/traefik-77ff894bb5   1         1         1       6m26s

然后可以通过NodePort访问Dashboard页面,如下:
![image.png](https://img-blog.csdnimg.cn/img_convert/8c2a161bef7abfdcdd3b8d2b2022e2c8.png#clientId=u7a806467-43d8-4&from=paste&height=625&id=u44e2c894&margin=[object Object]&name=image.png&originHeight=625&originWidth=1366&originalType=binary&ratio=1&size=73549&status=done&style=none&taskId=u260cd154-a52d-4de4-9c23-584e4c353cb&width=1366)

使用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-ingressannotations:kubernetes.io/ingress.class: traefik  traefik.ingress.kubernetes.io/router.entrypoints: web
spec:rules:- host: traefik-web.coolops.cn http:paths:- pathType: Prefixpath: /backend:service:name: traefikport: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端口的映射端口),如下:
![image.png](https://img-blog.csdnimg.cn/img_convert/2beb24e78d58e12f95c1e2dbfa5784f6.png#clientId=u7a806467-43d8-4&from=paste&height=695&id=uf6c5cf21&margin=[object Object]&name=image.png&originHeight=695&originWidth=1355&originalType=binary&ratio=1&size=81484&status=done&style=none&taskId=u783a4b5c-b733-4578-bbc6-68a90d9142c&width=1355)

使用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:- webroutes:- match: Host(`traefik-web2.coolops.cn`)kind: Ruleservices:- name: traefikport: 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/#/ 进行访问了。
![image.png](https://img-blog.csdnimg.cn/img_convert/0b7acce540bece7cc73436f924b402ff.png#clientId=u7a806467-43d8-4&from=paste&height=690&id=uc2966a4a&margin=[object Object]&name=image.png&originHeight=690&originWidth=1355&originalType=binary&ratio=1&size=81155&status=done&style=none&taskId=u62f785d0-2251-4839-b2e1-f812b40aac8&width=1355)​

暴露HTTP服务

首先,部署一个简单的whoami[4]应用,YAML文件如下:

---
apiVersion: v1
kind: Pod
metadata:name: whoamilabels:app: whoami
spec:containers:- name: whoamiimage: traefik/whoami:latestports:- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:name: whoami
spec:ports:- port: 80protocol: TCPtargetPort: 80selector:app: whoamitype: ClusterIP

部署成功后,创建一个路由规则,使外部可以访问。

# cat ingressroute.yaml
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:name: whoami-route
spec:entryPoints:- webroutes:- match: Host(`whoami.coolops.cn`)kind: Ruleservices:- name: whoamiport: 80

创建过后,就可以进行访问了,如下:
![image.png](https://img-blog.csdnimg.cn/img_convert/553c8d6527adfccf99d4fac27370bb46.png#clientId=u7a806467-43d8-4&from=paste&height=367&id=u007fca10&margin=[object Object]&name=image.png&originHeight=367&originWidth=1132&originalType=binary&ratio=1&size=27809&status=done&style=none&taskId=uc91a0d10-8b24-4b3d-b653-f6a68c3a073&width=1132)

暴露HTTPS服务

上面的whoami应用,是通过HTTP进行访问的,如果要通过HTTPS进行访问,应该如何配置呢?

Traefik支持HTTPS和TLS,对于证书可以选择自有证书,也可以使用Let’s Encrypt【5】自动生成证书。这里会分别介绍这两种方式。

自有证书配置HTTPS

现在公司基本都会自己购买更安全的证书,那对于自有证书配置HTTPS就会使用更加频繁,这里主要介绍这种配置方式。

1、申请或者购买证书

我这里是在腾讯云申请的免费证书。
![image.png](https://img-blog.csdnimg.cn/img_convert/bafd58a781a01b68e2de5ab4312a23ee.png#clientId=u7a806467-43d8-4&from=paste&height=88&id=u00f0c46d&margin=[object Object]&name=image.png&originHeight=88&originWidth=1093&originalType=binary&ratio=1&size=12021&status=done&style=none&taskId=u34256b14-4312-4af7-8a8b-2bbbf863713&width=1093)
然后下载对应的证书,并上传到服务器上。

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:- websecureroutes:- match: Host(`whoami.coolops.cn`)kind: Ruleservices:- name: whoamiport: 80 tls:secretName: whoami-tls

创建完成后,就可以通过https://whoami.coolops.cn:30358/ 进行访问了(30358是443映射出来的端口)。
![image.png](https://img-blog.csdnimg.cn/img_convert/4d3756c45a85acb2da802c9ef08645fe.png#clientId=u7a806467-43d8-4&from=paste&height=464&id=u2fb7c1f4&margin=[object Object]&name=image.png&originHeight=464&originWidth=1146&originalType=binary&ratio=1&size=34659&status=done&style=none&taskId=u69566c68-fdf2-4f8c-969f-16a6994b165&width=1146)

自动生成HTTPS证书

Traefik除了使用自有证书外,还支持Let's Encrypt自动生成证书【6】。

要使用Let's Encrypt自动生成证书,需要使用ACME。需要在静态配置中定义 “证书解析器”,Traefik负责从ACME服务器中检索证书。

然后,每个 "路由器 "被配置为启用TLS,并通过tls.certresolver配置选项与一个证书解析器关联。

TraefikACME验证方式主要有以下三种:

  • tlsChallenge
  • httpChallenge
  • dnsChallenge

如果使用tlsChallenge,则要求Let's Encrypt到 Traefik 443 端口必须是可达的。如果使用httpChallenge,则要求Let's Encrypt到 Traefik 80端口必须是可达的。如果使用dnsChallenge,则需要对应的providers[7]。

但是我们上面部署Traefik的时候并没有把80和443端口暴露出来,要测试tlsChallengehttpChallenge的话就必须暴露,下面我们更改一下my-value.yaml,如下:

service:type: NodePort ingressRoute:dashboard:enabled: false
ports:traefik:port: 9000expose: trueweb:port: 8000hostPort: 80expose: truewebsecure:port: 8443hostPort: 443expose: true
persistence:enabled: truename: dataaccessMode: ReadWriteOncesize: 5GstorageClass: "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端口,现在我们入口已经放开,接下来就修改Traefikmy-value.yaml配置,如下:

......
deployment:initContainers:- name: volume-permissionsimage: busybox:1.31.1command: ["sh", "-c", "chmod -Rv 600 /data/*"]volumeMounts:- name: datamountPath: /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:- websecureroutes:- match: Host(`whoami3.coolops.cn`)kind: Ruleservices:- name: whoamiport: 80 tls:certResolver: coolops

这时候我们访问https://whoami3.coolops.cn是可以正常使用证书的,如下:
![image.png](https://img-blog.csdnimg.cn/img_convert/4b478daa34b00695d1c1fc4e08308411.png#clientId=u7a806467-43d8-4&from=paste&height=685&id=u80861970&margin=[object Object]&name=image.png&originHeight=685&originWidth=1361&originalType=binary&ratio=1&size=71516&status=done&style=none&taskId=ude22bea9-41f3-4c49-b5c2-4cad6262989&width=1361)

2、httpChallenge

下面再使用httpChallenge进行测试,修改my-value.yaml配置文件如下:

......
deployment:initContainers:- name: volume-permissionsimage: busybox:1.31.1command: ["sh", "-c", "chmod -Rv 600 /data/*"]volumeMounts:- name: datamountPath: /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:- websecureroutes:- match: Host(`whoami4.coolops.cn`)kind: Ruleservices:- name: whoamiport: 80tls:certResolver: coolops

然后使用https://whoami4.coolops.cn,效果如下:
![image.png](https://img-blog.csdnimg.cn/img_convert/e43205cb697696d2214a103cfae4be24.png#clientId=u7a806467-43d8-4&from=paste&height=686&id=uc062ddd4&margin=[object Object]&name=image.png&originHeight=686&originWidth=1361&originalType=binary&ratio=1&size=71412&status=done&style=none&taskId=u37caba9c-b677-4710-9d50-aa0fd38b06f&width=1361)

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_KEYALICLOUD_SECRET_KEYALICLOUD_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:- websecureroutes:- match: Host(`whoami6.coolops.cn`)kind: Ruleservices:- name: whoamiport: 80 tls:certResolver: coolops domains:- main: "*.coolops.cn"

然后访问域名后,就可以看到证书签署 成功,如下:
![image.png](https://img-blog.csdnimg.cn/img_convert/8d6b5adfc5fccfe6313187c0adcf614d.png#clientId=u7a806467-43d8-4&from=paste&height=676&id=ufd9f0ec3&margin=[object Object]&name=image.png&originHeight=676&originWidth=1357&originalType=binary&ratio=1&size=75248&status=done&style=none&taskId=ub4cfd6ad-ccf4-419b-99a6-6c2ae0e6a90&width=1357)

中间件的使用

在介绍Traefik的核心概念的时候有提到一个请求匹配Rules后,会经过一系列的Middleware,再到具体的Services上。这个Middleware是什么呢?

![image.png](https://img-blog.csdnimg.cn/img_convert/996ef9647b9e82e72e8517e127e932ad.png#clientId=u7a806467-43d8-4&from=paste&id=u4ee1fa0d&margin=[object Object]&name=image.png&originHeight=1730&originWidth=3165&originalType=url&ratio=1&size=484063&status=done&style=none&taskId=u2c5f5763-4c52-404e-8d36-a2d3b000485)

MiddlewareTraefik 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:- websecureroutes:- match: Host(`whoami3.coolops.cn`)kind: Ruleservices:- name: whoamiport: 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:- webroutes:- match: Host(`whoami3.coolops.cn`)kind: Ruleservices:- name: whoamiport: 80middlewares:- name: redirect-https-middleware

然后访问http://whoami3.coolops.cn就会被强制跳转到https://whoami3.coolops.cn
![image.png](https://img-blog.csdnimg.cn/img_convert/28112c53d04b530be2bce31e968aee52.png#clientId=u7a806467-43d8-4&from=paste&height=689&id=udb9868f7&margin=[object Object]&name=image.png&originHeight=689&originWidth=1366&originalType=binary&ratio=1&size=80934&status=done&style=none&taskId=ua5040ad7-2dc8-478f-967c-8074114c176&width=1366)

去除请求路径前缀

有时候会遇到这么一个需求:

  • 只有一个域名
  • 相通过这个域名访问不同的应用

这种需求是非常常见的,在NGINX中,我们可以配置多个Location来定制规则,使用Traefik也可以这么做。

但是定制不同的前缀后,由于应用本身并没有这些前缀,导致请求返回404,这时候我们就需要对请求的path进行处理,还是以whoami应用为例。

1、创建一个带前缀的ingressRoute
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:name: whoami7-route
spec:entryPoints:- webroutes:- match: Host(`whoami7.coolops.cn`) && PathPrefix('/coolops')kind: Ruleservices:- name: whoamiport: 80 

我们现在访问是会返回404状态的。
![image.png](https://img-blog.csdnimg.cn/img_convert/0e248cff3a860b88ab886e3d8df06471.png#clientId=u7a806467-43d8-4&from=paste&height=108&id=u7ded52fb&margin=[object Object]&name=image.png&originHeight=108&originWidth=1366&originalType=binary&ratio=1&size=9739&status=done&style=none&taskId=u37d773a9-2faa-4267-ac37-9daa7e98fe4&width=1366)

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:- webroutes:- match: Host(`whoami7.coolops.cn`) && PathPrefix('/coolops')kind: Ruleservices:- name: whoamiport: 80middlewares:- 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: redistemplate:metadata:labels:app: redisspec:containers:- name: redisimage: redis:5.0.14ports:- containerPort: 6379protocol: TCP
---
apiVersion: v1
kind: Service
metadata:name: redis
spec:ports:- port: 6379targetPort: 6379selector:app: redis
2、暴露Redis端口

暴露TCP端口使用的是SNI【10】,而SNI又是依赖TLS的,所以我们需要配置证书才行,但是如果没有证书的话,我们可以使用通配符*进行配置。

(1)、添加一个redis的entrypoints

修改Traefik的部署文件my-value.yaml,添加如下内容:

ports:traefik:port: 9000expose: trueweb:port: 8000hostPort: 80expose: truewebsecure:port: 8443hostPort: 443expose: trueredis:port: 6379containerPort: 6379hostPort: 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=:6379用来指定entrypoint。

(2)、创建ingressRoute进行对外暴露
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRouteTCP
metadata:name: redis-traefik-tcp
spec:entryPoints:- redisroutes:- match: HostSNI(`*`)services:- name: redisport: 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: appv1template:metadata:labels:use: testapp: appv1spec:containers:- name: nginximage: nginximagePullPolicy: IfNotPresentlifecycle:postStart:exec:command:  ["/bin/sh", "-c", "echo Hello v1 > /usr/share/nginx/html/index.html"]ports:- containerPort: 80name: portv1---apiVersion: v1
kind: Service
metadata:name: appv1
spec:selector:app: appv1ports:- name: httpport: 80targetPort: portv1

appv2.yaml

---
apiVersion: apps/v1
kind: Deployment
metadata:name: appv2
spec:selector:matchLabels:app: appv2template:metadata:labels:use: testapp: appv2spec:containers:- name: nginximage: nginximagePullPolicy: IfNotPresentlifecycle:postStart:exec:command:  ["/bin/sh", "-c", "echo Hello v2 > /usr/share/nginx/html/index.html"]ports:- containerPort: 80name: portv2---apiVersion: v1
kind: Service
metadata:name: appv2
spec:selector:app: appv2ports:- name: httpport: 80targetPort: portv2
2、创建TraefikService

在 Traefik2.1以后新增了一个 TraefikService的 CRD 资源,我们可以直接利用这个对象来配置 WRR

apiVersion: traefik.containo.us/v1alpha1
kind: TraefikService
metadata:name: app-wrr
spec:weighted:services:- name: appv1weight: 3port: 80kind: Service- name: appv2weight: 1port: 80kind: Service
3、创建ingressRoute
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:name: app-ingressroute-canary
spec:entryPoints:- webroutes:- match: Host(`app.coolops.cn`)kind: Ruleservices:- name: app-wrrkind: TraefikService

注意:这里配置的不是Service类型,而是TraefikService

然后就可以通过访问http://app.coolops.cn来校验结果。
![image.png](https://img-blog.csdnimg.cn/img_convert/6173e25ded6e62c30c848e3d8b0b4eee.png#clientId=u7a806467-43d8-4&from=paste&height=338&id=u1691ac13&margin=[object Object]&name=image.png&originHeight=338&originWidth=1113&originalType=binary&ratio=1&size=34300&status=done&style=none&taskId=udf2daa58-15d3-464c-9e8e-323d21b8064&width=1113)

V2测试没问题后,就可以将流量全切到V2了。

流量复制

Traefik 2.0之后还引入了镜像服务[11],它可以将请求的流量按规则复制一份发送给其他服务,并且会忽略这部分请求的响应。

这个功能在做一些压测或者问题复现的时候还是很有用。

这里依然以上没的appv1和appv2为例进行简单的演示。

1、创建TraefikService,定义复制规则
apiVersion: traefik.containo.us/v1alpha1
kind: TraefikService
metadata:name: app-mirror
spec:mirroring:name: appv1port: 80mirrors:- name: appv2percent: 50port: 80

上面定义的意思是将请求到appv1的50%请求复制到appv2。

2、创建ingressRoute,进行效果演示
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:name: app-ingressroute-mirror
spec:entryPoints:- webroutes:- match: Host(`mirror.coolops.cn`)kind: Ruleservices:- name: app-mirrorkind: TraefikService

然后进行测试,效果如下:
![image.png](https://img-blog.csdnimg.cn/img_convert/0e49a7f5b4b6f50ac734a5038d252468.png#clientId=u7a806467-43d8-4&from=paste&height=547&id=u05a68112&margin=[object Object]&name=image.png&originHeight=547&originWidth=1116&originalType=binary&ratio=1&size=63785&status=done&style=none&taskId=u7e74c495-82b8-48ef-979b-8f66d1e0f96&width=1116)

发了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服务网络,这些接口由许多供应商实现,并得到了广泛的行业支持。

![image.png](https://img-blog.csdnimg.cn/img_convert/427b6152827956a33afd66372799debd.png#clientId=uc2302164-bc8a-4&from=paste&id=ue66ad4c0&margin=[object Object]&name=image.png&originHeight=1418&originWidth=2414&originalType=url&ratio=1&size=346699&status=done&style=none&taskId=u104c3b4c-ce16-4cfe-abad-52f4ace42d5)

  • 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- secretsverbs:- get- list- watch- apiGroups:- networking.x-k8s.ioresources:- gatewayclasses- gateways- httproutes- tcproutes- tlsroutesverbs:- get- list- watch- apiGroups:- networking.x-k8s.ioresources:- gatewayclasses/status- gateways/status- httproutes/status- tcproutes/status- tlsroutes/statusverbs:- update---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:name: gateway-controllerroleRef:apiGroup: rbac.authorization.k8s.iokind: ClusterRolename: gateway-role
subjects:- kind: ServiceAccountname: traefiknamespace: 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-gatewaynamespace: traefik-ingress
spec: gatewayClassName: traefiklisteners: - protocol: HTTPport: 8000 routes: kind: HTTPRoutenamespaces:from: Allselector:matchLabels:app: traefik
(3)、创建HTTPRoute
apiVersion: networking.x-k8s.io/v1alpha1
kind: HTTPRoute
metadata:name: whoami-gateway-api-route namespace: traefik-ingresslabels:app: traefik
spec:hostnames:- "traefik1.coolops.cn"rules:- matches:- path:type: Prefixvalue: /forwardTo:- serviceName: traefik port: 9000weight: 1
(4)、现在就可以直接在浏览器访问了

![image.png](https://img-blog.csdnimg.cn/img_convert/e3e169500911d0dd9f77f6d897e4203c.png#clientId=uc2302164-bc8a-4&from=paste&height=692&id=u665434c1&margin=[object Object]&name=image.png&originHeight=692&originWidth=1351&originalType=binary&ratio=1&size=90342&status=done&style=none&taskId=uda7b21d2-7c1e-4344-a41b-50e25a3b11d&width=1351)

GatewayClass在集群中可以只创建一个,然后GatewayHTTPRoute是需要对应的。

比如我这里要暴露default命名空间下的whoami应用,YAML就应该如下:

apiVersion: networking.x-k8s.io/v1alpha1
kind: Gateway
metadata: name: http-gateway
spec: gatewayClassName: traefiklisteners: - protocol: HTTPport: 8000 routes: kind: HTTPRoutenamespaces:from: Allselector: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: Prefixvalue: /forwardTo:- serviceName: whoami port: 80weight: 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/

一文带你看懂Traefik相关推荐

  1. java byte char io流_一文带你看懂JAVA IO流,史上最全面的IO教学

    原标题:一文带你看懂JAVA IO流,史上最全面的IO教学 一.IO流是什么 惯例引用百科的回答 流是一种抽象概念,它代表了数据的无结构化传递.按照流的方式进行输入输出,数据被当成无结构的字节序或字符 ...

  2. java io流详解_一文带你看懂JAVA IO流,史上最全面的IO教学啦

    一.IO流是什么 惯例引用百科的回答流是一种抽象概念,它代表了数据的无结构化传递.按照流的方式进行输入输出,数据被当成无结构的字节序或字符序列.从流中取得数据的操作称为提取操作,而向流中添加数据的操作 ...

  3. javaio流_一文带你看懂JAVA IO流,史上最全面的IO教学啦

    一.IO流是什么 惯例引用百科的回答 流是一种抽象概念,它代表了数据的无结构化传递.按照流的方式进行输入输出,数据被当成无结构的字节序或字符序列.从流中取得数据的操作称为提取操作,而向流中添加数据的操 ...

  4. 一文带你看懂JAVA IO流(一),史上最全面的IO教学啦(附送JAVA IO脑图)

    一.IO流是什么 惯例引用百科的回答 流是一种抽象概念,它代表了数据的无结构化传递.按照流的方式进行输入输出,数据被当成无结构的字节序或字符序列.从流中取得数据的操作称为提取操作,而向流中添加数据的操 ...

  5. 一文带你看懂JAVA IO流,史上最全面的IO教学啦(附送JAVA IO脑图

    一.IO流是什么 惯例引用百科的回答 流是一种抽象概念,它代表了数据的无结构化传递.按照流的方式进行输入输出,数据被当成无结构的字节序或字符序列.从流中取得数据的操作称为提取操作,而向流中添加数据的操 ...

  6. 机器学习(1)一文带你看懂显卡,显卡驱动,CUDA,CUDNN(内含举例)

    一文带你看懂显卡,显卡驱动,CUDA,CUDNN(内含举例) 显卡 显卡驱动 CUDA CUDNN 举一个生动形象的例子 显卡 显卡是硬件设备.(花钱购买的) (注:显卡不是GPU,显卡的核心组件包含 ...

  7. 一文带你看懂 MySQL 存储引擎

    本文目录: 1.MySQL体系结构 2.存储引擎介绍 3.MySQL 存储引擎特性 4.MySQL 有哪些存储引擎 5.了解 MySQL 数据存储方式 6.MySQL存储引擎介绍 6.1 CSV存储引 ...

  8. 一文带你看懂java 泛型,史上最全面的泛型教学啦。

    认真看这篇文章,保证你们对泛型又有新的理解,如果没有的话,请顺着网线来打我呀. 概述 引用下百度百科的回答 泛型是程序设计语言的一种特性.允许程序员在强类型程序设计语言中编写代码时定义一些可变部分,那 ...

  9. 一文带你看懂PaddleHub

    作者丨Charlotte77 来源丨我爱PaddlePaddle Hub 是什么?Hub 本意是中心,docker 有 docker Hub,大家可以把自己创建的镜像打包提交到 docker hub ...

最新文章

  1. 电脑卡顿不流畅是什么原因_为什么Windows/iOS操作很流畅,而Linux/Android却很卡顿呢...
  2. Java:形式参数问题和返回值问题
  3. 本地项目关联到远程git仓库
  4. Lesson 16.3 卷积操作
  5. 【报告分享】B2B内容营销指南—制定有效内容策略-领英.pdf(附下载链接)
  6. Dynamic Performance Tables not accessible Automatic Statistics disabled for this session
  7. Flask+Mysql搭建网站之数据库问题
  8. sed 多行替换,多行模式处理字符串;一次替换
  9. 点计算机管理没反应,电脑任务栏没反应怎么办 任务栏没反应解决方法
  10. 集群容错机制:failover、failfast、failback、failsafe、forking
  11. 趣学Spring:一文搞懂Aware、异步编程、计划任务
  12. 「津津乐道播客」#342 编码人声:跟「老」程序员们聊聊编程的历史与未来
  13. 安装完Tensorflow却找不到指定模块
  14. 资深HR分享:常见面试技巧,都是套路!
  15. 2016年度人物揭晓:任正非王健林最具影响,贾跃亭当选风云人物
  16. Power BI 矩阵总计放表第一列
  17. RACI 职责分配矩阵 模型使用详解及案例分析
  18. ffmpeg超时设置
  19. 浏览器上查看微信公众号的所有历史文章
  20. 美通社日历 | 会展及重要事件信息、企业财报发布,节假日备忘(3月15日—3月21日)...

热门文章

  1. 达内java面试题集_达内经典java面试题集(一)
  2. eclipse中文化
  3. 组件式GIS开发总结(一)
  4. GIS开发:使用空间数据库
  5. WindowLess RichEdit 实现QQ聊天窗口的气泡效果,设计思路和方法。
  6. 鼠标不能动,插上了但没反应
  7. 怎样做好云计算的运维工作
  8. 合并两个有序链表-力扣21-java双百方案
  9. 学习少儿编程是新时代的刚需必然
  10. 软考高级介绍以及岗位介绍