Traefik真香!

技术

Traefik 是一款开源的反向代理和负载均衡软件,可以自动地为多个微服务实例进行负载均衡,并提供 HTTP/HTTPS/TCP/UDP 等协议支持。

Traefik 具有简单易用、自动发现服务、动态配置、可插拔的中间件等特点,被广泛应用于云原生和容器化场景中,介绍中也是表明自己是一个云原生网关。

Traefik 支持多种后端服务,包括 Kubernetes、Docker Swarm、Mesos、Consul、Etcd、Zookeeper、Redis 等,同时也提供了丰富的 API 和 Dashboard 等管理工具,使得用户能够方便地对反向代理和负载均衡进行配置和监控。

基本概念

Traefik 有 4 个基本概念,EntryPoints、Routers、Middlewares、Services。(官方图已经很清晰明了了,就不多画图了)

picture.image 架构

EntryPoints

网络入口点,配置端口、协议,包括 HTTP、HTTPS、TCP 和 UDP,每个入口点都有一个唯一标识符,并可以配置不同的访问规则和路由策略。

picture.image

针对http、https 和 udp 不同的配置方式:


      
        
## Static configuration  
entryPoints:  
  web:  
    address: ":80"  
  websecure:  
    address: ":443"  
  streaming:  
    address: ":1704/udp"
    

Routers

路由,负责将传入的请求连接到可以处理它们的服务,在这个过程中,路由可以使用一些中间件来修改请求的一些信息。

picture.image

配置/foo开始的请求路由到的后端服务。


      
        
## Dynamic configuration  
http:  
  routers:  
    my-router:  
      rule: "Path(`/foo`)"  
      service: service-foo
    

路由可以配置不同的的规则,比如针对请求 host 和请求路径进行匹配。


      
        
rule = "Host(`example.com`) || (Host(`example.org`) && Path(`/traefik`))"
    

| 规则 | 描述 | | Headers(key, value) | 请求头校验规则 | | HeadersRegexp(key, regexp) | 请求头校验规则,value 正则匹配 | | Host(example.com, ...) | 请求域名校验规则 | | HostRegexp(example.com, {subdomain:[a-z]+}.example.com, ...) | 请求域名正则匹配规则 | | Method(GET, ...) | 请求方法校验规则,支持GET\POST\PUT\DELETE\PATCH\HEAD | | Path(/path, /articles/{cat:[a-z]+}/{id:[0-9]+}, ...) | 请求路径匹配规则,精确匹配,支持正则 | | PathPrefix(/products/, /articles/{cat:[a-z]+}/{id:[0-9]+}) | 请求路径前缀匹配规则,支持正则 | | Query(foo=bar, bar=baz) | 请求参数匹配规则 | | ClientIP(10.0.0.0/16, ::1) | 请求 IP 匹配规则 |

Middlewares

中间件,用于对请求进行处理和转换,类似过滤器、拦截器,有些人可能把他理解成很多网关中的插件,但是其实在 Traefik 里面也有插件的概念,并且可以发布分享,可以参考 https://plugins.traefik.io/create。

Traefik 提供了多种内置的中间件,比如日志记录、重定向、身份验证和限流等第,此外,也可以根据需要自定义中间件。

picture.image

配置方式:


      
        
# As a Docker Label  
whoami:  
  #  A container that exposes an API to show its IP address  
  image: traefik/whoami  
  labels:  
    #  `foo-add-prefix` 中间件  
    - "traefik.http.middlewares.foo-add-prefix.addprefix.prefix=/foo"  
    - "traefik.http.routers.router1.middlewares=foo-add-prefix@docker"
    

列出一些 HTTP 中间件列表,其实很多一看名字基本就知道是干嘛用的,基本上基础的网关鉴权、熔断、限流都有默认的插件。

| 中间件 | 描述 | | AddPrefix | 路径添前缀 | | BasicAuth | 鉴权 | | Buffering | 缓冲 | | Chain | 中间件链,可以定义可重用的中间件组合 | | CircuitBreaker | 熔断 | | Compress | 压缩 | | Headers | 请求头操作,可以添加、删除请求头 | | IPWhiteList | IP 白名单 | | RateLimit | 限流 | | Retry | 重试 |

Services

服务指的是 Traefik 服务,每个服务都有一个唯一标识符,并可以配置不同的负载均衡规则和健康检查策略。

