hetzner-k3s 0.5.5 → 0.5.8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 54bad08b660435283978314edf5d2823fd98a72958051615efc8ec5b24ce0b88
4
- data.tar.gz: 653edb24301d237515b4abfae4538893f40f4707d462c3344f083a082d0fe0e8
3
+ metadata.gz: c0d855f62ab9e222986d220edcdde203f7eb363ab725c8aa4e1f1389f2b251e2
4
+ data.tar.gz: 19d6a1ff6769cbec2207539d615d6a873eaede07aec9b15a43e6ef9d79101731
5
5
  SHA512:
6
- metadata.gz: 93536c6ddf9091ed6c148388e4f29dd2630fd5daf03dd7feafe218cc1dad97ebc3bf3db01799126a9fed70003b2b57db1eb73a81ad807362459c95190527684e
7
- data.tar.gz: 6bf703828e75363b7ba03ec413b4eff9ab97ca06c2cd8d4f82baca05fc2c32e43d86f0137f1f8f5af0dc4455b7edf157f74bda1621869beb89432058a78b0dcd
6
+ metadata.gz: d8fdc127e71f790e530d3abf97ca30d22b28d75eff687e436d1351336595ae7ba912c0c947c8b1738ab9d50447e577c4be753db3c20a2bfbcca195fcc6a0d193
7
+ data.tar.gz: 5cb4203c6270f0e82b66049fefd7244aaeb42e1dd89e257a0e1ba4b126db04ed8adf27b715b10874248f6661b6fed3126e562913ec2342f086bbff4c717c329b
data/.rubocop.yml CHANGED
@@ -119,3 +119,17 @@ Metrics/ParameterLists:
119
119
  Style/FrozenStringLiteralComment:
120
120
  Exclude:
121
121
  - exe/hetzner-k3s
122
+ Lint/RefinementImportMethods: # new in 1.27
123
+ Enabled: true
124
+ Security/CompoundHash: # new in 1.28
125
+ Enabled: true
126
+ Style/EnvHome: # new in 1.29
127
+ Enabled: true
128
+ Style/FetchEnvVar: # new in 1.28
129
+ Enabled: true
130
+ Style/NestedFileDirname: # new in 1.26
131
+ Enabled: true
132
+ Style/ObjectThen: # new in 1.28
133
+ Enabled: true
134
+ Style/RedundantInitialize: # new in 1.27
135
+ Enabled: true
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 3.1.0
1
+ ruby-3.1.2
data/Dockerfile CHANGED
@@ -1,4 +1,4 @@
1
- FROM ruby:3.1.0-alpine
1
+ FROM ruby:3.1.2-alpine
2
2
 
3
3
  RUN apk update --no-cache \
4
4
  && apk add build-base git openssh-client curl bash
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- hetzner-k3s (0.5.5)
4
+ hetzner-k3s (0.5.7)
5
5
  bcrypt_pbkdf
6
6
  ed25519
7
7
  http
@@ -30,7 +30,7 @@ GEM
30
30
  http-cookie (~> 1.0)
31
31
  http-form_data (~> 2.2)
32
32
  http-parser (~> 1.2.0)
33
- http-cookie (1.0.4)
33
+ http-cookie (1.0.5)
34
34
  domain_name (~> 0.5)
35
35
  http-form_data (2.3.0)
36
36
  http-parser (1.2.3)
@@ -39,7 +39,7 @@ GEM
39
39
  parallel (1.21.0)
40
40
  parser (3.1.0.0)
41
41
  ast (~> 2.4.1)
42
- public_suffix (4.0.6)
42
+ public_suffix (4.0.7)
43
43
  rainbow (3.1.1)
44
44
  rake (12.3.3)
45
45
  regexp_parser (2.2.0)
@@ -74,7 +74,7 @@ GEM
74
74
  thor (1.2.1)
75
75
  unf (0.1.4)
76
76
  unf_ext
77
- unf_ext (0.0.8)
77
+ unf_ext (0.0.8.2)
78
78
  unicode-display_width (2.1.0)
79
79
 
80
80
  PLATFORMS
@@ -87,4 +87,4 @@ DEPENDENCIES
87
87
  rubocop
88
88
 
89
89
  BUNDLED WITH
90
- 2.3.4
90
+ 2.3.14
data/README.md CHANGED
@@ -16,6 +16,8 @@ Using this tool, creating a highly available k3s cluster with 3 masters for the
16
16
 
