当前位置:网站首页>Simple integration of client go gin six list watch two (about the improvement of RS, pod and deployment)

Simple integration of client go gin six list watch two (about the improvement of RS, pod and deployment)

2022-06-11 06:42:00 saynaihe

background :

The front is finished client-go gin Simple integration of five -list-watch deployment application , Go one step further Rs Pod It also realizes list-watch!
Less written before :

/src/core/deployment_init.go

// to update 
func (depmap *DeploymentMap) Update(dep *v1.Deployment) error {
	if list, ok := depmap.data.Load(dep.Namespace); ok {
		for i, range_dep := range list.([]*v1.Deployment) {
			if range_dep.Name == dep.Name {
				list.([]*v1.Deployment)[i] = dep
				depmap.data.Store(dep.Namespace, list)
			}
		}
		return nil
	}
	return fmt.Errorf("deployment-%s not found", dep.Name)
}

Forget the Store data …depmap.data.Store(dep.Namespace, list)!

client-go gin Simple integration of six -list-watch Two ( About Rs And Pod)

About Rs list-watch

/src/core/rs_init.go

package core

import (
	"errors"
	"fmt"
	v1 "k8s.io/api/apps/v1"
	"log"
	"sync"
)

type RSMapStruct struct {
	Data sync.Map
}

func (rsmap *RSMapStruct) Add(rs *v1.ReplicaSet) {
	key := rs.Namespace
	if value, ok := rsmap.Data.Load(key); ok {
		value = append(value.([]*v1.ReplicaSet), rs)
		rsmap.Data.Store(key, value)
	} else {
		rsmap.Data.Store(key, []*v1.ReplicaSet{rs})
	}
}
func (rsmap *RSMapStruct) Update(rs *v1.ReplicaSet) error {
	key := rs.Namespace
	if value, ok := rsmap.Data.Load(key); ok {
		for index, r := range value.([]*v1.ReplicaSet) {
			if r.Name == rs.Name {
				value.([]*v1.ReplicaSet)[index] = rs
				rsmap.Data.Store(key, value)
				return nil
			}
		}
	}

	return fmt.Errorf("rs-%s not found", rs.Name)
}

func (rsmap *RSMapStruct) Delete(rs *v1.ReplicaSet) {
	key := rs.Namespace
	if value, ok := rsmap.Data.Load(key); ok {
		for index, r := range value.([]*v1.ReplicaSet) {
			if r.Name == rs.Name {
				value = append(value.([]*v1.ReplicaSet)[0:index], value.([]*v1.ReplicaSet)[index+1:]...)
				rsmap.Data.Store(key, value)
				return
			}
		}
	}
}

func (rsmap *RSMapStruct) ListByNS(ns string) ([]*v1.ReplicaSet, error) {
	if list, ok := rsmap.Data.Load(ns); ok {
		return list.([]*v1.ReplicaSet), nil
	}
	return nil, errors.New("rs record not found")
}

func (rsmap *RSMapStruct) GetRsLabelsByDeployment(deploy *v1.Deployment) ([]map[string]string, error) {
	rs, err := rsmap.ListByNS(deploy.Namespace)
	if err != nil {
		return nil, err
	}
	ret := make([]map[string]string, 0)
	for _, item := range rs {
		//if item.Annotations["deployment.kubernetes.io/revision"] != deploy.Annotations["deployment.kubernetes.io/revision"] {
		//	continue
		//}
		for _, v := range item.OwnerReferences {
			if v.Name == deploy.Name {
				ret = append(ret, item.Labels)
				break
			}
		}
	}
	return ret, nil
}

type RSHandler struct {
}

func (rsmap *RSHandler) OnAdd(obj interface{}) {
	RSMap.Add(obj.(*v1.ReplicaSet))
}
func (rsmap *RSHandler) OnUpdate(oldObj interface{}, newObj interface{}) {
	err := RSMap.Update(newObj.(*v1.ReplicaSet))
	if err != nil {
		log.Println(err)
	}
}
func (rsmap *RSHandler) OnDelete(obj interface{}) {
	RSMap.Delete(obj.(*v1.ReplicaSet))
}

var RSMap *RSMapStruct

func init() {
	RSMap = &RSMapStruct{}
}

About Pod list-watch

Write a first util Method ( Just to judge two label Are they the same? !):
/src/core/Util.go

