标签: 边缘路由

  • Traefik和Docker配合优秀的边缘路由

    Traefik简单介绍

    最近把一套服务从K8S降级为普通的docker-compose,使用了Traefik来做反向代理,也称为边缘路由,相当于守护整套服务的边界,他和Docker配合完美,可以轻松的发现服务并且发布服务,当然也可以配置路由,以及很简单就能实现的中间件。最早nginx-proxy最先实现了其中docker服务发现的功能,但是Traefik的使用更方便,更强大,还带有一个UI控制面板。

    基于2.6的Traefik,来看下我的部署笔记,一个反向代理,后面挂载一个api服务,还有api要用的缓存,分别拥有两个网络。

    docker-compose服务

    • 这里有一个反直觉的地方,80和443的服务要分别配置两条相同的路由,但是名字不同,分别对应不同的入口,443的入口要开启TLS,80的入口建议你开启中间件跳转,从http跳转到https。
    • 我的例子中api服务delta使用了两个网络,所以请记得traefik.docker.network=traefik配置发现用的网络,否则很有可能出504 Gateway timeout。
    version: '3'
    
    services:
      proxy:
        image: traefik:2.6
        restart: unless-stopped
        ports:
          - "80:80"
          - "443:443"
          - "9000:9000"
        depends_on:
          - delta
        volumes:
          - /var/run/docker.sock:/var/run/docker.sock
          - ./traefik.toml:/traefik.toml # traefik静态配置
          - ./logs:/var/log # traefik日志
          - ./dynamic_conf.toml:/dynamic_conf.toml # traefik动态配置
          - ./ssl:/data/ssl/ # 证书
        networks:
          - traefik
    
      delta:
        image: ccr.ccs.tencentyun.com/zhouzhou/phpallinone:allinone-master-20220331 # 一个简单的nginx
        expose:
          - 80 # 一定要有 不会自动发现  超过一个端口就配置loadbalancer.server.port
        deploy:
          replicas: 2 # 副本数量
        labels:
          - "traefik.enable=true" # 声明公开此容器访问
          - "traefik.http.routers.delta.rule=Host(`api.zhouzhou.net`)" # 解析规则用域名
          - "traefik.http.routers.delta.entrypoints=web" # 只允许来自预定义的入口点 web 80的请求
          - "traefik.http.routers.delta-ssl.rule=Host(`api.zhouzhou.net`)" # ssl单独写一条 routers
          - "traefik.http.routers.delta-ssl.entrypoints=websecure" # 只允许来自预定义的入口点 443的请求
          - "traefik.http.routers.delta-ssl.tls=true" # 443的请求要ssl
          # - "traefik.http.services.delta.loadbalancer.server.port=80"
          - traefik.docker.network=traefik # 发现网络
          - "traefik.http.routers.delta.middlewares=https-redirect" # 跳转中间件
          - "traefik.http.middlewares.https-redirect.redirectscheme.scheme=https" # http跳https
        networks:
          - traefik
          - delta
        depends_on:
          - cache
        environment:
          - APP_ENV=prod
      cache:
        image: bitnami/redis:latest
        environment:
          - ALLOW_EMPTY_PASSWORD=yes
        networks:
          - delta
    
    networks:
      traefik:
        external: true # 必须有外部网络 方便其他访问 以及在两个网络情况下traefik.docker.network起作用
      delta:

    traefik.toml 静态配置

    • 这里exposedByDefault配置需要注意,如果是false,需要显示的标记需要被发现的服务。
    ################################################################
    #
    # Configuration sample for Traefik v2.
    #
    # For Traefik v1: https://github.com/traefik/traefik/blob/v1.7/traefik.sample.toml
    #
    ################################################################
    
    ################################################################
    # Global configuration
    ################################################################
    [global]
      checkNewVersion = true
      sendAnonymousUsage = true
    
    ################################################################
    # Entrypoints configuration
    ################################################################
    
    # Entrypoints definition
    #
    # Optional
    # Default:
    [entryPoints]
      [entryPoints.web]
        address = ":80"
    
      [entryPoints.websecure]
        address = ":443"
    
      [entryPoints.traefik]
        address = ":9000"
    
    ################################################################
    # Traefik logs configuration
    ################################################################
    
    # Traefik logs
    # Enabled by default and log to stdout
    #
    # Optional
    #
    [log]
    
      # Log level
      #
      # Optional
      # Default: "ERROR"
      #
      # level = "DEBUG"
    
      # Sets the filepath for the traefik log. If not specified, stdout will be used.
      # Intermediate directories are created if necessary.
      #
      # Optional
      # Default: os.Stdout
      #
      filePath = "/var/log/traefik.log"
    
      # Format is either "json" or "common".
      #
      # Optional
      # Default: "common"
      #
      format = "json"
    
    ################################################################
    # Access logs configuration
    ################################################################
    
    # Enable access logs
    # By default it will write to stdout and produce logs in the textual
    # Common Log Format (CLF), extended with additional fields.
    #
    # Optional
    #
    # [accessLog]
    
      # Sets the file path for the access log. If not specified, stdout will be used.
      # Intermediate directories are created if necessary.
      #
      # Optional
      # Default: os.Stdout
      #
      # filePath = "/path/to/log/log.txt"
    
      # Format is either "json" or "common".
      #
      # Optional
      # Default: "common"
      #
      # format = "json"
    
    ################################################################
    # API and dashboard configuration
    ################################################################
    
    # Enable API and dashboard
    [api]
    
      # Enable the API in insecure mode
      #
      # Optional
      # Default: false
      #
      insecure = false
    
      # Enabled Dashboard
      #
      # Optional
      # Default: true
      #
      dashboard = true
    
    ################################################################
    # Ping configuration
    ################################################################
    
    # Enable ping
    [ping]
    
      # Name of the related entry point
      #
      # Optional
      # Default: "traefik"
      #
      entryPoint = "traefik"
    
    ################################################################
    # Docker configuration backend
    ################################################################
    
    # Enable Docker configuration backend
    [providers.docker]
    
      # Docker server endpoint. Can be a tcp or a unix socket endpoint.
      #
      # Required
      # Default: "unix:///var/run/docker.sock"
      #
      endpoint = "unix:///var/run/docker.sock"
    
      # Default host rule.
      #
      # Optional
      # Default: "Host(`{{ normalize .Name }}`)"
      #
      # defaultRule = "Host(`{{ normalize .Name }}.docker.localhost`)"
    
      # Expose containers by default in traefik
      #
      # Optional
      # Default: true
      #
      # 限制服务发现范围
      # 如果设置为 false, 则没有 traefik.enable=true 标签的容器将从生成的路由配置中忽略
      exposedByDefault = false
      # network = "traefik"
    
    # 动态配置
    [providers.file]
      filename = "dynamic_conf.toml"
      watch = true

    dynamic_conf.toml 动态加载的配置

    • 这里是动态配置,在静态配置里可以看到最下面的providers.file,根据官方手册,可以修改立即生效。
    • 这里做了一个中间件,为Traefik的控制面板提供了一个BasicAuth的验证功能,密码自己用htpasswd生成。
    • 证书也挂载这里了。
    # dashboard界面
    [http.routers.api]
      rule = "Host(`traefik.zhouzhou.net`)" # 匹配规则
      entrypoints = ["websecure"] #界面走443
      service = "api@internal"
      middlewares = ["myAuth"]
      [http.routers.api.tls]
    
    # 给dashboard准备的密码 nickzhuo 密码 test
    [http.middlewares.myAuth.basicAuth]
      users = [
        "nickzhuo:$apr1$mattJycX$3UG/8ObEI4kowL9yBBfE01"
      ]
    
    # 证书配置
    [tls]
      [[tls.certificates]]
        certFile = "/data/ssl/api.zhouzhou.net_bundle.crt"
        keyFile = "/data/ssl/api.zhouzhou.net.key"
      [[tls.certificates]]
        certFile = "/data/ssl/traefik.zhouzhou.net_bundle.crt"
        keyFile = "/data/ssl/traefik.zhouzhou.net.key"