文章目录
- 四种Kubernetes APIServer 交互的客户端
- RESTClient
- clientSet
- dynamicClient
- DiscoveryClient
- 创建、更新、查询、删除Deployment
- 参考资料
四种Kubernetes APIServer 交互的客户端
Client-Go 共提供了 4 种与 Kubernetes APIServer 交互的客户端。分别是 RESTClient、DiscoveryClient、ClientSet、DynamicClient。
- RESTClient:最基础的客户端,主要是对 HTTP 请求进行了封装,支持 Json 和 Protobuf 格式的数据。
- DiscoveryClient:发现客户端,负责发现 APIServer 支持的资源组、资源版本和资源信息的。
- ClientSet:负责操作 Kubernetes 内置的资源对象,例如:Pod、Service等。
- DynamicClient:动态客户端,可以对任意的 Kubernetes 资源对象进行通用操作,包括 CRD。
RESTClient
package mainimport ("context""flag""fmt""path/filepath"_ "time"corev1 "k8s.io/api/core/v1""k8s.io/client-go/kubernetes/scheme""k8s.io/client-go/rest"_ "k8s.io/apimachinery/pkg/api/errors"_ "k8s.io/client-go/kubernetes""k8s.io/client-go/tools/clientcmd""k8s.io/client-go/util/homedir"
)func main() {var kubeconfig *stringif home := homedir.HomeDir(); home != "" {kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")} else {kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")}// 把用户传递的命令行参数解析为对应变量的值flag.Parse()// use the current context in kubeconfig 在kubeconfig中使用当前上下文config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)if err != nil {panic(err.Error())}// 使用 RESTClient 需要开发者自行设置资源 URL// pod 资源没有 group,在核心组,所以前缀是 apiconfig.APIPath = "api"// 设置 corev1 groupVersionconfig.GroupVersion = &corev1.SchemeGroupVersion// 设置解析器,用于用于解析 schemeconfig.NegotiatedSerializer = scheme.Codecs.WithoutConversion()// 初始化 RESTClientrestClient, err := rest.RESTClientFor(config)if err != nil {panic(err.Error())}// 调用结果用 podList 解析result := &corev1.PodList{}// 获取 kube-system 命名空间的 podnamespace := "kube-system"// 链式调用 RESTClient 方法获取,并将结果解析到 corev1.PodList{}err = restClient.Get().Namespace(namespace).Resource("pods").Do(context.TODO()).Into(result)if err != nil {panic(err.Error())}// 打印结果for _, pod := range result.Items {fmt.Printf("namespace: %s, pod: %s \n", pod.Namespace, pod.Name)//fmt.Printf(" Kind: %s, APIVersion: %s \n", pod.Kind, pod.APIVersion)}}
执行go build -o app .
输出
namespace: kube-system, pod: coredns-6554b8b87f-f8dq6
namespace: kube-system, pod: coredns-6554b8b87f-qr4wn
namespace: kube-system, pod: etcd-minikube
namespace: kube-system, pod: kube-apiserver-minikube
namespace: kube-system, pod: kube-controller-manager-minikube
namespace: kube-system, pod: kube-proxy-tppnz
namespace: kube-system, pod: kube-scheduler-minikube
namespace: kube-system, pod: storage-provisioner
clientSet
package mainimport ("context""flag""fmt""path/filepath"metav1 "k8s.io/apimachinery/pkg/apis/meta/v1""k8s.io/client-go/kubernetes""k8s.io/client-go/tools/clientcmd""k8s.io/client-go/util/homedir"
)func main() {var kubeconfig *stringif home := homedir.HomeDir(); home != "" {kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")} else {kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")}// 把用户传递的命令行参数解析为对应变量的值flag.Parse()// use the current context in kubeconfig 在kubeconfig中使用当前上下文config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)if err != nil {panic(err.Error())}// 获取 clientSetclientSet, err := kubernetes.NewForConfig(config)if err != nil {panic(err.Error())}namespace := "kube-system"// 链式调用 ClientSet 获取 pod 列表podList, err := clientSet.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{})if err != nil {panic(err.Error())}for _, pod := range podList.Items {fmt.Printf("namespace: %s, pod: %s \n", pod.Namespace, pod.Name)}
}
dynamicClient
package mainimport ("context""flag""fmt""path/filepath"corev1 "k8s.io/api/core/v1"metav1 "k8s.io/apimachinery/pkg/apis/meta/v1""k8s.io/apimachinery/pkg/runtime""k8s.io/apimachinery/pkg/runtime/schema""k8s.io/client-go/dynamic""k8s.io/client-go/tools/clientcmd""k8s.io/client-go/util/homedir"
)func main() {var kubeconfig *stringif home := homedir.HomeDir(); home != "" {kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")} else {kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")}// 把用户传递的命令行参数解析为对应变量的值flag.Parse()// use the current context in kubeconfig 在kubeconfig中使用当前上下文config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)if err != nil {panic(err.Error())}// 初始化 DynamicClientdynamicClient, err := dynamic.NewForConfig(config)if err != nil {panic(err.Error())}// 提供 pod 的 gvr,因为是动态调用,dynamicClient 不知道需要操作哪个资源,所以需要自己提供gvr := schema.GroupVersionResource{Group: "",Version: "v1",Resource: "pods",}//链式调用 dynamicClient 获取数据result, err := dynamicClient.Resource(gvr).Namespace("kube-system").List(context.TODO(), metav1.ListOptions{})if err != nil {panic(err.Error())}podList := &corev1.PodList{}// 将结果解析到 podList scheme 中err = runtime.DefaultUnstructuredConverter.FromUnstructured(result.UnstructuredContent(), podList)for _, pod := range podList.Items {fmt.Printf("namespace: %s, pod: %s \n", pod.Namespace, pod.Name)fmt.Printf(" Kind: %s, APIVersion: %s \n", pod.Kind, pod.APIVersion)}
}
DiscoveryClient
package mainimport ("flag""fmt""path/filepath""k8s.io/apimachinery/pkg/runtime/schema""k8s.io/client-go/discovery""k8s.io/client-go/tools/clientcmd""k8s.io/client-go/util/homedir"
)func main() {var kubeconfig *stringif home := homedir.HomeDir(); home != "" {kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")} else {kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")}// 把用户传递的命令行参数解析为对应变量的值flag.Parse()// use the current context in kubeconfig 在kubeconfig中使用当前上下文config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)if err != nil {panic(err.Error())}// 初始化 DiscoveryClientdiscoveryClient, err := discovery.NewDiscoveryClientForConfig(config)if err != nil {panic(err.Error())}// 获取集群所有资源_, apiResourceList, err := discoveryClient.ServerGroupsAndResources()if err != nil {panic(err.Error())}for _, resources := range apiResourceList {gv, err := schema.ParseGroupVersion(resources.GroupVersion)if err != nil {panic(err.Error())}for _, resource := range resources.APIResources {fmt.Printf("group: %s, version: %s, resource: %s \n", gv.Group, gv.Version, resource.Name)}}
}
输出
group: authentication.k8s.io, version: v1, resource: selfsubjectreviews
group: authentication.k8s.io, version: v1, resource: tokenreviews
group: authorization.k8s.io, version: v1, resource: localsubjectaccessreviews
group: authorization.k8s.io, version: v1, resource: selfsubjectaccessreviews
group: authorization.k8s.io, version: v1, resource: selfsubjectrulesreviews
group: authorization.k8s.io, version: v1, resource: subjectaccessreviews
group: storage.k8s.io, version: v1, resource: csidrivers
group: storage.k8s.io, version: v1, resource: csinodes
group: storage.k8s.io, version: v1, resource: csistoragecapacities
group: storage.k8s.io, version: v1, resource: storageclasses
group: storage.k8s.io, version: v1, resource: volumeattachments
group: storage.k8s.io, version: v1, resource: volumeattachments/status
group: admissionregistration.k8s.io, version: v1, resource: mutatingwebhookconfigurations
group: admissionregistration.k8s.io, version: v1, resource: validatingwebhookconfigurations
group: flowcontrol.apiserver.k8s.io, version: v1beta3, resource: flowschemas
group: flowcontrol.apiserver.k8s.io, version: v1beta3, resource: flowschemas/status
group: flowcontrol.apiserver.k8s.io, version: v1beta3, resource: prioritylevelconfigurations
group: flowcontrol.apiserver.k8s.io, version: v1beta3, resource: prioritylevelconfigurations/status
group: apiregistration.k8s.io, version: v1, resource: apiservices
group: apiregistration.k8s.io, version: v1, resource: apiservices/status
group: apps, version: v1, resource: controllerrevisions
group: apps, version: v1, resource: daemonsets
group: apps, version: v1, resource: daemonsets/status
group: apps, version: v1, resource: deployments
group: apps, version: v1, resource: deployments/scale
group: apps, version: v1, resource: deployments/status
group: apps, version: v1, resource: replicasets
group: apps, version: v1, resource: replicasets/scale
group: apps, version: v1, resource: replicasets/status
group: apps, version: v1, resource: statefulsets
group: apps, version: v1, resource: statefulsets/scale
group: apps, version: v1, resource: statefulsets/status
group: , version: v1, resource: bindings
group: , version: v1, resource: componentstatuses
group: , version: v1, resource: configmaps
group: , version: v1, resource: endpoints
group: , version: v1, resource: events
group: , version: v1, resource: limitranges
group: , version: v1, resource: namespaces
group: , version: v1, resource: namespaces/finalize
group: , version: v1, resource: namespaces/status
group: , version: v1, resource: nodes
group: , version: v1, resource: nodes/proxy
group: , version: v1, resource: nodes/status
group: , version: v1, resource: persistentvolumeclaims
group: , version: v1, resource: persistentvolumeclaims/status
group: , version: v1, resource: persistentvolumes
group: , version: v1, resource: persistentvolumes/status
group: , version: v1, resource: pods
group: , version: v1, resource: pods/attach
group: , version: v1, resource: pods/binding
group: , version: v1, resource: pods/ephemeralcontainers
group: , version: v1, resource: pods/eviction
group: , version: v1, resource: pods/exec
group: , version: v1, resource: pods/log
group: , version: v1, resource: pods/portforward
group: , version: v1, resource: pods/proxy
group: , version: v1, resource: pods/status
group: , version: v1, resource: podtemplates
group: , version: v1, resource: replicationcontrollers
group: , version: v1, resource: replicationcontrollers/scale
group: , version: v1, resource: replicationcontrollers/status
group: , version: v1, resource: resourcequotas
group: , version: v1, resource: resourcequotas/status
group: , version: v1, resource: secrets
group: , version: v1, resource: serviceaccounts
group: , version: v1, resource: serviceaccounts/token
group: , version: v1, resource: services
group: , version: v1, resource: services/proxy
group: , version: v1, resource: services/status
group: networking.k8s.io, version: v1, resource: ingressclasses
group: networking.k8s.io, version: v1, resource: ingresses
group: networking.k8s.io, version: v1, resource: ingresses/status
group: networking.k8s.io, version: v1, resource: networkpolicies
group: certificates.k8s.io, version: v1, resource: certificatesigningrequests
group: certificates.k8s.io, version: v1, resource: certificatesigningrequests/approval
group: certificates.k8s.io, version: v1, resource: certificatesigningrequests/status
group: coordination.k8s.io, version: v1, resource: leases
group: events.k8s.io, version: v1, resource: events
group: batch, version: v1, resource: cronjobs
group: batch, version: v1, resource: cronjobs/status
group: batch, version: v1, resource: jobs
group: batch, version: v1, resource: jobs/status
group: scheduling.k8s.io, version: v1, resource: priorityclasses
group: autoscaling, version: v1, resource: horizontalpodautoscalers
group: autoscaling, version: v1, resource: horizontalpodautoscalers/status
group: flowcontrol.apiserver.k8s.io, version: v1beta2, resource: flowschemas
group: flowcontrol.apiserver.k8s.io, version: v1beta2, resource: flowschemas/status
group: flowcontrol.apiserver.k8s.io, version: v1beta2, resource: prioritylevelconfigurations
group: flowcontrol.apiserver.k8s.io, version: v1beta2, resource: prioritylevelconfigurations/status
group: discovery.k8s.io, version: v1, resource: endpointslices
group: apiextensions.k8s.io, version: v1, resource: customresourcedefinitions
group: apiextensions.k8s.io, version: v1, resource: customresourcedefinitions/status
group: policy, version: v1, resource: poddisruptionbudgets
group: policy, version: v1, resource: poddisruptionbudgets/status
group: autoscaling, version: v2, resource: horizontalpodautoscalers
group: autoscaling, version: v2, resource: horizontalpodautoscalers/status
group: rbac.authorization.k8s.io, version: v1, resource: clusterrolebindings
group: rbac.authorization.k8s.io, version: v1, resource: clusterroles
group: rbac.authorization.k8s.io, version: v1, resource: rolebindings
group: rbac.authorization.k8s.io, version: v1, resource: roles
group: node.k8s.io, version: v1, resource: runtimeclasses
创建、更新、查询、删除Deployment
使用client-go,实现一个deployment的创建、更新和删除操作。代码依据官方的例子修改而来
package mainimport ("bufio""context""flag""fmt"appsv1 "k8s.io/api/apps/v1"corev1 "k8s.io/api/core/v1"v1 "k8s.io/apimachinery/pkg/apis/meta/v1""k8s.io/client-go/kubernetes"appsresv1 "k8s.io/client-go/kubernetes/typed/apps/v1""k8s.io/client-go/tools/clientcmd""k8s.io/client-go/util/homedir""k8s.io/client-go/util/retry""k8s.io/klog/v2""os""path/filepath"
)func main() {// 1、创建配置文件var kubeconfig *stringif home := homedir.HomeDir(); home != "" {kubeconfig = flag.String("kubeconfig", filepath.Join(home, ".kube", "config"), "(optional) absolute path to the kubeconfig file")} else {kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file")}// 把用户传递的命令行参数解析为对应变量的值flag.Parse()// 在kubeconfig中使用当前上下文config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)if err != nil {panic(err.Error())}// 2、创建clientsetclientset, err := kubernetes.NewForConfig(config)if err != nil {panic(err)}deployClient := clientset.AppsV1().Deployments(corev1.NamespaceDefault)// 3、创建deploymentCreateDeploy(deployClient)prompt()// 4、更新deploymentUpdateDeploy(deployClient)prompt()// 5、查询deploymentListDeploy(deployClient)prompt()// 6、删除deploymentDeleteDeploy(deployClient)
}func CreateDeploy(client appsresv1.DeploymentInterface) {klog.Info("CreateDeploy...........")replicas := int32(2)deploy := appsv1.Deployment{TypeMeta: v1.TypeMeta{Kind: "Deployment",APIVersion: "apps/v1",},ObjectMeta: v1.ObjectMeta{Name: "deploy-nginx-demo",Namespace: corev1.NamespaceDefault,},Spec: appsv1.DeploymentSpec{Replicas: &replicas,Selector: &v1.LabelSelector{MatchLabels: map[string]string{"app": "nginx",},},Template: corev1.PodTemplateSpec{ObjectMeta: v1.ObjectMeta{Name: "nginx",Labels: map[string]string{"app": "nginx",},},Spec: corev1.PodSpec{Containers: []corev1.Container{{Name: "web",Image: "nginx:1.12",Ports: []corev1.ContainerPort{{Protocol: corev1.ProtocolTCP,ContainerPort: 80,},},},},},},},}dep, err := client.Create(context.Background(), &deploy, v1.CreateOptions{})if err != nil {klog.Errorf("create deployment error:%v", err)return}klog.Infof("create deployment success, name:%s", dep.Name)
}func UpdateDeploy(client appsresv1.DeploymentInterface) {klog.Info("UpdateDeploy...........")// 当有多个客户端对同一个资源进行操作时,可能会发生错误。使用RetryOnConflict来重试,重试相关参数由DefaultRetry来提供err := retry.RetryOnConflict(retry.DefaultRetry, func() error {// 查询要更新的deploydeploy, err := client.Get(context.Background(), "deploy-nginx-demo", v1.GetOptions{})if err != nil {klog.Errorf("can't get deployment, err:%v", err)return nil}// 修改参数后进行更新replicas := int32(1)deploy.Spec.Replicas = &replicasdeploy.Spec.Template.Spec.Containers[0].Image = "nginx:1.13"_, err = client.Update(context.Background(), deploy, v1.UpdateOptions{})if err != nil {klog.Errorf("update deployment error, err:%v", err)}return err})if err != nil {klog.Errorf("update deployment error, err:%v", err)} else {klog.Infof("update deployment success")}}func ListDeploy(client appsresv1.DeploymentInterface) {klog.Info("ListDeploy...........")deplist, err := client.List(context.Background(), v1.ListOptions{})if err != nil {klog.Errorf("list deployment error, err:%v", err)return}for _, dep := range deplist.Items {klog.Infof("deploy name:%s, replicas:%d, container image:%s", dep.Name, *dep.Spec.Replicas, dep.Spec.Template.Spec.Containers[0].Image)}
}func DeleteDeploy(client appsresv1.DeploymentInterface) {klog.Info("DeleteDeploy...........")// 删除策略deletePolicy := v1.DeletePropagationForegrounderr := client.Delete(context.Background(), "deploy-nginx-demo", v1.DeleteOptions{PropagationPolicy: &deletePolicy})if err != nil {klog.Errorf("delete deployment error, err:%v", err)} else {klog.Info("delete deployment success")}
}func prompt() {fmt.Printf("-> Press Return key to continue.")scanner := bufio.NewScanner(os.Stdin)for scanner.Scan() {break}if err := scanner.Err(); err != nil {panic(err)}fmt.Println()
}
参考资料
k8s类型定义2之基础设施TypeMeta与ObjectMeta
k8s编程operator——(2) client-go中的informer
Client-go 客户端
k8s编程operator——(1) client-go基础部分