如何使用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
相关产品推荐
相关产品推荐

