diff --git a/install/ingress-controller/9-with-rbac.yaml b/install/ingress-controller/9-with-rbac.yaml index 48a32b4b0..0d6941310 100644 --- a/install/ingress-controller/9-with-rbac.yaml +++ b/install/ingress-controller/9-with-rbac.yaml @@ -25,7 +25,6 @@ spec: - --default-backend-service=$(POD_NAMESPACE)/default-http-backend - --configmap=$(POD_NAMESPACE)/nginx-configuration - --annotations-prefix=nginx.ingress.kubernetes.io - - --watch-namespace=$(POD_NAMESPACE) env: - name: POD_NAME valueFrom: diff --git a/pkg/client/heapsterclient.go b/pkg/client/heapsterclient.go index 2154d47ac..dc42936e2 100644 --- a/pkg/client/heapsterclient.go +++ b/pkg/client/heapsterclient.go @@ -28,8 +28,8 @@ import ( const ( DefaultHeapsterScheme = "http" - DefaultHeapsterService = "192.168.0.34" //"heapster" - DefaultHeapsterPort = "31082" // use the first exposed port on the service + DefaultHeapsterService = "heapster.kube-system.svc.cluster.local" //"heapster" + DefaultHeapsterPort = "80" // use the first exposed port on the service HeapsterApiPath = "/api/v1/model" HeapsterEndpointUrl = DefaultHeapsterScheme + "://" + DefaultHeapsterService + ":" + DefaultHeapsterPort + HeapsterApiPath ) diff --git a/pkg/models/controllers/namespaces.go b/pkg/models/controllers/namespaces.go index 50aa4df66..0bb83401d 100644 --- a/pkg/models/controllers/namespaces.go +++ b/pkg/models/controllers/namespaces.go @@ -208,6 +208,7 @@ func (ctl *NamespaceCtl) createRoleAndRuntime(item v1.Namespace) { resp, err := ctl.createOpRuntime(ns, user) if err != nil { + glog.Error(resp) return } @@ -268,6 +269,7 @@ func (ctl *NamespaceCtl) listAndWatch() { for _, item := range list { obj := ctl.generateObject(*item) db.Create(obj) + ctl.createRoleAndRuntime(*item) } @@ -277,17 +279,20 @@ func (ctl *NamespaceCtl) listAndWatch() { object := obj.(*v1.Namespace) mysqlObject := ctl.generateObject(*object) db.Create(mysqlObject) + ctl.createRoleAndRuntime(*object) }, UpdateFunc: func(old, new interface{}) { object := new.(*v1.Namespace) mysqlObject := ctl.generateObject(*object) db.Save(mysqlObject) + ctl.createRoleAndRuntime(*object) }, DeleteFunc: func(obj interface{}) { var item Namespace object := obj.(*v1.Namespace) db.Where("name=?", object.Name).Find(&item) db.Delete(item) + ctl.deleteOpRuntime(*object) }, }) diff --git a/pkg/models/controllers/pods.go b/pkg/models/controllers/pods.go index d266adf98..fd929ad4b 100644 --- a/pkg/models/controllers/pods.go +++ b/pkg/models/controllers/pods.go @@ -18,6 +18,7 @@ package controllers import ( "encoding/json" + "fmt" "time" "github.com/golang/glog" @@ -26,8 +27,6 @@ import ( "k8s.io/apimachinery/pkg/labels" "k8s.io/client-go/informers" "k8s.io/client-go/tools/cache" - - "kubesphere.io/kubesphere/pkg/models/metrics" ) const inUse = "in_use_pods" @@ -44,22 +43,24 @@ func (ctl *PodCtl) addAnnotationToPvc(item v1.Pod) { Pvc.Annotations = make(map[string]string) } annotation := Pvc.Annotations + if len(annotation[inUse]) == 0 { pods := []string{item.Name} str, _ := json.Marshal(pods) annotation[inUse] = string(str) } else { var pods []string - json.Unmarshal([]byte(annotation[inUse]), pods) + json.Unmarshal([]byte(annotation[inUse]), &pods) for _, pod := range pods { if pod == item.Name { return } - pods = append(pods, item.Name) - str, _ := json.Marshal(pods) - annotation[inUse] = string(str) } + pods = append(pods, item.Name) + str, _ := json.Marshal(pods) + annotation[inUse] = string(str) } + Pvc.Annotations = annotation ctl.K8sClient.CoreV1().PersistentVolumeClaims(item.Namespace).Update(Pvc) } } @@ -89,13 +90,85 @@ func (ctl *PodCtl) delAnnotationFromPvc(item v1.Pod) { } } +func getStatusAndRestartCount(pod v1.Pod) (string, int) { + status := string(pod.Status.Phase) + restarts := 0 + if pod.Status.Reason != "" { + status = pod.Status.Reason + } + + initializing := false + for i := range pod.Status.InitContainerStatuses { + container := pod.Status.InitContainerStatuses[i] + restarts += int(container.RestartCount) + switch { + case container.State.Terminated != nil && container.State.Terminated.ExitCode == 0: + continue + case container.State.Terminated != nil: + // initialization is failed + if len(container.State.Terminated.Reason) == 0 { + if container.State.Terminated.Signal != 0 { + status = fmt.Sprintf("Init:Signal:%d", container.State.Terminated.Signal) + } else { + status = fmt.Sprintf("Init:ExitCode:%d", container.State.Terminated.ExitCode) + } + } else { + status = "Init:" + container.State.Terminated.Reason + } + initializing = true + case container.State.Waiting != nil && len(container.State.Waiting.Reason) > 0 && container.State.Waiting.Reason != "PodInitializing": + status = "Init:" + container.State.Waiting.Reason + initializing = true + default: + status = fmt.Sprintf("Init:%d/%d", i, len(pod.Spec.InitContainers)) + initializing = true + } + break + } + if !initializing { + restarts = 0 + hasRunning := false + for i := len(pod.Status.ContainerStatuses) - 1; i >= 0; i-- { + container := pod.Status.ContainerStatuses[i] + + restarts += int(container.RestartCount) + if container.State.Waiting != nil && container.State.Waiting.Reason != "" { + status = container.State.Waiting.Reason + } else if container.State.Terminated != nil && container.State.Terminated.Reason != "" { + status = container.State.Terminated.Reason + } else if container.State.Terminated != nil && container.State.Terminated.Reason == "" { + if container.State.Terminated.Signal != 0 { + status = fmt.Sprintf("Signal:%d", container.State.Terminated.Signal) + } else { + status = fmt.Sprintf("ExitCode:%d", container.State.Terminated.ExitCode) + } + } else if container.Ready && container.State.Running != nil { + hasRunning = true + } + } + + // change pod status back to "Running" if there is at least one container still reporting as "Running" status + if status == "Completed" && hasRunning { + status = "Running" + } + } + + if pod.DeletionTimestamp != nil && pod.Status.Reason == "NodeLost" { + status = "Unknown" + } else if pod.DeletionTimestamp != nil { + status = "Terminating" + } + + return status, restarts +} + func (ctl *PodCtl) generateObject(item v1.Pod) *Pod { name := item.Name namespace := item.Namespace podIp := item.Status.PodIP nodeName := item.Spec.NodeName nodeIp := item.Status.HostIP - status := string(item.Status.Phase) + status, restartCount := getStatusAndRestartCount(item) createTime := item.CreationTimestamp.Time containerStatus := item.Status.ContainerStatuses containerSpecs := item.Spec.Containers @@ -118,7 +191,7 @@ func (ctl *PodCtl) generateObject(item v1.Pod) *Pod { } object := &Pod{Namespace: namespace, Name: name, Node: nodeName, PodIp: podIp, Status: status, NodeIp: nodeIp, - CreateTime: createTime, Annotation: Annotation{item.Annotations}, Containers: containers} + CreateTime: createTime, Annotation: Annotation{item.Annotations}, Containers: containers, RestartCount: restartCount} return object } @@ -160,7 +233,7 @@ func (ctl *PodCtl) listAndWatch() { UpdateFunc: func(old, new interface{}) { object := new.(*v1.Pod) mysqlObject := ctl.generateObject(*object) - + ctl.addAnnotationToPvc(*object) db.Save(mysqlObject) }, @@ -191,22 +264,6 @@ func (ctl *PodCtl) ListWithConditions(conditions string, paging *Paging) (int, i listWithConditions(ctl.DB, &total, &object, &list, conditions, paging, order) - ch := make(chan metrics.PodMetrics) - - for index, _ := range list { - go metrics.GetSinglePodMetrics(list[index].Namespace, list[index].Name, ch) - } - - var resultMetrics = make(map[string]metrics.PodMetrics) - for range list { - podMetric := <-ch - resultMetrics[podMetric.PodName] = podMetric - } - - for index, _ := range list { - list[index].Metrics = resultMetrics[list[index].Name] - } - return total, list, nil } diff --git a/pkg/models/controllers/pvcs.go b/pkg/models/controllers/pvcs.go index e1eeb3af3..2c61aa8d7 100644 --- a/pkg/models/controllers/pvcs.go +++ b/pkg/models/controllers/pvcs.go @@ -47,6 +47,9 @@ func (ctl *PvcCtl) generateObject(item *v1.PersistentVolumeClaim) *Pvc { } storageClass := "-" + if len(item.Annotations["volume.beta.kubernetes.io/storage-class"]) > 0 { + storageClass = item.Annotations["volume.beta.kubernetes.io/storage-class"] + } if item.Spec.StorageClassName != nil { storageClass = *item.Spec.StorageClassName } diff --git a/pkg/models/controllers/types.go b/pkg/models/controllers/types.go index 40c58d6f8..4c924ad25 100644 --- a/pkg/models/controllers/types.go +++ b/pkg/models/controllers/types.go @@ -177,16 +177,17 @@ func (Ingress) TableName() string { } type Pod struct { - Name string `gorm:"primary_key" json:"name"` - Namespace string `gorm:"primary_key" json:"namespace"` - Status string `json:"status,omitempty"` - Node string `json:"node,omitempty"` - NodeIp string `json:"nodeIp,omitempty"` - PodIp string `json:"podIp,omitempty"` - Containers Containers `gorm:"type:text" json:"containers,omitempty"` - Annotation Annotation `json:"annotations"` - CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"` - Metrics metrics.PodMetrics `json:"metrics,omitempty"` + Name string `gorm:"primary_key" json:"name"` + Namespace string `gorm:"primary_key" json:"namespace"` + Status string `json:"status,omitempty"` + Node string `json:"node,omitempty"` + NodeIp string `json:"nodeIp,omitempty"` + PodIp string `json:"podIp,omitempty"` + Containers Containers `gorm:"type:text" json:"containers,omitempty"` + Annotation Annotation `json:"annotations"` + RestartCount int `json:"restartCount"` + Metrics metrics.PodMetrics `json:"metrics,omitempty"` + CreateTime time.Time `gorm:"column:createTime" json:"createTime,omitempty"` } type Container struct { diff --git a/pkg/models/kubectl.go b/pkg/models/kubectl.go index 1f725c00b..a3bdb5c22 100644 --- a/pkg/models/kubectl.go +++ b/pkg/models/kubectl.go @@ -129,9 +129,26 @@ func DelKubectlPod(user string) error { if err != nil { return err } - replicas := int32(0) - deploy.Spec.Replicas = &replicas - k8sClient.AppsV1beta2().Deployments(namespace).Update(deploy) + err = k8sClient.AppsV1beta2().Deployments(namespace).Delete(user, &meta_v1.DeleteOptions{}) - return err + if err != nil { + return err + } + + label := labels.SelectorFromSet(labels.Set(deploy.Spec.Selector.MatchLabels)).String() + rsList, err := k8sClient.AppsV1beta2().ReplicaSets(namespace).List(meta_v1.ListOptions{LabelSelector: label}) + if err != nil { + glog.Error(err) + return err + } + + for _, rs := range rsList.Items { + err = k8sClient.AppsV1beta2().ReplicaSets(namespace).Delete(rs.Name, &meta_v1.DeleteOptions{}) + if err != nil { + glog.Error(err) + return err + } + } + + return nil } diff --git a/pkg/models/metrics/pods.go b/pkg/models/metrics/pods.go index 9563ea44f..a09a7af8f 100644 --- a/pkg/models/metrics/pods.go +++ b/pkg/models/metrics/pods.go @@ -94,7 +94,9 @@ func GetPodMetricsInNamespace(namespace string) constants.PageableResponse { options := v1.ListOptions{} podList, _ := k8sClient.CoreV1().Pods(namespace).List(options) - podMetrics.Items = append(podMetrics.Items, GetPodsMetrics(podList)) + for _, podMetric := range GetPodsMetrics(podList) { + podMetrics.Items = append(podMetrics.Items, podMetric) + } podMetrics.TotalCount = len(podMetrics.Items) return podMetrics @@ -107,7 +109,9 @@ func GetPodMetricsInNode(nodeName string) constants.PageableResponse { FieldSelector: "spec.nodeName=" + nodeName, } podList, _ := k8sClient.CoreV1().Pods("").List(options) - podMetrics.Items = append(podMetrics.Items, GetPodsMetrics(podList)) + for _, podMetric := range GetPodsMetrics(podList) { + podMetrics.Items = append(podMetrics.Items, podMetric) + } podMetrics.TotalCount = len(podMetrics.Items) return podMetrics @@ -120,7 +124,9 @@ func GetPodMetricsInNamespaceOfNode(namespace string, nodeName string) constants FieldSelector: "spec.nodeName=" + nodeName + ",metadata.namespace=" + namespace, } podList, _ := k8sClient.CoreV1().Pods("").List(options) - podMetrics.Items = append(podMetrics.Items, GetPodsMetrics(podList)) + for _, podMetric := range GetPodsMetrics(podList) { + podMetrics.Items = append(podMetrics.Items, podMetric) + } podMetrics.TotalCount = len(podMetrics.Items) return podMetrics @@ -131,7 +137,9 @@ func GetAllPodMetrics() constants.PageableResponse { k8sClient := client.NewK8sClient() options := v1.ListOptions{} podList, _ := k8sClient.CoreV1().Pods("").List(options) - podMetrics.Items = append(podMetrics.Items, GetPodsMetrics(podList)) + for _, podMetric := range GetPodsMetrics(podList) { + podMetrics.Items = append(podMetrics.Items, podMetric) + } podMetrics.TotalCount = len(podMetrics.Items) return podMetrics