linkerd实战(3)HTTP1.1 Identifiers详解

概述
上一篇我们一步一步搭建了linkerd示例,用到了默认的Identifier将服务调用方的请求转换成service name。现在我们来具体了解一下linkerd中Identifier的使用。
在linkerd中所有的基于http/1.1协议的Identifier都有一个kind属性配置,不同的kind配置使用不同转换策略对请求进行转换生成service name。如果不配置默认为kind:io.l5d.header.token

Header Token Identifier
将使用http header的项作为servive name的标识。如果不设置header名称,默认会使用Host。
kind:io.l5d.header.token
额外属性配置:
配置名
默认值
描述
header
Host
选用哪个Http Header作为service name标识
转换目标service name模板:
/ dstPrefix / [headerValue]

模板占位符
默认值
描述
dstPrefix
/svc
在routers中配置的dstPrefix前缀值
headerValue
N/A
配置的header值
示例:
修改示例,我们采用test-header作为自定义的header,配置调整如下:
routers:
- protocol: http
identifier:
kind: io.l5d.header.token
header: test-header
dtab: |
/svc => /#/io.l5d.fs;
servers:
- port: 4140
ip: 0.0.0.0

运行:
$ curl -H "test-header:test" http://127.0.0.1:4140
It works!

Method and Host Identifier
将组合使用http header的项Host,method和URL(可选)作为servive name的标识。
kind: io.l5d.methodAndHost
额外属性配置:
配置名
默认值
描述
httpUriInDst
false
是否把请求uri作为service name标识的一部分,
建议使用path identifier来更精确控制uri

Http1.1中转换目标service name模板:
/ dstPrefix / 1.1 / method / host [/ uri* ]

Http1.0中转换目标service name模板(没有host信息):
/ dstPrefix / 1.1 / method [/ uri* ]

模板占位符
默认值
描述
dstPrefix
/svc
在routers中配置的dstPrefix前缀值
method
N/A
请求method,如get、post、head等
host
N/A
请求的Host header,大小写敏感,在http1.0不适用
uri
Not used
只在将path作为service name一部分时使用
示例:
修改示例,配置调整如下:
routers:
- protocol: http
identifier:
kind: io.l5d.methodAndHost
dtab: |
/svc => /#/io.l5d.fs;
servers:
- port: 4140
ip: 0.0.0.0

