NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

如何在 GO 语言中使用 Kubernetes API?

  • 2020-04-12
  • 本文字数:3472 字

    阅读完需:约 11 分钟

如何在GO语言中使用Kubernetes API?

Rancher Labs 首席软件工程师 Alena Prokharchyk 受邀在 2017 年 12 月 6-8 日的 CNCF 主办的 Kubernetes 领域顶级盛会 KubeCon + CloudNativeCon 2017 北美峰会上进行演讲,本文由演讲内容整理而成。


随着 Kubernetes 越来越受欢迎,围绕它的集成和监控服务的数量也在不断增长。Golang 编写的所有此类服务的关键组件是 kubernetes / client-go——一个用于与 Kubernetes 集群 API 通信的软件包。在本文中,我们将讨论 client-go 使用的基本知识,以及如何为开发人员节约编写实际应用程序逻辑所需的时间。我们还将展示使用该软件包的最佳实践,并从每天与 Kubernetes 进行集成工作的开发人员的角度,分享我们已有的经验。内容将包括:


  • 集群中的客户端认证 vs. 集群外的客户端认证

  • 基本列表,使用 client-go 去创建和删除 Kubernetes 对象的操作

  • 如何使用 ListWatch 和 Informers 监视 K8s 事件并做出反应

  • 如何管理软件包依赖

Kubernetes 是一个平台

Kubernetes 有很多受欢迎的地方。用户喜欢它的丰富功能、稳定性和性能。对贡献者来说,Kubernetes 开源社区不仅规模庞大,还易于上手、反馈迅速。而真正让 Kubernetes 吸引了第三方开发者的是它的 可扩展性。该项目提供了很多方式来添加新功能、扩展现有功能而且不会中断主代码库。正是这些,使得 Kubernetes 发展成为了一个平台。


这里有一些方式来扩展 Kubernetes:



上图所示,你可以发现每个 Kubernetes 集群组件无论是 Kubelet 还是 API 服务器,都可以以某种方式进行扩展。今天我们将重点介绍一种“自定义控制器”的方式,从现在起我将它称为 Kubernetes 控制器(Kubernetes Controller),或者简单地称为 控制器(Controller)

Kubernetes 控制器究竟是什么?

控制器最常见的定义是:使得系统的当前状态达到所期望的状态的代码。但这究竟是什么意思呢?我们以 Ingress 控制器为例。Ingress 是一个 Kubernetes 资源,它能够对集群中服务的外部访问进行定义。通常采用 HTTP 并且有负载均衡支持。然而 Kubernetes 的核心代码中并没有 ingress 的实现。第三方控制器的实现将包含:


1、监控 ingress/services/endpoint 资源的事件(创建、更新、删除)


2、程序内部或外部的负载均衡器


3、使用负载均衡器的地址来更新 Ingress


“所期望的状态”在 Ingress 这里指的是 IP 地址指向运行着的负载均衡器,该均衡器由用户根据 ingress 规范定义的规则实现。并且由外部 Ingress 控制器负责将 ingress 资源转移到这一状态。


对相同的资源,控制器的实现以及部署他们的方式也可能会有所不同。你可以选择 nginx 控制器并将其部署到集群中的每个节点上作为守护进程集(Daemon Set),也可以选择在 Kubernetes 集群外部运行 ingress 控制器并且对 F5 编程作为负载均衡器。这里没有严格的规定,Kubernetes 就是如此灵活。

Client-go

这里有几种获得 Kubernetes 集群及其资源相关信息的方法,你可以使用 Dashboard、kubectl 或者使用对 Kubernetes API 的编程式访问来实现。Client-go 所有用 Go 语言编写的工具中使用最为广泛的库,还有许多其他语言的版本(java、python 等)。如果你还没自己写过控制器,我推荐你 首先去尝试 go/client-go。Kubernetes 是用 Go 编写的,而且我发现使用和主项目相同的语言来开发插件会更加方便。

我们来搭建吧……

要熟悉相关的平台和工具,最好的办法就是去实践,去实现一些东西。我们从简单入手,先实现一个如下的控制器:


