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

如何使用Golang程序化更新K8s中已部署DaemonSet的环境变量

使用client-go更新DaemonSet的环境变量值

核心步骤

  • 初始化Kubernetes客户端:支持本地开发(基于kubeconfig)和集群内运行(基于服务账号)两种场景
  • 获取目标DaemonSet资源
  • 定位并修改容器中的目标环境变量
  • 提交更新到K8s API服务器

完整代码示例

package main

import (
	"context"
	"flag"
	"fmt"
	"os"
	"path/filepath"

	corev1 "k8s.io/api/core/v1"
	appsV1 "k8s.io/api/apps/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"
	"k8s.io/client-go/util/homedir"
)

func main() {
	// 命令行参数:指定DaemonSet的命名空间、名称、要修改的环境变量名和新值
	namespace := flag.String("namespace", "default", "Namespace of the DaemonSet")
	daemonSetName := flag.String("name", "", "Name of the DaemonSet to update")
	envVarName := flag.String("env-name", "", "Name of the environment variable to modify")
	envVarValue := flag.String("env-value", "", "New value for the environment variable")
	flag.Parse()

	if *daemonSetName == "" || *envVarName == "" || *envVarValue == "" {
		fmt.Println("Error: --name, --env-name, --env-value are required parameters")
		os.Exit(1)
	}

	// 初始化K8s客户端
	var kubeconfig *string
	if home := homedir.HomeDir(); home != "" {
		kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
	} else {
		kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
	}
	flag.Parse()

	config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
	if err != nil {
		// 如果加载kubeconfig失败,尝试使用集群内配置(适用于Pod中运行的程序)
		config, err = rest.InClusterConfig()
		if err != nil {
			panic(err.Error())
		}
	}

	clientset, err := kubernetes.NewForConfig(config)
	if err != nil {
		panic(err.Error())
	}

	// 获取目标DaemonSet
	daemonSet, err := clientset.AppsV1().DaemonSets(*namespace).Get(context.TODO(), *daemonSetName, metav1.GetOptions{})
	if err != nil {
		panic(fmt.Errorf("failed to get DaemonSet: %v", err))
	}

	// 修改环境变量:遍历所有容器(包括init容器)
	updated := false
	// 处理主容器
	for i, container := range daemonSet.Spec.Template.Spec.Containers {
		for j, env := range container.Env {
			if env.Name == *envVarName {
				daemonSet.Spec.Template.Spec.Containers[i].Env[j].Value = *envVarValue
				updated = true
				break
			}
		}
		// 如果容器中没有该变量,添加进去
		if !updated {
			daemonSet.Spec.Template.Spec.Containers[i].Env = append(container.Env, corev1.EnvVar{
				Name:  *envVarName,
				Value: *envVarValue,
			})
			updated = true
		}
	}

	// 处理Init容器(如果有的话)
	if !updated {
		for i, container := range daemonSet.Spec.Template.Spec.InitContainers {
			for j, env := range container.Env {
				if env.Name == *envVarName {
					daemonSet.Spec.Template.Spec.InitContainers[i].Env[j].Value = *envVarValue
					updated = true
					break
				}
			}
			if !updated {
				daemonSet.Spec.Template.Spec.InitContainers[i].Env = append(container.Env, corev1.EnvVar{
					Name:  *envVarName,
					Value: *envVarValue,
				})
				updated = true
			}
		}
	}

	if !updated {
		fmt.Printf("Environment variable %s not found in any containers of DaemonSet %s\n", *envVarName, *daemonSetName)
		os.Exit(0)
	}

	// 提交更新
	_, err = clientset.AppsV1().DaemonSets(*namespace).Update(context.TODO(), daemonSet, metav1.UpdateOptions{})
	if err != nil {
		panic(fmt.Errorf("failed to update DaemonSet: %v", err))
	}

	fmt.Printf("Successfully updated environment variable %s to %s in DaemonSet %s/%s\n", *envVarName, *envVarValue, *namespace, *daemonSetName)
}

关键注意事项

  • 版本兼容:确保client-go的版本与Kubernetes集群版本相差不超过1个小版本(例如集群是1.27,client-go用1.26-1.28)
  • 权限控制:运行程序的身份(本地用户或集群内服务账号)需要拥有daemonsets.update的权限
  • 错误处理:代码中简化了错误处理,生产环境建议添加更细致的错误捕获和重试逻辑
  • 滚动更新:修改DaemonSet的Pod模板会触发滚动更新,所有旧Pod会被逐步替换为新配置的Pod

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 20:30:49