func IsValidLabel(m1, m2 map[string]string) bool {
	for key := range m2 {
		if m2[key] != m1[key] {
			return false
		}
	}

	return true
}

basic copy since deployment_init.go:
/src/core/pod_int.go

package core

import (
	"fmt"
	corev1 "k8s.io/api/core/v1"
	"log"
	"sync"
)

type PodMapStruct struct {
	data sync.Map
}

func (podmap *PodMapStruct) Add(pod *corev1.Pod) {
	key := pod.Namespace
	if value, ok := podmap.data.Load(key); ok {
		value = append(value.([]*corev1.Pod), pod)
		podmap.data.Store(key, value)
	} else {
		podmap.data.Store(key, []*corev1.Pod{pod})
	}
}
func (podmap *PodMapStruct) Update(pod *corev1.Pod) error {
	key := pod.Namespace
	if value, ok := podmap.data.Load(key); ok {

		for index, p := range value.([]*corev1.Pod) {
			if p.Name == pod.Name {
				value.([]*corev1.Pod)[index] = pod
				podmap.data.Store(key, value)
				return nil
			}
		}
	}

	return fmt.Errorf("pod-%s not found", pod.Name)
}
func (podmap *PodMapStruct) Delete(pod *corev1.Pod) {
	key := pod.Namespace
	if value, ok := podmap.data.Load(key); ok {
		for index, p := range value.([]*corev1.Pod) {
			if p.Name == pod.Name {
				value = append(value.([]*corev1.Pod)[0:index], value.([]*corev1.Pod)[index+1:]...)
				podmap.data.Store(key, value)
				return
			}
		}
	}
}
func (podmap *PodMapStruct) ListByNS(ns string) ([]*corev1.Pod, error) {

	if ns != "" {
		if list, ok := podmap.data.Load(ns); ok {
			return list.([]*corev1.Pod), nil
		}
	}
	return nil, fmt.Errorf("pods not found")
}
func (podmap *PodMapStruct) ListByLabels(ns string, labels []map[string]string) ([]*corev1.Pod, error) {
	pods, err := podmap.ListByNS(ns)
	if err != nil {
		return nil, err
	}
	ret := make([]*corev1.Pod, 0)
	for _, pod := range pods {
		for _, label := range labels {
			if IsValidLabel(pod.Labels, label) {
				ret = append(ret, pod)
			}
		}
	}
	return ret, nil
}

type PodHandler struct {
}
var PodMap *PodMapStruct

func init() {
	PodMap = &PodMapStruct{}
}
func (podmap *PodHandler) OnAdd(obj interface{}) {
	PodMap.Add(obj.(*corev1.Pod))
}
func (podmap *PodHandler) OnUpdate(oldObj interface{}, newObj interface{}) {
	err := PodMap.Update(newObj.(*corev1.Pod))
	if err != nil {
		log.Println(err)
	}
}
func (podmap *PodHandler) OnDelete(obj interface{}) {
	PodMap.Delete(obj.(*corev1.Pod))
}

deployment informer AddEventHandler

/src/core/deployment_init.go

package core

import (
	"fmt"
	"k8s-demo1/src/lib"
	v1 "k8s.io/api/apps/v1"
	"k8s.io/apimachinery/pkg/util/wait"
	"k8s.io/client-go/informers"
	"log"
	"sync"
)

type DeploymentMap struct {
	data sync.Map
}

func (depmap *DeploymentMap) Add(dep *v1.Deployment) {
	if list, ok := depmap.data.Load(dep.Namespace); ok {
		list = append(list.([]*v1.Deployment), dep)
		depmap.data.Store(dep.Namespace, list)
	} else {
		depmap.data.Store(dep.Namespace, []*v1.Deployment{dep})
	}
}
func (depmap *DeploymentMap) Update(dep *v1.Deployment) error {
	if list, ok := depmap.data.Load(dep.Namespace); ok {
		for i, range_dep := range list.([]*v1.Deployment) {
			if range_dep.Name == dep.Name {
				list.([]*v1.Deployment)[i] = dep
			}
		}
		return nil
	}
	return fmt.Errorf("deployment-%s not found", dep.Name)
}