需要注意的是这里的服务指的是 Traefik 自身的 service,并非是我们自己的服务。

picture.image

配置示例:


      
        
## Dynamic configuration  
http:  
  services:  
    my-service:  
      loadBalancer:  
        servers:  
        - url: "http://<private-ip-server-1>:<private-port-server-1>/"  
        - url: "http://<private-ip-server-2>:<private-port-server-2>/"
    

根据以上的概念,实际上在 Traefik 中一个请求的流程:

  • • 当客户端发送请求时,请求首先会被协议处理器接收并解析。
  • • 然后,请求会被路由器匹配到相应的路由规则,并根据规则将请求转发给相应的中间件链。
  • • 中间件链会按照顺序执行各个中间件,并根据需要对请求进行处理和转换。
  • • 处理完请求后,请求会被转发给相应的后端服务器。
  • • 后端服务器将处理完请求后的响应返回给 Traefik。
  • • 最后,Traefik 将响应返回给客户端。
负载均衡

Traefik 的负载均衡功能通过负载均衡器来实现,支持多种负载均衡策略,包括轮询、随机、加权轮询和加权随机等。

当 Traefik 接收到请求时,根据路由规则将请求转发给相应的后端服务器。如果后端服务器有多个,Traefik 就需要使用负载均衡算法来选择一个服务器处理请求。具体流程如下:

    1. Traefik 会先根据配置的路由规则,将请求匹配到对应的前端入口点
    1. 针对该入口点,Traefik 会获取所有与之关联的后端服务列表
    1. 根据负载均衡策略,在可用的后端服务器中选择一个服务
    1. 将请求转发给所选择的后端服务
    1. 如果后端服务出现故障或者不可用,Traefik 会将其从服务器列表中移除,并选择另外一个可用的服务器来处理请求。

目前来说,官方支持轮询和加权轮询策略。

加权轮询

比如配置 v1 版本权重为3,v2版本权重为1,可用于灰度流量,配置方式如下。


      
        
## Dynamic configuration  
http:  
  services:  
    app:  
      weighted:  
        services:  
        - name: appv1  
          weight: 3  
        - name: appv2  
          weight: 1  
  
    appv1:  
      loadBalancer:  
        servers:  
        - url: "http://private-ip-server-1/"  
  
    appv2:  
      loadBalancer:  
        servers:  
        - url: "http://private-ip-server-2/"
    

流量复制

另外还有一个比较特殊的是镜像请求,镜像能够将发送到一个服务的请求镜像到其他服务,或者我们叫做流量复制更好。

比如针对 appv1的请求,配置 percent 10,那么 10% 的流量就会被打到 appv2 服务上,配置方式如下:


      
        
## Dynamic configuration  
http:  
  services:  
    mirrored-api:  
      mirroring:  
        service: appv1  
        # maxBodySize is the maximum size allowed for the body of the request.  
        # If the body is larger, the request is not mirrored.  
        # Default value is -1, which means unlimited size.  
        maxBodySize: 1024  
        mirrors:  
        - name: appv2  
          percent: 10  
  
    appv1:  
      loadBalancer:  
        servers:  
        - url: "http://private-ip-server-1/"  
  
    appv2:  
      loadBalancer:  
        servers:  
        - url: "http://private-ip-server-2/"
    

健康检查&故障转移

Traefik 要做负载均衡同样是需要健康检查的机制,健康检查需要配置健康检查的路径、请求频率(默认30秒)、超时时间(默认5秒),但是 K8S 有自己的健康检查机制,会移除失效的 pod,所以这里的健康检查对 K8S CRD 和 K8SIngress 无效。

故障转移只是依赖健康检查做正常的负载均衡而已,配置方式如下:


      
        
## Dynamic configuration  
http:  
  services:  
    app:  
      failover:  
        service: main  
        fallback: backup  
  
    main:  
      loadBalancer:  
        healthCheck:  
          path: /status  
          interval: 10s  
          timeout: 3s  
        servers:  
        - url: "http://private-ip-server-1/"  
  
    backup:  
      loadBalancer:  
        servers:  
        - url: "http://private-ip-server-2/"
    
部署

接下来通过 Docker 和 K8S 方式了解一下基本的使用。

Docker

首先下载镜:


      
        
docker run -d -p 8080:8080 -p 80:80 -v $PWD/traefik.yml:/etc/traefik/traefik.yml traefik:v2.10
    

