scaltainer 0.4.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
![Build Status](https://github.com/hammady/scaltainer/actions/workflows/tests.yml/badge.svg)
|
2
2
|
[![Coverage Status](https://coveralls.io/repos/github/hammady/scaltainer/badge.svg?service=github&branch=master)](https://coveralls.io/github/hammady/scaltainer?branch=master)
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/scaltainer.svg)](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
|