app/models/miq_worker/container_common.rb
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
env = container_environment_variables.merge(environment_variables).map { |name, value| {:name => name, :value => value} }
container = definition[:spec][:template][:spec][:containers].first
container[:imagePullPolicy] = container_image_tag.include?("latest") ? "Always" : "IfNotPresent"
container[:image] = container_image
container[:resources] = resource_constraints
container[:env].concat(env)
end
def container_environment_variables
{"WORKER_CLASS_NAME" => self.class.name}
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.present?
"#{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