热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

自定义Traefik2中间件

Traefik2.X版本发布以来受到了很大的关注,特别是提供的中间件机制非常受欢迎,但是目前对于用户来说能使用的也只有官方提供的中间件,这对于某些特殊场景可能就满足不了需求了,自然而然就想到了自定义中间件,然而现在要想自定义中间件不是一件容易的事情,虽然实现一个中间件很简单,因为目前官方没有提供方法可以将我们自定义的中间件配置到Traefik中,所以只能采用比较low的一种方法,那就是直接更改官方

Traefik 2.X 版本发布以来受到了很大的关注,特别是提供的中间件机制非常受欢迎,但是目前对于用户来说能使用的也只有官方提供的中间件,这对于某些特殊场景可能就满足不了需求了,自然而然就想到了自定义中间件,然而现在要想自定义中间件不是一件容易的事情,虽然实现一个中间件很简单,因为目前官方没有提供方法可以将我们自定义的中间件配置到 Traefik 中,所以只能采用比较 low 的一种方法,那就是直接更改官方的源代码了,下面我们以一个简单的示例来说明下如何自定义一个 Traefik 中间件。

自定义

首先下载 Traefik 源码,切换到最新的 v2.1 代码分支:

$ git clone https://github.com/containous/traefik
$ cd traefik
$ git checkout v2.1
$ git checkout -b dev

在 v2.1 分支基础上创建一个本地的 dev 分支,然后添加我们自定义的 luascript 中间件:

$ git submodule add https://github.com/cnych/traefik2-luascript pkg/middlewares/luascript
$ git status
On branch dev
Changes to be committed:
  (use "git reset HEAD ..." to unstage)

        new file:   .gitmodules
        new file:   pkg/middlewares/luascript

这样就将我们自定义的 luascript 中间件代码添加到了 Traefik 源码中,但是这还不够,只是声明了中间件而已,还需要将该中间件配置到 Traefik 的中间件中去才能生效,前往 pkg/config/dynamic/middleware.go 文件在 Middleware 结构体下面添加自定义脚本字段:

// pkg/config/dynamic/middleware.go
// Middleware holds the Middleware configuration.
type Middleware struct {
    ......
    LuaScript         *LuaScript         `json:"lua,omitempty" toml:"lua,omitempty" yaml:"lua,omitempty"`
}

// +k8s:deepcopy-gen=true

// LuaScript config
type LuaScript struct {
	Script string `json:"script,omitempty" toml:"script,omitempty" yaml:"script,omitempty"`
}

然后在服务端构建器中注册上面定义的 LuaScript 中间件,代码位于 pkg/server/middleware/middlewares.go ,在 buildConstructor 方法中添加上自定义中间件的信息:

// pkg/server/middleware/middlewares.go
import (
    // ...
    "github.com/containous/traefik/v2/pkg/middlewares/luascript"  
    // ...
)

// ...

// it is the responsibility of the caller to make sure that b.configs[middlewareName].Middleware exists
func (b *Builder) buildConstructor(ctx context.Context, middlewareName string) (alice.Constructor, error) {
    // ... other middlewares

    // LuaScript
	if config.LuaScript != nil {
		if middleware != nil {
			return nil, badConf
		}
		middleware = func(next http.Handler) (http.Handler, error) {
			return luascript.New(ctx, next, *config.LuaScript, middlewareName)
		}
	}

	if middleware == nil {
		return nil, fmt.Errorf("invalid middleware %q configuration: invalid middleware type or middleware does not exist", middlewareName)
	}

	return tracing.Wrap(ctx, middleware), nil
}

到这里我们就完成了自定义中间件。

测试

接下来重新编译打包 Traefik 即可:

$ go generate
$ export GOPROXY=https://goproxy.cn 
$ export GO111MODULE=on 
$ go build ./cmd/traefik

编译完成后可以用这个包来测试下这个中间件,首先创建一个 FileProvider 的配置文件:(config.toml)

[http.routers]
  [http.routers.router1]
    service = "service1"
    middlewares = ["example-luascript"]
    rule = "Host(`localhost`)"

[http.middlewares]
 [http.middlewares.example-luascript.lua]
   script = "example.lua"

[http.services]
 [http.services.service1]
   [http.services.service1.loadBalancer]
     [[http.services.service1.LoadBalancer.servers]]
       url = "https://www.baidu.com"

这个配置文件我们使用 FileProvider 来配置了一个请求,将域名 localhost 的请求转发到 service1 这个 Service 上,在中间使用了 example-luascript 这个 lua 中间件,可以看到这里我们用 script 属性指定了一个名为 example.lua 的脚本,下面来定义这个脚本:(example.lua)

local http = require('http')
local log = require('log')

log.warn('Hello from LUA script')
http.setResponseHeader('X-New-Response-Header', 'QikQiak')

现在我们可以直接使用上面编译好的 Traefik 二进制文件来启动服务:

# 用 --providers.file 开启 FileProvider,指定配置文件
$ ./traefik --providers.file.filename=config.toml --log.level=warn 
INFO[0000] Configuration loaded from flags.

然后我们打开另外一个终端,在终端中输入如下请求命令:

