Skip to content

Commit cb2365e

Browse files
authored
add missing docs (external scheduler and plugin extender) (#287)
* add missing docs (external scheduler and plugin extender) * fix minor point * fix based on the suggestion * fix broken import * add the important note on the top
1 parent 9540f5d commit cb2365e

File tree

16 files changed

+509
-260
lines changed

16 files changed

+509
-260
lines changed

README.md

Lines changed: 65 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -9,32 +9,81 @@ Nowadays, the scheduler is configurable/extendable in the multiple ways:
99
- etc...
1010

1111
But, unfortunately, not all configurations/expansions yield good results.
12-
Those who customize the scheduler need to make sure their scheduler is working as expected, and doesn't have an unacceptably negative impact on the scheduling.
12+
Those who customize the scheduler need to make sure their scheduler is working as expected,
13+
and doesn't have an unacceptably negative impact on the scheduling.
1314

14-
In real Kubernetes, we cannot know the results of scheduling in detail without reading the logs, which usually requires privileged access to the control plane.
15-
That's why we are developing a simulator for kube-scheduler -- you can try out the behavior of the scheduler with web UI while checking which plugin made what decision for which Node.
15+
In real Kubernetes, we cannot know the results of scheduling in detail without reading the logs,
16+
which usually requires privileged access to the control plane.
17+
18+
That's why we are developing a simulator for kube-scheduler
19+
-- you can try out the behavior of the scheduler while checking which plugin made what decision for which Node.
1620

1721
## Simulator's architecture
1822

1923
We have several components:
20-
- Simulator (in `/simulator`)
21-
- Web UI (in `/web`)
24+
- Simulator (in `/simulator`): the core implementation of the simulator
25+
- Web UI (in `/web`): the Web client of the simulator
2226
- Coming soon... :) (see [./keps](./keps) to see some nice ideas we're working on)
2327

2428
### Simulator
2529

26-
Simulator internally has kube-apiserver, scheduler, and HTTP server.
30+
Simulator is kube-apiserver + scheduler + the HTTP server which mainly for the web UI.
31+
32+
There are several ways to integrate your scheduler into the simulator.
33+
See [integrate-your-scheduler.md](simulator/docs/integrate-your-scheduler.md).
34+
35+
You can create any resources by communicating with kube-apiserver in any ways (kubectl, k8s client library, or web UI described next)
36+
and see how scheduling is done.
37+
38+
When you create Pods, Pods will get annotations from the simulator which contains the scheduling results per plugins or extenders.
39+
40+
```yaml
41+
kind: Pod
42+
apiVersion: v1
43+
metadata:
44+
name: hoge-pod
45+
annotations:
46+
scheduler-simulator/bind-result: '{"DefaultBinder":"success"}'
47+
scheduler-simulator/filter-result: >-
48+
{"node-282x7":{"AzureDiskLimits":"passed","EBSLimits":"passed","GCEPDLimits":"passed","InterPodAffinity":"passed","NodeAffinity":"passed","NodeName":"passed","NodePorts":"passed","NodeResourcesFit":"passed","NodeUnschedulable":"passed","NodeVolumeLimits":"passed","PodTopologySpread":"passed","TaintToleration":"passed","VolumeBinding":"passed","VolumeRestrictions":"passed","VolumeZone":"passed"},"node-gp9t4":{"AzureDiskLimits":"passed","EBSLimits":"passed","GCEPDLimits":"passed","InterPodAffinity":"passed","NodeAffinity":"passed","NodeName":"passed","NodePorts":"passed","NodeResourcesFit":"passed","NodeUnschedulable":"passed","NodeVolumeLimits":"passed","PodTopologySpread":"passed","TaintToleration":"passed","VolumeBinding":"passed","VolumeRestrictions":"passed","VolumeZone":"passed"}}
49+
scheduler-simulator/finalscore-result: >-
50+
{"node-282x7":{"ImageLocality":"0","InterPodAffinity":"0","NodeAffinity":"0","NodeNumber":"0","NodeResourcesBalancedAllocation":"76","NodeResourcesFit":"73","PodTopologySpread":"200","TaintToleration":"300","VolumeBinding":"0"},"node-gp9t4":{"ImageLocality":"0","InterPodAffinity":"0","NodeAffinity":"0","NodeNumber":"0","NodeResourcesBalancedAllocation":"76","NodeResourcesFit":"73","PodTopologySpread":"200","TaintToleration":"300","VolumeBinding":"0"}}
51+
scheduler-simulator/permit-result: '{}'
52+
scheduler-simulator/permit-result-timeout: '{}'
53+
scheduler-simulator/postfilter-result: '{}'
54+
scheduler-simulator/prebind-result: '{"VolumeBinding":"success"}'
55+
scheduler-simulator/prefilter-result: '{}'
56+
scheduler-simulator/prefilter-result-status: >-
57+
{"InterPodAffinity":"success","NodeAffinity":"success","NodePorts":"success","NodeResourcesFit":"success","PodTopologySpread":"success","VolumeBinding":"success","VolumeRestrictions":"success"}
58+
scheduler-simulator/prescore-result: >-
59+
{"InterPodAffinity":"success","NodeAffinity":"success","NodeNumber":"success","PodTopologySpread":"success","TaintToleration":"success"}
60+
scheduler-simulator/reserve-result: '{"VolumeBinding":"success"}'
61+
scheduler-simulator/result-history: >-
62+
[{"noderesourcefit-prefilter-data":"{\"MilliCPU\":100,\"Memory\":17179869184,\"EphemeralStorage\":0,\"AllowedPodNumber\":0,\"ScalarResources\":null}","scheduler-simulator/bind-result":"{\"DefaultBinder\":\"success\"}","scheduler-simulator/filter-result":"{\"node-282x7\":{\"AzureDiskLimits\":\"passed\",\"EBSLimits\":\"passed\",\"GCEPDLimits\":\"passed\",\"InterPodAffinity\":\"passed\",\"NodeAffinity\":\"passed\",\"NodeName\":\"passed\",\"NodePorts\":\"passed\",\"NodeResourcesFit\":\"passed\",\"NodeUnschedulable\":\"passed\",\"NodeVolumeLimits\":\"passed\",\"PodTopologySpread\":\"passed\",\"TaintToleration\":\"passed\",\"VolumeBinding\":\"passed\",\"VolumeRestrictions\":\"passed\",\"VolumeZone\":\"passed\"},\"node-gp9t4\":{\"AzureDiskLimits\":\"passed\",\"EBSLimits\":\"passed\",\"GCEPDLimits\":\"passed\",\"InterPodAffinity\":\"passed\",\"NodeAffinity\":\"passed\",\"NodeName\":\"passed\",\"NodePorts\":\"passed\",\"NodeResourcesFit\":\"passed\",\"NodeUnschedulable\":\"passed\",\"NodeVolumeLimits\":\"passed\",\"PodTopologySpread\":\"passed\",\"TaintToleration\":\"passed\",\"VolumeBinding\":\"passed\",\"VolumeRestrictions\":\"passed\",\"VolumeZone\":\"passed\"}}","scheduler-simulator/finalscore-result":"{\"node-282x7\":{\"ImageLocality\":\"0\",\"InterPodAffinity\":\"0\",\"NodeAffinity\":\"0\",\"NodeNumber\":\"0\",\"NodeResourcesBalancedAllocation\":\"76\",\"NodeResourcesFit\":\"73\",\"PodTopologySpread\":\"200\",\"TaintToleration\":\"300\",\"VolumeBinding\":\"0\"},\"node-gp9t4\":{\"ImageLocality\":\"0\",\"InterPodAffinity\":\"0\",\"NodeAffinity\":\"0\",\"NodeNumber\":\"0\",\"NodeResourcesBalancedAllocation\":\"76\",\"NodeResourcesFit\":\"73\",\"PodTopologySpread\":\"200\",\"TaintToleration\":\"300\",\"VolumeBinding\":\"0\"}}","scheduler-simulator/permit-result":"{}","scheduler-simulator/permit-result-timeout":"{}","scheduler-simulator/postfilter-result":"{}","scheduler-simulator/prebind-result":"{\"VolumeBinding\":\"success\"}","scheduler-simulator/prefilter-result":"{}","scheduler-simulator/prefilter-result-status":"{\"InterPodAffinity\":\"success\",\"NodeAffinity\":\"success\",\"NodePorts\":\"success\",\"NodeResourcesFit\":\"success\",\"PodTopologySpread\":\"success\",\"VolumeBinding\":\"success\",\"VolumeRestrictions\":\"success\"}","scheduler-simulator/prescore-result":"{\"InterPodAffinity\":\"success\",\"NodeAffinity\":\"success\",\"NodeNumber\":\"success\",\"PodTopologySpread\":\"success\",\"TaintToleration\":\"success\"}","scheduler-simulator/reserve-result":"{\"VolumeBinding\":\"success\"}","scheduler-simulator/score-result":"{\"node-282x7\":{\"ImageLocality\":\"0\",\"InterPodAffinity\":\"0\",\"NodeAffinity\":\"0\",\"NodeNumber\":\"0\",\"NodeResourcesBalancedAllocation\":\"76\",\"NodeResourcesFit\":\"73\",\"PodTopologySpread\":\"0\",\"TaintToleration\":\"0\",\"VolumeBinding\":\"0\"},\"node-gp9t4\":{\"ImageLocality\":\"0\",\"InterPodAffinity\":\"0\",\"NodeAffinity\":\"0\",\"NodeNumber\":\"0\",\"NodeResourcesBalancedAllocation\":\"76\",\"NodeResourcesFit\":\"73\",\"PodTopologySpread\":\"0\",\"TaintToleration\":\"0\",\"VolumeBinding\":\"0\"}}","scheduler-simulator/selected-node":"node-282x7"}]
63+
scheduler-simulator/score-result: >-
64+
{"node-282x7":{"ImageLocality":"0","InterPodAffinity":"0","NodeAffinity":"0","NodeNumber":"0","NodeResourcesBalancedAllocation":"76","NodeResourcesFit":"73","PodTopologySpread":"0","TaintToleration":"0","VolumeBinding":"0"},"node-gp9t4":{"ImageLocality":"0","InterPodAffinity":"0","NodeAffinity":"0","NodeNumber":"0","NodeResourcesBalancedAllocation":"76","NodeResourcesFit":"73","PodTopologySpread":"0","TaintToleration":"0","VolumeBinding":"0"}}
65+
scheduler-simulator/selected-node: node-282x7
66+
```
67+
68+
You can utilize these results to understand your scheduler, check/test your configurations or customized scheduler's behavior.
2769
28-
You can create any resources by communicating with kube-apiserver via kubectl, k8s client library, or web UI.
70+
Further expansion, you can export internal state more, change specific behaviours on plugins etc by implementing [PluginExtender](./simulator/docs/plugin-extender.md).
71+
72+
The simulator has its own configuration,
73+
you can refer to the [documentation](./simulator/docs/simulator-server-config.md).
2974
3075
See the following docs to know more about simulator:
3176
- [how-it-works.md](simulator/docs/how-it-works.md): describes about how the simulator works.
3277
- [kube-apiserver.md](simulator/docs/kube-apiserver.md): describe about kube-apiserver in simulator. (how you can configure and access)
33-
- [api.md](simulator/docs/api.md): describes about HTTP server the simulator has.
78+
- [api.md](simulator/docs/api.md): describes about HTTP server the simulator has. (mainly for the webUI)
3479
3580
### Web UI
3681
37-
Web UI is one of the clients of simulator, but it's optimized for simulator.
82+
It's well-optimized Web UI for the simulator.
83+
84+
Web UI is the best way to check the scheduler's behavior very easily.
85+
Nice table view for the scheduling result, the scheduler configuration reload feature, etc...
86+
every core features of the simulator can be access with human-friendly ways!
3887
3988
From the web, you can create/edit/delete these resources to simulate a cluster.
4089
@@ -48,7 +97,7 @@ From the web, you can create/edit/delete these resources to simulate a cluster.
4897
4998
![list resources](simulator/docs/images/resources.png)
5099
51-
You can create resources with yaml file as usual.
100+
It has a cool yaml editor to create/edit resources.
52101
53102
![create node](simulator/docs/images/create-node.png)
54103
@@ -60,27 +109,14 @@ And, after pods are scheduled, you can see the results of
60109
61110
![result](simulator/docs/images/result.jpg)
62111
63-
You can configure the scheduler on the simulator through KubeSchedulerConfiguration.
64-
65-
[Scheduler Configuration | Kubernetes](https://kubernetes.io/docs/reference/scheduling/config/)
112+
Also, You can change the configuration of the scheduler through [KubeSchedulerConfiguration](https://kubernetes.io/docs/reference/scheduling/config/).
66113
67-
You can pass a path to KubeSchedulerConfiguration via the environment variable `KUBE_SCHEDULER_CONFIG_PATH` and the simulator will start kube-scheduler with that configuration.
68-
69-
Note: changes to any fields other than `.profiles` are disabled on simulator, since they do not affect the results of the scheduling.
114+
(Note: changes to any fields other than `.profiles` are disabled on simulator, since they do not affect the results of the scheduling.)
70115

71116
![configure scheduler](simulator/docs/images/schedulerconfiguration.png)
72117

73-
If you want to use your custom plugins as out-of-tree plugins in the simulator, please follow [this doc](simulator/docs/how-to-use-custom-plugins/README.md).
74-
75118
## Getting started
76119

77-
You can find more information about environment variables available in the simulator server
78-
[here.](./simulator/docs/environment-variables.md)
79-
80-
81-
The simulator server configuration can also be set through the configuration file,
82-
you can refer to the [documentation](./simulator/docs/simulator-server-config.md).
83-
84120
### Run simulator with Docker
85121

86122
We have [docker-compose.yml](docker-compose.yml) to run the simulator easily. You should install [docker](https://docs.docker.com/engine/install/) and [docker-compose](https://docs.docker.com/compose/install/) firstly.
@@ -101,7 +137,7 @@ Please allocate enough memory in that case.
101137

102138
You have to run frontend, server and etcd.
103139

104-
#### Run simulator server and etcd
140+
#### 1. Run simulator server and etcd
105141

106142
To run this simulator's server, you have to install Go and etcd.
107143

@@ -114,12 +150,13 @@ make start
114150

115151
It starts etcd and simulator-server locally.
116152

117-
#### Run simulator frontend
153+
#### 2. Run simulator frontend
118154

119155
To run the frontend, please see [README.md](web/README.md) on ./web dir.
120156

121-
## [Beta] Existing cluster importing
157+
## Beta features
122158

159+
### [Beta] Existing cluster importing
123160

124161
The simulator can import resources from your cluster.
125162
You can use it by setting an `EXTERNAL_IMPORT_ENABLED` environment variable to `1`.

simulator/docs/custom-plugin.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
## How to use your custom plugins in the simulator
2+
3+
This doc describes how to use your custom plugins in the scheduler running in the simulator.
4+
5+
### 1. Add your custom plugin's registry in OutOfTreeRegistries function.
6+
7+
Please add your custom plugin's registry in `outOfTreeRegistries` in config package here:
8+
9+
[kube-scheduler-simulator/simulator/scheduler/config/plugin.go](/simulator/scheduler/config/plugin.go)
10+
11+
### 2. Configure the scheduler to enable your custom plugin
12+
13+
You can configure the scheduler to use your custom plugins through KubeSchedulerConfiguration.
14+
15+
[Scheduler Configuration | Kubernetes](https://kubernetes.io/docs/reference/scheduling/config/)
16+
17+
You can change the scheduler configuration in Web UI or
18+
by passing a default KubeSchedulerConfiguration file via the environment variable `KUBE_SCHEDULER_CONFIG_PATH`.
19+
20+
### Example
21+
22+
We will explain the case where you want to add [nodenumber](../sample/nodenumber/plugin.go) plugin as example.
23+
24+
The nodenumber plugin is an example plugin that favors nodes that have the number suffix which is the same as the number suffix of the pod name.
25+
And we can configure it via `NodeNumberArgs`.
26+
27+
First, you need to add registry for the nodenumber plugin to `outOfTreeRegistries`.
28+
29+
```go
30+
outOfTreeRegistries = runtime.Registry{
31+
// TODO(user): add your plugins registries here.
32+
nodenumber.Name: nodenumber.New,
33+
}
34+
```
35+
36+
Now you can use the nodenumber plugin in the simulator.
37+
38+
If you apply this configuration to the scheduler, you can see the nodenumber plugin is working (and NodeNumberArgs is applied to the nodenumber plugin) in the simulator,
39+
and see the nodenumber plugin's result like other in-tree plugins.
40+
41+
```yaml
42+
kind: KubeSchedulerConfiguration
43+
apiVersion: kubescheduler.config.k8s.io/v1
44+
# ....
45+
profiles:
46+
- schedulerName: default-scheduler
47+
plugins:
48+
# ....
49+
multiPoint:
50+
enabled:
51+
# ....
52+
- name: NodeNumber # added
53+
weight: 10
54+
```
55+
56+
![result](images/result-nodenumber.jpg)

simulator/docs/environment-variables.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
1-
# Environment Variables
1+
## [deprecated] Environment Variables
22

3-
This page describes the environment variables that are used to configure the simulator.
4-
5-
Please refer to [docker-compose.yml](./../../docker-compose.yml) as an example use.
3+
**Deprecation notice**: We're planning to remove the configuration via environment variables.
4+
Until deprecation, the simulator will read the configuration in the environment variable first,
5+
if the environment variable is not set, it will read the configuration in the configuration file.
6+
For config file, please refer to the simulator [config.yaml](./../config.yaml).
67

7-
## For Simulator
8+
---
89

9-
**Deprecation notice**: We're planning to remove the configuration via environment variables.
10+
This page describes the environment variables that are used to configure the simulator.
1011

11-
Until deprecation, the simulator will read the configuration in the environment variable first,
12-
if the environment variable is not set, it will read the configuration in the configuration file.
12+
Please refer to [docker-compose.yml](./../../docker-compose.yml) as an example use.
1313

14-
For config file, please refer to the simulator [config.yaml](./../config.yaml).
14+
### For Simulator
1515

1616
`PORT`: (required) This is the port number on which kube-scheduler-simulator
1717
server is started.
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
## External scheduler
2+
3+
This document describes how to use the external scheduler instead of the scheduler running in the simulator.
4+
5+
We use the [`externalscheduler` package](../pkg/externalscheduler);
6+
the scheduler built with the [`externalscheduler` package](../pkg/externalscheduler) will export the scheduling results on each Pod annotation.
7+
8+
### Use cases
9+
10+
- Running your scheduler instead of the default one in the simulator
11+
- You can still see the scheduling results in web UI as well!
12+
- Running your scheduler with the simulator feature in your cluster
13+
- All Pods, scheduled by this scheduler, will get the scheduler results on its annotation while each scheduling is done as usual.
14+
- Note that it has performance overhead in each scheduling cycle
15+
since the scheduler needs to make additional effort to export the scheduling results.
16+
17+
### Change your scheduler
18+
19+
Here, we assume you're registering your custom plugins in your scheduler like this:
20+
21+
```go
22+
// your scheduler's main package
23+
func main() {
24+
command := app.NewSchedulerCommand(
25+
app.WithPlugin(yourcustomplugin.Name, yourcustomplugin.New),
26+
)
27+
28+
code := cli.Run(command)
29+
os.Exit(code)
30+
}
31+
```
32+
33+
Then, you need to replace few lines to use the [`externalscheduler` package](../pkg/externalscheduler).
34+
35+
```go
36+
func main() {
37+
command, cancelFn, err := externalscheduler.NewSchedulerCommand(
38+
externalscheduler.WithPlugin(yourcustomplugin.Name, yourcustomplugin.New),
39+
externalscheduler.WithPluginExtenders(noderesources.Name, extender.New), // [optional] see plugin-extender.md about PluginExtender.
40+
)
41+
if err != nil {
42+
klog.Info(fmt.Sprintf("failed to build the scheduler command: %+v", err))
43+
os.Exit(1)
44+
}
45+
code := cli.Run(command)
46+
cancelFn()
47+
os.Exit(code)
48+
}
49+
```
50+
51+
As you see, `externalscheduler.NewSchedulerCommand` has much similar interface as the `app.NewSchedulerCommand`.
52+
You can register your plugins by `externalscheduler.WithPlugin` option.
53+
54+
Via this step, all Pods scheduled by this scheduler will get the scheduling results in the annotation like in the simulator!
55+
56+
### Connect your scheduler to the kube-apiserver in the simulator
57+
58+
If you are here to run the scheduler built with [`externalscheduler` package](../pkg/externalscheduler) in your cluster,
59+
you don't need to follow this step.
60+
61+
Let's connect your scheduler into the simulator.
62+
63+
First, you need to set `externalSchedulerEnabled: true` on [the simulator config](../config.yaml)
64+
so that the scheduler in the simulator won't get started.
65+
66+
Next, you need to connect your scheduler into the simulator's kube-apiserver via KubeSchedulerConfig:
67+
68+
```yaml
69+
kind: KubeSchedulerConfiguration
70+
apiVersion: kubescheduler.config.k8s.io/v1
71+
clientConnection:
72+
kubeconfig: ./path/to/kubeconfig.yaml
73+
```
74+
75+
You can use this [kubeconfig.yaml](./kubeconfig.yaml) to communicate with the simulator's kube-apiserver.
76+
77+
### The example external scheduler
78+
79+
We have the sample external scheduler implementation in [./sample/external-scheduler](./sample/external-scheduler).
80+
81+
prerequisite:
82+
1. set `externalSchedulerEnabled: true` on [the simulator config](../config.yaml)
83+
2. run the simulator
84+
85+
```shell
86+
cd sample/external-scheduler
87+
go run main.go --config scheduler.yaml
88+
```
89+
90+
You'll see the simulator is working with the external scheduler.

0 commit comments

Comments
 (0)