【istio】手把手编写template和adapter

栏目: 后端 · 发布时间: 5年前

内容简介:该template主要用于定契约,描述三个事实, 其实第三点可以归纳到第一点:在编写自定义的template时,遇到了一些问题:

demo 主要是讲解自己写一个template和一个adapter,并在本地跑起这个demo来。

template主要用于定契约,描述三个事实, 其实第三点可以归纳到第一点:

  1. template该模板提供的服务类型,且每个模板只能提供一种服务,服务种类有:CHECK、QUOTA、REPORT和ATTRIBUTE_GENERATOR四类;
  2. 提供数据模型,也就是这个模板主要是针对哪些数据进行处理,比如:指标类型数据,日志类型数据,监控类型数据、鉴权类型数据、配额类型数据等等;
  3. 其他的则是一些针对(1)的grpc service接口定义。其目的就是为了让支持该模板的adapter实现这些service接口定义;

demo演示

# terminal01, 启动mix server服务,指定配置文件地址
mixs server --configStoreURL=fs://$(pwd)/testdata

# terminal02, 启动适配器服务grpc server
./l04
print person request data: xhj, 31, clever01

# termial03, 通过mix客户端命令发送一个check请求给mixer server。然后就出现了terminal02打印的日志信息
mixc check --string_attributes destination.owner=xhj,destination.container.name=clever01 --int64_attributes destination.port=31

遇到的问题

在编写自定义的template时,遇到了一些问题:

  1. template编写template.proto协议文件时,数据模型定义的变量名不能使用name,该名已经被template自身占用。
  2. template编写template.proto协议文件,还需要注意一点,需要相关写一些注释,和yaml注释文件,否则在生成文件时,会报一些"no comment"的信息。虽然不影响业务逻辑,但是最好是写上;

在编写自定义的adapter时,同样也遇到了一些问题:

其他问题是在发起mixc check客户端调用或者mixs server启动时出现的,比如:

* rpc error: code = Internal desc = grpc: error unmarshalling request: unexpected EOF
config does not conform to schema of template 'person': unable to encode fieldEncoder email_address: destination.container.name | "cdh_cjx@163.com". unable to build primitve encoder for:email_address destination.container.name | "cdh_cjx@163.com". unknown attribute destination.container.name
error creating instance: destination='person.template.istio-system:h1.handler.istio-system (myperson.adapter.istio-system)', error='fieldEncoder: age - lookup failed: 'destination.port''
field 'age' not found in message 'Params'
field 'age' is of type 'string' instead of expected type 'int'
panic: Unknown map type string

针对 unknown attribute xxx 标签的错误,一般都是在标签属性文件中没有定义这类标签,需要添加attributes.yaml文件中

针对"expected type int"的错误,这里重点介绍下:

我们知道对于每一个template定义,都有固定的服务种类支持,比如:check, quota, report, generate_attributes四类,那么对于本demo实例,template是定义的check服务类型,那么对应实现的adapter,则是对envoy proxy发过来器的grpc client请求进行check数据校验,主要是指鉴权类的校验.

那么运维在写kind为handler的这类对针对check服务类型的配置时,其中的spec部分的params参数,则主要是鉴权类型的数据值,比如ACL、token等数据。

注意:是具体的数据,因为这会对grpc client发送过来的数据处理后,并与adapter指定的数据(kind: handler对象资源下的spec下的params数据)进行比对。

因为mixer server是动态watch配置的,所以配置是可以动态修改的。这个就解决了check类型数据校验的动态变化。

所以针对上面错误的解决方案,就是我的 operator_cfg.yaml 配置kind:handler的params应该是具体数据,而不是什么 age: destination.port | 31 .

针对 panic: Unknown map type string 错误,一般都是mixc客户端的命令写得有错误。

其他问题有待考究。

编写template

我们创建一个person模板,用于处理所有与人相关的基本信息, 包括用户名、年龄和email

cd $GOPATH/src/istio.io/istio/mixer/template
mkdir person && cd person cat template.proto
syntax = "proto3";

