admin管理员组

文章数量:1395752

When I attempt to use the client-go client to apply a Deployment, I encounter the error "invalid object type: /, Kind=". Interestingly, if I use the create method instead, the Deployment is created successfully without any issues, and the code compiles perfectly fine. This discrepancy suggests that there might be a problem with how the Apply method is being used or how the object is being configured for Apply.

I’ve thoroughly reviewed the official Kubernetes and client-go documentation but haven’t found any specific guidance or examples that address this particular issue. It’s unclear why the Apply method fails while create works as expected. I suspect it might be related to how the ApplyConfiguration object is structured or how the FieldManager is being set, but I’m unable to pinpoint the exact cause.

If anyone has encountered a similar issue or has insights into why this might be happening, I would greatly appreciate your help. Any suggestions or solutions would be incredibly valuable. Thank you so much in advance for your assistance!

main.go

package main

import (
    "context"
    "flag"
    "fmt"
    "log"
    "path/filepath"
    "time"

    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    applyappsv1 "k8s.io/client-go/applyconfigurations/apps/v1"
    applycorev1 "k8s.io/client-go/applyconfigurations/core/v1"
    applymetav1 "k8s.io/client-go/applyconfigurations/meta/v1"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/tools/clientcmd"
    "k8s.io/client-go/util/homedir"
    "k8s.io/utils/pointer"
)

func main() {
    var kubeconfig *string
    if home := homedir.HomeDir(); home != "" {
        kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
    } else {
        kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
    }
    flag.Parse()

    config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
    if err != nil {
        panic(err.Error())
    }

    clientset, err := kubernetes.NewForConfig(config)
    if err != nil {
        panic(err.Error())
    }

    deploymentName := "test-deployment"
    namespace := "default"

    deploymentApplyConfig := applyappsv1.DeploymentApplyConfiguration{
        ObjectMetaApplyConfiguration: &applymetav1.ObjectMetaApplyConfiguration{
            Name:      &deploymentName,
            Namespace: &namespace,
        },
        Spec: &applyappsv1.DeploymentSpecApplyConfiguration{
            Replicas: pointer.Int32(3),
            Selector: &applymetav1.LabelSelectorApplyConfiguration{
                MatchLabels: map[string]string{
                    "app": "test-app",
                },
            },
            Template: &applycorev1.PodTemplateSpecApplyConfiguration{
                ObjectMetaApplyConfiguration: &applymetav1.ObjectMetaApplyConfiguration{
                    Labels: map[string]string{
                        "app": "test-app",
                    },
                },
                Spec: &applycorev1.PodSpecApplyConfiguration{
                    Containers: []applycorev1.ContainerApplyConfiguration{
                        {
                            Name:  pointer.String("nginx"),
                            Image: pointer.String("nginx:1.14.2"),
                            Ports: []applycorev1.ContainerPortApplyConfiguration{
                                {
                                    ContainerPort: pointer.Int32(80),
                                },
                            },
                        },
                    },
                },
            },
        },
    }

    fmt.Println("Applying Deployment...")
    appliedDeployment, err := clientset.AppsV1().Deployments(namespace).Apply(
        context.TODO(),
        &deploymentApplyConfig,
        metav1.ApplyOptions{FieldManager: "test-client"},
    )
    if err != nil {
        log.Fatalf("Error applying Deployment: %s", err)
    }
    fmt.Printf("Applied Deployment %q\n", appliedDeployment.Name)
}

Output:

Applying Deployment...
2025/03/15 12:48:06 Error applying Deployment: invalid object type: /, Kind=
exit status 1

Versions:

go version: 1.23.0
client-go version: 0.32.0
k8s-version: 1.32.0

When I attempt to use the client-go client to apply a Deployment, I encounter the error "invalid object type: /, Kind=". Interestingly, if I use the create method instead, the Deployment is created successfully without any issues, and the code compiles perfectly fine. This discrepancy suggests that there might be a problem with how the Apply method is being used or how the object is being configured for Apply.

I’ve thoroughly reviewed the official Kubernetes and client-go documentation but haven’t found any specific guidance or examples that address this particular issue. It’s unclear why the Apply method fails while create works as expected. I suspect it might be related to how the ApplyConfiguration object is structured or how the FieldManager is being set, but I’m unable to pinpoint the exact cause.

If anyone has encountered a similar issue or has insights into why this might be happening, I would greatly appreciate your help. Any suggestions or solutions would be incredibly valuable. Thank you so much in advance for your assistance!

main.go

package main

import (
    "context"
    "flag"
    "fmt"
    "log"
    "path/filepath"
    "time"

    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    applyappsv1 "k8s.io/client-go/applyconfigurations/apps/v1"
    applycorev1 "k8s.io/client-go/applyconfigurations/core/v1"
    applymetav1 "k8s.io/client-go/applyconfigurations/meta/v1"
    "k8s.io/client-go/kubernetes"
    "k8s.io/client-go/tools/clientcmd"
    "k8s.io/client-go/util/homedir"
    "k8s.io/utils/pointer"
)

