hetzner-k3s 0.5.7 → 0.6.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,7 +4,7 @@ require 'net/ssh'
4
4
  require 'securerandom'
5
5
  require 'base64'
6
6
  require 'timeout'
7
- require 'subprocess'
7
+ require 'fileutils'
8
8
 
9
9
  require_relative '../infra/client'
10
10
  require_relative '../infra/firewall'
@@ -19,13 +19,11 @@ require_relative '../utils'
19
19
  class Cluster
20
20
  include Utils
21
21
 
22
- def initialize(hetzner_client:, hetzner_token:)
23
- @hetzner_client = hetzner_client
24
- @hetzner_token = hetzner_token
22
+ def initialize(configuration:)
23
+ @configuration = configuration
25
24
  end
26
25
 
27
- def create(configuration:)
28
- @configuration = configuration
26
+ def create
29
27
  @cluster_name = configuration['cluster_name']
30
28
  @kubeconfig_path = File.expand_path(configuration['kubeconfig_path'])
31
29
  @public_ssh_key_path = File.expand_path(configuration['public_ssh_key_path'])
@@ -37,7 +35,8 @@ class Cluster
37
35
  @masters_location = configuration['location']
38
36
  @verify_host_key = configuration.fetch('verify_host_key', false)
39
37
  @servers = []
40
- @networks = configuration['ssh_allowed_networks']
38
+ @ssh_networks = configuration['ssh_allowed_networks']
39
+ @api_networks = configuration['api_allowed_networks']
41
40
  @enable_encryption = configuration.fetch('enable_encryption', false)
42
41
  @kube_api_server_args = configuration.fetch('kube_api_server_args', [])
43
42
  @kube_scheduler_args = configuration.fetch('kube_scheduler_args', [])
@@ -57,8 +56,7 @@ class Cluster
57
56
  deploy_system_upgrade_controller
58
57
  end
59
58
 
60
- def delete(configuration:)
61
- @configuration = configuration
59
+ def delete
62
60
  @cluster_name = configuration['cluster_name']
63
61
  @kubeconfig_path = File.expand_path(configuration['kubeconfig_path'])
64
62
  @public_ssh_key_path = File.expand_path(configuration['public_ssh_key_path'])
@@ -68,8 +66,7 @@ class Cluster
68
66
  delete_resources
69
67
  end
70
68
 
71
- def upgrade(configuration:, new_k3s_version:, config_file:)
72
- @configuration = configuration
69
+ def upgrade(new_k3s_version:, config_file:)
73
70
  @cluster_name = configuration['cluster_name']
74
71
  @kubeconfig_path = File.expand_path(configuration['kubeconfig_path'])
75
72
  @new_k3s_version = new_k3s_version
@@ -82,21 +79,21 @@ class Cluster
82
79
 
83
80
  attr_accessor :servers
84
81
 
85
- attr_reader :hetzner_client, :cluster_name, :kubeconfig_path, :k3s_version,
82
+ attr_reader :configuration, :cluster_name, :kubeconfig_path, :k3s_version,
86
83
  :masters_config, :worker_node_pools,
87
84
  :masters_location, :public_ssh_key_path,
88
- :hetzner_token, :new_k3s_version, :configuration,
89
- :config_file, :verify_host_key, :networks, :private_ssh_key_path,
85
+ :hetzner_token, :new_k3s_version,
86
+ :config_file, :verify_host_key, :ssh_networks, :private_ssh_key_path,
90
87
  :enable_encryption, :kube_api_server_args, :kube_scheduler_args,
91
88
  :kube_controller_manager_args, :kube_cloud_controller_manager_args,
92
- :kubelet_args, :kube_proxy_args
89
+ :kubelet_args, :kube_proxy_args, :api_networks
93
90
 
94
91
  def find_worker_node_pools(configuration)
95
92
  configuration.fetch('worker_node_pools', [])
96
93
  end
97
94
 
98
95
  def latest_k3s_version
