问题背景
大概是因为 k8s 定义了一些特殊的数据类型,所以 k8s 对象 yaml 序列化时与其它 yaml 包结果不同。
源代码
package mainimport ("log""os""github.com/ghodss/yaml"yamlv2 "gopkg.in/yaml.v2"yamlv3 "k8s.io/apimachinery/pkg/util/yaml"corev1 "k8s.io/api/core/v1"v1 "k8s.io/apimachinery/pkg/apis/meta/v1""k8s.io/apimachinery/pkg/util/intstr"
)func main() {// 输出重定向到文件f, err := os.OpenFile("test.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)if err != nil {panic(err)}defer f.Close()log.SetOutput(f)var service *corev1.Serviceservice = &corev1.Service{ObjectMeta: v1.ObjectMeta{Name: "test-service",Namespace: "default",Labels: map[string]string{"app": "test-app",},},Spec: corev1.ServiceSpec{Selector: map[string]string{"app": "test-app",},Ports: []corev1.ServicePort{{Name: "http",Port: 80,TargetPort: intstr.IntOrString{Type: intstr.Int,IntVal: 8080,},},},},}{bytes, err := yaml.Marshal(service)if err != nil {panic(err)}log.Printf("yaml:\n%s\n\n", string(bytes))var service2 *corev1.Serviceerr = yaml.Unmarshal(bytes, &service2)if err != nil {panic(err)}log.Printf("service2: %+v\n\n", service2)log.Println()}{bytes, err := yamlv2.Marshal(service)if err != nil {panic(err)}log.Printf("yamlv2:\n%s\n\n", string(bytes))var service2 *corev1.Serviceerr = yamlv2.Unmarshal(bytes, &service2)if err != nil {panic(err)}log.Printf("service2: %+v\n\n", service2)log.Println()}{bytes3, err := yaml.Marshal(service)if err != nil {panic(err)}log.Printf("yaml:\n%s", string(bytes3))var service2 *corev1.Serviceerr = yamlv3.Unmarshal(bytes3, &service2)if err != nil {panic(err)}log.Printf("service2: %+v\n\n", service2)log.Println()}
}
module tmpGogo 1.20require (github.com/ghodss/yaml v1.0.0gopkg.in/yaml.v2 v2.4.0k8s.io/api v0.29.1k8s.io/apimachinery v0.29.1
)require (github.com/go-logr/logr v1.3.0 // indirectgithub.com/gogo/protobuf v1.3.2 // indirectgithub.com/google/gofuzz v1.2.0 // indirectgithub.com/json-iterator/go v1.1.12 // indirectgithub.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirectgithub.com/modern-go/reflect2 v1.0.2 // indirectgolang.org/x/net v0.19.0 // indirectgolang.org/x/text v0.14.0 // indirectgopkg.in/inf.v0 v0.9.1 // indirectk8s.io/klog/v2 v2.110.1 // indirectk8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirectsigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirectsigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirectsigs.k8s.io/yaml v1.3.0 // indirect
)
输出结果:
2024/01/31 17:10:20 yaml:
metadata:creationTimestamp: nulllabels:app: test-appname: test-servicenamespace: default
spec:ports:- name: httpport: 80targetPort: 8080selector:app: test-app
status:loadBalancer: {}2024/01/31 17:10:20 service2: &Service{ObjectMeta:{test-service default 0 0001-01-01 00:00:00 +0000 UTC <nil> <nil> map[app:test-app] map[] [] [] []},Spec:ServiceSpec{Ports:[]ServicePort{ServicePort{Name:http,Protocol:,Port:80,TargetPort:{0 8080 },NodePort:0,AppProtocol:nil,},},Selector:map[string]string{app: test-app,},ClusterIP:,Type:,ExternalIPs:[],SessionAffinity:,LoadBalancerIP:,LoadBalancerSourceRanges:[],ExternalName:,ExternalTrafficPolicy:,HealthCheckNodePort:0,PublishNotReadyAddresses:false,SessionAffinityConfig:nil,IPFamilyPolicy:nil,ClusterIPs:[],IPFamilies:[],AllocateLoadBalancerNodePorts:nil,LoadBalancerClass:nil,InternalTrafficPolicy:nil,},Status:ServiceStatus{LoadBalancer:LoadBalancerStatus{Ingress:[]LoadBalancerIngress{},},Conditions:[]Condition{},},}2024/01/31 17:10:20
2024/01/31 17:10:20 yamlv2:
typemeta:kind: ""apiversion: ""
objectmeta:name: test-servicegeneratename: ""namespace: defaultselflink: ""uid: ""resourceversion: ""generation: 0creationtimestamp: "0001-01-01T00:00:00Z"deletiontimestamp: nulldeletiongraceperiodseconds: nulllabels:app: test-appannotations: {}ownerreferences: []finalizers: []managedfields: []
spec:ports:- name: httpprotocol: ""appprotocol: nullport: 80targetport:type: 0intval: 8080strval: ""nodeport: 0selector:app: test-appclusterip: ""clusterips: []type: ""externalips: []sessionaffinity: ""loadbalancerip: ""loadbalancersourceranges: []externalname: ""externaltrafficpolicy: ""healthchecknodeport: 0publishnotreadyaddresses: falsesessionaffinityconfig: nullipfamilies: []ipfamilypolicy: nullallocateloadbalancernodeports: nullloadbalancerclass: nullinternaltrafficpolicy: null
status:loadbalancer:ingress: []conditions: []2024/01/31 17:10:20 service2: &Service{ObjectMeta:{test-service default 0 0001-01-01 00:00:00 +0000 UTC <nil> <nil> map[app:test-app] map[] [] [] []},Spec:ServiceSpec{Ports:[]ServicePort{ServicePort{Name:http,Protocol:,Port:80,TargetPort:{0 8080 },NodePort:0,AppProtocol:nil,},},Selector:map[string]string{app: test-app,},ClusterIP:,Type:,ExternalIPs:[],SessionAffinity:,LoadBalancerIP:,LoadBalancerSourceRanges:[],ExternalName:,ExternalTrafficPolicy:,HealthCheckNodePort:0,PublishNotReadyAddresses:false,SessionAffinityConfig:nil,IPFamilyPolicy:nil,ClusterIPs:[],IPFamilies:[],AllocateLoadBalancerNodePorts:nil,LoadBalancerClass:nil,InternalTrafficPolicy:nil,},Status:ServiceStatus{LoadBalancer:LoadBalancerStatus{Ingress:[]LoadBalancerIngress{},},Conditions:[]Condition{},},}2024/01/31 17:10:20
2024/01/31 17:10:20 yaml:
metadata:creationTimestamp: nulllabels:app: test-appname: test-servicenamespace: default
spec:ports:- name: httpport: 80targetPort: 8080selector:app: test-app
status:loadBalancer: {}
2024/01/31 17:10:20 service2: &Service{ObjectMeta:{test-service default 0 0001-01-01 00:00:00 +0000 UTC <nil> <nil> map[app:test-app] map[] [] [] []},Spec:ServiceSpec{Ports:[]ServicePort{ServicePort{Name:http,Protocol:,Port:80,TargetPort:{0 8080 },NodePort:0,AppProtocol:nil,},},Selector:map[string]string{app: test-app,},ClusterIP:,Type:,ExternalIPs:[],SessionAffinity:,LoadBalancerIP:,LoadBalancerSourceRanges:[],ExternalName:,ExternalTrafficPolicy:,HealthCheckNodePort:0,PublishNotReadyAddresses:false,SessionAffinityConfig:nil,IPFamilyPolicy:nil,ClusterIPs:[],IPFamilies:[],AllocateLoadBalancerNodePorts:nil,LoadBalancerClass:nil,InternalTrafficPolicy:nil,},Status:ServiceStatus{LoadBalancer:LoadBalancerStatus{Ingress:[]LoadBalancerIngress{},},Conditions:[]Condition{},},}2024/01/31 17:10:20