定制资源(Custom Resource)是对 Kubernetes API 的扩展。Istio在k8s原生资源的基础上增加了Virtual Service,Gateway等资源。通常我们操作这些资源时,都是在命令行通过 kubectl
进行。如果想在代码中直接操作相关资源时,该怎么办呢?
其实通过集成对应语言的Istio Client,我们可以通过对应语言的代码中直接操作Istio定制资源。
本文介绍如何使用Go语言的SDK client-go在ASM中创建istio资源。
前提条件
首先当然需要准备好kubernetes集群并安装好Istio。文本中代码基于go1.18与istio.io/client-go v1.14.0版本编写。
安装依赖
- 在项目路径下启动命令行终端
- 如果项目中尚未创建go.mod文件,运行
go mod init [模块名]
- 安装依赖包
go get github.com/ghodss/yaml istio.io/client-go/pkg/apis/networking/v1beta1 istio.io/client-go/pkg/clientset/versioned k8s.io/apimachinery/pkg/apis/meta/v1 k8s.io/client-go/tools/clientcmd
配置连接
我们需要获取集群的 kubeconfig
文件,这个文件通常位于 Kubernetes 集群的 master 节点服务器的 $HOME/.kube/config 路径(注意,kubeconfig
是类型名而不是文件名)。并复制到计算机 $HOME/.kube/config 或自定义路径下的kube config文件中。
生成配置文件
将下列虚拟服务和网关规则对应配置分别保存成 virtualService.yaml
和 gateway.yaml
,并放入项目文件夹中。
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"*"
创建虚拟服务
以下代码将在default命名空间创建 virtualService.yaml
指定的虚拟服务。
packagemainimport ( "context""fmt""io/ioutil""github.com/ghodss/yaml""istio.io/client-go/pkg/apis/networking/v1beta1"versionedclient"istio.io/client-go/pkg/clientset/versioned"metav1"k8s.io/apimachinery/pkg/apis/meta/v1""k8s.io/client-go/tools/clientcmd") funcmain() { constNAMESPACE="default"restConfig, err :=clientcmd.BuildConfigFromFlags("", "{path to kube config file}") // 将{}内容替换成kube config实际路径,默认是$HOME/.kube/configiferr!=nil { fmt.Println("获取连接配置失败") return } clientset, err :=versionedclient.NewForConfig(restConfig) iferr!=nil { fmt.Println("创建客户端失败") return } // 此处通过yaml反序列化构造VirtualService结构体,也可以直接构造virtualService :=&v1beta1.VirtualService{} bytes, err :=ioutil.ReadFile("virtualService.yaml") iferr!=nil { fmt.Println("读取yaml文件失败") return } err=yaml.Unmarshal(bytes, &virtualService) iferr!=nil { fmt.Println("反序列化失败") return } _, err=clientset.NetworkingV1beta1().VirtualServices(NAMESPACE).Create(context.TODO(), virtualService, metav1.CreateOptions{}) iferr!=nil { fmt.Println("创建虚拟服务失败") } printAllVisualServices(clientset, NAMESPACE) } // 打印命名空间下全部的虚拟服务funcprintAllVisualServices(clientset*versionedclient.Clientset, namespacestring) { vsList, err :=clientset.NetworkingV1beta1().VirtualServices(namespace).List(context.TODO(), metav1.ListOptions{}) iferr!=nil { fmt.Println("获取虚拟服务失败") } for_, vs :=rangevsList.Items { fmt.Println(vs) } }
创建网关规则
以下代码将在default命名空间创建 gateway.yaml
指定的网关规则。
packagemainimport ( "context""fmt""io/ioutil""github.com/ghodss/yaml""istio.io/client-go/pkg/apis/networking/v1beta1"versionedclient"istio.io/client-go/pkg/clientset/versioned"metav1"k8s.io/apimachinery/pkg/apis/meta/v1""k8s.io/client-go/tools/clientcmd") funcmain() { constNAMESPACE="default"restConfig, err :=clientcmd.BuildConfigFromFlags("", "{path to kube config file}") // 将{}内容替换成kube config实际路径,默认是$HOME/.kube/configiferr!=nil { fmt.Println("获取连接配置失败") return } clientset, err :=versionedclient.NewForConfig(restConfig) iferr!=nil { fmt.Println("创建客户端失败") return } // 此处通过yaml反序列化构造Gateway结构体,也可以直接构造gateway :=&v1beta1.Gateway{} bytes, err :=ioutil.ReadFile("gateway.yaml") iferr!=nil { fmt.Println("读取yaml文件失败") return } err=yaml.Unmarshal(bytes, &gateway) iferr!=nil { fmt.Println("反序列化失败") return } _, err=clientset.NetworkingV1beta1().Gateways(NAMESPACE).Create(context.TODO(), gateway, metav1.CreateOptions{}) iferr!=nil { fmt.Println("创建网关规则失败") } printAllGateways(clientset, NAMESPACE) } // 打印命名空间下全部的网关规则funcprintAllGateways(clientset*versionedclient.Clientset, namespacestring) { gwList, err :=clientset.NetworkingV1beta1().Gateways(namespace).List(context.TODO(), metav1.ListOptions{}) iferr!=nil { fmt.Println("获取网关规则失败") } for_, gw :=rangegwList.Items { fmt.Println(gw) } }