自定义 Traefik2 中间件

栏目: IT技术 · 发布时间: 4年前

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

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 <file>..." 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: */*
>
< HTTP/1.1 403 Forbidden
< Content-Length: 0
< Content-Type: text/plain; charset=utf-8
< Date: Mon, 20 Jan 2020 04:00:15 GMT
< Server: bfe
< X-New-Response-Header: QikQiak
<
* Connection #0 to host localhost left intact

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

...
< X-New-Response-Header: QikQiak
...

同时也可以发现 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

参考资料

自定义 Traefik2 中间件

微信公众号

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

自定义 Traefik2 中间件

「真诚赞赏,手留余香」


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

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

算法神探

算法神探

[美] 杰瑞米·库比卡 / 啊哈磊、李嘉浩 / 电子工业出版社 / 2017-2 / 65

《算法神探:一部谷歌首席工程师写的CS小说》围绕程序设计典型算法,精心编织了一个扣人心弦又趣味横生的侦探缉凶故事。小说主人公运用高超的搜索技巧和精深的算法知识,最终识破阴谋、缉拿元凶。其间,用二分搜索搜查走私船、用搜索树跟踪间谍、用深度优先搜索逃离监狱、用优先队列开锁及用最佳优先搜索追寻线索等跌宕起伏又富含算法精要的情节,让读者在愉悦的沉浸式体验中快速提升境界,加深对程序世界的理解。《算法神探:一......一起来看看 《算法神探》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

URL 编码/解码
URL 编码/解码

URL 编码/解码