跳转至

第十三节 Mixer 适配器的应用(简介/Denier访问控制/Listchecker访问控制)

Istio 除了提供了丰富的流量控制功能,还通过Mixer:提供了可扩展的外接功能。

Mixer“知晓”每一次服务间的调用过程,这些调用过程会为Mixer:提供丰富的相关信息,Mixer通过接人的适配器对这些信息进行处理,能够在调用的预检(执行前)和报告(执行后)阶段执行多种任务

并且Mixer的适配器模型是可以扩充的,这也赋予了Mixer更大的扩展能力。

1、Mixer适配器简介

Mixer:中现有的适配器大致可以分为以下两类。

  • 一类是Istio内部实现的适配器,用于完成网格的内部功能,例如FluentdStdioRedisQuota等。
  • 另一类是第三方服务的适配器,用于和外部系统进行对接,例如DataDogStackDriver等。

本章同样从应用场景出发,介绍在Istio中使用Mixer:能够完成的各种任务,只涉及网格内部功能相关的适配器,如下所述。

  • Denier:根据自定义条件判断是否拒绝服务
  • Fluentd: 向Fluentd服务提交日志。
  • List:用于执行白名单或者黑名单检查。
  • MemQuota:以内存为存储后端,提供简易的配额控制功能。
  • Prometheus:为Prometheus提供Istio的监控指标。
  • RedisQuota:基于Redis存储后端,提供配额管理功能。
  • StatsD:向StatsD发送监控指标。
  • Stdio:用于在本地输出日志和指标。

Mixer:的配置通常由以下三部分组成

  • Handler: 声明一个适配器的配置
  • Instance: 声明一个模板,用模板将传给Mixer的数据转换为特定适配器的输出格式
  • Rule: 将InstanceHanlder连接起来, 确认处理关系

2、 基于Denier适配器的访问控制

本节会利用Denier适配器为httpbin服务创建一个Rule对象,该对象会阻止来自sleep 服务的v1版本的请求。

要使用Denier适配器, 则首先要定义它的个Handler,每个适配器都会自己的配置格式,可前往官方网站https://istio.io/docs/reference/config/policy-and-telemetry/adapters/)进行查询。

本节为Denier:适配器定义的Handler结构很简单,仅包含一个错误码和消息:

apiVersion: "config.istio.io/v1alpha2" 
kind: denier 
metadata: 
  name: code-7 
spec: 
  status: 
    code: 7 
    message: Not allowed 

这段代码意味着:如果有流量的预检请求通过Rule对象传递给了这个Handler就会调用失败,返回错误码7及错误信急Not allowed

将其保存为denier.yaml 然后使用kubectl apply命令提交到Kubernetes集群

$ kubectl apply -f denier.yaml 
denier.config.istio.io/code-7 created

我们现在只想禁止一个sleep服务的v1版本.仅通过Rule对象的match字段匹配即可因此可以使用一个checknonting的校板来定义输入.就是说无须对进入的数据进行检查

apiVersion: "config.istio.io/v1alpha2" 
kind: checknothing 
metadata: 
  name: place-holder 
spec: 

checknothing的模板因为没做任何处理.所以也是相当简单的将其深存为checknothing.yaml并使用kubectl apply命令提交到Kubernetes集群

$ kubectl apply -f checknonthing.yaml --validate=false
checknothing.config.istio.io/place-holder created

接下来就可以创建一个Rule对象把二者连接起来编辑denier.rule.yaml

apiVersion: "config.istio.io/v1alpha2" 
kind: rule 
metadata: 
  name: deny-sleep-v1-to-httpbin 
spec: 
  match: destination.labels["app"] == "httpbin" && source.labels["app"] == "sleep" && source.labels["version"] == "v1"
  actions: 
  - handler: code-7.denier 
    instances: place-holder.checknothing

注意,在instancehandler两个宇段中引用对象的方式为一名称.类型

handler: code-7.denier 
instances: [place-holder.checknothing]

match字段中使用源和目标的标签时服进行鉴别、整个表达式实现了对来自Sleep服务的v1版本向httpbin服务发起调用的流量的识别

$ kubectl apply -f denier.rule.yaml 
rule.config.istio.io/deny-sleep-v1-to-httpbin created
$ kubectl exec -it sleep-v1-548d87cc5c-92lqk -c sleep bash
bash-4.4# http --body http://httpbin:8000/ip
PERMISSION DENIED:code一7.denier.defau1t:Not allowed


$ kubectl exec -it sleep-v2-7c6b874968-dx6ll -c sleep bash
bash-4.4# http --body http://httpbin:8000/ip
{
    "origin": "127.0.0.1"
}

