forked from ManageIQ/manageiq
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontainer_common.rb
126 lines (102 loc) · 4.66 KB
/
container_common.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
class MiqWorker
module ContainerCommon
extend ActiveSupport::Concern
def configure_worker_deployment(definition, replicas = 0)
definition[:spec][:replicas] = replicas
definition[:spec][:template][:spec][:terminationGracePeriodSeconds] = self.class.worker_settings[:stopping_timeout].seconds
if MiqServer.my_zone != "default"
definition[:spec][:template][:spec][:nodeSelector] = zone_selector
end
container = definition[:spec][:template][:spec][:containers].first
if container_image_tag.include?("latest")
container[:imagePullPolicy] = "Always"
else
container[:imagePullPolicy] = "IfNotPresent"
end
container[:image] = container_image
container[:env] << {:name => "WORKER_CLASS_NAME", :value => self.class.name}
container[:env] << {:name => "BUNDLER_GROUPS", :value => self.class.bundler_groups.join(",")}
container[:resources] = resource_constraints
end
def scale_deployment
ContainerOrchestrator.new.scale(worker_deployment_name, self.class.workers)
delete_container_objects if self.class.workers.zero?
end
def patch_deployment
# Start with just resource constraints. Perhaps the livenessProbe, readinessProbe,
# and various timeouts such as terminationGracePeriodSeconds, could be patched later on.
# Note, we need to specify the name and image as they're required fields for the API to 'find'
# the correct container, even if we only ever have one.
data = {
:spec => {
:template => {
:spec => {
:containers => [
{
:name => worker_deployment_name,
:image => container_image,
:resources => resource_constraints
}
]
}
}
}
}
ContainerOrchestrator.new.patch_deployment(worker_deployment_name, data)
end
def zone_selector
product = Vmdb::Appliance.PRODUCT_NAME.downcase.gsub(/[^-a-z0-9\.]/, "-")
zone = MiqServer.my_zone.chomp.strip.gsub(/[^-A-Za-z0-9_\.\/]/, "-")
{"#{product}/zone-#{zone}" => "true"}
end
def container_image
ENV["BASE_WORKER_IMAGE"] || default_image
end
def default_image
"#{container_image_namespace}/#{container_image_name}:#{container_image_tag}"
end
def resource_constraints
return {} unless Settings.server.worker_monitor.enforce_resource_constraints
mem_limit = self.class.worker_settings[:memory_threshold]
cpu_limit = self.class.worker_settings[:cpu_threshold_percent]
# If request > limit, kubeclient will raise each time we try
# [Kubeclient::HttpError]: Deployment.apps "1-schedule" is invalid: spec.template.spec.containers[0].resources.requests: Invalid value: "567Mi": must be less than or equal to memory limit
mem_request = self.class.worker_settings[:memory_request]
cpu_request = self.class.worker_settings[:cpu_request_percent]
raise ArgumentError, "#{self.class.name} - cpu_request_percent (#{cpu_request.inspect}) cannot exceed cpu_threshold_percent (#{cpu_limit.inspect})" if (cpu_request || 0) > (cpu_limit || Float::INFINITY)
raise ArgumentError, "#{self.class.name} - memory_request (#{mem_request.inspect}) cannot exceed memory_threshold (#{mem_limit.inspect})" if (mem_request || 0) > (mem_limit || Float::INFINITY.megabytes)
{}.tap do |h|
h.store_path(:limits, :memory, format_memory_threshold(mem_limit)) if mem_limit
h.store_path(:limits, :cpu, format_cpu_threshold(cpu_limit)) if cpu_limit
h.store_path(:requests, :memory, format_memory_threshold(mem_request)) if mem_request
h.store_path(:requests, :cpu, format_cpu_threshold(cpu_request)) if cpu_request
end
end
def container_image_namespace
ENV["CONTAINER_IMAGE_NAMESPACE"]
end
def container_image_name
"manageiq-base-worker"
end
def container_image_tag
ENV["CONTAINER_IMAGE_TAG"] || "latest"
end
def deployment_prefix
"#{MiqServer.my_server.compressed_id}-"
end
def worker_deployment_name
@worker_deployment_name ||= begin
deployment_name = abbreviated_class_name.dup.chomp("Worker").sub("Manager", "").sub(/^Miq/, "")
deployment_name << "-#{ApplicationRecord.split_id(ems_id).last}" if respond_to?(:ems_id) && ems_id.kind_of?(Fixnum)
"#{deployment_prefix}#{deployment_name.underscore.dasherize.tr("/", "-")}"
end
end
private
def format_memory_threshold(value)
"#{value / 1.megabyte}Mi"
end
def format_cpu_threshold(value)
"#{((value / 100.0) * 1000).to_i}m"
end
end
end