Skip to content

Commit

Permalink
Configure dns replicas (#30)
Browse files Browse the repository at this point in the history
  • Loading branch information
SpComb authored and jakolehm committed Mar 6, 2018
1 parent aedefbb commit 372e71a
Show file tree
Hide file tree
Showing 16 changed files with 328 additions and 20 deletions.
3 changes: 2 additions & 1 deletion cluster.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ hosts:
private_address: 10.10.1.3
role: worker
network:
dns_replicas: 3
service_cidr: 10.96.0.0/12
pod_network_cidr: 10.32.0.0/12
trusted_subnets:
Expand All @@ -31,4 +32,4 @@ addons:
enabled: true
interval: 7d
kured:
enabled: true
enabled: true
15 changes: 14 additions & 1 deletion lib/kupo/config.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,21 @@

module Kupo
class Config < Dry::Struct
HOSTS_PER_DNS_REPLICA = 10

attribute :hosts, Types::Coercible::Array.of(Kupo::Configuration::Host)
attribute :network, Kupo::Configuration::Network
attribute :addons, Kupo::Types::Hash

# @return [Integer]
def dns_replicas
if network.dns_replicas
return network.dns_replicas
elsif hosts.length == 1
return 1
else
return 1 + (hosts.length / HOSTS_PER_DNS_REPLICA.to_f).ceil
end
end
end
end
end
14 changes: 13 additions & 1 deletion lib/kupo/config_schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ class ConfigSchema
# @return [Dry::Validation::Schema]
def self.build
Dry::Validation.Form do
configure do
def self.messages
super.merge(
en: { errors: {network_dns_replicas: "network.dns_replicas cannot be larger than the number of hosts"}}
)
end
end
required(:hosts).each do
schema do
required(:address).filled
Expand All @@ -18,12 +25,17 @@ def self.build
end
end
optional(:network).schema do
optional(:dns_replicas).filled(:int?, gt?: 0)
optional(:service_cidr).filled(:str?)
optional(:pod_network_cidr).filled(:str?)
optional(:trusted_subnets).each(type?: String)
end
optional(:addons).filled

validate(network_dns_replicas: [:network, :hosts]) do |network, hosts|
!network[:dns_replicas] || network[:dns_replicas] <= hosts.length
end
end
end
end
end
end
3 changes: 2 additions & 1 deletion lib/kupo/configuration/network.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ module Kupo::Configuration
class Network < Dry::Struct
constructor_type :schema

attribute :dns_replicas, Kupo::Types::Int
attribute :service_cidr, Kupo::Types::String.default('10.96.0.0/12')
attribute :pod_network_cidr, Kupo::Types::String.default('10.32.0.0/12')
attribute :trusted_subnets, Kupo::Types::Array.member(Kupo::Types::String)
end
end
end
47 changes: 40 additions & 7 deletions lib/kupo/kube.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,38 @@ def entities
@entities
end

def entity_for_resource(resource)
name = Kubeclient::ClientMixin.underscore_entity(resource.kind.to_s)
definition = entities[name]

fail "Unknown entity for resource #{resource.kind} => #{name}" unless definition

definition
end

def apis(options= {})
response = rest_client.get(@headers)
format_response(options[:as] || @as, response.body)
end

# @param resource [Kubeclient::Resource]
# @return [Kubeclient::Resource]
def update_resource(resource)
definition = entity_for_resource(resource)

old_resource = get_entity(definition.resource_name, resource.metadata.name, resource.metadata.namespace)
resource.metadata.resourceVersion = old_resource.metadata.resourceVersion
merged_resource = Kubeclient::Resource.new(old_resource.to_h.deep_merge!(resource.to_h, {overwrite_arrays: true}))
update_entity(definition.resource_name, merged_resource)
end

# @param resource [Kubeclient::Resource]
# @return [Kubeclient::Resource]
def create_resource(resource)
definition = entity_for_resource(resource)

create_entity(resource.kind, definition.resource_name, resource)
end
end

RESOURCE_LABEL = 'kupo.kontena.io/stack'.freeze
Expand Down Expand Up @@ -100,17 +128,22 @@ def self.prune_stack(host, stack, checksum)
# @return [Kubeclient::Resource]
def self.apply_resource(host, resource)
resource_client = self.client(host, resource.apiVersion)

begin
definition = resource_client.entities[underscore_entity(resource.kind.to_s)]
old_resource = resource_client.get_entity(definition.resource_name, resource.metadata.name, resource.metadata.namespace)
resource.metadata.resourceVersion = old_resource.metadata.resourceVersion
merged_resource = Kubeclient::Resource.new(old_resource.to_h.deep_merge!(resource.to_h, {overwrite_arrays: true}))
resource_client.update_entity(definition.resource_name, merged_resource)
resource_client.update_resource(resource)
rescue Kubeclient::ResourceNotFoundError
resource_client.create_entity(resource.kind, definition.resource_name, resource)
resource_client.create_resource(resource)
end
end

# @param host [String]
# @param resource [Kubeclient::Resource]
# @return [Kubeclient::Resource]
def self.update_resource(host, resource)
resource_client = self.client(host, resource.apiVersion)
resource_client.update_resource(resource)
end

# @param host [String]
# @param resource [Kubeclient::Resource]
# @return [Kubeclient::Resource]
Expand Down Expand Up @@ -149,4 +182,4 @@ def self.parse_resource_file(path, vars = {})
def self.underscore_entity(kind)
Kubeclient::ClientMixin.underscore_entity(kind.to_s)
end
end
end
3 changes: 2 additions & 1 deletion lib/kupo/phases/configure_client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
module Kupo::Phases
class ConfigureClient < Base

# @param master [Kupo::Configuration::Host]
def initialize(master)
@master = master
end
Expand All @@ -26,4 +27,4 @@ def config_dir
File.join(Dir.home, '.kupo')
end
end
end
end
99 changes: 99 additions & 0 deletions lib/kupo/phases/configure_dns.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
require_relative 'base'

module Kupo::Phases
class ConfigureDNS < Base
# @param master [Kupo::Configuration::Node]
# @param config [Kupo::Config]
def initialize(master, config)
@master = master
@config = config
end

def call
patch_kubedns(
replicas: @config.dns_replicas,
max_surge: self.max_surge,
max_unavailable: self.max_unavailable,
)
end

# @return [Integer]
def max_surge
replicas = @config.dns_replicas
nodes = @config.hosts.length

if replicas == nodes
# cannot create any extra replicas
0
elsif nodes <= replicas * 1.5
# at most one per extra node
nodes - replicas
else
# half
(replicas * 0.5).floor
end
end

# @return [Integer]
def max_unavailable
replicas = @config.dns_replicas

if replicas == 1
# must allow taking down all replicas
1
else
# half
(replicas * 0.5).floor
end
end

# @param replicas [Integer]
# @param nodes [Integer]
def patch_kubedns(replicas: , max_surge: , max_unavailable: )
logger.info(@master.address) { "Patching kube-dns addon with #{replicas} replicas (max-surge #{max_surge}, max-unavailable #{max_unavailable})..." }

kube_client = Kupo::Kube.update_resource(@master.address, Kubeclient::Resource.new({
apiVersion: 'extensions/v1beta1',
kind: 'Deployment',
metadata: {
namespace: 'kube-system',
name: 'kube-dns',
},
spec: {
replicas: replicas,
strategy: {
type: "RollingUpdate",
rollingUpdate: {
maxSurge: max_surge, # must be zero for a two-node cluster
maxUnavailable: max_unavailable, # must be at least one, even for a single-node cluster
},
},
template: {
spec: {
affinity: {
podAntiAffinity: {
requiredDuringSchedulingIgnoredDuringExecution: [
{
labelSelector: {
matchExpressions: [
{
key: "k8s-app",
operator: "In",
values: [
"kube-dns",
],
},
],
},
topologyKey: "kubernetes.io/hostname",
},
],
},
},
},
},
},
}))
end
end
end
3 changes: 2 additions & 1 deletion lib/kupo/phases/configure_host.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ class ConfigureHost < Base
name: 'kubernetes', version: '1.9.3', license: 'Apache License 2.0'
))

