【问题标题】:Traefik 2.0 behind docker swarm not workingdocker swarm 后面的 Traefik 2.0 不工作
【发布时间】:2019-10-16 10:24:44
【问题描述】:

所以,我正在尝试使用 Traefik 通过 docker swarm 对我的 Web 应用程序进行负载平衡。

但是,我已经尝试了许多配置,但不知何故不起作用。我已经阅读了文档并阅读了互联网上的一些文章。不幸的是,许多文章引用 traefik 1.x 而不是 traefik 2.0。

这是我用于 traefik 的 docker-stack.yml

version: '3.7'
services:
  traefik:
    image: traefik:2.0
    deploy:
      mode: global
      placement:
        constraints:
        - node.role == manager
      restart_policy:
        condition: on-failure
      labels:
      - traefik.docker.network=load_balancer
    configs:
    - source: traefik
      target: /etc/traefik/traefik.yml
    ports:
    - 80:80
    volumes:
    - /var/run/docker.sock:/var/run/docker.sock
    networks:
    - load_balancer
configs:
  traefik:
    file: ./traefik.yml
networks:
  load_balancer:
    external: true
    name: load_balancer

whoami.yml(用于测试目的)

version: '3.7'
services:
  whoami:
    image: containous/whoami
    deploy:
      labels:
      - traefik.enable=true
      - traefik.docker.network=load_balancer
      - traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)
    networks:
    - load_balancer
networks:
  load_balancer:
    external: true
    name: load_balancer

我的 traefik.yml

log:
  level: DEBUG

api:
  insecure: true

providers:
  docker:
    exposedByDefault: false
    swarmMode: true
    watch: true

docker 网络 ls

hxjw9rytw3od        load_balancer       overlay             swarm

curl -H 主机:whoami.docker.localhost http://127.0.0.1

404 page not found

