定制资源(Custom Resource)是对 Kubernetes API 的扩展。Istio在k8s原生资源的基础上增加了Virtual Service,Gateway等资源。通常我们操作这些资源时,都是在命令行通过 kubectl
进行。如果想在代码中直接操作相关资源时,该怎么办呢?
其实通过集成对应语言的Istio Client,我们可以通过对应语言的代码中直接操作Istio定制资源。
本文介绍如何使用JAVA语言的SDK isito-client在ASM中创建istio资源。
前提条件
首先当然需要准备好kubernetes集群并安装好Istio。本文中代码基于JAVA 11与fabric8io/istio-client 6.0.0-RC1版本编写。
安装依赖
在maven配置文件 pom.xml
中添加如下依赖项
<dependencies><dependency><groupId>io.fabric8</groupId><artifactId>istio-client</artifactId><version>6.0.0-RC1</version></dependency></dependencies>
配置连接
我们需要获取集群的 kubeconfig
文件,这个文件通常位于 Kubernetes 集群的 master 节点服务器的 $HOME/.kube/config 路径(注意,kubeconfig
是类型名而不是文件名)。并复制到计算机 $HOME/.kube/config路径下。SDK在连接时将会默认使用系统kube config文件,如需指定使用特定的kube config文件,请参考创建网关规则部分代码。
生成配置文件
将下列虚拟服务和网关规则对应配置分别保存成 virtualService.yaml
和 gateway.yaml
,并放入项目静态资源文件夹中。对于maven项目,默认是 src/main/resources
文件夹。
apiVersion networking.istio.io/v1alpha3 kind VirtualService metadata name bookinfo spec hosts"*" gateways bookinfo-gateway httpmatchuri exact /productpage uri prefix /static uri exact /login uri exact /logout uri prefix /api/v1/products routedestination host productpage port number9080
apiVersion networking.istio.io/v1alpha3 kind Gateway metadata name bookinfo-gateway spec selector istio ingressgateway # use istio default controller serversport number80 name http protocol HTTP hosts"*"
创建虚拟服务
在使用JAVA istio-client创建istio资源时,可以选择使用yaml文件创建、也可以选择使用链式调用的方式创建。以下将分别示例创建虚拟服务的两种方式。
使用yaml文件创建
以下代码将在default命名空间创建 virtualService.yaml
指定的虚拟服务。
importjava.io.FileReader; importjava.io.IOException; importio.fabric8.istio.api.networking.v1beta1.VirtualService; importio.fabric8.istio.client.DefaultIstioClient; importio.fabric8.istio.client.IstioClient; importio.fabric8.kubernetes.client.Config; importio.fabric8.kubernetes.client.utils.IOHelpers; publicclassVirtualServiceExample { publicstaticvoidmain( String[] args ) { IstioClientistioClient=newDefaultIstioClient(); finalStringNAMESPACE="default"; // 创建资源的命名空间VirtualServicevirtualService=istioClient.v1beta1().virtualServices().load( VirtualServiceExample.class.getResourceAsStream("/virtualService.yaml") ).get(); istioClient.v1beta1().virtualServices().inNamespace(NAMESPACE).resource(virtualService).create(); printAllVirtualServices(istioClient); istioClient.close(); } // 打印网格中所有的VirtualServicestaticvoidprintAllVirtualServices(IstioClientistioClient) { istioClient.v1beta1().virtualServices().list().getItems().forEach(System.out::println); } }
使用链式调用创建
如果不想使用yaml配置文件定义资源,istio-client也提供了链式调用的能力,以纯代码的方式创建istio资源。以下代码和使用yaml文件的方法等价。
importio.fabric8.istio.api.networking.v1beta1.VirtualServiceBuilder; importio.fabric8.istio.client.DefaultIstioClient; importio.fabric8.istio.client.IstioClient; publicclassVirtualServiceChainingExample { publicstaticvoidmain(String[] args) { IstioClientistioClient=newDefaultIstioClient(); finalStringNAMESPACE="default"; istioClient.v1beta1().virtualServices().inNamespace(NAMESPACE).resource( newVirtualServiceBuilder() .withNewMetadata() .withName("bookinfo") .endMetadata() .withNewSpec() .addToHosts("*") .addToGateways("bookinfo-gateway") .addNewHttp() .addNewMatch().withNewUri().withNewStringMatchExactType("/productpage").endUri().endMatch() .addNewMatch().withNewUri().withNewStringMatchPrefixType("/static").endUri().endMatch() .addNewMatch().withNewUri().withNewStringMatchExactType("/login").endUri().endMatch() .addNewMatch().withNewUri().withNewStringMatchExactType("/logout").endUri().endMatch() .addNewMatch().withNewUri().withNewStringMatchPrefixType("/api/v1/products").endUri().endMatch() .addNewRoute() .withNewDestination() .withHost("productpage") .withNewPort() .withNumber(9080) .endPort() .endDestination() .endRoute() .endHttp() .endSpec() .build() ).create(); printAllVirtualServices(istioClient); istioClient.close(); } // 打印网格中所有的VirtualServicestaticvoidprintAllVirtualServices(IstioClientistioClient) { istioClient.v1beta1().virtualServices().list().getItems().forEach(System.out::println); } }
创建网关规则
以下代码根据指定的kube config文件创建连接后,在default命名空间创建 gateway.yaml
指定的网关规则。此处直接采用使用YAML文件的方式创建,不再赘述使用链式调用的方式。
importjava.io.FileReader; importjava.io.IOException; importio.fabric8.istio.api.networking.v1beta1.Gateway; importio.fabric8.istio.client.DefaultIstioClient; importio.fabric8.istio.client.IstioClient; importio.fabric8.kubernetes.client.Config; importio.fabric8.kubernetes.client.utils.IOHelpers; publicclassGateWayExample { publicstaticvoidmain(String[] args) throwsIOException { // 读取kube config连接配置文件StringkubeconfigContents=null; FileReaderreader=newFileReader("{path to kube config file}"); // 将{}内容替换成kube config实际路径kubeconfigContents=IOHelpers.readFully(reader); Configconfig=Config.fromKubeconfig(null, kubeconfigContents, null); IstioClientistioClient=newDefaultIstioClient(config); finalStringNAMESPACE="default"; // 创建资源的命名空间Gatewaygateway=istioClient.v1beta1().gateways().load( GateWayExample.class.getResourceAsStream("/gateway.yaml") ).get(); istioClient.v1beta1().gateways().inNamespace(NAMESPACE).resource(gateway).create(); printAllGateways(istioClient); istioClient.close(); } // 打印网格中所有的GatewaystaticvoidprintAllGateways(IstioClientistioClient) { istioClient.v1beta1().gateways().list().getItems().forEach(System.out::println); } }