//  Delete 
func (depmap *DeploymentMap) Delete(dep *v1.Deployment) {
	if list, ok := depmap.data.Load(dep.Namespace); ok {
		for i, range_dep := range list.([]*v1.Deployment) {
			if range_dep.Name == dep.Name {
				newList := append(list.([]*v1.Deployment)[:i], list.([]*v1.Deployment)[i+1:]...)
				depmap.data.Store(dep.Namespace, newList)
				break
			}
		}
	}
}
func (depmap *DeploymentMap) ListByNS(ns string) ([]*v1.Deployment, error) {
	if list, ok := depmap.data.Load(ns); ok {
		return list.([]*v1.Deployment), nil
	}
	return nil, fmt.Errorf("record not found")
}

var DepMap *DeploymentMap

func init() {
	DepMap = &DeploymentMap{}
}

type DepHandler struct {
}

func (d *DepHandler) OnAdd(obj interface{}) {
	//fmt.Println(obj.(*v1.Deployment).Name)
	DepMap.Add(obj.(*v1.Deployment))
}
func (d *DepHandler) OnUpdate(oldObj, newObj interface{}) {
	err := DepMap.Update(newObj.(*v1.Deployment))
	if err != nil {
		log.Println(err)
	}
}
func (d *DepHandler) OnDelete(obj interface{}) {
	if d, ok := obj.(*v1.Deployment); ok {
		DepMap.Delete(d)
	}
}

func InitDeployment() {
	factory := informers.NewSharedInformerFactory(lib.K8sClient, 0)
	depinformer := factory.Apps().V1().Deployments()
	depinformer.Informer().AddEventHandler(&DepHandler{})
	podInformer := factory.Core().V1().Pods().Informer()
	podInformer.AddEventHandler(&PodHandler{})

	rsInformer := factory.Apps().V1().ReplicaSets().Informer()
	rsInformer.AddEventHandler(&RSHandler{})
	factory.Start(wait.NeverStop)
}

Pod.go

/src/service/Pod.go

package service

