青海网站建设哪家强,wordpress聚合插件,软文投放平台有哪些?,济南建设信息网官网文章目录 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 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
客户端列出了各种语言对应的访问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的依赖
lyamlyaml文件的解析luajsonjson的解析base64解析tokenluasechttpsluasockethttps依赖luasocketfun提供了一些iter、map等操作可以改写lpegluajson依赖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.podsextras中有两个方法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)创建资源提供创建资源的yamlupdate(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资源的yamlpatch变更的字段stylebody
5 lua相关
5.1 self
self类似于c/java中的this和python中的selfc/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元素则抛出异常函数返回新的tablegetmetatable(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, #mytable1, 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, #self1, self)return selfendend
})local secondtable {4,5,6}mytable:plus(secondtable)for i1,#mytable doprint(mytable[i])
end这里是给table增加了plus方法通过增加带__index的metatable实现__index对应的是个函数而且它返回的也是个函数返回的这个函数完成的就是两个table拼接的操作。因此当调用mytable:plus时由于mytable没有plus对应的值就会查找metatable中的__index元素由于__index存在则会调用并传入mytable和调用的键因此这里keyplus而__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的所有podhttp://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-kindconcat是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中的selfLua 元表(Metatable)Lua 5.4 Reference Manualk8s restful API 结构分析对lua继承中self.__index self的释疑Kubernetes API