$ curl -v http://localhost
* Rebuilt URL to: http://localhost/
*   Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 80 (#0)
> GET / HTTP/1.1
> Host: localhost
> User-Agent: curl/7.54.0
> Accept: */*
>
 
 

我们可以看到 baidu.com 给我们返回的响应 Header 里面有我们在 lua 脚本里面的定义信息:

...
 
 

同时也可以发现 Traefik 日志中新的记录输出:

WARN[2020-01-20T12:03:51+08:00] Hello from LUA script                         middlewareName=example-luascript@file middlewareType=LuaScript

到这里我们就完成了自定义 Traefik 中间件。不过我们也可以看到上面的方式耦合性太高了,需要我们去官方的源代码中去添加代码,这样显然不是一个很好的做法,即使我们自定义的中间件非常有用,要想合并到官方的主线中去也是比较困难的,至少时间成本非常高。在 Traefik 的 Github Issue 中也有关于自定义插件的讨论,不过讨论虽然非常热闹,不过这个已经过去两年了还是没有什么进展,所以要想等到官方支持这个特性,估计需要很长一段路要走了……

自定义 Traefik2 中间件
custom traefik middleware

参考资料

  • enable custom plugins/middlewares for Traefik #1336
  • LuaScript middleware for Traefik v2

自定义 Traefik2 中间件

微信公众号

扫描下面的二维码关注我们的微信公众帐号,在微信公众帐号中回复◉加群◉即可加入到我们的 kubernetes 讨论群里面共同学习。

自定义 Traefik2 中间件

「真诚赞赏,手留余香」


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 我们


推荐阅读
  • 先上图引入插件在pubspec.yaml中引入charts_flutter插件使用的时候版本到0.6.0,插件地址:https:github.comgooglecharts使用插件 ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • t-io 2.0.0发布-法网天眼第一版的回顾和更新说明
    本文回顾了t-io 1.x版本的工程结构和性能数据,并介绍了t-io在码云上的成绩和用户反馈。同时,还提到了@openSeLi同学发布的t-io 30W长连接并发压力测试报告。最后,详细介绍了t-io 2.0.0版本的更新内容,包括更简洁的使用方式和内置的httpsession功能。 ... [详细]
  • 李逍遥寻找仙药的迷阵之旅
    本文讲述了少年李逍遥为了救治婶婶的病情,前往仙灵岛寻找仙药的故事。他需要穿越一个由M×N个方格组成的迷阵,有些方格内有怪物,有些方格是安全的。李逍遥需要避开有怪物的方格,并经过最少的方格,找到仙药。在寻找的过程中,他还会遇到神秘人物。本文提供了一个迷阵样例及李逍遥找到仙药的路线。 ... [详细]
  • uniapp开发H5解决跨域问题的两种代理方法
    本文介绍了uniapp开发H5解决跨域问题的两种代理方法,分别是在manifest.json文件和vue.config.js文件中设置代理。通过设置代理根域名和配置路径别名,可以实现H5页面的跨域访问。同时还介绍了如何开启内网穿透,让外网的人可以访问到本地调试的H5页面。 ... [详细]
  • 本文介绍了如何使用JSONObiect和Gson相关方法实现json数据与kotlin对象的相互转换。首先解释了JSON的概念和数据格式,然后详细介绍了相关API,包括JSONObject和Gson的使用方法。接着讲解了如何将json格式的字符串转换为kotlin对象或List,以及如何将kotlin对象转换为json字符串。最后提到了使用Map封装json对象的特殊情况。文章还对JSON和XML进行了比较,指出了JSON的优势和缺点。 ... [详细]
  • 本文介绍了一个React Native新手在尝试将数据发布到服务器时遇到的问题,以及他的React Native代码和服务器端代码。他使用fetch方法将数据发送到服务器,但无法在服务器端读取/获取发布的数据。 ... [详细]
  • 本文介绍了Codeforces Round #321 (Div. 2)比赛中的问题Kefa and Dishes,通过状压和spfa算法解决了这个问题。给定一个有向图,求在不超过m步的情况下,能获得的最大权值和。点不能重复走。文章详细介绍了问题的题意、解题思路和代码实现。 ... [详细]
  • Gitlab接入公司内部单点登录的安装和配置教程
    本文介绍了如何将公司内部的Gitlab系统接入单点登录服务,并提供了安装和配置的详细教程。通过使用oauth2协议,将原有的各子系统的独立登录统一迁移至单点登录。文章包括Gitlab的安装环境、版本号、编辑配置文件的步骤,并解决了在迁移过程中可能遇到的问题。 ... [详细]
  • YOLOV4 Pytorch版本训练自建数据集和预测
    1.程序下载本文程序核心部分完全参考开源代码:https:github.comWongKinYiuPyTorch_YOLOv4。只是从一种学习的角度去写了我的代码仓库,在基础上增加 ... [详细]
  • 样式迁移(风格迁移)
    原文来源:https:arxiv.org、https:github.com作者:FujunLuan、SylvainParis、EliShechtman、KavitaB ... [详细]
  • 注:此文章仅仅作为个人使用python过程中,认为好用开源包的记录。1.邮件功能yagmailyagmail是一个高度封装的邮件包,大大减少了发邮件的代码量。2.http请 ... [详细]
  • Linux运维 第五阶段 puppet基础
    一、相关概念:1、puppet基于CS架构,使用ruby编写,在类UNIX平台上集中配置管理系统,它可以管理配置文件、用户、 ... [详细]
author-avatar
越野瘾君子_939
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有