前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >client-go gin的简单整合五-list-watch deployment应用

client-go gin的简单整合五-list-watch deployment应用

原创
作者头像
对你无可奈何
发布2022-05-25 19:54:31
4270
发布2022-05-25 19:54:31
举报
文章被收录于专栏:运维专栏运维专栏

背景:

紧接client-go gin的简单整合四-list-watch初探,list-watch的模式都在测试文件中写的,现在修改一下前面做的deployment pod namespace 等等的api!

client-go gin的简单整合五-list-watch deployment应用

src目录下创建core文件夹,并创建deployment_init.go文件,将test1.go中相关deployment配置迁移过来!(默认test1.go中内容迁移过来)

/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)
}

// 删除
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{})
	factory.Start(wait.NeverStop)
}

/src/service/deployment.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 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),
		})

	}
	g.JSON(200, ret)
	return
}
func GetDeployment(g *gin.Context) {
	ns := g.Query("ns")
	name := g.Query("name")
	ctx := context.Background()
	getopt := metav1.GetOptions{}
	dps, err := K8sClient.AppsV1().Deployments(ns).Get(ctx, name, getopt)
	if err != nil {
		g.Error(err)
	}
	ret := make([]*Deployment, 0)
	ret = append(ret, &Deployment{
		Namespace:           dps.Namespace,
		Name:                dps.Name,
		Replicas:            dps.Status.Replicas,
		AvailableReplicas:   dps.Status.AvailableReplicas,
		UnavailableReplicas: dps.Status.UnavailableReplicas,
		Images:              dps.Spec.Template.Spec.Containers[0].Image,
		CreateTime:          dps.CreationTimestamp.Format("2006-01-02 15:03:04"),
		Labels:              dps.Labels,
		Pods:                GetPodsByDep(ns, dps),
	})
	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 {
	ctx := context.Background()
	listopt := metav1.ListOptions{
		LabelSelector: GetLabels(dep.Spec.Selector.MatchLabels),
	}
	list, err := K8sClient.CoreV1().Pods(ns).List(ctx, listopt)
	if err != nil {
		panic(err.Error())
	}
	pods := make([]*Pod, len(list.Items))
	for i, pod := range list.Items {
		pods[i] = &Pod{
			Namespace:  pod.Namespace,
			Name:       pod.Name, //获取 pod名称
			Status:     string(pod.Status.Phase),
			Images:     pod.Spec.Containers[0].Image,
			NodeName:   pod.Spec.NodeName, //所属节点
			Labels:     pod.Labels,
			CreateTime: pod.CreationTimestamp.Format("2006-01-02 15:04:05"), //创建时间
		}
	}

	return pods

}

go run main.go 启动应用

浏览器访问http://127.0.0.1:8080/deployments?ns=default

image.png
image.png

继续完善deployment的程序

问题复现:

nginx.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: nginx
  name: nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        resources: {}
status: {}
[zhangpeng@zhangpeng k8s]$ kubectl apply -f nginx.yaml 
deployment.apps/nginx created

nginx1.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  creationTimestamp: null
  labels:
    app: nginx
  name: nginx1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  strategy: {}
  template:
    metadata:
      creationTimestamp: null
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx1
        resources: {}
status: {}
[zhangpeng@zhangpeng k8s]$ kubectl apply -f nginx1.yaml 
deployment.apps/nginx1 created
image.png
image.png

浏览器继续访问http://127.0.0.1:8080/deployments?ns=default

见证奇迹的时候到了!为什么deployments中出现了另外一个deployment中的pod了呢?

image.png
image.png
image.png
image.png

Deployment repliceset and Pods

这是因为我们前面将Pod与Deployment绑定使用了(其实我的个人环境完全可以这样,因为我的标签没有重复使用的都区分了不同的名称)

关于deployment与RepliceSet:

https://kubernetes.io/zh/docs/concepts/workloads/controllers/deployment/

https://kubernetes.io/zh/docs/concepts/workloads/controllers/replicaset/#how-a-replicaset-works

deployment管理pod的机制:

[root@k8s-master-01 test]# kubectl get deployments
NAME     READY   UP-TO-DATE   AVAILABLE   AGE
nginx    1/1     1            1           2m40s
nginx1   1/1     1            1           2m16s
[root@k8s-master-01 test]# kubectl get pods
NAME                      READY   STATUS    RESTARTS   AGE
nginx-6799fc88d8-sbrcd    1/1     Running   0          2m46s
nginx1-6dc5c6d499-bzhgn   1/1     Running   0          2m22s
[root@k8s-master-01 test]# kubectl get rs
NAME                DESIRED   CURRENT   READY   AGE
nginx-6799fc88d8    1         1         1       3m42s
nginx1-6dc5c6d499   1         1         1       3m18s

注:非前面集群 ,远程办公在家演示.....故pod名称 主机名可能不相同,忽略......

首先写一个方法根据deployment名称取repliceset标签:

image.png
image.png
image.png
image.png

/src/common/common.go

package common

import (
	"context"
	"k8s-demo1/src/lib"
	v1 "k8s.io/api/apps/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func GetRsLableByDeployment(dep *v1.Deployment) string {
	selector, _ := metav1.LabelSelectorAsSelector(dep.Spec.Selector)
	listOpt := metav1.ListOptions{
		LabelSelector: selector.String(),
	}
	rs, _ := lib.K8sClient.AppsV1().ReplicaSets(dep.Namespace).List(context.Background(), listOpt)
	for _, item := range rs.Items {
		if IsCurrentRsByDep(dep, item) {
			s, err := metav1.LabelSelectorAsSelector(item.Spec.Selector)
			if err != nil {
				return ""
			}
			return s.String()
		}
	}
	return ""
}
func IsCurrentRsByDep(dep *v1.Deployment, rs v1.ReplicaSet) bool {
	if rs.ObjectMeta.Annotations["deployment.kubernetes.io/revision"] != dep.ObjectMeta.Annotations["deployment.kubernetes.io/revision"] {
		return false
	}
	for _, ref := range rs.OwnerReferences {
		if ref.Kind == "Deployment" && ref.Name == dep.Name {
			return true
		}

	}
	return false
}

/src/service/deployment.go

package service

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

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,
			CreateTime:          item.CreationTimestamp.Format("2006-01-02 15:03:04"),
			Labels:              item.GetLabels(),
			Pods:                GetPodsByDep(ns, item),
		})

	}
	g.JSON(200, ret)
	return
}

