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

【kubernetes】使用luakube访问kubernetes api

文章目录

      • 1 kubernetes client
      • 2 luakube初体验
      • 3 luakube代码分析
      • 4 luakube包的调用
      • 5 lua相关
        • 5.1 self
        • 5.2 metatable
          • 5.2.1 使用metatable对table新增操作符
          • 5.2.2 使用metatable对table新增方法
          • 5.2.3 再探luakube
      • 6 参考文档

1 kubernetes client

客户端列出了各种语言对应的访问k8s的客户端库,有官方维护的,还有一些是社区和个人维护的。

这里面没有列出lua的库,在GitHub上搜索可以看到有luakube,虽然好像没啥star,而且4个多月没更新了,可以用它进行测试下,如果基础的连接k8s的部分完成了,后面的各种资源操作可以自行开发和添加。当然,了解kubernetes api的都知道,这些api库基本就是对http api的调用封装,因此,luakube也是对http api的封装,它的优点在于,使用体验跟k8s的golang库的api类似,也就是拥有类k8s的调用方式。

2 luakube初体验

要使用luakube,第一步当然是环境安装,然后执行其中的示例代码。

luakube是个lua中的包,使用luarocks进行管理,因此,先安装lua和luarocks,然后再安装luakube。

luakube的依赖:

  • lyaml:yaml文件的解析
  • luajson:json的解析
  • base64:解析token
  • luasec:https
  • luasocket:https依赖luasocket
  • fun:提供了一些iter、map等操作,可以改写
  • lpeg:luajson依赖lpeg

luarocks中每个包都有一个rockspec文件,该文件描述了该包的依赖以及一些安装信息。因此,安装luakube有两种方式:要么按照rockspec的提示一个依赖一个依赖的安装,要么直接使用rockspec文件安装:

安装方法1:

yum install -y libyaml-devel
luarocks install lyaml
yum install -y lua-lpeg
luarocks install luajson
luarocks install luasocket
yum install -y openssl-devel
luarocks install luasec
luarocks install base64
luarocks install fun
luarocks install luakube

安装方法2:

luarocks install https://raw.githubusercontent.com/f4z3r/luakube/master/rockspecs/luakube-0.1.0-0.rockspec

安装方法3:

git clone https://github.com/f4z3r/luakube.git
cd luakube && luarocks make

第1种方法和第2种方法都是将luakube作为模块安装,相当于直接下载源码然后拷贝到安装目录,第3种方式是直接用本地目录中的rockspec文件进行安装,将本地目录的源代码拷贝到安装目录。

因此,如果是需要对luakube进行修改,可以用第3种方式,在本地目录修改后执行luarocks make,然后再进行测试。

安装完luakube,可以执行简单的demo代码进行测试,在luakube仓库的examples目录中有获取pod的logs的测试代码get_logs.lua:

local config = require "kube.config"
local api = require "kube.api"-- Use local kube config to connect to cluster
local conf = config.from_kube_config()
local global_client = api.Client:new(conf)-- Get the Core V1 client
local client = global_client:corev1()-- Get the last three lines of logs from the coredns container as a string
local container_logs = client:pods("kube-system"):logs("coredns-558bd4d5db-xr5tj", {tailLines = 3, container = "coredns"})-- Get the logs over the last 10 seconds for all containers in the pod
local last_logs = client:pods("kube-system"):logs("coredns-558bd4d5db-xr5tj", {sinceSeconds = 10})

测试时需要修改上面的名称空间和pod名,就可以得到对应pod的日志。

3 luakube代码分析

luakube源代码分成3个部分:

  • config.lua:对kubeconfig文件进行操作,外部代码实际调用时通常是调用from_kube_config(如果参数指定了kubeconfig文件,则用该文件作为凭证,如果没有指定,则用默认的kubeconfig文件路径)和in_cluster_config(在k8s集群中运行时获取sa的token作为凭证)
  • api.lua:对https调用的封装
  • api/:对每个version对应的资源进行操作

下面从分析examples/get_logs.lua的角度看下luakube的具体实现。

local conf = config.from_kube_config()

首先获取到kubeconfig配置,如果没有提供文件名,则使用默认配置文件($HOME/.kube/config)。

local global_client = api.Client:new(conf)

根据上面得到的kubeconfig配置创建client,这里创建的就是api.lua中的api.Client。

local client = global_client:corev1()

调用api.lua中的api.Client:corev1()获取某个版本的api。

