-
Notifications
You must be signed in to change notification settings - Fork 5.1k
auto-pause addon: automatically pause Kubernetes when not in use #10427
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
26 commits
Select commit
Hold shift + click to select a range
72135d7
add auto pause proxy
medyagh a3f5f75
change port
medyagh 5dfc304
rename
medyagh 8412efb
add addons
medyagh 44a256b
add auto-pause binary
medyagh 191e116
autopause prototype
medyagh 21d9f50
adding channels
medyagh 8739e20
update addon name
medyagh adc9d9e
add auto-pause to docker image
medyagh 8df298f
fix build
medyagh 175dbcf
add auto-pause to kic image
medyagh d047b97
add assets
medyagh 549bb10
update kicbase with pause
medyagh a162f26
spell
medyagh 8a65288
add helpers to enable disable autopause
medyagh 1bd0b6d
add final touch
medyagh 50642f4
fix kubecontext
medyagh 48c5f1e
rename func
medyagh 43cf3fa
fix build
medyagh 7f3b2c2
addres review comments
medyagh 7377228
address review comments
medyagh 4a6f00b
add todo with issue numbers
medyagh e9e81ce
bump kicbase
medyagh f272822
bump kic base
medyagh 0030bb0
lint
medyagh c6668b9
lint
medyagh File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or 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 |
|---|---|---|
|
|
@@ -26,6 +26,7 @@ _testmain.go | |
| *.test | ||
| *.prof | ||
|
|
||
| /deploy/kicbase/auto-pause | ||
| /out | ||
| /_gopath | ||
|
|
||
|
|
||
This file contains hidden or 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 hidden or 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,123 @@ | ||
| /* | ||
| Copyright 2021 The Kubernetes Authors All rights reserved. | ||
|
|
||
| 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 main | ||
|
|
||
| import ( | ||
| "fmt" | ||
| "log" | ||
| "net/http" | ||
| "sync" | ||
| "time" | ||
|
|
||
| "k8s.io/minikube/pkg/minikube/cluster" | ||
| "k8s.io/minikube/pkg/minikube/command" | ||
| "k8s.io/minikube/pkg/minikube/cruntime" | ||
| "k8s.io/minikube/pkg/minikube/exit" | ||
| "k8s.io/minikube/pkg/minikube/out" | ||
| "k8s.io/minikube/pkg/minikube/reason" | ||
| "k8s.io/minikube/pkg/minikube/style" | ||
| ) | ||
|
|
||
| var unpauseRequests = make(chan struct{}) | ||
| var done = make(chan struct{}) | ||
| var mu sync.Mutex | ||
|
|
||
| // TODO: initialize with current state (handle the case that user enables auto-pause after it is already paused) | ||
| var runtimePaused = false | ||
| var version = "0.0.1" | ||
|
|
||
| // TODO: #10597 make this configurable to support containerd/cri-o | ||
| var runtime = "docker" | ||
|
|
||
| func main() { | ||
| // TODO: #10595 make this configurable | ||
| const interval = time.Minute * 1 | ||
| // channel for incoming messages | ||
| go func() { | ||
| for { | ||
| // On each iteration new timer is created | ||
| select { | ||
| // TODO: #10596 make it memory-leak proof | ||
| case <-time.After(interval): | ||
medyagh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| runPause() | ||
| case <-unpauseRequests: | ||
| fmt.Printf("Got request\n") | ||
| if runtimePaused { | ||
| runUnpause() | ||
| } | ||
|
|
||
| done <- struct{}{} | ||
| } | ||
| } | ||
| }() | ||
|
|
||
| http.HandleFunc("/", handler) // each request calls handler | ||
| fmt.Printf("Starting auto-pause server %s at port 8080 \n", version) | ||
medyagh marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| log.Fatal(http.ListenAndServe("0.0.0.0:8080", nil)) | ||
| } | ||
|
|
||
| // handler echoes the Path component of the requested URL. | ||
| func handler(w http.ResponseWriter, r *http.Request) { | ||
| unpauseRequests <- struct{}{} | ||
| <-done | ||
| fmt.Fprintf(w, "allow") | ||
| } | ||
|
|
||
| func runPause() { | ||
| mu.Lock() | ||
| defer mu.Unlock() | ||
| if runtimePaused { | ||
| return | ||
| } | ||
|
|
||
| r := command.NewExecRunner(true) | ||
|
|
||
| cr, err := cruntime.New(cruntime.Config{Type: runtime, Runner: r}) | ||
| if err != nil { | ||
| exit.Error(reason.InternalNewRuntime, "Failed runtime", err) | ||
| } | ||
|
|
||
| uids, err := cluster.Pause(cr, r, []string{"kube-system"}) | ||
| if err != nil { | ||
| exit.Error(reason.GuestPause, "Pause", err) | ||
| } | ||
|
|
||
| runtimePaused = true | ||
|
|
||
| out.Step(style.Unpause, "Paused {{.count}} containers", out.V{"count": len(uids)}) | ||
| } | ||
|
|
||
| func runUnpause() { | ||
| fmt.Println("unpausing...") | ||
| mu.Lock() | ||
| defer mu.Unlock() | ||
|
|
||
| r := command.NewExecRunner(true) | ||
|
|
||
| cr, err := cruntime.New(cruntime.Config{Type: runtime, Runner: r}) | ||
| if err != nil { | ||
| exit.Error(reason.InternalNewRuntime, "Failed runtime", err) | ||
| } | ||
|
|
||
| uids, err := cluster.Unpause(cr, r, nil) | ||
| if err != nil { | ||
| exit.Error(reason.GuestUnpause, "Unpause", err) | ||
| } | ||
| runtimePaused = false | ||
|
|
||
| out.Step(style.Unpause, "Unpaused {{.count}} containers", out.V{"count": len(uids)}) | ||
| } | ||
This file contains hidden or 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 hidden or 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,10 @@ | ||
| [Unit] | ||
| Description=Auto Pause Service | ||
|
|
||
| [Service] | ||
| Type=simple | ||
| ExecStart=/usr/local/bin/auto-pause | ||
| Restart=always | ||
|
|
||
| [Install] | ||
| WantedBy=multi-user.target |
This file contains hidden or 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,47 @@ | ||
| --- | ||
| apiVersion: v1 | ||
| kind: Namespace | ||
| metadata: | ||
| name: auto-pause | ||
| --- | ||
| apiVersion: apps/v1 | ||
| kind: Deployment | ||
| metadata: | ||
| name: auto-pause-proxy | ||
| namespace: auto-pause | ||
| labels: | ||
| app: auto-pause-proxy | ||
| spec: | ||
| replicas: 1 | ||
| selector: | ||
| matchLabels: | ||
| app: auto-pause-proxy | ||
| template: | ||
| metadata: | ||
| creationTimestamp: null | ||
| labels: | ||
| app: auto-pause-proxy | ||
| spec: | ||
| volumes: | ||
| - name: ha-cfg | ||
| hostPath: | ||
| path: /var/lib/minikube/haproxy.cfg | ||
| type: File | ||
| - name: lua-script | ||
| hostPath: | ||
| path: /var/lib/minikube/unpause.lua | ||
| type: File | ||
| containers: | ||
| - name: auto-pause | ||
| image: "haproxy:2.3.5-alpine" | ||
| ports: | ||
| - name: https | ||
| containerPort: 6443 | ||
| hostPort: 32443 | ||
| protocol: TCP | ||
| volumeMounts: | ||
| - name: ha-cfg | ||
| mountPath: /usr/local/etc/haproxy/haproxy.cfg | ||
| readOnly: true | ||
| - name: lua-script | ||
| mountPath: /etc/haproxy/unpause.lua |
This file contains hidden or 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,37 @@ | ||
| #--------------------------------------------------------------------- | ||
| # Configure HAProxy for Kubernetes API Server | ||
| #--------------------------------------------------------------------- | ||
| listen stats | ||
| bind *:9000 | ||
| mode http | ||
| stats enable | ||
| stats hide-version | ||
| stats uri / | ||
| stats refresh 30s | ||
| option httplog | ||
|
|
||
| # change haproxy.cfg file with the following | ||
| global | ||
| lua-load /etc/haproxy/unpause.lua | ||
|
|
||
| ############## Configure HAProxy Secure Frontend ############# | ||
| frontend k8s-api-https-proxy | ||
| bind *:6443 | ||
| mode tcp | ||
| tcp-request inspect-delay 5s | ||
| tcp-request content accept if { req.ssl_hello_type 1 } | ||
| default_backend k8s-api-https | ||
| ############## Configure HAProxy SecureBackend ############# | ||
| backend k8s-api-https | ||
| balance roundrobin | ||
| mode tcp | ||
| #tcp-request inspect-delay 10s | ||
| #tcp-request content lua.foo_action | ||
| tcp-request inspect-delay 10s | ||
| tcp-request content lua.unpause 192.168.49.2 8080 | ||
| tcp-request content reject if { var(req.blocked) -m bool } | ||
| option tcplog | ||
| option tcp-check | ||
| default-server inter 10s downinter 5s rise 2 fall 2 slowstart 60s maxconn 250 maxqueue 256 weight 100 | ||
| server k8s-api-1 192.168.49.2:8443 check | ||
|
|
This file contains hidden or 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,57 @@ | ||
| local function unpause(txn, addr, port) | ||
| if not addr then addr = '127.0.0.1' end | ||
| if not port then port = 5000 end | ||
|
|
||
| -- Set up a request to the service | ||
| local hdrs = { | ||
| [1] = string.format('host: %s:%s', addr, port), | ||
| [2] = 'accept: */*', | ||
| [3] = 'connection: close' | ||
| } | ||
|
|
||
| local req = { | ||
| [1] = string.format('GET /%s HTTP/1.1', tostring(txn.f:src())), | ||
| [2] = table.concat(hdrs, '\r\n'), | ||
| [3] = '\r\n' | ||
| } | ||
|
|
||
| req = table.concat(req, '\r\n') | ||
|
|
||
| -- Use core.tcp to get an instance of the Socket class | ||
| local socket = core.tcp() | ||
| socket:settimeout(5) | ||
|
|
||
| -- Connect to the service and send the request | ||
| if socket:connect(addr, port) then | ||
| if socket:send(req) then | ||
| -- Skip response headers | ||
| while true do | ||
| local line, _ = socket:receive('*l') | ||
|
|
||
| if not line then break end | ||
| if line == '' then break end | ||
| end | ||
|
|
||
| -- Get response body, if any | ||
| local content = socket:receive('*a') | ||
|
|
||
| -- Check if this request should be allowed | ||
| if content and content == 'allow' then | ||
| txn:set_var('req.blocked', false) | ||
| return | ||
| end | ||
| else | ||
| core.Alert('Could not connect to IP Checker server (send)') | ||
| end | ||
|
|
||
| socket:close() | ||
| else | ||
| core.Alert('Could not connect to IP Checker server (connect)') | ||
| end | ||
|
|
||
| -- The request should be blocked | ||
| txn:set_var('req.blocked', true) | ||
| end | ||
|
|
||
| core.register_action('unpause', {'tcp-req'}, unpause, 2) | ||
|
|
This file contains hidden or 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
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.