创建配置文件:


      
        
version: '3'  
  
services:  
  whoami:  
    # A container that exposes an API to show its IP address  
    image: traefik/whoami  
    labels:  
      - "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)"  
  reverse-proxy:  
    # The official v2 Traefik docker image  
    image: traefik:v2.10  
    # Enables the web UI and tells Traefik to listen to docker  
    command: --api.insecure=true --providers.docker  
    ports:  
      # The HTTP port  
      - "80:80"  
      # The Web UI (enabled by --api.insecure=true)  
      - "8080:8080"  
    volumes:  
      # So that Traefik can listen to the Docker events  
      - /var/run/docker.sock:/var/run/docker.sock
    

启动:


      
        
docker-compose up -d reverse-proxy  
docker-compose up -d whoami
    

服务创建成功,自动服务发现 whoami,并且存在规则,请求头带 Host 请求可以访问到 whoami 的服务。

picture.image

测试请求http://localhost可以得到响应

picture.image

同时,可以使用命令扩容:


      
        
docker-compose up -d --scale whoami=2
    

发现启动了两个 whoami 的实例

picture.image

再次请求会发现响应的 IP 会发生变化 IP: 172.18.0.4或者 IP: 172.18.0.3,从后台也可以看到两个实例

picture.image

K8S

Traefik 结合 K8S 首先需要 K8S 的环境,Mac 下直接使用 Docker Desktop 还是比较方便的。

Mac K8S 环境搭建

首先,下载 Docker Desktop,下载好之后是自带 K8S 的,我们只要在设置中开启即可。

picture.image

开启之后需要等待一段时间,需要去拉取相关依赖的镜像,国内可能需要自己科学上网,OK 之后可以看到 K8S 已经启动成功。

picture.image

到这里那其实已经就好了,顺便可以安装一下Kubernetes Dashboard,默认情况下不会部署控制台,使用命令部署:


      
        
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml
    

运行结果:


      
        
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml  
  
namespace/kubernetes-dashboard created  
serviceaccount/kubernetes-dashboard created  
service/kubernetes-dashboard created  
secret/kubernetes-dashboard-certs created  
secret/kubernetes-dashboard-csrf created  
secret/kubernetes-dashboard-key-holder created  
configmap/kubernetes-dashboard-settings created  
role.rbac.authorization.k8s.io/kubernetes-dashboard created  
clusterrole.rbac.authorization.k8s.io/kubernetes-dashboard created  
rolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created  
clusterrolebinding.rbac.authorization.k8s.io/kubernetes-dashboard created  
deployment.apps/kubernetes-dashboard created  
service/dashboard-metrics-scraper created  
deployment.apps/dashboard-metrics-scraper created
    

然后,使用 kubectl 命令行工具来启用 Dashboard 访问。


      
        
kubectl proxy
    

启动成功之后访问 http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/ ,进入控制台页面,然后需要我们去配置 token,目前只能通过这种方式去访问。

picture.image

按照官网文档:https://github.com/kubernetes/dashboard/blob/master/docs/user/access-control/creating-sample-user.md,配置一个账户和集群角色,复制到一个文件就行,不需要做修改,保存文件为 k8s-admin.yaml


      
        
apiVersion: v1  
kind: ServiceAccount  
metadata:  
  name: admin-user  
  namespace: kubernetes-dashboard  
---  
apiVersion: rbac.authorization.k8s.io/v1  
kind: ClusterRoleBinding  
metadata:  
  name: admin-user  
roleRef:  
  apiGroup: rbac.authorization.k8s.io  
  kind: ClusterRole  
  name: cluster-admin  
subjects:  
- kind: ServiceAccount  
  name: admin-user  
  namespace: kubernetes-dashboard
    

使用命令创建服务:


      
        
kubectl create -f k8s-admin.yaml
    

执行命令,生成 token:


      
        
kubectl -n kubernetes-dashboard create token admin-user
    

picture.image

然后填入 token,就可以正常访问 dashboard 了。

picture.image

Traefik 部署

参考官方文档:https://doc.traefik.io/traefik/getting-started/quick-start-with-kubernetes/

Traefik 使用 Kubernetes API 来做服务发现,为了使用 Kubernetes API,Traefik 需要一些权限,首先是创建角色,创建 ClusterRole 角色:


      
        
