go – cpu / memory amount not populated in core.v1.Pod.PodSpec-ThrowExceptions

Exception or error:

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
How to solve:

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.

Answer:

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.

Answer:

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.

Leave a Reply

Your email address will not be published. Required fields are marked *