You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过client-go在Go中执行kubectl apply命令?

使用client-go实现kubectl apply功能

要实现类似kubectl apply -f crds.yaml的功能,client-go可以通过Server-Side Apply完成,这是和kubectl apply逻辑对齐的官方方案,尤其适合处理CRD这类无预定义Go结构体的资源。以下是完整实现步骤和代码示例:

核心依赖

确保Go模块引入必要的client-go包:

require (
    k8s.io/client-go v0.28.4
    sigs.k8s.io/yaml v1.3.0
)

完整代码示例

package main

import (
	"context"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"

	"k8s.io/apimachinery/pkg/api/meta"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/runtime/schema"
	"k8s.io/client-go/dynamic"
	"k8s.io/client-go/tools/clientcmd"
	"sigs.k8s.io/yaml"
)

func main() {
	// 1. 加载kubeconfig(默认读取~/.kube/config)
	kubeconfig := filepath.Join(
		homeDir(), ".kube", "config",
	)
	config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
	if err != nil {
		log.Fatalf("加载kubeconfig失败: %v", err)
	}

	// 2. 创建Dynamic Client(处理无预定义结构体的资源,比如CRD)
	dynamicClient, err := dynamic.NewForConfig(config)
	if err != nil {
		log.Fatalf("创建dynamic client失败: %v", err)
	}

	// 3. 读取并解析crds.yaml文件
	yamlContent, err := ioutil.ReadFile("crds.yaml")
	if err != nil {
		log.Fatalf("读取crds.yaml失败: %v", err)
	}

	// 解析yaml中的所有文档(支持多资源yaml)
	var docs []interface{}
	if err := yaml.Unmarshal(yamlContent, &docs); err != nil {
		log.Fatalf("解析yaml失败: %v", err)
	}

	// 4. 遍历每个资源执行apply操作
	for _, doc := range docs {
		// 转成Unstructured对象
		raw, err := yaml.Marshal(doc)
		if err != nil {
			log.Printf("跳过无效资源: %v", err)
			continue
		}
		var obj unstructured.Unstructured
		if err := yaml.Unmarshal(raw, &obj); err != nil {
			log.Printf("跳过无效资源: %v", err)
			continue
		}

		// 获取资源的GroupVersionKind
		gvk := obj.GroupVersionKind()
		// 获取资源的REST映射(确定API路径)
		restMapper, err := meta.NewDefaultRESTMapper([]schema.GroupVersion{gvk.GroupVersion()})
		if err != nil {
			log.Printf("为%s创建REST mapper失败: %v", gvk, err)
			continue
		}
		mapping, err := restMapper.RESTMapping(gvk.GroupKind(), gvk.Version)
		if err != nil {
			log.Printf("获取%s的REST mapping失败: %v", gvk, err)
			continue
		}

		// 构建资源操作接口
		resourceInterface := dynamicClient.Resource(mapping.Resource)
		if obj.GetNamespace() != "" {
			resourceInterface = resourceInterface.Namespace(obj.GetNamespace())
		}

		// 执行Server-Side Apply
		applyOpts := metav1.ApplyOptions{
			FieldManager: "client-go-apply-example", // 字段管理器,标识修改来源
			Force:        true,                      // 强制覆盖冲突(按需调整)
		}

		result, err := resourceInterface.Apply(context.TODO(), obj.GetName(), &obj, applyOpts)
		if err != nil {
			log.Printf("应用资源%s/%s失败: %v", obj.GetNamespace(), obj.GetName(), err)
			continue
		}

		log.Printf("成功应用资源: %s/%s (%s)", result.GetNamespace(), result.GetName(), result.GetKind())
	}
}

// homeDir 获取用户主目录(跨平台)
func homeDir() string {
	h, err := os.UserHomeDir()
	if err != nil {
		log.Printf("获取用户主目录失败: %v", err)
		return "/"
	}
	return h
}

关键说明

  • Dynamic Client:针对CRD这类无预生成Go结构体的资源,必须用Dynamic Client基于Unstructured对象操作。
  • Server-Side Apply:这是Kubernetes官方推荐的apply方式,通过FieldManager追踪资源字段归属,避免冲突,和kubectl apply逻辑完全一致。
  • 多文档YAML:代码支持解析yaml中的多个资源文档,逐个执行apply。
  • 字段管理器:必须指定FieldManager,Kubernetes用它记录修改来源;若有字段冲突,可通过Force: true强制覆盖(谨慎使用)。

低版本兼容方案:CreateOrUpdate

如果Kubernetes版本低于1.16(不支持Server-Side Apply),可以手动实现CreateOrUpdate逻辑:

// 示例:手动处理创建或更新
_, err = resourceInterface.Create(context.TODO(), &obj, metav1.CreateOptions{})
if err != nil {
    if apierrors.IsAlreadyExists(err) {
        // 获取现有资源
        existingObj, err := resourceInterface.Get(context.TODO(), obj.GetName(), metav1.GetOptions{})
        if err != nil {
            log.Fatal(err)
        }
        // 手动合并字段(需自行处理字段覆盖逻辑,复杂度较高)
        obj.SetResourceVersion(existingObj.GetResourceVersion())
        _, err = resourceInterface.Update(context.TODO(), &obj, metav1.UpdateOptions{})
        if err != nil {
            log.Fatal(err)
        }
    } else {
        log.Fatal(err)
    }
}

该方式需自行处理字段合并,逻辑复杂易出错,优先推荐Server-Side Apply。

内容的提问来源于stack exchange,提问作者Astin Gengo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 20:25:19