Go\Gin\Mustache
给K8s做一个小功能,主要使用kubectl调用若干命令,包括一些静态页面,使用Go语言开发,包括gonic/gin、hoisie/mustache这些第三方包,前端简单使用vue+elementui。使用go的主要原因是生产环境的不确定,只确定是centos系统,不确定有没有python或者java的运行环境,为了避免麻烦,正好可以利用go的可移植性...
给K8s做一个小功能,主要使用kubectl调用若干命令,包括一些静态页面,使用Go语言开发,包括gonic/gin、hoisie/mustache这些第三方包,前端简单使用vue+elementui。
使用go的主要原因是生产环境的不确定,只确定是centos系统,不确定有没有python或者java的运行环境,为了避免麻烦,正好可以利用go的可移植性
查看go支持的平台列表的命令
go tool dist list
在mac上开发go,go build编译出的文件不能运行在linux平台,须使用以下命令build
env GOOS=linux GOARCH=amd64 GOARM=7 go build
利用go mod和JetBrains的Goland可以避免go path等一些恼人的问题,确实可以提高效率。
额外值得介绍的:mustache模版规范,类似于JSON或者XML,mustache是规范,不是API接口。具体可参考:
https://mustache.github.io/
为什么要用mustache呢?举个简单例子,程序中要定制K8s的yaml文件,需要替换yaml中的一些参数,在程序中一行一行生成一个yaml文件太麻烦,利用mustache模版可以轻松解决,mustache模版支持循环和判断,可以满足大部分需要,比如下面mustache模版的例子:
apiVersion: xxxx/v1
kind: XXX
metadata:
name: {{dep_name}}
namespace: kube
spec:
template:
spec:
containers:
- image: {{image}}
imagePullPolicy: Never
name: tens
command: ["{{comm}}", "{{arg}}"]
args:
{{#args}}
- --{{Key}}={{Value}}
{{/args}}resources:
limits:
cpu: {{cpu}}
volumeMounts:
- name: {{volumeMountname}}
mountPath: "{{mountPath}}"
restartPolicy: Never
其中 {{dep_name}}就是需要被替换的变量,{{#args}}...{{/args}}则表示循环替换--{{Key}}={{Value}},最终被rander出来的yaml文件如下:
apiVersion: xxxx/v1
kind: XXX
metadata:
name: 1111
namespace: kube
spec:
template:
spec:
containers:
- image: Image
imagePullPolicy: Never
name: tensorflow
command: Command
args:
- --1=1
- --2=2
- --3=3
resources:
limits:
cpu: 2
volumeMounts:
- name: VolumeMount
mountPath: Mount Path
restartPolicy: Never
go本身没有mustache模版api,一般使用hoisie/mustache提供的api,这个api已经5、6年没有更新了,事实上mustache规范也没怎么变过,go语言向下兼容也不错,也许稳定就是这个api最大的优势吧,简单代码示例如下:
type DEP struct {
Count string `json:"count"`
Replicas []Replica `json:"replicas"`
}
type Replica struct {
Type string `json:"type"`
Num string `json:"num"`
Image string `json:"image"`
Command string `json:"command"`
Args []Arg `json:"args"`
VolumeMountname string `json:"volumeMountname"`
MountPath string `json:"mountPath"`
VolumesName string `json:"volumesName"`
}
type Arg struct {
Key string `json:"key"`
Value string `json:"value"`
}
func RenderJob(dep DEP)(string, error) {
rep := dep.Replicas[0]
comms := strings.Split(rep.Command, ",")
data := mustache.RenderFile("template/cpu.yaml.template",
map[string]interface{}{
...
"arg": comms[1],
"cpu": rep.Cpu,
"args": rep.Args,
"volumeMountname": rep.VolumeMountname,
"mountPath": rep.MountPath,
"valumesNameClaim": rep.VolumesName,
"valumesName": rep.VolumesName})
print(data)
WriteYml("yml/"+tfj.TrainName+".yaml", data)
}
...
func WriteYml(fileName string, dataStr string) {
dstFile, err := os.Create(fileName)
if err != nil {
fmt.Println(err.Error())
return
}
defer dstFile.Close()
dstFile.WriteString(dataStr)
}
关于gin,是一个go的web服务器程序,官网如下:
https://gin-gonic.com/
https://github.com/gin-gonic/gin
网传gin比beego的性能好很多,至于为什么没用go自带的http api,是因为怕后续添加复杂功能的话,自带的http api应付不来
加入html前端显示的页面,只需在go工程目录内建一个存放html文件的目录即可,如下,在demo-go工程内建一个html文件夹就可以了
└── demo-go
├── go.mod
├── go.sum
├── html
│ ├── css
│ │ ├── fonts
│ │ │ ├── element-icons.eot
│ │ │ ├── element-icons.ttf
│ │ │ └── element-icons.woff
│ │ ├── index.css
│ │ └── custom.css
│ ├── index.html
│ ├── js
│ │ ├── axios.min.js
│ │ ├── elementui
│ │ │ ├── index.js
│ │ │ └── index.js.1
│ │ ├── main.js
│ │ └── vue.min.js
│ ├── sec.html
│ ├── fir.html
│ └── main.html
├── main.go
gin定义路由如下即可:
package main
import (
"github.com/gin-gonic/gin"
"net/http"
"os"
)
func execRouter() {
engine := gin.Default()
//定义了一个/configmap的路由
engine.GET("/configmap", func(c *gin.Context) {
res, err := util.Configmap()
if err != nil {
c.JSON(500, gin.H{
"message": err.Error(),
})
}
print(res)
c.JSON(200, gin.H{
"message": res,
})
})
//静态html页面的工程内路径
engine.Static("/html", "./html")
//服务监听的端口
engine.Run(":9311")
}
func main() {
//启动http服务
execRouter()
}
调用kubectl命令直接使用go自带exec.Command方法即可:
func Configmap() (string, error) {
cmd := exec.Command("kubectl","get","configmap","-o","json")
var out bytes.Buffer
var stderr bytes.Buffer
cmd.Stdout = &out
cmd.Stderr = &stderr
err := cmd.Run()
if err != nil {
fmt.Println(fmt.Sprint(err) + ": " + stderr.String())
return "", err
}
fmt.Println("Result: " + out.String())
return out.String(), nil
}
如此,一个简单的go工程即搭建完毕,有模版渲染、有http服务,虽然没有用到更高级的go特性,作为试水还是可以的。
敬请关注:
更多推荐
所有评论(0)