Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ds 0.3.2 release #618

Merged
merged 4 commits into from
Nov 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions charts/oceanbase-dashboard/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.3.1
version: 0.3.2

# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "0.3.1"
appVersion: "0.3.2"
8 changes: 8 additions & 0 deletions charts/oceanbase-dashboard/templates/cluster-role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ rules:
- endpoints
- pods
verbs: ["get", "list", "watch"]
- apiGroups: ["metrics.k8s.io"]
resources:
- nodes
- nodes/proxy
- services
- endpoints
- pods
verbs: ["get", "list", "watch"]
- apiGroups:
- extensions
resources:
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ require (
k8s.io/apimachinery v0.29.3
k8s.io/client-go v0.29.3
k8s.io/kubernetes v1.27.2
k8s.io/metrics v0.0.0
sigs.k8s.io/controller-runtime v0.15.0
)

Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1004,6 +1004,8 @@ k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7F
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
k8s.io/kubernetes v1.27.2 h1:g4v9oY6u7vBUDEuq4FvC50Bbw2K7GZuvM00IIESWVf4=
k8s.io/kubernetes v1.27.2/go.mod h1:U8ZXeKBAPxeb4J4/HOaxjw1A9K6WfSH+fY2SS7CR6IM=
k8s.io/metrics v0.29.3 h1:nN+eavbMQ7Kuif2tIdTr2/F2ec2E/SIAWSruTZ+Ye6U=
k8s.io/metrics v0.29.3/go.mod h1:kb3tGGC4ZcIDIuvXyUE291RwJ5WmDu0tB4wAVZM6h2I=
k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI=
k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
Expand Down
56 changes: 19 additions & 37 deletions internal/dashboard/business/k8s/k8s.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
storagev1 "k8s.io/api/storage/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
metricsv1beta1 "k8s.io/metrics/pkg/apis/metrics/v1beta1"

"github.com/oceanbase/ob-operator/internal/dashboard/business/common"
"github.com/oceanbase/ob-operator/internal/dashboard/business/constant"
Expand Down Expand Up @@ -105,34 +106,21 @@ func extractNodeConditions(node *corev1.Node) []response.K8sNodeCondition {
return conditions
}

