Skip to content

Commit

Permalink
Merge pull request #6 from ElisaOyj/addreadme
Browse files Browse the repository at this point in the history
add readme
  • Loading branch information
zetaab authored Sep 16, 2021
2 parents 7905abb + 636edd4 commit 3b6f02f
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 10 deletions.
97 changes: 96 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,96 @@
# resource-advisor
# Kubernetes Resource Advisor

### Installation

```
export PLUGIN_VERSION=1.0.4
# MacOS (x86_64)
curl -sLo /usr/local/bin/kubectl-advisory https://github.com/ElisaOyj/kubernetes-resource-advisor/releases/download/${PLUGIN_VERSION}/resource-advisor-darwin-amd64
# MacOS (M1)
curl -sLo /usr/local/bin/kubectl-advisory https://github.com/ElisaOyj/kubernetes-resource-advisor/releases/download/${PLUGIN_VERSION}/resource-advisor-darwin-arm64
# Linux (x86_64)
curl -sLo /usr/local/bin/kubectl-advisory https://github.com/ElisaOyj/kubernetes-resource-advisor/releases/download/${PLUGIN_VERSION}/resource-advisor-linux-amd64
# All
chmod 755 /usr/local/bin/kubectl-advisory
```

You need to store the binary under PATH to make it usable as kubectl plugin.

### Usage

```
kubectl advisory --help
I0916 13:28:02.492261 96935 start.go:23] Starting application...
Kubernetes resource-advisor
Usage:
resource-advisor [flags]
Flags:
-h, --help help for resource-advisor
--limit-margin string Limit margin (default "1.2")
--namespace-selector string Namespace selector
--namespaces string Comma separated namespaces to be scanned
--quantile string Quantile to be used (default "0.95")
```

```
% kubectl advisory
I0916 13:26:56.442083 96863 start.go:23] Starting application...
Namespaces: logging
Quantile: 0.95
Limit margin: 1.2
+-----------+----------------------+------------+--------------------+--------------------+------------------+------------------+
| NAMESPACE | RESOURCE | CONTAINER | REQUEST CPU (SPEC) | REQUEST MEM (SPEC) | LIMIT CPU (SPEC) | LIMIT MEM (SPEC) |
+-----------+----------------------+------------+--------------------+--------------------+------------------+------------------+
| logging | daemonset/fluent-bit | fluent-bit | 10m (25m) | 100Mi (100Mi) | 100m (400m) | 100Mi (200Mi) |
+-----------+----------------------+------------+--------------------+--------------------+------------------+------------------+
Total savings:
You could save 0.32 vCPUs and 102.0 MB Memory by changing the settings
```

What these numbers mean? The idea of this tool is to find out `quantile` (default is 95%) CPU & memory real usage for single POD using Prometheus operator. We use that real usage value for specifying `requests`. Then there is another variable called `limit-margin` which is used for specifying `limits`. The default settings means that 95% of time the POD has quarantee for the resources, and 5% of time it uses burstable capacity between 95% -> 120% of POD maximum usage in history.


#### Using namespace-selector

```
% kubectl advisory --namespace-selector maintainer=a_crowd_devops
I0916 14:37:52.758305 5980 start.go:23] Starting application...
Namespaces: actions-runner-system,cert-manager,default,gha,kaas-test-infra
Quantile: 0.95
Limit margin: 1.2
+-----------------------+-------------------------------------------------+-----------------+--------------------+--------------------+------------------+------------------+
| NAMESPACE | RESOURCE | CONTAINER | REQUEST CPU (SPEC) | REQUEST MEM (SPEC) | LIMIT CPU (SPEC) | LIMIT MEM (SPEC) |
+-----------------------+-------------------------------------------------+-----------------+--------------------+--------------------+------------------+------------------+
| actions-runner-system | deployment/gha-exporter | gha-exporter | 10m (<nil>) | 100Mi (<nil>) | 10m (<nil>) | 100Mi (<nil>) |
| actions-runner-system | deployment/ghe-runner-actions-runner-controller | manager | 10m (<nil>) | 100Mi (<nil>) | 10m (<nil>) | 100Mi (<nil>) |
| actions-runner-system | deployment/ghe-runner-actions-runner-controller | kube-rbac-proxy | 10m (<nil>) | 100Mi (<nil>) | 10m (<nil>) | 100Mi (<nil>) |
| cert-manager | deployment/cert-manager | cert-manager | 10m (<nil>) | 100Mi (<nil>) | 10m (<nil>) | 100Mi (<nil>) |
| cert-manager | deployment/cert-manager-cainjector | cert-manager | 10m (<nil>) | 100Mi (<nil>) | 10m (<nil>) | 200Mi (<nil>) |
| cert-manager | deployment/cert-manager-webhook | cert-manager | 10m (<nil>) | 100Mi (<nil>) | 10m (<nil>) | 100Mi (<nil>) |
| kaas-test-infra | deployment/kaas-test-infra | kaas-test-infra | 10m (100m) | 100Mi (200Mi) | 10m (400m) | 100Mi (600Mi) |
+-----------------------+-------------------------------------------------+-----------------+--------------------+--------------------+------------------+------------------+
Total savings:
You could save 0.12 vCPUs and -380.6 MB Memory by changing the settings
```

