Skip to content

Commit

Permalink
Feature initframework and support capacity estimation (#1)
Browse files Browse the repository at this point in the history
* feat: support capacity estimation

Signed-off-by: kaku <[email protected]>
  • Loading branch information
likakuli authored Jan 19, 2023
1 parent 514f47e commit 72ac9c0
Show file tree
Hide file tree
Showing 34 changed files with 3,118 additions and 3 deletions.
64 changes: 64 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
name: build

on:
# Run this workflow every time a new commit pushed to upstream/fork repository.
# Run workflow on fork repository will help contributors find and resolve issues before sending a PR.
push:
pull_request:
jobs:
golangci:
name: lint
runs-on: ubuntu-18.04
steps:
- name: checkout code
uses: actions/checkout@v2
- name: install Go
uses: actions/setup-go@v2
with:
go-version: 1.19.x
- name: lint
run: hack/verify-staticcheck.sh
- name: import alias
run: hack/verify-import-aliases.sh
fmt:
name: gofmt
runs-on: ubuntu-18.04
steps:
- name: checkout code
uses: actions/checkout@v2
- name: install Go
uses: actions/setup-go@v2
with:
go-version: 1.19.x
- name: go fmt check
run: make fmt-check
vet:
name: go vet
runs-on: ubuntu-18.04
steps:
- name: checkout code
uses: actions/checkout@v2
- name: install Go
uses: actions/setup-go@v2
with:
go-version: 1.19.x
- name: go vet
run: make vet
# test:
# name: unit test
# needs:
# - fmt
# - vet
# runs-on: ubuntu-18.04
# steps:
# - name: checkout code
# uses: actions/checkout@v2
# - name: install Go
# uses: actions/setup-go@v2
# with:
# go-version: 1.19.x
# - name: Run coverage
# run: ./script/test.sh
# - name: Codecov
# uses: codecov/[email protected]

11 changes: 10 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,13 @@
*.out

# Dependency directories (remove the comment below to include it)
# vendor/
vendor/

# binary file
kcluster-capacity

# conf
pod.yaml
schedulerconfig
kubeconfig

1 change: 1 addition & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
Expand Down
116 changes: 116 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# Go information
GO ?= go
GOFMT ?= gofmt "-s"
GOOS ?= $(shell go env GOOS)
GOARCH ?= $(shell go env GOARCH)
SOURCES := $(shell find . -type f -name '*.go')

GOFILES := $(shell find . -name "*.go" | grep -v vendor)
TESTFOLDER := $(shell $(GO) list ./... | grep -v examples)
TESTTAGS ?= ""
VETPACKAGES ?= $(shell $(GO) list ./... | grep -v /examples/)

# Git information
GIT_VERSION ?= $(shell git describe --tags --dirty --always)
GIT_COMMIT_HASH ?= $(shell git rev-parse HEAD)
GIT_TREESTATE = "clean"
GIT_DIFF = $(shell git diff --quiet >/dev/null 2>&1; if [ $$? -eq 1 ]; then echo "1"; fi)
ifeq ($(GIT_DIFF), 1)
GIT_TREESTATE = "dirty"
endif
BUILDDATE = $(shell date -u +'%Y-%m-%dT%H:%M:%SZ')

LDFLAGS := "-X github.com/k-cloud-labs/kluster-capacity/pkg/version.gitVersion=$(GIT_VERSION) \
-X github.com/k-cloud-labs/kluster-capacity/pkg/version.gitCommit=$(GIT_COMMIT_HASH) \
-X github.com/k-cloud-labs/kluster-capacity/pkg/version.gitTreeState=$(GIT_TREESTATE) \
-X github.com/k-cloud-labs/kluster-capacity/pkg/version.buildDate=$(BUILDDATE)"

# Set your version by env or using latest tags from git
VERSION?=""
ifeq ($(VERSION), "")
LATEST_TAG=$(shell git describe --tags --always)
ifeq ($(LATEST_TAG),)
# Forked repo may not sync tags from upstream, so give it a default tag to make CI happy.
VERSION="unknown"
else
VERSION=$(LATEST_TAG)
endif
endif

# Setting SHELL to bash allows bash commands to be executed by recipes.
# This is a requirement for 'setup-envtest.sh' in the test target.
# Options are set to exit when a recipe line exits non-zero or a piped command fails.
SHELL = /usr/bin/env bash -o pipefail
.SHELLFLAGS = -ec

##@ General

# The help target prints out all targets with their descriptions organized
# beneath their categories. The categories are represented by '##@' and the
# target descriptions by '##'. The awk commands is responsible for reading the
# entire set of makefiles included in this invocation, looking for lines of the
# file as xyz: ## something, and then pretty-format the target and help. Then,
# if there's a line with ##@ something, that gets pretty-printed as a category.
# More info on the usage of ANSI control characters for terminal formatting:
# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters
# More info on the awk command:
# http://linuxcommand.org/lc3_adv_awk.php

.PHONY: help
help: ## Display this help.
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)

