scaltainer 0.4.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/actions/rspec_tests/action.yml +25 -0
- data/.github/workflows/docker-build-push.yml +62 -0
- data/.github/workflows/rubygems-release.yml +25 -0
- data/.github/workflows/tests.yml +24 -0
- data/Dockerfile +8 -3
- data/Gemfile.lock +39 -42
- data/README.md +37 -10
- data/exe/scaltainer +2 -2
- data/lib/scaltainer/command.rb +12 -3
- data/lib/scaltainer/runner.rb +24 -3
- data/lib/scaltainer/version.rb +1 -1
- data/publish.sh +10 -0
- data/scaltainer.gemspec +12 -10
- metadata +65 -33
- data/.travis.yml +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3537d6ea1b1cee2e5a5efce8a5c98e3727473585302d57fc816148d8ffce2a4d
|
4
|
+
data.tar.gz: 0de1927d3b4dc1a35fa755af035a495f7193b9105b8fc0a2088c2ffa2342192d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f63915a92b777a563f24f89aaae8045465545c0e19f5adf77741426e20aa9f1186aa56218a2bc0fc8001b07d1616e1a76014cee1eba1c5a961638c4e9531eac8
|
7
|
+
data.tar.gz: a189a04f2b4b7b04f348b6d9d7438bff6323781b63dd4f1191bbe1b3f4bf9fb47222d265279b4b349c3520d0c3a5d2a129e240800c40c3d479aaa7cbdd63c125
|
@@ -0,0 +1,25 @@
|
|
1
|
+
name: rspec-tests
|
2
|
+
description: Composite action for rspec tests
|
3
|
+
inputs:
|
4
|
+
github-token:
|
5
|
+
required: true
|
6
|
+
runs:
|
7
|
+
using: composite
|
8
|
+
steps:
|
9
|
+
- name: Install bundler
|
10
|
+
shell: bash
|
11
|
+
# The bundler version used must match the one in the repo's gemspec
|
12
|
+
run: gem install bundler:2.2.19
|
13
|
+
- name: Bundle dependencies
|
14
|
+
shell: bash
|
15
|
+
run: bundle
|
16
|
+
- name: Run rspec tests
|
17
|
+
shell: bash
|
18
|
+
env:
|
19
|
+
CI: true
|
20
|
+
run: bundle exec rspec
|
21
|
+
- name: Use coveralls
|
22
|
+
uses: coverallsapp/github-action@1.1.3
|
23
|
+
with:
|
24
|
+
github-token: ${{ inputs.github-token }}
|
25
|
+
path-to-lcov: 'coverage/lcov.info'
|
@@ -0,0 +1,62 @@
|
|
1
|
+
name: Docker
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
branches:
|
6
|
+
- master
|
7
|
+
tags:
|
8
|
+
- v*
|
9
|
+
|
10
|
+
env:
|
11
|
+
IMAGE_NAME: hammady/scaltainer
|
12
|
+
|
13
|
+
jobs:
|
14
|
+
docker:
|
15
|
+
runs-on: ubuntu-latest
|
16
|
+
if: github.event_name == 'push'
|
17
|
+
|
18
|
+
steps:
|
19
|
+
- name: Checkout
|
20
|
+
uses: actions/checkout@v2
|
21
|
+
|
22
|
+
- name: Determine target image name
|
23
|
+
id: image-name
|
24
|
+
run: |
|
25
|
+
IMAGE_ID=ghcr.io/$IMAGE_NAME
|
26
|
+
|
27
|
+
# Strip git ref prefix from version
|
28
|
+
VERSION=$(echo "${{ github.ref }}" | sed -e 's,.*/\(.*\),\1,')
|
29
|
+
|
30
|
+
# Strip "v" prefix from tag name
|
31
|
+
[[ "${{ github.ref }}" == "refs/tags/"* ]] && VERSION=$(echo $VERSION | sed -e 's/^v//')
|
32
|
+
|
33
|
+
# Use Docker `latest` tag convention
|
34
|
+
[ "$VERSION" == "master" ] && VERSION=latest
|
35
|
+
|
36
|
+
IMAGES=
|
37
|
+
IMAGES="$IMAGE_ID:$VERSION"$'\n'$IMAGES
|
38
|
+
|
39
|
+
# debug output
|
40
|
+
echo images $IMAGES
|
41
|
+
echo ::set-output name=images::"$IMAGES"
|
42
|
+
|
43
|
+
- name: Set up QEMU
|
44
|
+
uses: docker/setup-qemu-action@v1
|
45
|
+
|
46
|
+
- name: Set up Docker Buildx
|
47
|
+
uses: docker/setup-buildx-action@v1
|
48
|
+
|
49
|
+
- name: Login to registry
|
50
|
+
uses: docker/login-action@v1
|
51
|
+
with:
|
52
|
+
registry: ghcr.io
|
53
|
+
username: ${{ github.actor }}
|
54
|
+
password: ${{ secrets.GITHUB_TOKEN }}
|
55
|
+
|
56
|
+
- name: Build and push
|
57
|
+
uses: docker/build-push-action@v2
|
58
|
+
with:
|
59
|
+
context: .
|
60
|
+
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
61
|
+
push: true
|
62
|
+
tags: ${{ steps.image-name.outputs.images }}
|
@@ -0,0 +1,25 @@
|
|
1
|
+
name: Release
|
2
|
+
on:
|
3
|
+
push:
|
4
|
+
tags:
|
5
|
+
- v*
|
6
|
+
jobs:
|
7
|
+
release:
|
8
|
+
runs-on: ubuntu-latest
|
9
|
+
steps:
|
10
|
+
- uses: actions/checkout@v3
|
11
|
+
- uses: ruby/setup-ruby@v1
|
12
|
+
with:
|
13
|
+
ruby-version: '2.7'
|
14
|
+
- name: Install bundler
|
15
|
+
shell: bash
|
16
|
+
# The bundler version used must match the one in the repo's gemspec
|
17
|
+
run: gem install bundler:2.2.19
|
18
|
+
- name: Bundle dependencies
|
19
|
+
shell: bash
|
20
|
+
run: bundle
|
21
|
+
- name: Release gem
|
22
|
+
shell: bash
|
23
|
+
env:
|
24
|
+
RUBYGEMS_API_KEY: ${{ secrets.RUBYGEMS_API_KEY }}
|
25
|
+
run: ./publish.sh
|
@@ -0,0 +1,24 @@
|
|
1
|
+
name: 'Test'
|
2
|
+
on:
|
3
|
+
push:
|
4
|
+
branches:
|
5
|
+
- master
|
6
|
+
tags:
|
7
|
+
- v*
|
8
|
+
pull_request:
|
9
|
+
types: [opened, reopened, edited, synchronize]
|
10
|
+
jobs:
|
11
|
+
test:
|
12
|
+
strategy:
|
13
|
+
matrix:
|
14
|
+
ruby_version: [2.6, 2.7]
|
15
|
+
runs-on: ubuntu-latest
|
16
|
+
steps:
|
17
|
+
- uses: actions/checkout@v3
|
18
|
+
- uses: ruby/setup-ruby@v1
|
19
|
+
with:
|
20
|
+
ruby-version: '${{ matrix.ruby_version }}'
|
21
|
+
- name: Run rspec tests
|
22
|
+
uses: ./.github/actions/rspec_tests
|
23
|
+
with:
|
24
|
+
github-token: ${{ secrets.GITHUB_TOKEN }}
|
data/Dockerfile
CHANGED
@@ -1,11 +1,16 @@
|
|
1
|
-
FROM ruby:2.
|
1
|
+
FROM ruby:2.7
|
2
2
|
|
3
|
-
|
3
|
+
LABEL maintainer="Hossam Hammady <github@hammady.net>"
|
4
|
+
|
5
|
+
ENV NEW_RELIC_LOG=stdout
|
6
|
+
ENV NEW_RELIC_AUTOSTART_DENYLISTED_CONSTANTS=Scaltainer
|
7
|
+
|
8
|
+
RUN gem install bundler --version 2.2.19
|
4
9
|
|
5
10
|
WORKDIR /home
|
6
11
|
COPY / /home/
|
7
12
|
RUN bundle install && bundle exec rake install
|
8
13
|
|
9
|
-
ENTRYPOINT ["scaltainer"]
|
14
|
+
ENTRYPOINT ["bundle", "exec", "scaltainer"]
|
10
15
|
|
11
16
|
CMD ["-h"]
|
data/Gemfile.lock
CHANGED
@@ -1,35 +1,30 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
scaltainer (0.
|
5
|
-
docker-api
|
6
|
-
dotenv
|
7
|
-
excon (
|
8
|
-
kubeclient
|
9
|
-
|
4
|
+
scaltainer (0.6.0)
|
5
|
+
docker-api (~> 2.1)
|
6
|
+
dotenv (~> 2.7)
|
7
|
+
excon (~> 0.47)
|
8
|
+
kubeclient (~> 4.9)
|
9
|
+
newrelic_rpm (~> 7.1)
|
10
|
+
prometheus-client (~> 2.1)
|
10
11
|
|
11
12
|
GEM
|
12
13
|
remote: https://rubygems.org/
|
13
14
|
specs:
|
14
|
-
addressable (2.
|
15
|
-
public_suffix (>= 2.0.2, <
|
15
|
+
addressable (2.8.1)
|
16
|
+
public_suffix (>= 2.0.2, < 6.0)
|
16
17
|
coderay (1.1.1)
|
17
|
-
coveralls (0.8.21)
|
18
|
-
json (>= 1.8, < 3)
|
19
|
-
simplecov (~> 0.14.1)
|
20
|
-
term-ansicolor (~> 1.3)
|
21
|
-
thor (~> 0.19.4)
|
22
|
-
tins (~> 1.6)
|
23
18
|
diff-lcs (1.3)
|
24
|
-
docile (1.
|
25
|
-
docker-api (1.
|
19
|
+
docile (1.4.0)
|
20
|
+
docker-api (2.1.0)
|
26
21
|
excon (>= 0.47.0)
|
27
22
|
multi_json
|
28
23
|
domain_name (0.5.20190701)
|
29
24
|
unf (>= 0.0.5, < 1.0.0)
|
30
|
-
dotenv (2.7.
|
31
|
-
excon (0.
|
32
|
-
ffi (1.
|
25
|
+
dotenv (2.7.6)
|
26
|
+
excon (0.82.0)
|
27
|
+
ffi (1.15.5)
|
33
28
|
ffi-compiler (1.0.1)
|
34
29
|
ffi (>= 1.0.0)
|
35
30
|
rake
|
@@ -39,25 +34,29 @@ GEM
|
|
39
34
|
http-form_data (~> 2.2)
|
40
35
|
http-parser (~> 1.2.0)
|
41
36
|
http-accept (1.7.0)
|
42
|
-
http-cookie (1.0.
|
37
|
+
http-cookie (1.0.4)
|
43
38
|
domain_name (~> 0.5)
|
44
39
|
http-form_data (2.3.0)
|
45
|
-
http-parser (1.2.
|
40
|
+
http-parser (1.2.3)
|
46
41
|
ffi-compiler (>= 1.0, < 2.0)
|
47
|
-
json (2.
|
48
|
-
|
42
|
+
json (2.6.3)
|
43
|
+
jsonpath (1.1.0)
|
44
|
+
multi_json
|
45
|
+
kubeclient (4.9.3)
|
49
46
|
http (>= 3.0, < 5.0)
|
50
|
-
|
47
|
+
jsonpath (~> 1.0)
|
48
|
+
recursive-open-struct (~> 1.1, >= 1.1.1)
|
51
49
|
rest-client (~> 2.0)
|
52
|
-
mime-types (3.
|
50
|
+
mime-types (3.4.1)
|
53
51
|
mime-types-data (~> 3.2015)
|
54
|
-
mime-types-data (3.
|
55
|
-
multi_json (1.
|
52
|
+
mime-types-data (3.2022.0105)
|
53
|
+
multi_json (1.15.0)
|
56
54
|
netrc (0.11.0)
|
57
|
-
|
58
|
-
|
55
|
+
newrelic_rpm (7.1.0)
|
56
|
+
prometheus-client (2.1.0)
|
57
|
+
public_suffix (5.0.0)
|
59
58
|
rake (13.0.1)
|
60
|
-
recursive-open-struct (1.1.
|
59
|
+
recursive-open-struct (1.1.3)
|
61
60
|
rest-client (2.1.0)
|
62
61
|
http-accept (>= 1.7.0, < 2.0)
|
63
62
|
http-cookie (>= 1.0.2, < 2.0)
|
@@ -76,29 +75,27 @@ GEM
|
|
76
75
|
diff-lcs (>= 1.2.0, < 2.0)
|
77
76
|
rspec-support (~> 3.6.0)
|
78
77
|
rspec-support (3.6.0)
|
79
|
-
simplecov (0.
|
80
|
-
docile (~> 1.1
|
78
|
+
simplecov (0.17.1)
|
79
|
+
docile (~> 1.1)
|
81
80
|
json (>= 1.8, < 3)
|
82
81
|
simplecov-html (~> 0.10.0)
|
83
|
-
simplecov-html (0.10.
|
84
|
-
|
85
|
-
tins (~> 1.0)
|
86
|
-
thor (0.19.4)
|
87
|
-
tins (1.13.2)
|
82
|
+
simplecov-html (0.10.2)
|
83
|
+
simplecov-lcov (0.7.0)
|
88
84
|
unf (0.1.4)
|
89
85
|
unf_ext
|
90
|
-
unf_ext (0.0.
|
86
|
+
unf_ext (0.0.8.1)
|
91
87
|
|
92
88
|
PLATFORMS
|
93
89
|
ruby
|
94
90
|
|
95
91
|
DEPENDENCIES
|
96
|
-
bundler (~>
|
92
|
+
bundler (~> 2.2)
|
97
93
|
coderay (~> 1.1)
|
98
|
-
|
99
|
-
rake (>= 12.3.3)
|
94
|
+
rake (~> 13.0)
|
100
95
|
rspec (~> 3.5)
|
101
96
|
scaltainer!
|
97
|
+
simplecov (~> 0.17)
|
98
|
+
simplecov-lcov (~> 0.7)
|
102
99
|
|
103
100
|
BUNDLED WITH
|
104
|
-
|
101
|
+
2.2.19
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+

|
2
2
|
[](https://coveralls.io/github/hammady/scaltainer?branch=master)
|
3
3
|
[](https://badge.fury.io/rb/scaltainer)
|
4
4
|
|
@@ -22,15 +22,15 @@ Install using rubygems:
|
|
22
22
|
|
23
23
|
For Docker swarm:
|
24
24
|
|
25
|
-
scaltainer -o swarm
|
25
|
+
bundle exec scaltainer -o swarm
|
26
26
|
|
27
27
|
Or simply:
|
28
28
|
|
29
|
-
scaltainer
|
29
|
+
bundle exec scaltainer
|
30
30
|
|
31
31
|
For Kubernetes:
|
32
32
|
|
33
|
-
scaltainer -o kubernetes
|
33
|
+
bundle exec scaltainer -o kubernetes
|
34
34
|
|
35
35
|
|
36
36
|
This will do a one-time check on the running docker service replicas
|
@@ -38,7 +38,7 @@ or Kubernetes replication controllers, replica sets, or deployments.
|
|
38
38
|
Then it sends scaling out/in commands to the cluster as appropriate.
|
39
39
|
Configuration is read from `scaltainer.yml` by default. If you want to read from another file add `-f yourconfig.yml`:
|
40
40
|
|
41
|
-
scaltainer -f yourconfig.yml
|
41
|
+
bundle exec scaltainer -f yourconfig.yml
|
42
42
|
|
43
43
|
Note that after each run a new file is created (`yourconfig.yml.state`) which stores the state of the previous run.
|
44
44
|
This is because there are some configuration parameters (like sensitivity) need to
|
@@ -46,19 +46,19 @@ remember previous runs.
|
|
46
46
|
If you want to specify a different location for the state file, add the `--state-file` parameter.
|
47
47
|
Example:
|
48
48
|
|
49
|
-
scaltainer -f /path/to/configuration/file.yml --state-file /path/to/different/state/file.yml
|
49
|
+
bundle exec scaltainer -f /path/to/configuration/file.yml --state-file /path/to/different/state/file.yml
|
50
50
|
|
51
51
|
Typically one would want to repeatedly call scaltainer every minute or so. To do this
|
52
52
|
specify the wait time between repetitions using the `-w` parameter in seconds:
|
53
53
|
|
54
|
-
scaltainer -w 60
|
54
|
+
bundle exec scaltainer -w 60
|
55
55
|
|
56
56
|
This will repeatedly call scaltainer every 60 seconds, sleeping in-between.
|
57
57
|
|
58
58
|
If you would like to monitor the changes in scaling out and in. You can install
|
59
59
|
Prometheus and add a configuration parameter pointing to its Push Gateway:
|
60
60
|
|
61
|
-
scaltainer -g prometheus-pushgateway.monitoring.svc.cluster.local:9091
|
61
|
+
bundle exec scaltainer -g prometheus-pushgateway.monitoring.svc.cluster.local:9091
|
62
62
|
|
63
63
|
Where `prometheus-pushgateway.monitoring.svc.cluster.local:9091` is the address
|
64
64
|
of the push gateway. For Kubernetes environments the above denotes the gateway service
|
@@ -73,6 +73,29 @@ configuration file.
|
|
73
73
|
- `scaltainer_worker_queue_size_total`: queue sizes as reported by the worker services
|
74
74
|
- `scaltainer_ticks_total`: iterations scaltainer has performed (if `-w` is used)
|
75
75
|
|
76
|
+
If you prefer to use New Relic monitoring, replace the `-g` parameter with `--enable-newrelic-reporting`.
|
77
|
+
If enabled, must set the environment variables `NEW_RELIC_LICENSE_KEY` and `NEW_RELIC_APP_NAME` (see below).
|
78
|
+
Once enabled, the below will be reported:
|
79
|
+
|
80
|
+
- `Custom/WebReplicas/service`
|
81
|
+
- `Custom/WorkerReplicas/service`
|
82
|
+
- `Custom/WebMetric/service`
|
83
|
+
- `Custom/WorkerMetric/service`
|
84
|
+
- `Custom/Scaltainer/ticks`
|
85
|
+
|
86
|
+
Where `service` is a placeholder for each service defined in `yourconfig.yml`.
|
87
|
+
|
88
|
+
Here is an example NRQL to query the metrics:
|
89
|
+
|
90
|
+
```
|
91
|
+
FROM Metric
|
92
|
+
SELECT max(newrelic.timeslice.value)
|
93
|
+
WHERE appName = 'YOUR APP NAME'
|
94
|
+
WITH METRIC_FORMAT 'Custom/WebReplicas/{web}'
|
95
|
+
FACET web
|
96
|
+
SINCE 1 day ago TIMESERIES MAX
|
97
|
+
```
|
98
|
+
|
76
99
|
## Configuration
|
77
100
|
|
78
101
|
### Environment variables
|
@@ -133,6 +156,10 @@ environment variables are set using `docker config` or `docker secret`.
|
|
133
156
|
These files should be in the form `VARIABLE=value`.
|
134
157
|
A typical value of this variable would be: `{/run/secrets/*,/config1,/config2}`
|
135
158
|
|
159
|
+
- `NEW_RELIC_LICENSE_KEY`: New Relic license key, required if `--enable_newrelic_reporting`
|
160
|
+
is used.
|
161
|
+
- `NEW_RELIC_APP_NAME`: New Relic application name, required if `--enable_newrelic_reporting`
|
162
|
+
is used.
|
136
163
|
### Configuration file
|
137
164
|
|
138
165
|
The configuration file (determined by `-f FILE` command line parameter) should be in the following form:
|
@@ -186,7 +213,7 @@ A service definition for scaltainer is typically something like this:
|
|
186
213
|
version: '3.3'
|
187
214
|
services:
|
188
215
|
scaltainer:
|
189
|
-
image:
|
216
|
+
image: hammady/scaltainer:latest
|
190
217
|
command: -f /scaltainer.yml --state-file /tmp/scaltainer-state.yml -w 60
|
191
218
|
volumes:
|
192
219
|
- /var/run/docker.sock:/var/run/docker.sock
|
@@ -255,7 +282,7 @@ Where scaltainer-kube.yaml has the following content:
|
|
255
282
|
app: scaltainer
|
256
283
|
spec:
|
257
284
|
containers:
|
258
|
-
- image:
|
285
|
+
- image: hammady/scaltainer:latest
|
259
286
|
name: scaltainer
|
260
287
|
args:
|
261
288
|
- -o
|
data/exe/scaltainer
CHANGED
@@ -3,8 +3,8 @@
|
|
3
3
|
require 'scaltainer'
|
4
4
|
|
5
5
|
begin
|
6
|
-
configfile, statefile, logger, wait, orchestrator, pushgateway = Scaltainer::Command.parse ARGV
|
7
|
-
Scaltainer::Runner.new configfile, statefile, logger, wait, orchestrator, pushgateway
|
6
|
+
configfile, statefile, logger, wait, orchestrator, pushgateway, enable_newrelic_reporting = Scaltainer::Command.parse ARGV
|
7
|
+
Scaltainer::Runner.new configfile, statefile, logger, wait, orchestrator, pushgateway, enable_newrelic_reporting
|
8
8
|
rescue => e
|
9
9
|
$stderr.puts e.message
|
10
10
|
$stderr.puts e.backtrace
|
data/lib/scaltainer/command.rb
CHANGED
@@ -4,7 +4,7 @@ require "optparse"
|
|
4
4
|
module Scaltainer
|
5
5
|
class Command
|
6
6
|
def self.parse(args)
|
7
|
-
configfile, statefile, wait, orchestrator, pushgateway = 'scaltainer.yml', nil, 0, :swarm, nil
|
7
|
+
configfile, statefile, wait, orchestrator, pushgateway, enable_newrelic_reporting = 'scaltainer.yml', nil, 0, :swarm, nil, false
|
8
8
|
OptionParser.new do |opts|
|
9
9
|
opts.banner = "Usage: scaltainer [options]"
|
10
10
|
opts.on("-f", "--conf-file FILE", "Specify configuration file (default: scaltainer.yml)") do |file|
|
@@ -22,6 +22,13 @@ module Scaltainer
|
|
22
22
|
opts.on("-g", "--prometheus-push-gateway ADDRESS", "Specify prometheus push gateway address in the form of host:port") do |gw|
|
23
23
|
pushgateway = gw
|
24
24
|
end
|
25
|
+
opts.on("--enable-newrelic-reporting", "Enable metrics pushing to New Relic") do
|
26
|
+
newrelic_license_key = ENV['NEW_RELIC_LICENSE_KEY']
|
27
|
+
newrelic_app_name = ENV['NEW_RELIC_APP_NAME']
|
28
|
+
raise 'Must set NEW_RELIC_LICENSE_KEY environment variable if --enable-newrelic-reporting is set' if newrelic_license_key.nil? || newrelic_license_key == ""
|
29
|
+
raise 'Must set NEW_RELIC_APP_NAME environment variable if --enable-newrelic-reporting is set' if newrelic_app_name.nil? || newrelic_app_name == ""
|
30
|
+
enable_newrelic_reporting = true
|
31
|
+
end
|
25
32
|
opts.on("-v", "--version", "Show version and exit") do
|
26
33
|
puts Scaltainer::VERSION
|
27
34
|
exit 0
|
@@ -41,10 +48,12 @@ module Scaltainer
|
|
41
48
|
puts " Make sure the KUBERNETES_CONTROLLER_KIND you specify is part of the api specified using KUBERNETES_API_ENDPOINT and KUBERNETES_API_VERSION"
|
42
49
|
puts "General options:"
|
43
50
|
puts "- HIREFIRE_TOKEN"
|
44
|
-
puts "- NEW_RELIC_API_KEY"
|
51
|
+
puts "- NEW_RELIC_API_KEY: New Relic API key for retrieving web metrics"
|
45
52
|
puts "- RESPONSE_TIME_WINDOW: defaults to 5"
|
46
53
|
puts "- LOG_LEVEL: defaults to INFO"
|
47
54
|
puts "- DOCKER_SECRETS_PATH_GLOB: path glob containing env files to load"
|
55
|
+
puts "- NEW_RELIC_LICENSE_KEY: New Relic license key, required if --enable_newrelic_reporting is used"
|
56
|
+
puts "- NEW_RELIC_APP_NAME: New Relic application name, required if --enable_newrelic_reporting is used"
|
48
57
|
exit
|
49
58
|
end
|
50
59
|
end.parse!
|
@@ -58,7 +67,7 @@ module Scaltainer
|
|
58
67
|
logger = Logger.new(STDOUT)
|
59
68
|
logger.level = %w(debug info warn error fatal unknown).find_index((ENV['LOG_LEVEL'] || '').downcase) || 1
|
60
69
|
|
61
|
-
return configfile, statefile, logger, wait, orchestrator, pushgateway
|
70
|
+
return configfile, statefile, logger, wait, orchestrator, pushgateway, enable_newrelic_reporting
|
62
71
|
end
|
63
72
|
|
64
73
|
private
|
data/lib/scaltainer/runner.rb
CHANGED
@@ -2,10 +2,11 @@ require "yaml"
|
|
2
2
|
require 'socket'
|
3
3
|
require 'prometheus/client'
|
4
4
|
require 'prometheus/client/push'
|
5
|
+
require 'newrelic_rpm'
|
5
6
|
|
6
7
|
module Scaltainer
|
7
8
|
class Runner
|
8
|
-
def initialize(configfile, statefile, logger, wait, orchestrator, pushgateway)
|
9
|
+
def initialize(configfile, statefile, logger, wait, orchestrator, pushgateway, enable_newrelic_reporting)
|
9
10
|
@orchestrator = orchestrator
|
10
11
|
@logger = logger
|
11
12
|
@default_service_config = {
|
@@ -23,11 +24,13 @@ module Scaltainer
|
|
23
24
|
service_type_web = ServiceTypeWeb.new(endpoint)
|
24
25
|
service_type_worker = ServiceTypeWorker.new(endpoint)
|
25
26
|
register_pushgateway(pushgateway) if pushgateway
|
27
|
+
register_newrelic if enable_newrelic_reporting
|
26
28
|
namespace = config["namespace"] || config["stack_name"]
|
27
29
|
loop do
|
28
30
|
run config, state, service_type_web, service_type_worker, namespace
|
29
31
|
save_state statefile, state
|
30
32
|
sync_pushgateway(namespace, state) if pushgateway
|
33
|
+
sync_newrelic(state) if enable_newrelic_reporting
|
31
34
|
sleep wait
|
32
35
|
break if wait == 0
|
33
36
|
end
|
@@ -135,8 +138,8 @@ module Scaltainer
|
|
135
138
|
|
136
139
|
def sync_pushgateway(namespace, state)
|
137
140
|
@logger.debug("Now syncing state #{state} in namespace #{namespace}")
|
138
|
-
factor = 1
|
139
141
|
state.each do |service, state|
|
142
|
+
factor = 1
|
140
143
|
if state["service_type"] == 'Web'
|
141
144
|
replicas_gauge = @web_replicas_gauge
|
142
145
|
metrics_gauge = @web_metrics_gauge
|
@@ -151,10 +154,28 @@ module Scaltainer
|
|
151
154
|
@ticks_counter.increment(labels: {namespace: namespace})
|
152
155
|
begin
|
153
156
|
@pushgateway.add(@registry)
|
157
|
+
@logger.info "Pushed metrics successfully to the configured Prometheus Push Gateway"
|
154
158
|
rescue => e
|
155
159
|
@logger.warn "[#{e.class}] Error pushing metrics to the configured Prometheus Push Gateway: #{e.message}"
|
156
160
|
end
|
157
|
-
|
161
|
+
end
|
162
|
+
|
163
|
+
def register_newrelic
|
164
|
+
::NewRelic::Agent.manual_start
|
165
|
+
end
|
166
|
+
|
167
|
+
def record_newrelic_metric(name, value)
|
168
|
+
@logger.debug("Reporting NewRelic metric: #{name} = #{value}")
|
169
|
+
::NewRelic::Agent.record_metric(name, value.to_i)
|
170
|
+
end
|
171
|
+
|
172
|
+
def sync_newrelic(state)
|
173
|
+
@logger.debug("Now reporting state #{state} to the NewRelic agent")
|
174
|
+
::NewRelic::Agent.increment_metric('Custom/Scaltainer/ticks')
|
175
|
+
state.each do |service, state|
|
176
|
+
record_newrelic_metric "Custom/#{state["service_type"]}Replicas/#{service}", state["replicas"]
|
177
|
+
record_newrelic_metric "Custom/#{state["service_type"]}Metric/#{service}", state["metric"]
|
178
|
+
end
|
158
179
|
end
|
159
180
|
|
160
181
|
end # class
|
data/lib/scaltainer/version.rb
CHANGED
data/publish.sh
ADDED
data/scaltainer.gemspec
CHANGED
@@ -22,15 +22,17 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
23
23
|
spec.require_paths = ["lib"]
|
24
24
|
|
25
|
-
spec.add_development_dependency "bundler", "~>
|
26
|
-
spec.add_development_dependency "rake", "
|
27
|
-
spec.add_development_dependency
|
28
|
-
spec.add_development_dependency
|
29
|
-
spec.add_development_dependency
|
25
|
+
spec.add_development_dependency "bundler", "~> 2.2"
|
26
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
27
|
+
spec.add_development_dependency "rspec", "~> 3.5"
|
28
|
+
spec.add_development_dependency "coderay", "~> 1.1"
|
29
|
+
spec.add_development_dependency "simplecov", "~> 0.17"
|
30
|
+
spec.add_development_dependency "simplecov-lcov", "~> 0.7"
|
30
31
|
|
31
|
-
spec.add_runtime_dependency
|
32
|
-
spec.add_runtime_dependency "docker-api"
|
33
|
-
spec.add_runtime_dependency "kubeclient"
|
34
|
-
spec.add_runtime_dependency "dotenv"
|
35
|
-
spec.add_runtime_dependency "prometheus-client"
|
32
|
+
spec.add_runtime_dependency "excon", "~> 0.47"
|
33
|
+
spec.add_runtime_dependency "docker-api", "~> 2.1"
|
34
|
+
spec.add_runtime_dependency "kubeclient", "~> 4.9"
|
35
|
+
spec.add_runtime_dependency "dotenv", "~> 2.7"
|
36
|
+
spec.add_runtime_dependency "prometheus-client", "~> 2.1"
|
37
|
+
spec.add_runtime_dependency "newrelic_rpm", "~> 7.1"
|
36
38
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scaltainer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hossam Hammady
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-09-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '2.2'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '2.2'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rake
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: '13.0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: '13.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rspec
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -67,89 +67,117 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '1.1'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: simplecov
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '0.
|
75
|
+
version: '0.17'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '0.
|
82
|
+
version: '0.17'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: simplecov-lcov
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0.7'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0.7'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: excon
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
86
100
|
requirements:
|
87
|
-
- - "
|
101
|
+
- - "~>"
|
88
102
|
- !ruby/object:Gem::Version
|
89
|
-
version: 0.47
|
103
|
+
version: '0.47'
|
90
104
|
type: :runtime
|
91
105
|
prerelease: false
|
92
106
|
version_requirements: !ruby/object:Gem::Requirement
|
93
107
|
requirements:
|
94
|
-
- - "
|
108
|
+
- - "~>"
|
95
109
|
- !ruby/object:Gem::Version
|
96
|
-
version: 0.47
|
110
|
+
version: '0.47'
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: docker-api
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
100
114
|
requirements:
|
101
|
-
- - "
|
115
|
+
- - "~>"
|
102
116
|
- !ruby/object:Gem::Version
|
103
|
-
version: '
|
117
|
+
version: '2.1'
|
104
118
|
type: :runtime
|
105
119
|
prerelease: false
|
106
120
|
version_requirements: !ruby/object:Gem::Requirement
|
107
121
|
requirements:
|
108
|
-
- - "
|
122
|
+
- - "~>"
|
109
123
|
- !ruby/object:Gem::Version
|
110
|
-
version: '
|
124
|
+
version: '2.1'
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
126
|
name: kubeclient
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
114
128
|
requirements:
|
115
|
-
- - "
|
129
|
+
- - "~>"
|
116
130
|
- !ruby/object:Gem::Version
|
117
|
-
version: '
|
131
|
+
version: '4.9'
|
118
132
|
type: :runtime
|
119
133
|
prerelease: false
|
120
134
|
version_requirements: !ruby/object:Gem::Requirement
|
121
135
|
requirements:
|
122
|
-
- - "
|
136
|
+
- - "~>"
|
123
137
|
- !ruby/object:Gem::Version
|
124
|
-
version: '
|
138
|
+
version: '4.9'
|
125
139
|
- !ruby/object:Gem::Dependency
|
126
140
|
name: dotenv
|
127
141
|
requirement: !ruby/object:Gem::Requirement
|
128
142
|
requirements:
|
129
|
-
- - "
|
143
|
+
- - "~>"
|
130
144
|
- !ruby/object:Gem::Version
|
131
|
-
version: '
|
145
|
+
version: '2.7'
|
132
146
|
type: :runtime
|
133
147
|
prerelease: false
|
134
148
|
version_requirements: !ruby/object:Gem::Requirement
|
135
149
|
requirements:
|
136
|
-
- - "
|
150
|
+
- - "~>"
|
137
151
|
- !ruby/object:Gem::Version
|
138
|
-
version: '
|
152
|
+
version: '2.7'
|
139
153
|
- !ruby/object:Gem::Dependency
|
140
154
|
name: prometheus-client
|
141
155
|
requirement: !ruby/object:Gem::Requirement
|
142
156
|
requirements:
|
143
|
-
- - "
|
157
|
+
- - "~>"
|
144
158
|
- !ruby/object:Gem::Version
|
145
|
-
version: '
|
159
|
+
version: '2.1'
|
146
160
|
type: :runtime
|
147
161
|
prerelease: false
|
148
162
|
version_requirements: !ruby/object:Gem::Requirement
|
149
163
|
requirements:
|
150
|
-
- - "
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '2.1'
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: newrelic_rpm
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - "~>"
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '7.1'
|
174
|
+
type: :runtime
|
175
|
+
prerelease: false
|
176
|
+
version_requirements: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - "~>"
|
151
179
|
- !ruby/object:Gem::Version
|
152
|
-
version: '
|
180
|
+
version: '7.1'
|
153
181
|
description: |-
|
154
182
|
A ruby gem inspired by HireFire to autoscale kubernetes controllers and docker services.
|
155
183
|
Metrics can be standard average response time, New Relic web metrics, queue size for workers, ...
|
@@ -161,9 +189,12 @@ extensions: []
|
|
161
189
|
extra_rdoc_files: []
|
162
190
|
files:
|
163
191
|
- ".dockerignore"
|
192
|
+
- ".github/actions/rspec_tests/action.yml"
|
193
|
+
- ".github/workflows/docker-build-push.yml"
|
194
|
+
- ".github/workflows/rubygems-release.yml"
|
195
|
+
- ".github/workflows/tests.yml"
|
164
196
|
- ".gitignore"
|
165
197
|
- ".rspec"
|
166
|
-
- ".travis.yml"
|
167
198
|
- Dockerfile
|
168
199
|
- Gemfile
|
169
200
|
- Gemfile.lock
|
@@ -187,6 +218,7 @@ files:
|
|
187
218
|
- lib/scaltainer/service_types/web.rb
|
188
219
|
- lib/scaltainer/service_types/worker.rb
|
189
220
|
- lib/scaltainer/version.rb
|
221
|
+
- publish.sh
|
190
222
|
- scaltainer.gemspec
|
191
223
|
homepage: https://github.com/hammady/scaltainer
|
192
224
|
licenses:
|
@@ -207,7 +239,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
207
239
|
- !ruby/object:Gem::Version
|
208
240
|
version: '0'
|
209
241
|
requirements: []
|
210
|
-
rubygems_version: 3.
|
242
|
+
rubygems_version: 3.1.6
|
211
243
|
signing_key:
|
212
244
|
specification_version: 4
|
213
245
|
summary: Autoscale kubernetes controllers and docker services based on application
|