hetzner-k3s 0.6.2.pre1 → 0.6.2
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/Gemfile.lock +3 -3
- data/README.md +10 -0
- data/cluster_config.yaml.example +10 -0
- data/hetzner-k3s.gemspec +1 -1
- data/lib/hetzner/k3s/cluster.rb +98 -3
- data/lib/hetzner/k3s/configuration.rb +12 -13
- data/lib/hetzner/k3s/version.rb +1 -1
- data/lib/hetzner/utils.rb +3 -0
- metadata +8 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 873c76ec7a993a8c890f72c8158daa82597eb994e3f5e70c9b53d98604903f38
|
4
|
+
data.tar.gz: d0b1f622ff21728d1bb6b41b2a373eca693121a0eb619776adf9590ef926f80a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4bdc7f2fa5f6ef40bcd1e089d89b26c228b77fe3c06fb4af884910e4fe69fb6ad67951160a4ecdbcb6f076adbc16521bfd45b661644e7f6b927ba002e5a3ba67
|
7
|
+
data.tar.gz: 94a8f6b3df49db94d7412d5f350ce3f996980f0741e694a8b91a7ff0c71783cdaa12b4263cab31395288497dd3c790be45ca62e00f844d9df863a13b3623de79
|
data/Gemfile.lock
CHANGED
@@ -1,12 +1,12 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
hetzner-k3s (0.6.
|
4
|
+
hetzner-k3s (0.6.1)
|
5
5
|
bcrypt_pbkdf
|
6
6
|
childprocess
|
7
7
|
ed25519
|
8
8
|
httparty
|
9
|
-
net-ssh
|
9
|
+
net-ssh
|
10
10
|
sshkey
|
11
11
|
thor
|
12
12
|
|
@@ -25,7 +25,7 @@ GEM
|
|
25
25
|
mime-types-data (~> 3.2015)
|
26
26
|
mime-types-data (3.2022.0105)
|
27
27
|
multi_xml (0.6.0)
|
28
|
-
net-ssh (
|
28
|
+
net-ssh (7.0.1)
|
29
29
|
parallel (1.20.1)
|
30
30
|
parser (3.1.2.1)
|
31
31
|
ast (~> 2.4.1)
|
data/README.md
CHANGED
@@ -138,10 +138,20 @@ schedule_workloads_on_masters: false
|
|
138
138
|
masters:
|
139
139
|
instance_type: cpx21
|
140
140
|
instance_count: 3
|
141
|
+
# labels:
|
142
|
+
# purpose: master
|
143
|
+
# size: cpx21
|
144
|
+
# taints:
|
145
|
+
# something: value1:NoSchedule
|
141
146
|
worker_node_pools:
|
142
147
|
- name: small
|
143
148
|
instance_type: cpx21
|
144
149
|
instance_count: 4
|
150
|
+
# labels:
|
151
|
+
# purpose: worker
|
152
|
+
# size: cpx21
|
153
|
+
# taints:
|
154
|
+
# something: GpuWorkloadsOnly:NoSchedule
|
145
155
|
- name: big
|
146
156
|
instance_type: cpx31
|
147
157
|
instance_count: 2
|
data/cluster_config.yaml.example
CHANGED
@@ -15,10 +15,20 @@ schedule_workloads_on_masters: false
|
|
15
15
|
masters:
|
16
16
|
instance_type: cpx21
|
17
17
|
instance_count: 3
|
18
|
+
# labels:
|
19
|
+
# purpose: master
|
20
|
+
# size: cpx21
|
21
|
+
# taints:
|
22
|
+
# something: value1:NoSchedule
|
18
23
|
worker_node_pools:
|
19
24
|
- name: small
|
20
25
|
instance_type: cpx21
|
21
26
|
instance_count: 4
|
27
|
+
# labels:
|
28
|
+
# purpose: worker
|
29
|
+
# size: cpx21
|
30
|
+
# taints:
|
31
|
+
# something: GpuWorkloadsOnly:NoSchedule
|
22
32
|
- name: big
|
23
33
|
instance_type: cpx31
|
24
34
|
instance_count: 2
|
data/hetzner-k3s.gemspec
CHANGED
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
|
|
24
24
|
spec.add_dependency 'childprocess'
|
25
25
|
spec.add_dependency 'ed25519'
|
26
26
|
spec.add_dependency 'httparty'
|
27
|
-
spec.add_dependency 'net-ssh'
|
27
|
+
spec.add_dependency 'net-ssh'
|
28
28
|
spec.add_dependency 'sshkey'
|
29
29
|
spec.add_dependency 'thor'
|
30
30
|
spec.add_development_dependency 'rubocop'
|
data/lib/hetzner/k3s/cluster.rb
CHANGED
@@ -51,6 +51,9 @@ class Cluster
|
|
51
51
|
|
52
52
|
sleep 10
|
53
53
|
|
54
|
+
label_nodes
|
55
|
+
taint_nodes
|
56
|
+
|
54
57
|
deploy_cloud_controller_manager
|
55
58
|
deploy_csi_driver
|
56
59
|
deploy_system_upgrade_controller
|
@@ -294,6 +297,82 @@ class Cluster
|
|
294
297
|
threads.each(&:join) unless threads.empty?
|
295
298
|
end
|
296
299
|
|
300
|
+
def label_nodes
|
301
|
+
check_kubectl
|
302
|
+
|
303
|
+
if master_definitions_for_create.first[:labels]
|
304
|
+
master_labels = master_definitions_for_create.first[:labels].map{ |k, v| "#{k}=#{v}" }.join(' ')
|
305
|
+
master_node_names = []
|
306
|
+
|
307
|
+
master_definitions_for_create.each do |master|
|
308
|
+
master_node_names << "#{configuration['cluster_name']}-#{master[:instance_type]}-#{master[:instance_id]}"
|
309
|
+
end
|
310
|
+
|
311
|
+
master_node_names = master_node_names.join(' ')
|
312
|
+
|
313
|
+
cmd = "kubectl label --overwrite nodes #{master_node_names} #{master_labels}"
|
314
|
+
|
315
|
+
run cmd, kubeconfig_path: kubeconfig_path
|
316
|
+
end
|
317
|
+
|
318
|
+
workers = []
|
319
|
+
|
320
|
+
worker_node_pools.each do |worker_node_pool|
|
321
|
+
workers += worker_node_pool_definitions(worker_node_pool)
|
322
|
+
end
|
323
|
+
|
324
|
+
return unless workers.any?
|
325
|
+
|
326
|
+
workers.each do |worker|
|
327
|
+
next unless worker[:labels]
|
328
|
+
|
329
|
+
worker_labels = worker[:labels].map{ |k, v| "#{k}=#{v}" }.join(' ')
|
330
|
+
worker_node_name = "#{configuration['cluster_name']}-#{worker[:instance_type]}-#{worker[:instance_id]}"
|
331
|
+
|
332
|
+
cmd = "kubectl label --overwrite nodes #{worker_node_name} #{worker_labels}"
|
333
|
+
|
334
|
+
run cmd, kubeconfig_path: kubeconfig_path
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
def taint_nodes
|
339
|
+
check_kubectl
|
340
|
+
|
341
|
+
if master_definitions_for_create.first[:taints]
|
342
|
+
master_taints = master_definitions_for_create.first[:taints].map{ |k, v| "#{k}=#{v}" }.join(' ')
|
343
|
+
master_node_names = []
|
344
|
+
|
345
|
+
master_definitions_for_create.each do |master|
|
346
|
+
master_node_names << "#{configuration['cluster_name']}-#{master[:instance_type]}-#{master[:instance_id]}"
|
347
|
+
end
|
348
|
+
|
349
|
+
master_node_names = master_node_names.join(' ')
|
350
|
+
|
351
|
+
cmd = "kubectl taint --overwrite nodes #{master_node_names} #{master_taints}"
|
352
|
+
|
353
|
+
run cmd, kubeconfig_path: kubeconfig_path
|
354
|
+
end
|
355
|
+
|
356
|
+
workers = []
|
357
|
+
|
358
|
+
worker_node_pools.each do |worker_node_pool|
|
359
|
+
workers += worker_node_pool_definitions(worker_node_pool)
|
360
|
+
end
|
361
|
+
|
362
|
+
return unless workers.any?
|
363
|
+
|
364
|
+
workers.each do |worker|
|
365
|
+
next unless worker[:taints]
|
366
|
+
|
367
|
+
worker_taints = worker[:taints].map{ |k, v| "#{k}=#{v}" }.join(' ')
|
368
|
+
worker_node_name = "#{configuration['cluster_name']}-#{worker[:instance_type]}-#{worker[:instance_id]}"
|
369
|
+
|
370
|
+
cmd = "kubectl taint --overwrite nodes #{worker_node_name} #{worker_taints}"
|
371
|
+
|
372
|
+
run cmd, kubeconfig_path: kubeconfig_path
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
297
376
|
def deploy_cloud_controller_manager
|
298
377
|
check_kubectl
|
299
378
|
|
@@ -480,6 +559,14 @@ class Cluster
|
|
480
559
|
@master_instance_type ||= masters_config['instance_type']
|
481
560
|
end
|
482
561
|
|
562
|
+
def master_labels
|
563
|
+
@master_labels ||= masters_config['labels']
|
564
|
+
end
|
565
|
+
|
566
|
+
def master_taints
|
567
|
+
@master_taints ||= masters_config['taints']
|
568
|
+
end
|
569
|
+
|
483
570
|
def masters_count
|
484
571
|
@masters_count ||= masters_config['instance_count']
|
485
572
|
end
|
@@ -510,7 +597,9 @@ class Cluster
|
|
510
597
|
ssh_key_id: ssh_key_id,
|
511
598
|
image: image,
|
512
599
|
additional_packages: additional_packages,
|
513
|
-
additional_post_create_commands: additional_post_create_commands
|
600
|
+
additional_post_create_commands: additional_post_create_commands,
|
601
|
+
labels: master_labels,
|
602
|
+
taints: master_taints
|
514
603
|
}
|
515
604
|
end
|
516
605
|
|
@@ -535,6 +624,8 @@ class Cluster
|
|
535
624
|
worker_instance_type = worker_node_pool['instance_type']
|
536
625
|
worker_count = worker_node_pool['instance_count']
|
537
626
|
worker_location = worker_node_pool['location'] || masters_location
|
627
|
+
labels = worker_node_pool['labels']
|
628
|
+
taints = worker_node_pool['taints']
|
538
629
|
|
539
630
|
definitions = []
|
540
631
|
|
@@ -549,7 +640,9 @@ class Cluster
|
|
549
640
|
ssh_key_id: ssh_key_id,
|
550
641
|
image: image,
|
551
642
|
additional_packages: additional_packages,
|
552
|
-
additional_post_create_commands: additional_post_create_commands
|
643
|
+
additional_post_create_commands: additional_post_create_commands,
|
644
|
+
labels: labels,
|
645
|
+
taints: taints
|
553
646
|
}
|
554
647
|
end
|
555
648
|
|
@@ -576,8 +669,10 @@ class Cluster
|
|
576
669
|
servers = []
|
577
670
|
|
578
671
|
threads = server_configs.map do |server_config|
|
672
|
+
config = server_config.reject! { |k, _v| %i[labels taints].include?(k) }
|
673
|
+
|
579
674
|
Thread.new do
|
580
|
-
servers << Hetzner::Server.new(hetzner_client: hetzner_client, cluster_name: cluster_name).create(**
|
675
|
+
servers << Hetzner::Server.new(hetzner_client: hetzner_client, cluster_name: cluster_name).create(**config)
|
581
676
|
end
|
582
677
|
end
|
583
678
|
|
@@ -3,7 +3,7 @@
|
|
3
3
|
module Hetzner
|
4
4
|
class Configuration
|
5
5
|
GITHUB_DELIM_LINKS = ','
|
6
|
-
GITHUB_LINK_REGEX = /<([^>]+)>; rel="([^"]+)"
|
6
|
+
GITHUB_LINK_REGEX = /<([^>]+)>; rel="([^"]+)"/.freeze
|
7
7
|
|
8
8
|
attr_reader :hetzner_client
|
9
9
|
|
@@ -92,8 +92,6 @@ module Hetzner
|
|
92
92
|
configuration
|
93
93
|
end
|
94
94
|
|
95
|
-
private_class_method
|
96
|
-
|
97
95
|
def self.fetch_releases(url)
|
98
96
|
response = HTTParty.get(url)
|
99
97
|
[response, JSON.parse(response.body).map { |hash| hash['name'] }]
|
@@ -196,7 +194,7 @@ module Hetzner
|
|
196
194
|
|
197
195
|
unless invalid_ranges.empty?
|
198
196
|
invalid_ranges.each do |_network|
|
199
|
-
errors <<
|
197
|
+
errors << "Please use the CIDR notation for the #{access_type} networks to avoid ambiguity"
|
200
198
|
end
|
201
199
|
end
|
202
200
|
|
@@ -210,19 +208,17 @@ module Hetzner
|
|
210
208
|
false
|
211
209
|
end
|
212
210
|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
211
|
+
return if current_ip_network
|
212
|
+
|
213
|
+
case access_type
|
214
|
+
when 'SSH'
|
215
|
+
errors << "Your current IP #{current_ip} is not included into any of the #{access_type} networks you've specified, so we won't be able to SSH into the nodes "
|
216
|
+
when 'API'
|
217
|
+
errors << "Your current IP #{current_ip} is not included into any of the #{access_type} networks you've specified, so we won't be able to connect to the Kubernetes API"
|
220
218
|
end
|
221
219
|
end
|
222
220
|
|
223
|
-
|
224
221
|
def validate_ssh_allowed_networks
|
225
|
-
return
|
226
222
|
validate_networks('ssh_allowed_networks', 'SSH')
|
227
223
|
end
|
228
224
|
|
@@ -441,6 +437,9 @@ module Hetzner
|
|
441
437
|
instance_group_errors << "#{instance_group_type} has an invalid instance count"
|
442
438
|
end
|
443
439
|
|
440
|
+
instance_group_errors << "#{instance_group_type} has an invalid labels format - a hash is expected" if !instance_group['labels'].nil? && !instance_group['labels'].is_a?(Hash)
|
441
|
+
instance_group_errors << "#{instance_group_type} has an invalid taints format - a hash is expected" if !instance_group['taints'].nil? && !instance_group['taints'].is_a?(Hash)
|
442
|
+
|
444
443
|
errors << instance_group_errors
|
445
444
|
end
|
446
445
|
|
data/lib/hetzner/k3s/version.rb
CHANGED
data/lib/hetzner/utils.rb
CHANGED
@@ -89,6 +89,9 @@ module Utils
|
|
89
89
|
# p [e.class, e.message]
|
90
90
|
# retries += 1
|
91
91
|
# retry unless retries > 15 || e.message =~ /Bad file descriptor/
|
92
|
+
rescue Timeout::Error, IOError, Errno::EBADF
|
93
|
+
retries += 1
|
94
|
+
retry unless retries > 15
|
92
95
|
rescue Net::SSH::Disconnect => e
|
93
96
|
retries += 1
|
94
97
|
retry unless retries > 15 || e.message =~ /Too many authentication failures/
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hetzner-k3s
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.2
|
4
|
+
version: 0.6.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vito Botta
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-08-
|
11
|
+
date: 2022-08-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bcrypt_pbkdf
|
@@ -70,16 +70,16 @@ dependencies:
|
|
70
70
|
name: net-ssh
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- -
|
73
|
+
- - ">="
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
75
|
+
version: '0'
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- -
|
80
|
+
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version:
|
82
|
+
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: sshkey
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -177,9 +177,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
177
177
|
version: 2.7.1
|
178
178
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
179
179
|
requirements:
|
180
|
-
- - "
|
180
|
+
- - ">="
|
181
181
|
- !ruby/object:Gem::Version
|
182
|
-
version:
|
182
|
+
version: '0'
|
183
183
|
requirements: []
|
184
184
|
rubygems_version: 3.1.2
|
185
185
|
signing_key:
|