kind: ClusterRole  
apiVersion: rbac.authorization.k8s.io/v1  
metadata:  
  name: traefik-role  
  
rules:  
  - apiGroups:  
      - ""  
    resources:  
      - services  
      - endpoints  
      - secrets  
    verbs:  
      - get  
      - list  
      - watch  
  - apiGroups:  
      - extensions  
      - networking.k8s.io  
    resources:  
      - ingresses  
      - ingressclasses  
    verbs:  
      - get  
      - list  
      - watch  
  - apiGroups:  
      - extensions  
      - networking.k8s.io  
    resources:  
      - ingresses/status  
    verbs:  
      - update
    

然后创建用于 traefik 的账户:


      
        
apiVersion: v1  
kind: ServiceAccount  
metadata:  
  name: traefik-account
    

然后,在账户上绑定角色以应用权限和规则:


      
        
kind: ClusterRoleBinding  
apiVersion: rbac.authorization.k8s.io/v1  
metadata:  
  name: traefik-role-binding  
  
roleRef:  
  apiGroup: rbac.authorization.k8s.io  
  kind: ClusterRole  
  name: traefik-role  
subjects:  
  - kind: ServiceAccount  
    name: traefik-account  
    namespace: default 
    

这样角色和账户的配置已经完成了,接下来需要配置 Traefik 的服务信息和 Dashboard 控制台,其中 args 参数是 traefik 的启动静态配置参数。


      
        
kind: Deployment  
apiVersion: apps/v1  
metadata:  
  name: traefik-deployment  
  labels:  
    app: traefik  
  
spec:  
  replicas: 1  
  selector:  
    matchLabels:  
      app: traefik  
  template:  
    metadata:  
      labels:  
        app: traefik  
    spec:  
      serviceAccountName: traefik-account  
      containers:  
        - name: traefik  
          image: traefik:v2.10  
          args:  
            - --api.insecure  
            - --providers.kubernetesingress  
          ports:  
            - name: web  
              containerPort: 80  
            - name: dashboard  
              containerPort: 8080
    

创建 Traefik 的服务资源:


      
        
apiVersion: v1  
kind: Service  
metadata:  
  name: traefik-dashboard-service  
  
spec:  
  type: LoadBalancer  
  ports:  
    - port: 8080  
      targetPort: dashboard  
  selector:  
    app: traefik  
---  
apiVersion: v1  
kind: Service  
metadata:  
  name: traefik-web-service  
  
spec:  
  type: LoadBalancer  
  ports:  
    - targetPort: web  
      port: 80  
  selector:  
    app: traefik
    

最终,我们可以根据这些配置统一到一个配置文件中,命名为k8s-traefik.yaml,然后使用命令创建:


      
        
kubectl apply -f k8s-traefik.yaml  
clusterrole.rbac.authorization.k8s.io/traefik-role created  
serviceaccount/traefik-account created  
clusterrolebinding.rbac.authorization.k8s.io/traefik-role-binding created  
deployment.apps/traefik-deployment created  
service/traefik-dashboard-service created  
service/traefik-web-service created
    

这时候,访问控制台http://localhost:8080/dashboard/#/,可以看到已经成功了。

picture.image

现在服务部署成功,还需要部署一些后台服务来测试一下,使用官方提供的示例应用程序 traefik/whoami

同样,新建一个文件命名为k8s-whoami.yaml,使用命令创建服务,这样服务就部署成功了。


      
        
kubectl apply -f k8s-whoami.yaml  
deployment.apps/whoami created  
service/whoami created  
ingress.networking.k8s.io/whoami-ingress created
    

从后台可以看到服务启动成功:

picture.image

同时,可以访问http://localhost访问到服务:

picture.image

最后欢迎加入苏三的知识星球【Java突击队 】,一起学习,一起进步。

星球中有很多独家的干货内容,比如:Java后端学习路线,分享实战项目,源码分析,百万级系统设计,系统上线的一些坑,MQ专题,真实面试题,每天都会回答大家提出的问题,免费修改简历,免费回答工作中的问题。

星球目前开通了9个优质专栏:技术选型、系统设计、踩坑分享、工作实战、底层原理、Spring源码解读、痛点问题、高频面试题 和 性能优化。

picture.image

每一个 专栏都是大家非常关心,和非常有价值的话题,我相信在专栏中你会学到很多东西,值回票价。

picture.image

加入星球如果不满意,3天内包退。

0
0
0
0
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论