local container_logs = client:pods("kube-system"):logs("coredns-558bd4d5db-xr5tj", {tailLines = 3, container = "coredns"})

上面的代码是获取kube-system命名空间的coredns-558bd4d5db-xr5tj这个pod的coredns容器的后面3行日志。

调用client:pods就是调用core_v1.lua中的core_v1.Client.pods = utils.generate_object_client("pods", pod_base, true, true, true, extras),而utils.generate_object_client则是返回一个client,该client有各种操作资源的方法,同时还会将extras中指定的一些方法也放到该client中,对于core_v1.Client.pods,extras中有两个方法:logs和ephemeralcontainers,分别用于获取日志和临时容器。

当执行logs()时,就会调用extras中的logs方法,它会调用自身的raw_call()方法,而raw_call该方法就定义于api.lua中。

相当于调用的起点和终点都位于api.lua中。

在整体的实现中,用到了lua中的metadata编程,让返回的client拥有各种方法。

4 luakube包的调用

了解了上述实现的函数调用流程,在具体使用luakube包时,就可以按照k8s的设计调用相关的通用的函数。

例如,对于pod,可以使用client:pods(“kube-system”):list()获取kube-system命名空间的所有pod的列表,其他的如nodes、services、configmaps、secrets、serviceaccounts等都有类似的调用。

当前资源支持的操作有:

  • get(name, query):获取某个资源,可以给出资源名称
  • status(name):资源状态
  • create(obj, query):创建资源,提供创建资源的yaml
  • update(obj, query):更新资源
  • update_status(obj, query):更新资源状态
  • patch(name, patch, query, style):变更资源
  • path_status(name, patch, query, style):变更资源状态
  • delete(name, query):删除资源
  • delete_collection(body, query)
  • list(query):列出资源

其中:

  • name:资源名称
  • query:获取资源的条件,这个需要传table,然后会拼接到https请求的后面
  • obj:资源的yaml
  • patch:变更的字段
  • style
  • body

5 lua相关

5.1 self

self类似于c++/java中的this和python中的self,c++/java中的this由编译器自动处理,python中的self需要开发人员添加,而lua中的self还提供了语言级别的区分:

local t = {a = 1, b = 2}
function t:Add()return (self.a + self.b)
end
function t.Sub(self)return (self.a - self.b)
endprint(t.Add(t))
print(t:Sub())

如果用冒号定义和调用方法,lua解释器会自动添加self,如果用点号,则需要开发人员添加self。

5.2 metatable

metatable翻译为元表,可以理解为table的额外属性,当访问table的一些操作时,如果table不存在,可以由元表进行完成。

lua中的metatable的概念跟python中的保留方法很像:

python中对于双下划线开头和结尾的方法有特殊含义,例如,当创建一个对象时,就是调用类的__init__()方法,当用iter某个序列时,就是调用类的__iter__()方法,也就是说,当对对象调用某个方法时,会调用某个约定好的方法,如果开发人员没有定义则调用默认的方法,当然,默认方法必须要支持此类行为,例如,如果用iter遍历一个不能遍历的对象,如果没有定义__iter__()则会调用失败。

在lua中,除了常用的基本数据类型(nil、布尔、数字、字符串)之外,table是lua提供的唯一的的复合数据类型(其他数据类型都是针对特定场景),table可以用于实现数组、集合、字典、类等类型,而metatable就是在table上面附加的一种属性,也就是说,metatable只针对table类型。

跟python类似,在lua中,双下划线开头的方法有特殊含义,例如,当用+操作符对两个table相加时,就是调用第一个table的metatable中的__add()方法,这种相当于实现了对操作符的自定义,跟python中的__add__和C++中的operator +类似;当调用table一个不存在的方法时,就会调用table的metatable中的对应的方法,这种相当于实现了对类方法的动态增加。

要想使用metatable,有两个重要的方法:

  • setmetatable(table, metable):设置table的metatable,虽然这里是table,但是根据lua的文档可以知道,任何值都有metatable,但是只有table的metable可以在lua中通过setmtatable修改,其他类型只能通过C语言修改。如果metatable设置为nil,则删除table的metatable;如果table的metatable中有__metatable元素,则抛出异常,函数返回新的table
  • getmetatable(object):返回对象的metatable。如果object没有metatable,则返回nil;如果object的metatable有__metatable元素,则返回对应的值;如果object的metatable没有__metatable元素,则返回对象的metatable。

