Kubectl and client-go Part 1
- Kubectl and client-go Part 1 Clientset and Nodes
- Kubectl and client-go Part 2 Pods
- Kubectl and client-go Part 3 Secrets and Apply File
For the past two weeks, I’ve been learning the APIs of client-go. client-go is the official client library of Kubernetes, which is used internally by Kubernetes as well. The Kubernetes command line tool kubectl is built on client-go.
For a Kubernetes starter like me, it’s not an easy job. One reason is because there are very few discussions about client-go online. So for any problems you met, there is no such easy way of Googling out an answer. The only way you can do is digging out an answer from the source codes by yourself.
I’m happy with my progress so far. I’m to the point that I’m able to write any commonly used kubectl commands with client-go.
Resources
How to access a remote Kubernetes cluster
A Kubernetes clientset is an API group of all sorts of Kubernets cluster controls. Every Kubernetes client-go app starts with a clientset.
To generate a clientset, The easiest way is copying the “/etc/kubernetes/admin.conf” file from the remote Kubernetes master node to your local Go project folder, say next to your main.go code, at “./admin.conf”. This config file contains the credentials to deal with the cluster.
import (
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
)
func NewK8sClient(masterUrl, kubeconfigPath string) (kubernetes.Interface, error) {
// use the current context in kubeconfig
config, err := clientcmd.BuildConfigFromFlags(masterUrl, kubeconfigPath)
if err != nil {
return nil, err
}
// create the clientset
return kubernetes.NewForConfig(config)
}
func main() {
NewK8sClient("https://10.109.195.70:6443", "./admin.conf")
}
You can find the masterUrl from the admin.conf file. It’s the server address of the cluster. As long as you can access the IP address of the master node, you are able to control your Kubernetes cluster from remote.
Nodes
Read more on Kubernets Nodes. In client-go, NodeInterface includes all the APIs to deal with Nodes.
- List
kubectl
kubectl get nodes
client-go
import (
"context"
"k8s.io/client-go/kubernetes"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func ListNodes(clientset kubernetes.Interface) ([]v1.Node, error) {
nodes, err := clientset.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{})
if err != nil {
return nil, err
}
return nodes.Items, nil
}
As we know, kubectl get nodes displays 5 columns:
| NAME | STATUS | ROLES | AGE | VERSION | |--------------------|--------|--------|-----|---------| | k8s-worker-node1 | Ready | <none> | 13d | v1.18.2 | | k8s-master-node1 | Ready | master | 13d | v1.18.2 |
A big effort I spent on is to figure out which column maps to which property of Node.
1. Name
Name is the Metadata of Node.
2. Status
To see if a Node is Ready:
import (
"k8s.io/api/core/v1"
)
func IsReady(node *v1.Node) bool {
var cond v1.NodeCondition
for _, c := range node.Status.Conditions {
if c.Type == v1.NodeReady {
cond = c
break
}
}
return cond.Status == v1.ConditionTrue
}
3. Roles
To check if a Node is a master node, search if the label “node-role.kubernetes.io/master” is present.
func IsMaster(node *v1.Node) bool {
if _, ok := node.Labels["node-role.kubernetes.io/master"]; ok {
return true
}
return false
}
4. Age
Calculate the age of a Node from the CreationTimestamp.
func Age(node *v1.Node) uint {
diff := uint(time.Now().Sub(node.CreationTimestamp.Time).Hours())
return uint(diff / 24)
}
5. Version
Get the Kubernetes version from the Node status.
func KubeletVersion(node *v1.Node) string {
return node.Status.NodeInfo.KubeletVersion
}
- Get
NOTE: To get the details of a Node, instead of using “kubectl describe”, a better command is “kubectl get -o yaml/json”. The output will be in the same structure as the client-go struct.
kubectl
kubectl get node <node_name> -o yaml
client-go
func GetNode(clientset kubernetes.Interface, name string) (*v1.Node, error) {
return clientset.CoreV1().Nodes().Get(context.TODO(), name, metav1.GetOptions{})
}