背景:

实现了后面一些简略list-watch的demo,这里开始进一步实现crud的基本操作,就从create开始了。这里从create namespace deployment pod service作一个简略的利用列举

create namespace

对于namespace

后面做过list的利用:client-go list namespace,/src/service/Namespace.go文件如下:

package serviceimport (    "context"    "github.com/gin-gonic/gin"    . "k8s-demo1/src/lib"    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"    "time")type Time struct {    time.Time `protobuf:"-"`}type Namespace struct {    Name       string    CreateTime Time `json:"CreateTime"`    Status     string    Labels     map[string]string}func ListNamespace(g *gin.Context) {    ns, err := K8sClient.CoreV1().Namespaces().List(context.Background(), metav1.ListOptions{})    if err != nil {        g.Error(err)        return    }    ret := make([]*Namespace, 0)    for _, item := range ns.Items {        ret = append(ret, &Namespace{            Name:       item.Name,            CreateTime: Time(item.CreationTimestamp),            Status:     string(item.Status.Phase),            Labels:     item.Labels,        })    }    g.JSON(200, ret)    return}

创立一个namespace

当初要创立一个create 创立命名空间的办法!


最终如下:

func create(ns Namespace) (*v1.Namespace, error) {    ctx := context.Background()    newNamespace, err := K8sClient.CoreV1().Namespaces().Create(ctx, &v1.Namespace{        ObjectMeta: metav1.ObjectMeta{            Name:   ns.Name,            Labels: ns.Labels,        },    }, metav1.CreateOptions{})    if err != nil {        fmt.Println(err)    }    return newNamespace, err}

而后创立CreateNameSpace,最终如下:

package serviceimport (    "context"    "fmt"    "github.com/gin-gonic/gin"    . "k8s-demo1/src/lib"    v1 "k8s.io/api/core/v1"    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"    "time")type Time struct {    time.Time `protobuf:"-"`}type Namespace struct {    Name        string            `json:"name"`    CreateTime  time.Time         `json:"CreateTime"`    Status      string            `json:"status"`    Labels      map[string]string `json:"labels"`    Annotations map[string]string `json:"annotations"`}func ListNamespace(g *gin.Context) {    ns, err := K8sClient.CoreV1().Namespaces().List(context.Background(), metav1.ListOptions{})    if err != nil {        g.Error(err)        return    }    ret := make([]*Namespace, 0)    for _, item := range ns.Items {        ret = append(ret, &Namespace{            Name:       item.Name,            CreateTime: item.CreationTimestamp.Time,            Status:     string(item.Status.Phase),            Labels:     item.Labels,        })    }    g.JSON(200, ret)    return}func create(ns Namespace) (*v1.Namespace, error) {    ctx := context.Background()    newNamespace, err := K8sClient.CoreV1().Namespaces().Create(ctx, &v1.Namespace{        ObjectMeta: metav1.ObjectMeta{            Name:   ns.Name,            Labels: ns.Labels,        },    }, metav1.CreateOptions{})    if err != nil {        fmt.Println(err)    }    return newNamespace, err}func CreateNameSpace(g *gin.Context) {    var nameSpace Namespace    if err := g.ShouldBind(&nameSpace); err != nil {        g.JSON(500, err)    }    namespace, err := create(nameSpace)    if err != nil {        g.JSON(500, err)    }    ns := Namespace{        Name:        namespace.Name,        CreateTime:  namespace.CreationTimestamp.Time,        Status:      string(namespace.Status.Phase),        Labels:      nil,        Annotations: nil,    }    g.JSON(200, ns)}

注:ShouldBind强调一下参照:https://www.kancloud.cn/shuangdeyu/gin_book/949426。当然了name是不能够为空的能够尝试一下!

编辑并运行main.go

package mainimport (    "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.POST("/namespace", service.CreateNameSpace)    r.GET("/deployments", service.ListDeployment)    r.GET("/service", service.ListService)    r.GET("pods", service.ListallPod)    core.InitDeployment()    r.Run()}
[zhangpeng@zhangpeng ~]$ kubectl get nsNAME              STATUS   AGEdefault           Active   50dkube-node-lease   Active   50dkube-public       Active   50dkube-system       Active   50d

运行main.go......

Postman 测试


Create Pod

参照:https://blog.csdn.net/weixin_42562106/article/details/122024744,比照下面的后面创立namespace步骤创立Pod 文件:

Pod.go

/src/service/Pod.go

package serviceimport (    "context"    "fmt"    "github.com/gin-gonic/gin"    "k8s-demo1/src/core"    . "k8s-demo1/src/lib"    v1 "k8s.io/api/apps/v1"    corev1 "k8s.io/api/core/v1"    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1")type Pod struct {    Namespace   string                 `json:"namespace"`    Name        string                 `json:"name"`    Status      string                 `json:"status"`    Images      string                 `json:"images"`    NodeName    string                 `json:"nodename"`    CreateTime  string                 `json:"createtime"`    Annotations map[string]string      `json:"annotations"`    Port        []corev1.ContainerPort `json:"port"`    //IsReady    bool    //Message      string    //HostIp       string    //PodIp        string    //RestartCount int32    Labels map[string]string `json:"labels"`}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,            //IsReady:   GetPodIsReady(*item),            //Message: GetPodMessage(*item),            //Message:      core.EventMap.GetMessage(item.Namespace, "Pod", item.Name),            //HostIp:       item.Status.HostIP,            //PodIp:        item.Status.PodIP,            //RestartCount: item.Status.ContainerStatuses[0].RestartCount,            CreateTime: item.CreationTimestamp.Format("2006-01-02 15:04:05"),        })    }    g.JSON(200, ret)    return}func Createpod(pod Pod) (*corev1.Pod, error) {    newpod, err := K8sClient.CoreV1().Pods(pod.Namespace).Create(context.TODO(), &corev1.Pod{        ObjectMeta: metav1.ObjectMeta{            Name:        pod.Name,            Namespace:   pod.Namespace,            Labels:      pod.Labels,            Annotations: pod.Annotations,        },        Spec: corev1.PodSpec{            Containers: []corev1.Container{                {Name: pod.Name, Image: pod.Images},            },        },    }, metav1.CreateOptions{})    if err != nil {        fmt.Println(err)    }    return newpod, err}func CreatePod(g *gin.Context) {    var NewPod Pod    if err := g.ShouldBind(&NewPod); err != nil {        g.JSON(500, err)    }    pod, err := Createpod(NewPod)    if err != nil {        g.JSON(500, err)    }    newpod := Pod{        Namespace:   pod.Namespace,        Name:        pod.Name,        Images:      pod.Spec.Containers[0].Image,        CreateTime:  pod.CreationTimestamp.Format("2006-01-02 15:04:05"),        Annotations: nil,    }    g.JSON(200, newpod)}

注: json:"",shouldbind的应用仍然是是......

main.go增加路由

main.go

package mainimport (    "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("pods", service.ListallPod)    r.POST("/namespace", service.CreateNameSpace)    r.POST("/pod", service.CreatePod)    core.InitDeployment()    r.Run()}

运行main.go

go run main.go(间接goland运行了)

Postman 测试创立pod

在zhangpeng 命名空间下创立镜像为nginx,名为zhangpeng的pod

get拜访验证pod是否创立胜利:
http://127.0.0.1:8080/pods?ns...

Create Deployment

参照:创立一个deployment.反正还是没有想好怎么搞,而后在github找到了一个我能看懂的拿来主义了:
https://github.com/c18871384325/Go-teacher/blob/784f81c7309e2567cbdd45580c3a8f277a1f3528/course/day20-20200829/codes/cmdb/forms/k8s.go
and https://github.com/c18871384325/Go-teacher/blob/784f81c7309e2567cbdd45580c3a8f277a1f3528/course/day20-20200829/codes/cmdb/services/k8s.go

github拿来主义

/src/service/DepUtils.go

package serviceimport (    coreV1 "k8s.io/api/core/v1"    "strconv"    "strings")func (d *Deployment) GetLabels() map[string]string {    labelsMap := make(map[string]string)    labels := strings.Split(d.Labels, "\n")    for _, label := range labels {        values := strings.SplitN(label, ":", 2)        if len(values) != 2 {            continue        }        labelsMap[strings.TrimSpace(values[0])] = strings.TrimSpace(values[1])    }    return labelsMap}func (d *Deployment) GetSelectors() map[string]string {    selectors := d.GetLabels()    selectors["app"] = d.Name    return selectors}func (d *Deployment) GetPorts() []coreV1.ContainerPort {    portList := make([]coreV1.ContainerPort, 0, 5)    ports := strings.Split(d.Ports, "\n")    for _, port := range ports {        values := strings.SplitN(port, ",", 3)        if len(values) != 3 {            continue        }        intPort, err := strconv.Atoi(values[1])        if err != nil {            continue        }        protocol := coreV1.ProtocolTCP        if strings.Compare(strings.ToLower(values[0]), "tcp") != 0 {            protocol = coreV1.ProtocolUDP        }        portList = append(portList, coreV1.ContainerPort{            Name:          strings.TrimSpace(values[2]),            ContainerPort: int32(intPort),            Protocol:      protocol,        })    }    return portList}func (d *Deployment) GetImageName() string {    // 全副为应为字母数字和:    pods := strings.Index(d.Images, ":")    if pods > 0 {        return d.Images[:pods]    }    return d.Images}

/src/service/deployment.go

package serviceimport (    "context"    "fmt"    "github.com/gin-gonic/gin"    "k8s-demo1/src/core"    . "k8s-demo1/src/lib"    v1 "k8s.io/api/apps/v1"    corev1 "k8s.io/api/core/v1"    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"    "log")type Deployment struct {    Namespace           string `json:"namespace"`    Name                string `json:"name"`    Replicas            int32  `json:"replicas"`    AvailableReplicas   int32  `json:"available-replicas"`    UnavailableReplicas int32  `json:"unavailable-replicas"`    Images              string `json:"images"`    Ports               string `json:"ports"`    CreateTime          string `json:"CreateTime"`    Labels              string `json:"labels"`    Pods                []*Pod `json:"pods"`}func ListDeployment(g *gin.Context) {    ns := g.Query("ns")    deplist, _ := core.DepMap.ListByNS(ns)    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 Createdep(dep Deployment) (*v1.Deployment, error) {    newdep, err := K8sClient.AppsV1().Deployments(dep.Namespace).Create(context.TODO(), &v1.Deployment{        ObjectMeta: metav1.ObjectMeta{            Name:      dep.Name,            Namespace: dep.Namespace,            Labels:    dep.GetLabels(),        },        Spec: v1.DeploymentSpec{            Replicas: &dep.Replicas,            Selector: &metav1.LabelSelector{                MatchLabels: dep.GetSelectors(),            },            Template: corev1.PodTemplateSpec{                ObjectMeta: metav1.ObjectMeta{                    Name:   dep.Name,                    Labels: dep.GetSelectors(),                },                Spec: corev1.PodSpec{                    Containers: []corev1.Container{                        {                            Name:  dep.GetImageName(),                            Image: dep.Images,                            Ports: dep.GetPorts(),                                      },                    },                },            },        },    }, metav1.CreateOptions{})    if err != nil {        fmt.Println(err)    }    return newdep, err}func CreateDep(g *gin.Context) {    var newDep Deployment    if err := g.ShouldBind(&newDep); err != nil {        g.JSON(500, err)    }    newdep, err := Createdep(newDep)    if err != nil {        g.JSON(500, err)    }    newDep1 := Deployment{        Namespace:  newdep.Namespace,        Name:       newdep.Name,        Pods:       GetPodsByDep(*newdep),        CreateTime: newdep.CreationTimestamp.Format("2006-01-02 15:03:04"),    }    g.JSON(200, newDep1)}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)    //fmt.Println(rsLabelsMap)    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),                //IsReady:   GetPodIsReady(*pod),                //    Message:    GetPodMessage(*pod),                //Message:      core.EventMap.GetMessage(pod.Namespace, "Pod", pod.Name),                //HostIp:       pod.Status.HostIP,                //PodIp:        pod.Status.PodIP,                //RestartCount: pod.Status.ContainerStatuses[0].RestartCount,                CreateTime: pod.CreationTimestamp.Format("2006-01-02 15:04:05"),            })        }    }    return ret}

注:Deployment struct有几个数据类型改了 ,办法有的也没有提交进来......前面整合......

增加post路由并运行main.go

main.go 路由增加POST("/deployment", service.CreateDep),运行main.go!

package mainimport (    "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("pods", service.ListallPod)    r.POST("/namespace", service.CreateNameSpace)    r.POST("/pod", service.CreatePod)    r.POST("/deployment", service.CreateDep)    core.InitDeployment()    r.Run()}

Postman测试创立deployment

http://127.0.0.1:8080/deployment

{"name":"zhangpeng","namespace":"zhangpeng","replicas":1,"ports":"tcp,80,web","images":"nginx"}


kubernetes集群操作:

[zhangpeng@zhangpeng ~]$ kubectl get all -n zhangpengNAME                             READY   STATUS    RESTARTS   AGEpod/zhangpeng-5dffd5664f-z567c   1/1     Running   0          62sNAME                        READY   UP-TO-DATE   AVAILABLE   AGEdeployment.apps/zhangpeng   1/1     1            1           62sNAME                                   DESIRED   CURRENT   READY   AGEreplicaset.apps/zhangpeng-5dffd5664f   1         1         1       62s

[zhangpeng@zhangpeng ~]$ kubectl get deployment -n zhangpeng -o yaml

apiVersion: v1items:- apiVersion: apps/v1  kind: Deployment  metadata:    annotations:      deployment.kubernetes.io/revision: "1"    creationTimestamp: "2022-06-21T08:36:12Z"    generation: 1    name: zhangpeng    namespace: zhangpeng    resourceVersion: "5991952"    uid: e8a48bdf-4c86-4413-8fb0-99ef1ddd1d6d  spec:    progressDeadlineSeconds: 600    replicas: 1    revisionHistoryLimit: 10    selector:      matchLabels:        app: zhangpeng    strategy:      rollingUpdate:        maxSurge: 25%        maxUnavailable: 25%      type: RollingUpdate    template:      metadata:        creationTimestamp: null        labels:          app: zhangpeng        name: zhangpeng      spec:        containers:        - image: nginx          imagePullPolicy: Always          name: nginx          ports:          - containerPort: 80            name: web            protocol: TCP          resources: {}          terminationMessagePath: /dev/termination-log          terminationMessagePolicy: File        dnsPolicy: ClusterFirst        restartPolicy: Always        schedulerName: default-scheduler        securityContext: {}        terminationGracePeriodSeconds: 30  status:    availableReplicas: 1    conditions:    - lastTransitionTime: "2022-06-21T08:36:29Z"      lastUpdateTime: "2022-06-21T08:36:29Z"      message: Deployment has minimum availability.      reason: MinimumReplicasAvailable      status: "True"      type: Available    - lastTransitionTime: "2022-06-21T08:36:12Z"      lastUpdateTime: "2022-06-21T08:36:29Z"      message: ReplicaSet "zhangpeng-5dffd5664f" has successfully progressed.      reason: NewReplicaSetAvailable      status: "True"      type: Progressing    observedGeneration: 1    readyReplicas: 1    replicas: 1    updatedReplicas: 1kind: Listmetadata:  resourceVersion: ""

次要是想验证一下ports的相干配置!

瑕疵


再搞一次程序就挂......打印对于rs的谬误,预计list watch还算那里有问题,先疏忽:

前面再去钻研吧.......当初我就是想能创立deployment......

总结:

  1. github大法好,的长于查找资源
  2. 没有想好list watch是否能够创立deployment?
  3. /src/service/DepUtils.go还要消化,拿来的感觉很有用。ports的获取形式我开始始终没有想好怎么实现,感激github......