.PHONY: checkall
checkall: fmt-check vet ## Do all check
hack/verify-staticcheck.sh
hack/verify-import-aliases.sh

.PHONY: kluster-capacity
kluster-capacity: $(SOURCES) ## Build kluster-capacity webhook binary file
@CGO_ENABLED=0 GOOS=$(GOOS) go build \
-ldflags $(LDFLAGS) \
-o kluster-capacity \
main.go

.PHONY: clean
clean: ## Clean kluster-capacity webhook binary file
@rm -rf kluster-capacity

.PHONY: fmt
fmt: ## Format project files
@$(GOFMT) -w $(GOFILES)

.PHONY: fmt-check
fmt-check: ## Check project files format info
@diff=$$($(GOFMT) -d $(GOFILES)); \
if [ -n "$$diff" ]; then \
echo "Please run 'make fmt' and commit the result:"; \
echo "$${diff}"; \
exit 1; \
fi;

.PHONY: vet
vet:
@$(GO) vet $(VETPACKAGES)

.PHONY: test
test: fmt-check vet ## Run project unit test and generate coverage result
echo "mode: count" > coverage.out
for d in $(TESTFOLDER); do \
$(GO) test -tags $(TESTTAGS) -v -covermode=count -coverprofile=profile.out $$d > tmp.out; \
cat tmp.out; \
if grep -q "^--- FAIL" tmp.out; then \
rm tmp.out; \
exit 1; \
elif grep -q "build failed" tmp.out; then \
rm tmp.out; \
exit 1; \
elif grep -q "setup failed" tmp.out; then \
rm tmp.out; \
exit 1; \
fi; \
if [ -f profile.out ]; then \
cat profile.out | grep -v "mode:" >> coverage.out; \
rm profile.out; \
fi; \
done
112 changes: 110 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,110 @@
# kluster-capacity
Cluster capacity tool for capacity estimation、scheduler simulation、cluster compression
# kluster-capacity

![kluster-capacity-logo](docs/images/capacity-management-capacity-icon.jpeg)

