Skip to content

Commit

Permalink
add annotator and code clean up
Browse files Browse the repository at this point in the history
  • Loading branch information
kelseyhightower committed Aug 19, 2016
1 parent c5e45d3 commit f5b0348
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 18 deletions.
77 changes: 66 additions & 11 deletions README.md
Expand Up @@ -4,27 +4,82 @@ Toy scheduler for use in Kubernetes demos.

## Usage

Annotate each node using the annotator command:

```
kubectl proxy
```
```
Starting to serve on 127.0.0.1:8001
```

```
go run annotator/main.go
```
```
gke-k0-default-pool-728d327f-00lq 1.60
gke-k0-default-pool-728d327f-3vzg 0.20
gke-k0-default-pool-728d327f-nmz7 0.80
gke-k0-default-pool-728d327f-pxee 0.05
gke-k0-default-pool-728d327f-xm4i 0.05
gke-k0-default-pool-728d327f-zynj 0.20
```

### Create a deployment

```
kubectl create -f deployments/nginx.yaml
```
```
kubectl get nodes
deployment "nginx" created
```

The nginx pod should be in a pending state:

```
kubectl get pods
```
```
NAME STATUS AGE
gke-testing-default-pool-5b24138e-iw9u Ready 14d
gke-testing-default-pool-5b24138e-tudj Ready 14d
gke-testing-default-pool-5b24138e-vobb Ready 14d
NAME READY STATUS RESTARTS AGE
nginx-1431970305-mwghf 0/1 Pending 0 27s
```

### Run the Scheduler

List the nodes and note the price of each node.

```
annotator -l
```
kubectl annotate nodes --overwrite \
gke-testing-default-pool-5b24138e-iw9u kubernetes.io/cost=0.05
```
gke-k0-default-pool-728d327f-00lq 0.80
gke-k0-default-pool-728d327f-3vzg 0.40
gke-k0-default-pool-728d327f-nmz7 0.40
gke-k0-default-pool-728d327f-pxee 0.05
gke-k0-default-pool-728d327f-xm4i 1.60
gke-k0-default-pool-728d327f-zynj 0.40
```

Run the best price scheduler:

```
kubectl annotate nodes --overwrite \
gke-testing-default-pool-5b24138e-tudj kubernetes.io/cost=0.20
scheduler
```
```
2016/08/19 11:16:25 Starting custom scheduler...
2016/08/19 11:16:28 Successfully assigned nginx-1431970305-mwghf to gke-k0-default-pool-728d327f-pxee
2016/08/19 11:16:35 Shutdown signal received, exiting...
2016/08/19 11:16:35 Stopped reconciliation loop.
2016/08/19 11:16:35 Stopped scheduler.
```

> Notice the pending nginx pod is deployed to the node with the lowest cost.
## Run the Scheduler on Kubernetes

```
kubectl create -f deployments/scheduler.yaml
```
kubectl annotate nodes --overwrite \
gke-testing-default-pool-5b24138e-vobb kubernetes.io/cost=1.60
```
deployment "scheduler" created
```
101 changes: 101 additions & 0 deletions annotator/main.go
@@ -0,0 +1,101 @@
package main

import (
"bytes"
"encoding/json"
"flag"
"fmt"
"math/rand"
"net/http"
"os"
"time"
)

var listOnly bool

type NodeList struct {
Items []Node `json:"items"`
}

type Node struct {
Metadata Metadata `json:"metadata"`
}

type Metadata struct {
Name string `json:"name,omitempty"`
Annotations map[string]string `json:"annotations"`
}

func main() {
flag.BoolVar(&listOnly, "l", false, "List current annotations and exist")
flag.Parse()

prices := []string{"0.05", "0.10", "0.20", "0.40", "0.80", "1.60"}
resp, err := http.Get("http://127.0.0.1:8001/api/v1/nodes")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
if resp.StatusCode != 200 {
fmt.Println("Invalid status code", resp.Status)
os.Exit(1)
}

var nodes NodeList
decoder := json.NewDecoder(resp.Body)
err = decoder.Decode(&nodes)
if err != nil {
fmt.Println(err)
os.Exit(1)
}

if listOnly {
for _, node := range nodes.Items {
price := node.Metadata.Annotations["hightower.com/cost"]
fmt.Printf("%s %s\n", node.Metadata.Name, price)
}
os.Exit(0)
}

rand.Seed(time.Now().Unix())
for _, node := range nodes.Items {
price := prices[rand.Intn(len(prices))]
annotations := map[string]string{
"hightower.com/cost": price,
}
patch := Node{
Metadata{
Annotations: annotations,
},
}

var b []byte
body := bytes.NewBuffer(b)
err := json.NewEncoder(body).Encode(patch)
if err != nil {
fmt.Println(err)
os.Exit(1)
}

url := "http://127.0.0.1:8001/api/v1/nodes/" + node.Metadata.Name
request, err := http.NewRequest("PATCH", url, body)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
request.Header.Set("Content-Type", "application/strategic-merge-patch+json")
request.Header.Set("Accept", "application/json, */*")

resp, err := http.DefaultClient.Do(request)
if err != nil {
fmt.Println(err)
os.Exit(1)
}

if resp.StatusCode != 200 {
fmt.Println(err)
os.Exit(1)
}
fmt.Printf("%s %s\n", node.Metadata.Name, price)
}
}
4 changes: 3 additions & 1 deletion bestprice.go
Expand Up @@ -13,7 +13,9 @@

package main

import "strconv"
import (
"strconv"
)

func bestPrice(nodes []Node) (Node, error) {
type NodePrice struct {
Expand Down
4 changes: 2 additions & 2 deletions build-container
@@ -1,4 +1,4 @@
GOOS=linux bash build
docker build -t kelseyhightower/scheduler:0.2.0 .
docker push kelseyhightower/scheduler:0.2.0
docker build -t kelseyhightower/scheduler:0.4.0 .
docker push kelseyhightower/scheduler:0.4.0
rm scheduler
6 changes: 3 additions & 3 deletions deployments/nginx.yaml
Expand Up @@ -16,8 +16,8 @@ spec:
spec:
containers:
- name: nginx
image: "nginx:1.11"
image: "nginx:1.11.1-alpine"
resources:
requests:
cpu: "200m"
memory: "64M"
cpu: "500m"
memory: "128M"
2 changes: 1 addition & 1 deletion deployments/scheduler.yaml
Expand Up @@ -14,7 +14,7 @@ spec:
spec:
containers:
- name: scheduler
image: kelseyhightower/scheduler:0.2.0
image: kelseyhightower/scheduler:0.4.0
- name: kubectl
image: kelseyhightower/kubectl:1.3.4
args:
Expand Down

0 comments on commit f5b0348

Please sign in to comment.