We are moving the health checks into load_balancers_vms. The main reason these are not handled as part of VM monitoring is because the VM might be up and running but the load balancer makes a decision based on the application state. It is safer to keep this separate. This code will also interract with load balancer and keeping a code path as part of a VM that is not part of a load balancer doesn't seem clever. We are making a couple of logic changes here. 1. The state of the load balancer node is only updated when the monitor is sure their state is changed. This way, we don't have to look into counters at the time of update. 2. IPv4 and IPv6 availability is handled properly. Before, these were kind of mixed up and causing some logical errors. Now, they are distinctly checked and properly declared. This commit itself doesn't simply stop the health probe strands. We will need to handle their migration manually by destroying the strands.
129 lines
5.7 KiB
Ruby
129 lines
5.7 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require_relative "../model"
|
|
|
|
class LoadBalancer < Sequel::Model
|
|
many_to_one :project
|
|
many_to_many :vms
|
|
many_to_many :active_vms, class: :Vm, left_key: :load_balancer_id, right_key: :vm_id, join_table: :load_balancers_vms, conditions: {state: ["up"]}
|
|
many_to_many :vms_to_dns, class: :Vm, left_key: :load_balancer_id, right_key: :vm_id, join_table: :load_balancers_vms, conditions: Sequel.~(state: ["evacuating", "detaching"])
|
|
one_to_one :strand, key: :id
|
|
many_to_one :private_subnet
|
|
one_to_many :load_balancers_vms, key: :load_balancer_id, class: :LoadBalancersVms
|
|
many_to_many :certs, join_table: :certs_load_balancers, left_key: :load_balancer_id, right_key: :cert_id
|
|
one_to_many :certs_load_balancers, key: :load_balancer_id, class: :CertsLoadBalancers
|
|
many_to_one :custom_hostname_dns_zone, class: :DnsZone, key: :custom_hostname_dns_zone_id
|
|
|
|
plugin :association_dependencies, load_balancers_vms: :destroy, certs_load_balancers: :destroy
|
|
|
|
include ResourceMethods
|
|
include SemaphoreMethods
|
|
include ObjectTag::Cleanup
|
|
dataset_module Pagination
|
|
semaphore :destroy, :update_load_balancer, :rewrite_dns_records, :refresh_cert
|
|
|
|
def path
|
|
"/location/#{private_subnet.display_location}/load-balancer/#{name}"
|
|
end
|
|
|
|
def add_vm(vm)
|
|
DB.transaction do
|
|
LoadBalancersVms.create_with_id(load_balancer_id: id, vm_id: vm.id)
|
|
|
|
Strand.create_with_id(prog: "Vnet::CertServer", label: "put_certificate", stack: [{subject_id: id, vm_id: vm.id}], parent_id: id)
|
|
incr_rewrite_dns_records
|
|
end
|
|
end
|
|
|
|
def detach_vm(vm)
|
|
load_balancers_vms_dataset.where(vm_id: vm.id, state: ["up", "down", "evacuating"]).update(state: "detaching")
|
|
Strand.create_with_id(prog: "Vnet::CertServer", label: "remove_cert_server", stack: [{subject_id: id, vm_id: vm.id}], parent_id: id)
|
|
incr_update_load_balancer
|
|
end
|
|
|
|
def evacuate_vm(vm)
|
|
DB.transaction do
|
|
load_balancers_vms_dataset.where(vm_id: vm.id, state: ["up", "down"]).update(state: "evacuating")
|
|
Strand.create_with_id(prog: "Vnet::CertServer", label: "remove_cert_server", stack: [{subject_id: id, vm_id: vm.id}], parent_id: id)
|
|
incr_update_load_balancer
|
|
incr_rewrite_dns_records
|
|
end
|
|
end
|
|
|
|
def remove_vm(vm)
|
|
load_balancers_vms_dataset[vm_id: vm.id].destroy
|
|
incr_rewrite_dns_records
|
|
end
|
|
|
|
def hostname
|
|
custom_hostname || "#{name}.#{private_subnet.ubid[-5...]}.#{Config.load_balancer_service_hostname}"
|
|
end
|
|
|
|
def dns_zone
|
|
custom_hostname_dns_zone || DnsZone[project_id: Config.load_balancer_service_project_id, name: Config.load_balancer_service_hostname]
|
|
end
|
|
|
|
def need_certificates?
|
|
return true if certs_dataset.empty?
|
|
|
|
certs_dataset.where { created_at > Time.now - 60 * 60 * 24 * 30 * 2 }.empty?
|
|
end
|
|
|
|
def active_cert
|
|
certs_dataset.where { created_at > Time.now - 60 * 60 * 24 * 30 * 3 }.order(Sequel.desc(:created_at)).first
|
|
end
|
|
|
|
def ipv4_enabled?
|
|
stack == Stack::IPV4 || stack == Stack::DUAL
|
|
end
|
|
|
|
def ipv6_enabled?
|
|
stack == Stack::IPV6 || stack == Stack::DUAL
|
|
end
|
|
|
|
module Stack
|
|
IPV4 = "ipv4"
|
|
IPV6 = "ipv6"
|
|
DUAL = "dual"
|
|
end
|
|
end
|
|
|
|
# Table: load_balancer
|
|
# Columns:
|
|
# id | uuid | PRIMARY KEY
|
|
# name | text | NOT NULL
|
|
# algorithm | lb_algorithm | NOT NULL DEFAULT 'round_robin'::lb_algorithm
|
|
# src_port | integer | NOT NULL
|
|
# dst_port | integer | NOT NULL
|
|
# private_subnet_id | uuid | NOT NULL
|
|
# health_check_endpoint | text | NOT NULL
|
|
# health_check_interval | integer | NOT NULL DEFAULT 10
|
|
# health_check_timeout | integer | NOT NULL DEFAULT 5
|
|
# health_check_up_threshold | integer | NOT NULL DEFAULT 5
|
|
# health_check_down_threshold | integer | NOT NULL DEFAULT 3
|
|
# health_check_protocol | lb_hc_protocol | NOT NULL DEFAULT 'http'::lb_hc_protocol
|
|
# custom_hostname | text |
|
|
# custom_hostname_dns_zone_id | uuid |
|
|
# stack | lb_stack | NOT NULL DEFAULT 'dual'::lb_stack
|
|
# project_id | uuid | NOT NULL
|
|
# Indexes:
|
|
# load_balancer_pkey | PRIMARY KEY btree (id)
|
|
# load_balancer_custom_hostname_key | UNIQUE btree (custom_hostname)
|
|
# load_balancer_private_subnet_id_name_uidx | UNIQUE btree (private_subnet_id, name)
|
|
# Check constraints:
|
|
# health_check_down_threshold_gt_0 | (health_check_down_threshold > 0)
|
|
# health_check_interval_gt_0 | (health_check_interval > 0)
|
|
# health_check_interval_lt_600 | (health_check_interval < 600)
|
|
# health_check_timeout_gt_0 | (health_check_timeout > 0)
|
|
# health_check_timeout_lt_health_check_interval | (health_check_timeout <= health_check_interval)
|
|
# health_check_up_threshold_gt_0 | (health_check_up_threshold > 0)
|
|
# Foreign key constraints:
|
|
# load_balancer_custom_hostname_dns_zone_id_fkey | (custom_hostname_dns_zone_id) REFERENCES dns_zone(id)
|
|
# load_balancer_private_subnet_id_fkey | (private_subnet_id) REFERENCES private_subnet(id)
|
|
# load_balancer_project_id_fkey | (project_id) REFERENCES project(id)
|
|
# Referenced By:
|
|
# certs_load_balancers | certs_load_balancers_load_balancer_id_fkey | (load_balancer_id) REFERENCES load_balancer(id)
|
|
# inference_endpoint | inference_endpoint_load_balancer_id_fkey | (load_balancer_id) REFERENCES load_balancer(id)
|
|
# kubernetes_cluster | kubernetes_cluster_api_server_lb_id_fkey | (api_server_lb_id) REFERENCES load_balancer(id)
|
|
# load_balancers_vms | load_balancers_vms_load_balancer_id_fkey | (load_balancer_id) REFERENCES load_balancer(id)
|