两个月没来 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)
}
这里的 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"`
}
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
删除如果删除的是一个对象直接删除即可, 但是如果删除的是数组中的每一个元素则需要指定索引
这次我们将 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
接下来将 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 一下操作就是同时操作多个地址
新增 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
无法一起更新。