-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feature initframework and support capacity estimation (#1)
* feat: support capacity estimation Signed-off-by: kaku <[email protected]>
- Loading branch information
Showing
34 changed files
with
3,118 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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] | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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/ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
- [ ] ... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
Oops, something went wrong.