func GetDeployment(g *gin.Context) {
	ns := g.Query("ns")
	name := g.Query("name")
	ctx := context.Background()
	getopt := metav1.GetOptions{}
	dps, err := K8sClient.AppsV1().Deployments(ns).Get(ctx, name, getopt)
	if err != nil {
		fmt.Println(err)
	}
	ret := make([]*Deployment, 0)
	ret = append(ret, &Deployment{
		Namespace:           dps.Namespace,
		Name:                dps.Name,
		Replicas:            dps.Status.Replicas,
		AvailableReplicas:   dps.Status.AvailableReplicas,
		UnavailableReplicas: dps.Status.UnavailableReplicas,
		Images:              dps.Spec.Template.Spec.Containers[0].Image,
		CreateTime:          dps.CreationTimestamp.Format("2006-01-02 15:03:04"),
		Labels:              dps.Labels,
		Pods:                GetPodsByDep(ns, dps),
	})
	//fmt.Println(ret)
	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 {
	ctx := context.Background()
	listopt := metav1.ListOptions{
		LabelSelector: common.GetRsLableByDeployment(dep),
	}
	list, err := K8sClient.CoreV1().Pods(ns).List(ctx, listopt)
	if err != nil {
		panic(err.Error())
	}
	pods := make([]*Pod, len(list.Items))
	for i, pod := range list.Items {
		pods[i] = &Pod{
			Namespace:  pod.Namespace,
			Name:       pod.Name, //获取 pod名称
			Status:     string(pod.Status.Phase),
			Images:     pod.Spec.Containers[0].Image,
			NodeName:   pod.Spec.NodeName, //所属节点
			Labels:     pod.Labels,
			CreateTime: pod.CreationTimestamp.Format("2006-01-02 15:04:05"), //创建时间
		}
	}

	return pods

}

/src/main.go

package main

import (
	"github.com/gin-gonic/gin"
	"k8s-demo1/src/core"
	"k8s-demo1/src/service"
	//	"k8s.io/client-go/informers/core"
)

func main() {
	r := gin.Default()
	r.GET("/", func(context *gin.Context) {
		context.JSON(200, "hello")
	})
	r.GET("/namespaces", service.ListNamespace)
	r.GET("/deployments", service.ListDeployment)
	r.GET("/service", service.ListService)
	r.GET("/deployment", service.GetDeployment)
	r.GET("pods", service.ListallPod)
	//	r.GET("deployment1", service.GetDeployment1)
	core.InitDeployment()
	r.Run()
}

http://127.0.0.1:8080/deployments?ns=default

注:远程测试的用内网集群(前面做实验yaml开始有写错的,测试怀疑人生了。远程测试的!)

829f6c298d526f0dda2bcb3d35f6cc2.png
829f6c298d526f0dda2bcb3d35f6cc2.png

收获:

  1. 代码好多https://github.com/cleverhu/k8s-manger-v1中copy来的。
  2. deployment repliceset pods之间的关系还要深究一下。kubernetes基础知识还是要更深入一下
  3. 代码写的还是很不顺畅......一步一步来吧

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景:
  • client-go gin的简单整合五-list-watch deployment应用
    • /src/core/deployment_init.go
      • go run main.go 启动应用
      • 继续完善deployment的程序
        • 问题复现:
          • nginx.yaml
          • nginx1.yaml
        • Deployment repliceset and Pods
          • 关于deployment与RepliceSet:
          • /src/common/common.go
      • 收获:
      相关产品与服务
      容器服务
      腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档