# @param host [Kupo::Configuration::Host]
def initialize(host)
@host = host
@ssh = Kupo::SSH::Client.for_host(@host)
Expand Down Expand Up @@ -41,4 +42,4 @@ def exec_script(script)
end
end
end
end
end
4 changes: 2 additions & 2 deletions lib/kupo/phases/configure_kubelet.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class ConfigureKubelet < Base

DROPIN_PATH = "/etc/systemd/system/kubelet.service.d/5-kupo.conf".freeze

# @param master [Kupo::Configuration::Host]
# @param host [Kupo::Configuration::Host]
def initialize(host)
@host = host
@ssh = Kupo::SSH::Client.for_host(@host)
Expand Down Expand Up @@ -37,4 +37,4 @@ def build_systemd_dropin
config + args.join(' ') + "'"
end
end
end
end
4 changes: 3 additions & 1 deletion lib/kupo/phases/configure_master.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
module Kupo::Phases
class ConfigureMaster < Base

# @param master [Kupo::Configuration::Host]
# @param config [Kupo::Configuration::Network]
def initialize(master, config)
@master = master
@config = config
Expand Down Expand Up @@ -68,4 +70,4 @@ def upgrade
end
end
end
end
end
3 changes: 2 additions & 1 deletion lib/kupo/phases/configure_metrics.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class ConfigureMetrics < Base
name: 'heapster', version: '1.5.1', license: 'Apache License 2.0'
))

