hako 0.16.0 → 0.17.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7c78bf9739661a4f8020dadce5cd49efd68092f0
4
- data.tar.gz: 731b2f7faec9a00225048cbbcfa3c3223326d15b
3
+ metadata.gz: ee95e37d80652b4fab57fff012c2b40e0b8ee5d2
4
+ data.tar.gz: 30ddde0b682e1dc63d1119c1de91c7bb2dc3dacf
5
5
  SHA512:
6
- metadata.gz: e7725a47c69273f2604a0039ec74a0a5d4d4a2c785642287689b6cec0ba58dc9ab790d1c659372de27fd1e34f18a878486b1abd5adb37e70ba4ec954683f893e
7
- data.tar.gz: 511a77047f7c97c91114ab1dfad3b90828c1cdaf991c3476cf92eafc344197767b4109873b34ef8913e0e43c6c92e54d2657fcf85db4f978fa5af3ded2563a05
6
+ metadata.gz: 59d03d5f2422b3fb21dcc20db36cc850a49ac6fab2af338b94db6946a6a0b01fa8d2ffdb2252a7e8b12be245de4899e391182d082d07a54d4e43ed150f8e2e6a
7
+ data.tar.gz: d8cc1d44728b3c9a64287a9e82d6633fb24bca4ff3a638a1b540251d5df02d05dd3c4be0849c4d8c5ac0bfce6be5a5d5a06b54c95abcde33dc162a6af435bb92
@@ -0,0 +1,56 @@
1
+ scheduler:
2
+ type: ecs
3
+ region: ap-northeast-1
4
+ cluster: eagletmt
5
+ desired_count: 2
6
+ role: ecsServiceRole
7
+ elb:
8
+ listeners:
9
+ - load_balancer_port: 80
10
+ protocol: HTTP
11
+ subnets:
12
+ - subnet-XXXXXXXX
13
+ - subnet-YYYYYYYY
14
+ security_groups:
15
+ - sg-ZZZZZZZZ
16
+ autoscaling:
17
+ role_arn: arn:aws:iam::012345678901:role/ecsAutoscaleRole
18
+ min_capacity: 1
19
+ max_capacity: 4
20
+ policies:
21
+ # Add one task when ecs-scaling-out-hello-autoscaling-service is in alarm state
22
+ - alarms: [ecs-scaling-out-hello-autoscaling-service]
23
+ cooldown: 300
24
+ adjustment_type: ChangeInCapacity
25
+ scaling_adjustment: 1
26
+ metric_interval_lower_bound: 0
27
+ metric_aggregation_type: Average
28
+ # Remove one task when ecs-scaling-in-hello-autoscaling-service is in alarm state
29
+ - alarms: [ecs-scaling-in-hello-autoscaling-service]
30
+ cooldown: 300
31
+ adjustment_type: ChangeInCapacity
32
+ scaling_adjustment: 1
33
+ metric_interval_upper_bound: 0
34
+ metric_aggregation_type: Average
35
+ app:
36
+ image: ryotarai/hello-sinatra
37
+ memory: 128
38
+ cpu: 256
39
+ port: 3000
40
+ env:
41
+ $providers:
42
+ - type: file
43
+ path: hello.env
44
+ PORT: 3000
45
+ MESSAGE: '#{username}-san'
46
+ additional_containers:
47
+ front:
48
+ image_tag: hako-nginx
49
+ memory: 32
50
+ cpu: 32
51
+ scripts:
52
+ - <<: !include front.yml
53
+ locations:
54
+ /:
55
+ allow_only_from:
56
+ - 10.0.0.0/24
@@ -3,7 +3,7 @@ scheduler:
3
3
  region: ap-northeast-1
4
4
  cluster: eagletmt
5
5
  desired_count: 2
6
- task_role_arn: HelloRole
6
+ task_role_arn: arn:aws:iam::012345678901:role/HelloRole
7
7
  app:
8
8
  image: ryotarai/hello-sinatra
9
9
  memory: 128
@@ -4,6 +4,7 @@ require 'hako'
4
4
  require 'hako/scheduler'
5
5
  require 'hako/schedulers/ecs_definition_comparator'
6
6
  require 'hako/schedulers/ecs_elb'
7
+ require 'hako/schedulers/ecs_autoscaling'
7
8
 
8
9
  module Hako
9
10
  module Schedulers
