将YAML格式的Kubernetes清单反序列化为Go语言对象

这是 ZOZO Advent Calendar 2023 日历 Vol.5 的第三天的文章。

以下本文将介绍如何将YAML格式的Kubernetes清单加载并反序列化为具有相应类型的Go语言对象。

通过使用 k8s.io/apimachinery 模块提供的 yaml 包的功能,可以实现这一点。

实施示例和解释

以下是一个例子,它读取以YAML格式编写的Pod清单文件,并将其反序列化为具有core/v1 Pod类型的对象,然后使用client-go从Go语言对象创建Kubernetes Pod对象。在这个例子中创建的Pod有以下两种类型。

    1. 具有原始清单字段值的Pod

 

    更改了Pod名称的新Pod
package main

import (
	"context"
	"flag"
	"fmt"
	"os"

	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime/serializer/json"
	"k8s.io/apimachinery/pkg/runtime/serializer/yaml"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/kubernetes/scheme"
	"k8s.io/client-go/tools/clientcmd"
)

var kubeconfig string

func main() {
	// YAMLマニフェストの読み込み
	path := "sample_pod.yaml"

	data, err := os.ReadFile(path)
	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	// シリアライザの作成
	jsonSerializer := json.NewSerializerWithOptions(
		json.SimpleMetaFactory{},
		nil,
		scheme.Scheme,
		json.SerializerOptions{},
	)
	yamlSerializer := yaml.NewDecodingSerializer(jsonSerializer)

	// 読み込んだYAMLマニフェストのバイト列をcorev1.Pod型のオブジェクトにデシリアライズ
	var original corev1.Pod
	if _, _, err := yamlSerializer.Decode(data, nil, &original); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	// Podを作成するクライアントの作成
	flag.StringVar(&kubeconfig, "kubeconfig", "", "kubeconfig path")
	flag.Parse()
	config, _ := clientcmd.BuildConfigFromFlags("", kubeconfig)
	clientset, _ := kubernetes.NewForConfig(config)

	// オブジェクトからsample-original Podを作成
	_, err = clientset.CoreV1().Pods("default").Create(context.TODO(), &original, metav1.CreateOptions{})

	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}

	// sample-originalオブジェクトのPod名を変更した新規オブジェクトを作成
	updated := original.DeepCopy()
	updated.ObjectMeta.Name = "sample-updated"

	// Pod名を変更した新規オブジェクトからsample-original Podを作成
	_, err = clientset.CoreV1().Pods("default").Create(context.TODO(), updated, metav1.CreateOptions{})

	if err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}

读取的YAML清单目标如下。

apiVersion: v1
kind: Pod
metadata:
  name: original-sample
  namespace: default
spec:
  containers:
  - name: sleep-container
    image: alpine
    command: ["sleep", "3600"]

以下是对deserialize.go的实现进行说明。

[]字节 → 对corev1.Pod的反序列化

将字节列(byte列)反序列化为corev1.Pod类型的对象是在yamlSerializer对象的Decode方法中完成的。
yamlSerializer对象的Decode方法会将接收到的YAML转换为JSON,并调用apimachinery/pkg/runtime/serializer/json包中Serializer类型的Decode方法。
如果对Decode的具体实现感兴趣,可以参考k8s.io/apimachinery/pkg/runtime/serializer/json包中的Decode方法。

调用yaml.NewDecodingSerializer函数来初始化yamlSerializer,并将jsonSerializer作为参数传递。
而在初始化jsonSerializer时,调用了k8s.io/apimachinery/pkg/runtime/serializer/json包中的NewSerializerWithOptions函数。
该函数的实现如下所示。

// NewSerializerWithOptions creates a JSON/YAML serializer that handles encoding versioned objects into the proper JSON/YAML
// form. If typer is not nil, the object has the group, version, and kind fields set. Options are copied into the Serializer
// and are immutable.
func NewSerializerWithOptions(meta MetaFactory, creater runtime.ObjectCreater, typer runtime.ObjectTyper, options SerializerOptions) *Serializer {
	return &Serializer{
		meta:       meta,
		creater:    creater,
		typer:      typer,
		options:    options,
		identifier: identifier(options),
	}
}

只需要一种选项:
如函数文档所述,通过在第三个typer参数中传递非nil值,创建的对象将具有Group-Version-Kind字段。
在这里,我们指定了要反序列化的资源的scheme。

在deserialize.go中,我们使用了k8s.io/client-go/kubernetes/scheme包中的Scheme变量,并传递了具有corev1.Pod类型的scheme。

方案变量具有k8s.io/apimachinery/pkg/runtime/scheme包中的Scheme类型,而此类型满足NewSerializerWithOptions函数的typer参数应具备的runtime.ObjectTyper接口。

这段是关于将YAML格式的Kubernetes清单转换为corev1.Pod对象的部分的说明。

从Go对象创建Kubernetes对象。

在deserialize.go文件中,从创建客户端以后的处理中,我们使用client-go库从配置文件中创建的对象来创建Kubernetes的Pod对象。
并且我们还根据从配置文件中创建的对象创建了其他对象,并通过修改部分字段的值来创建与原始配置文件不同的Kubernetes的Pod对象。

请参考以下有关client-go的内容,该节涉及client-go、api和apimachinery的功能和关系。

请问您需要将”实行结果”翻译成中文吗?

在deserialize.go的执行结果中,我们可以看到预期创建了Kubernetes Pod对象。

go run deserialize.go --kubeconfig $HOME/.kube/config

k get po                                                                                                                                                                                                                       
NAME              READY   STATUS    RESTARTS   AGE
sample-original   1/1     Running   0          47m
sample-updated    1/1     Running   0          47m

总结

本文介绍了如何使用yaml包提供的功能,通过以下步骤将YAML格式的Kubernetes清单加载并反序列化为具有相应类型的Go语言对象。

翻译结果:
通过使用k8s.io/apimachinery模块提供的yaml包的功能,我们可以实现以下步骤来加载并反序列化YAML格式的Kubernetes清单为具备相应类型的Go语言对象。

    1. 准备具有反序列化类型信息的方案。

 

    1. 使用准备好的方案创建jsonSerializer。

 

    1. 从创建好的jsonSerializer创建yamlSerializer。

 

    在yamlSerializer的Decode方法中,指定YAML清单的字节序列和反序列化目标对象的指针进行执行。

由于输入是字节序列,因此在反序列化请求的主体时,不仅限于清单文件,可能会出现许多情况。

请提供更多的上下文以便我能够正确地为您提供答案。

    Kubernetes Programming with Go
广告
将在 10 秒后关闭
bannerAds