0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何使用kubernetes client-go实践一个简单的与K8s交互过程

Linux爱好者 来源:Linux爱好者 作者:Vladimir Vivien 2021-02-02 11:16 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

【导读】Kubernetes项目使用Go语言编写,对Go api原生支持非常便捷。本篇文章介绍了如何使用kubernetes client-go实践一个简单的与K8s交互过程。

kubernetes 的Go Client项目(client-go)

go client是k8s client中最古老的一个,具有很多特性。Client-go 没有使用Swagger生成器,它使用的是源于k8s项目中的源代码生成工具,这个工具的目的是要生成k8s风格的对象和序列化程序。

该项目是一组包的集合,该包能够满足从REST风格的原语到复杂client的不同的编程需求。

d4dd48de-61ff-11eb-8b86-12bb97331649.jpg

RESTClient是一个基础包,它使用api-machinery库中的类型作为一组REST原语提供对API的访问。作为对RESTClient之上的抽象,_clientset_将是你创建k8s client工具的起点。它暴露了公开化的API资源及其对应的序列化。

注意:在 client-go中还包含了如discovery, dynamic, 和 scale这样的包,虽然本次不介绍这些包,但是了解它们的能力还是很重要的。

一个简单的k8s client 工具

让我们再次回顾我们将要构建的工具,来说明go client的用法。pvcwatch是一个简单的命令行工具,它可以监听集群中声明的PVC容量。当总数到达一个阈值的时候,他会采取一个action(在这个例子中是在屏幕上通知显示)

d541877c-61ff-11eb-8b86-12bb97331649.jpg

你能在github上找到完整的例子

这个例子是为了展示k8s的go client的以下几个方面:- 如何去连接 - 资源列表的检索和遍历 - 对象监听

Setup

client-go支持Godep和dep作为vendor的管理程序,我觉得dep便于使用所以继续使用dep。例如,以下是client-go v6.0和k8s API v1.9所需最低限度的Gopkg.toml

[[constraint]]
  name = "k8s.io/api"
  version = "kubernetes-1.9.0"
[[constraint]]
  name = "k8s.io/apimachinery"
  version = "kubernetes-1.9.0"
[[constraint]]
  name = "k8s.io/client-go"
  version = "6.0.0"

运行dep ensure确保剩下的工作。

连接 API Server

我们Go client的第一步就是建立一个与API Server的连接。为了做到这一点,我们要使用实体包中的clientcmd,如下代码所示:

import(
...
"k8s.io/client-go/tools/clientcmd"
)
funcmain(){
kubeconfig:=filepath.Join(
os.Getenv("HOME"),".kube","config",
)
config,err:=clientcmd.BuildConfigFromFlags("",kubeconfig)
iferr!=nil{
log.Fatal(err)
}
...
}

_Client-go_通过提供实体功能来从不同的上下文中获取你的配置,从而使之成为一个不重要的任务。

从config文件

正如上面的例子所做的那样,你能从kubeconfig文件启动配置来连接API server。当你的代码运行在集群之外的时候这是一个理想的方案。clientcmd.BuildConfigFromFlags("", configFile)

从集群

当你的代码运行在这个集群中的时候,你可以用上面的函数并且不使用任何参数,这个函数就会通过集群的信息去连接api server。

clientcmd.BuildConfigFromFlags("", "")

或者我们可以通过rest包来创建一个使用集群中的信息去配置启动的(译者注:k8s里所有的Pod都会以Volume的方式自动挂载k8s里面默认的ServiceAccount,所以会用默认的ServiceAccount的授权信息),如下:

import "k8s.io/client-go/rest"
...
rest.InClusterConfig()

创建一个clientset

我们需要创建一个序列化的client为了让我们获取API对象。在kubernetes包中的Clientset类型定义,提供了去访问公开的API对象的序列化client,如下:

typeClientsetstruct{
*authenticationv1beta1.AuthenticationV1beta1Client
*authorizationv1.AuthorizationV1Client
...
*corev1.CoreV1Client
}

一旦我们有正确的配置连接,我们就能使用这个配置去初始化一个clientset,如下:

funcmain(){
config,err:=clientcmd.BuildConfigFromFlags("",kubeconfig)
...
clientset,err:=kubernetes.NewForConfig(config)
iferr!=nil{
log.Fatal(err)
}
}