#### Using as library

```
import "github.com/ElisaOyj/kubernetes-resource-advisor/pkg/advisor"
...
response, err := advisor.Run(&advisor.Options{
Namespaces: "logging,monitoring",
})
```

### Motivation

As SRE team we are seeing all the time Kubernetes clusters in which developers are requesting too much / too low amount of CPU or memory to PODs. In big environments this can lead to huge overhead - PODs are requesting the CPU/mem but not using it. That was motivation for this tool, by this tool we can check the real usage of CPU/memory of pod and change the requests/limits accordingly.
22 changes: 16 additions & 6 deletions pkg/advisor/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,18 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func (o *Options) loadDefaults() {
if o.Quantile == "" {
o.Quantile = "0.95"
}
if o.LimitMargin == "" {
o.LimitMargin = "1.2"
}
}

// Run executes the resource advisor
func Run(o *Options) (*Response, error) {
o.loadDefaults()
var err error
if o.Client == nil {
o.Client, err = newClientSet()
Expand All @@ -41,26 +51,26 @@ func Run(o *Options) (*Response, error) {
for _, name := range namespaces.Items {
strNamespace = append(strNamespace, name.Name)
}
o.Namespaces = strings.Join(strNamespace, ",")
} else if o.NamespaceInput != "" {
o.Namespaces = o.NamespaceInput
o.usedNamespaces = strings.Join(strNamespace, ",")
} else if o.Namespaces != "" {
o.usedNamespaces = o.Namespaces
} else {
_, namespace, err := findConfig()
if err != nil {
return nil, err
}
o.Namespaces = namespace
o.usedNamespaces = namespace
}

fmt.Printf("Namespaces: %s\n", o.Namespaces)
fmt.Printf("Namespaces: %s\n", o.usedNamespaces)
fmt.Printf("Quantile: %s\n", o.Quantile)
fmt.Printf("Limit margin: %s\n", o.LimitMargin)

data := [][]string{}

totalCPUSave := float64(0.00)
totalMemSave := float64(0.00)
for _, namespace := range strings.Split(o.Namespaces, ",") {
for _, namespace := range strings.Split(o.usedNamespaces, ",") {
deployments, err := o.Client.AppsV1().Deployments(namespace).List(ctx, metav1.ListOptions{})
if err != nil {
return nil, err
Expand Down
3 changes: 1 addition & 2 deletions pkg/advisor/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ func init() {
func Execute() {
options := &Options{}
flag.Lookup("logtostderr").Value.Set("true")
glog.Infof("Starting application...\n")
glog.Flush()
rootCmd := &cobra.Command{
Use: "resource-advisor",
Expand All @@ -36,7 +35,7 @@ func Execute() {
},
}

rootCmd.Flags().StringVar(&options.NamespaceInput, "namespaces", "", "Comma separated namespaces to be scanned")
rootCmd.Flags().StringVar(&options.Namespaces, "namespaces", "", "Comma separated namespaces to be scanned")
rootCmd.Flags().StringVar(&options.NamespaceSelector, "namespace-selector", "", "Namespace selector")
rootCmd.Flags().StringVar(&options.Quantile, "quantile", "0.95", "Quantile to be used")
rootCmd.Flags().StringVar(&options.LimitMargin, "limit-margin", "1.2", "Limit margin")
Expand Down
2 changes: 1 addition & 1 deletion pkg/advisor/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (

// Options contains struct to call resource-advisor run
type Options struct {
NamespaceInput string
usedNamespaces string
NamespaceSelector string
Namespaces string
Quantile string
Expand Down
6 changes: 6 additions & 0 deletions pkg/advisor/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,9 @@ func (o *Options) findPods(ctx context.Context, namespace string, selector strin
for k, v := range totalRequestCPU {
scale := 10
value := float64Peak(v)
if value < 0.01 {
scale = 100
}
final.RequestCPU[k] = math.Ceil(value*float64(scale)) / float64(scale)
}
for k, v := range totalRequestMem {
Expand All @@ -294,6 +297,9 @@ func (o *Options) findPods(ctx context.Context, namespace string, selector strin
for k, v := range totalLimitCPU {
scale := 10
value := float64Peak(v)
if value < 0.01 {
scale = 100
}
final.LimitCPU[k] = math.Ceil(value*float64(scale)) / float64(scale)
}
for k, v := range totalLimitMem {
Expand Down

0 comments on commit 3b6f02f

Please sign in to comment.