当前位置: 首页 > news >正文

01-client-go

想学习K8S源码,可以加 :mkjnnm

1、介绍

client-go 是用来和 k8s 集群交互的go语言客户端库,地址为:https://github.com/kubernetes/client-go client-go 的版本有两种标识方式:

  • v0.x.y (For each v1.x.y Kubernetes release, the major version (first digit) would remain 0)
  • kubernetes-1.x.y

ps: k8s 发布v1.30.0 版本时,client-go 会同步发布两个版本 v0.30.0 (推荐使用)和 kubernetes-1.30.0

如果你想使用最新版本的客户端库,你可以运行如下命令:

go get k8s.io/client-go@latest

如果你想使用特定版本,推荐使用如下命令:

go get k8s.io/client-go@v0.20.4

2、目录结构

client-go 包含以下几部分:

  • The kubernetes package contains the clientset to access Kubernetes API.
  • The discovery package is used to discover APIs supported by a Kubernetes API server.
  • The dynamic package contains a dynamic client that can perform generic operations on arbitrary Kubernetes API objects.
  • The plugin/pkg/client/auth packages contain optional authentication plugins for obtaining credentials from external sources.
  • The transport package is used to set up auth and start a connection.
  • The tools/cache package is useful for writing controllers.

3、使用

1.初始化

  • 集群内初始化
  • 集群外初始化

如果你的应用跑在集群中的pod上,推荐使用集群内初始化,否则使用集群外初始化。

// 集群外初始化 client
// 需要集群的 kubeconfig 配置文件
func main() {var kubeconfig *stringif 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()// use the current context in kubeconfigconfig, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)if err != nil {panic(err.Error())}// create the clientsetclientset, err := kubernetes.NewForConfig(config)if err != nil {panic(err.Error())}
}

2. 列出集群内pod资源

pods, err := clientset.CoreV1().Pods("").List(context.TODO(), metav1.ListOptions{})if err != nil {panic(err.Error())}fmt.Printf("There are %d pods in the cluster\n", len(pods.Items))

上述代码在client-
go仓库下examples目录

你可以运行该代码:

cd out-of-cluster-client-configuration
go build -o app .
./app -kubeconfig=/path/to/xxx

3. deployment资源CRUD - typed (clientset)方式

以下代码创建一个有2个副本数的deployment,然后更新副本数为1,升级nginx镜像版本,最后删除

	deploymentsClient := clientset.AppsV1().Deployments(apiv1.NamespaceDefault)deployment := &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "demo-deployment",},Spec: appsv1.DeploymentSpec{Replicas: int32Ptr(2),Selector: &metav1.LabelSelector{MatchLabels: map[string]string{"app": "demo",},},Template: apiv1.PodTemplateSpec{ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{"app": "demo",},},Spec: apiv1.PodSpec{Containers: []apiv1.Container{{Name:  "web",Image: "nginx:1.12",Ports: []apiv1.ContainerPort{{Name:          "http",Protocol:      apiv1.ProtocolTCP,ContainerPort: 80,},},},},},},},}// Create Deploymentfmt.Println("Creating deployment...")result, err := deploymentsClient.Create(context.TODO(), deployment, metav1.CreateOptions{})if err != nil {panic(err)}fmt.Printf("Created deployment %q.\n", result.GetObjectMeta().GetName())// Update Deploymentprompt()fmt.Println("Updating deployment...")//    You have two options to Update() this Deployment:////    1. Modify the "deployment" variable and call: Update(deployment).//       This works like the "kubectl replace" command and it overwrites/loses changes//       made by other clients between you Create() and Update() the object.//    2. Modify the "result" returned by Get() and retry Update(result) until//       you no longer get a conflict error. This way, you can preserve changes made//       by other clients between Create() and Update(). This is implemented below//			 using the retry utility package included with client-go. (RECOMMENDED)//// More Info:// https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistencyretryErr := retry.RetryOnConflict(retry.DefaultRetry, func() error {// Retrieve the latest version of Deployment before attempting update// RetryOnConflict uses exponential backoff to avoid exhausting the apiserverresult, getErr := deploymentsClient.Get(context.TODO(), "demo-deployment", metav1.GetOptions{})if getErr != nil {panic(fmt.Errorf("Failed to get latest version of Deployment: %v", getErr))}result.Spec.Replicas = int32Ptr(1)                           // reduce replica countresult.Spec.Template.Spec.Containers[0].Image = "nginx:1.13" // change nginx version_, updateErr := deploymentsClient.Update(context.TODO(), result, metav1.UpdateOptions{})return updateErr})if retryErr != nil {panic(fmt.Errorf("Update failed: %v", retryErr))}fmt.Println("Updated deployment...")// List Deploymentsprompt()fmt.Printf("Listing deployments in namespace %q:\n", apiv1.NamespaceDefault)list, err := deploymentsClient.List(context.TODO(), metav1.ListOptions{})if err != nil {panic(err)}for _, d := range list.Items {fmt.Printf(" * %s (%d replicas)\n", d.Name, *d.Spec.Replicas)}// Delete Deploymentprompt()fmt.Println("Deleting deployment...")deletePolicy := metav1.DeletePropagationForegroundif err := deploymentsClient.Delete(context.TODO(), "demo-deployment", metav1.DeleteOptions{PropagationPolicy: &deletePolicy,}); err != nil {panic(err)}fmt.Println("Deleted deployment.")
}func prompt() {fmt.Printf("-> Press Return key to continue.")scanner := bufio.NewScanner(os.Stdin)for scanner.Scan() {break}if err := scanner.Err(); err != nil {panic(err)}fmt.Println()
}func int32Ptr(i int32) *int32 { return &i }

