hetzner-k3s 0.5.6 → 0.5.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +15 -1
- data/.ruby-version +1 -1
- data/Dockerfile +1 -1
- data/Gemfile.lock +5 -5
- data/README.md +39 -7
- data/bin/build.sh +3 -5
- data/hetzner-k3s.gemspec +1 -1
- data/lib/hetzner/infra/firewall.rb +6 -8
- data/lib/hetzner/infra/network.rb +19 -9
- data/lib/hetzner/infra/server.rb +73 -46
- data/lib/hetzner/k3s/cli.rb +14 -386
- data/lib/hetzner/k3s/cluster.rb +53 -29
- data/lib/hetzner/k3s/configuration.rb +484 -0
- data/lib/hetzner/k3s/version.rb +1 -1
- data/lib/hetzner/utils.rb +7 -4
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 65fe7fa7e6bdeeb49175cfb92184ab320ef8ac40a3aa03f921f1e5fda1b172d7
|
4
|
+
data.tar.gz: 1448919374ef90f7614580251b28000c470b0ed7fba39724e8953f29f176c1bb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 15f783adb7408a1df5c3e9a114d9dcbc61830ead33acb7bc162ca935b6cdcfe26507e2c404d48c831cae600fe765adc31e686b511c4f675c561d6eb9acabafd2
|
7
|
+
data.tar.gz: df10039025e735d6a73c84fb60516d70bc0aa48220db1bab9d99dd30caad87339ba6be83e2d3f1029f40f95719a6fcde5784956c86ef20d524b67d504f93920a
|
data/.rubocop.yml
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
Gemspec/
|
1
|
+
Gemspec/DeprecatedAttributeAssignment: # new in 1.10
|
2
2
|
Enabled: true
|
3
3
|
Gemspec/RequireMFA: # new in 1.23
|
4
4
|
Enabled: true
|
@@ -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.
|
1
|
+
ruby-3.1.2
|
data/Dockerfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
hetzner-k3s (0.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.
|
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.
|
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.
|
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.
|
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
|
44
|
+
docker run --rm -it \
|
45
|
+
-v ${PWD}:/cluster \
|
46
|
+
-v ${HOME}/.ssh:/tmp/.ssh \
|
47
|
+
vitobotta/hetzner-k3s:v0.5.9 \
|
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.
|
@@ -58,6 +65,8 @@ public_ssh_key_path: "~/.ssh/id_rsa.pub"
|
|
58
65
|
private_ssh_key_path: "~/.ssh/id_rsa"
|
59
66
|
ssh_allowed_networks:
|
60
67
|
- 0.0.0.0/0
|
68
|
+
api_allowed_networks:
|
69
|
+
- 0.0.0.0/0
|
61
70
|
verify_host_key: false
|
62
71
|
location: nbg1
|
63
72
|
schedule_workloads_on_masters: false
|
@@ -73,6 +82,11 @@ worker_node_pools:
|
|
73
82
|
instance_count: 2
|
74
83
|
additional_packages:
|
75
84
|
- somepackage
|
85
|
+
post_create_commands:
|
86
|
+
- apt update
|
87
|
+
- apt upgrade -y
|
88
|
+
- apt autoremove -y
|
89
|
+
- shutdown -r now
|
76
90
|
enable_encryption: true
|
77
91
|
# kube_api_server_args:
|
78
92
|
# - arg1
|
@@ -92,6 +106,7 @@ enable_encryption: true
|
|
92
106
|
# kube_proxy_args:
|
93
107
|
# - arg1
|
94
108
|
# - ...
|
109
|
+
# existing_network: <specify if you want to use an existing network, otherwise one will be created for this cluster>
|
95
110
|
|
96
111
|
```
|
97
112
|
|
@@ -131,9 +146,11 @@ curl \
|
|
131
146
|
'https://api.hetzner.cloud/v1/images'
|
132
147
|
```
|
133
148
|
|
134
|
-
|
149
|
+
Notes:
|
135
150
|
|
136
|
-
|
151
|
+
- if you use a custom image, the creation of the servers may take longer than when using the default image
|
152
|
+
- the option `verify_host_key` is by default set to `false` to disable host key verification. This is because sometimes when creating new servers, Hetzner may assign IP addresses that were previously used by other servers you owned in the past. Therefore the host key verification would fail. If you set this option to `true` and this happens, the tool won't be able to continue creating the cluster until you resolve the issue with one of the suggestions it will give you
|
153
|
+
- the setting `api_allowed_networks` allows specifying which networks can access the Kubernetes API, but this only works with single master clusters currently. Multi-master HA clusters require a load balancer for the API, but load balancers are not yet covered by Hetzner's firewalls.
|
137
154
|
|
138
155
|
Finally, to create the cluster run:
|
139
156
|
|
@@ -159,6 +176,8 @@ The `create-cluster` command can be run any number of times with the same config
|
|
159
176
|
|
160
177
|
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
178
|
|
179
|
+
**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).
|
180
|
+
|
162
181
|
### Scaling down a node pool
|
163
182
|
|
164
183
|
To make a node pool smaller:
|
@@ -194,7 +213,6 @@ Note that the API server will briefly be unavailable during the upgrade of the c
|
|
194
213
|
|
195
214
|
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
215
|
|
197
|
-
|
198
216
|
### What to do if the upgrade doesn't go smoothly
|
199
217
|
|
200
218
|
If the upgrade gets stuck for some reason, or it doesn't upgrade all the nodes:
|
@@ -220,7 +238,8 @@ I have noticed that sometimes I need to re-run the upgrade command a couple of t
|
|
220
238
|
You can also check the logs of the system upgrade controller's pod:
|
221
239
|
|
222
240
|
```bash
|
223
|
-
kubectl -n system-upgrade
|
241
|
+
kubectl -n system-upgrade \
|
242
|
+
logs -f $(kubectl -n system-upgrade get pod -l pod-template-hash -o jsonpath="{.items[0].metadata.name}")
|
224
243
|
```
|
225
244
|
|
226
245
|
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 +248,15 @@ A final note about upgrades is that if for some reason the upgrade gets stuck af
|
|
229
248
|
kubectl label node <master1> <master2> <master2> plan.upgrade.cattle.io/k3s-server=upgraded
|
230
249
|
```
|
231
250
|
|
251
|
+
## Upgrading the OS on nodes
|
252
|
+
|
253
|
+
- consider adding a temporary node during the process if you don't have enough spare capacity in the cluster
|
254
|
+
- drain one node
|
255
|
+
- update etc
|
256
|
+
- reboot
|
257
|
+
- uncordon
|
258
|
+
- proceed with the next node
|
259
|
+
|
232
260
|
## Deleting a cluster
|
233
261
|
|
234
262
|
To delete a cluster, running
|
@@ -263,7 +291,7 @@ I set `load-balancer.hetzner.cloud/hostname` to a valid hostname that I configur
|
|
263
291
|
|
264
292
|
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
293
|
|
266
|
-
The other annotations should be self explanatory. You can find a list of the available annotations here.
|
294
|
+
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
295
|
|
268
296
|
## Persistent volumes
|
269
297
|
|
@@ -279,6 +307,10 @@ I recommend that you create a separate Hetzner project for each cluster, because
|
|
279
307
|
|
280
308
|
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
309
|
|
310
|
+
Contributors:
|
311
|
+
|
312
|
+
- [TitanFighter](https://github.com/TitanFighter) for [this awesome tutorial](https://github.com/vitobotta/hetzner-k3s/wiki/Tutorial:---Setting-up-a-cluster)
|
313
|
+
|
282
314
|
## License
|
283
315
|
|
284
316
|
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.
|
7
|
+
docker build -t ${IMAGE}:v0.5.9 \
|
10
8
|
--platform=linux/amd64 \
|
11
|
-
--cache-from ${IMAGE}:v0.5.
|
9
|
+
--cache-from ${IMAGE}:v0.5.8 \
|
12
10
|
--build-arg BUILDKIT_INLINE_CACHE=1 .
|
13
11
|
|
14
|
-
docker push vitobotta/hetzner-k3s:v0.5.
|
12
|
+
docker push vitobotta/hetzner-k3s:v0.5.9
|
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.
|
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,9 +7,10 @@ module Hetzner
|
|
7
7
|
@cluster_name = cluster_name
|
8
8
|
end
|
9
9
|
|
10
|
-
def create(high_availability:,
|
10
|
+
def create(high_availability:, ssh_networks:, api_networks:)
|
11
11
|
@high_availability = high_availability
|
12
|
-
@
|
12
|
+
@ssh_networks = ssh_networks
|
13
|
+
@api_networks = api_networks
|
13
14
|
puts
|
14
15
|
|
15
16
|
if (firewall = find_firewall)
|
@@ -47,7 +48,7 @@ module Hetzner
|
|
47
48
|
|
48
49
|
private
|
49
50
|
|
50
|
-
attr_reader :hetzner_client, :cluster_name, :firewall, :high_availability, :
|
51
|
+
attr_reader :hetzner_client, :cluster_name, :firewall, :high_availability, :ssh_networks, :api_networks
|
51
52
|
|
52
53
|
def create_firewall_config
|
53
54
|
rules = [
|
@@ -56,7 +57,7 @@ module Hetzner
|
|
56
57
|
direction: 'in',
|
57
58
|
protocol: 'tcp',
|
58
59
|
port: '22',
|
59
|
-
source_ips:
|
60
|
+
source_ips: ssh_networks,
|
60
61
|
destination_ips: []
|
61
62
|
},
|
62
63
|
{
|
@@ -98,10 +99,7 @@ module Hetzner
|
|
98
99
|
direction: 'in',
|
99
100
|
protocol: 'tcp',
|
100
101
|
port: '6443',
|
101
|
-
source_ips:
|
102
|
-
'0.0.0.0/0',
|
103
|
-
'::/0'
|
104
|
-
],
|
102
|
+
source_ips: api_networks,
|
105
103
|
destination_ips: []
|
106
104
|
}
|
107
105
|
end
|
@@ -2,9 +2,10 @@
|
|
2
2
|
|
3
3
|
module Hetzner
|
4
4
|
class Network
|
5
|
-
def initialize(hetzner_client:, cluster_name:)
|
5
|
+
def initialize(hetzner_client:, cluster_name:, existing_network:)
|
6
6
|
@hetzner_client = hetzner_client
|
7
7
|
@cluster_name = cluster_name
|
8
|
+
@existing_network = existing_network
|
8
9
|
end
|
9
10
|
|
10
11
|
def create(location:)
|
@@ -29,9 +30,13 @@ module Hetzner
|
|
29
30
|
|
30
31
|
def delete
|
31
32
|
if (network = find_network)
|
32
|
-
|
33
|
-
|
34
|
-
|
33
|
+
if network["name"] == existing_network
|
34
|
+
puts "Network existed before cluster, skipping."
|
35
|
+
else
|
36
|
+
puts 'Deleting network...'
|
37
|
+
hetzner_client.delete('/networks', network['id'])
|
38
|
+
puts '...network deleted.'
|
39
|
+
end
|
35
40
|
else
|
36
41
|
puts 'Network no longer exists, skipping.'
|
37
42
|
end
|
@@ -39,9 +44,18 @@ module Hetzner
|
|
39
44
|
puts
|
40
45
|
end
|
41
46
|
|
47
|
+
def find_network
|
48
|
+
network_name = existing_network || cluster_name
|
49
|
+
hetzner_client.get('/networks')['networks'].detect { |network| network['name'] == network_name }
|
50
|
+
end
|
51
|
+
|
52
|
+
def get
|
53
|
+
find_network
|
54
|
+
end
|
55
|
+
|
42
56
|
private
|
43
57
|
|
44
|
-
attr_reader :hetzner_client, :cluster_name, :location
|
58
|
+
attr_reader :hetzner_client, :cluster_name, :location, :existing_network
|
45
59
|
|
46
60
|
def network_config
|
47
61
|
{
|
@@ -56,9 +70,5 @@ module Hetzner
|
|
56
70
|
]
|
57
71
|
}
|
58
72
|
end
|
59
|
-
|
60
|
-
def find_network
|
61
|
-
hetzner_client.get('/networks')['networks'].detect { |network| network['name'] == cluster_name }
|
62
|
-
end
|
63
73
|
end
|
64
74
|
end
|
data/lib/hetzner/infra/server.rb
CHANGED
@@ -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
|
-
|
26
|
-
|
27
|
-
|
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
|
-
|
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 = [
|
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
|
-
|
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
|