Search code examples
configmapkubernetes-secretskubernetes-statefulsetkubernetes-deploymentkubernetes-go-client

Setting ConfigMapRef and SecretRef for Deployment in Golang K8s client


I have got messed with this bug for hours and still dont know why!

I created a simple Configmap and a Secret called config1 and secret1 respectively. (Yaml files for these are within this repo: https://github.com/hoangphanthai/test)

After that I created a Go file (test.go above) to create a Statefulset and a Deployment. I want all pods (created by Statefulset and Deployment) refer to these Configmap and Secret in their Env variables. The Metadata and Spec of both Statefulset and Deployment are identical except for their names.

However, only Statefulset is created successfully but the Deployment. The error is "Deployment.apps "d1" is invalid: spec.template.spec.containers[0].envFrom: Invalid value: "": may not have more than one field specified at a time"

The second run, both Statefulset and Deployment are not successed, it show the "Failed to continue - runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation] Unable to propogate EXC_BAD_ACCESS signal to target process and panic (see https://github.com/go-delve/delve/issues/852) Last known immediate stacktrace (goroutine id 1):""

The important piece of code is as (the full code is within the test.go file in the Repo) :

deployment := &appsv1.Deployment{
    ObjectMeta: metav1.ObjectMeta{
        Name: "d1",
    },

    Spec: appsv1.DeploymentSpec{
        Replicas: &repNo,
        Selector: &metav1.LabelSelector{
            MatchLabels: map[string]string{
                "app": "postgres",
            },
        },
        Template: apiv1.PodTemplateSpec{
            ObjectMeta: metav1.ObjectMeta{
                Labels: map[string]string{
                    "app": "postgres",
                },
            },
            Spec: apiv1.PodSpec{
                Containers: containerList,
            },
        },
    },
}

statefulset := &appsv1.StatefulSet{
    ObjectMeta: metav1.ObjectMeta{
        Name: "s1",
    },

    Spec: appsv1.StatefulSetSpec{
        Replicas: &repNo,
        Selector: &metav1.LabelSelector{
            MatchLabels: map[string]string{
                "app": "postgres",
            },
        },
        Template: apiv1.PodTemplateSpec{
            ObjectMeta: metav1.ObjectMeta{
                Labels: map[string]string{
                    "app": "postgres",
                },
            },
            Spec: apiv1.PodSpec{
                Containers: containerList,
            },
        },
    },
}

At first I think it is not possible to set the ConfigMapRef and SecretRef at the same time but then I tried to apply a deployment via yaml (dep.yaml above) which is exactly the same as in the code but it worked.

I also googled it but dont know how to solve it.

I would be very thankful if someone tell me how to fix this.

Thank you for your reading.


Solution

  • Based on this error:

    Deployment.apps "d1" is invalid: spec.template.spec.containers[0].envFrom: Invalid value: "": may not have more than one field specified at a time"

    I suggests that you should try the following in you code. Notice that only one field is specified for EnvFromSource type, and it's either ConfigMapRef or SecretRef but never both:

            EnvFrom: []apiv1.EnvFromSource{
                apiv1.EnvFromSource {
                    ConfigMapRef: &apiv1.ConfigMapEnvSource{
                        LocalObjectReference: apiv1.LocalObjectReference{
                            Name: configMapName,
                        },
                    },
                },
                apiv1.EnvFromSource {
                    SecretRef: &apiv1.SecretEnvSource{
                        LocalObjectReference: apiv1.LocalObjectReference{
                            Name: secretName,
                        },
                    },
                },
            }