Skip to content

Dynamic Client 动态客户端

适用场景

  • 操作 CRD(自定义资源),编译时不知道类型
  • 编写通用工具(如 kubectl、Helm)
  • 处理任意 K8s 资源

基本使用

go
import (
    "k8s.io/apimachinery/pkg/runtime/schema"
    "k8s.io/client-go/dynamic"
)

dynamicClient, err := dynamic.NewForConfig(config)

// 定义 GVR(Group/Version/Resource)
deployGVR := schema.GroupVersionResource{
    Group:    "apps",
    Version:  "v1",
    Resource: "deployments",
}

// 列出资源
list, err := dynamicClient.Resource(deployGVR).Namespace("default").List(ctx, metav1.ListOptions{})
for _, item := range list.Items {
    name, _, _ := unstructured.NestedString(item.Object, "metadata", "name")
    replicas, _, _ := unstructured.NestedInt64(item.Object, "spec", "replicas")
    fmt.Printf("Deployment: %s, Replicas: %d\n", name, replicas)
}

// 获取单个资源
obj, err := dynamicClient.Resource(deployGVR).Namespace("default").Get(ctx, "my-app", metav1.GetOptions{})

// 创建 CRD 资源
crdObj := &unstructured.Unstructured{
    Object: map[string]interface{}{
        "apiVersion": "mygroup.io/v1",
        "kind":       "MyResource",
        "metadata": map[string]interface{}{
            "name":      "my-resource",
            "namespace": "default",
        },
        "spec": map[string]interface{}{
            "replicas": int64(3),
            "image":    "my-app:v1",
        },
    },
}

myGVR := schema.GroupVersionResource{Group: "mygroup.io", Version: "v1", Resource: "myresources"}
_, err = dynamicClient.Resource(myGVR).Namespace("default").Create(ctx, crdObj, metav1.CreateOptions{})

Unstructured 操作

go
// 读取嵌套字段
name, found, err := unstructured.NestedString(obj.Object, "metadata", "name")
replicas, found, err := unstructured.NestedInt64(obj.Object, "spec", "replicas")
labels, found, err := unstructured.NestedStringMap(obj.Object, "metadata", "labels")
containers, found, err := unstructured.NestedSlice(obj.Object, "spec", "template", "spec", "containers")

// 设置嵌套字段
unstructured.SetNestedField(obj.Object, int64(5), "spec", "replicas")
unstructured.SetNestedStringMap(obj.Object, map[string]string{"version": "v2"}, "metadata", "labels")

// 转换为具体类型
var deploy appsv1.Deployment
err = runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, &deploy)

// 转换为 Unstructured
unstructuredObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&deploy)

服务端应用(Server-Side Apply)

go
// 使用 SSA 进行声明式更新(推荐)
patch := &unstructured.Unstructured{
    Object: map[string]interface{}{
        "apiVersion": "apps/v1",
        "kind":       "Deployment",
        "metadata": map[string]interface{}{
            "name":      "my-app",
            "namespace": "default",
        },
        "spec": map[string]interface{}{
            "replicas": int64(5),
        },
    },
}

data, _ := json.Marshal(patch.Object)
_, err = dynamicClient.Resource(deployGVR).Namespace("default").Patch(
    ctx, "my-app",
    types.ApplyPatchType,
    data,
    metav1.PatchOptions{
        FieldManager: "my-controller",
        Force:        pointer.Bool(true),
    },
)

本站内容由 褚成志 整理编写,仅供学习参考