kubectl

其实通过集成对应语言的Istio Client,我们可以通过对应语言的代码中直接操作Istio定制资源。

本文介绍如何使用Go语言的SDK client-go在ASM中创建istio资源。

前提条件

首先当然需要准备好kubernetes集群并安装好Istio。文本中代码基于go1.18与istio.io/client-go v1.14.0版本编写。

安装依赖
  1. 在项目路径下启动命令行终端
  2. 如果项目中尚未创建go.mod文件,运行
go mod init [模块名]
  1. 安装依赖包
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
配置连接
kubeconfigkubeconfig
生成配置文件
virtualService.yamlgateway.yaml
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
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: bookinfo-gateway
spec:
  selector:
    istio: ingressgateway # use istio default controller
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - "*"
创建虚拟服务
virtualService.yaml
package main

import (
    "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"
)

func main() {
    const NAMESPACE = "default"
    restConfig, err := clientcmd.BuildConfigFromFlags("", "{path to kube config file}") // 将{}内容替换成kube config实际路径,默认是$HOME/.kube/config
    if err != nil {
        fmt.Println("获取连接配置失败")
        return
    }
    clientset, err := versionedclient.NewForConfig(restConfig)
    if err != nil {
        fmt.Println("创建客户端失败")
        return
    }
    // 此处通过yaml反序列化构造VirtualService结构体,也可以直接构造
    virtualService := &v1beta1.VirtualService{}
    bytes, err := ioutil.ReadFile("virtualService.yaml")
    if err != nil {
        fmt.Println("读取yaml文件失败")
        return
    }
    err = yaml.Unmarshal(bytes, &virtualService)
    if err != nil {
        fmt.Println("反序列化失败")
        return
    }
    _, err = clientset.NetworkingV1beta1().VirtualServices(NAMESPACE).Create(context.TODO(), virtualService, metav1.CreateOptions{})
    if err != nil {
        fmt.Println("创建虚拟服务失败")
    }
    printAllVisualServices(clientset, NAMESPACE)
}

// 打印命名空间下全部的虚拟服务
func printAllVisualServices(clientset *versionedclient.Clientset, namespace string) {
    vsList, err := clientset.NetworkingV1beta1().VirtualServices(namespace).List(context.TODO(), metav1.ListOptions{})
    if err != nil {
        fmt.Println("获取虚拟服务失败")
    }
    for _, vs := range vsList.Items {
        fmt.Println(vs)
    }
}


创建网关规则
gateway.yaml
package main

import (
    "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"
)

func main() {
    const NAMESPACE = "default"
    restConfig, err := clientcmd.BuildConfigFromFlags("", "{path to kube config file}") // 将{}内容替换成kube config实际路径,默认是$HOME/.kube/config
    if err != nil {
        fmt.Println("获取连接配置失败")
        return
    }
    clientset, err := versionedclient.NewForConfig(restConfig)
    if err != nil {
        fmt.Println("创建客户端失败")
        return
    }
    // 此处通过yaml反序列化构造Gateway结构体,也可以直接构造
    gateway := &v1beta1.Gateway{}
    bytes, err := ioutil.ReadFile("gateway.yaml")
    if err != nil {
        fmt.Println("读取yaml文件失败")
        return
    }
    err = yaml.Unmarshal(bytes, &gateway)
    if err != nil {
        fmt.Println("反序列化失败")
        return
    }
    _, err = clientset.NetworkingV1beta1().Gateways(NAMESPACE).Create(context.TODO(), gateway, metav1.CreateOptions{})
    if err != nil {
        fmt.Println("创建网关规则失败")
    }
    printAllGateways(clientset, NAMESPACE)
}

// 打印命名空间下全部的网关规则
func printAllGateways(clientset *versionedclient.Clientset, namespace string) {
    gwList, err := clientset.NetworkingV1beta1().Gateways(namespace).List(context.TODO(), metav1.ListOptions{})
    if err != nil {
        fmt.Println("获取网关规则失败")
    }
    for _, gw := range gwList.Items {
        fmt.Println(gw)
    }
}