[![Build Status](https://github.com/k-cloud-labs/kluster-capacity/actions/workflows/ci.yml/badge.svg)](https://github.com/k-cloud-labs/kluster-capacity/actions?query=workflow%3Abuild)
[![Go Report Card](https://goreportcard.com/badge/github.com/k-cloud-labs/kluster-capacity)](https://goreportcard.com/report/github.com/k-cloud-labs/kluster-capacity)
[![Go doc](https://img.shields.io/badge/go.dev-reference-brightgreen?logo=go&logoColor=white&style=flat)](https://pkg.go.dev/github.com/k-cloud-labs/kluster-capacity)


Cluster capacity tool support capacity estimation、scheduler simulation、cluster compression.
This repository is inspired by https://github.com/kubernetes-sigs/cluster-capacity.
And the code of this repository is based on https://github.com/kubernetes-sigs/cluster-capacity.


## Capacity Estimation
### Intro
As new pods get scheduled on nodes in a cluster, more resources get consumed. Monitoring available resources in the cluster is very important as operators can increase the current resources in time before all of them get exhausted. Or, carry different steps that lead to increase of available resources.

Cluster capacity consists of capacities of individual cluster nodes. Capacity covers CPU, memory, disk space and other resources.

Overall remaining allocatable capacity is a rough estimation since it does not assume all resources being distributed among nodes. Goal is to analyze remaining allocatable resources and estimate available capacity that is still consumable in terms of a number of instances of a pod with given requirements that can be scheduled in a cluster.

### Build and Run

Build the framework:

```sh
$ cd $GOPATH/src/github.com/k-cloud-labs/
$ git clone https://github.com/k-cloud-labs/kluster-capacity
$ cd kluster-capacity
$ make kluster-capacity
```
and run the analysis:

```sh
$ ./kluster-capacity ce --kubeconfig <path to kubeconfig> --pod-template <path to pod template>
```
For more information about available options run:

```sh
$ ./kluster-capacity ce --help
```

### Demonstration

Assuming a cluster is running with 4 nodes and 1 master with each node with 2 CPUs and 4GB of memory.
With pod resource requirements to be `150m` of CPU and ``100Mi`` of Memory.

```sh
$ ./kluster-capacity ce --kubeconfig <path to kubeconfig> --pod-template <path to pod template> --verbose
Pod requirements:
- cpu: 150m
- memory: 100Mi

The cluster can schedule 52 instance(s) of the pod.
Termination reason: FailedScheduling: pod (small-pod-52) failed to fit in any node
fit failure on node (kube-node-1): Insufficient cpu
fit failure on node (kube-node-4): Insufficient cpu
fit failure on node (kube-node-2): Insufficient cpu
fit failure on node (kube-node-3): Insufficient cpu


Pod distribution among nodes:
- kube-node-1: 13 instance(s)
- kube-node-4: 13 instance(s)
- kube-node-2: 13 instance(s)
- kube-node-3: 13 instance(s)
```

Once the number of running pods in the cluster grows and the analysis is run again,
the number of schedulable pods decreases as well:

```sh
$ ./kluster-capacity ce --kubeconfig <path to kubeconfig> --pods-template <path to pod template> --verbose
Pod requirements:
- cpu: 150m
- memory: 100Mi

The cluster can schedule 46 instance(s) of the pod.
Termination reason: FailedScheduling: pod (small-pod-46) failed to fit in any node
fit failure on node (kube-node-1): Insufficient cpu
fit failure on node (kube-node-4): Insufficient cpu
fit failure on node (kube-node-2): Insufficient cpu
fit failure on node (kube-node-3): Insufficient cpu


Pod distribution among nodes:
- kube-node-1: 11 instance(s)
- kube-node-4: 12 instance(s)
- kube-node-2: 11 instance(s)
- kube-node-3: 12 instance(s)
```

### Output format
`ce` command has a flag `--output (-o)` to format its output as json or yaml.

```sh
$ ./kluster-capacity ce --kubeconfig <path to kubeconfig> --pods-template <path to pod template> -o json
$ ./kluster-capacity ce --kubeconfig <path to kubeconfig> --pods-template <path to pod template> -o yaml
```

The json or yaml output is not versioned and is not guaranteed to be stable across various releases.

## Scheduler Simulation


## Cluster Compression

## Feature
- [ ] ...
38 changes: 38 additions & 0 deletions app/cmds/cc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
Copyright © 2023 k-cloud-labs org
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmds

import (
"errors"

"github.com/spf13/cobra"
)

// ccCmd represents the cc command
var ccCmd = &cobra.Command{
Use: "cc",
Short: "cluster compression",
// TODO: add detail usage info
Long: `cluster compression`,
SilenceErrors: false,
RunE: func(cmd *cobra.Command, args []string) error {
return errors.New("not implemented")
},
}

func NewClusterCompressionCmd() *cobra.Command {
return ccCmd
}
Loading

0 comments on commit 72ac9c0

Please sign in to comment.