traefikを使ってリクエストをロードバランシング&リバースプロキシしてみよう

# traefikとは
traefikとは動的な設定が可能な、エッジルーター(ロードバランサー＆リバースプロキシ)です。　　
オープンソースでGo言語で作られているのが特徴です。
[Traefik Labs](https://traefik.io/)というフランスの企業で開発されています。
基本的にコンテナとして使用され、Kubernetesとも相性が良いです。

https://doc.traefik.io/traefik/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/964196/a3b7e553-9195-436c-2565-f9a5fbf4998d.png)

# 早速使ってみる
今回構築する構成は下図の通りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/964196/16857a43-1bc3-91ac-86f5-6e902d40fbb4.png)

- コンテナ管理はdocker-composeを使用
- リクエストパスに応じて各コンテナへリバースプロキシする
- 3個のnginxコンテナはラウンドロビンでロードバランシングする

GitHubにサンプルがあるので、git pullしてREADMEの手順を実行して確認できます。

https://github.com/hdk-t/traefik-example

## 環境
MacBookAir(2019) 16GB
MacOS Monterey 12.3.1

## traefikの設定
traefikの設定方法は大きく２種類あります
- 静的設定(Static Configuration)
  - yaml記法または、toml記法で記述します
  - 静的設定の変更にはコンテナの再起動が必要です
- 動的設定(Dynamic Configuration)
  - 設定方法がいくつか存在します。(Docker,file,k8s etc..)
  - 動的設定の変更はコンテナの再起動を必要としません

今回は動的設定の方法にDockerを使用します。
Dockerを使用した動的設定の方法は、コンテナのラベルにtraefikの属性を付与することで設定できます。
traefikは常に同じdocker networkのコンテナを監視しており、それらの変更や追加を検知して動的な設定を実現させています。

traefikコンテナの設定です。
```./gateway/docker-compose.yml
version: '3'
networks:
  traefik_example_network:
    external: true
services:
  traefik:
    image: traefik:v2.6.1
    restart: always
    environment:
      - TZ=Japan
    ports:
      - target: 80
        published: 80
        protocol: tcp 
        mode: host
    security_opt:
      - no-new-privileges:true
    networks:
      - traefik_example_network
    volumes:
      - ./logs:/var/logs
      - ./traefik:/etc/traefik
      - /var/run/docker.sock:/var/run/docker.sock:ro,cached
    labels:
      ### traefik configration
      - traefik.enable=true
      - traefik.http.routers.dashboard.rule=(Host(`traefik.localhost`))
      - traefik.http.routers.dashboard.service=api@internal
```
traefikの静的設定です。yaml記法で記述します。
```./gateway/traefik/traefik.yml
providers:
  docker:
    exposedByDefault: false
    network: proxy
    watch: true
entrypoints:
  http:
    address: ":80"
    forwardedHeaders:
      insecure: true
      trustedIPs:
        - "127.0.0.1/32"
        - "172.0.0.1/8"
        - "192.168.0.0/16"
api:
  dashboard: true
  insecure: false
log:
  level: INFO
experimental:
  http3: true
global:
  sendAnonymousUsage: false
accessLog:
  filePath: "/var/logs/access.log"
  bufferingsize: 100
  filters:
    statuscodes: 
      - "100-599"
    retryattempts: true
    minduration: "100ms"
  fields:
    names:
      StartUTC: drop
```

## webサーバーの設定

今回はwebサーバーにNginxとApacheのコンテナを使用します。
```./web/docker-compose.yml
version: '3'
networks:
  traefik_example_network:
    external: true
services:
  nginx:
    image: nginx
    restart: always
    networks: 
      - traefik_example_network
    labels:
      ### traefik configration
      - traefik.enable=true
      - traefik.http.routers.nginx.rule=PathPrefix(`/nginx`)
      - traefik.http.services.nginx.loadbalancer.server.port=80
      - traefik.http.middlewares.nginx-omitprefix.stripprefix.prefixes=/nginx
      - traefik.http.routers.nginx.middlewares=nginx-omitprefix
  apache:
    image: httpd
    restart: always
    networks:
      - traefik_example_network
    labels:
      ### traefik configration
      - traefik.enable=true
      - traefik.http.routers.apache.rule=PathPrefix(`/apache`)
      - traefik.http.services.apache.loadbalancer.server.port=80
      - traefik.http.middlewares.apache-omitprefix.stripprefix.prefixes=/apache
      - traefik.http.routers.apache.middlewares=apache-omitprefix
```

## 起動とスケールアップ
設定ファイルの記述が完了したら、専用のdocker networkを作成して、コンテナを立ち上げます。
  `docker network create traefik_example_network`

  `docker-compose -f ./gateway/docker-compose.yml up -d`

  `docker-compose -f ./web/docker-compose.yml up -d`

この時点で下記にアクセスできるはずです。

traefikのダッシュボード
http://traefik.localhost

Nginx
http://localhost/nginx

Apache
http://localhost/apache

上記が確認できたら、nginxをスケールアップします。
`docker-compose -f ./web/docker-compose.yml scale nginx=3`

これで、最初の図のような状態になりました。
アクセスログを見るとラウンドロビンでロードバランシングされている事が分かります。