ecs_deploy 1.0.4 → 1.0.6
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/CHANGELOG.md +17 -0
- data/README.md +16 -17
- data/lib/ecs_deploy/auto_scaler/auto_scaling_group_config.rb +4 -4
- data/lib/ecs_deploy/auto_scaler/cluster_resource_manager.rb +4 -4
- data/lib/ecs_deploy/auto_scaler/instance_drainer.rb +1 -1
- data/lib/ecs_deploy/auto_scaler/service_config.rb +10 -10
- data/lib/ecs_deploy/auto_scaler/spot_fleet_request_config.rb +1 -1
- data/lib/ecs_deploy/auto_scaler.rb +2 -2
- data/lib/ecs_deploy/capistrano.rb +6 -4
- data/lib/ecs_deploy/configuration.rb +3 -1
- data/lib/ecs_deploy/instance_fluctuation_manager.rb +3 -3
- data/lib/ecs_deploy/scheduled_task.rb +4 -3
- data/lib/ecs_deploy/service.rb +12 -6
- data/lib/ecs_deploy/task_definition.rb +11 -14
- data/lib/ecs_deploy/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c835fe6c187c1e2558ba6de3c957bb41f3eafde5804b79fd611864f0ef32aa31
|
|
4
|
+
data.tar.gz: 47b1b66e32e8a246bd97658f85b473f5c07942d73e4bc932685a8fbe7386fd4a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: e599e6a06c67bf78dc17a6b746ba680e8043440dda0870595bd2aa36cb08b6357eb3350c88875897510327fa261fb45cdbd7ff237f0cd5c52a1d6021f910d9fb
|
|
7
|
+
data.tar.gz: f65b908df4382062dec6ba228d1714df5f2b64a516c42450482767ebf48c52345a3d72db465c57fd6058f4082d6b07b2569ce18b369337a2eb71f2ffe9121769
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# v1.0
|
|
2
2
|
|
|
3
|
+
## Release v1.0.6 - 2024/03/19
|
|
4
|
+
|
|
5
|
+
### Enhancement
|
|
6
|
+
|
|
7
|
+
- Make region fallback logic consistent in Capistrano tasks https://github.com/reproio/ecs_deploy/pull/91
|
|
8
|
+
- Add runtime_platform to task_definition. https://github.com/reproio/ecs_deploy/pull/92
|
|
9
|
+
|
|
10
|
+
### Bug fixes
|
|
11
|
+
|
|
12
|
+
- Delete option :placement_strategy if DAEMON service https://github.com/reproio/ecs_deploy/pull/93
|
|
13
|
+
|
|
14
|
+
## Release v1.0.5 - 2023/03/15
|
|
15
|
+
|
|
16
|
+
### Enhancement
|
|
17
|
+
|
|
18
|
+
- Add variable of capistrano `ecs_client_retry_params` to override parameter of ECS::Client#initialize https://github.com/reproio/ecs_deploy/pull/88
|
|
19
|
+
|
|
3
20
|
## Release v1.0.4 - 2023/02/10
|
|
4
21
|
|
|
5
22
|
### Bug fixes
|
data/README.md
CHANGED
|
@@ -1,30 +1,26 @@
|
|
|
1
1
|
# EcsDeploy
|
|
2
2
|
|
|
3
|
-
Helper script for deployment to Amazon ECS
|
|
3
|
+
Helper script for deployment to Amazon ECS, designed to be compatible with `capistrano`.
|
|
4
4
|
|
|
5
5
|
This gem is experimental.
|
|
6
6
|
|
|
7
|
-
Main purpose is combination with capistrano API.
|
|
8
|
-
|
|
9
7
|
## Installation
|
|
10
8
|
|
|
11
9
|
Add this line to your application's Gemfile:
|
|
12
10
|
|
|
13
11
|
```ruby
|
|
14
|
-
gem
|
|
12
|
+
gem "ecs_deploy", github: "reproio/ecs_deploy"
|
|
15
13
|
```
|
|
16
14
|
|
|
17
15
|
And then execute:
|
|
18
16
|
|
|
19
17
|
$ bundle
|
|
20
18
|
|
|
21
|
-
##
|
|
22
|
-
|
|
23
|
-
Use by Capistrano.
|
|
19
|
+
## Configuration
|
|
24
20
|
|
|
25
21
|
```ruby
|
|
26
22
|
# Capfile
|
|
27
|
-
require
|
|
23
|
+
require "ecs_deploy/capistrano"
|
|
28
24
|
|
|
29
25
|
# deploy.rb
|
|
30
26
|
set :ecs_default_cluster, "ecs-cluster-name"
|
|
@@ -33,6 +29,7 @@ set :ecs_service_role, "customEcsServiceRole" # default: ecsServiceRole
|
|
|
33
29
|
set :ecs_deploy_wait_timeout, 600 # default: 300
|
|
34
30
|
set :ecs_wait_until_services_stable_max_attempts, 40 # optional
|
|
35
31
|
set :ecs_wait_until_services_stable_delay, 15 # optional
|
|
32
|
+
set :ecs_client_params, { retry_mode: "standard", max_attempts: 10 } # default: {}
|
|
36
33
|
|
|
37
34
|
set :ecs_tasks, [
|
|
38
35
|
{
|
|
@@ -92,11 +89,11 @@ set :ecs_tasks, [
|
|
|
92
89
|
|
|
93
90
|
set :ecs_scheduled_tasks, [
|
|
94
91
|
{
|
|
95
|
-
cluster: "default", #
|
|
92
|
+
cluster: "default", # Defaults to fetch(:ecs_default_cluster)
|
|
96
93
|
rule_name: "schedule_name",
|
|
97
94
|
schedule_expression: "cron(0 12 * * ? *)",
|
|
98
95
|
description: "schedule_description", # Optional
|
|
99
|
-
target_id: "task_name", #
|
|
96
|
+
target_id: "task_name", # Defaults to the task_definition_name
|
|
100
97
|
task_definition_name: "myapp-#{fetch(:rails_env)}",
|
|
101
98
|
task_count: 2, # Default 1
|
|
102
99
|
revision: 12, # Optional
|
|
@@ -129,12 +126,14 @@ set :ecs_services, [
|
|
|
129
126
|
]
|
|
130
127
|
```
|
|
131
128
|
|
|
129
|
+
## Usage
|
|
130
|
+
|
|
132
131
|
```sh
|
|
133
|
-
cap <stage> ecs:register_task_definition # register ecs_tasks as TaskDefinition
|
|
134
|
-
cap <stage> ecs:deploy_scheduled_task # register ecs_scheduled_tasks to CloudWatchEvent
|
|
135
|
-
cap <stage> ecs:deploy # create or update Service by ecs_services info
|
|
132
|
+
bundle exec cap <stage> ecs:register_task_definition # register ecs_tasks as TaskDefinition
|
|
133
|
+
bundle exec cap <stage> ecs:deploy_scheduled_task # register ecs_scheduled_tasks to CloudWatchEvent
|
|
134
|
+
bundle exec cap <stage> ecs:deploy # create or update Service by ecs_services info
|
|
136
135
|
|
|
137
|
-
cap <stage> ecs:rollback # deregister current task definition and update Service by previous revision of current task definition
|
|
136
|
+
bundle exec cap <stage> ecs:rollback # deregister current task definition and update Service by previous revision of current task definition
|
|
138
137
|
```
|
|
139
138
|
|
|
140
139
|
### Rollback example
|
|
@@ -193,7 +192,7 @@ The autoscaler of `ecs_deploy` supports auto scaling of ECS services and cluster
|
|
|
193
192
|
|
|
194
193
|
### Prerequisits
|
|
195
194
|
|
|
196
|
-
*
|
|
195
|
+
* An ECS cluster whose instances belong to either an Auto Scaling group or a Spot Fleet request
|
|
197
196
|
* You have CloudWatch alarms and you want to scale services when their state changes
|
|
198
197
|
|
|
199
198
|
### How to use autoscaler
|
|
@@ -282,7 +281,7 @@ Then, execute the following command:
|
|
|
282
281
|
ecs_auto_scaler <config yaml>
|
|
283
282
|
```
|
|
284
283
|
|
|
285
|
-
|
|
284
|
+
It is recommended to run the `ecs_auto_scaler` via a container on ECS.
|
|
286
285
|
|
|
287
286
|
### Signals
|
|
288
287
|
|
|
@@ -459,7 +458,7 @@ The following permissions are required for the preceding configuration of "repro
|
|
|
459
458
|
|
|
460
459
|
### How to deploy faster with Auto Scaling Group
|
|
461
460
|
|
|
462
|
-
Add following configuration to your deploy.rb
|
|
461
|
+
Add the following configuration and hooks to your `config/deploy.rb`:
|
|
463
462
|
|
|
464
463
|
```ruby
|
|
465
464
|
# deploy.rb
|
|
@@ -35,7 +35,7 @@ module EcsDeploy
|
|
|
35
35
|
if decreased_capacity > 0
|
|
36
36
|
new_desired_capacity = current_asg.desired_capacity - decreased_capacity
|
|
37
37
|
cluster_resource_manager.trigger_capacity_update(current_asg.desired_capacity, new_desired_capacity)
|
|
38
|
-
@logger.info "#{log_prefix}
|
|
38
|
+
@logger.info "#{log_prefix} Updated desired_capacity to #{new_desired_capacity}"
|
|
39
39
|
else
|
|
40
40
|
@logger.info "#{log_prefix} Tried to Update desired_capacity but there were no deregisterable instances"
|
|
41
41
|
end
|
|
@@ -47,7 +47,7 @@ module EcsDeploy
|
|
|
47
47
|
desired_capacity: desired_capacity,
|
|
48
48
|
)
|
|
49
49
|
cluster_resource_manager.trigger_capacity_update(current_asg.desired_capacity, desired_capacity)
|
|
50
|
-
@logger.info "#{log_prefix}
|
|
50
|
+
@logger.info "#{log_prefix} Updated desired_capacity to #{desired_capacity}"
|
|
51
51
|
end
|
|
52
52
|
rescue => e
|
|
53
53
|
AutoScaler.error_logger.error(e)
|
|
@@ -74,7 +74,7 @@ module EcsDeploy
|
|
|
74
74
|
)
|
|
75
75
|
end
|
|
76
76
|
|
|
77
|
-
@logger.info "#{log_prefix}
|
|
77
|
+
@logger.info "#{log_prefix} Detached instances from ASG: #{instance_ids.inspect}"
|
|
78
78
|
end
|
|
79
79
|
|
|
80
80
|
private
|
|
@@ -89,7 +89,7 @@ module EcsDeploy
|
|
|
89
89
|
auto_scaling_group_instances.any? {|instance| instance.instance_id == i.ec2_instance_id }
|
|
90
90
|
end
|
|
91
91
|
|
|
92
|
-
@logger.info "#{log_prefix}
|
|
92
|
+
@logger.info "#{log_prefix} Fetched deregisterable instances: #{deregisterable_instances.map(&:ec2_instance_id).inspect}"
|
|
93
93
|
|
|
94
94
|
az_to_instance_count = auto_scaling_group_instances.each_with_object(Hash.new(0)) { |i, h| h[i.availability_zone] += 1 }
|
|
95
95
|
az_to_deregisterable_instances = deregisterable_instances.group_by do |i|
|
|
@@ -27,7 +27,7 @@ module EcsDeploy
|
|
|
27
27
|
|
|
28
28
|
def acquire(capacity, timeout: nil)
|
|
29
29
|
@mutex.synchronize do
|
|
30
|
-
@logger&.debug("#{log_prefix}
|
|
30
|
+
@logger&.debug("#{log_prefix} Trying to acquire #{capacity} capacity (capacity: #{@capacity}, used_capacity: #{@used_capacity})")
|
|
31
31
|
Timeout.timeout(timeout) do
|
|
32
32
|
while @capacity - @used_capacity < capacity
|
|
33
33
|
@resource.wait(@mutex)
|
|
@@ -77,7 +77,7 @@ module EcsDeploy
|
|
|
77
77
|
return if new_desired_capacity == old_desired_capacity
|
|
78
78
|
|
|
79
79
|
th = Thread.new do
|
|
80
|
-
@logger&.info "#{log_prefix}
|
|
80
|
+
@logger&.info "#{log_prefix} Updating capacity: #{old_desired_capacity} -> #{new_desired_capacity}"
|
|
81
81
|
Timeout.timeout(180) do
|
|
82
82
|
until @capacity == new_desired_capacity ||
|
|
83
83
|
(new_desired_capacity > old_desired_capacity && @capacity > new_desired_capacity) ||
|
|
@@ -91,7 +91,7 @@ module EcsDeploy
|
|
|
91
91
|
|
|
92
92
|
sleep interval
|
|
93
93
|
end
|
|
94
|
-
@logger&.info "#{log_prefix} capacity
|
|
94
|
+
@logger&.info "#{log_prefix} updated capacity to #{@capacity}"
|
|
95
95
|
end
|
|
96
96
|
rescue Timeout::Error => e
|
|
97
97
|
msg = "#{log_prefix} `#{__method__}': #{e} (#{e.class})"
|
|
@@ -108,7 +108,7 @@ module EcsDeploy
|
|
|
108
108
|
end
|
|
109
109
|
|
|
110
110
|
if wait_until_capacity_updated
|
|
111
|
-
@logger&.info "#{log_prefix}
|
|
111
|
+
@logger&.info "#{log_prefix} Waiting for the number of active instances to reach #{new_desired_capacity} (from #{old_desired_capacity})"
|
|
112
112
|
th.join
|
|
113
113
|
end
|
|
114
114
|
end
|
|
@@ -79,7 +79,7 @@ module EcsDeploy
|
|
|
79
79
|
cl = ecs_client(region)
|
|
80
80
|
config_to_instance_ids.each do |config, instance_ids|
|
|
81
81
|
if config.disable_draining == true || config.disable_draining == "true"
|
|
82
|
-
@logger.info "
|
|
82
|
+
@logger.info "Skipped draining instances: region: #{region}, cluster: #{config.cluster}, instance_ids: #{instance_ids.inspect}"
|
|
83
83
|
next
|
|
84
84
|
end
|
|
85
85
|
|
|
@@ -40,7 +40,7 @@ module EcsDeploy
|
|
|
40
40
|
next if difference >= trigger.step
|
|
41
41
|
|
|
42
42
|
if trigger.match?
|
|
43
|
-
@logger.info "#{log_prefix}
|
|
43
|
+
@logger.info "#{log_prefix} Firing upscale trigger by #{trigger.alarm_name} #{trigger.state}"
|
|
44
44
|
difference = trigger.step
|
|
45
45
|
end
|
|
46
46
|
end
|
|
@@ -50,7 +50,7 @@ module EcsDeploy
|
|
|
50
50
|
next if difference > 0 && !trigger.prioritized_over_upscale_triggers?
|
|
51
51
|
next unless trigger.match?
|
|
52
52
|
|
|
53
|
-
@logger.info "#{log_prefix}
|
|
53
|
+
@logger.info "#{log_prefix} Firing downscale trigger by #{trigger.alarm_name} #{trigger.state}"
|
|
54
54
|
difference = [difference, -trigger.step].min
|
|
55
55
|
end
|
|
56
56
|
end
|
|
@@ -124,28 +124,28 @@ module EcsDeploy
|
|
|
124
124
|
if current_level < next_level && overheat? # next max
|
|
125
125
|
level = next_level
|
|
126
126
|
@reach_max_at = nil
|
|
127
|
-
@logger.info "#{log_prefix} Service is
|
|
127
|
+
@logger.info "#{log_prefix} Service is overheated, uses next max count"
|
|
128
128
|
elsif current_level < next_level && !overheat? # wait cooldown
|
|
129
129
|
level = current_level
|
|
130
130
|
now = Process.clock_gettime(Process::CLOCK_MONOTONIC, :second)
|
|
131
131
|
@reach_max_at ||= now
|
|
132
|
-
@logger.info "#{log_prefix} Service
|
|
132
|
+
@logger.info "#{log_prefix} Service waiting for cooldown period to elapse #{(now - @reach_max_at).to_i}sec"
|
|
133
133
|
elsif current_level == next_level && next_desired_count >= max_task_count[current_level] # reach current max
|
|
134
134
|
level = current_level
|
|
135
135
|
now = Process.clock_gettime(Process::CLOCK_MONOTONIC, :second)
|
|
136
136
|
@reach_max_at ||= now
|
|
137
|
-
@logger.info "#{log_prefix} Service
|
|
137
|
+
@logger.info "#{log_prefix} Service waiting for cooldown period to elapse #{(now - @reach_max_at).to_i}sec"
|
|
138
138
|
if next_desired_count > max_task_count[current_level] && current_level == max_task_count.size - 1
|
|
139
139
|
@logger.warn "#{log_prefix} Desired count has reached the maximum value and couldn't be increased"
|
|
140
140
|
end
|
|
141
141
|
elsif current_level == next_level && next_desired_count < max_task_count[current_level]
|
|
142
142
|
level = current_level
|
|
143
143
|
@reach_max_at = nil
|
|
144
|
-
@logger.info "#{log_prefix} Service
|
|
144
|
+
@logger.info "#{log_prefix} Service has finished cooling down"
|
|
145
145
|
elsif current_level > next_level
|
|
146
146
|
level = next_level
|
|
147
147
|
@reach_max_at = nil
|
|
148
|
-
@logger.info "#{log_prefix} Service
|
|
148
|
+
@logger.info "#{log_prefix} Service has finished cooling down"
|
|
149
149
|
end
|
|
150
150
|
|
|
151
151
|
next_desired_count = [next_desired_count, max_task_count[level]].min
|
|
@@ -156,7 +156,7 @@ module EcsDeploy
|
|
|
156
156
|
end
|
|
157
157
|
|
|
158
158
|
@last_updated_at = Process.clock_gettime(Process::CLOCK_MONOTONIC, :second)
|
|
159
|
-
@logger.info "#{log_prefix}
|
|
159
|
+
@logger.info "#{log_prefix} Updated desired_count to #{next_desired_count}"
|
|
160
160
|
rescue => e
|
|
161
161
|
AutoScaler.error_logger.error(e)
|
|
162
162
|
end
|
|
@@ -197,7 +197,7 @@ module EcsDeploy
|
|
|
197
197
|
|
|
198
198
|
cl.wait_until(:services_stable, cluster: cluster, services: [name]) do |w|
|
|
199
199
|
w.before_wait do
|
|
200
|
-
@logger.debug "#{log_prefix}
|
|
200
|
+
@logger.debug "#{log_prefix} waiting for service to stabilize"
|
|
201
201
|
end
|
|
202
202
|
end
|
|
203
203
|
|
|
@@ -205,7 +205,7 @@ module EcsDeploy
|
|
|
205
205
|
stopping_task_arns.each_slice(MAX_DESCRIBABLE_TASK_COUNT) do |arns|
|
|
206
206
|
cl.wait_until(:tasks_stopped, cluster: cluster, tasks: arns) do |w|
|
|
207
207
|
w.before_wait do
|
|
208
|
-
@logger.debug "#{log_prefix}
|
|
208
|
+
@logger.debug "#{log_prefix} waiting for tasks to finish stopping"
|
|
209
209
|
end
|
|
210
210
|
end
|
|
211
211
|
end
|
|
@@ -43,7 +43,7 @@ module EcsDeploy
|
|
|
43
43
|
# Wait until the capacity is updated to prevent the process from terminating before container draining is completed
|
|
44
44
|
wait_until_capacity_updated: desired_capacity < request_config.target_capacity,
|
|
45
45
|
)
|
|
46
|
-
@logger.info "#{log_prefix}
|
|
46
|
+
@logger.info "#{log_prefix} Updated desired_capacity to #{desired_capacity}"
|
|
47
47
|
rescue => e
|
|
48
48
|
AutoScaler.error_logger.error(e)
|
|
49
49
|
end
|
|
@@ -50,7 +50,7 @@ module EcsDeploy
|
|
|
50
50
|
loop_with_polling_interval("loop of #{cluster_scaling_config.name}") do
|
|
51
51
|
ths = cluster_scaling_config.service_configs.map do |service_config|
|
|
52
52
|
Thread.new(service_config) do |s|
|
|
53
|
-
@logger.debug "
|
|
53
|
+
@logger.debug "Scaling service #{s.name}"
|
|
54
54
|
s.adjust_desired_count(cluster_scaling_config.cluster_resource_manager)
|
|
55
55
|
end
|
|
56
56
|
end
|
|
@@ -58,7 +58,7 @@ module EcsDeploy
|
|
|
58
58
|
|
|
59
59
|
ths.each(&:join)
|
|
60
60
|
|
|
61
|
-
@logger.debug "
|
|
61
|
+
@logger.debug "Scaling cluster #{cluster_scaling_config.name}"
|
|
62
62
|
|
|
63
63
|
required_capacity = cluster_scaling_config.service_configs.sum { |s| s.desired_count * s.required_capacity }
|
|
64
64
|
cluster_scaling_config.update_desired_capacity(required_capacity)
|
|
@@ -10,6 +10,7 @@ namespace :ecs do
|
|
|
10
10
|
c.default_region = Array(fetch(:ecs_region))[0] if fetch(:ecs_region)
|
|
11
11
|
c.ecs_wait_until_services_stable_max_attempts = fetch(:ecs_wait_until_services_stable_max_attempts) if fetch(:ecs_wait_until_services_stable_max_attempts)
|
|
12
12
|
c.ecs_wait_until_services_stable_delay = fetch(:ecs_wait_until_services_stable_delay) if fetch(:ecs_wait_until_services_stable_delay)
|
|
13
|
+
c.ecs_client_params = fetch(:ecs_client_params) if fetch(:ecs_client_params)
|
|
13
14
|
end
|
|
14
15
|
|
|
15
16
|
if ENV["TARGET_CLUSTER"]
|
|
@@ -41,6 +42,7 @@ namespace :ecs do
|
|
|
41
42
|
cpu: t[:cpu],
|
|
42
43
|
memory: t[:memory],
|
|
43
44
|
tags: t[:tags],
|
|
45
|
+
runtime_platform: t[:runtime_platform],
|
|
44
46
|
)
|
|
45
47
|
result = task_definition.register
|
|
46
48
|
ecs_registered_tasks[region][t[:name]] = result
|
|
@@ -54,7 +56,7 @@ namespace :ecs do
|
|
|
54
56
|
task deploy_scheduled_task: [:configure, :register_task_definition] do
|
|
55
57
|
if fetch(:ecs_scheduled_tasks)
|
|
56
58
|
regions = Array(fetch(:ecs_region))
|
|
57
|
-
regions = [
|
|
59
|
+
regions = [EcsDeploy.config.default_region] if regions.empty?
|
|
58
60
|
regions.each do |r|
|
|
59
61
|
fetch(:ecs_scheduled_tasks).each do |t|
|
|
60
62
|
scheduled_task = EcsDeploy::ScheduledTask.new(
|
|
@@ -84,7 +86,7 @@ namespace :ecs do
|
|
|
84
86
|
task deploy: [:configure, :register_task_definition] do
|
|
85
87
|
if fetch(:ecs_services)
|
|
86
88
|
regions = Array(fetch(:ecs_region))
|
|
87
|
-
regions = [
|
|
89
|
+
regions = [EcsDeploy.config.default_region] if regions.empty?
|
|
88
90
|
regions.each do |r|
|
|
89
91
|
services = fetch(:ecs_services).map do |service|
|
|
90
92
|
if fetch(:target_cluster) && fetch(:target_cluster).size > 0
|
|
@@ -127,7 +129,7 @@ namespace :ecs do
|
|
|
127
129
|
task rollback: [:configure] do
|
|
128
130
|
if fetch(:ecs_services)
|
|
129
131
|
regions = Array(fetch(:ecs_region))
|
|
130
|
-
regions = [
|
|
132
|
+
regions = [EcsDeploy.config.default_region] if regions.empty?
|
|
131
133
|
|
|
132
134
|
rollback_routes = {}
|
|
133
135
|
regions.each do |r|
|
|
@@ -164,7 +166,7 @@ namespace :ecs do
|
|
|
164
166
|
|
|
165
167
|
EcsDeploy.logger.info "#{current_task_definition_arn} -> #{rollback_arn}"
|
|
166
168
|
|
|
167
|
-
raise "Past task_definition_arns is
|
|
169
|
+
raise "Past task_definition_arns is empty" unless rollback_arn
|
|
168
170
|
|
|
169
171
|
service_options = {
|
|
170
172
|
region: r,
|
|
@@ -8,7 +8,8 @@ module EcsDeploy
|
|
|
8
8
|
:deploy_wait_timeout,
|
|
9
9
|
:ecs_service_role,
|
|
10
10
|
:ecs_wait_until_services_stable_max_attempts,
|
|
11
|
-
:ecs_wait_until_services_stable_delay
|
|
11
|
+
:ecs_wait_until_services_stable_delay,
|
|
12
|
+
:ecs_client_params
|
|
12
13
|
|
|
13
14
|
def initialize
|
|
14
15
|
@log_level = :info
|
|
@@ -16,6 +17,7 @@ module EcsDeploy
|
|
|
16
17
|
# The following values are the default values of Aws::ECS::Waiters::ServicesStable
|
|
17
18
|
@ecs_wait_until_services_stable_max_attempts = 40
|
|
18
19
|
@ecs_wait_until_services_stable_delay = 15
|
|
20
|
+
@ecs_client_params = {}
|
|
19
21
|
end
|
|
20
22
|
end
|
|
21
23
|
end
|
|
@@ -21,7 +21,7 @@ module EcsDeploy
|
|
|
21
21
|
def increase
|
|
22
22
|
asg = fetch_auto_scaling_group
|
|
23
23
|
|
|
24
|
-
@logger.info("
|
|
24
|
+
@logger.info("Increasing desired capacity of #{@auto_scaling_group_name}: #{asg.desired_capacity} => #{asg.max_size}")
|
|
25
25
|
as_client.update_auto_scaling_group(auto_scaling_group_name: @auto_scaling_group_name, desired_capacity: asg.max_size)
|
|
26
26
|
|
|
27
27
|
# Run in background because increasing instances may take time
|
|
@@ -47,7 +47,7 @@ module EcsDeploy
|
|
|
47
47
|
@logger.info("The capacity is already #{asg.desired_capacity}")
|
|
48
48
|
return
|
|
49
49
|
end
|
|
50
|
-
@logger.info("
|
|
50
|
+
@logger.info("Decreasing desired capacity of #{@auto_scaling_group_name}: #{asg.desired_capacity} => #{@desired_capacity}")
|
|
51
51
|
|
|
52
52
|
container_instances = ecs_client.list_container_instances(cluster: @cluster).flat_map do |resp|
|
|
53
53
|
ecs_client.describe_container_instances(
|
|
@@ -113,7 +113,7 @@ module EcsDeploy
|
|
|
113
113
|
end
|
|
114
114
|
|
|
115
115
|
def ecs_client
|
|
116
|
-
@ecs_client ||= Aws::ECS::Client.new(aws_params)
|
|
116
|
+
@ecs_client ||= Aws::ECS::Client.new(aws_params.merge(EcsDeploy.config.ecs_client_params))
|
|
117
117
|
end
|
|
118
118
|
|
|
119
119
|
def fetch_auto_scaling_group
|
|
@@ -27,9 +27,10 @@ module EcsDeploy
|
|
|
27
27
|
@platform_version = platform_version
|
|
28
28
|
@group = group
|
|
29
29
|
region ||= EcsDeploy.config.default_region
|
|
30
|
+
params ||= EcsDeploy.config.ecs_client_params
|
|
30
31
|
@container_overrides = container_overrides
|
|
31
32
|
|
|
32
|
-
@client = region ? Aws::ECS::Client.new(region: region) : Aws::ECS::Client.new
|
|
33
|
+
@client = region ? Aws::ECS::Client.new(params.merge(region: region)) : Aws::ECS::Client.new(params)
|
|
33
34
|
@region = @client.config.region
|
|
34
35
|
@cloud_watch_events = Aws::CloudWatchEvents::Client.new(region: @region)
|
|
35
36
|
end
|
|
@@ -61,7 +62,7 @@ module EcsDeploy
|
|
|
61
62
|
state: @enabled ? "ENABLED" : "DISABLED",
|
|
62
63
|
description: @description,
|
|
63
64
|
)
|
|
64
|
-
EcsDeploy.logger.info "
|
|
65
|
+
EcsDeploy.logger.info "created cloudwatch event rule [#{res.rule_arn}] [#{@region}] [#{Paint['OK', :green]}]"
|
|
65
66
|
end
|
|
66
67
|
|
|
67
68
|
def put_targets
|
|
@@ -89,7 +90,7 @@ module EcsDeploy
|
|
|
89
90
|
targets: [target]
|
|
90
91
|
)
|
|
91
92
|
if res.failed_entry_count.zero?
|
|
92
|
-
EcsDeploy.logger.info "
|
|
93
|
+
EcsDeploy.logger.info "created cloudwatch event target [#{@target_id}] [#{@region}] [#{Paint['OK', :green]}]"
|
|
93
94
|
else
|
|
94
95
|
res.failed_entries.each do |entry|
|
|
95
96
|
EcsDeploy.logger.error "failed to create cloudwatch event target [#{@region}] target_id=#{entry.target_id} error_code=#{entry.error_code} error_message=#{entry.error_message}"
|
data/lib/ecs_deploy/service.rb
CHANGED
|
@@ -49,7 +49,8 @@ module EcsDeploy
|
|
|
49
49
|
@response = nil
|
|
50
50
|
|
|
51
51
|
region ||= EcsDeploy.config.default_region
|
|
52
|
-
|
|
52
|
+
params ||= EcsDeploy.config.ecs_client_params
|
|
53
|
+
@client = region ? Aws::ECS::Client.new(params.merge(region: region)) : Aws::ECS::Client.new(params)
|
|
53
54
|
@region = @client.config.region
|
|
54
55
|
|
|
55
56
|
@delete = delete
|
|
@@ -102,9 +103,10 @@ module EcsDeploy
|
|
|
102
103
|
if @scheduling_strategy == 'DAEMON'
|
|
103
104
|
service_options[:scheduling_strategy] = @scheduling_strategy
|
|
104
105
|
service_options.delete(:desired_count)
|
|
106
|
+
service_options.delete(:placement_strategy)
|
|
105
107
|
end
|
|
106
108
|
@response = @client.create_service(service_options)
|
|
107
|
-
EcsDeploy.logger.info "
|
|
109
|
+
EcsDeploy.logger.info "created service [#{@service_name}] [#{@cluster}] [#{@region}] [#{Paint['OK', :green]}]"
|
|
108
110
|
else
|
|
109
111
|
return delete_service if @delete
|
|
110
112
|
|
|
@@ -116,8 +118,11 @@ module EcsDeploy
|
|
|
116
118
|
service_options.merge!({force_new_deployment: true}) if need_force_new_deployment?(current_service)
|
|
117
119
|
|
|
118
120
|
update_tags(@service_name, @tags)
|
|
121
|
+
if @scheduling_strategy == 'DAEMON'
|
|
122
|
+
service_options.delete(:placement_strategy)
|
|
123
|
+
end
|
|
119
124
|
@response = @client.update_service(service_options)
|
|
120
|
-
EcsDeploy.logger.info "
|
|
125
|
+
EcsDeploy.logger.info "updated service [#{@service_name}] [#{@cluster}] [#{@region}] [#{Paint['OK', :green]}]"
|
|
121
126
|
end
|
|
122
127
|
end
|
|
123
128
|
|
|
@@ -144,7 +149,7 @@ module EcsDeploy
|
|
|
144
149
|
sleep 1
|
|
145
150
|
end
|
|
146
151
|
@client.delete_service(cluster: @cluster, service: @service_name)
|
|
147
|
-
EcsDeploy.logger.info "
|
|
152
|
+
EcsDeploy.logger.info "deleted service [#{@service_name}] [#{@cluster}] [#{@region}] [#{Paint['OK', :green]}]"
|
|
148
153
|
end
|
|
149
154
|
|
|
150
155
|
def update_tags(service_name, tags)
|
|
@@ -181,11 +186,12 @@ module EcsDeploy
|
|
|
181
186
|
|
|
182
187
|
def self.wait_all_running(services)
|
|
183
188
|
services.group_by { |s| [s.cluster, s.region] }.flat_map do |(cl, region), ss|
|
|
184
|
-
|
|
189
|
+
params ||= EcsDeploy.config.ecs_client_params
|
|
190
|
+
client = Aws::ECS::Client.new(params.merge(region: region))
|
|
185
191
|
ss.reject(&:delete).map(&:service_name).each_slice(MAX_DESCRIBE_SERVICES).map do |chunked_service_names|
|
|
186
192
|
Thread.new do
|
|
187
193
|
EcsDeploy.config.ecs_wait_until_services_stable_max_attempts.times do
|
|
188
|
-
EcsDeploy.logger.info "
|
|
194
|
+
EcsDeploy.logger.info "waiting for services to stabilize [#{chunked_service_names.join(", ")}] [#{cl}]"
|
|
189
195
|
resp = client.describe_services(cluster: cl, services: chunked_service_names)
|
|
190
196
|
resp.services.each do |s|
|
|
191
197
|
# cf. https://github.com/aws/aws-sdk-ruby/blob/master/gems/aws-sdk-ecs/lib/aws-sdk-ecs/waiters.rb#L91-L96
|
|
@@ -1,19 +1,13 @@
|
|
|
1
1
|
module EcsDeploy
|
|
2
2
|
class TaskDefinition
|
|
3
|
-
RETRY_BACKOFF = lambda do |c|
|
|
4
|
-
sleep(1)
|
|
5
|
-
end
|
|
6
|
-
|
|
7
|
-
RETRY_LIMIT = 10
|
|
8
|
-
|
|
9
3
|
def self.deregister(arn, region: nil)
|
|
10
4
|
region ||= EcsDeploy.config.default_region
|
|
11
|
-
|
|
12
|
-
client = region ? Aws::ECS::Client.new(
|
|
5
|
+
params ||= EcsDeploy.config.ecs_client_params
|
|
6
|
+
client = region ? Aws::ECS::Client.new(params.merge(region: region)) : Aws::ECS::Client.new(params)
|
|
13
7
|
client.deregister_task_definition({
|
|
14
8
|
task_definition: arn,
|
|
15
9
|
})
|
|
16
|
-
EcsDeploy.logger.info "
|
|
10
|
+
EcsDeploy.logger.info "deregistered task definition [#{arn}] [#{client.config.region}] [#{Paint['OK', :green]}]"
|
|
17
11
|
end
|
|
18
12
|
|
|
19
13
|
def initialize(
|
|
@@ -23,12 +17,14 @@ module EcsDeploy
|
|
|
23
17
|
execution_role_arn: nil,
|
|
24
18
|
requires_compatibilities: nil,
|
|
25
19
|
cpu: nil, memory: nil,
|
|
26
|
-
tags: nil
|
|
20
|
+
tags: nil,
|
|
21
|
+
runtime_platform: {}
|
|
27
22
|
)
|
|
28
23
|
@task_definition_name = task_definition_name
|
|
29
24
|
@task_role_arn = task_role_arn
|
|
30
25
|
@execution_role_arn = execution_role_arn
|
|
31
26
|
region ||= EcsDeploy.config.default_region
|
|
27
|
+
params ||= EcsDeploy.config.ecs_client_params
|
|
32
28
|
|
|
33
29
|
@container_definitions = container_definitions.map do |cd|
|
|
34
30
|
if cd[:docker_labels]
|
|
@@ -46,9 +42,9 @@ module EcsDeploy
|
|
|
46
42
|
@cpu = cpu&.to_s
|
|
47
43
|
@memory = memory&.to_s
|
|
48
44
|
@tags = tags
|
|
49
|
-
|
|
50
|
-
@client = region ? Aws::ECS::Client.new(param.merge(region: region)) : Aws::ECS::Client.new(param)
|
|
45
|
+
@client = region ? Aws::ECS::Client.new(params.merge(region: region)) : Aws::ECS::Client.new(params)
|
|
51
46
|
@region = @client.config.region
|
|
47
|
+
@runtime_platform = runtime_platform
|
|
52
48
|
end
|
|
53
49
|
|
|
54
50
|
def recent_task_definition_arns
|
|
@@ -72,9 +68,10 @@ module EcsDeploy
|
|
|
72
68
|
execution_role_arn: @execution_role_arn,
|
|
73
69
|
requires_compatibilities: @requires_compatibilities,
|
|
74
70
|
cpu: @cpu, memory: @memory,
|
|
75
|
-
tags: @tags
|
|
71
|
+
tags: @tags,
|
|
72
|
+
runtime_platform: @runtime_platform
|
|
76
73
|
})
|
|
77
|
-
EcsDeploy.logger.info "
|
|
74
|
+
EcsDeploy.logger.info "registered task definition [#{@task_definition_name}] [#{@region}] [#{Paint['OK', :green]}]"
|
|
78
75
|
res.task_definition
|
|
79
76
|
end
|
|
80
77
|
end
|
data/lib/ecs_deploy/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ecs_deploy
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- joker1007
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2024-03-21 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: aws-sdk-autoscaling
|
|
@@ -236,7 +236,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
236
236
|
- !ruby/object:Gem::Version
|
|
237
237
|
version: '0'
|
|
238
238
|
requirements: []
|
|
239
|
-
rubygems_version: 3.
|
|
239
|
+
rubygems_version: 3.5.6
|
|
240
240
|
signing_key:
|
|
241
241
|
specification_version: 4
|
|
242
242
|
summary: AWS ECS deploy helper
|