Skip to content
This repository has been archived by the owner on Nov 3, 2023. It is now read-only.

Commit

Permalink
PMM-7652 Resource Calculator: add disk part for minikube and EKS (#156)
Browse files Browse the repository at this point in the history
Add ability to get available/total disk size for minikube and eks.
  • Loading branch information
Jan Prukner committed Mar 29, 2021
1 parent 1284f92 commit 4a6c29c
Show file tree
Hide file tree
Showing 15 changed files with 584 additions and 80 deletions.
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ go 1.15

require (
github.com/AlekSi/pointer v1.1.0
github.com/avast/retry-go v3.0.0+incompatible
github.com/google/uuid v1.2.0
github.com/grpc-ecosystem/go-grpc-middleware v1.2.2
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
github.com/hashicorp/go-version v1.2.0
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/percona-platform/dbaas-api v0.0.0-20210328175343-759c17a8159f
github.com/percona-platform/dbaas-api v0.0.0-20210329112158-1d3454914a79
github.com/percona-platform/saas v0.0.0-20201127072600-f1ffa53f7871
github.com/percona/pmm v2.15.1-0.20210318204615-bbf8e9314afd+incompatible
github.com/pkg/errors v0.9.1
Expand Down
16 changes: 8 additions & 8 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hC
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHSxpiH9JdtuBj0=
github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
github.com/aws/aws-sdk-go v1.27.0 h1:0xphMHGMLBrPMfxR2AmVjZKcMEESEgWF8Kru94BNByk=
github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
Expand Down Expand Up @@ -234,14 +236,12 @@ github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh
github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
github.com/percona-platform/dbaas-api v0.0.0-20210321220339-30c981da6087 h1:oDaIEi+DmX7+VBwRq9YkHIyHiIzHni9X7UCW2jS/WF0=
github.com/percona-platform/dbaas-api v0.0.0-20210321220339-30c981da6087/go.mod h1:YS1v1YWwqJd4JaD9wUtNaOSpJPHzIwS9YTWdl3M8hHk=
github.com/percona-platform/dbaas-api v0.0.0-20210321224817-89840197027c h1:6qgZpO7LPLNqmYpONc8E7RQE70uc6g29/MRT4ihFiec=
github.com/percona-platform/dbaas-api v0.0.0-20210321224817-89840197027c/go.mod h1:YS1v1YWwqJd4JaD9wUtNaOSpJPHzIwS9YTWdl3M8hHk=
github.com/percona-platform/dbaas-api v0.0.0-20210321231621-1721399776b2 h1:Z6EYeQ0sjMt2bo/hupST7ma/kzs9SoptHQ4xPq2ih40=
github.com/percona-platform/dbaas-api v0.0.0-20210321231621-1721399776b2/go.mod h1:YS1v1YWwqJd4JaD9wUtNaOSpJPHzIwS9YTWdl3M8hHk=
github.com/percona-platform/dbaas-api v0.0.0-20210328175343-759c17a8159f h1:zJPu/Qxwl885B86n8+h58veZH2/KJFezPXZ8yCFyQtQ=
github.com/percona-platform/dbaas-api v0.0.0-20210328175343-759c17a8159f/go.mod h1:YS1v1YWwqJd4JaD9wUtNaOSpJPHzIwS9YTWdl3M8hHk=
github.com/percona-platform/dbaas-api v0.0.0-20210322144728-186062445c94 h1:aGuFweTLvc7AQMbzuGy29V6eE2/ck/iSFINIJl3WnT8=
github.com/percona-platform/dbaas-api v0.0.0-20210322144728-186062445c94/go.mod h1:YS1v1YWwqJd4JaD9wUtNaOSpJPHzIwS9YTWdl3M8hHk=
github.com/percona-platform/dbaas-api v0.0.0-20210329093136-9eb831cb0dcf h1:FISvoi9XfKnzk6/536OJXU1LvcwLZBFFQ1OkkrJkHa8=
github.com/percona-platform/dbaas-api v0.0.0-20210329093136-9eb831cb0dcf/go.mod h1:YS1v1YWwqJd4JaD9wUtNaOSpJPHzIwS9YTWdl3M8hHk=
github.com/percona-platform/dbaas-api v0.0.0-20210329112158-1d3454914a79 h1:mgv5cJvIM89mAchVKr2gv47DSDkOVIBevPyEpIsq+Ck=
github.com/percona-platform/dbaas-api v0.0.0-20210329112158-1d3454914a79/go.mod h1:YS1v1YWwqJd4JaD9wUtNaOSpJPHzIwS9YTWdl3M8hHk=
github.com/percona-platform/saas v0.0.0-20201127072600-f1ffa53f7871 h1:ZZ0kr0qHypQwWUdxkZU+FNcbxr3XEoeONGOTNAxHvkg=
github.com/percona-platform/saas v0.0.0-20201127072600-f1ffa53f7871/go.mod h1:FrPTFbFWkDaTwvfjRCsaqC5UYgBar+BUOJUzbQl1q5c=
github.com/percona/pmm v2.15.1-0.20210318204615-bbf8e9314afd+incompatible h1:Jgfznlzuy1RTUjb4ooEt8fzHjkqRDSHZ2U1rFnqa7fA=
Expand Down
1 change: 1 addition & 0 deletions packages.dot
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
digraph packages {
"/service/cluster" -> "/service/k8sclient";
"/service/cluster" -> "/service/k8sclient/common";
"/service/k8sclient" -> "/service/k8sclient/common";
"/service/k8sclient" -> "/service/k8sclient/internal/kubectl";
"/service/k8sclient" -> "/service/k8sclient/internal/psmdb";
Expand Down
41 changes: 37 additions & 4 deletions service/cluster/kubernetes_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"google.golang.org/grpc/status"

"github.com/percona-platform/dbaas-controller/service/k8sclient"
"github.com/percona-platform/dbaas-controller/service/k8sclient/common"
)

var operatorStatusesMap = map[k8sclient.OperatorStatus]controllerv1beta1.OperatorsStatus{
Expand Down Expand Up @@ -84,24 +85,56 @@ func (k KubernetesClusterService) GetResources(ctx context.Context, req *control
}
defer k8sClient.Cleanup() //nolint:errcheck

allCPUMillis, allMemoryBytes, _, err := k8sClient.GetAllClusterResources(ctx)
// Get cluster type
clusterType := k8sClient.GetKubernetesClusterType(ctx)
var volumes *common.PersistentVolumeList
if clusterType == k8sclient.AmazonEKSClusterType {
volumes, err = k8sClient.GetPersistentVolumes(ctx)
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
}
}
allCPUMillis, allMemoryBytes, allDiskBytes, err := k8sClient.GetAllClusterResources(ctx, clusterType, volumes)
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
}

consumedCPUMillis, consumedMemoryBytes, err := k8sClient.GetConsumedCPUAndMemory(ctx)
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
}