// Example config:
//
//```shell
//apiVersion: "config.istio.io/v1alpha2"
//kind: person
//metadata:
//   name: person
//   namespace: istio-system
//spec:
//   owner: destination.owner | "guest"
//   age: destination.port | "24"
//   email_address: destination.labels["email_address"] | "cdh_cjx@163.com"
//```
package person;

//import "policy/v1beta1/type.proto";
import "mixer/adapter/model/v1beta1/extensions.proto";

option (istio.mixer.adapter.model.v1beta1.template_variety) = TEMPLATE_VARIETY_CHECK;

// The `person` template represents person info key, used to authorize API calls.
message Template {
    // The owner being called (destination.owner).
    string  owner = 1;
    // The age being called (destination.port).
    int64 age = 2;
    // The email_address being called (destination.labels["email_address"]).
    string email_address = 3;
}
$GOPATH/src/istio.io/istio/bin/mixer_codegen.sh -t template.proto

ls

person.pb.html                          template_handler.gen.go                 template_handler_service.proto
template.proto                          template_handler_service.descriptor_set template_proto.descriptor_set
template.yaml                           template_handler_service.pb.go

编写adapter

cd ../../adapter mkdir myperson && cd myperson

下面myperson.go用于提供grpc server服务,对于该check服务类型,则主要是用户基本信息校验,不通过返回给mixc客户端相应的错误码和错误信息

而config目录则主要用于认证校验grpc client发送过来的数据。也就是说config中存储的是目标数据模型

mkdir config && touch myperson.go cat myperson.go

package myperson

import (
        "context"
        "fmt"
        "net"

        google_rpc "github.com/gogo/googleapis/google/rpc"
        "google.golang.org/grpc"
        istio_mixer_adapter_model_v1beta11 "istio.io/api/mixer/adapter/model/v1beta1"
        "istio.io/istio/mixer/adapter/myperson/config"
        "istio.io/istio/mixer/template/person"
)

type (
        Server interface {
                Addr() string
                Close() error
                Run(shutdown chan error)
        }

        MyPerson struct {
                listener net.Listener
                server   *grpc.Server
        }
)
var _ person.HandlePersonServiceServer = &MyPerson{}

func (m *MyPerson) Addr() string {
        return m.listener.Addr().String()
}

func (m *MyPerson) Close() error {
        if m.server != nil {
                m.server.GracefulStop()
        }
        if m.listener != nil {
                m.listener.Close()
        }
        return nil
}

func (m *MyPerson) Run(shutdown chan error) {
        shutdown <- m.server.Serve(m.listener)
}

func (m *MyPerson) HandlePerson(ctx context.Context, req *person.HandlePersonRequest) (
        *istio_mixer_adapter_model_v1beta11.CheckResult, error) {
        fmt.Printf("print person request data: %s, %d, %s\n",
                req.Instance.Owner,
                req.Instance.Age,
                req.Instance.EmailAddress,                                                                                
        )
        fmt.Println("print adapter info.....")
        cfg := &config.Params{}
        if err := cfg.Unmarshal(req.AdapterConfig.Value); err != nil {
                panic(err.Error())
        }
        fmt.Printf("print person adapter data: %s, %d, %s\n",
                cfg.Owner,
                cfg.Age,
                cfg.EmailAddress,
        )
        if req.Instance.Owner == cfg.Owner &&
                req.Instance.Age == cfg.Age &&
                req.Instance.EmailAddress == cfg.EmailAddress {
                return &istio_mixer_adapter_model_v1beta11.CheckResult{}, nil
        }
        return &istio_mixer_adapter_model_v1beta11.CheckResult{
                Status: google_rpc.Status{
                        Code:    40001,
                        Message: "基本信息不匹配",
                },
        }, nil
}


func NewMyPerson(addr string) (Server, error) {
        if addr == "" {
                addr = "127.0.0.1:4001"
        }
        listener, err := net.Listen("tcp", fmt.Sprintf("%s", addr))
        if err != nil {
                return nil, err
        }
        s := &MyPerson{
                listener: listener,
        }
        fmt.Printf("grpc://%s\n", addr)
        s.server = grpc.NewServer()
        person.RegisterHandlePersonServiceServer(s.server, s)
        return s, nil
}
cd config && touch config.proto
cat config.proto
syntax="proto3";

