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

    文章

    10

    浏览量

    8768
  • kubernetes
    +关注

    关注

    0

    文章

    224

    浏览量

    8712

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

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

收藏 人收藏

    评论

    相关推荐

    k8s和docker区别对比,哪个更强?

    Docker和KubernetesK8s)是容器化技术的两大流行工具。Docker关注构建和打包容器,适用于本地开发和单主机管理;而K8s则提供容器编排和管理平台,适用于多主机或云环境,具备自动化
    的头像 发表于 12-11 13:55 70次阅读

    k8s微服务架构就是云原生吗?两者是什么关系

    k8s微服务架构就是云原生吗?K8s微服务架构并不等同于云原生,但两者之间存在密切的联系。Kubernetes在云原生架构中扮演着核心组件的角色,它简化了容器化应用程序的管理,提供了弹性、自动化
    的头像 发表于 11-25 09:39 136次阅读

    混合云部署k8s集群方法有哪些?

    混合云部署k8s集群方法是首先需在本地与公有云分别建立K8s集群,并确保网络连接。接着,配置kubeconfig文件连接两集群,并安装云服务插件以实现资源互通。然后,编写Deployment文件部署应用,并使用kubectl命令应用至集群。最后,验证应用状态并监控集群性能
    的头像 发表于 11-07 09:37 140次阅读

    k8s可以部署私有云吗?私有云部署全攻略

    Kubernetes(简称K8S)可以部署私有云。Kubernetes开源的容器编排引擎,能够自动化容器的部署、扩展和管理,使得应用可
    的头像 发表于 10-25 09:32 158次阅读

    k8s云原生开发要求

    KubernetesK8s)云原生开发对硬件有定要求。CPU方面,建议至少配备2逻辑核心,高性能CPU更佳。内存至少4GB,但8GB或
    的头像 发表于 10-24 10:03 210次阅读
    <b class='flag-5'>k8s</b>云原生开发要求

    k8s容器启动失败的常见原因及解决办法

    k8s容器启动失败的问题通常出现在开发者使用Kubernetes进行容器编排时,可能的原因有多种,例如:配置错误、镜像问题、资源限制、依赖问题、网络问题、节点状态异常、其他因素等,以下是对这些常见原因的详细分析:
    的头像 发表于 10-11 10:12 235次阅读

    云服务器部署k8s需要什么配置?

    云服务器部署K8s需要至少2核CPU、4GB内存、50GBSSD存储的主节点用于管理集群,工作节点建议至少2核CPU、2GB内存、20GBSSD。还需安装Docker,选择兼容的Kubernetes版本,配置网络插件,以及确保系统安全、监控和备份措施到位。
    的头像 发表于 10-09 15:31 203次阅读

    纳尼?自建K8s集群日志收集还能通过JMQ保存到JES

    作者:京东科技 刘恩浩 、背景 基于K8s集群的私有化交付方案中,日志收集采用了ilogtail+logstash+kafka+es方案,其中ilogtail负责日志收集,logstash负责对数
    的头像 发表于 09-30 14:45 209次阅读

    常用的k8s容器网络模式有哪些?

    常用的k8s容器网络模式包括Bridge模式、Host模式、Overlay模式、Flannel模式、CNI(ContainerNetworkInterface)模式。K8s的容器网络模式多种多样
    的头像 发表于 09-19 11:29 234次阅读

    基于DPU与SmartNIC的K8s Service解决方案

    1.  方案背景 1.1. Kubernetes Service介绍 Kubernetes Service是Kubernetes中的核心
    的头像 发表于 09-02 17:01 917次阅读
    基于DPU与SmartNIC的<b class='flag-5'>K8s</b> Service解决方案

    如何使用Kubeadm命令在PetaExpress Ubuntu系统上安装Kubernetes集群

    Kubernetes,通常缩写为K8s,是开源的容器编排平台,旨在自动化容器化应用的部署、扩展和管理。有了Kubernetes,您可以轻
    的头像 发表于 07-15 13:31 857次阅读
    如何使用Kubeadm命令在PetaExpress Ubuntu系统上安装<b class='flag-5'>Kubernetes</b>集群

    K8S学习教程三:在PetaExpress KubeSphere 容器部署 Wiki 系统 wiki.js 并启用中文全文检索

    K8S学习教程(三):在PetaExpress KubeSphere 容器部署 Wiki 系统 wiki.js 并启用中文全文检索  。
    的头像 发表于 07-08 17:03 635次阅读
    <b class='flag-5'>K8S</b>学习教程三:在PetaExpress KubeSphere 容器部署 Wiki 系统 wiki.js 并启用中文全文检索

    K8S学习教程(二):在 PetaExpress KubeSphere容器平台部署高可用 Redis 集群

    并且需要手动重启节点,相较之下,使用 PetaExpress 提供的 Kubernetes(k8s) 服务 进行 Redis 集群的部署,则展现出了显著的优势: 1、安装便捷:使用镜像或者 yaml 配置文件即可件安装,极大地
    的头像 发表于 07-03 15:30 736次阅读
    <b class='flag-5'>K8S</b>学习教程(二):在 PetaExpress KubeSphere容器平台部署高可用 Redis 集群

    K8s容器debug高级技巧

    如果您在 Kubernetes 上运行软件,您会想要在某些时候去调试您所部署的软件的些方面。对于习惯于使用虚拟机 (VMs) 的人来说能自然使用的简单的调试方法,就是连接到
    的头像 发表于 01-12 11:31 574次阅读

    K8S落地实践经验分享

    k8sKubernetes,是开源的容器编排引擎,用来对容器化应用进行自动化部署、 扩缩和管理。
    的头像 发表于 01-02 11:45 1116次阅读
    <b class='flag-5'>K8S</b>落地<b class='flag-5'>实践</b>经验分享