背景:
实现了后面一些简略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......
总结:
- github大法好,的长于查找资源
- 没有想好list watch是否能够创立deployment?
- /src/service/DepUtils.go还要消化,拿来的感觉很有用。ports的获取形式我开始始终没有想好怎么实现,感激github......