99
- response = HTTP.get('https://api.github.com/repos/k3s-io/k3s/tags').body
96
+ response = HTTParty.get('https://api.github.com/repos/k3s-io/k3s/tags').body
100
97
  JSON.parse(response).first['name']
101
98
  end
102
99
 
@@ -106,22 +103,22 @@ class Cluster
106
103
  end
107
104
 
108
105
  def delete_placement_groups
109
- Hetzner::PlacementGroup.new(hetzner_client:, cluster_name:).delete
106
+ Hetzner::PlacementGroup.new(hetzner_client: hetzner_client, cluster_name: cluster_name).delete
110
107
 
111
108
  worker_node_pools.each do |pool|
112
109
  pool_name = pool['name']
113
- Hetzner::PlacementGroup.new(hetzner_client:, cluster_name:, pool_name:).delete
110
+ Hetzner::PlacementGroup.new(hetzner_client: hetzner_client, cluster_name: cluster_name, pool_name: pool_name).delete
114
111
  end
115
112
  end
116
113
 
117
114
  def delete_resources
118
- Hetzner::LoadBalancer.new(hetzner_client:, cluster_name:).delete(high_availability: (masters.size > 1))
115
+ Hetzner::LoadBalancer.new(hetzner_client: hetzner_client, cluster_name: cluster_name).delete(high_availability: (masters.size > 1))
119
116
 
120
- Hetzner::Firewall.new(hetzner_client:, cluster_name:).delete(all_servers)
117
+ Hetzner::Firewall.new(hetzner_client: hetzner_client, cluster_name: cluster_name).delete(all_servers)
121
118
 
122
- Hetzner::Network.new(hetzner_client:, cluster_name:).delete
119
+ Hetzner::Network.new(hetzner_client: hetzner_client, cluster_name: cluster_name, existing_network: existing_network).delete
123
120
 
124
- Hetzner::SSHKey.new(hetzner_client:, cluster_name:).delete(public_ssh_key_path:)
121
+ Hetzner::SSHKey.new(hetzner_client: hetzner_client, cluster_name: cluster_name).delete(public_ssh_key_path: public_ssh_key_path)
125
122
 
126
123
  delete_placement_groups
127
124
  delete_servers
@@ -190,15 +187,30 @@ class Cluster
190
187
  puts 'Upgrade will now start. Run `watch kubectl get nodes` to see the nodes being upgraded. This should take a few minutes for a small cluster.'
191
188
  puts 'The API server may be briefly unavailable during the upgrade of the controlplane.'
192
189
 
193
- configuration['k3s_version'] = new_k3s_version
190
+ updated_configuration = configuration.raw
191
+ updated_configuration['k3s_version'] = new_k3s_version
194
192
 
195
- File.write(config_file, configuration.to_yaml)
193
+ File.write(config_file, updated_configuration.to_yaml)
196
194
  end
197
195
 
198
196
  def master_script(master)
199
197
  server = master == first_master ? ' --cluster-init ' : " --server https://#{api_server_ip}:6443 "
200
198
  flannel_interface = find_flannel_interface(master)
201
- flannel_wireguard = enable_encryption ? ' --flannel-backend=wireguard ' : ' '
199
+
200
+ available_k3s_releases = Hetzner::Configuration.available_releases
201
+ wireguard_native_min_version_index = available_k3s_releases.find_index('v1.23.6+k3s1')
202
+ selected_version_index = available_k3s_releases.find_index(k3s_version)
203
+
204
+ flannel_wireguard = if enable_encryption
205
+ if selected_version_index >= wireguard_native_min_version_index
206
+ ' --flannel-backend=wireguard-native '
207
+ else
208
+ ' --flannel-backend=wireguard '
209
+ end
210
+ else
211
+ ' '
212
+ end
213
+
202
214
  extra_args = "#{kube_api_server_args_list} #{kube_scheduler_args_list} #{kube_controller_manager_args_list} #{kube_cloud_controller_manager_args_list} #{kubelet_args_list} #{kube_proxy_args_list}"
203
215
  taint = schedule_workloads_on_masters? ? ' ' : ' --node-taint CriticalAddonsOnly=true:NoExecute '
