k8s series 16: API | 8月更文挑战

424 阅读3分钟

简介

如果想要实现更加自动化智能化的 操作,,或者需要自已写一套k8s管理平台,,那么就需要二次开发了,k8s官方支持多语言的lib,如下图

在日常运维中用到的kubectl 其实也是调的api运行的

官网还提供了api文档面,给供查询,因为涉及到的api实在太多了,全部记住是不太实现的,有个文档就便于辅助了

文档页地址:  kubernetes.io/docs/refere…

使用

因为博主平时使用golang写工具比较多一点,这里以golang为例

官方也给提供了一个例子    地址:  github.com/kubernetes/…

客户端集成

在使用go api时有两个认证方式,一种是集群里认证,一种是集群外认证,这里以集群外证书方式进行认证

如果不改变以下代码,,需要将认证文件config 放到 用户目录的.kube下,,就是集群初始化生成的文件

var kubeconfig *string
if 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()

如果想将config放到 指定路径,,则需要在第5行 "" 写入绝对路径

生成客户端配置

接下来使用kubenetes 创建clientset对象

config, err := clientcmd.BuildConfigFromFlags("", *kubeconfig)
if err != nil {
	panic(err.Error())
}
clientset, err := kubernetes.NewForConfig(config)

clientset对象包含了所有资源,也是所有资源的入口

构建deployment资源对象

拿到一个默认命名空间的 deployment对象

deploymentsClient := clientset.AppsV1().Deployments(apiv1.NamespaceDefault)

使用此对象可以进行 deployment控制器的增删改查

创建

根据deployment资源类型,定义基中meta数据以及spec内容

此例部署一个nginx

deployment := &appsv1.Deployment{
	ObjectMeta: metav1.ObjectMeta{
		Name: "demo-deployment",
	},
	Spec: appsv1.DeploymentSpec{
		Replicas: int32Ptr(2),
		Selector: &metav1.LabelSelector{
			MatchLabels: map[string]string{
				"app": "demo",
			},
		},
		Template: apiv1.PodTemplateSpec{
			ObjectMeta: metav1.ObjectMeta{
				Labels: map[string]string{
		 		   "app": "demo",
				},
			},
			Spec: apiv1.PodSpec{
				Containers: []apiv1.Container{
					{
						Name:  "web",
						Image: "nginx:1.12",
						Ports: []apiv1.ContainerPort{
							{
								Name:          "http",
								Protocol:      apiv1.ProtocolTCP,
								ContainerPort: 80,
							},
						},
					},
				},
	     	},
		},
	},
}


// Create Deployment
fmt.Println("Creating deployment...")
result, err := deploymentsClient.Create(context.TODO(), deployment, metav1.CreateOptions{})
if err != nil {
	panic(err)
}
fmt.Printf("Created deployment %q.\n", result.GetObjectMeta().GetName())

更新

这里更新了nginx 的镜像为nginx:1.13

这里可以看到一个prompt()的函数,主要是为了将每个动作作分隔,,有这个函数,每执行 更新,查看,删除都需要 手动敲一下 键盘

// Update Deployment
prompt()
fmt.Println("Updating deployment...")

retryErr := retry.RetryOnConflict(retry.DefaultRetry, func() error {

    result, getErr := deploymentsClient.Get(context.TODO(), "demo-deployment", metav1.GetOptions{})
    if getErr != nil {
	   panic(fmt.Errorf("Failed to get latest version of Deployment: %v", getErr))
     }
     result.Spec.Replicas = int32Ptr(1)                           // reduce replica count
     result.Spec.Template.Spec.Containers[0].Image = "nginx:1.13" // change nginx version
     _, updateErr := deploymentsClient.Update(context.TODO(), result, metav1.UpdateOptions{})
     return updateErr
})
if retryErr != nil {
	panic(fmt.Errorf("Update failed: %v", retryErr))
}
fmt.Println("Updated deployment...")

查看

从切片中将资源遍历到d身上,然后打印pod名称,和复本个数

// List Deployments
prompt()
fmt.Printf("Listing deployments in namespace %q:\n", apiv1.NamespaceDefault)
list, err := deploymentsClient.List(context.TODO(), metav1.ListOptions{})
if err != nil {
	panic(err)
}
for _, d := range list.Items {
	fmt.Printf(" * %s (%d replicas)\n", d.Name, *d.Spec.Replicas)
}

删除

指定deployment名称(demo-deployment) 删除

prompt()
fmt.Println("Deleting deployment...")
deletePolicy := metav1.DeletePropagationForeground
if err := deploymentsClient.Delete(context.TODO(), "demo-deployment", metav1.DeleteOptions{
	PropagationPolicy: &deletePolicy,
}); err != nil {
	panic(err)
}
fmt.Println("Deleted deployment.")

全部运行之后截图如下:

list资源例子

node

查看node列表

nodes,_ := clientset.CoreV1().Nodes().List(context.TODO(),metav1.ListOptions{})
for i, node := range nodes.Items {
	fmt.Printf("[%d] %s\n", i, node.GetName())
}

services

查看service列表

services,_ := clientset.CoreV1().Services("").List(context.TODO(),metav1.ListOptions{})
for i, svc := range services.Items {
	fmt.Printf("[%d] %s\n", i, svc.GetName())
}

大部分资源在CoreV1下,还有一些在ExtensionsV1beta1下,还有AppsV1下,使用clientset.  提示相关

上面查看的都是默认namespace的列表,想要查看有namespace下的 资源列表,在前面加个遍历既可

namespace

查看namespace列表

namespaces,_ := clientset.CoreV1().Namespaces().List(context.TODO(),metav1.ListOptions{})
for i,namespace := range namespaces.Items {
	fmt.Printf("[%d] %s\n", i, namespace.GetName())
}

总结

官方出来的sdk用起来还是蛮顺的,如果只是实现一些查看或者删除功能,会比较简单,但是如果要更新或者创建,便会涉及很多的知识点,这其中包括要对 相应控制器的了解 

在每一次动作中都有context.TODO() 这样一个参数,,这是用于控制该线程的(超时控制),,如果是TODO那就什么也不干,就是不干涉,以服务提供者为准