import (
	"context"
	"fmt"
	"github.com/gin-gonic/gin"
	"k8s-demo1/src/core"
	. "k8s-demo1/src/lib"
	v1 "k8s.io/api/apps/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

type Pod struct {
	Namespace  string
	Name       string
	Status     string
	Images     string
	NodeName   string
	CreateTime string
	Labels     map[string]string
}

func ListallPod(g *gin.Context) {
	ns := g.Query("ns")

	//pods, err := K8sClient.CoreV1().Pods(ns).List(context.Background(), metav1.ListOptions{})
	pods, err := core.PodMap.ListByNS(ns)
	if err != nil {
		g.Error(err)
	}
	ret := make([]*Pod, 0)
	for _, item := range pods {

		ret = append(ret, &Pod{
			Namespace:  item.Namespace,
			Name:       item.Name,
			Status:     string(item.Status.Phase),
			Labels:     item.Labels,
			NodeName:   item.Spec.NodeName,
			Images:     item.Spec.Containers[0].Image,
			CreateTime: item.CreationTimestamp.Format("2006-01-02 15:04:05"),
		})

	}
	g.JSON(200, ret)
	return
}

deployment.go Modification of

deployment.go We need to revise it ( Last time I didn't put GetPodsByDep And other methods are modified as list-wath!)
/src/service/deployment.go:

package service

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"k8s-demo1/src/core"
	v1 "k8s.io/api/apps/v1"
	"log"
)

type Deployment struct {
	Namespace           string
	Name                string
	Replicas            int32
	AvailableReplicas   int32
	UnavailableReplicas int32
	Images              string
	CreateTime          string
	Labels              map[string]string
	Pods                []*Pod
}

func ListDeployment(g *gin.Context) {
	ns := g.Query("ns")
	deplist, err := core.DepMap.ListByNS(ns)
	//dps, err := K8sClient.AppsV1().Deployments(ns).List(context.Background(), metav1.ListOptions{})
	if err != nil {
		g.Error(err)
	}
	ret := make([]*Deployment, 0)
	for _, item := range deplist {
		ret = append(ret, &Deployment{
			Namespace:           item.Namespace,
			Name:                item.Name,
			Replicas:            item.Status.Replicas,
			AvailableReplicas:   item.Status.AvailableReplicas,
			UnavailableReplicas: item.Status.UnavailableReplicas,
			Images:              item.Spec.Template.Spec.Containers[0].Image,
			Labels:              item.GetLabels(),
			Pods:                GetPodsByDep(ns, *item),
			CreateTime:          item.CreationTimestamp.Format("2006-01-02 15:03:04"),
		})

	}
	g.JSON(200, ret)
	return
}

func GetLabels(m map[string]string) string {
	labels := ""
	// aa=xxx,xxx=xx
	for k, v := range m {
		if labels != "" {
			labels += ","
		}
		labels += fmt.Sprintf("%s=%s", k, v)
	}
	return labels
}
func GetPodsByDep(ns string, dep v1.Deployment) []*Pod {
	rsLabelsMap, err := core.RSMap.GetRsLabelsByDeployment(&dep)
	if err != nil {
		log.Fatal(err)
	}
	pods, err := core.PodMap.ListByLabels(dep.Namespace, rsLabelsMap)
	if err != nil {
		log.Fatal(err)
	}
	ret := make([]*Pod, 0)
	for _, pod := range pods {
		ret = append(ret, &Pod{
			Name:       pod.Name,
			Namespace:  pod.Namespace,
			Images:     pod.Spec.Containers[0].Image,
			NodeName:   pod.Spec.NodeName,
			Labels:     pod.Labels,
			Status:     string(pod.Status.Phase),
			CreateTime: pod.CreationTimestamp.Format("2006-01-02 15:04:05"),
		})
	}
	return ret
}

function main.go

function main.go See if you can access pod list ?
http://127.0.0.1:8080/pods?ns=default
image.png

deployments Pit under …

function main.go I also took a look at it deployment If there is something wrong :
http://127.0.0.1:8080/deployments?ns=default
image.png
what…deployment Of pod Yes ! Think about it :GetRsLabelsByDeployment I didn't judge rc And pod The relationship between ,pod Of label The judgment is still imprecise , Did not think of a good way , Stole a lazy :
/src/core/rs_int.go

package core

import (
	"errors"
	"fmt"
	v1 "k8s.io/api/apps/v1"
	"log"
	"sync"
)

type RSMapStruct struct {
	Data sync.Map
}

func (rsmap *RSMapStruct) Add(rs *v1.ReplicaSet) {
	key := rs.Namespace
	if value, ok := rsmap.Data.Load(key); ok {
		value = append(value.([]*v1.ReplicaSet), rs)
		rsmap.Data.Store(key, value)
	} else {
		rsmap.Data.Store(key, []*v1.ReplicaSet{rs})
	}
}
func (rsmap *RSMapStruct) Update(rs *v1.ReplicaSet) error {
	key := rs.Namespace
	if value, ok := rsmap.Data.Load(key); ok {
		for index, r := range value.([]*v1.ReplicaSet) {
			if r.Name == rs.Name {
				value.([]*v1.ReplicaSet)[index] = rs
				rsmap.Data.Store(key, value)
				return nil
			}
		}
	}

	return fmt.Errorf("rs-%s not found", rs.Name)
}

func (rsmap *RSMapStruct) Delete(rs *v1.ReplicaSet) {
	key := rs.Namespace
	if value, ok := rsmap.Data.Load(key); ok {
		for index, r := range value.([]*v1.ReplicaSet) {
			if r.Name == rs.Name {
				value = append(value.([]*v1.ReplicaSet)[0:index], value.([]*v1.ReplicaSet)[index+1:]...)
				rsmap.Data.Store(key, value)
				return
			}
		}
	}
}

func (rsmap *RSMapStruct) ListByNS(ns string) ([]*v1.ReplicaSet, error) {
	if list, ok := rsmap.Data.Load(ns); ok {
		return list.([]*v1.ReplicaSet), nil
	}
	return nil, errors.New("rs record not found")
}

func (rsmap *RSMapStruct) GetRsLabelsByDeployment(deploy *v1.Deployment) ([]map[string]string, error) {
	rs, err := rsmap.ListByNS(deploy.Namespace)
	if err != nil {
		return nil, err
	}
	ret := make([]map[string]string, 0)
	for _, item := range rs {
		//if item.Annotations["deployment.kubernetes.io/revision"] != deploy.Annotations["deployment.kubernetes.io/revision"] {
		//	continue
		//}
		for _, v := range item.OwnerReferences {
			if v.Name == deploy.Name {
				ret = append(ret, item.Labels)
				break
			}
		}
	}
	return ret, nil
}
func (rsmap *RSMapStruct) GetRsLabelsByDeploymentname(deploy *v1.Deployment) string {
	rs, err := rsmap.ListByNS(deploy.Namespace)
	if err != nil {
		fmt.Println(err)
	}
	for _, item := range rs {
		//if item.Annotations["deployment.kubernetes.io/revision"] != deploy.Annotations["deployment.kubernetes.io/revision"] {
		//	continue
		//}
		for _, v := range item.OwnerReferences {
			if v.Name == deploy.Name {
				return item.Name
			}
		}
	}
	return ""
}

type RSHandler struct {
}

func (rsmap *RSHandler) OnAdd(obj interface{}) {
	RSMap.Add(obj.(*v1.ReplicaSet))
}
func (rsmap *RSHandler) OnUpdate(oldObj interface{}, newObj interface{}) {
	err := RSMap.Update(newObj.(*v1.ReplicaSet))
	if err != nil {
		log.Println(err)
	}
}
func (rsmap *RSHandler) OnDelete(obj interface{}) {
	RSMap.Delete(obj.(*v1.ReplicaSet))
}

var RSMap *RSMapStruct

func init() {
	RSMap = &RSMapStruct{}
}

imitation GetRsLabelsByDeployment Wrote a **GetRsLabelsByDeploymentname Method ,** EN return rc Of name be equal to pod Of OwnerReferences In the field name Field !
image.png
/src/service/deployment.go

package service

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"k8s-demo1/src/core"
	v1 "k8s.io/api/apps/v1"
	"log"
)