运行:
$ curl -H "test-header:test" http://127.0.0.1:4140
No hosts are available for /svc/1.1/GET/test, Dtab.base=[/svc=>/#/io.l5d.fs], Dtab.local=[] ...
这时候我们的请求被转换成/svc/1.1/GET/test,对应的服务发现没有配置。

我们把之前定义在disco下的test文件复制到1.1/GET下面
$ cp disco\test disco\1.1\GET\

再次运行:
$ curl -H "test-header:test" http://127.0.0.1:4140
It works!

Path Identifier
将使用path或path中部分路径作为servive name的标识。可以通过额外配置指定截取url前几个“/”作为service name。
kind: io.l5d.path
额外属性配置:
配置名
默认值
描述
segments
1
path中前几段作为service name
consume
false
是否把path中匹配到的部分路径从请求中移除,如果true,
则发往目标地址请求不再携带匹配到的路径

Http1.1中转换目标service name模板:
/ dstPrefix [/ *urlPath ]

模板占位符
默认值
描述
dstPrefix
/svc
在routers中配置的dstPrefix前缀值
urlPath
N/A
根据segments配置截取的path中匹配到的部分路径
示例:
修改示例,配置调整如下:
routers:
- protocol: http
identifier:
kind: io.l5d.path
segments: 1
consume: true
dtab: |
/svc => /#/io.l5d.fs;
servers:
- port: 4140
ip: 0.0.0.0

运行:
$ curl http://127.0.0.1:4140 /test
It works!

如果我们不配置consume,则发往目标请求也会带上/test,导致404错误。

Header Identifier
将单独使用Http Header中的项作为servive name的标识。因为service name 标识路径,因此配置的Header项的值必须/开头。
kind: io.l5d.header
额外属性配置:
配置名
默认值
描述
header
l5d-name
作为service name的header项

Http1.1中转换目标service name模板:
/ dstPrefix [*headerValue ]

模板占位符
默认值
描述
dstPrefix
/svc
在routers中配置的dstPrefix前缀值
headerValue
N/A
配置的header项的值
示例:
修改示例,配置调整如下:
routers:
- protocol: http
identifier:
kind: io.l5d.header
header:test-header
dtab: |
/svc => /#/io.l5d.fs;
servers:
- port: 4140
ip: 0.0.0.0

运行:
$ curl -H "test-header:/test" http://127.0.0.1:4140
It works!

如果header的值不是/开头,则linkerd在做识别的时候会抛出错误。
$ curl -H "test-header:test" http://127.0.0.1:4140
Unknown destination: Request("GET /", from /127.0.0.1:50727) / '/' expected but 't' found at '[t]est'

Ingress Identifier
将使用 Kubernetes ingress controller,通过请求比较ingress resource rules,然后根据规则返回service name。
kind: io.l5d.ingress
额外属性配置:
配置名
默认值
描述
namespace
(all)
ingress resources部署的命名空间,默认搜索所有
ingressClassAnnotation
linkerd
当使用  multiple ingress controllers ,
Linkerd只会选择带这个注解的类
ignoreDefaultBackends
false
标识仅匹配显示申明 host或者path的请求
host
localhost
Kubernetes master host.
port
8001
Kubernetes master port.

Http1.1中转换目标service name模板:
/ dstPrefix / namespace / port / service

模板占位符
默认值
描述
dstPrefix
/svc
在routers中配置的dstPrefix前缀值
namespace
N/A
Kubernetes namespace
port
N/A
端口
service
N/A
服务名
示例:
修改示例,配置调整如下:
routers:- protocol: http identifier: kind: io.l5d.ingress namespace: default servers: - port: 4140 dtab: /svc => /#/io.l5d.k8snamers:- kind: io.l5d.k8s

假设ingeress resource配置:

apiVersion: extensions/v1beta1kind: Ingressmetadata: name: my-first-ingress namespace: defaultannotations: kubernetes.io/ingress.class: "linkerd"spec: rules: - http: paths: - path: /testpath backend: serviceName: test servicePort: 80

请求 http://localhost:4140/test将转换为/svc/default/80/test,因需要k8s环境,这里不做代码演示。


Istio Identifier
将请求和  istio route-rules 比对并基于规则转换成service name。
kind: io.l5d.k8s.istio
额外属性配置:
配置名
默认值
描述
discoveryHost
istio-pilot
 Istio-Pilot 主机
discoveryPort
8080
 Istio-Pilot 主机服务发现端口
apiserverHost
istio-pilot
 Istio-Pilot 主机
apiserverPort
8081
 Istio-Pilot 主机api server端口

Http1.1中转换目标service name模板:
请求未匹配k8s集群
/ dstPrefix / "ext" / host / port
请求未匹配route-rule
/ dstPrefix / "dest" / cluster / "::" / port
请求匹配route-rule
/ dstPrefix / "route" / routeRule

模板占位符
默认值
描述
dstPrefix
/svc
在routers中配置的dstPrefix前缀值
routeRule
N/A
匹配请求的规则名称
host
N/A
请求的host
cluster
N/A
请求的集群
port
N/A
请求的port
示例:
修改示例,配置调整如下:
routers:- protocol: http identifier: kind: io.l5d.k8s.istio

因需要k8s环境,这里不做代码演示。

Static Identifier

将所有请求转换为静态的service name固定值。
kind: io.l5d.static
额外属性配置:
配置名
默认值
描述
path
required
作为service name的值

Http1.1中转换目标service name模板:
/ dstPrefix / *path

模板占位符
默认值
描述
dstPrefix
/svc
在routers中配置的dstPrefix前缀值
path
N/A
配置的path的值
示例:
修改示例,配置调整如下:
routers:- protocol: http identifier: kind: io.l5d.static path: /test

运行:
$ curl http://127.0.0.1:4140
It works!

小结
Linkerd在路由请求的第一阶段,将请求转换为serveice name的时候,提供了一组Identifiers来处理转换。若不能满足需要,还可以自己开发Identifier作为插件来扩展功能。

你可能感兴趣的:(linkerd)