1、监控 Kubernetes 节点


2、当节点上的镜像占用存储空间时进行警报,并且可以更改


这部分的实现,源码可以在这里找到:


https://github.com/alena1108/kubecon2017

基本流程

配置项目

作为一名开发者,我和 Rancher Labs 的同事们更愿意使用轻便简易的工具,在这里我将分享 3 个我最喜欢的工具,它们将帮助我们完成第一个项目。


1、go-skel – Go 语言的微服务 skeleton,只需执行 run ./skel.sh test123 即可,它会为新的 go 项目 test123 创建 skeleton。


2、trash – Go 语言的供应商管理工具。实际上这儿有很多依赖项管理工具,但是在临时依赖项管理方面,trash 使用起来非常出色,而且简单。


3、dapper – 在一致性环境中对任何现有构建工具进行封装的一种工具

添加 client-go 作为一个依赖项

为了方便使用 client-go 的代码,我们必须要将其设置为项目的依赖项。将它添加到 vendor.conf 文件中:



接着运行trash。它会将 vendor.conf 中定义的所有依赖项都拉到项目的 vendor 文件夹中。在这里需要确保 client-go 与你集群对应的 Kubernetes 版本是兼容的。

创建一个客户端

在创建与 Kubernetes API 通信的客户端之前,我们必须要先决定如何运行我们的工具:是在 Kubetnetes 集群内部还是外部。当应用程序在集群内部运行时,对它进行容器化,部署成为 Kubernetes pod。它还提供了一些额外的功能:你可以选择部署它的方式(Deamon set 运行在每个节点上,或者作为 n 个副本的部署),配置针对它的健康检查等等。当应用程序在集群外部运行时,就需要自己来管理它。下面的配置可以让我们的工具变得更灵活,并且支持基于 config flag 定义客户端的两种方式:



我们将在调试应用程序时使用集群外部运行的方式,这样你不需要每次都构建镜像并且将其重新部署成 Kubernetes pod。在测试好应用程序后,我们就可以构建镜像并将其部署到集群中。


正如在截图中看到的那样,正在构建配置,并将其传递到kubernetes.NewForConfig来生成客户端。

使用基本的 CRUDs

我们的工具需要监控节点。在实现逻辑流程之前,我们先来熟悉使用 client-go 执行 CRUD 操作:



上面的截图展示了:


1、List 节点 minikube,是经过 FieldSelector 过滤器实现的


2、用新的标注来更新节点


3、使用 gracePerios=10 秒指令删除节点—意思是从该命令执行后 10 秒才会执行删除操作


上面所有的步骤都是使用我们之前创建的用户集(clientset)进行的。


我们还需要节点上镜像的相关信息;它可以通过访问相应的字段来检索:


使用 Informer 来进行监控/通知

现在我们知道了如何从 Kubernetes APIs 中获取节点并从中得到镜像信息。那么我们该如何监控镜像大小的变化呢?最简单的方法是 周期性轮询节点,计算当前的镜像存储容量,并将其和先前轮询的结果比较。这里的不足之处在于:无论节点是否发生变化,我们执行的列表调用都会获取所有的节点,这可能会很费资源——特别是当轮询间隔很短的时候。而我们真正想要实现的是—在节点发生变化时得到通知,只有在这之后才执行我们的逻辑流程。这些就是 client-go 的 Informer 来做的。



在这个例子中,我们经过watchList指令为节点对象创建 Informer 来监控节点,设置对象类型为api.Node和 30 秒的同步周期来周期性地轮询节点,无论节点是否发生改变——这种方式在更新事件出于某种原因发生终止时可以很好的进行撤回。在最后一个参数,我们传递了 2 个回调函数——handleNodeAdd 和 handleNodeUpdate。这些回调函数具有实际的逻辑,并且在节点上的镜像占用存储发生改变时触发。NewInformer 返回 2 个对象——controller 和 store。一旦 controller 启动,将会开始对 node.update 和 node.add 的监控,并且调用回调函数。这部分代码的存储区位于内存缓存中,由 informer 负责更新,另外你可以在缓存区中获取节点对象而不用直接调用 Kubernetes APIs:



