client-go 简介
client-go 是 Kubernetes 官方提供的 Go 语言客户端库,是与 K8s API Server 交互的标准方式。无论是简单的运维脚本、复杂的控制器(Controller)、Operator,还是自定义的 CLI 工具,底层都大量依赖 client-go。
client-go 的源码仓库为 k8s.io/client-go,通常与 k8s.io/apimachinery、k8s.io/api 等包一起使用。
client-go 整体架构
client-go 的核心模块包括:
| 模块 | 作用 |
|---|---|
| Clientset | 提供类型化的 REST 客户端,支持各类 K8s 资源的 CRUD |
| RESTClient | 底层 REST 调用封装,灵活但使用较繁琐 |
| DynamicClient | 动态客户端,无需预先知道资源类型,适合处理 CRD |
| DiscoveryClient | 发现集群支持的 API 组、版本和资源 |
| Informers | 基于 List-Watch 的本地缓存机制,高效监听资源变化 |
| Workqueue | 事件队列,配合 Informer 实现可靠的事件处理 |
| Lister | 只读本地缓存查询接口,性能高 |
理解这些模块的关系,是编写高效、稳定 K8s 程序的基础。
使用场景
client-go 常见的使用场景有:
- 运维脚本:批量查询、修改、删除资源。
- 自定义 CLI 工具:为团队封装内部使用的 kubectl 插件或独立工具。
- 控制器与 Operator:监听资源变化并调谐期望状态。
- 平台集成:将 K8s 能力集成到 PaaS、CICD 或 AIOps 平台。
Golang 命令行工具开发
使用 Go 开发命令行工具时,常用 cobra 框架。基本结构如下:
package main
import (
"fmt"
"github.com/spf13/cobra"
)
var rootCmd = &cobra.Command{
Use: "myctl",
Short: "一个自定义的 K8s 运维工具",
}
var listCmd = &cobra.Command{
Use: "list",
Short: "列出 Pod",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("列出所有 Pod...")
},
}
func main() {
rootCmd.AddCommand(listCmd)
if err := rootCmd.Execute(); err != nil {
panic(err)
}
}
cobra 支持子命令、参数解析、配置文件读取,是构建 kubectl 插件风格工具的首选。
client-go 深度实战
创建 Clientset
import (
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
)
func main() {
config, err := clientcmd.BuildConfigFromFlags("", clientcmd.RecommendedHomeFile)
if err != nil {
panic(err)
}
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
panic(err)
}
// 使用 clientset 操作资源
}
调谐改查
| 操作 | 示例方法 |
|---|---|
| 查询 | clientset.CoreV1().Pods(ns).List(ctx, metav1.ListOptions{}) |
| 创建 | clientset.CoreV1().Pods(ns).Create(ctx, pod, metav1.CreateOptions{}) |
| 更新 | clientset.CoreV1().Pods(ns).Update(ctx, pod, metav1.UpdateOptions{}) |
| 删除 | clientset.CoreV1().Pods(ns).Delete(ctx, name, metav1.DeleteOptions{}) |
控制器与 Informer
控制器遵循 Kubernetes 的声明式控制循环:
观察(Watch) -> 分析(Diff) -> 执行(Act) -> 重试(Retry)
使用 Informer 监听资源变化,配合 Workqueue 实现异步处理:
informer := factory.Core().V1().Pods().Informer()
informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
key, _ := cache.MetaNamespaceKeyFunc(obj)
workqueue.Add(key)
},
UpdateFunc: func(old, new interface{}) {
key, _ := cache.MetaNamespaceKeyFunc(new)
workqueue.Add(key)
},
DeleteFunc: func(obj interface{}) {
key, _ := cache.DeletionHandlingMetaNamespaceKeyFunc(obj)
workqueue.Add(key)
},
})
选举机制
在高可用控制器部署中,通常需要 Leader Election 保证同一时刻只有一个实例执行 reconcile。client-go 提供了 tools/leaderelection 包,支持基于 Lease 或 ConfigMap/Endpoint 的选主:
lock := &resourcelock.LeaseLock{
LeaseMeta: metav1.ObjectMeta{Name: "my-controller", Namespace: "default"},
Client: clientset.CoordinationV1(),
LockConfig: resourcelock.ResourceLockConfig{
Identity: hostname,
},
}
基于 client-go 的基础设施自动化脚本
借助 client-go,可以将常见运维操作固化为 Go 程序。例如:
- 批量给指定命名空间添加标签。
- 定时清理 Evicted 状态的 Pod。
- 根据注解自动为 Service 创建 Ingress。
- 导出集群资源配置为 GitOps 仓库。
这类脚本比 Shell 更易于维护、测试和分发,也更容易与 AIOps 平台集成。
总结
client-go 是 Kubernetes 生态的编程入口。掌握 Clientset、Informer、Workqueue、Leader Election 等核心概念,是开发控制器、Operator 和 AIOps 工具的关键。下一篇笔记将结合 AIOps 场景,展示如何使用 client-go 实现智能运维脚本。