// config for myperson
package adapter.myperson.config;

import "gogoproto/gogo.proto";

option go_package="config";

// config for myperson
message Params {
    // Path of the file to save the information about runtime requests.
    string owner = 1;
    // age for person
    int64 age = 2;
    // email_address for person
    string email_address = 3;
}
$GOPATH/src/istio.io/istio/bin/mixer_codegen.sh -a config.proto -x "-s=false -n myperson -t person"

ls

adapter.myperson.config.pb.html config.proto                    myperson.yaml
config.pb.go                    config.proto_descriptor

注意事项:

  1. config目录下的其他文件动态生成,是需要myperson.go支持的,因为adpater动态生成的配置文件myperson.yaml中kind: adapter在spec部分是需要指定templates的。
  2. 按照(1), 在编写myperson.go文件时,首先注释掉HandlePerson方法中的函数体,因为myperson.go编译需要能通过。然后等config目录下的文件生成后,在补充实现grpc server的service方法

测试集实施

cd $GOPATH/src/istio.io/istio/mixer/adapter/myperson
mkdir testdata && touch operator_cfg.yaml
cp config/myperson.yaml testdata/
cat operator_cfg.yaml
# handler for adapter myperson
apiVersion: "config.istio.io/v1alpha2"
kind: handler
metadata:
 name: h1
 namespace: istio-system
spec:
 adapter: myperson
 connection:
     address: "127.0.0.1:4001" #replaces at runtime by the test
 params:
   owner: "donghai"
   age: 30
   email_address: "cdh_cjx@163.com"
---

# instance for template metric
apiVersion: "config.istio.io/v1alpha2"
kind: instance
metadata:
 name: i1
 namespace: istio-system
spec:
 template: person
 params:
   owner: destination.owner | "donghai"
   age: destination.port | 31
   email_address: destination.labels["email_address"] | "cdh_cjx@163.com"
---

# rule to dispatch to handler h1
apiVersion: "config.istio.io/v1alpha2"
kind: rule
metadata:
 name: r1
 namespace: istio-system
spec:
 actions:
 - handler: h1.istio-system
   instances:
   - i1
---

cp operator_cfg.yaml testdata/

cp ../../template/person/template.yaml testdata/

cp ../../testdata/config/attributes.yaml testdata/

注意需要在attributes.yaml文件中追加几个属性词汇

destination.port:
        valueType: INT64

如果发现在启动mixer server服务时,报其他属性词汇不存在,则在该文件中继续添加。

运行结果:

当mixc check传输的属性标签名与值不等于设定的目标值时,返回值:

mixc check --string_attributes destination.owner=donghai --stringmap_attributes "destination.labels=email_address:cdh_cjx@163.com" --int64_attributes destination.port=31

Check RPC completed successfully. Check status was Code 40001 (h1.handler.istio-system:基本信息不匹配)

表明认证不通过

mixc check --string_attributes destination.owner=donghai --stringmap_attributes "destination.labels=email_address:cdh_cjx@163.com" --int64_attributes destination.port=30

当相同时,返回值:

Check RPC completed successfully. Check status was OK

总结

这个只是本地编写adapter与template,并在本地测试验证。如果要上k8s的话,这里有一个完整的 demo

参考文献

  1. 教程|构建生产就绪的Istio Adapter
  2. Mixer Out Of Process Adapter Dev Guide
  3. Mixer Out of Process Adapter Walkthrough

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

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

The Art of Computer Programming, Volume 2

The Art of Computer Programming, Volume 2

Knuth, Donald E. / Addison-Wesley Professional / 1997-11-04 / USD 79.99

Finally, after a wait of more than thirty-five years, the first part of Volume 4 is at last ready for publication. Check out the boxed set that brings together Volumes 1 - 4A in one elegant case, and ......一起来看看 《The Art of Computer Programming, Volume 2》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

html转js在线工具
html转js在线工具

html转js在线工具

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具