mirror of
https://github.com/kubevela/kubevela.git
synced 2026-02-14 18:10:21 +00:00
Feat: System diagnose (#4662)
* Feat: System Info & Diagnose Signed-off-by: foursevenlove <foursevenlove@gmail.com> * Fix:1.misspelling 2.license Signed-off-by: foursevenlove <foursevenlove@gmail.com> * Fix: pattern of imported package Signed-off-by: foursevenlove <foursevenlove@gmail.com> * Fix: pattern of imported package Signed-off-by: foursevenlove <foursevenlove@gmail.com> * Fix:1.return error instead of panic 2.get deployment by label instead of by namespace 3.when getting a single deployment, the result is displayed in multi rows. Feat: 1.the system info command displays the cpu and memory metrics 2.the system info command displays the numbers of ready pods and desired pods. * Feat: 1.the system info command displays the environment variables * Fix: Making syntax simple * Feat(system info):1.ARGS多行展示2.指定名称时无须指定namespace3.优化界面展示,支持原始打印或者以wide/yaml形式打印4.指定名称时,打印更可读信息 Signed-off-by: foursevenlove <foursevenlove@gmail.com> * Feat:add comment Signed-off-by: foursevenlove <foursevenlove@gmail.com> * Fix:syntactic redundancy Signed-off-by: foursevenlove <foursevenlove@gmail.com> * Feat:Display all ARGS Signed-off-by: foursevenlove <foursevenlove@gmail.com> * Feat:Display all ARGS Signed-off-by: foursevenlove <foursevenlove@gmail.com> Add signoff * Fix:1.return error instead of panic 2.get deployment by label instead of by namespace 3.when getting a single deployment, the result is displayed in multi rows. Feat: 1.the system info command displays the cpu and memory metrics 2.the system info command displays the numbers of ready pods and desired pods. Signed-off-by: foursevenlove <foursevenlove@gmail.com> * Feat:System diagnose Signed-off-by: foursevenlove <foursevenlove@gmail.com> * Feat:Diagnose cluster-gateway pod's status Signed-off-by: foursevenlove <foursevenlove@gmail.com> Signed-off-by: foursevenlove <foursevenlove@gmail.com>
This commit is contained in:
@@ -29,7 +29,11 @@ import (
|
||||
v1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
apiregistrationV1beta "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1"
|
||||
apiregistration "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1"
|
||||
"k8s.io/metrics/pkg/apis/metrics/v1beta1"
|
||||
metrics "k8s.io/metrics/pkg/client/clientset/versioned"
|
||||
"sigs.k8s.io/yaml"
|
||||
@@ -44,6 +48,8 @@ const (
|
||||
FlagSpecify = "specify"
|
||||
// FlagOutputFormat specifies the output format. One of: (wide | yaml)
|
||||
FlagOutputFormat = "output"
|
||||
// APIServiceName is the name of APIService
|
||||
APIServiceName = "v1alpha1.cluster.core.oam.dev"
|
||||
)
|
||||
|
||||
// NewSystemCommand print system detail info
|
||||
@@ -96,6 +102,16 @@ func NewSystemInfoCommand(c common.Args) *cobra.Command {
|
||||
}
|
||||
}
|
||||
// Get kube config
|
||||
if outputFormat != "" {
|
||||
outputFormatOptions := map[string]struct{}{
|
||||
"wide": {},
|
||||
"yaml": {},
|
||||
}
|
||||
if _, exist := outputFormatOptions[outputFormat]; !exist {
|
||||
return errors.Errorf("Outputformat must in wide | yaml !")
|
||||
}
|
||||
}
|
||||
// Get kube config
|
||||
config, err := c.GetConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -311,26 +327,18 @@ func NewSystemDiagnoseCommand(c common.Args) *cobra.Command {
|
||||
Short: "Diagnoses system problems.",
|
||||
Long: "Diagnoses system problems.",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
// Diagnoses APIService of cluster-gateway
|
||||
// Diagnose clusters' health
|
||||
fmt.Println("------------------------------------------------------")
|
||||
fmt.Println("Diagnosing APIService of cluster-gateway...")
|
||||
fmt.Println("Diagnosing health of clusters...")
|
||||
k8sClient, err := c.GetClient()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get k8s client")
|
||||
}
|
||||
_, err = multicluster.GetClusterGatewayService(context.Background(), k8sClient)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get cluster secret namespace, please ensure cluster gateway is correctly deployed")
|
||||
}
|
||||
fmt.Println("Result: APIService of cluster-gateway is fine~")
|
||||
fmt.Println("------------------------------------------------------")
|
||||
// Diagnose clusters' health
|
||||
fmt.Println("------------------------------------------------------")
|
||||
fmt.Println("Diagnosing health of clusters...")
|
||||
clusters, err := multicluster.ListVirtualClusters(context.Background(), k8sClient)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fail to get registered cluster")
|
||||
}
|
||||
// Get kube config
|
||||
config, err := c.GetConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -348,6 +356,31 @@ func NewSystemDiagnoseCommand(c common.Args) *cobra.Command {
|
||||
}
|
||||
fmt.Println("Result: Clusters are fine~")
|
||||
fmt.Println("------------------------------------------------------")
|
||||
// Diagnoses the link of hub APIServer to cluster-gateway
|
||||
fmt.Println("------------------------------------------------------")
|
||||
fmt.Println("Diagnosing the link of hub APIServer to cluster-gateway...")
|
||||
// Get clientset
|
||||
clientset, err := apiregistration.NewForConfig(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
apiService, err := clientset.APIServices().Get(ctx, APIServiceName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, condition := range apiService.Status.Conditions {
|
||||
if condition.Type == "Available" {
|
||||
if condition.Status != "True" {
|
||||
cmd.Printf("APIService \"%s\" is not available! \nMessage: %s\n", APIServiceName, condition.Message)
|
||||
return CheckAPIService(ctx, config, apiService)
|
||||
}
|
||||
cmd.Printf("APIService \"%s\" is available!\n", APIServiceName)
|
||||
}
|
||||
}
|
||||
fmt.Println("Result: The link of hub APIServer to cluster-gateway is fine~")
|
||||
fmt.Println("------------------------------------------------------")
|
||||
// Todo: Diagnose others
|
||||
return nil
|
||||
},
|
||||
@@ -357,3 +390,39 @@ func NewSystemDiagnoseCommand(c common.Args) *cobra.Command {
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
// CheckAPIService checks the APIService
|
||||
func CheckAPIService(ctx context.Context, config *rest.Config, apiService *apiregistrationV1beta.APIService) error {
|
||||
svcName := apiService.Spec.Service.Name
|
||||
svcNamespace := apiService.Spec.Service.Namespace
|
||||
clientset, err := kubernetes.NewForConfig(config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
svc, err := clientset.CoreV1().Services(svcNamespace).Get(ctx, svcName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
set := labels.Set(svc.Spec.Selector)
|
||||
listOptions := metav1.ListOptions{LabelSelector: set.AsSelector().String()}
|
||||
pods, err := clientset.CoreV1().Pods(svcNamespace).List(ctx, listOptions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(pods.Items) == 0 {
|
||||
return errors.Errorf("No available pods in %s namespace with label %s.", svcNamespace, set.AsSelector().String())
|
||||
}
|
||||
for _, pod := range pods.Items {
|
||||
for _, status := range pod.Status.ContainerStatuses {
|
||||
if !status.Ready {
|
||||
for _, condition := range pod.Status.Conditions {
|
||||
if condition.Status != "True" {
|
||||
return errors.Errorf("Pod %s is not ready. Condition \"%s\" status: %s.", pod.Name, condition.Type, condition.Status)
|
||||
}
|
||||
}
|
||||
return errors.Errorf("Pod %s is not ready.", pod.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user