@@ -21,6 +22,9 @@ module Hako
21
22
  @role = options.fetch('role', nil)
22
23
  @task_role_arn = options.fetch('task_role_arn', nil)
23
24
  @ecs_elb_options = options.fetch('elb', nil)
25
+ if options.key?('autoscaling')
26
+ @autoscaling = EcsAutoscaling.new(options.fetch('autoscaling'), dry_run: @dry_run)
27
+ end
24
28
  @started_at = nil
25
29
  @container_instance_arn = nil
26
30
  end
@@ -39,6 +43,9 @@ module Hako
39
43
  definitions.each do |d|
40
44
  Hako.logger.info "Add container #{d}"
41
45
  end
46
+ if @autoscaling
47
+ @autoscaling.apply(Aws::ECS::Types::Service.new(cluster_arn: @cluster, service_name: @app_id))
48
+ end
42
49
  else
43
50
  task_definition = register_task_definition(definitions)
44
51
  if task_definition == :noop
@@ -50,8 +57,14 @@ module Hako
50
57
  service = create_or_update_service(task_definition.task_definition_arn, front_port)
51
58
  if service == :noop
52
59
  Hako.logger.info "Service isn't changed"
60
+ if @autoscaling
61
+ @autoscaling.apply(describe_service)
62
+ end
53
63
  else
54
64
  Hako.logger.info "Updated service: #{service.service_arn}"
65
+ if @autoscaling
66
+ @autoscaling.apply(service)
67
+ end
55
68
  wait_for_ready(service)
56
69
  end
57
70
  Hako.logger.info 'Deployment completed'
@@ -532,6 +545,10 @@ module Hako
532
545
  desired_count: @desired_count,
533
546
  task_definition: task_definition_arn,
534
547
  }
548
+ if @autoscaling
549
+ # Keep current desired_count if autoscaling is enabled
550
+ params[:desired_count] = service.desired_count
551
+ end
535
552
  if service_changed?(service, params)
536
553
  ecs_client.update_service(params).service
