Istio client-go 使用 patch 更新资源

写在前面

两个月没来 csdn 了,中间一直在进行公司的服务网格项目,感觉时间还是进行很快的,今天突然心血来潮想记录一下如何使用 client-go patch 怎么更新配置以及使用的坑,本文使用 json-patch 来介绍。

测试配置

官方 bookinfo 的配置, 随便使用可以是任何配置, 直接在服务器 kubectl apply 即可

apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: reviews
spec:
  host: reviews
  subsets:
  - name: v1
    labels:
      version: v1
  - name: v2
    labels:
      version: v2
  - name: v3
    labels:
      version: v3

实现

client-go 依赖就不说了,直接 go get 即可, 执行方法, 主要注意传递过来的 val,那就是我们的 patch

func Update(val []byte, name, ns string) string {

	response, err := client.IstioClient.NetworkingV1beta1().DestinationRules(ns).Patch(context.TODO(), name, patch.JSONPatchType, val, metav1.PatchOptions{})
	if err != nil {
		return fmt.Sprintf("%v.%v 更新失败 %v", name, ns, err)
	}

	j, _ := json.Marshal(response)
	return string(j)

}

操作单个 subset

这里的 patchSubsetValue 结构体是公共的,应为是操作 subset 所以所有的动作都可以使用它。详情可以查看 json-patch

type patchSubsetValue struct {
	// 操作, 例如: add、remove、replace、
	Op    string          `json:"op"`
	// 到什么路径,列如下面的: /spec/subset 从 / 下开始这里的位置就是根据具体的配置
	Path  string          `json:"path"`
	// 路径所指向的结构体
	Value *v1beta1.Subset `json:"value"`
}
添加 subset
package patch

import (
	"encoding/json"
	"fmt"
	"istio.io/api/networking/v1beta1"
	"testing"
)
	
func TestUpdate(t *testing.T) {

	patch := make([]patchSubsetValue, 0)

	patch = append(patch, patchSubsetValue{
		Op:   "add",
		// /spec/subsets/- 指定插入到数组结尾 subset 是一个数组
		Path: "/spec/subsets/-",
		Value: &v1beta1.Subset{
			Name:   "v4",
			Labels: map[string]string{"version": "v4"},
		},
	})

	patchByte, _ := json.Marshal(patch)
	response := Update(patchByte, "reviews", "default")
	fmt.Println(response)
}

查看更新后的 DestinationRule 发现 subset 已经添加成功

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: reviews
  namespace: default
spec:
  host: reviews
  subsets:
  - labels:
      version: v1
    name: v1
  - labels:
      version: v2
    name: v2
  - labels:
      version: v3
    name: v3
  - labels:
      version: v4
    name: v4
删除 subset

删除如果删除的是一个对象直接删除即可, 但是如果删除的是数组中的每一个元素则需要指定索引
这次我们将 v1 版本删除, 即:指定 0 索引进行删除, 删除不需要指定值, 指定索引即可. 如果删除不存在的内容, 运行时会抛出恐慌

func TestUpdate(t *testing.T) {

	patch := make([]patchSubsetValue, 0)

	patch = append(patch, patchSubsetValue{
		Op:   "remove",
		Path: "/spec/subsets/0",
	})

	patchByte, _ := json.Marshal(patch)
	response := Update(patchByte, "reviews", "default")
	fmt.Println(response)
}

查看删除后的内容, 已经成功

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: reviews
  namespace: default
spec:
  host: reviews
  subsets:
  - labels:
      version: v2
    name: v2
  - labels:
      version: v3
    name: v3
  - labels:
      version: v4
    name: v4
更新/替换 subset

接下来将 v3 版本直接替换为 v5 版本

func TestUpdate(t *testing.T) {

	patch := make([]patchSubsetValue, 0)

	patch = append(patch, patchSubsetValue{
		Op:   "replace",
		Path: "/spec/subsets/1",
		Value: &v1beta1.Subset{
			Name:   "v5",
			Labels: map[string]string{"version": "v5"},
		},
	})

	patchByte, _ := json.Marshal(patch)
	response := Update(patchByte, "reviews", "default")
	fmt.Println(response)
}

查看更新后内容, 没有问题

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: reviews
  namespace: default
spec:
  host: reviews
  subsets:
  - labels:
      version: v2
    name: v2
  - labels:
      version: v5
    name: v5
  - labels:
      version: v4
    name: v4

以上所有操作都是只操作一个 subset 一下操作就是同时操作多个地址

操作多个 subset

新增 v6 版本, 然后删除 v2 版本,替换 v5 版本为 v7

func TestUpdate(t *testing.T) {

	patch := make([]patchSubsetValue, 0)

	patch = append(patch, patchSubsetValue{
		Op:   "add",
		Path: "/spec/subsets/-",
		Value: &v1beta1.Subset{
			Name:   "v6",
			Labels: map[string]string{"version": "v6"},
		},
	})

	patch = append(patch, patchSubsetValue{
		Op:   "remove",
		Path: "/spec/subsets/0",
	})

	patch = append(patch, patchSubsetValue{
		Op:   "replace",
		Path: "/spec/subsets/0",
		Value: &v1beta1.Subset{
			Name:   "v7",
			Labels: map[string]string{"version": "v7"},
		},
	})

	patchByte, _ := json.Marshal(patch)
	response := Update(patchByte, "reviews", "default")
	fmt.Println(response)
}

查看结果

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: reviews
  namespace: default
spec:
  host: reviews
  subsets:
  - labels:
      version: v7
    name: v7
  - labels:
      version: v4
    name: v4
  - labels:
      version: v6
    name: v6

直接更新多个值没有问题,实际开发中使用 json patch 比较坑的就是如果想要更新多个字段的值,并且多个字段位置各不相同,json patch 无法实现。比如 /spec/subset/spec/trafficpolicy 无法一起更新。

你可能感兴趣的:(istio,istio,client-go,kubernetes,go,patch)