给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/v1kind: XXXmetadata:  name: {{dep_name}}  namespace: kubespec:  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/v1kind: XXXmetadata:  name: 1111  namespace: kubespec:  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 mainimport (  "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特性,作为试水还是可以的。

   

敬请关注:

 

Logo

K8S/Kubernetes社区为您提供最前沿的新闻资讯和知识内容

更多推荐