func main() {
    var kubeconfig *string
    if home := homedir.HomeDir(); home != "" {
        kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")
    } else {
        kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")
    }
    flag.Parse()

    config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
    if err != nil {
        panic(err.Error())
    }

    clientset, err := kubernetes.NewForConfig(config)
    if err != nil {
        panic(err.Error())
    }

    deploymentName := "test-deployment"
    namespace := "default"

    deploymentApplyConfig := applyappsv1.DeploymentApplyConfiguration{
        ObjectMetaApplyConfiguration: &applymetav1.ObjectMetaApplyConfiguration{
            Name:      &deploymentName,
            Namespace: &namespace,
        },
        Spec: &applyappsv1.DeploymentSpecApplyConfiguration{
            Replicas: pointer.Int32(3),
            Selector: &applymetav1.LabelSelectorApplyConfiguration{
                MatchLabels: map[string]string{
                    "app": "test-app",
                },
            },
            Template: &applycorev1.PodTemplateSpecApplyConfiguration{
                ObjectMetaApplyConfiguration: &applymetav1.ObjectMetaApplyConfiguration{
                    Labels: map[string]string{
                        "app": "test-app",
                    },
                },
                Spec: &applycorev1.PodSpecApplyConfiguration{
                    Containers: []applycorev1.ContainerApplyConfiguration{
                        {
                            Name:  pointer.String("nginx"),
                            Image: pointer.String("nginx:1.14.2"),
                            Ports: []applycorev1.ContainerPortApplyConfiguration{
                                {
                                    ContainerPort: pointer.Int32(80),
                                },
                            },
                        },
                    },
                },
            },
        },
    }

    fmt.Println("Applying Deployment...")
    appliedDeployment, err := clientset.AppsV1().Deployments(namespace).Apply(
        context.TODO(),
        &deploymentApplyConfig,
        metav1.ApplyOptions{FieldManager: "test-client"},
    )
    if err != nil {
        log.Fatalf("Error applying Deployment: %s", err)
    }
    fmt.Printf("Applied Deployment %q\n", appliedDeployment.Name)
}

Output:

Applying Deployment...
2025/03/15 12:48:06 Error applying Deployment: invalid object type: /, Kind=
exit status 1

Versions:

go version: 1.23.0
client-go version: 0.32.0
k8s-version: 1.32.0
Share Improve this question asked Mar 15 at 5:11 groobygrooby 234 bronze badges 3
  • If you were to use the Deployment function, it sets the kind and apiVersion (see Deployment). Your code does not do this. – DazWilkin Commented Mar 15 at 18:38
  • Deployment returns an DeploymentApplyConfigurationl which also includes a bunch of methods (e.g. WithSpec) that will ensure that you're mutating the structs with the correct fields being set. Perhaps use that approach? – DazWilkin Commented Mar 15 at 18:40
  • Thanks, DazWilkin. I'm new to client-go programming. Could you please show me how to fix this issue, like how to ​set the kind and apiVersion? I can't ​find where to set them. – grooby Commented Mar 21 at 5:55
Add a comment  | 

1 Answer 1

Reset to default 1

The simplest way to correct your code is to add TypeMetaApplyConfiguration to your struct:

deploymentApplyConfig := applyappsv1.DeploymentApplyConfiguration{
    TypeMetaApplyConfiguration: applymetav1.TypeMetaApplyConfiguration{
        Kind:       pointer.String("Deployment"),
        APIVersion: pointer.String("apps/v1"),
    },
    ObjectMetaApplyConfiguration: &applymetav1.ObjectMetaApplyConfiguration{
        Name:      &deploymentName,
        Namespace: &namespace,
    },
    ...

But, per my comment, there are methods to help with the construction and it may be preferable to use these:

deploymentName := "test-deployment"
namespace := "default"

labels := map[string]string{
    "app": "test-app",
}

containerName := "nginx"
image := "docker.io/nginx:1.14.2"
port := int32(8080)

deploymentApplyConfig := applyappsv1.Deployment(
    deploymentName,
    namespace,
).WithSpec(
    applyappsv1.DeploymentSpec().WithReplicas(3).WithSelector(
        applymetav1.LabelSelector().WithMatchLabels(labels),
    ).WithTemplate(
        applycorev1.PodTemplateSpec().WithLabels(labels).WithSpec(
            applycorev1.PodSpec().WithContainers(
                applycorev1.Container().WithName(containerName).WithImage(image).WithPorts(applycorev1.ContainerPort().WithContainerPort(port)),
            ),
        ),
    ),
)

本文标签: kubernetesWhy does ClientSet in clientgo fail to deploy a DeploymentStack Overflow