Java操作Istio(kubernetes-client)

3 篇文章 0 订阅
3 篇文章 0 订阅

istio由于他对服务代码的完全不侵入性,以及kubernetes类云平台的普及 实用性越来越强。但istio至今也没有合适的dashboard,并且不同公司不同的业务场景导致使用istio做的事情也不相同.有偏向灰度发布的场景也有偏向对流量分布的场景。免不得需要使用业务代码操作istio的流量规则等配置。这里提供一个快速可行的操作方案


实现方式

在使用中我们更多是需要通过代码对istio进行控制,而istio在kubernetes中的规则资源是以CRD的形式存在的。所以 使用原本的kubernetes客户端扩展其资源对象请求拼装逻辑 是可以实现对istio资源进操控的。
java代码的sdk中操作kubernetes集群时较多使用的是fabric的kubernetes-clientkubernetes提供的client-java,这里由于之前对kubernetes资源进操作时使用的客户端是fabric的kubernetes-client所以这里进行扩展时采用的也是kubernetes-client
而关于这个方案的实现方式,在github上也有人已经进行了完整的代码实现(
https://github.com/snowdrop/istio-java-api
这里我们可以使用相对简单的方案去实现这些功能,扩展kubernetes-client的资源CRD,保留原生资源操作方法的前提下扩展对Istio资源进行支持

以下功能Demo已上传github,地址 https://github.com/llarao/istio-java.git

kubernetes-client扩展
  1. 创建项目,拉取项目包
        <dependency>
            <groupId>io.fabric8</groupId>
            <artifactId>kubernetes-client</artifactId>
            <version>4.9.1</version>
        </dependency>

在这里插入图片描述

可以看到kubernetes-client包含了client包以及model相关包。这里我们可以将对istio的操作需求分为两步

  • 提供对istio的操作支持
  • 提供对istio资源对象的链式拼装能力

其中的步骤1,实现相对简单。完成配置后我们可以通过kubernetes-client原生支持的操作方式对istio的资源进操作增删改查的操作。实现代码后效果如下

在这里插入图片描述

步骤2完成后可以通过Builder类快速对资源对象完成拼装。实现代码后效果如下

在这里插入图片描述

接下来分别进行说明

提供对istio资源的操作支持
  • 增加资源对象模型类
  • 增加资源对象Operations类
  • 创建客户端连接类
增加资源对象模型类

创建资源对象模型实际就是根据资源对象的完整结构创建资源类,建议根据官网的对象结构进行创建(原因是istio版本更新相对频繁 ,对象结构虽然没有大变化但还是有新的功能字段的)。这里以VirtualService举例,根据官方的结构表格以及字段类型进行对象的创建
https://istio.io/docs/reference/config/networking/virtual-service/

在这里插入图片描述

模型创建,模型创建时需要注意几个点,首先VirtualServic最外层需要实现HashMetadata接口。
内层需要实现KubernetesResource接口(如VirtualServiceSpec)
这里需要额外注意一下,资源的kind是VirtualService。 apiVersion是networking.istio.io/v1alpha3

在这里插入图片描述

在这里插入图片描述

资源对象创建完成后还需要额外创建两个对象
分别是List对象与Doneable对象

在这里插入图片描述

在这里插入图片描述

List对象是批量获取时返回的对象类型(如client.apps().deployments().innamespace().list()),注意kind和apiversion的调整,编写时可以参考kubernetes原生对象的类来编写(如DeploymentList)。
Doneable对象中提供的done方法会在触发replace时使用(最开始这里忘记写了,后来需要对vs规则做修改时报错,无法修改导致原因就是这里),编写时同理可以参考原生类对应的类来编写

在这里插入图片描述

增加资源对象Operations类

完成了基础数据模型编写后,需要开始调整client相关的类让集群客户端能够对我们新资源进行支持。这一支持首先就要提供Operations类,这个类主要用来提供请求调用时地址拼装的相关参数。
为了拼装这些参数首先我们要了解istio生成规则时真实的请求地址是什么。
进入kubernetes master节点

在这里插入图片描述

执行apply命令,补充-v=10|grephttp

在这里插入图片描述

这样我们就了解了istio规则真实请求的api地址,那么我们将这个真实地址通过Operations来拼装出来

在这里插入图片描述

apiGoupName、piGroupVersion、pural三个字段的对应关系如下所示,这样我们就可以定义Operations里的参数了。(Operations类如上所示,编写时依然可以参考原生资源)

在这里插入图片描述

这里字段的对应关系可以看下kubernetes-client中请求拼装的方法 —》OperationSupport.getRootUrl()方法。这里拼装请求地址时使用的方法

在这里插入图片描述

创建客户端连接类

前置工作到这里就告一段落,开始对接客户端。下来几个类都是与客户端直接关联的适配器或者链接类

  1. 基础客户端接口,接口用于对接上一步我们完成的Operations类,这里注意需要继承Client接口

在这里插入图片描述

  1. Istio客户端类,实现了基础客户端接口,可以看到这里通过Operations的构造方法反悔了Operations控制器

在这里插入图片描述

  1. 集群客户端适配器,创建客户端后需要将这个适配器注入到扩展适配器列表中

在这里插入图片描述

  1. 集群操作客户端接口,这里我们继承kubernetesClient,保持对原生资源的支持

在这里插入图片描述

  1. 集群操作客户端实现类,这里一定要注意进行Adapters.register操作,将第三部定义的适配器注入到扩展适配列表中,不然客户端反射操作时会抛出异常。让集群客户端初始化时就进行这个注入过程就好。

在这里插入图片描述

完成这些我们第一步的操作就完成了。

在这里插入图片描述

提供对istio资源对象的链式拼装能力

这一步进行的内容并不难,只是工作相对繁琐、重复、容易遗漏。需要格外注意,不然链路调用时会出现莫名其妙的问题定位较难。
进行这一步时可以使用原生对象进行参考来编写。
首先我们先明确一下,fabric中对资源对象定义了四种附属对象,分别用于不同的场景

  • Builder
  • Fluent
  • FluentImpl
  • Nested
    如下
    在这里插入图片描述
    但不是每个资源对象只有这四个类,是每一层对象有这些类,以VS举例
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: bookinfo
spec:
  hosts:
  - "*"
  gateways:
  - bookinfo-gateway
  http:
  - match:
    - uri:
        exact: /productpage
    - uri:
        prefix: /static
    - uri:
        exact: /login
    - uri:
        exact: /logout
    - uri:
        prefix: /api/v1/products
    route:
    - destination:
        host: productpage
        port:
          number: 9080

我们创建对象模型时需要根据规则的层级去包装对象比如Virtualservice中包含Spec对象,Spec对象中包含Hosts对象包含Http对象,每一层我们需要为其定义这些附属对象。这些才是工作量,这里初步算了一下单VS的对象差不多就有40多个(如果打算编写的话,建议从Gateway资源开始做,结构简单)

在这里插入图片描述

接下来我们对每一种对象进行说明

Builder

Builder类是将链路调用对象与资源对象转化的对象,需要继承其对应的FluentImpl类

在这里插入图片描述

箭头指向的地方都是通过FluentImpl类中的方法对资源对象或Builder对象进行赋值的过程,Builder实际上最大的作用就是通过FluentImpl属性值向资源对象进行赋予。

Fluent接口

Fluent接口需要为对应资源模块里所有的字段提供对齐操作的方法,根据每一个字段是数组是集合,是基础对象还是自定义对象进行不同的处理,这里做举例说明但不一定说全,可以参考原生对象的Fluent做参考。

  • 关于跳转,我们进行对象的链式拼装时需要向下级跳转,完成下级拼装后再会跳的过程如下,这一过程是需要通过自定义Nested内部类来实现的

在这里插入图片描述

  • 关于资源类型
  1. 数组: 建议提供以下方法,如果是自定义资源对象需要包含中间部分引入Nested内部类向下级跳转的方法
    List<SpecHttpRoute> getRoutes();
    SpecHttpRoute buildRoutes(int index);
    List<SpecHttpRoute> buildRoutes();
    A withRoutes(List<SpecHttpRoute> items);
    A withRoutes(SpecHttpRoute... items);
    Boolean hasRoutes();
    
    SpecHttpRouteNested<A> addNewRoutes();
    SpecHttpRouteNested<A> setNewRouteLike(SpecHttpRoute item);
    SpecHttpRouteNested<A> setNewRouteLike(int i , SpecHttpRoute item);
    SpecHttpRouteNested<A> editFirstRoutes();
    SpecHttpRouteNested<A> editLastRoutes();
    SpecHttpRouteNested<A> editRoutes(int i);
    
    A addNewRoutes(SpecHttpRoute specHttp);
    A setToRoutes(int index, SpecHttpRoute item);
    A addToRoutes(int index, SpecHttpRoute item);
    A addToRoutes(SpecHttpRoute... items);
    A addAllToRoutes(Collection<SpecHttpRoute> items);
    A removeFromRoutes(SpecHttpRoute... items);
    A removeAllFromRoutes(Collection<SpecHttpRoute> items);
  1. 自定义资源类型,自定义资源对象需要包含中间部分引入Nested内部类向下级跳转的方法
    SpecHttpRewrite buildRewrite();
    A withRewrite(SpecHttpRewrite item);
    Boolean hasRewrite();
    SpecHttpFluent.SpecHttpRewriteNested<A> withNewRewrite();
    SpecHttpFluent.SpecHttpRewriteNested<A> withNewRewriteLike(SpecHttpRewrite item);
    SpecHttpFluent.SpecHttpRewriteNested<A> editRewrite();
    SpecHttpFluent.SpecHttpRewriteNested<A> editOrNewRewrite();
    SpecHttpFluent.SpecHttpRewriteNested<A> editOrNewRewriteLike(SpecHttpRewrite item);
  1. 普通资源类型
    String getExact();
    A withExact(String item);

(ps:这个类有点长就分两个图来截了。)

在这里插入图片描述

在这里插入图片描述

需要注意的是关于Nested内部接口的定义,继承Nested,下级Fluent对象泛型为当前Nested。

public interface SpecHttpRouteNested<N> extends io.fabric8.kubernetes.api.builder.Nested<N>, SpecHttpRouteFluent<SpecHttpRouteNested<N>> {
        public N and();    public N endRoute();
    }
FluentImpl

实现Fluent接口定义实现类,需要注意红线部分,以及箭头部分,Fluent中包含当前资源对象里的所有属性,但自定义类型的属性在FluentImpl中必须改成对应的Builder,每个方法的实现方式都相对简单,可以自己编写或者参考Deployment的即可

在这里插入图片描述

  • 关于NestedImpl:在FluentImpl中需要对Fluent中定义的Nested进行实现。需要注意的点已经标注了红线与箭头
    NestedImpl需要继承对应下级的FluentImpl,需要实现同级Fluent的Nested
    包含了and和end方法,实际end方法就是在调用and方法。实现的能力是根据下级中赋予的属性生成对应的Builder,赋予本级对应的Builder属性中。

在这里插入图片描述

具体每一个类都可以参考原有的资源对象来编写,这里只做简述。这样完成了代码后能够实现如下的资源拼装能力。

在这里插入图片描述

END

这样可以完成对istio的操作客户端。并且可以完全复用kubernetes-client中的客户端以及其他原生资源对象的操作方法。开发量不大而且也不复杂,只是刚开始看的时候会被多个相似的类弄乱,理清类间的调用逻辑其实并不复杂。
这样的操作并不只针对istio的资源,如果公司自研了一些CRD,也可以使用这种方式进行封装提供操作客户端。

ps:再多说一句,istio赋予规则时需要开启自动注入,这里并不建议对命名空间开启自动注入。毕竟sidecar对资源占用不小是不争的事实。建议通过annotation注解对指定的deployment开启,尽可能节省资源(但这毕竟是业务层相关的逻辑了,按需取舍吧)
注入间的覆盖逻辑如下

在这里插入图片描述

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
要下载 kubernetes-client 依赖包,首先需要确定要下载的是哪个版本的依赖包。可以通过查找文档或官方网站获得相关信息。接下来,可以使用以下几种方式来下载: 1. 使用 Maven:如果你的项目是基于 Maven 构建的,可以在项目的 pom.xml 文件中添加 kubernetes-client 的依赖,并执行 Maven 命令进行下载。例如,在 pom.xml 文件的 dependencies 标签下添加以下代码: ``` <dependency> <groupId>io.kubernetes</groupId> <artifactId>kubernetes-client</artifactId> <version>版本号</version> </dependency> ``` 请将“版本号”替换为你需要下载的 kubernetes-client 的具体版本号,然后运行 Maven 命令进行下载。 2. 使用 Gradle:如果你的项目是基于 Gradle 构建的,可以在项目的 build.gradle 文件中添加 kubernetes-client 的依赖,并执行 Gradle 命令进行下载。例如,添加以下代码到 build.gradle 文件的 dependencies 标签下: ``` implementation 'io.kubernetes:kubernetes-client:版本号' ``` 请将“版本号”替换为你需要下载的 kubernetes-client 的具体版本号,然后运行 Gradle 命令进行下载。 3. 手动下载:如果你不使用构建工具,也可以手动下载 kubernetes-client 的依赖包。在官方网站或其他可信的软件仓库中,搜索并下载相应的依赖包。然后将它添加到你的项目中,并在代码中引入相应的类和方法。 无论使用哪种方式下载,一定注意下载的依赖包版本与你的项目兼容。下载完成后,就可以在你的代码中使用 kubernetes-client 依赖包提供的功能了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值