204
216
 
@@ -214,10 +226,8 @@ class Cluster
214
226
  --cluster-cidr=10.244.0.0/16 \
215
227
  --etcd-expose-metrics=true \
216
228
  #{flannel_wireguard} \
217
- --kube-controller-manager-arg="address=0.0.0.0" \
218
229
  --kube-controller-manager-arg="bind-address=0.0.0.0" \
219
230
  --kube-proxy-arg="metrics-bind-address=0.0.0.0" \
220
- --kube-scheduler-arg="address=0.0.0.0" \
221
231
  --kube-scheduler-arg="bind-address=0.0.0.0" \
222
232
  #{taint} #{extra_args} \
223
233
  --kubelet-arg="cloud-provider=external" \
@@ -298,8 +308,8 @@ class Cluster
298
308
  namespace: 'kube-system'
299
309
  name: 'hcloud'
300
310
  stringData:
301
- network: "#{cluster_name}"
302
- token: "#{hetzner_token}"
311
+ network: "#{existing_network || cluster_name}"
312
+ token: "#{configuration.hetzner_token}"
303
313
  EOF
304
314
  BASH
305
315
 
@@ -318,7 +328,7 @@ class Cluster
318
328
  puts
319
329
  puts 'Deploying k3s System Upgrade Controller...'
320
330
 
321
- cmd = 'kubectl apply -f https://github.com/rancher/system-upgrade-controller/releases/download/v0.8.1/system-upgrade-controller.yaml'
331
+ cmd = 'kubectl apply -f https://github.com/rancher/system-upgrade-controller/releases/download/v0.9.1/system-upgrade-controller.yaml'
322
332
 
323
333
  run cmd, kubeconfig_path: kubeconfig_path
324
334
 
@@ -339,13 +349,13 @@ class Cluster
339
349
  namespace: 'kube-system'
340
350
  name: 'hcloud-csi'
341
351
  stringData:
342
- token: "#{hetzner_token}"
352
+ token: "#{configuration.hetzner_token}"
343
353
  EOF
344
354
  BASH
345
355
 
346
356
  run cmd, kubeconfig_path: kubeconfig_path
347
357
 
348
- cmd = 'kubectl apply -f https://raw.githubusercontent.com/hetznercloud/csi-driver/v1.6.0/deploy/kubernetes/hcloud-csi.yml'
358
+ cmd = 'kubectl apply -f https://raw.githubusercontent.com/hetznercloud/csi-driver/master/deploy/kubernetes/hcloud-csi.yml'
349
359
 
350
360
  run cmd, kubeconfig_path: kubeconfig_path
351
361
 
@@ -413,7 +423,7 @@ class Cluster
413
423
 
414
424
  masters.each do |master|
415
425
  master_private_ip = master['private_net'][0]['ip']
416
- sans << " --tls-san=#{master_private_ip} "
426
+ sans += " --tls-san=#{master_private_ip} "
417
427
  end
418
428
 
419
429
  sans
@@ -463,7 +473,7 @@ class Cluster
463
473
 
464
474
  def placement_group_id(pool_name = nil)
465
475
  @placement_groups ||= {}
466
- @placement_groups[pool_name || '__masters__'] ||= Hetzner::PlacementGroup.new(hetzner_client:, cluster_name:, pool_name:).create
476
+ @placement_groups[pool_name || '__masters__'] ||= Hetzner::PlacementGroup.new(hetzner_client: hetzner_client, cluster_name: cluster_name, pool_name: pool_name).create
467
477
  end
468
478
 
469
479
  def master_instance_type
@@ -475,15 +485,15 @@ class Cluster
475
485
  end
476
486
 
477
487
  def firewall_id
478
- @firewall_id ||= Hetzner::Firewall.new(hetzner_client:, cluster_name:).create(high_availability: (masters_count > 1), networks:)
488
+ @firewall_id ||= Hetzner::Firewall.new(hetzner_client: hetzner_client, cluster_name: cluster_name).create(high_availability: (masters_count > 1), ssh_networks: ssh_networks, api_networks: api_networks)
479
489
  end