# @param master [Kupo::Configuration::Host]
def initialize(master)
@master = master
end
Expand All @@ -22,4 +23,4 @@ def call
Kupo::Kube.apply_stack(@master.address, 'heapster', {version: '1.5.1'})
end
end
end
end
4 changes: 3 additions & 1 deletion lib/kupo/phases/configure_network.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ class ConfigureNetwork < Base
name: 'weave', version: '2.2.0', license: 'Apache License 2.0'
))

# @param master [Kupo::Configuration::Host]
# @param config [Kupo::Configuration::Network]
def initialize(master, config)
@master = master
@config = config
Expand Down Expand Up @@ -49,4 +51,4 @@ def generate_password
SecureRandom.hex(24)
end
end
end
end
4 changes: 3 additions & 1 deletion lib/kupo/phases/join_node.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
module Kupo::Phases
class JoinNode < Base

# @param host [Kupo::Configuration::Host]
# @param master [Kupo::Configuration::Host]
def initialize(host, master)
@host = host
@master = master
Expand Down Expand Up @@ -33,4 +35,4 @@ def call
end
end
end
end
end
3 changes: 2 additions & 1 deletion lib/kupo/phases/validate_host.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module Kupo::Phases
class ValidateHost
include Kupo::Phases::Logging

# @param host [Kupo::Configuration::Host]
def initialize(host)
@host = host
end
Expand All @@ -18,4 +19,4 @@ def call
end
end
end
end
end
1 change: 1 addition & 0 deletions lib/kupo/up_command.rb
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ def handle_masters(master, config)
Phases::ConfigureKubelet.new(master).call
Phases::ConfigureMaster.new(master, config.network).call
Phases::ConfigureClient.new(master).call
Phases::ConfigureDNS.new(master, config).call
Phases::ConfigureNetwork.new(master, config.network).call
Phases::ConfigureMetrics.new(master).call
end
Expand Down
Loading

0 comments on commit 372e71a

Please sign in to comment.