【问题讨论】:

    标签: docker-swarm traefik


    【解决方案1】:

    也许您必须在配置中添加入口点声明:https://docs.traefik.io/routing/entrypoints/

    【讨论】:

      【解决方案2】:

      我希望现在回答这个问题还为时不晚。我找到了解决办法。

      首先,您可以使用traefik.yml 进行配置,也可以在docker-compose command 字段中使用traefik cli 标志。

      如果您使用traefik.yml 作为您的主要配置,这是工作方法。 在file 上使用directoryrecommended

      traefik.yml

      log:
        level: DEBUG
      
      api:
        insecure: true
      
      # This is required
      entryPoints:
        web:
          address: ':80'
        websecure:
          address: ':443'
      
      providers:
        file: # Required, if you use traefik.yml as your main configuration
          directory: /etc/traefik
          watch: true
        docker:
          exposedByDefault: false
          swarmMode: true
          watch: true
      

      使用 traefik cli 标志的工作方法

      docker-compose.stack.yml

      version: '3.7'
      services:
        traefik:
          image: traefik:2.0
          deploy:
            mode: global
            placement:
              constraints:
              - node.role == manager
            restart_policy:
              condition: on-failure
          command:
            - --log.level=DEBUG
            - --api.insecure=true
            - --ping=true
            - --entrypoints.web.address=:80
            - --entrypoints.websecure.address=:443
            - --providers.docker.swarmmode=true
            - --providers.docker.exposedbydefault=false
            - --providers.docker.network=load_balancer
            - --providers.docker.watch=true
          ports:
          - 80:80
          volumes:
          - /var/run/docker.sock:/var/run/docker.sock
          networks:
          - load_balancer
      networks:
        load_balancer:
          external: true
          name: load_balancer
      

      whoami.yml(用于测试目的)

      version: '3.7'
      services:
        whoami:
          image: containous/whoami
          deploy:
            labels:
            - traefik.enable=true
            - traefik.docker.network=load_balancer
            - traefik.http.routers.whoami.entrypoints=web
            - traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)
            - traefik.http.services.whoami.loadbalancer.server.port=80
          networks:
          - load_balancer
      networks:
        load_balancer:
          external: true
          name: load_balancer
      
      

      通过 curl 测试

      curl -H Host:whoami.docker.localhost 127.0.0.1
      

      【讨论】:

        【解决方案3】:

        我可以建议您不要使用 traefik.yml,而是使用 cli 参数来配置您的实例。

        你可以这样:

        version: "3.7"
        
        services:
          ingress:
            image: traefik:v2.0
            networks:
              - ingress-net
            ports:
              - "80:80"
              - "443:443"
              # TCP Port if needed for any service you have
              - "60000:60000"
            command:
              ###                          ###
              # Traefik Global Configuration #
              ###                          ###
              # Enable DEBUG logs
              - "--log.level=DEBUG" # DEBUG, INFO, etc...
              - "--ping=true"
              # Enable api access without authentification (only GET route so it only possible to get IPs)
              - "--api.insecure=true" # You can insecure here, because It accessible only in the container if you didn't open the port.
              # Set the provider to Docker
              - "--providers.docker=true"
              # Set the docker network
              - "--providers.docker.network=ingress-net"
              # Set to docker swarm cluster
              - "--providers.docker.swarmMode=true"
              # If False : Do not expose containers to the web by default
              - "--providers.docker.exposedByDefault=false"
              # Default rule to service-name.example.com
              - "--providers.docker.defaultRule=Host(`{{ trimPrefix `/` .Name }}.example.com`)"
              # Default http port
              - "--entrypoints.http.address=:80"
              # Default https port
              - "--entrypoints.https.address=:443"
              # Enable let's encrypt
              - "--certificatesResolvers.certbot=true"
              - "--certificatesResolvers.certbot.acme.httpChallenge=true"
              - "--certificatesResolvers.certbot.acme.httpChallenge.entrypoint=http"
              - "--certificatesResolvers.certbot.acme.email=admin@example.com"
              - "--certificatesResolvers.certbot.acme.storage=/letsencrypt/acme.json"
              # TCP Entrypoint if needed
              - "--entrypoints.tcpendpointname.address=:60000"
        
            volumes:
              - /var/run/docker.sock:/var/run/docker.sock:ro
              - ./acme.json:/letsencrypt/acme.json
        
            deploy:
              replicas: 1
              labels:
                ###               ###
                # Traefik Dashboard #
                ###               ###
                # Enable this endpoint
                - traefik.enable=true
                ##
                # Http
                #
                # Set the service route
                - traefik.http.routers.ingress_http.rule=Host(`ingress.example.com`)
                # Set the entrypoint (http or https)
                - traefik.http.routers.ingress_http.entrypoints=http
                # Rule to redirect to http to https
                - traefik.http.middlewares.ingress-https-redirect.redirectscheme.scheme=https
                # Enable Https redirection
                - traefik.http.routers.ingress_http.middlewares=ingress-https-redirect@docker
                #
                ##
        
                ##
                # Https
                #
                - traefik.http.routers.ingress_https.rule=Host(`ingress.example.com`)
                # Set the entrypoint (http or https)
                - traefik.http.routers.ingress_https.entrypoints=https
                # Enable Let's encrypt auto certificat creation
                - traefik.http.routers.ingress_https.tls.certresolver=certbot
                # Enable authentification
                - traefik.http.routers.ingress_https.middlewares=ingress-auth@
                # Uncommant this to enable basic authentification
                # - traefik.http.middlewares.ingress-auth.basicauth.users=admin:$$this$$is$$encrypted$$password
                #
                ##
        
                ##
                # TCP Endpoint
                #
                # Set the service route
                - "traefik.tcp.routers.tcpendpointname.rule=HostSNI(`*`)"
                # Here you can set the host uri if you use tls only.
                # - "traefik.tcp.routers.tcpendpointname.rule=HostSNI(`tcp.example.com`)"
                # - "traefik.tcp.routers.tcpendpointname.tls=true"
                # Set the entrypoin
                - "traefik.tcp.routers.tcpendpointname.entrypoints=tcpendpointname"
                #
                ##
        
                ##
                # Service
                #
                # Set the service port
                - traefik.http.services.ingress.loadbalancer.server.port=8080
                #
                ##
              placement:
                constraints:
                  - node.role == manager
        
        networks:
          ingress-net:
            external: true
        

        希望对你有帮助。

        您可以对任何其他使用相同逻辑的容器使用相同的标签。

        【讨论】:

        • 我认为建议一种具有完全不同上下文的不同方法而不是首先尝试理解 OP 的设置没有任何帮助。它也不会帮助该线程的其他访问者。
        【解决方案4】:

        因为你有一个404 page not found Traefik 似乎可用。

        但是,当使用 curl 获取http://127.0.0.1 时,此IP 地址将成为请求的Host 标头字段的内容。 Traefik 又使用它来路由请求。由于您的 whoami 服务旨在匹配对主机 whoami.docker.localhost 的请求,因此 Traefik 的给定响应很好。

        您是否尝试过获取http://whoami.docker.localhost?在使用 curl 进行测试之前,您可能需要将此主机名注入主机 /etc/hosts 文件。

        127.0.0.1 whoami.docker.localhost
        

        或者,您可以尝试使用 netcat 之类的工具(有时以 nc 的形式提供)手动 HTTP 请求:

        # netcat 127.0.0.1 80
        GET / HTTP/1.0
        Host: whoami.docker.localhost
        
        

        按照HTTP的要求,输入第二行请求后需要按两次回车。

        【讨论】:

          【解决方案5】:

          端口检测

          Docker Swarm 不向 Traefik 提供任何 port detection 信息。

          因此,您必须使用标签 traefik.http.services..loadbalancer.server.port 指定用于通信的端口(查看routing section for Docker 中此标签的参考)。

          【讨论】:

            【解决方案6】:

            Traefik 的 Docker 服务发现需要 container labels instead of image labels(检查 traefik's quickstart)。

            以下最小的工作示例适用于 docker swarm:

            version: '3.7'
            
            services:
              traefik:
                image: traefik:2.0
                command: --providers.docker
                ports:
                  - 80:80
                volumes:
                  - /var/run/docker.sock:/var/run/docker.sock
            
              whoami:
                image: containous/whoami
                labels:   # defining a container label instead of an image label
                  - "traefik.http.routers.whoami.rule=Host(`whoami.docker.localhost`)"
            

            【讨论】:

            • 我不认为这个特定的例子适用于 Docker Swarm。您的链接目标没问题,但故意关注错误的解决方案。标签必须在deploy: 容器中为每个服务定义。请参阅related docs在 Swarm 模式下,Traefik 使用服务上的标签,而不是单个容器上的标签。
            • @ThomasUrban 我的示例是一个多应用、多网络 docker 堆栈部署的最小工作示例,我现在正在运行 Traefik2.0 作为入口控制器。启动一个“hello world”示例来试一试。
            • 嗯,我自己在用 Docker swarm 运行 Traefik,所以肯定有些奇怪。我只是指出您的帖子似乎自相矛盾,而且似乎与 Traefik 文档本身的陈述相反。你说“需要容器标签”...... Traefik 说“在服务上找到标签,而不是在单个容器上”......所以,它现在可能对你有用,但它仍然与 Traefik 的建议相反。在这种情况下,我宁愿坚持官方建议,以尽可能地面向未来。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-10-20
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多