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

Posted 对你无可奈何

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了client-go gin的简单整合五-list-watch deployment应用相关的知识,希望对你有一定的参考价值。

背景:

紧接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.Deploymentdep)
    

//更新
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

继续完善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


浏览器继续访问http://127.0.0.1:8080/deployments?ns=default
见证奇迹的时候到了!为什么deployments中出现了另外一个deployment中的pod了呢?


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标签:

/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开始有写错的,测试怀疑人生了。远程测试的!)

收获:

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

以上是关于client-go gin的简单整合五-list-watch deployment应用的主要内容,如果未能解决你的问题,请参考以下文章

client-go gin的简单整合六-list-watch二(关于Rs与Pod以及Deployment的完善)

client-go gin的简单整合六-list-watch二(关于Rs与Pod以及Deployment的完善)

client-go gin的简单整合六-list-watch二(关于Rs与Pod以及Deployment的完善)

client-go gin的简单整合二(list列表相关进一步操作)

client-go gin的简单整合四-list-watch初探

client-go gin的简单整合三(list列表相关再进阶关于Pods)