云原生之API网关Traefik

1. 前言

说到web服务的开源网关,我首先想到的是Nginx,最早使用的就是它,现在都还在使用它。系统上线了Docker Swarm集群之后,不继续使用Nginx直接做Docker服务的网关,是因为Nginx毕竟比Docker Swarm出现的早,其集成度还是不高。

我们经过技术调研对比后,选择了Traefik作为微服务API网关,也是因为Traefik和Docker集成比较好,通过在各个应用程序的docker-compose.yml里设置labels,把Traefik声明清楚,服务能够被Traefik自动接管,用不着我们在nginx.conf里那样手工进行配置,这大大简化了我们的配置工作。

当然nginx ingress controller和k8s的搭配,我并没有亲自搭建过,虽然有几台AI服务器是采用这样的部署方式,都是厂家预安装好的。

2. 简介

Traefik是一个高性能、易用的API网关,支持多种后端服务,如Docker、Kubernetes等,它采用Go语言开发。

Traefik官网文档地址是:Traefik Proxy Documentation - Traefik

Traefik基于EntryPoints入口点、Routers路由器、Middlewares 中间件和Services服务的概念。它主要功能包括动态配置、自动服务发现以及对多个后端和协议的支持。

  1. EntryPoints: EntryPoints对Traefit是一个网络入口点,它定义了接收数据包的端口port, 包括TCP和UDP。

  2. Routers: 路由器负责将传入的请求连接到可以处理这些请求的服务。

  3. Middlewares: 中间件附着于路由器上,它能够修改经过路由器的请求包和应答包。

  4. Services: 服务组件负责配置请求怎样达到实际的后端服务。

3. 安装

各种安装方法说明参见官网:Traefik Installation Documentation - Traefik, 这里仅仅贴一下Docker Swarm集群里的安装方式,主要是docker-compose.yml编排:

XML 复制代码
version: "3.2"

services:
  gateway:
    image: traefik:v2.3.2
    command:
      - "--log.level=INFO"
      - "--api=true"
      - "--api.dashboard=true"
      - "--api.insecure=true"
      # 启用swarm模式支持
      - "--providers.docker.swarmMode=true"
      # 默认不公开容器
      - "--providers.docker.exposedbydefault=false"
      # 为traefik-net网络启用代理
      - "--providers.docker.network=gateway"
      # 开发环境:创建名为`web-dev`的入口点,并为其暴露于80端口。该入口点会指示其它容器在哪个端口公开
      - "--entrypoints.web-dev.address=:80"
      # 测试环境:创建名为`web-test`的入口点,并为其暴露于81端口。该入口点会指示其它容器在哪个端口公开      
      - "--entrypoints.web-test.address=:81"
      # 预发布环境:创建名为`web-staging`的入口点,并为其暴露于82端口。该入口点会指示其它容器在哪个端口公开
      - "--entrypoints.web-stagin.address=:82"      
    ports:
      - 2080:80
      - 2081:81
      - 2082:82
      - 1080:8080
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    networks:
      - gateway
    deploy:
      placement:
        constraints:
          - node.labels.traefik == true

networks:
  gateway:
    external: true

安装的操作不外乎在docker-compose.yml所在目录执行:

docker-compose up -d

docker ps | grep traefik

docker service ls | grep traefik

如果安装成功,则管理web地址是:http://127.0.0.1:1080/dashboard/#/,肯定不是127.0.0.1,换上实际IP地址即可。

4. EntryPoints

上图说明了EntryPoints可以支持多个端口,它向外部网络提供服务访问的入口点,架构上和功能细节上不用去细分析,那么配置上体现在哪里,我们怎么配置多个EntryPoint。

XML 复制代码
      - "--entrypoints.web-dev.address=:80"
      # 测试环境:创建名为`web-test`的入口点,并为其暴露于81端口。该入口点会指示其它容器在哪个端口公开      
      - "--entrypoints.web-test.address=:81"
      # 预发布环境:创建名为`web-staging`的入口点,并为其暴露于82端口。该入口点会指示其它容器在哪个端口公开
      - "--entrypoints.web-stagin.address=:82"      
    ports:
      - 2080:80
      - 2081:81
      - 2082:82

就是上面这几行,我们有3个环境,那可以配置3个EntryPoint,Traefik也是一个docker服务,也是以容器运行,所以它的内部端口是80,81,82,暴露给外部的是2080,2081,2082, 我们想怎么做端口规划就怎么配置。

我们的3个EntryPoint配置应该在traefik dashboard界面上看得见,上图我的实际配置稍有不同而涂抹掉了,方法是一样的。

5. Routers

路由器在EntryPoint和Service之间,自然是路由分发的作用, 同理,我们不要去纠结它的架构和功能细节,主要在使用上怎么配置让路由正确生效。

这里不需要在Traefik的docker-compose.yml里配置,而是在各个Docker Swarm上部署的应用程序docker-compose.yml里配置,Traefik会自动扫描发现并让路由配置生效,这个方式非常好,也是一种自动注册与发现。例如我在用户中心管理系统的docker-compose.yml里这样配置:

