自定義 Traefik(本地)插件

2021.12.29

Traefik 已經默認實現了很多中間件,可以滿足大部分我們日常的需求,但是在實際工作中,用戶仍然還是有自定義中間件的需求,為解決這個問題,官方推出了一個 Traefik Pilot[1] 的功能了,此外在 Traefik v2.5 版本還推出了支持本地私有插件的功能。

Traefik Pilot
Traefik Pilot 是一個 SaaS 平台,和 Traefik 進行鏈接來擴展其功能,它提供了很多功能,通過一個全局控制面板和 Dashboard 來增強對 Traefik 的觀測和控制:

  • Traefik 代理和代理組的網絡活動的指標
  • 服務健康問題和安全漏洞警報

  • 擴展 Traefik 功能的插件

    在 Traefik 可以使用 Traefik Pilot 的功能之前,必須先連接它們,我們只需要對 Traefik 的靜態配置進行少量更改即可。
     

    Traefik 代理必須要能訪問互聯網才能連接到 Traefik Pilot,通過 HTTPS 在 443 端口上建立連接。

    首先我們需要在 Traefik Pilot 主頁上(https://pilot.traefik.io/)創建一個帳戶,註冊新的 Traefik 實例並開始使用 Traefik Pilot。登錄後,可以通過選擇 Register New Traefik Instance來創建新實例。
     

    另外,當我們的 Traefik 尚未連接到 Traefik Pilot 時,Traefik Web UI 中將出現一個響鈴圖標,我們可以選擇 Connect with Traefik Pilot 導航到 Traefik Pilot UI 進行操作。
        
    登录完成后,Traefik Pilot 会生成一个新实例的令牌,我们需要将这个 Token 令牌添加到 Traefik 静态配置中。  
     

    在 Traefik 安裝配置文件中啟用 Pilot 的配置:

    1. # Activate Pilot integration 
    2. pilot: 
    3.   enabled: true 
    4.   token: "e079ea6e-536a-48c6-b3e3-f7cfaf94f477" 

      更新完成後,我們在 Traefik 的 Web UI 中就可以看到 Traefik Pilot UI 相關的信息了。
       

      接下來我們就可以在 Traefik Pilot 的插件頁面選擇我們想要使用的插件,比如我們這裡使用 Demo Plugin[2] 這個插件。

      點擊右上角的 Install Plugin 按鈕安裝插件會彈出一個對話框提示我們如何安裝。
       

      首先我們需要將當前 Traefik 註冊到 Traefik Pilot(已完成),然後需要以靜態配置的方式添加這個插件到 Traefik 中,然後添加插件啟動參數:

      1. # Activate Pilot integration 
      2. pilot: 
      3.   enabled: true 
      4.   token: "e079ea6e-536a-48c6-b3e3-f7cfaf94f477" 
      5.  
      6. additionalArguments: 
      7. # 添加 demo plugin 的支持 
      8. - --experimental.plugins.plugindemo.modulename=github.com/traefik/plugindemo 
      9. - --experimental.plugins.plugindemo.version=v0.2.1 
      10. # 其他配置 

        更新完成後創建一個如下所示的 Middleware 對象:

        1. ➜ cat <<EOF | kubectl apply -f - 
        2. apiVersion: traefik.containo.us/v1alpha1 
        3. kind: Middleware 
        4. metadata: 
        5.   name: myplugin 
        6. spec: 
        7.   plugin: 
        8.     plugindemo:  # 插件名 
        9.       Headers: 
        10.         X-Demo: test 
        11.         Foo: bar 
        12. EOF 

          然後添加到上面的 whoami 應用的 IngressRoute 對像中去:

          1. apiVersion: traefik.containo.us/v1alpha1 
          2. kind: IngressRoute 
          3. metadata: 
          4.   name: ingressroute-demo 
          5.   namespace: default 
          6. spec: 
          7.   entryPoints: 
          8.   - web 
          9.   routes: 
          10.   - match: Host(`who.qikqiak.com`) && PathPrefix(`/notls`) 
          11.     kind: Rule 
          12.     services: 
          13.     - name: whoami  # K8s Service 
          14.       port: 80 
          15.     middlewares: 
          16.     - name: myplugin  # 使用上面新建的 middleware 

            更新完成後,當我們去訪問 http://who.qikqiak.com/notls 的時候就可以看到新增了兩個上面插件中定義的兩個 Header。
             

            當然除了使用 Traefik Pilot 上開發者提供的插件之外,我們也可以根據自己的需求自行開發自己的插件,可以自行參考插件開發文檔[3]。 

       

      本地私有插件

     上面我們介紹了可以使用 Traefik Pilot 來使用插件,但是這是一個 SaaS 服務平台,對於大部分企業場景下面不是很適用,我們更多的場景下需要在本地環境加載插件,為解決這個問題,在 Traefik v2.5 版本後,就提供了一種直接從本地存儲目錄加載插件的新方法,不需要啟用 Traefik Pilot,只需要將插件源碼放入一個名為 /plugins-local 的新目錄,相對於當前工作目錄去創建這個目錄,比如我們直接使用的是 traefik 的 docker 鏡像,則入口點則是根目錄 /,Traefik 本身會去構建你的插件,所以我們要做的就是編寫源代碼,並把它放在正確的目錄下,讓 Traefik 來加載它即可。

    需要注意的是由於在每次啟動的時候插件只加載一次,所以如果我們希望重新加載你的插件源碼的時候需要重新啟動 Traefik。

    下面我們使用一個簡單的自定義插件示例來說明如何使用私有插件。首先我們定義一個名為 Dockerfile.demo 的 Dockerfile 文件,先從 git 倉庫中克隆插件源碼,然後以 traefik:v2.5 為基礎鏡像,將插件源碼拷貝到 /plugins-local 目錄,如下所示:

    1. FROM alpine:3 
    2. ARG PLUGIN_MODULE=github.com/traefik/plugindemo 
    3. ARG PLUGIN_GIT_REPO=https://github.com/traefik/plugindemo.git 
    4. ARG PLUGIN_GIT_BRANCH=master 
    5. RUN apk add --update git && \ 
    6.     git clone ${PLUGIN_GIT_REPO} /plugins-local/src/${PLUGIN_MODULE} \ 
    7.       --depth 1 --single-branch --branch ${PLUGIN_GIT_BRANCH} 
    8.  
    9. FROM traefik:v2.5 
    10. COPY --from=0 /plugins-local /plugins-local 

      我們這裡使用的演示插件和上面 Pilot 中演示的是同一個插件,我們可以通過該插件去自定義請求頭信息。
      然後在 Dockerfile.demo 目錄下面,構建鏡像:

      1. ➜ docker build -f Dockerfile.demo -t cnych/traefik-private-demo-plugin:2.5.4 . 
      2. # 推送到镜像仓库 
      3. ➜ docker push cnych/traefik-private-demo-plugin:2.5.4 

        鏡像構建完成後就可以使用這個鏡像來測試 demo 插件了,將鏡像修改成上面我們自定義的鏡像地址:

        1. image: 
        2.   name: cnych/traefik-private-demo-plugin 
        3.   tag: 2.5.4 
        4.  
        5. # 其他省略 
        6.  
        7. # 不需要开启 pilot 了 
        8. pilot: 
        9.   enabled: false 
        10.  
        11. additionalArguments: 
        12. # 添加 demo plugin 的本地支持 
        13. - --experimental.localPlugins.plugindemo.moduleName=github.com/traefik/plugindemo 
        14. # 其他省略 

          注意上面我們添加 Traefik 的啟動參數的時候使用的 --experimental.localPlugins。更新完成後就可以使用我們的私有插件來創建一個 Middleware 對象了:

          1. ➜ cat <<EOF | kubectl apply -f - 
          2. apiVersion: traefik.containo.us/v1alpha1 
          3. kind: Middleware 
          4. metadata: 
          5.   name: my-private-plugin 
          6. spec: 
          7.   plugin: 
          8.     plugindemo:  # 插件名 
          9.       Headers: 
          10.         X-Demo: private-demo 
          11.         Foo: bar 
          12. EOF 

            然後添加到上面的 whoami 應用的 IngressRoute 對像中去:

            1. apiVersion: traefik.containo.us/v1alpha1 
            2. kind: IngressRoute 
            3. metadata: 
            4.   name: ingressroute-demo 
            5.   namespace: default 
            6. spec: 
            7.   entryPoints: 
            8.   - web 
            9.   routes: 
            10.   - match: Host(`who.qikqiak.com`) && PathPrefix(`/notls`) 
            11.     kind: Rule 
            12.     services: 
            13.     - name: whoami  # K8s Service 
            14.       port: 80 
            15.     middlewares: 
            16.     - name: my-private-plugin  # 使用上面新建的 middleware 

              更新上面的資源對像後,我們再去訪問 http://who.qikqiak.com/notls 就可以看到新增了兩個上面插件中定義的兩個 Header,證明我們的私有插件配置成功了:
               

              有了本地私有插件的支持,Traefik 才算真正开始起飞吧? 

              参考资料

              [1]Traefik Pilot: https://pilot.traefik.io/

              [2]Demo Plugin: https://github.com/traefik/plugindemo

              [3]Plugin dev doc: https://doc.traefik.io/traefik-pilot/plugins/plugin-dev/