537
554
  else
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+ require 'hako'
3
+ require 'hako/error'
4
+
5
+ module Hako
6
+ module Schedulers
7
+ class EcsAutoscaling
8
+ def initialize(options, dry_run:)
9
+ @dry_run = dry_run
10
+ @role_arn = required_option(options, 'role_arn')
11
+ @min_capacity = required_option(options, 'min_capacity')
12
+ @max_capacity = required_option(options, 'max_capacity')
13
+ @policies = required_option(options, 'policies').map { |r| Policy.new(r) }
14
+ end
15
+
16
+ PUT_METRIC_ALARM_OPTIONS = %i[
17
+ alarm_name alarm_description actions_enabled ok_actions alarm_actions
18
+ insufficient_data_actions metric_name namespace statistic dimensions
19
+ period unit evaluation_periods threshold comparison_operator
20
+ ].freeze
21
+
22
+ # @param [Aws::ECS::Types::Service] service
23
+ # @return [nil]
24
+ def apply(service)
25
+ resource_id = "service/#{service.cluster_arn.slice(%r{[^/]+\z}, 0)}/#{service.service_name}"
26
+ service_namespace = 'ecs'
27
+ scalable_dimension = 'ecs:service:DesiredCount'
28
+
29
+ Hako.logger.info("Registering scalable target to #{resource_id}")
30
+ unless @dry_run
31
+ autoscaling_client.register_scalable_target(
32
+ service_namespace: service_namespace,
33
+ resource_id: resource_id,
34
+ scalable_dimension: scalable_dimension,
35
+ min_capacity: @min_capacity,
36
+ max_capacity: @max_capacity,
37
+ role_arn: @role_arn,
38
+ )
39
+ end
40
+ @policies.each do |policy|
41
+ Hako.logger.info("Configuring scaling policy #{policy.name}")
42
+ if @dry_run
43
+ policy.alarms.each do |alarm_name|
44
+ Hako.logger.info("Configuring #{alarm_name}'s alarm_action")
45
+ end
46
+ else
47
+ policy_arn = autoscaling_client.put_scaling_policy(
48
+ policy_name: policy.name,
49
+ service_namespace: service_namespace,
50
+ resource_id: resource_id,
51
+ scalable_dimension: scalable_dimension,
52
+ policy_type: 'StepScaling',
53
+ step_scaling_policy_configuration: {
54
+ adjustment_type: policy.adjustment_type,
55
+ step_adjustments: [
56
+ {
57
+ scaling_adjustment: policy.scaling_adjustment,
58
+ metric_interval_lower_bound: policy.metric_interval_lower_bound,
59
+ metric_interval_upper_bound: policy.metric_interval_upper_bound,
60
+ },
61
+ ],
62
+ cooldown: policy.cooldown,
63
+ metric_aggregation_type: policy.metric_aggregation_type,
64
+ },
65
+ ).policy_arn
66
+
67
+ alarms = cw_client.describe_alarms(alarm_names: policy.alarms).flat_map(&:metric_alarms).map { |a| [a.alarm_name, a] }.to_h
68
+ policy.alarms.each do |alarm_name|
69
+ alarm = alarms.fetch(alarm_name) { raise Error.new("Alarm #{alarm_name} does not exist") }
70
+ Hako.logger.info("Updating #{alarm_name}'s alarm_actions from #{alarm.alarm_actions} to #{[policy_arn]}")
71
+ params = PUT_METRIC_ALARM_OPTIONS.map { |key| [key, alarm.public_send(key)] }.to_h
72
+ params[:alarm_actions] = [policy_arn]
73
+ cw_client.put_metric_alarm(params)
74
+ end
75
+ end
76
+ end
77
+ nil
78
+ end
79
+
80
+ private
81
+
82
+ # @param [Hash] options
83
+ # @param [String] key
84
+ # @return [Object]
85
+ def required_option(options, key)
86
+ options.fetch(key) { raise Error.new("scheduler.autoscaling.#{key} must be set") }
87
+ end
88
+
89
+ # @return [Aws::ApplicationAutoScaling]
90
+ def autoscaling_client
91
+ @autoscaling_client ||= Aws::ApplicationAutoScaling::Client.new
92
+ end
93
+
94
+ # @return [Aws::CloudWatch::Client]
95
+ def cw_client
96
+ @cw_client ||= Aws::CloudWatch::Client.new
97
+ end
98
+
99
+ class Policy
100
+ attr_reader :alarms, :cooldown, :adjustment_type, :scaling_adjustment, :metric_interval_lower_bound, :metric_interval_upper_bound, :metric_aggregation_type
101
+
102
+ # @param [Hash] options
103
+ def initialize(options)
104
+ @alarms = required_option(options, 'alarms')
105
+ @cooldown = required_option(options, 'cooldown')
106
+ @adjustment_type = required_option(options, 'adjustment_type')
107
+ @scaling_adjustment = required_option(options, 'scaling_adjustment')
108
+ @metric_interval_lower_bound = options.fetch('metric_interval_lower_bound', nil)
109
+ @metric_interval_upper_bound = options.fetch('metric_interval_upper_bound', nil)
110
+ @metric_aggregation_type = required_option(options, 'metric_aggregation_type')
111
+ end
112
+
113
+ # @return [String]
114
+ def name
115
+ alarms.join('-and-')
116
+ end
117
+
118
+ private
119
+
120
+ # @param [Hash] options
121
+ # @param [String] key
122
+ # @return [Object]
123
+ def required_option(options, key)
124
+ options.fetch(key) { raise Error.new("scheduler.autoscaling.policies.#{key} must be set") }
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Hako
3
- VERSION = '0.16.0'
3
+ VERSION = '0.17.0'
4
4
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hako
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.16.0
4
+ version: 0.17.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kohei Suzuki
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-07-14 00:00:00.000000000 Z
11
+ date: 2016-07-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aws-sdk
@@ -114,6 +114,7 @@ files:
114
114
  - bin/console
115
115
  - bin/setup
116
116
  - examples/front.yml
117
+ - examples/hello-autoscaling.yml
117
118
  - examples/hello-lb.yml
118
119
  - examples/hello.env
119
120
  - examples/hello.yml
@@ -135,6 +136,7 @@ files:
135
136
  - lib/hako/scheduler.rb
136
137
  - lib/hako/schedulers.rb
137
138
  - lib/hako/schedulers/ecs.rb
139
+ - lib/hako/schedulers/ecs_autoscaling.rb
138
140
  - lib/hako/schedulers/ecs_definition_comparator.rb
139
141
  - lib/hako/schedulers/ecs_elb.rb
140
142
  - lib/hako/script.rb