'cpu / memory amount not populated in core.v1.Pod.PodSpec

Using the following code:

func GetPods(clientset *kubernetes.Clientset, name, namespace string) ([]corev1.Pod, error) {
    list, err := clientset.CoreV1().Pods(namespace).List(metav1.ListOptions{
        LabelSelector: fmt.Sprintf("app=%s", name),
    })
    if err != nil {
        return nil, err
    }
return list.Items, nil
}

And then dump the results into yaml using gopkg.in/yaml.v2, and here's the yaml clause that describes container resource:

resources:
  limits:
    cpu:
      format: DecimalSI
    memory:
      format: BinarySI
  requests:
    cpu:
      format: DecimalSI
    memory:
      format: BinarySI

Which includes none of the actual resource amount that I'm actually interested in, which should look like this using kubectl get pod xxx -o yaml:

resources:
  limits:
    cpu: "4"
    memory: 8Gi
  requests:
    cpu: 200m
    memory: 100Mi

So how can I properly get the pod spec yaml, that includes all the resource info, using the golang library? What did I do wrong in the above process?

Update

I noticed the Pod.String and Pod.Marshal methods.

The pod.String() output seems to be a formatted string of the core.v1.Pod instance, this isn't much use to me since it's not serialized.

Pod.Marshal() gives a byte array, contains lots of gibberish when printed. The method itself is one of those undocumented methods inside k8s.io/api/core/v1/generated.pb.go, I really don't know what to do with its output:

func (p *PodResolver) SpecYaml() (string, error) {
    bs, err := p.pod.Marshal()
    fmt.Println(string(bs))
    return string(bs), err
}
// prints a whole lot of gibberish like cpu\x12\x03\n\x014\n\x0f\n\x06memory\x12\x05\n\x038Gi\x12\r\n\x03cpu\x12\x06\n\x04200m\x12\x11\n\x06memory\x12\a\n\x05100MiJ-\n\n


Solution 1:[1]

You can simply call the String() method on the quantity fields which would return something like "100m"

There doesnt seem to be any yaml tags on the Quantity type.

Solution 2:[2]

Try this out:

func GetPods(clientset *kubernetes.Clientset, name, namespace string) ([]corev1.Pod, error) {
list, err := clientset.CoreV1().Pods(namespace).List(metav1.ListOptions{
    LabelSelector: fmt.Sprintf("app=%s", name),
})
if err != nil {
    return nil, err
}
for _, l := range list.Items {
    fmt.Println("Request CPU ==> ", l.Spec.Containers[0].Resources.Requests.Cpu(), " Request Memory ==> ", l.Spec.Containers[0].Resources.Requests.Memory())
    fmt.Println("Limit CPU ==> ", l.Spec.Containers[0].Resources.Limits.Cpu(), " Limit Memory ==> ", l.Spec.Containers[0].Resources.Limits.Memory()) } return list.Items, nil }

Keep in mind that every time something becomes complex it's time to choose another path.

k8s APIs are not so well documented as could be, in this case my suggestion is open up the debug console and navigate through component trees which will certainly indicate which interface use and it's structure.

Solution 3:[3]

So instead of using yaml.Marshal, I should use json.Marshal, that'd give me all the information including cpu and memory quantity.

As mentioned by @user2326871, Quantity struct is missing yaml tags.

What a weird library, and all its weird methods, I was so sure that kubectl must be using the same Pod struct to generate all its yaml outputs.

Solution 4:[4]

You can use "k8s.io/apimachinery/pkg/runtime/serializer/json" to marshal deployment(or pod) object to the YAML(manifest) string.

try like this.

import k8sJson "k8s.io/apimachinery/pkg/runtime/serializer/json"

e := k8sJson.NewYAMLSerializer(k8sJson.DefaultMetaFactory, nil, nil)
yamlDeployment := new(bytes.Buffer)
err = e.Encode(deployment, yamlDeployment)

fmt.Println(yamlDeployment.String())

Solution 5:[5]

A bit late but for the next one.
You should switch from package gopkg.in/yaml.v3 to this one sigs.k8s.io/yaml
and still use the yaml.Marshal(your_kubernetes_struct)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 user2326871
Solution 2
Solution 3 timfeirg
Solution 4
Solution 5 Quentin