在工作中需要对kubernetes进行自定义资源的开发,操作K8s的资源肯定是必不可少的。K8s原生语言是用Go编写的,所以在CRD中使用client-go来操作资源。本次介绍一下使用client-go来操作Deployment。
1. 创建main函数
go
func main() {
homePath := homedir.HomeDir()
if homePath == "" {
panic("homePath is empty")
}
kubeConfig := filepath.Join(homePath, ".kube", "config")
config, err := clientcmd.BuildConfigFromFlags("", kubeConfig)
if err != nil {
panic(err)
}
// use the config to create a client
clientSet, err := kubernetes.NewForConfig(config)
if err != nil {
panic(err)
}
dpClient := clientSet.AppsV1().Deployments(corev1.NamespaceDefault)
log.Println("start handle deployments...")
// 创建一个deployment
err = createDeployment(dpClient)
if err != nil {
panic(err)
}
log.Println("create deployment success")
<-time.Tick(time.Minute * 1)
// 修改一个deployment
err = updateDeployment(dpClient)
if err != nil {
panic(err)
}
log.Println("update deployment success")
<-time.Tick(time.Minute * 1)
// 删除一个deployment
err = deleteDeployment(dpClient)
if err != nil {
panic(err)
}
log.Println("delete deployment success")
}
这里创建了一个main函数,首先获取到kubernetes配置文件并创建出clientSet,再使用clientSet创建出来操作deployment的客户端。
随后定义了三个函数,分别是:
创建Deployment:createDeployment
修改Deployment:updateDeployment
删除Deployment:deleteDeployment
2. 创建Deployment
接下来编写createDeployment函数,此函数将在kubernetes集群中生成Deployment
go
func createDeployment(dpClient v1.DeploymentInterface) error {
replicas := int32(3)
newDp := appv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: "nginx-deployment",
},
Spec: appv1.DeploymentSpec{
Replicas: &replicas,
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{
"app": "nginx",
},
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
// 这里的label要和上面的selector的label一致
Labels: map[string]string{
"app": "nginx",
},
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "nginx",
Image: "nginx:1.16",
Ports: []corev1.ContainerPort{
{
ContainerPort: 80,
Name: "http",
Protocol: corev1.ProtocolTCP,
},
},
},
},
},
},
},
}
_, err := dpClient.Create(context.TODO(), &newDp, metav1.CreateOptions{})
if err != nil {
return err
}
return nil
}
定义副本数量3个,编写Deployment配置,定义ObjectMeta、Spec、Template各种参数
这里提一句Selector中"app": "nginx" 和 Template中是一样的,因为Deployment是通过标签关连到所属副本中pod的
3. 修改Deployment
在接下来的操作中,将nginx的版本变更一下,来达到修改的目的
go
func updateDeployment(dpClient v1.DeploymentInterface) error {
dp, err := dpClient.Get(context.TODO(), "nginx-deployment", metav1.GetOptions{})
if err != nil {
return err
}
dp.Spec.Template.Spec.Containers[0].Image = "nginx:1.17"
updateDp, err := dpClient.Update(context.TODO(), dp, metav1.UpdateOptions{})
if err != nil {
return err
}
return retry.RetryOnConflict(retry.DefaultRetry, func() error {
_, err := dpClient.Update(context.TODO(), updateDp, metav1.UpdateOptions{})
return err
})
}
此处的操作为现将之前创建好的dp获取到,然后进行nginx镜像版本的变更,随后进行使用客户端进行更新操作
此外还通过retry.RetryOnConflict来解决更新冲突
4. 删除Deployment
go
func deleteDeployment(dpClient v1.DeploymentInterface) error {
deletePolicy := metav1.DeletePropagationForeground
err := dpClient.Delete(context.TODO(), "nginx-deployment", metav1.DeleteOptions{
PropagationPolicy: &deletePolicy,
})
if err != nil {
return err
}
return nil
}
这里的删除操作定义了删除选项,表示前台级联删除。在这种模式下,删除操作会首先返回删除的资源,然后在后台删除关联的依赖对象。在 Kubernetes API 中,前台级联删除的表现形式是:首先将删除的对象的 metadata.deletionTimestamp
字段设置为当前时间,然后客户端会在此对象的 metadata.finalizers
列表中看到值 foregroundDeletion
。在依赖对象被删除后,Kubernetes 垃圾收集器会最后删除这个对象。
5. build
代码编写完成打包成二进制
go
go build -o ./handle_deployment
此时观察deployment所有流程效果
完整代码地址:https://github.com/xiaowei6688/k8s_go_example/tree/dev/handle_deployment