consumedCPUMillis, consumedMemoryBytes, _, err := k8sClient.GetConsumedResources(ctx, "")
consumedDiskBytes, err := k8sClient.GetConsumedDiskBytes(ctx, clusterType, volumes)
if err != nil {
return nil, status.Error(codes.Internal, err.Error())
}

availableCPUMillis := allCPUMillis - consumedCPUMillis
// handle underflow
if availableCPUMillis > allCPUMillis {
availableCPUMillis = 0
}
availableMemoryBytes := allMemoryBytes - consumedMemoryBytes
// handle underflow
if availableMemoryBytes > allMemoryBytes {
availableMemoryBytes = 0
}
availableDiskBytes := allDiskBytes - consumedDiskBytes
// handle underflow
if availableDiskBytes > allDiskBytes {
availableDiskBytes = 0
}

return &controllerv1beta1.GetResourcesResponse{
All: &controllerv1beta1.Resources{
CpuM: allCPUMillis,
MemoryBytes: allMemoryBytes,
DiskSize: allDiskBytes,
},
Available: &controllerv1beta1.Resources{
CpuM: allCPUMillis - consumedCPUMillis,
MemoryBytes: allMemoryBytes - consumedMemoryBytes,
CpuM: availableCPUMillis,
MemoryBytes: availableMemoryBytes,
DiskSize: availableDiskBytes,
},
}, nil
}
4 changes: 2 additions & 2 deletions service/cluster/psmdb_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func (s *PSMDBClusterService) ListPSMDBClusters(ctx context.Context, req *contro
params := &controllerv1beta1.PSMDBClusterParams{
ClusterSize: cluster.Size,
Replicaset: &controllerv1beta1.PSMDBClusterParams_ReplicaSet{
DiskSize: diskSizeBytes,
DiskSize: int64(diskSizeBytes),
},
}
if cluster.Replicaset.ComputeResources != nil {
Expand All @@ -90,7 +90,7 @@ func (s *PSMDBClusterService) ListPSMDBClusters(ctx context.Context, req *contro
}
params.Replicaset.ComputeResources = &controllerv1beta1.ComputeResources{
CpuM: int32(cpuMillis),
MemoryBytes: memoryBytes,
MemoryBytes: int64(memoryBytes),
}
}
res.Clusters[i] = &controllerv1beta1.ListPSMDBClustersResponse_Cluster{
Expand Down
8 changes: 4 additions & 4 deletions service/cluster/xtra_db_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,10 +78,10 @@ func (s *XtraDBClusterService) ListXtraDBClusters(ctx context.Context, req *cont
params := &controllerv1beta1.XtraDBClusterParams{
ClusterSize: cluster.Size,
Pxc: &controllerv1beta1.XtraDBClusterParams_PXC{
DiskSize: pxcDiskSize,
DiskSize: int64(pxcDiskSize),
},
Proxysql: &controllerv1beta1.XtraDBClusterParams_ProxySQL{
DiskSize: proxySQLDiskSize,
DiskSize: int64(proxySQLDiskSize),
},
}
if cluster.PXC.ComputeResources != nil {
Expand All @@ -95,7 +95,7 @@ func (s *XtraDBClusterService) ListXtraDBClusters(ctx context.Context, req *cont
}
params.Pxc.ComputeResources = &controllerv1beta1.ComputeResources{
CpuM: int32(cpuMillis),
MemoryBytes: memoryBytes,
MemoryBytes: int64(memoryBytes),
}
}
if cluster.ProxySQL.ComputeResources != nil {
Expand All @@ -109,7 +109,7 @@ func (s *XtraDBClusterService) ListXtraDBClusters(ctx context.Context, req *cont
}
params.Proxysql.ComputeResources = &controllerv1beta1.ComputeResources{
CpuM: int32(cpuMillis),
MemoryBytes: memoryBytes,
MemoryBytes: int64(memoryBytes),
}
}
res.Clusters[i] = &controllerv1beta1.ListXtraDBClustersResponse_Cluster{
Expand Down
88 changes: 86 additions & 2 deletions service/k8sclient/common/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,25 @@ type EmptyDirVolumeSource struct{}

// ContainerStatus contains container's status.
type ContainerStatus struct {
Name string `json:"name,omitempty"`
State map[string]interface{} `json:"state,omitempty"`
Name string `json:"name,omitempty"`
State map[string]struct{} `json:"state,omitempty"`
}

// ContainerSpec represents a container definition.
type ContainerSpec struct {
Name string `json:"name,omitempty"`
Image string `json:"image,omitempty"`
Resources ResourceRequirements `json:"resources,omitempty"`
}

// PodVolumePersistentVolumeClaim represents PVC of volume mounted to a pod.
type PodVolumePersistentVolumeClaim struct{}

// PodVolume holds info about volume attached to pod.
type PodVolume struct {
PersistentVolumeClaim *PodVolumePersistentVolumeClaim `json:"persistentVolumeClaim,omitempty"`
}

// PodSpec is a description of a pod.
type PodSpec struct {
// NodeName is a request to schedule this pod onto a specific node. If it is non-empty,
Expand All @@ -63,6 +72,9 @@ type PodSpec struct {

// List of init containers.
InitContainers []ContainerSpec `json:"initContainers,omitempty"`

// Volumes stores list of volumes used by pod.
Volumes []PodVolume `json:"volumes,omitempty"`
}

// PodPhase defines Pod's phase.
Expand All @@ -83,6 +95,10 @@ const (
// and at least one container has terminated in failure. That is,
// the container either exited with non-zero status or was terminated by the system.
PodPhaseFailed PodPhase = "Failed"
// PodPhaseRunning indicates that the Pod has been bound to a node, and all
// of the containers have been created. At least one container is still running,
// or is in the process of starting or restarting.
PodPhaseRunning PodPhase = "Running"
)

// ContainerState describes container's state - waiting, running, terminated.
Expand Down Expand Up @@ -164,12 +180,54 @@ const (
SecretTypeOpaque SecretType = "Opaque"
)

type (
// NodeConditionType represents type of condition Node can get into.
NodeConditionType string
// NodeConditionStatus represents status of Node's condition.
NodeConditionStatus string
)

const (
// NodeConditionStatusTrue represents status when a Node's condition is true.
NodeConditionStatusTrue NodeConditionStatus = "True"
// NodeConditionDiskPressure indicates if Node has enough free disk space.
// If this condition is True, it means Node has less free space then defined.
// The Node then tries to free space by deleting unused images first. If more
// disk space is needed after that, it starts evicting pods.
NodeConditionDiskPressure NodeConditionType = "DiskPressure"
)

// NodeCondition holds Node's condition.
type NodeCondition struct {
// Type of condition.
Type NodeConditionType `json:"type,omitempty"`
// Status of the condition could be "True", "False" or "Unknown".
Status NodeConditionStatus `json:"status,omitempty"`
}

// IsNodeInCondition returns true if node's condition given as an argument has
// status "True". Otherwise it returns false.
func IsNodeInCondition(node Node, conditionType NodeConditionType) bool {
for _, condition := range node.Status.Conditions {
if condition.Status == NodeConditionStatusTrue && condition.Type == conditionType {
return true
}
}
return false
}

// NodeStatus holds Kubernetes node status.
type NodeStatus struct {
// Allocatable is amount of recources from node's capacity that is available
// for allocation by pods. The difference between capacity and allocatable of
// the node is reserved for Kubernetes overhead and non-Kubernetes processes.
Allocatable ResourceList `json:"allocatable,omitempty"`

// Images is a list of container images stored at node.
Images []Image `json:"images,omitempty"`

// Conditions stores node's conditions.
Conditions []NodeCondition `json:"conditions,omitempty"`
}

// Taint reserves node for pods that tolerate the taint.
Expand All @@ -179,6 +237,12 @@ type Taint struct {
Key string `json:"key,omitempty"`
}

// Image holds continaer image names and image size.
type Image struct {
Names []string `json:"names,omitempty"`
SizeBytes int64 `json:"sizeBytes,omitempty"`
}

// NodeSpec holds Kubernetes node specification.
type NodeSpec struct {
Taints []Taint `json:"taints,omitempty"`
Expand All @@ -187,8 +251,28 @@ type NodeSpec struct {
// Node holds information about Kubernetes node.
type Node struct {
TypeMeta
ObjectMeta `json:"metadata,omitempty"`
// Specification of the node.
Spec NodeSpec `json:"spec,omitempty"`
// Status of the node.
Status NodeStatus `json:"status,omitempty"`
}

// PersistentVolumeCapacity holds string representation of storage size.
type PersistentVolumeCapacity struct {
// Storage size as string.
Storage string `json:"storage,omitempty"`
}

// PersistentVolumeSpec holds PV specs.
type PersistentVolumeSpec struct {
// Capacity of the volume.
Capacity PersistentVolumeCapacity `json:"capacity,omitempty"`
}

// PersistentVolume holds information about PV.
type PersistentVolume struct {
TypeMeta
// Specification of the volume.
Spec PersistentVolumeSpec `json:"spec,omitempty"`
}
26 changes: 25 additions & 1 deletion service/k8sclient/common/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,5 +142,29 @@ const (
type NodeList struct {
TypeMeta // anonymous for embedding

Items []Node `json:"items"`
Items []Node `json:"items,omitempty"`
}

// PersistentVolumeList holds a list of persistent volume objects.
type PersistentVolumeList struct {
TypeMeta // anonymous for embedding

Items []PersistentVolume `json:"items,omitempty"`
}

// NodeFileSystemSummary holds a summary of Node's filesystem.
type NodeFileSystemSummary struct {
UsedBytes uint64 `json:"usedBytes,omitempty"`
}

// NodeSummaryNode holds information about Node inside Node's summary.
type NodeSummaryNode struct {
FileSystem NodeFileSystemSummary `json:"fs,omitempty"`
}

// NodeSummary holds summary of the Node.
// One gets this by requesting Kubernetes API endpoint:
// /v1/nodes/<node-name>/proxy/stats/summary.
type NodeSummary struct {
Node NodeSummaryNode `json:"node,omitempty"`
}

0 comments on commit 4a6c29c

Please sign in to comment.