对于我们的例子,我们使用的是v1的API对象。下一步,我们要使用clientset通过CoreV1()去访问核心api资源,如下:

funcmain(){
...
clientset,err:=kubernetes.NewForConfig(config)
iferr!=nil{
log.Fatal(err)
}
api:=clientset.CoreV1()
}

你能在这里看到可以获得clientsets。

获取集群的PVC列表

我们对clientset执行的最基本操作之一获取存储的API对象的列表。在我们的例子中,我们将要拿到一个namespace下面的pvc列表,如下:

import(
...
metav1"k8s.io/apimachinery/pkg/apis/meta/v1"
)
funcmain(){
varns,label,fieldstring
flag.StringVar(&ns,"namespace","","namespace")
flag.StringVar(&label,"l","","Labelselector")
flag.StringVar(&field,"f","","Fieldselector")
...
api:=clientset.CoreV1()
//setuplistoptions
listOptions:=metav1.ListOptions{
LabelSelector:label,
FieldSelector:field,
}
pvcs,err:=api.PersistentVolumeClaims(ns).List(listOptions)
iferr!=nil{
log.Fatal(err)
}
printPVCs(pvcs)
...
}

在上面的代码中,我们使用ListOptions指定 label 和 field selectors (还有namespace)来缩小pvc列表的范围,这个结果的返回类型是v1.PeristentVolumeClaimList。下面的这个代码展示了我们如何去遍历和打印从api server中获取的pvc列表。

funcprintPVCs(pvcs*v1.PersistentVolumeClaimList){
template:="%-32s%-8s%-8s
"
fmt.Printf(template,"NAME","STATUS","CAPACITY")
for_,pvc:=rangepvcs.Items{
quant:=pvc.Spec.Resources.Requests[v1.ResourceStorage]
fmt.Printf(
template,
pvc.Name,
string(pvc.Status.Phase),
quant.String())
}
}

监听集群中pvc

k8s的Go client框架支持为指定的API对象在其生命周期事件中监听集群的能力,包括创建,更新,删除一个指定对象时候触发的CREATED,MODIFIED,DELETED事件。对于我们的命令行工具,我们将要监听在集群中已经声明的PVC的总量。

对于某一个namespace,当pvc的容量到达了某一个阈值(比如说200Gi),我们将会采取某个动作。为了简单起见,我们将要在屏幕上打印个通知。但是在更复杂的实现中,可以使用相同的办法触发一个自动操作。

启动监听功能

现在让我们为PersistentVolumeClaim这个资源通过Watch去创建一个监听器。然后这个监听器通过ResultChan从go的channel中访问事件通知。

funcmain(){
...
api:=clientset.CoreV1()
listOptions:=metav1.ListOptions{
LabelSelector:label,
FieldSelector:field,
}
watcher,err:=api.PersistentVolumeClaims(ns).
Watch(listOptions)
iferr!=nil{
log.Fatal(err)
}
ch:=watcher.ResultChan()
...
}

循环事件

接下来我们将要处理资源事件。但是在我们处理事件之前,我们先声明resource.Quantity类型的的两个变量为maxClaimsQuanttotalClaimQuant来分别表示我们的申请资源阈值(译者注:代表某个ns下集群中运行的PVC申请的上限)和运行总数。

import(
"k8s.io/apimachinery/pkg/api/resource"
...
)
funcmain(){
varmaxClaimsstring
flag.StringVar(&maxClaims,"max-claims","200Gi",
"Maximumtotalclaimstowatch")
vartotalClaimedQuantresource.Quantity
maxClaimedQuant:=resource.MustParse(maxClaims)
...
ch:=watcher.ResultChan()
forevent:=rangech{
pvc,ok:=event.Object.(*v1.PersistentVolumeClaim)
if!ok{
log.Fatal("unexpectedtype")
}
...
}
}

在上面的for-range循环中,watcher的channel用于处理来自服务器传入的通知。每个事件赋值给变量event,并且event.Object的类型被声明为PersistentVolumeClaim类型,所以我们能从中提取出来。

处理ADDED事件

当一个新的PVC创建的时候,event.Type的值被设置为watch.Added。然后我们用下面的代码去获取新增的声明的容量(quant),将其添加到正在运行的总容量中(totalClaimedQuant)。最后我们去检查是否当前的容量总值大于当初设定的最大值(maxClaimedQuant),如果大于的话我们就触发一个事件。