4.deployment资源CRUD - dynamic方式

使用typed方式创建资源虽然方便,但是需要事先使用client-gen生成且会与某个特定版本耦合,不够通用,所以我们可以使用 unstructured.Unstructured 来表示集群中任意对象。

	client, err := dynamic.NewForConfig(config)if err != nil {panic(err)}deploymentRes := schema.GroupVersionResource{Group: "apps", Version: "v1", Resource: "deployments"}deployment := &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "apps/v1","kind":       "Deployment","metadata": map[string]interface{}{"name": "demo-deployment",},"spec": map[string]interface{}{"replicas": 2,"selector": map[string]interface{}{"matchLabels": map[string]interface{}{"app": "demo",},},"template": map[string]interface{}{"metadata": map[string]interface{}{"labels": map[string]interface{}{"app": "demo",},},"spec": map[string]interface{}{"containers": []map[string]interface{}{{"name":  "web","image": "nginx:1.12","ports": []map[string]interface{}{{"name":          "http","protocol":      "TCP","containerPort": 80,},},},},},},},},}// Create Deploymentfmt.Println("Creating deployment...")result, err := client.Resource(deploymentRes).Namespace(apiv1.NamespaceDefault).Create(context.TODO(), deployment, metav1.CreateOptions{})if err != nil {panic(err)}fmt.Printf("Created deployment %q.\n", result.GetName())

5. discoveryClient

3-4小节我们学习了 typed client 和 dynamic client ,这两个client使用来操作集群中资源,比如创建 deployment,删除pod。discovery client 不同,他是用来发现服务端支持的组、版本、资源类型:

// Package discovery provides ways to discover server-supported
// API groups, versions and resources.

我们可以查询服务端支持的组与版本、某个组的资源列表