XML 复制代码
      labels:
        - "traefik.enable=true"
        # 路由规则
        - "traefik.http.routers.usercenter-${SCOPE}.rule=PathPrefix(`/uc`)"
        # 中间件引用
        - "traefik.http.routers.usercenter-${SCOPE}.middlewares=auth-${SCOPE}"
        # 入口点
        - "traefik.http.routers.usercenter-${SCOPE}.entrypoints=web-${SCOPE}"
        # 服务负载均衡
        - "traefik.http.services.usercenter-${SCOPE}.loadbalancer.server.port=80"
        # 中间件定义:委派认证中间件(此处定义,其他服务直接引用,不能重复定义)
        - "traefik.http.middlewares.auth-${SCOPE}.forwardauth.address=http://usercenter-${SCOPE}_authservice/auth/"
        - "traefik.http.middlewares.auth-${SCOPE}.forwardauth.authResponseHeaders=user_id,user_name"
        - "traefik.http.middlewares.auth-${SCOPE}.forwardauth.trustForwardHeader=true"

Routers和其它三个模块都有交互,处在中心位置,所以它的配置涉及了入口点EntryPoint、路由规则rule、中间件Middlewares和服务services负载均衡的配置,每个应用程序服务配置只需前面5行,下面的中间件定义,下面再讲。

我们在traefik dashboard上可以看到路由器的生效配置:

6. Middlewares

Middleware中间件附着于路由器上,它能够修改经过路由器的请求包和应答包,而且可以配置很多个。有两类中间件:HTTP和TCP,官网文档:Traefik Proxy Middleware Overview - Traefik

例如,我利用ForwardAuth中间件来做认证鉴权,上面docker-compose.yml的中间件定义就是如此:

XML 复制代码
        # 中间件定义:委派认证中间件(此处定义,其他服务直接引用,不能重复定义)
        - "traefik.http.middlewares.auth-${SCOPE}.forwardauth.address=http://usercenter-${SCOPE}_authservice/auth/"
        - "traefik.http.middlewares.auth-${SCOPE}.forwardauth.authResponseHeaders=user_id,user_name"
        - "traefik.http.middlewares.auth-${SCOPE}.forwardauth.trustForwardHeader=true"

中间件定义只要在用户认证中心的系统里定义一次就可以了,具体你在哪个服务里定义随你的便,但是要符合架构定义。

在其它业务系统里如果需要进行用户认证鉴权,就在docker-compose.yml加入一行引用即可。例如:

XML 复制代码
# 中间件引用
        - "traefik.http.routers.usercenter-${SCOPE}.middlewares=auth-${SCOPE}"

也就是我的usercentor服务引用了auth中间件,外部进来的HTTP请求会被Router先发往[http://usercenter-${SCOPE}_authservice/auth/,](/auth/%22 "http://usercenter-${SCOPE}_authservice/auth/, 返回OK才前传给后面的service组件,不然就会返回认证失败,如401、403错误码。 ")

auth组件返回200才前传给后面的service组件,不然就会返回认证失败,如401、403错误码。

我们在traefik dashboard上可以看到中间件的生效配置:

7. Services

这里的服务是Traefik的服务组件,负责把请求分发到后端实际的服务组件去,同时做好负载均衡,具体参见官方文档:Traefik Services Documentation - Traefik

XML 复制代码
        # 容器内的入口点,treafik无法获知你的服务的访问入口点,所以你必须以此告诉Traefik
        # Traefik同时会在此对横向拓展的容器建立负载均衡
        # 更多见https://docs.traefik.io/routing/services/
        - "traefik.http.services.demo-service-${SCOPE}.loadbalancer.server.port=80"

同样,在traefik dashboard界面上可以看到服务的配置:

8. 云原生部署架构

Traefik的功能细节有很多,具体不再累述,那么云原生知识点讲的网关这里,基本的环境部署技术点也算出来了,对一个小型云原生应用系统基本可以运作了。例如我们可能有这样一个部署架构:

我们的系统已经容器化、集群化、支持服务编排、具有服务注册和发现机制、具有负载均衡能力、对外提供API网关能力,使用的技术也比较简单,小团队都可以hold得住。

9. 总结

Traefik是一个采用Go语言开发的高性能、易用的微服务API网关,支持多种后端服务,如Docker、Kubernetes等,它有4个主要组件EntryPoints、Routers、Middlewares和Services, 提供路由、服务发现、负载均衡和大量好用的中间件功能。

相关推荐
wclass-zhengge5 分钟前
K8S篇(基本介绍)
云原生·容器·kubernetes
颜淡慕潇12 分钟前
【K8S问题系列 |1 】Kubernetes 中 NodePort 类型的 Service 无法访问【已解决】
后端·云原生·容器·kubernetes·问题解决
昌sit!8 小时前
K8S node节点没有相应的pod镜像运行故障处理办法
云原生·容器·kubernetes
茶馆大橘12 小时前
微服务系列五:避免雪崩问题的限流、隔离、熔断措施
java·jmeter·spring cloud·微服务·云原生·架构·sentinel
北漂IT民工_程序员_ZG12 小时前
k8s集群安装(minikube)
云原生·容器·kubernetes
coding侠客12 小时前
揭秘!微服务架构下,Apollo 配置中心凭啥扮演关键角色?
微服务·云原生·架构
2301_8061313618 小时前
Kubernetes的基本构建块和最小可调度单元pod-0
云原生·容器·kubernetes
licy__1 天前
Docker 基础命令简介
docker·云原生·eureka
0_1_bits1 天前
【系统设计】高效的分布式系统:使用 Spring Boot 和 Kafka 实现 Saga 模式
spring boot·后端·云原生·架构·kafka·linq
探索云原生1 天前
GPU 环境搭建指南:如何在裸机、Docker、K8s 等环境中使用 GPU
ai·云原生·kubernetes·go·gpu