type Deployment struct {
	Namespace           string
	Name                string
	Replicas            int32
	AvailableReplicas   int32
	UnavailableReplicas int32
	Images              string
	CreateTime          string
	Labels              map[string]string
	Pods                []*Pod
}

func ListDeployment(g *gin.Context) {
	ns := g.Query("ns")
	deplist, _ := core.DepMap.ListByNS(ns)
	//dps, err := K8sClient.AppsV1().Deployments(ns).List(context.Background(), metav1.ListOptions{})
	//if err != nil {
	//	g.Error(err)
	//}
	ret := make([]*Deployment, 0)
	for _, item := range deplist {
		ret = append(ret, &Deployment{
			Namespace:           item.Namespace,
			Name:                item.Name,
			Replicas:            item.Status.Replicas,
			AvailableReplicas:   item.Status.AvailableReplicas,
			UnavailableReplicas: item.Status.UnavailableReplicas,
			Images:              item.Spec.Template.Spec.Containers[0].Image,
			Labels:              item.GetLabels(),
			Pods:                GetPodsByDep(*item),
			CreateTime:          item.CreationTimestamp.Format("2006-01-02 15:03:04"),
		})

	}
	g.JSON(200, ret)
	return
}

func GetLabels(m map[string]string) string {
	labels := ""
	// aa=xxx,xxx=xx
	for k, v := range m {
		if labels != "" {
			labels += ","
		}
		labels += fmt.Sprintf("%s=%s", k, v)
	}
	return labels
}
func GetPodsByDep(dep v1.Deployment) []*Pod {
	rsLabelsMap, err := core.RSMap.GetRsLabelsByDeployment(&dep)
	if err != nil {
		log.Fatal(err)
	}

	pods, err := core.PodMap.ListByRsLabels(dep.Namespace, rsLabelsMap)
	if err != nil {
		log.Fatal(err)
	}
	ret := make([]*Pod, 0)

	for _, pod := range pods {
		if core.RSMap.GetRsLabelsByDeploymentname(&dep) == pod.OwnerReferences[0].Name {
			ret = append(ret, &Pod{
				Name:       pod.Name,
				Namespace:  pod.Namespace,
				Images:     pod.Spec.Containers[0].Image,
				NodeName:   pod.Spec.NodeName,
				Labels:     pod.Labels,
				Status:     string(pod.Status.Phase),
				CreateTime: pod.CreationTimestamp.Format("2006-01-02 15:04:05"),
			})
		}
	}
	return ret
}

function mai.go, visit http://127.0.0.1:8080/deployments?ns=default
image.png
It is an accurate match , I don't know if there will be any pits …

summary :

Sum up the lessons learned in this process :

  1. deployment rs pod The relationship between
  2. OwnerReferences The matching of
  3. Let's continue crud Well … This place is a little long for me to understand list-watch
原网站

版权声明
本文为[saynaihe]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/162/202206110639384363.html