测试结果表明,从sleep服务的v1版本向httpbin服务发起i请求,会失败且返回"PERMISSION DENIED:code一7.denier.defau1t:Not allowed" ,

sleep服务的v2版本向httpbin服务发起请求,就会正常返回结果。

为了后续内容的继续进行,删除刚刚创建的三个对象:

$ kubectl delete -f denier.rule.yaml -f checknonthing.yaml -f denier.yaml 
rule.config.istio.io "deny-sleep-v1-to-httpbin" deleted
checknothing.config.istio.io "place-holder" deleted
denier.config.istio.io "code-7" deleted

3、 基于Listchecker适配器的访问控制

上面提供的Denier适配器的访问控制是比较死板的,表达式修改也稍显烦琐,如果想使用更灵活的控制方式,则可以使用Listchecker适配器。

Listechecker适配器中会保存一个列表,并可以声明这一列表是黑名单还是白名单,在有数据输入后,首先判断该数据是否属于列表成员,然后根据列表的黑名单或白名单属性来返回是否许可此次调用。

Alt Image Text

然后就可以创建一系列对象来验证这一列表是否正确了。为Listchecker适配器创建一个Handler对象,其中的数据定义来自表的第1行:

apiVersion: config.istio.io/v1alpha2 
kind: listchecker 
metadata:
  name: chaos 
spec: 
  overrides: ["v1", "v3"] 
  blacklist: true
$ kubectl apply -f chaos-listchcker.yaml 
listchecker.config.istio.io/chaos created

在上面的代码中使用了overrides字段保存一个列表用于检查并在blacklist字段声明这一列表为黑名单。

Listchecker适配器还可以使用providerUrl字段引用一个远程列表并定时更新,以获得更大的灵话性

接下来使用listentry模板从输入数据中提取内容并输出给Listchecker适配器。将下面代码保存为version.listentry.yaml

apiVersion: config.istio.io/v1alpha2 
kind: listentry 
metadata:
  name: version 
spec: 
  value: source.labels["version"]

listentry只有value一个字段在其中用表达式从输入数据中提取内容进行后续输出

$ kubectl apply -f version.listentry.yaml 
listentry.config.istio.io/version created

最后创建Rule对象将InstanceHandler 连接在一起这为httpbin的流址进行测试:

apiVersion: config.istio.io/v1alpha2 
kind: rule 
metadata:
  name: checkversion 
spec: 
  match: destination.labels["app"] == "httpbin" 
  actions: 
  - handler: chaos.listchecker 
    instances: 
      - version.listentry

listentry.rule.yaml

$ kubectl apply -f listentry.rule.yaml 
rule.config.istio.io/checkversion created

现在HandlerInstance, 及Rule三个对象都已经创建完毕了.我们可以进行测试了:

$ kubectl exec -it sleep-v1-548d87cc5c-92lqk -c sleep bash
bash-4.4# http --body http://httpbin:8000/ip
PERMISSION DENIED:chaos.Iistchecker.default:v1 is blacklisted

$ kubectl exec -it sleep-v2-7c6b874968-dx6ll -c sleep bash
bash-4.4# http --body http://httpbin:8000/ip
{
    "origin": "127.0.0.1"
}

可以看到,在使用sleep Podv1版本访间httpbin服务时,访问被拒绝,出现错误信息"PERMISSION DENIED:chaos.Iistchecker.default:v1 is blacklisted

而从sleep服务的v2版本进行访问时就可以成功返回向应的内容要验证白名单也很简单、只要把chaos.listchecker.yaml中的blacklist: true改成 blacklist: false.然后重新提交即可。

再次执行测试:

apiVersion: config.istio.io/v1alpha2 
kind: listchecker 
metadata:
  name: chaos 
spec: 
  overrides: ["v1", "v3"] 
  blacklist: false
$ kubectl apply -f chaos-listchcker.yaml 
listchecker.config.istio.io/chaos configured
$ kubectl exec -it sleep-v1-548d87cc5c-92lqk -c sleep bash
bash-4.4# http --body http://httpbin:8000/ip
{
    "origin": "127.0.0.1"
}

$ kubectl exec -it sleep-v2-7c6b874968-dx6ll -c sleep bash
bash-4.4# http --body http://httpbin:8000/ip
NOT FOUND:chaoslistchecker.default:v2 is not whitelisted

Listchecker适配器更新之后进行新一轮测试,可以看到测试结果发生了变化, 与中的3:4行一致

sleep服务的v2版本向httpbin发出的访问被拒绝,返回信息为 NOT FOUND:chaoslistchecker.default:v2 is not whitelisted