我们的项目中只有一个控制器,使用常规的 Informer 就足够了。不过,如果未来你的项目最终同一个对象拥有了多个控制器,我 建议你使用 SharedInformer。这样一来你不用再一个一个为每个控制器配上 Informer,只需要注册一个 Shared informer 即可,并且让每个控制器注册自己的一组回调函数,返回共享缓存,这可以减少内存占用:


部署时间

是时候来部署和测试代码了!对于第一次运行,我们只需要创建一个 go 的二进制文件并且在集群外模式下运行它即可:



如要更改消息输出,那么使用镜像部署一个 pod,该镜像是没有在当前节点显示的镜像。


在基本的功能通过测试之后,接下来就是按照集群模式尝试运行它了。为此我们必须先创建镜像,定义它的 Dockerfile:



并使用docker build创建一个镜像,该命令将生成一个可用在 Kubernetes 中部署 pod 的镜像。现在你的应用程序可以作为一个 pod 运行在 Kubernetes 集群上了。这里是一个部署定义的例子,在之前的截图中,我使用了该例部署我们的应用程序:



在本文中我们做了如下工作:


1、创建 go 项目


2、为项目添加 client-go 包的依赖项


3、创建用于和 Kubernetes api 通信的客户端


4、定义一个用于监控节点对象改变,并且一旦发生就执行回调函数的 Informer


5、在回调函数中实现一个实际的逻辑


6、在集群外运行二进制文件来测试代码,并把它部署到集群中


2020-04-12 20:401424

评论

发布
暂无评论
发现更多内容

架构师训练营 - 第 11 周作业

Jam

极客大学架构师训练营 0 期 week 11 学习笔记

chun1123

安全 高可用系统的架构

系统不可用的原因和解决方案

极客李

极客时间架构师训练营 - week11 - 作业 2

jjn0703

极客大学架构师训练营

架构师训练营第 0 期第 11 周作业

无名氏

第十一周命题作业

菲尼克斯

第十一周学习总结

菲尼克斯

架构师训练营第十一周作业

子豪sirius

高可用的系统架构

莫莫大人

极客大学架构师训练营

Week 11命题作业

Jeremy

云上度假村木莲庄酒店助你远离城市的喧嚣

InfoQ_967a83c6d0d7

etcd的高可用

李小匪

Apache Pulsar 社区周报:08-15 ~ 08-21

Apache Pulsar

云原生 Apache Pulsar 消息系统 消息中间件

java安全编码指南之:拒绝Denial of Service

程序那些事

Java 安全编码指南 java安全编码 DOS攻击 zip炸弹

漫画解读:唐僧师徒如何帮助大唐官网打造CDN+OSS完美架构?

阿里云Edge Plus

极客大学架构师训练营第十一周学习总结

竹森先生

架构师训练营 Week 11 总结

Wancho

极客大学架构师训练营 0 期 week 11 作业

chun1123

高可用 密码校验

Flink算子状态-9

小知识点

scala 大数据 flink

架构师训练营 Week 11 作业

Wancho

架构师训练营 第十一周 作业

CR

架构师训练营 第十一周 总结

CR

【高并发】高并发秒杀系统架构解密,不是所有的秒杀都是秒杀!

冰河

高并发 分布式限流 秒杀系统 异步削峰 签约计划第二季

用户密码验证函数

周冬辉

加密

系统稳定高可用的方案以及用户密码验证函数

Acker飏

Week 11 作业

鱼_XueTr

用户密码验证函数

任小龙

安全架构和高可用系统的架构

周冬辉

高可用系统的架构

Newbe.Claptrap 框架入门,第四步 —— 利用 Minion,商品下单

newbe36524

云计算 微服务 dock .net core ASP.NET Core

【华为云数据库技术大公开】机房失火后,还能拯救你的数据吗?

华为云开发者联盟

数据库 机房 华为云 数据存储 云数据库

Week11作业1

熊威

如何在GO语言中使用Kubernetes API?_文化 & 方法_Rancher_InfoQ精选文章