# traefik-gateway-dashboard

**本文为dashboard用法，基础用法请参考：[traefik-gateway](http://qq829.cn/book/books/42e7a/page/traefik-gateway)**

**重要bug提醒**：截止至2023-06-22,如果动态创建的服务发现，少于1个中间件，则会出错，既需要保证整个项目至少要有一个中间件。可以随便写一个，但是必须要有一个。

### 三个镜像

**2023-06-21:无需再部署dashboard**

- **traefik**
  - swr.cn-south-1.myhuaweicloud.com/vp-whdev/all-in-devops/traefik:v1.4.20231227
    - 内置插件：rewritebody
    - 内置插件：rewriteHeaders
    
  > 更新日志：2023-12-27
  >> - 增加环境变量： "INDEX_ROOT=/root/"
  >>> 以支持动态创建首页不是从根目录开始。既不再需要单独挂载配置以设置首页不是从根目录开始，注意路径需要 **/dir/** 的前后2个反斜杠（/）都需要。因为内部方式为字符串替换， `sed -i 's|/traefik-dashboard/|'${INDEX_ROOT}'traefik-dashboard/|g' /etc/traefik/conf.d/traefik-dashboard.yaml` 应用程序不会处理任何额外的内容。你也可以继续使用外挂文件自行处理首页不是根目录（不推荐）。
  >>>
  >>> 
  >> - 增加环境变量:'PASSWRD=admin:httpwd'
  >>>  可以在外部设置用户名和密码,密码使用`htpasswd`方式是生成，在线生成网址：http://www.jsons.cn/htpasswd/
  >>> 注意，由于设置放置于环境变量，需要将($)特殊符号进行处理，($)使用($$)

  > 更新日志：2023-06-26
  >> - 修改内置插件偶尔会失效的问题

- **动态服务发现**
  - swr.cn-south-1.myhuaweicloud.com/vp-whdev/all-in-devops/traefik-service-discovery:v1.4.20231227
 
  > 更新日志：2023-12-27
  > > - 增加监控和告警功能
  > > - 修改配置文件值
  > >  > spring.profiles.active = dev|prod|sqlite-dev|sqlite-prod
  > >  > dev和prod为mysql数据库，sqlite-dev和sqlite-prod为sqlite数据库。由于sqlite数据不支持某些特性，将被弃用。
  > > 
  > 更新日志：2023-06-28
  > >  - 动态服务发现静态资源添加服务监控前端代码
  > >  - 修复镜像包运行entrypoint.sh文件不存在问题
  > >  - mysql数据脚本调整
  
  > 更新日志：2023-06-21：
  > >  - 打包dashboard面板到一个服务，无需再部署dashboard
  > >  - 增加服务监控
  
- **~~dashboard面板~~**
  - ~~swr.cn-south-1.myhuaweicloud.com/vp-whdev/all-in-devops/traefik-service-discovery-dashboard-front:stage~~
  > ~~更新日志：2023-06-21~~
  > >  - ~~dashboard面板已经集成到动态服务发现,无需部署~~


### 安装部署说明



- 部署: traefik

```
# 建议服务名：traefik-gateway
# 端口开放
# 80，http端口
# 443,https端口
# 8080,traefik自带的dashboard端口，可以不开放
  ```

- 部署traefik-service-discovery

```
# 服务名必须为 traefik-service-discovery


# 端口开放
# 8080，非必须

# 环境变量

spring.profiles.active = prod|sqlite-prod

# prod，使用mysql数据库,sqlite-prod，使用sqlite数据库，sqlite不支持服务监控,不推荐使用，在未来的版本中，sqlite数据库将被弃用。
# 如果使用sqlite数据库，需要注意数据库持久化路径，容器目录/data,容器初始化时会自动复制初始化数据库文件。


# 设置mysql数据库配置

app.datasource.host =
app.datasource.name=
app.datasource.password =
app.datasource.username =

```


- 数据库初始化脚本



数据库初始化脚本下载：<https://iovhm.com/book/attachments/14>


- ~~traefik-service-discovery-dashboard-fron~~


```shell

# 2023-06-21,本服务已经集成到traefik-service-discovery，不需要部署
# 端口开放:80
# 访问路径/front/

```

- 负载均衡配置
  
|路径|服务|说明|备注|
|---|---|---|---|
|/|traefik|网站根目录|必须|
| /traefik-dashboard/ | traefik|traefik内置的dashboard|非必须，如果没有配置网站根目录则需要|
| /traefikconfig-dashboard/|traefik|traefik动态路由dashboard|非必须，如果没有配置网站根目录则需要|
|/traefik-service-discovery/|traefik|动态路由api|非必须，如果没有配置网站根目录则需要|

### 首页不是从根目录开始


如果你的首页不是从根目录开始，则需要做一些单独的配置，实现原理为，将dashboard需要用到的3个路径处理为所需要的目录。

复制下面的配置文件，挂载到traefik-gatewy的容器路径


```yaml

# 使用k8s集群时，建议使用配置映射卷

./index-not-root.yaml:/etc/traefik/conf.d/conf2/index-not-root.yaml

```



**需要在负载均衡加入配置**

|路径|服务|说明|备注|
|---|---|---|---|
|/minio/|traefik|业务路由入口|必须|
| /_minio/|traefik|面板路由入口|如果配置了下面三个路径，则是非必须|
| /_minio/traefik-dashboard/|traefik|traefik内置的dashboard|非必须，如果没有配置面板入口则需要|
| /_minio/traefikconfig-dashboard/|traefik|动态路由dashboard|非必须，如果没有配置面板入口则需要|
| /_minio/traefik-service-discovery/|traefik|动态路由api|非必须，如果没有配置面板入口则需要|


```yaml

http:
  routers:
    # 首页不是根目录
    index-not-root:
    # 注意路由匹配前缀，填写你的实际路径，为了保证一致性，建议本服务使用 _ 开头
    # 注意中间件中的路径前缀，应该和路由路径一致，
    # 注意重写header的前缀，应该和路由路径一致。
    # 根据本路由规则，可以看出是将服务又重定向到traefik-gateway,即多了一层不必要的代理，会带来性能损失。
    # 由此，这个额外的路由，只应该用于处理traefik控制面板
    # 真正的服务不应该由此处理，而应该直接指向到traefik-gateway
    # 既你需要配置面板路由路径，应该与你的服务路径，使用不通的名称
    # 本次使用的是 _minio ,请将本文的_minio 替换为你需要的
      # rule: "PathPrefix(`/_minio/`)" 
    # 2023-06-22,：只处理dashboard相关的3个路径，以开启面板，业务路由在面板进行配置，以解决多了一层代理问题   
      rule: "PathPrefix(`/_minio/traefik-dashboard/`) || PathPrefix(`/_minio/traefikconfig-dashboard/`) || PathPrefix(`/_minio/traefik-service-discovery/`)"  
      service: index-not-root
      middlewares:
        - stripPrefix-index-not-root
        - rewritebody-index-not-root
        - rewriteHeaders-index-not-root
  services:
    index-not-root:
      loadBalancer:
        servers:
          - url: http://traefik-gateway:80    # 部署的traefik主程序必须叫这个名字或者修改为实际部署的名字
  middlewares:
  # 去除前缀  
    stripPrefix-index-not-root:
      stripPrefix:
        prefixes:
          - "/_minio/"
  # 正文路径改写
    rewritebody-index-not-root:
      plugin:
        plugin-rewritebody:                   # 要和静态配置文件的插件名称对应上
          rewrites:
            - regex: "/traefik-service-discovery/api/"
              replacement: "/_minio/traefik-service-discovery/api/"
            - regex: "/traefik-dashboard/api"
              replacement: "/_minio/traefik-dashboard/api"
            - regex: "/_minio/dashboard/"
              replacement: "/_minio/traefik-dashboard/dashboard/"
  # Header重定向改写
    rewriteHeaders-index-not-root:
      plugin:
        plugin-rewriteHeaders:                # 要和静态配置文件的插件名称对应上
          rewrites:
            - header: "Location"
              regex: "/_minio/dashboard/"
              replacement: "/_minio/traefik-dashboard/dashboard/"



```
  


### 插件使用


[插件参考网址](https://doc.traefik.io/traefik/middlewares/http/overview/)


```yaml

middlewares:
# 删除路径前前缀，traefik默认会把整个URL路径全部传过来，会导致与后端路径不一致，需要进行路径删除处理
  stripPrefix-traefikconfig-dashboard:
    stripPrefix:
      prefixes:
        - "/traefikconfig-dashboard/"

# 增加路径前缀，对应与后端服务，即使在填写URL路径，traefik也不会处理后端路径，会导致与后端路径不一致，需要增加实际路径
  addPrefixFront-traefikconfig-dashboard:
    addPrefix:
      prefix: "/front/"

  # 正文路径改写
    rewritebody-traefikconfig-dashboard:
      plugin:
      # 要和静态配置文件的插件名称对应上
        plugin-rewritebody: 
          rewrites:
            - regex: "/api/"
              replacement: "/traefik-service-discovery/api/"   

# 基础身份验证
  basicAuth-traefikconfig-dashboard:
      basicAuth:
        removeHeader: true
        users:
          - "admin:" # 在线生成 http://www.jsons.cn/htpasswd/


# 发送到后端时修改header,例如后端限制了域名
  headers-peisong:
    headers:
      customRequestHeaders:
        host: "peisong.gxzszs.cn"

# 重写 header，对响应的head进行处理，例如写死的重定向
  rewriteHeaders-peisong:
    plugin:
      plugin-rewriteHeaders: # 要和静态配置文件的插件名称对应上，本镜像仅能使用这个名字
        rewrites:
          - header: "Location"
            regex: "peisong.gxzszs.cn"
            replacement: "peisong.gxfusui.com"
          - header: "Location"
            regex: "http://peisong.gxfusui.com/plugin.php"
            replacement: "/plugin.php"




```

#### 在plugin-rewritebody使用正则表达式需要注意的事项

如下面的代码所示，一个使用了双反斜杠，一个使用的是单反斜杠，实际上取决于最外围的引号，这是json决定的，而不是这里的字符串的问题，需要注意。

需要转义的字符有：

- `\` 转义为 `\\`
- `"` 转义为`\"`
- `()` 转义为 `\\(\\)`

```yaml

middlewares:
  rewritebody-iams-pis:
    plugin:
      plugin-rewritebody:
        rewrites:
          - regex: '\bpis.guizhougas.cn\b'
            replacement: 'iams-pis.shulianhuiyun.com'

  rewritebody-iams-iot:
    plugin:
      plugin-rewritebody:
        rewrites:
          - regex: "\\biot.shulianhuiyun.com\\b"
            replacement: "iams-iot.shulianhuiyun.com"

```