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?
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
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.
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.
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.