import(
"k8s.io/apimachinery/pkg/watch"
...
)
funcmain(){
...
forevent:=rangech{
pvc,ok:=event.Object.(*v1.PersistentVolumeClaim)
if!ok{
log.Fatal("unexpectedtype")
}
quant:=pvc.Spec.Resources.Requests[v1.ResourceStorage]
switchevent.Type{
casewatch.Added:
totalClaimedQuant.Add(quant)
log.Printf("PVC%sadded,claimsize%s
",
pvc.Name,quant.String())
iftotalClaimedQuant.Cmp(maxClaimedQuant)==1{
log.Printf(
"
Claimoveragereached:max%sat%s",
maxClaimedQuant.String(),
totalClaimedQuant.String())
//triggeraction
log.Println("***Takingaction***")
}
}
...
}
}
}

处理DELETED事件

代码也会在PVC被删除的时候做出反应,它执行相反的逻辑以及把被删除的这个PVC申请的容量在正在运行的容量的总值里面减去。

funcmain(){
...
forevent:=rangech{
...
switchevent.Type{
casewatch.Deleted:
quant:=pvc.Spec.Resources.Requests[v1.ResourceStorage]
totalClaimedQuant.Sub(quant)
log.Printf("PVC%sremoved,size%s
",
pvc.Name,quant.String())
iftotalClaimedQuant.Cmp(maxClaimedQuant)<= 0{
log.Printf("Claimusagenormal:max%sat%s",
maxClaimedQuant.String(),
totalClaimedQuant.String(),
)
//triggeraction
log.Println("***Takingaction***")
}
}
...
}
}

运行程序

当程序在一个运行中的集群被执行的时候,首先会列出PVC的列表。然后开始监听集群中新的PersistentVolumeClaim事件。

$>./pvcwatch
Usingkubeconfig:/Users/vladimir/.kube/config
---PVCs----
NAMESTATUSCAPACITY
my-redis-redisBound50Gi
my-redis2-redisBound100Gi
-----------------------------
Totalcapacityclaimed:150Gi
-----------------------------
---PVCWatch(maxclaims200Gi)----
2018/02/1321:55:03PVCmy-redis2-redisadded,claimsize100Gi
2018/02/1321:55:03
At50.0%claimcapcity(100Gi/200Gi)
2018/02/1321:55:03PVCmy-redis-redisadded,claimsize50Gi
2018/02/1321:55:03
At75.0%claimcapcity(150Gi/200Gi)

下面让我们部署一个应用到集群中,这个应用会申请75Gi容量的存储。(例如,让我们通过helm去部署一个实例influxdb)。

helminstall--namemy-influx
--setpersistence.enabled=true,persistence.size=75Gistable/influxdb

正如下面你看到的,我们的工具立刻反应出来有个新的声明以及一个警告因为当前的运行的声明总量已经大于我们设定的阈值。

---PVCWatch(maxclaims200Gi)----
...
2018/02/1321:55:03
At75.0%claimcapcity(150Gi/200Gi)
2018/02/1322:01:29PVCmy-influx-influxdbadded,claimsize75Gi
2018/02/1322:01:29
Claimoveragereached:max200Giat225Gi
2018/02/1322:01:29***Takingaction***
2018/02/1322:01:29
At112.5%claimcapcity(225Gi/200Gi)

相反,从集群中删除一个PVC的时候,该工具会相应展示提示信息。

...
At 112.5% claim capcity (225Gi/200Gi)
2018/02/14 1136 PVC my-redis2-redis removed, size 100Gi
2018/02/14 1136 Claim usage normal: max 200Gi at 125Gi
2018/02/14 1136 *** Taking action ***

总结

这篇文章是进行的系列的一部分,使用Go语言的官方k8s客户端与API server进行交互。和以前一样,这个代码会逐步的去实现一个命令行工具去监听指定namespace下面的PVC的大小。这个代码实现了一个简单的监听列表去触发从服务器返回的资源事件。

责任编辑:xj

原文标题:使用 Go 构建 Kubernetes 应用

文章出处:【微信公众号:Linux爱好者】欢迎添加关注!文章转载请注明出处。


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Client
    +关注

    关注

    0

    文章

    13

    浏览量

    9247
  • kubernetes
    +关注

    关注

    0

    文章

    256

    浏览量

    9419

