0

是否有关于在 go-client 某处构建k8s 作业的文档?特别是我正在尝试将工作 yaml 转换为代码,并且在我的一生中找不到说明字段如何转换的参考文档

4

2 回答 2

1

k8s.io/api是 Kubernetes 的一个包,它kubectl和其他组件使用它来实现 Kubernetes API。在这个包中,有一个实现JobAPI 的结构体,您可以使用它来将 Job 清单转换为 Go 结构体。

我认为这段代码可以提供帮助:

package main

import (
    "fmt"
    "io/ioutil"
    "os"

    "gopkg.in/yaml.v2"
    v1 "k8s.io/api/batch/v1"
)

func main() {
    file, err := os.Open("/path/to/job.yaml")
    if err != nil {
        panic(err)
    }

    b, err := ioutil.ReadAll(file)
    if err != nil {
        panic(err)
    }

    job := &v1.Job{}
    err = yaml.Unmarshal(b, job)
    if err != nil {
        panic(err)
    }

    fmt.Println(job)
}
于 2020-06-11T05:23:37.387 回答
0

将 YAML 转换为 Golang 可能很困难,并且经常缺少带有示例的文档。

我编写了一个名为naml的工具,它能够将任何 Kubernetes YAML 转换为原始 Go。它很方便,因为它使用您运行它的 Kubernetes 版本,并且使用最新版本的 Kubernetes 代码库编译。

如果您想创建一个 Job,并查看该 Job 的有效 Go,它看起来像这样。beeps使用容器映像创建作业boops

[nova@emma ~]$ kubectl create job beeps --image boops
job.batch/beeps created
[nova@emma ~]$ 

Naml 将通过设计输出一个工作程序,但您也将获得您正在寻找的输出。

[nova@emma naml]$ kubectl get job beeps -o yaml | naml codify
// Copyright © 2021 Kris Nóva <kris@nivenly.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//   ███╗   ██╗ █████╗ ███╗   ███╗██╗
//   ████╗  ██║██╔══██╗████╗ ████║██║
//   ██╔██╗ ██║███████║██╔████╔██║██║
//   ██║╚██╗██║██╔══██║██║╚██╔╝██║██║
//   ██║ ╚████║██║  ██║██║ ╚═╝ ██║███████╗
//   ╚═╝  ╚═══╝╚═╝  ╚═╝╚═╝     ╚═╝╚══════╝
//

package main

import (
        "context"
        "fmt"
        "os"

        "github.com/hexops/valast"
        batchv1 "k8s.io/api/batch/v1"
        corev1 "k8s.io/api/core/v1"
        metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
        "k8s.io/apimachinery/pkg/types"

        "github.com/kris-nova/naml"
        "k8s.io/apimachinery/pkg/runtime"
        "k8s.io/client-go/kubernetes"
)

// Version is the current release of your application.
var Version string = "0.0.1"

func main() {
        // Load the application into the NAML registery
        // Note: naml.Register() can be used multiple times.
        naml.Register(NewApp("App", "Application autogenerated from NAML v0.3.1"))

        // Run the generic naml command line program with
        // the application loaded.
        err := naml.RunCommandLine()
        if err != nil {
                fmt.Println(err.Error())
                os.Exit(1)
        }
}

// App is a very important grown up business application.
type App struct {
        metav1.ObjectMeta
        description string
        objects     []runtime.Object
        // ----------------------------------
        // Add your configuration fields here
        // ----------------------------------
}

// NewApp will create a new instance of App.
//
// See https://github.com/naml-examples for more examples.
//
// This is where you pass in fields to your application (similar to Values.yaml)
// Example: func NewApp(name string, example string, something int) *App
func NewApp(name, description string) *App {
        return &App{
                description: description,
                ObjectMeta: metav1.ObjectMeta{
                        Name:            name,
                        ResourceVersion: Version,
                },
                // ----------------------------------
                // Add your configuration fields here
                // ----------------------------------
        }
}

func (a *App) Install(client *kubernetes.Clientset) error {
        var err error

        beepsJob := &batchv1.Job{
                TypeMeta: metav1.TypeMeta{
                        Kind:       "Job",
                        APIVersion: "batch/batchv1",
                },
                ObjectMeta: metav1.ObjectMeta{
                        Name:            "beeps",
                        Namespace:       "default",
                        UID:             types.UID("650e4f36-3316-4506-bbe0-1e34c13742cf"),
                        ResourceVersion: "3231200",
                        Generation:      1,
                        Labels: map[string]string{
                                "controller-uid": "650e4f36-3316-4506-bbe0-1e34c13742cf",
                                "job-name":       "beeps",
                        },
                },
                Spec: batchv1.JobSpec{
                        Parallelism:  valast.Addr(int32(1)).(*int32),
                        Completions:  valast.Addr(int32(1)).(*int32),
                        BackoffLimit: valast.Addr(int32(6)).(*int32),
                        Selector: &metav1.LabelSelector{MatchLabels: map[string]string{
                                "controller-uid": "650e4f36-3316-4506-bbe0-1e34c13742cf",
                        }},
                        Template: corev1.PodTemplateSpec{
                                ObjectMeta: metav1.ObjectMeta{Labels: map[string]string{
                                        "controller-uid": "650e4f36-3316-4506-bbe0-1e34c13742cf",
                                        "job-name":       "beeps",
                                }},
                                Spec: corev1.PodSpec{
                                        Containers: []corev1.Container{corev1.Container{
                                                Name:                     "beeps",
                                                Image:                    "boops",
                                                TerminationMessagePath:   "/dev/termination-log",
                                                TerminationMessagePolicy: corev1.TerminationMessagePolicy("File"),
                                                ImagePullPolicy:          corev1.PullPolicy("Always"),
                                        }},
                                        RestartPolicy:                 corev1.RestartPolicy("Never"),
                                        TerminationGracePeriodSeconds: valast.Addr(int64(30)).(*int64),
                                        DNSPolicy:                     corev1.DNSPolicy("ClusterFirst"),
                                        SecurityContext:               &corev1.PodSecurityContext{},
                                        SchedulerName:                 "default-scheduler",
                                },
                        },
                        CompletionMode: valast.Addr(batchv1.CompletionMode("NonIndexed")).(*batchv1.CompletionMode),
                        Suspend:        valast.Addr(false).(*bool),
                },
        }
        a.objects = append(a.objects, beepsJob)

        if client != nil {
                _, err = client.BatchV1().Jobs("default").Create(context.TODO(), beepsJob, metav1.CreateOptions{})
                if err != nil {
                        return err
                }
        }

        return err
}

func (a *App) Uninstall(client *kubernetes.Clientset) error {
        var err error

        if client != nil {
                err = client.BatchV1().Jobs("default").Delete(context.TODO(), "beeps", metav1.DeleteOptions{})
                if err != nil {
                        return err
                }
        }

        return err
}

func (a *App) Description() string {
        return a.description
}

func (a *App) Meta() *metav1.ObjectMeta {
        return &a.ObjectMeta
}

func (a *App) Objects() []runtime.Object {
        return a.objects
}
于 2021-10-22T01:08:35.320 回答