func extractNodeResource(ctx context.Context, node *corev1.Node) *response.K8sNodeResource {
func extractNodeResource(metricsMap map[string]metricsv1beta1.NodeMetrics, node *corev1.Node) *response.K8sNodeResource {
nodeResource := &response.K8sNodeResource{}
metrics, ok := metricsMap[node.Name]
nodeResource.CpuTotal = node.Status.Capacity.Cpu().AsApproximateFloat64()
nodeResource.MemoryTotal = node.Status.Capacity.Memory().AsApproximateFloat64() / constant.GB
podList, err := resource.ListAllPods(ctx)
if err == nil {
cpuRequested := 0.0
memoryRequested := 0.0
for _, pod := range podList.Items {
if !strings.Contains(pod.Spec.NodeName, node.Name) {
continue
}
for _, container := range pod.Spec.Containers {
cpuRequest, found := container.Resources.Requests[ResourceCpu]
if found {
cpuRequested += cpuRequest.AsApproximateFloat64()
}
memoryRequest, found := container.Resources.Requests[ResourceMemory]
if found {
memoryRequested += memoryRequest.AsApproximateFloat64() / constant.GB
}
}
if ok {
if cpuUsed, ok := metrics.Usage[corev1.ResourceCPU]; ok {
nodeResource.CpuUsed = cpuUsed.AsApproximateFloat64()
}
if memoryUsed, ok := metrics.Usage[corev1.ResourceMemory]; ok {
nodeResource.MemoryUsed = memoryUsed.AsApproximateFloat64() / constant.GB
}
nodeResource.CpuUsed = cpuRequested
nodeResource.MemoryUsed = memoryRequested
nodeResource.CpuFree = nodeResource.CpuTotal - nodeResource.CpuUsed
nodeResource.MemoryFree = nodeResource.MemoryTotal - nodeResource.MemoryUsed
}
nodeResource.CpuFree = nodeResource.CpuTotal - nodeResource.CpuUsed
nodeResource.MemoryFree = nodeResource.MemoryTotal - nodeResource.MemoryUsed
return nodeResource
}

Expand Down Expand Up @@ -222,6 +210,7 @@ func ListEvents(ctx context.Context, queryEventParam *param.QueryEventParam) ([]
func ListNodes(ctx context.Context) ([]response.K8sNode, error) {
nodes := make([]response.K8sNode, 0)
nodeList, err := resource.ListNodes(ctx)
nodeMetricsMap, metricsErr := resource.ListNodeMetrics(ctx)
if err == nil {
for _, node := range nodeList.Items {
internalAddress, externalAddress := extractNodeAddress(&node)
Expand All @@ -240,28 +229,21 @@ func ListNodes(ctx context.Context) ([]response.K8sNode, error) {
CRI: node.Status.NodeInfo.ContainerRuntimeVersion,
}

nodeResource := &response.K8sNodeResource{}
if metricsErr == nil {
nodeResource = extractNodeResource(nodeMetricsMap, &node)
} else {
logger.Errorf("Got error when list node metrics, err: %v", metricsErr)
}
nodes = append(nodes, response.K8sNode{
Info: nodeInfo,
Resource: extractNodeResource(ctx, &node),
Resource: nodeResource,
})
}
}
return nodes, err
}

func ListNodeResources(ctx context.Context) ([]response.K8sNodeResource, error) {
nodeList, err := resource.ListNodes(ctx)
if err != nil {
return nil, err
}
nodeResources := make([]response.K8sNodeResource, 0, len(nodeList.Items))
for _, node := range nodeList.Items {
nodeResource := extractNodeResource(ctx, &node)
nodeResources = append(nodeResources, *nodeResource)
}
return nodeResources, nil
}

func ListStorageClasses(ctx context.Context) ([]response.StorageClass, error) {
storageClasses := make([]response.StorageClass, 0)
storageClassList, err := resource.ListStorageClasses(ctx)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ See the Mulan PSL v2 for more details.
package constant

const (
MetricConfigFile = "internal/assets/metric.yaml"
MetricConfigFileEnUS = "internal/assets/metric_en_US.yaml"
MetricConfigFileZhCN = "internal/assets/metric_zh_CN.yaml"
MetricExprConfigFile = "internal/assets/metric_expr.yaml"
MetricConfigFile = "internal/assets/dashboard/metric.yaml"
MetricConfigFileEnUS = "internal/assets/dashboard/metric_en_US.yaml"
MetricConfigFileZhCN = "internal/assets/dashboard/metric_zh_CN.yaml"
MetricExprConfigFile = "internal/assets/dashboard/metric_expr.yaml"
)

const (
Expand Down
79 changes: 66 additions & 13 deletions internal/dashboard/business/oceanbase/obcluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,12 +203,28 @@ func buildOBClusterTopologyResp(ctx context.Context, obcluster *v1alpha1.OBClust
affinities := make([]modelcommon.AffinitySpec, 0)
if obzone.Spec.Topology.Affinity != nil {
zoneAffinity := obzone.Spec.Topology.Affinity
switch {
case zoneAffinity.NodeAffinity != nil:
for _, term := range zoneAffinity.NodeAffinity.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms {
for _, req := range term.MatchExpressions {
if zoneAffinity.NodeAffinity != nil {
zn := zoneAffinity.NodeAffinity
if zn.RequiredDuringSchedulingIgnoredDuringExecution != nil {
for _, term := range zn.RequiredDuringSchedulingIgnoredDuringExecution.NodeSelectorTerms {
for _, req := range term.MatchExpressions {
affinities = append(affinities, modelcommon.AffinitySpec{
Type: modelcommon.NodeAffinityType,
SelectorExpression: modelcommon.SelectorExpression{
Key: req.Key,
Operator: string(req.Operator),
Values: req.Values,
},
})
}
}
}
for _, term := range zn.PreferredDuringSchedulingIgnoredDuringExecution {
for _, req := range term.Preference.MatchExpressions {
affinities = append(affinities, modelcommon.AffinitySpec{
Type: modelcommon.NodeAffinityType,
Type: modelcommon.NodeAffinityType,
Weight: term.Weight,
Preferred: true,
SelectorExpression: modelcommon.SelectorExpression{
Key: req.Key,
Operator: string(req.Operator),
Expand All @@ -217,8 +233,10 @@ func buildOBClusterTopologyResp(ctx context.Context, obcluster *v1alpha1.OBClust
})
}
}
case zoneAffinity.PodAffinity != nil:
for _, term := range zoneAffinity.PodAffinity.RequiredDuringSchedulingIgnoredDuringExecution {
}
if zoneAffinity.PodAffinity != nil {
zp := zoneAffinity.PodAffinity
for _, term := range zp.RequiredDuringSchedulingIgnoredDuringExecution {
for _, req := range term.LabelSelector.MatchExpressions {
affinities = append(affinities, modelcommon.AffinitySpec{
Type: modelcommon.PodAffinityType,
Expand All @@ -230,8 +248,24 @@ func buildOBClusterTopologyResp(ctx context.Context, obcluster *v1alpha1.OBClust
})
}
}
case zoneAffinity.PodAntiAffinity != nil:
for _, term := range zoneAffinity.PodAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution {
for _, term := range zp.PreferredDuringSchedulingIgnoredDuringExecution {
for _, req := range term.PodAffinityTerm.LabelSelector.MatchExpressions {
affinities = append(affinities, modelcommon.AffinitySpec{
Type: modelcommon.PodAffinityType,
Weight: term.Weight,
Preferred: true,
SelectorExpression: modelcommon.SelectorExpression{
Key: req.Key,
Operator: string(req.Operator),
Values: req.Values,
},
})
}
}
}
if zoneAffinity.PodAntiAffinity != nil {
zpa := zoneAffinity.PodAntiAffinity
for _, term := range zpa.RequiredDuringSchedulingIgnoredDuringExecution {
for _, req := range term.LabelSelector.MatchExpressions {
affinities = append(affinities, modelcommon.AffinitySpec{
Type: modelcommon.PodAntiAffinityType,
Expand All @@ -243,14 +277,33 @@ func buildOBClusterTopologyResp(ctx context.Context, obcluster *v1alpha1.OBClust
})
}
}
for _, term := range zpa.PreferredDuringSchedulingIgnoredDuringExecution {
for _, req := range term.PodAffinityTerm.LabelSelector.MatchExpressions {
affinities = append(affinities, modelcommon.AffinitySpec{
Type: modelcommon.PodAntiAffinityType,
Weight: term.Weight,
Preferred: true,
SelectorExpression: modelcommon.SelectorExpression{
Key: req.Key,
Operator: string(req.Operator),
Values: req.Values,
},
})
}
}
}
}

tolerations := make([]modelcommon.KVPair, 0)
tolerations := make([]modelcommon.TolerationSpec, 0)
for _, toleration := range obzone.Spec.Topology.Tolerations {
tolerations = append(tolerations, modelcommon.KVPair{
Key: toleration.Key,
Value: toleration.Value,
tolerations = append(tolerations, modelcommon.TolerationSpec{
KVPair: modelcommon.KVPair{
Key: toleration.Key,
Value: toleration.Value,
},
Operator: string(toleration.Operator),
Effect: string(toleration.Effect),
TolerationSeconds: toleration.TolerationSeconds,
})
}
respZone := response.OBZone{
Expand Down
9 changes: 9 additions & 0 deletions internal/dashboard/model/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,15 @@ type AffinityType string
type AffinitySpec struct {
SelectorExpression `json:",inline"`
Type AffinityType `json:"type"`
Weight int32 `json:"weight,omitempty"`
Preferred bool `json:"preferred,omitempty"`
}

type TolerationSpec struct {
KVPair `json:",inline"`
Operator string `json:"operator"`
Effect string `json:"effect"`
TolerationSeconds *int64 `json:"tolerationSeconds,omitempty"`
}

type ClusterMode string
4 changes: 2 additions & 2 deletions internal/dashboard/model/response/obcluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ type OBZone struct {
OBServers []OBServer `json:"observers,omitempty"`
NodeSelector []common.KVPair `json:"nodeSelector,omitempty"`

Tolerations []common.KVPair `json:"tolerations,omitempty"`
Affinities []common.AffinitySpec `json:"affinities,omitempty"`
Tolerations []common.TolerationSpec `json:"tolerations,omitempty"`
Affinities []common.AffinitySpec `json:"affinities,omitempty"`
}

type OBMetrics struct {
Expand Down
4 changes: 2 additions & 2 deletions make/dashboard.mk
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ PROJECT=oceanbase-dashboard
PROCESSOR=4
PWD ?= $(shell pwd)

DASHBOARD_VERSION ?= 0.3.1
DASHBOARD_VERSION ?= 0.3.2
DASHBOARD_IMG ?= quay.io/oceanbase/oceanbase-dashboard:${DASHBOARD_VERSION}
COMMIT_HASH ?= $(shell git rev-parse --short HEAD)
BUILD_TIMESTAMP ?= $(shell date '+%Y%m%d%H%M%S')
Expand All @@ -31,7 +31,7 @@ dashboard-build: dashboard-bindata-gen dashboard-doc-gen ## Build oceanbase-dash

.PHONY: dashboard-bindata-gen
dashboard-bindata-gen: dashboard-dep-install ## Generate bindata
go-bindata -o internal/dashboard/generated/bindata/bindata.go -pkg bindata internal/assets/...
go-bindata -o internal/dashboard/generated/bindata/bindata.go -pkg bindata internal/assets/dashboard/...

.PHONY: dashboard-clean
dashboard-clean: ## Clean build
Expand Down
23 changes: 15 additions & 8 deletions pkg/k8s/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,15 @@ import (
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/metadata"
"k8s.io/client-go/rest"
"k8s.io/metrics/pkg/client/clientset/versioned"
)

type Client struct {
ClientSet *kubernetes.Clientset
DynamicClient dynamic.Interface
MetaClient metadata.Interface
config *rest.Config
ClientSet *kubernetes.Clientset
DynamicClient dynamic.Interface
MetaClient metadata.Interface
MetricsClientset *versioned.Clientset
config *rest.Config
}

var client *Client
Expand Down Expand Up @@ -75,11 +77,16 @@ func getClientFromConfig(config *rest.Config) (*Client, error) {
if err != nil {
return nil, errors.Wrap(err, "failed to create meta client")
}
metricsClientset, err := versioned.NewForConfig(config)
if err != nil {
return nil, errors.Wrap(err, "failed to create metrics client")
}
return &Client{
ClientSet: clientset,
DynamicClient: dynamicClient,
MetaClient: metaClient,
config: config,
ClientSet: clientset,
DynamicClient: dynamicClient,
MetaClient: metaClient,
MetricsClientset: metricsClientset,
config: config,
}, nil
}

Expand Down
15 changes: 15 additions & 0 deletions pkg/k8s/resource/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (

corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metricsv1beta1 "k8s.io/metrics/pkg/apis/metrics/v1beta1"

"github.com/oceanbase/ob-operator/pkg/k8s/client"
k8sconst "github.com/oceanbase/ob-operator/pkg/k8s/constants"
Expand All @@ -30,3 +31,17 @@ func ListNodes(ctx context.Context) (*corev1.NodeList, error) {
TimeoutSeconds: &timeout,
})
}

func ListNodeMetrics(ctx context.Context) (map[string]metricsv1beta1.NodeMetrics, error) {
client := client.GetClient()
nodeMetricsMap := make(map[string]metricsv1beta1.NodeMetrics)
metricsList, err := client.MetricsClientset.MetricsV1beta1().NodeMetricses().List(ctx, metav1.ListOptions{
TimeoutSeconds: &timeout,
})
if err == nil {
for _, metrics := range metricsList.Items {
nodeMetricsMap[metrics.Name] = metrics
}
}
return nodeMetricsMap, err
}
Loading
Loading