480
490
 
481
491
  def network_id
482
- @network_id ||= Hetzner::Network.new(hetzner_client:, cluster_name:).create(location: masters_location)
492
+ @network_id ||= Hetzner::Network.new(hetzner_client: hetzner_client, cluster_name: cluster_name, existing_network: existing_network).create(location: masters_location)
483
493
  end
484
494
 
485
495
  def ssh_key_id
486
- @ssh_key_id ||= Hetzner::SSHKey.new(hetzner_client:, cluster_name:).create(public_ssh_key_path:)
496
+ @ssh_key_id ||= Hetzner::SSHKey.new(hetzner_client: hetzner_client, cluster_name: cluster_name).create(public_ssh_key_path: public_ssh_key_path)
487
497
  end
488
498
 
489
499
  def master_definitions_for_create
@@ -494,13 +504,13 @@ class Cluster
494
504
  instance_type: master_instance_type,
495
505
  instance_id: "master#{i + 1}",
496
506
  location: masters_location,
497
- placement_group_id:,
498
- firewall_id:,
499
- network_id:,
500
- ssh_key_id:,
501
- image:,
502
- additional_packages:,
503
- additional_post_create_commands:
507
+ placement_group_id: placement_group_id,
508
+ firewall_id: firewall_id,
509
+ network_id: network_id,
510
+ ssh_key_id: ssh_key_id,
511
+ image: image,
512
+ additional_packages: additional_packages,
513
+ additional_post_create_commands: additional_post_create_commands
504
514
  }
505
515
  end
506
516
 
@@ -534,12 +544,12 @@ class Cluster
534
544
  instance_id: "pool-#{worker_node_pool_name}-worker#{i + 1}",
535
545
  placement_group_id: placement_group_id(worker_node_pool_name),
536
546
  location: worker_location,
537
- firewall_id:,
538
- network_id:,
539
- ssh_key_id:,
540
- image:,
541
- additional_packages:,
542
- additional_post_create_commands:
547
+ firewall_id: firewall_id,
548
+ network_id: network_id,
549
+ ssh_key_id: ssh_key_id,
550
+ image: image,
551
+ additional_packages: additional_packages,
552
+ additional_post_create_commands: additional_post_create_commands
543
553
  }
544
554
  end
545
555
 
@@ -547,7 +557,7 @@ class Cluster
547
557
  end
548
558
 
549
559
  def create_load_balancer
550
- Hetzner::LoadBalancer.new(hetzner_client:, cluster_name:).create(location: masters_location, network_id:)
560
+ Hetzner::LoadBalancer.new(hetzner_client: hetzner_client, cluster_name: cluster_name).create(location: masters_location, network_id: network_id)
551
561
  end
552
562
 
553
563
  def server_configs
@@ -567,7 +577,7 @@ class Cluster
567
577
 
568
578
  threads = server_configs.map do |server_config|
569
579
  Thread.new do
570
- servers << Hetzner::Server.new(hetzner_client:, cluster_name:).create(**server_config)
580
+ servers << Hetzner::Server.new(hetzner_client: hetzner_client, cluster_name: cluster_name).create(**server_config)
571
581
  end
572
582
  end
573
583
 
@@ -589,7 +599,7 @@ class Cluster
589
599
  def delete_servers
590
600
  threads = all_servers.map do |server|
591
601
  Thread.new do
592
- Hetzner::Server.new(hetzner_client:, cluster_name:).delete(server_name: server['name'])
602
+ Hetzner::Server.new(hetzner_client: hetzner_client, cluster_name: cluster_name).delete(server_name: server['name'])
593
603
  end
594
604
  end
595
605
 
@@ -643,4 +653,12 @@ class Cluster
643
653
  " --kube-proxy-arg=\"#{arg}\" "
644
654
  end.join
645
655
  end
656
+
657
+ def hetzner_client
658
+ configuration.hetzner_client
659
+ end
660
+
661
+ def existing_network
662
+ configuration['existing_network']
663
+ end
646
664
  end