func main() {var kubeconfig *stringif 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()// use the current context in kubeconfigconfig, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)if err != nil {panic(err.Error())}// *查询服务端支持的组列表discoveryClient := discovery.NewDiscoveryClientForConfigOrDie(config)gs, err := discoveryClient.ServerGroups()if err != nil {panic(err.Error())}spew.Dump(gs.Groups)// *查询core/v1 组下的资源列表rs, err := discoveryClient.ServerResourcesForGroupVersion("v1")if err != nil {panic(err.Error())}for _, r := range rs.APIResources {fmt.Println(r.Name)}}// 输出支持的组列表
/*
(v1.APIGroup) &APIGroup{Name:apps,Versions:[]GroupVersionForDiscovery{GroupVersionForDiscovery{GroupVersion:apps/v1,Version:v1,},},PreferredVersion:GroupVersionForDiscovery{GroupVersion:apps/v1,Version:v1,},ServerAddressByClientCIDRs:[]ServerAddressByClientCIDR{},},
(v1.APIGroup) &APIGroup{Name:events.k8s.io,Versions:[]GroupVersionForDiscovery{GroupVersionForDiscovery{GroupVersion:events.k8s.io/v1,Version:v1,},},PreferredVersion:GroupVersionForDiscovery{GroupVersion:events.k8s.io/v1,Version:v1,},ServerAddressByClientCIDRs:[]ServerAddressByClientCIDR{},},
...
*/// 输出core/v1组下的资源列表
/*
pods/status
podtemplates
replicationcontrollers
replicationcontrollers/scale
replicationcontrollers/status
resourcequotas
resourcequotas/status
secrets
serviceaccounts
...
*/

6. restClient

上面三种客户端都是基于 restClient 封装的,restClient 是 client-go 最基础的客户端,对http request 进行了封装,更加灵活,一般我们用不到。

// 根据配置信息构建restClient实例restClient, err := rest.RESTClientFor(config)if err!=nil {panic(err.Error())}// 保存pod结果的数据结构实例result := &corev1.PodList{}//  指定namespacenamespace := "kube-system"// 设置请求参数,然后发起请求// GET请求err = restClient.Get().//  指定namespace,参考path : /api/v1/namespaces/{namespace}/podsNamespace(namespace).// 查找多个pod,参考path : /api/v1/namespaces/{namespace}/podsResource("pods").// 指定大小限制和序列化工具VersionedParams(&metav1.ListOptions{Limit:100}, scheme.ParameterCodec).// 请求Do(context.TODO()).// 结果存入resultInto(result)

4、局限

使用 client 操作集群中资源会导致频繁的轮询,k8s client-go 包提供了更加高效的方式:informer 。

informer 提供了一种机制来监视 Kubernetes 集群内资源的变化并做出反应。它使开发人员能够接收有关各种 Kubernetes 对象(例如 Pod、服务、部署等)状态的实时更新。

Informer 将集群中的资源缓存在本地来减少频繁的API调用,提高性能并优化资源利用率。

相关文章:

01-client-go

想学习K8S源码,可以加 :mkjnnm 1、介绍 client-go 是用来和 k8s 集群交互的go语言客户端库,地址为:https://github.com/kubernetes/client-go client-go 的版本有两种标识方式: v0.x.y (For each v1.x.y Kubernetes…...

WebRTC QoS方法十三.2(Jitter延时的计算)

一、背景介绍 一些报文在网络传输中,会存在丢包重传和延时的情况。渲染时需要进行适当缓存,等待丢失被重传的报文或者正在路上传输的报文。 jitter延时计算是确认需要缓存的时间 另外,在检测到帧有重传情况时,也可适当在渲染时…...

PHP进阶:前后端交互、cookie验证、sql与php

单词:construct 构造 destruct 摧毁 empty 空的 trim 修剪 strip 清除 slash 斜线 special 特殊 char 字符 query 询问 构造方法(魔术方法) 构造方法是一种特殊的函数&#xff0…...

优思学院|ANOVA方差分析是什么?如何用EXCEL进行计算?

在数据分析、六西格玛管理领域中,ANOVA(方差分析)是一种基本的统计工具,广泛用于确定三组或三组以上的独立群体之间的平均值是否存在统计学上的显着差异。ANOVA的主要目的在于评估一个或多个因素的影响,通过比较不同样…...

Mindspore框架循环神经网络RNN模型实现情感分类|(三)RNN模型构建

Mindspore框架循环神经网络RNN模型实现情感分类 Mindspore框架循环神经网络RNN模型实现情感分类|(一)IMDB影评数据集准备 Mindspore框架循环神经网络RNN模型实现情感分类|(二)预训练词向量 Mindspore框架循环神经网络RNN模型实现…...

深度解读大语言模型中的Transformer架构

一、Transformer的诞生背景 传统的循环神经网络(RNN)和长短期记忆网络(LSTM)在处理自然语言时存在诸多局限性。RNN 由于其递归的结构,在处理长序列时容易出现梯度消失和梯度爆炸的问题。这导致模型难以捕捉长距离的依…...

安装好anaconda,打开jupyter notebook,新建 报500错

解决办法: 打开anaconda prompt 输入 jupyter --version 重新进入jupyter notebook: 可以成功进入进行代码编辑...

C++20之设计模式:状态模式

状态模式 状态模式状态驱动的状态机手工状态机Boost.MSM 中的状态机总结 状态模式 我必须承认:我的行为是由我的状态支配的。如果我没有足够的睡眠,我会有点累。如果我喝了酒,我就不会开车了。所有这些都是状态(states),它们支配着我的行为:…...

数据库安全综合治理方案(可编辑54页PPT)

引言:数据库安全综合治理方案是一个系统性的工作,需要从多个方面入手,综合运用各种技术和管理手段,确保数据库系统的安全稳定运行。 方案介绍: 数据库安全综合治理方案是一个综合性的策略,旨在确保数据库系…...

人工智能:大语言模型提示注入攻击安全风险分析报告下载

大语言模型提示注入攻击安全风险分析报告下载 今天分享的是人工智能AI研究报告:《大语言模型提示注入攻击安全风险分析报告》。(报告出品方:大数据协同安全技术国家工程研究中心安全大脑国家新一代人工智能开放创新平台) 研究报告…...

【购买源码时有许多需要注意的坑】

购买源码时有许多需要注意的“坑”,这些坑可能会对项目的后续开发和使用造成严重影响。以下是一些需要特别注意的方面: 源码的完整性 编译测试:确保到手的源码能够从头至尾编译、打包、部署和功能测试无误。这一步非常关键,因为只…...

CAS的三大问题和解决方案

一、ABA问题的解决方案 变量第一次读取的值是1,后来其他线程改成了3,然后又被其他线程修改成了1,原来期望的值是第一个1才会设置新值,第二个1跟期望不符合,但是,可以设置新值。 解决方案: &a…...

EDA和统计分析有什么区别

EDA(Electronic Design Automation)和统计分析在多个方面存在显著的区别,这些区别主要体现在它们的应用领域、目的、方法以及所使用的工具上。 EDA(电子设计自动化) 定义与目的: EDA是电子设计自动化&…...

CentOS 7 修改DNS

1、nmcli connection show 命令找到设备名称 # nmcli connection show NAME UUID TYPE DEVICE enp4s0 99559edf-4e0a-4bae-a528-6d75065261e9 ethernet enp4s0 2、nmcli connection modify 命令修改dns nmcli connection modif…...

PHP基础语法-Part2

if-else语句、switch语句 与其他语言相同 循环结构 for循环while循环do-while循环foreach循环,搭配数组使用 foreach ($age as $avlue) //只输出值 {xxx; } foreach ($age as $key > $avlue) //键和值都输出 {xxx; }foreach ($age as $key >…...

数据结构门槛-顺序表

顺序表 1. 线性表2. 顺序表2.1 静态顺序表2.2 动态顺序表2.2.1 动态数据表初始化和销毁2.2.2 动态数据表的尾插尾删2.2.3 动态数据表的头插头删2.2.4 动态数据表的中间部分插入删除2.2.5 动态数据表的查询数据位置 3. 总结 1. 线性表 线性表(linear list&#xff0…...

软件测试面试准备工作

1、 什么是数据库? 答:数据库是按照某种数据模型组织起来的并存放二级存储器中的数据集合。 2、 什么是关系型数据库? 答:关系型数据库是建立在关系数据库模型基础上的数据库, 借助集合代数等概念和方法处理数据库中的数据。目前主流的关…...

Java面试八股之后Spring、spring mvc和spring boot的区别

Spring、spring mvc和spring boot的区别 Spring, Spring Boot和Spring MVC都是Spring框架家族的一部分,它们各自有其特定的用途和优势。下面是它们之间的主要区别: Spring: Spring 是一个开源的轻量级Java开发框架,最初由Rod Johnson创建&…...

linux对齐TOF和RGB摄像头画面

问题:TOF和RGB画面不对齐 linux同时接入TOF和RGB,两者出图时间是由驱动层控制(RGB硬件触发出图),应用层只负责读取数据。 现在两者画面不对齐,发现是开始的时候两者出图数量不一致导致的。底层解决不了&a…...

配置linux客户端免密登录服务端linux主机的root用户

1、客户端与服务端的ip 客户端IP地址服务端IP地址 2、定位客户端,由客户端制作公私钥对 [rootclient ~]# ssh-keygen -t rsa (RSA是非对称加密算法) # 一路回车 3、定位客户端,将公钥上传到服务器端root账户 [rootc…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:

一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

遍历 Map 类型集合的方法汇总

1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...

《通信之道——从微积分到 5G》读书总结

第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...

2025盘古石杯决赛【手机取证】

前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来,实在找不到,希望有大佬教一下我。 还有就会议时间,我感觉不是图片时间,因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

三体问题详解

从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...

数据库分批入库

今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...

QT: `long long` 类型转换为 `QString` 2025.6.5

在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)

目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...

解决:Android studio 编译后报错\app\src\main\cpp\CMakeLists.txt‘ to exist

现象: android studio报错: [CXX1409] D:\GitLab\xxxxx\app.cxx\Debug\3f3w4y1i\arm64-v8a\android_gradle_build.json : expected buildFiles file ‘D:\GitLab\xxxxx\app\src\main\cpp\CMakeLists.txt’ to exist 解决: 不要动CMakeLists.…...