原文标题:使用 Go 构建 Kubernetes 应用

文章出处:【微信号:LinuxHub,微信公众号:Linux爱好者】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    香港服务器支持Docker和Kubernetes吗?

    在云原生技术成为主流的今天,Docker和KubernetesK8s)已成为现代化应用开发和部署的事实标准。对于选择香港服务器的开发者与企业而言,核心问题是:香港服务器能否完美支
    的头像 发表于 10-21 15:47 391次阅读

    K8s集群性能调优实战技巧

    大多数团队在遇到K8s性能问题时,第反应是"加机器"。但根据我对超过50生产集群的分析,80%的性能问题源于配置不当,而非资源不足。
    的头像 发表于 09-08 09:36 506次阅读

    K8s存储类设计与Ceph集成实战

    在云原生时代,存储是制约应用性能的关键瓶颈。本文将带你深入理解K8s存储类的设计原理,并手把手实现与Ceph的完美集成,让你的集群存储性能提升300%!
    的头像 发表于 08-22 11:50 615次阅读

    Kubernetes安全加固的核心技术

    在生产环境中,Kubernetes集群的安全性直接关系到企业数据安全和业务稳定性。本文将从实战角度,带你掌握K8s安全加固的核心技术。
    的头像 发表于 08-18 11:18 517次阅读

    高效管理Kubernetes集群的实用技巧

    作为名经验丰富的运维工程师,我深知在日常的Kubernetes集群管理中,熟练掌握kubectl命令是提升工作效率的关键。今天,我将分享15经过实战检验的kubectl实用技巧,帮助你像艺术家
    的头像 发表于 08-13 15:57 616次阅读

    解析K8S实用命令

    前言: 作为运维工程师,掌握 Kubernetes 命令行工具是日常工作的核心技能。本文将深入解析 K8S 最实用的命令,从基础操作到高级技巧,助你成为容器化集群管理专家。
    的头像 发表于 07-24 14:07 550次阅读

    k8s权限管理指南说明

    我们在目前的k8s集群环境里面,只能在master节点上执行kubectl的些命令,在其他节点上执行就会报错。
    的头像 发表于 06-26 14:06 558次阅读

    什么是 K8S,如何使用 K8S

    Kubernetes(简称K8S)是用于管理容器化应用程序的开源平台。以下是关于K8S及其使用方法的介绍:
    发表于 06-25 06:45

    k8s网络的基本介绍

    Kubernetes网络是指在Kubernetes集群中不同组件之间进行通信和交互的网络架构。
    的头像 发表于 06-16 13:42 634次阅读

    详解Kubernetes中的Pod调度亲和性

    KubernetesK8s)中,Pod 调度亲和性(Affinity) 是种高级调度策略,用于控制 Pod 与节点(Node)或其他 Pod 之间的关联(亲和)或反关联(反亲和)关系。通过亲和性规则,管理员可以更精细地控
    的头像 发表于 06-07 13:56 721次阅读

    简述K3SK8S的区别

    K3s 是CNCF 认证的 Kubernetes 发行版和Sandbox项目,专为低资源环境而设计。由 Rancher Labs 维护着 K3s
    的头像 发表于 04-18 10:27 1406次阅读

    k8s集群安全机制说明

    Kubernetes 作为分布式集群的管理工具,保证集群的安全性是其重要的任务。API Server 是集群内部各个组件通信的中介,
    的头像 发表于 04-03 14:09 614次阅读

    如何通过Docker和K8S集群实现高效调用GPU

    在有GPU资源的主机安装,改主机作为K8S集群的Node。
    的头像 发表于 03-18 16:50 956次阅读
    如何通过Docker和<b class='flag-5'>K8S</b>集群实现高效调用GPU

    搭建k8s需要买几台云主机?

    至少3台。搭建KubernetesK8s)集群所需的云主机数量因实际需求而异。基本的K8s集群通常需要至少3台云主机,包括1
    的头像 发表于 02-20 10:40 890次阅读

    自建K8S集群认证过期

    今天使用kubectl命令查看pod信息时,直正常运行的k8s集群突然不能访问了,输入任何命令都提示以下报错。
    的头像 发表于 02-07 12:32 653次阅读