下面演示操作符的实现和方法的增加:

5.2.1 使用metatable对table新增操作符
mytable = setmetatable({ 1, 2, 3 }, {__add = function(mytable, newtable)return table.move(newtable, 1, #newtable, #mytable+1, mytable)end
})secondtable = {4,5,6}mytable = mytable + secondtablefor k,v in ipairs(mytable) doprint(k,v)
end

使用setmetatable对table增加__add方法,__add实现时使用了table的move方法将第二个table中的元素放到第一个table中。

5.2.2 使用metatable对table新增方法
local mytable = {1, 2, 3}setmetatable(mytable, {__index = function(mytable, key)return function(self, newtable)table.move(newtable, 1, #newtable, #self+1, self)return selfendend
})local secondtable = {4,5,6}mytable:plus(secondtable)for i=1,#mytable doprint(mytable[i])
end

这里是给table增加了plus方法,通过增加带__index的metatable实现,__index对应的是个函数,而且它返回的也是个函数,返回的这个函数完成的就是两个table拼接的操作。因此,当调用mytable:plus时,由于mytable没有plus对应的值,就会查找metatable中的__index元素,由于__index存在,则会调用,并传入mytable和调用的键,因此,这里key==plus,而__index返回的时个函数,也就是说,mytable:plus返回的是个函数,然后用里面的这层函数调用,newtable传入的就是secondtable。

5.2.3 再探luakube

luakube通过k8s的rest api访问,因此,只要知道调用接口的url和参数即可。

k8s的rest api的url格式如下:

http://[api/apis]/api-group/api-version/namespaces/namespace/resource-kind/resource-name

例如,获取命名空间default的所有pod:http://127.0.0.1:8001/api/v1/namespaces/default/pods

而k8s的rest api,其实就是完成资源操作的CRUD,只有在需要提供yaml文件时,才会把yaml文件放到body里面,其他的参数都放到url里面,因此,重点就是要对url进行拼接和调用。

luakube为了使得调用封装的调用更加灵活,将url中不同的部分放到不同的地方。

开始的api和apis在api.lua中,现在只有api/v1是api,其他都是apis。

api-group/api-version在utils.lua的utils.generate_base(api)中,其中参数api就是api-group/api-version,在下面client.call中会将self.api_拼接到路径前面进行调用。

剩下的部分则在utils.lua的utils.generate_object_client(api,concat,namespaced)中,其中参数api就是资源类型resource-kind,concat是yaml中的apiVersion和kind,对于需要yaml文件作为参数的需要,namespaced则是说明该资源是否可以指定namespace,当然,最终是否要加上namespace,还要基于是否提供namespace参数。而最后的resource-name则是通过utils.generate_object_client()中的调用方法提供。

为了将上述的调用串起来,代码中大量使用下面的操作:

self.__index = self
setmetatable(o, self)

上面的代码将self作为o的metatable中的__index元素,于是,当访问o中的元素没有时,就会访问self中的元素,这样能够实现类似继承的机制,同时也可以给o添加方法,让o去调用self的方法,相当于子类调用父类的方法。

因此,将上面的url串起来的方式就是,在utils.generate_object_client()里面创建client,然后将core_v1.Client当作parent参数作为client的metatable,而core_v1.Client是通过utils.generate_base()返回的函数创建的client,这里又通过类似的机制调用api.lua中的方法。

总结下,通过metatable实现类似继承的机制,然后通过继承关系拼接url,最终调用api.lua中的https接口实现k8s的api的访问。

6 参考文档

  • Lua中的self
  • Lua 元表(Metatable)
  • Lua 5.4 Reference Manual
  • k8s restful API 结构分析
  • 对lua继承中self.__index = self的释疑
  • Kubernetes API

相关文章:

【kubernetes】使用luakube访问kubernetes api

文章目录 1 kubernetes client2 luakube初体验3 luakube代码分析4 luakube包的调用5 lua相关5.1 self5.2 metatable5.2.1 使用metatable对table新增操作符5.2.2 使用metatable对table新增方法5.2.3 再探luakube 6 参考文档 1 kubernetes client 客户端列出了各种语言对应的访问…...

【算法分析与设计】贪心算法(下)

目录 一、单源最短路径1.1 算法基本思想1.2 算法设计思想1.3 算法的正确性和计算复杂性1.4 归纳证明思路1.5 归纳步骤证明 二、最小生成树2.1 最小生成树性质2.1.1 生成树的性质2.1.2 生成树性质的应用 2.2 Prim算法2.2.1 正确性证明2.2.2 归纳基础2.2.3 归纳步骤2.3 Kruskal算…...

Arm Cache学习资料大汇总

关键词:cache学习、mmu学习、cache资料、mmu资料、arm资料、armv8资料、armv9资料、 trustzone视频、tee视频、ATF视频、secureboot视频、安全启动视频、selinux视频,cache视频、mmu视频,armv8视频、armv9视频、FF-A视频、密码学视频、RME/CC…...

Docker 学习总结(79)—— Dockerfile 编写技巧总结

目标 更快的构建速度 更小的 Docker 镜像大小 更少的 Docker 镜像层 充分利用镜像缓存 增加 Dockerfile 可读性 让 Docker 容器使用起来更简单 总结 编写 .dockerignore 文件 容器只运行单个应用 将多个 RUN 指令合并为一个 基础镜像的标签不要用 latest 每个 RUN 指令后删除多…...

链表经典面试题(二)

返回中间结点 1.中间结点的题目2.中间结点的图文分析3.中间结点的基本代码4.中间结点的优化代码 1.中间结点的题目 2.中间结点的图文分析 方法1:先求整体长度,再除以2,所得到的就是中间结点 方法2:双指针法,快指针走两…...

89、Redis 的 value 所支持的数据类型(String、List、Set、Zset、Hash)---->Zset 相关命令

本次讲解要点: ** Set相关命令:是指value中的数据类型** 启动redis服务器: 打开小黑窗: C:\Users\JH>e: E:>cd E:\install\Redis6.0\Redis-x64-6.0.14\bin E:\install\Redis6.0\Redis-x64-6.0.14\bin>redis-server.exe …...

知识图谱02——使用python将信息录入neo4j

将文档传入chatgpt,生成对应的cypher语句 链接: https://pan.baidu.com/s/1Ny-ttbBSpqYEigwYiCWMeA?pwdc7sc 提取码: c7sc 使用命令行安装对应的包 pip install neo4jchatgpt生成出的txt文档中的内容如下: MERGE (Node1:Entity {name: 原始舱单提运单…...

greenDAO-Android轻量级快速ORM框架

官网 https://github.com/greenrobot/greenDAO 简介 greenDAO is a light & fast ORM for Android that maps objects to SQLite databases. Being highly optimized for Android, greenDAO offers great performance and consumes minimal memory. Home page, documen…...

结构型设计模式——组合模式

摘要 组合模式(composite pattern): 允许你将对象组合成树形结构来表现"整体/部分"层次结构. 组合能让客户以一致的方式处理个别对象以及对象组合。 一、组合模式的意图 将对象组合成树形结构来表示“整体/部分”层次关系,允许用户以相同的方式处理单独…...

40. 组合总和 II

给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使用 一次 。 注意:解集不能包含重复的组合。 示例 1: 输入: candidates [10,1,2,7,6,1,5…...

安卓玩机-----给app加注册码 app加弹窗 云注入弹窗

在对接很多工作室业务中有些客户需要在他们自带的有些app中加注册码或者验证码的需求。其实操作起来也很简单。很多反编译软件有自带的注入功能。例如注入弹窗。这个是需要对应的注册码来启动应用。而且是随机id。重新安装app后需要重新注册才可以继续使用,原则上可…...

NLP的不同研究领域和最新发展的概述

一、介绍 作为理解、生成和处理自然语言文本的有效方法,自然语言处理 (NLP) 的研究近年来迅速普及并被广泛采用。鉴于NLP的快速发展,获得该领域的概述和维护它是困难的。这篇博文旨在提供NLP不同研究领域的结构化概述,…...

1.物联网射频识别,RFID概念、组成、中间件、标准,全球物品编码——EPC码

1.RFID概念 RFID是Radio Frequency Identification的缩写,又称无线射频识别,是一种通信技术,可通过无线电讯号识别特定目标并读写相关数据,而无需与被识别物体建立机械或光学接触。 RFID(Radio Frequency Identificati…...

MySQL函数与控制结构

MySQL数据库管理系统在数据存储和检索方面发挥着重要作用。除了基础的数据操作外,MySQL还提供了丰富的函数和控制结构来进行更复杂的数据处理。 本文将详细介绍如何在MySQL中使用begin-end语句块、自定义函数、以及各种控制语句。通过《三国志》游戏数据的实例将更深入地了解…...

【论文极速读】Prompt Tuning——一种高效的LLM模型下游任务适配方式

【论文极速读】Prompt Tuning——一种高效的LLM模型下游任务适配方式 FesianXu 20230928 at Baidu Search Team 前言 Prompt Tuning是一种PEFT方法(Parameter-Efficient FineTune),旨在以高效的方式对LLM模型进行下游任务适配,本…...

如何在 Elasticsearch 中使用 Openai Embedding 进行语义搜索

随着强大的 GPT 模型的出现,文本的语义提取得到了改进。 在本文中,我们将使用嵌入向量在文档中进行搜索,而不是使用关键字进行老式搜索。 什么是嵌入 - embedding? 在深度学习术语中,嵌入是文本或图像等内容的数字表示…...

世界第一ERP厂商SAP,推出类ChatGPT产品—Joule

9月27日,世界排名第一ERP厂商SAP在官网宣布,推出生成式AI助手Joule,并将其集成在采购、供应链、销售、人力资源、营销、数据分析等产品矩阵中,帮助客户实现降本增效。 据悉,Joule是一款功能类似ChatGPT的产品&#xf…...

嵌入式Linux应用开发-基础知识-第十八章系统对中断的处理③

嵌入式Linux应用开发-基础知识-第十八章系统对中断的处理③ 第十八章 Linux系统对中断的处理 ③18.5 编写使用中断的按键驱动程序 ③18.5.1 编程思路18.5.1.1 设备树相关18.5.1.2 驱动代码相关 18.5.2 先编写驱动程序18.5.2.1 从设备树获得 GPIO18.5.2.2 从 GPIO获得中断号18.5…...

【Python】返回指定时间对应的时间戳

使用模块datetime,附赠一个没啥用的“时间推算”功能(获取n天后对应的时间 代码: import datetimedef GetTimestamp(year,month,day,hour,minute,second,*,relativeNone,timezoneNone):#返回指定时间戳。指定relative时进行时间推算"""根…...

微服务moleculer03

1. Moleculer 目前支持SQLite,MySQL,MariaDB,PostgreSQL,MSSQL等数据库,这里以mysql为例 2. package.json 增加mysql依赖 "mysql2": "^2.3.3", "sequelize": "^6.21.3", &q…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

零基础设计模式——行为型模式 - 责任链模式

第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...

android13 app的触摸问题定位分析流程

一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...

Python竞赛环境搭建全攻略

Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型(算法、数据分析、机器学习等)不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...

数据结构:递归的种类(Types of Recursion)

目录 尾递归(Tail Recursion) 什么是 Loop(循环)? 复杂度分析 头递归(Head Recursion) 树形递归(Tree Recursion) 线性递归(Linear Recursion)…...

实战设计模式之模板方法模式

概述 模板方法模式定义了一个操作中的算法骨架,并将某些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的前提下,重新定义算法中的某些步骤。简单来说,就是在一个方法中定义了要执行的步骤顺序或算法框架,但允许子类…...

【Linux】Linux安装并配置RabbitMQ

目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...

jdbc查询mysql数据库时,出现id顺序错误的情况

我在repository中的查询语句如下所示&#xff0c;即传入一个List<intager>的数据&#xff0c;返回这些id的问题列表。但是由于数据库查询时ID列表的顺序与预期不一致&#xff0c;会导致返回的id是从小到大排列的&#xff0c;但我不希望这样。 Query("SELECT NEW com…...

《信号与系统》第 6 章 信号与系统的时域和频域特性

目录 6.0 引言 6.1 傅里叶变换的模和相位表示 6.2 线性时不变系统频率响应的模和相位表示 6.2.1 线性与非线性相位 6.2.2 群时延 6.2.3 对数模和相位图 6.3 理想频率选择性滤波器的时域特性 6.4 非理想滤波器的时域和频域特性讨论 6.5 一阶与二阶连续时间系统 6.5.1 …...

小智AI+MCP

什么是小智AI和MCP 如果还不清楚的先看往期文章 手搓小智AI聊天机器人 MCP 深度解析&#xff1a;AI 的USB接口 如何使用小智MCP 1.刷支持mcp的小智固件 2.下载官方MCP的示例代码 Github&#xff1a;https://github.com/78/mcp-calculator 安这个步骤执行 其中MCP_ENDPOI…...