17
17
  See roadmap [here](https://github.com/vitobotta/hetzner-k3s/projects/1) for the features planned or in progress.
18
18
 
19
+ Also see this [wiki page](https://github.com/vitobotta/hetzner-k3s/wiki/Tutorial:---Setting-up-a-cluster) for a tutorial on how to set up a cluster with the most common setup to get you started.
20
+
19
21
  ## Requirements
20
22
 
21
23
  All that is needed to use this tool is
@@ -26,7 +28,7 @@ All that is needed to use this tool is
26
28
 
27
29
  ## Installation
28
30
 
29
- Once you have the Ruby runtime up and running (3.1.0 or newer), you just need to install the gem:
31
+ Once you have the Ruby runtime up and running (3.1.2 or newer), you just need to install the gem:
30
32
 
31
33
  ```bash
32
34
  gem install hetzner-k3s
@@ -39,7 +41,12 @@ This will install the `hetzner-k3s` executable in your PATH.
39
41
  Alternatively, if you don't want to set up a Ruby runtime but have Docker installed, you can use a container. Run the following from inside the directory where you have the config file for the cluster (described in the next section):
40
42
 
41
43
  ```bash
42
- docker run --rm -it -v ${PWD}:/cluster -v ${HOME}/.ssh:/tmp/.ssh vitobotta/hetzner-k3s:v0.5.5 create-cluster --config-file /cluster/test.yaml
44
+ docker run --rm -it \
45
+ -v ${PWD}:/cluster \
46
+ -v ${HOME}/.ssh:/tmp/.ssh \
47
+ vitobotta/hetzner-k3s:v0.5.8 \
48
+ create-cluster \
49
+ --config-file /cluster/test.yaml
43
50
  ```
44
51
 
45
52
  Replace `test.yaml` with the name of your config file.
@@ -73,6 +80,11 @@ worker_node_pools:
73
80
  instance_count: 2
74
81
  additional_packages:
75
82
  - somepackage
83
+ post_create_commands:
84
+ - apt update
85
+ - apt upgrade -y
86
+ - apt autoremove -y
87
+ - shutdown -r now
76
88
  enable_encryption: true
77
89
  # kube_api_server_args:
78
90
  # - arg1
@@ -109,7 +121,7 @@ If you set `masters.instance_count` to 1 then the tool will create a non highly
109
121
 
110
122
  You can specify any number of worker node pools for example to have mixed nodes with different specs for different workloads.
111
123
 
112
- At the moment Hetzner Cloud has four locations: two in Germany (`nbg1`, Nuremberg and `fsn1`, Falkensteing), one in Finland (`hel1`, Helsinki) and one in the USA (`ash`, Ashburn, Virginia). Please note that the Ashburn, Virginia location has just
124
+ At the moment Hetzner Cloud has four locations: two in Germany (`nbg1`, Nuremberg and `fsn1`, Falkenstein), one in Finland (`hel1`, Helsinki) and one in the USA (`ash`, Ashburn, Virginia). Please note that the Ashburn, Virginia location has just
113
125
  been announced and it's limited to AMD instances for now.
114
126
 
115
127
  For the available instance types and their specs, either check from inside a project when adding a server manually or run the following with your Hetzner token:
@@ -159,6 +171,8 @@ The `create-cluster` command can be run any number of times with the same config
159
171
 
160
172
  To add one or more nodes to a node pool, just change the instance count in the configuration file for that node pool and re-run the create command.
161
173
 
174
+ **Important**: if you are increasing the size of a node pool created prior to v0.5.7, please see [this thread](https://github.com/vitobotta/hetzner-k3s/issues/80).
175
+
162
176
  ### Scaling down a node pool
163
177
 
164
178
  To make a node pool smaller:
@@ -194,7 +208,6 @@ Note that the API server will briefly be unavailable during the upgrade of the c
194
208
 
195
209
  To check the upgrade progress, run `watch kubectl get nodes -owide`. You will see the masters being upgraded one per time, followed by the worker nodes.
196
210
 
197
-
198
211
  ### What to do if the upgrade doesn't go smoothly
199
212
 
200
213
  If the upgrade gets stuck for some reason, or it doesn't upgrade all the nodes:
@@ -220,7 +233,8 @@ I have noticed that sometimes I need to re-run the upgrade command a couple of t
220
233
  You can also check the logs of the system upgrade controller's pod:
221
234
 
222
235
  ```bash
223
- kubectl -n system-upgrade logs -f $(kubectl -n system-upgrade get pod -l pod-template-hash -o jsonpath="{.items[0].metadata.name}")
236
+ kubectl -n system-upgrade \
237
+ logs -f $(kubectl -n system-upgrade get pod -l pod-template-hash -o jsonpath="{.items[0].metadata.name}")
224
238
  ```
225
239
 
226
240
  A final note about upgrades is that if for some reason the upgrade gets stuck after upgrading the masters and before upgrading the worker nodes, just cleaning up the resources as described above might not be enough. In that case also try running the following to tell the upgrade job for the workers that the masters have already been upgraded, so the upgrade can continue for the workers:
@@ -229,6 +243,15 @@ A final note about upgrades is that if for some reason the upgrade gets stuck af
229
243
  kubectl label node <master1> <master2> <master2> plan.upgrade.cattle.io/k3s-server=upgraded
230
244
  ```
231
245
 
246
+ ## Upgrading the OS on nodes
247
+
248
+ - consider adding a temporary node during the process if you don't have enough spare capacity in the cluster
249
+ - drain one node
250
+ - update etc
251
+ - reboot
252
+ - uncordon
253
+ - proceed with the next node
254
+
232
255
  ## Deleting a cluster
233
256
 
234
257
  To delete a cluster, running
@@ -263,7 +286,7 @@ I set `load-balancer.hetzner.cloud/hostname` to a valid hostname that I configur
263
286
 
264
287
  The annotation `load-balancer.hetzner.cloud/use-private-ip: "true"` ensures that the communication between the load balancer and the nodes happens through the private network, so we don't have to open any ports on the nodes (other than the port 6443 for the Kubernetes API server).
265
288
 
266
- The other annotations should be self explanatory. You can find a list of the available annotations here.
289
+ The other annotations should be self explanatory. You can find a list of the available annotations [here](https://pkg.go.dev/github.com/hetznercloud/hcloud-cloud-controller-manager/internal/annotation).
267
290
 
268
291
  ## Persistent volumes
269
292
 
@@ -279,6 +302,10 @@ I recommend that you create a separate Hetzner project for each cluster, because
279
302
 
280
303
  Please create a PR if you want to propose any changes, or open an issue if you are having trouble with the tool - I will do my best to help if I can.
281
304
 
305
+ Contributors:
306
+
307
+ - [TitanFighter](https://github.com/TitanFighter) for [this awesome tutorial](https://github.com/vitobotta/hetzner-k3s/wiki/Tutorial:---Setting-up-a-cluster)
308
+
282
309
  ## License
283
310
 
284
311
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/bin/build.sh CHANGED
@@ -2,13 +2,11 @@
2
2
 
3
3
  set -e
4
4
 
5
-
6
-
7
5
  IMAGE="vitobotta/hetzner-k3s"
8
6
 
9
- docker build -t ${IMAGE}:v0.5.5 \
7
+ docker build -t ${IMAGE}:v0.5.8 \
10
8
  --platform=linux/amd64 \
11
- --cache-from ${IMAGE}:v0.5.4 \
9
+ --cache-from ${IMAGE}:v0.5.7 \
12
10
  --build-arg BUILDKIT_INLINE_CACHE=1 .
13
11
 
14
- docker push vitobotta/hetzner-k3s:v0.5.5
12
+ docker push vitobotta/hetzner-k3s:v0.5.8
data/hetzner-k3s.gemspec CHANGED
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
12
12
  spec.description = 'A CLI to create a Kubernetes cluster in Hetzner Cloud very quickly using k3s.'
13
13
  spec.homepage = 'https://github.com/vitobotta/hetzner-k3s'
14
14
  spec.license = 'MIT'
15
- spec.required_ruby_version = Gem::Requirement.new('>= 3.1.0')
15
+ spec.required_ruby_version = Gem::Requirement.new('>= 3.1.2')
16
16
 
17
17
  # spec.metadata["allowed_push_host"] = "TODO: Set to 'http://mygemserver.com'"
18
18
 
@@ -7,13 +7,20 @@ module Hetzner
7
7
  @cluster_name = cluster_name
8
8
  end
9
9
 
10
- def create(location:, instance_type:, instance_id:, firewall_id:, network_id:, ssh_key_id:, placement_group_id:, image:, additional_packages: [])
10
+ def create(location:, instance_type:, instance_id:, firewall_id:, network_id:, ssh_key_id:, placement_group_id:, image:, additional_packages: [], additional_post_create_commands: [])
11
+ @location = location
12
+ @instance_type = instance_type
13
+ @instance_id = instance_id
14
+ @firewall_id = firewall_id
15
+ @network_id = network_id
16
+ @ssh_key_id = ssh_key_id
17
+ @placement_group_id = placement_group_id
18
+ @image = image
11
19
  @additional_packages = additional_packages
20
+ @additional_post_create_commands = additional_post_create_commands
12
21
 
13
22
  puts
14
23
 
15
- server_name = "#{cluster_name}-#{instance_type}-#{instance_id}"
16
-
17
24
  if (server = find_server(server_name))
18
25
  puts "Server #{server_name} already exists, skipping."
19
26
  puts
@@ -22,44 +29,16 @@ module Hetzner
22
29
 
23
30
  puts "Creating server #{server_name}..."
24
31
 
25
- server_config = {
26
- name: server_name,
27
- location:,
28
- image:,
29
- firewalls: [
30
- { firewall: firewall_id }
31
- ],
32
- networks: [
33
- network_id
34
- ],
35
- server_type: instance_type,
36
- ssh_keys: [
37
- ssh_key_id
38
- ],
39
- user_data:,
40
- labels: {
41
- cluster: cluster_name,
42
- role: (server_name =~ /master/ ? 'master' : 'worker')
43
- },
44
- placement_group: placement_group_id
45
- }
46
-
47
- response = hetzner_client.post('/servers', server_config)
48
- response_body = response.body
49
-
50
- server = JSON.parse(response_body)['server']
32
+ if (server = make_request)
33
+ puts "...server #{server_name} created."
34
+ puts
51
35
 
52
- unless server
36
+ server
37
+ else
53
38
  puts "Error creating server #{server_name}. Response details below:"
54
39
  puts
55
40
  p response
56
- return
57
41
  end
58
-
59
- puts "...server #{server_name} created."
60
- puts
61
-
62
- server
63
42
  end
64
43
 
65
44
  def delete(server_name:)
@@ -74,30 +53,78 @@ module Hetzner
74
53
 
75
54
  private
76
55
 
77
- attr_reader :hetzner_client, :cluster_name, :additional_packages
56
+ attr_reader :hetzner_client, :cluster_name, :location, :instance_type, :instance_id, :firewall_id, :network_id, :ssh_key_id, :placement_group_id, :image, :additional_packages, :additional_post_create_commands
78
57
 
79
58
  def find_server(server_name)
80
59
  hetzner_client.get('/servers?sort=created:desc')['servers'].detect { |network| network['name'] == server_name }
81
60
  end
82
61
 
83
62
  def user_data
84
- packages = ['fail2ban', 'wireguard']
63
+ packages = %w[fail2ban wireguard]
85
64
  packages += additional_packages if additional_packages
86
65
  packages = "'#{packages.join("', '")}'"
87
66
 
67
+ post_create_commands = [
68
+ 'crontab -l > /etc/cron_bkp',
69
+ 'echo "@reboot echo true > /etc/ready" >> /etc/cron_bkp',
70
+ 'crontab /etc/cron_bkp',
71
+ 'sed -i \'s/[#]*PermitRootLogin yes/PermitRootLogin prohibit-password/g\' /etc/ssh/sshd_config',
72
+ 'sed -i \'s/[#]*PasswordAuthentication yes/PasswordAuthentication no/g\' /etc/ssh/sshd_config',
73
+ 'systemctl restart sshd',
74
+ 'systemctl stop systemd-resolved',
75
+ 'systemctl disable systemd-resolved',
76
+ 'rm /etc/resolv.conf',
77
+ 'echo \'nameserver 1.1.1.1\' > /etc/resolv.conf',
78
+ 'echo \'nameserver 1.0.0.1\' >> /etc/resolv.conf'
79
+ ]
80
+
81
+ post_create_commands += additional_post_create_commands if additional_post_create_commands
82
+
83
+ post_create_commands += ['shutdown -r now'] if post_create_commands.grep(/shutdown|reboot/).grep_v(/@reboot/).empty?
84
+
85
+ post_create_commands = " - #{post_create_commands.join("\n - ")}"
86
+
88
87
  <<~YAML
89
88
  #cloud-config
90
89
  packages: [#{packages}]
91
90
  runcmd:
92
- - sed -i 's/[#]*PermitRootLogin yes/PermitRootLogin prohibit-password/g' /etc/ssh/sshd_config
93
- - sed -i 's/[#]*PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config
94
- - systemctl restart sshd
95
- - systemctl stop systemd-resolved
96
- - systemctl disable systemd-resolved
97
- - rm /etc/resolv.conf
98
- - echo "nameserver 1.1.1.1" > /etc/resolv.conf
99
- - echo "nameserver 1.0.0.1" >> /etc/resolv.conf
91
+ #{post_create_commands}
100
92
  YAML
101
93
  end
94
+
95
+ def server_name
96
+ @server_name ||= "#{cluster_name}-#{instance_type}-#{instance_id}"
97
+ end
98
+
99
+ def server_config
100
+ @server_config ||= {
101
+ name: server_name,
102
+ location:,
103
+ image:,
104
+ firewalls: [
105
+ { firewall: firewall_id }
106
+ ],
107
+ networks: [
108
+ network_id
109
+ ],
110
+ server_type: instance_type,
111
+ ssh_keys: [
112
+ ssh_key_id
113
+ ],
114
+ user_data:,
115
+ labels: {
116
+ cluster: cluster_name,
117
+ role: (server_name =~ /master/ ? 'master' : 'worker')
118
+ },
119
+ placement_group: placement_group_id
120
+ }
121
+ end
122
+
123
+ def make_request
124
+ response = hetzner_client.post('/servers', server_config)
125
+ response_body = response.body
126
+
127
+ JSON.parse(response_body)['server']
128
+ end
102
129
  end
103
130
  end