hetzner-k3s 0.4.1 → 0.4.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +22 -6
- data/bin/build.sh +4 -2
- data/lib/hetzner/infra/network.rb +4 -3
- data/lib/hetzner/infra/placement_group.rb +55 -0
- data/lib/hetzner/infra/server.rb +3 -2
- data/lib/hetzner/infra/ssh_key.rb +1 -1
- data/lib/hetzner/k3s/cli.rb +2 -1
- data/lib/hetzner/k3s/cluster.rb +18 -5
- data/lib/hetzner/k3s/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ffa9a3f4a629e25c670c3d4b3301aed094275d320db95e038ceac3e3ebebe1e2
|
4
|
+
data.tar.gz: ada1a6fb351c70f5c3a2ad52139b96911bcaa99b7d2351c89f770204dc9883c2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6dcd87e350acedf02f21bc7732f6515c74a3ee4482f554f982a05bfa96be39bda1d205014a3ff66efc8ea69fda545a9b5fc363ab8f6f0f16036ddebe87b3fc16
|
7
|
+
data.tar.gz: 2789c63c71e81b9334c9e95de8cd0e0f088f2f40bedaaf942e18003de70bac24535164f5ef225e6a9568360293611d1e20d192b1a88f306e425fb44e96a1d211
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
This is a CLI tool - based on a Ruby gem - to quickly create and manage Kubernetes clusters in [Hetzner Cloud](https://www.hetzner.com/cloud) using the lightweight Kubernetes distribution [k3s](https://k3s.io/) from [Rancher](https://rancher.com/).
|
4
4
|
|
5
|
-
Hetzner Cloud is an awesome cloud provider which offers a truly great service with the best performance/cost ratio in the market.
|
5
|
+
Hetzner Cloud is an awesome cloud provider which offers a truly great service with the best performance/cost ratio in the market. With Hetzner's Cloud Controller Manager and CSI driver you can provision load balancers and persistent volumes very easily.
|
6
6
|
|
7
7
|
k3s is my favorite Kubernetes distribution now because it uses much less memory and CPU, leaving more resources to workloads. It is also super quick to deploy because it's a single binary.
|
8
8
|
|
@@ -25,7 +25,7 @@ All that is needed to use this tool is
|
|
25
25
|
|
26
26
|
## Installation
|
27
27
|
|
28
|
-
Once you have the Ruby runtime up and running, you just need to install the gem:
|
28
|
+
Once you have the Ruby runtime up and running (2.7.2 or newer in the 2.7 series is recommended at this stage), you just need to install the gem:
|
29
29
|
|
30
30
|
```bash
|
31
31
|
gem install hetzner-k3s
|
@@ -38,7 +38,7 @@ This will install the `hetzner-k3s` executable in your PATH.
|
|
38
38
|
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):
|
39
39
|
|
40
40
|
```bash
|
41
|
-
docker run --rm -it -v ${PWD}:/cluster -v ${HOME}/.ssh:/tmp/.ssh vitobotta/hetzner-k3s:v0.4.
|
41
|
+
docker run --rm -it -v ${PWD}:/cluster -v ${HOME}/.ssh:/tmp/.ssh vitobotta/hetzner-k3s:v0.4.5 create-cluster --config-file /cluster/test.yaml
|
42
42
|
```
|
43
43
|
|
44
44
|
Replace `test.yaml` with the name of your config file.
|
@@ -59,6 +59,7 @@ ssh_allowed_networks:
|
|
59
59
|
- 0.0.0.0/0
|
60
60
|
verify_host_key: false
|
61
61
|
location: nbg1
|
62
|
+
schedule_workloads_on_masters: false
|
62
63
|
masters:
|
63
64
|
instance_type: cpx21
|
64
65
|
instance_count: 3
|
@@ -77,7 +78,7 @@ If you are using Docker, then set `kubeconfig_path` to `/cluster/kubeconfig` so
|
|
77
78
|
|
78
79
|
If you don't want to specify the Hetzner token in the config file (for example if you want to use the tool with CI), then you can use the `HCLOUD_TOKEN` environment variable instead, which has predecence.
|
79
80
|
|
80
|
-
**Important**: The tool assignes the label `cluster` to each server it creates, with the
|
81
|
+
**Important**: The tool assignes the label `cluster` to each server it creates, with the cluster name you specify in the config file, as the value. So please ensure you don't create unrelated servers in the same project having
|
81
82
|
the label `cluster=<cluster name>`, because otherwise they will be deleted if you delete the cluster. I recommend you create a separate Hetzner project for each cluster, see note at the end of this README for more details.
|
82
83
|
|
83
84
|
|
@@ -85,7 +86,8 @@ If you set `masters.instance_count` to 1 then the tool will create a non highly
|
|
85
86
|
|
86
87
|
You can specify any number of worker node pools for example to have mixed nodes with different specs for different workloads.
|
87
88
|
|
88
|
-
At the moment Hetzner Cloud has
|
89
|
+
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
|
90
|
+
been announced and it's limited to AMD instances for now.
|
89
91
|
|
90
92
|
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:
|
91
93
|
|
@@ -240,12 +242,26 @@ I recommend that you create a separate Hetzner project for each cluster, because
|
|
240
242
|
|
241
243
|
## changelog
|
242
244
|
|
245
|
+
- 0.4.5
|
246
|
+
- Fix network creation (bug introduced in the previous version)
|
247
|
+
|
248
|
+
- 0.4.4
|
249
|
+
- Add support for the new Ashburn, Virginia (USA) location
|
250
|
+
- Automatically use a placement group so that the instances are all created on different physical hosts for high availability
|
251
|
+
|
252
|
+
- 0.4.3
|
253
|
+
- Fix an issue with SSH key creation
|
254
|
+
|
255
|
+
- 0.4.2
|
256
|
+
- Update Hetzner CSI driver to v1.6.0
|
257
|
+
- Update System Upgrade Controller to v0.8.0
|
258
|
+
|
243
259
|
- 0.4.1
|
244
260
|
- Allow to optionally specify the path of the private SSH key
|
245
261
|
- Set correct permissions for the kubeconfig file
|
246
262
|
- Retry fetching manifests a few times to allow for temporary network issues
|
247
263
|
- Allow to optionally schedule workloads on masters
|
248
|
-
- Allow clusters with no worker node pools if
|
264
|
+
- Allow clusters with no worker node pools if scheduling is enabled for the masters
|
249
265
|
|
250
266
|
- 0.4.0
|
251
267
|
- Ensure the masters are removed from the API load balancer before deleting the load balancer
|
data/bin/build.sh
CHANGED
@@ -6,7 +6,9 @@ set -e
|
|
6
6
|
|
7
7
|
IMAGE="vitobotta/hetzner-k3s"
|
8
8
|
|
9
|
-
docker build -t ${IMAGE}:v0.4.
|
9
|
+
docker build -t ${IMAGE}:v0.4.5 \
|
10
10
|
--platform=linux/amd64 \
|
11
|
-
--cache-from ${IMAGE}:v0.4.
|
11
|
+
--cache-from ${IMAGE}:v0.4.4 \
|
12
12
|
--build-arg BUILDKIT_INLINE_CACHE=1 .
|
13
|
+
|
14
|
+
docker push vitobotta/hetzner-k3s:v0.4.5
|
@@ -5,7 +5,8 @@ module Hetzner
|
|
5
5
|
@cluster_name = cluster_name
|
6
6
|
end
|
7
7
|
|
8
|
-
def create
|
8
|
+
def create(location:)
|
9
|
+
@location = location
|
9
10
|
puts
|
10
11
|
|
11
12
|
if network = find_network
|
@@ -38,7 +39,7 @@ module Hetzner
|
|
38
39
|
|
39
40
|
private
|
40
41
|
|
41
|
-
attr_reader :hetzner_client, :cluster_name
|
42
|
+
attr_reader :hetzner_client, :cluster_name, :location
|
42
43
|
|
43
44
|
def network_config
|
44
45
|
{
|
@@ -47,7 +48,7 @@ module Hetzner
|
|
47
48
|
subnets: [
|
48
49
|
{
|
49
50
|
ip_range: "10.0.0.0/16",
|
50
|
-
network_zone: "eu-central",
|
51
|
+
network_zone: (location == "ash" ? "us-east" : "eu-central"),
|
51
52
|
type: "cloud"
|
52
53
|
}
|
53
54
|
]
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Hetzner
|
2
|
+
class PlacementGroup
|
3
|
+
def initialize(hetzner_client:, cluster_name:)
|
4
|
+
@hetzner_client = hetzner_client
|
5
|
+
@cluster_name = cluster_name
|
6
|
+
end
|
7
|
+
|
8
|
+
def create
|
9
|
+
puts
|
10
|
+
|
11
|
+
if (placement_group = find_placement_group)
|
12
|
+
puts "Placement group already exists, skipping."
|
13
|
+
puts
|
14
|
+
return placement_group["id"]
|
15
|
+
end
|
16
|
+
|
17
|
+
puts "Creating placement group..."
|
18
|
+
|
19
|
+
response = hetzner_client.post("/placement_groups", placement_group_config).body
|
20
|
+
|
21
|
+
puts "...placement group created."
|
22
|
+
puts
|
23
|
+
|
24
|
+
JSON.parse(response)["placement_group"]["id"]
|
25
|
+
end
|
26
|
+
|
27
|
+
def delete
|
28
|
+
if (placement_group = find_placement_group)
|
29
|
+
puts "Deleting placement group..."
|
30
|
+
hetzner_client.delete("/placement_groups", placement_group["id"])
|
31
|
+
puts "...placement group deleted."
|
32
|
+
else
|
33
|
+
puts "Placement group no longer exists, skipping."
|
34
|
+
end
|
35
|
+
|
36
|
+
puts
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
attr_reader :hetzner_client, :cluster_name
|
42
|
+
|
43
|
+
def placement_group_config
|
44
|
+
{
|
45
|
+
name: cluster_name,
|
46
|
+
type: "spread"
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
def find_placement_group
|
51
|
+
hetzner_client.get("/placement_groups")["placement_groups"].detect{ |placement_group| placement_group["name"] == cluster_name }
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
data/lib/hetzner/infra/server.rb
CHANGED
@@ -5,7 +5,7 @@ module Hetzner
|
|
5
5
|
@cluster_name = cluster_name
|
6
6
|
end
|
7
7
|
|
8
|
-
def create(location:, instance_type:, instance_id:, firewall_id:, network_id:, ssh_key_id:)
|
8
|
+
def create(location:, instance_type:, instance_id:, firewall_id:, network_id:, ssh_key_id:, placement_group_id:)
|
9
9
|
puts
|
10
10
|
|
11
11
|
server_name = "#{cluster_name}-#{instance_type}-#{instance_id}"
|
@@ -36,7 +36,8 @@ module Hetzner
|
|
36
36
|
labels: {
|
37
37
|
cluster: cluster_name,
|
38
38
|
role: (server_name =~ /master/ ? "master" : "worker")
|
39
|
-
}
|
39
|
+
},
|
40
|
+
placement_group: placement_group_id
|
40
41
|
}
|
41
42
|
|
42
43
|
response = hetzner_client.post("/servers", server_config).body
|
data/lib/hetzner/k3s/cli.rb
CHANGED
@@ -193,7 +193,7 @@ module Hetzner
|
|
193
193
|
|
194
194
|
def validate_location
|
195
195
|
return if locations.empty? && !valid_token?
|
196
|
-
errors << "Invalid location - available locations: nbg1 (Nuremberg, Germany), fsn1 (Falkenstein, Germany), hel1 (Helsinki, Finland)" unless locations.include? configuration.dig("location")
|
196
|
+
errors << "Invalid location - available locations: nbg1 (Nuremberg, Germany), fsn1 (Falkenstein, Germany), hel1 (Helsinki, Finland) or ash (Ashburn, Virginia, USA)" unless locations.include? configuration.dig("location")
|
197
197
|
end
|
198
198
|
|
199
199
|
def find_available_releases
|
@@ -339,6 +339,7 @@ module Hetzner
|
|
339
339
|
config_hash = YAML.load_file(File.expand_path(configuration["kubeconfig_path"]))
|
340
340
|
config_hash['current-context'] = configuration["cluster_name"]
|
341
341
|
@kubernetes_client = K8s::Client.config(K8s::Config.new(config_hash))
|
342
|
+
rescue
|
342
343
|
errors << "Cannot connect to the Kubernetes cluster"
|
343
344
|
false
|
344
345
|
end
|
data/lib/hetzner/k3s/cluster.rb
CHANGED
@@ -11,6 +11,7 @@ require_relative "../infra/network"
|
|
11
11
|
require_relative "../infra/ssh_key"
|
12
12
|
require_relative "../infra/server"
|
13
13
|
require_relative "../infra/load_balancer"
|
14
|
+
require_relative "../infra/placement_group"
|
14
15
|
|
15
16
|
require_relative "../k3s/client_patch"
|
16
17
|
|
@@ -89,6 +90,11 @@ class Cluster
|
|
89
90
|
master_instance_type = masters_config["instance_type"]
|
90
91
|
masters_count = masters_config["instance_count"]
|
91
92
|
|
93
|
+
placement_group_id = Hetzner::PlacementGroup.new(
|
94
|
+
hetzner_client: hetzner_client,
|
95
|
+
cluster_name: cluster_name
|
96
|
+
).create
|
97
|
+
|
92
98
|
firewall_id = Hetzner::Firewall.new(
|
93
99
|
hetzner_client: hetzner_client,
|
94
100
|
cluster_name: cluster_name
|
@@ -97,7 +103,7 @@ class Cluster
|
|
97
103
|
network_id = Hetzner::Network.new(
|
98
104
|
hetzner_client: hetzner_client,
|
99
105
|
cluster_name: cluster_name
|
100
|
-
).create
|
106
|
+
).create(location: location)
|
101
107
|
|
102
108
|
ssh_key_id = Hetzner::SSHKey.new(
|
103
109
|
hetzner_client: hetzner_client,
|
@@ -113,7 +119,8 @@ class Cluster
|
|
113
119
|
instance_id: "master#{i+1}",
|
114
120
|
firewall_id: firewall_id,
|
115
121
|
network_id: network_id,
|
116
|
-
ssh_key_id: ssh_key_id
|
122
|
+
ssh_key_id: ssh_key_id,
|
123
|
+
placement_group_id: placement_group_id
|
117
124
|
}
|
118
125
|
end
|
119
126
|
|
@@ -136,7 +143,8 @@ class Cluster
|
|
136
143
|
instance_id: "pool-#{worker_node_pool_name}-worker#{i+1}",
|
137
144
|
firewall_id: firewall_id,
|
138
145
|
network_id: network_id,
|
139
|
-
ssh_key_id: ssh_key_id
|
146
|
+
ssh_key_id: ssh_key_id,
|
147
|
+
placement_group_id: placement_group_id
|
140
148
|
}
|
141
149
|
end
|
142
150
|
end
|
@@ -158,6 +166,11 @@ class Cluster
|
|
158
166
|
end
|
159
167
|
|
160
168
|
def delete_resources
|
169
|
+
Hetzner::PlacementGroup.new(
|
170
|
+
hetzner_client: hetzner_client,
|
171
|
+
cluster_name: cluster_name
|
172
|
+
).delete
|
173
|
+
|
161
174
|
Hetzner::LoadBalancer.new(
|
162
175
|
hetzner_client: hetzner_client,
|
163
176
|
cluster_name: cluster_name
|
@@ -358,7 +371,7 @@ class Cluster
|
|
358
371
|
puts
|
359
372
|
puts "Deploying k3s System Upgrade Controller..."
|
360
373
|
|
361
|
-
manifest = HTTP.follow.get("https://github.com/rancher/system-upgrade-controller/releases/download/v0.
|
374
|
+
manifest = HTTP.follow.get("https://github.com/rancher/system-upgrade-controller/releases/download/v0.8.0/system-upgrade-controller.yaml").body
|
362
375
|
|
363
376
|
File.write("/tmp/system-upgrade-controller.yaml", manifest)
|
364
377
|
|
@@ -407,7 +420,7 @@ class Cluster
|
|
407
420
|
end
|
408
421
|
|
409
422
|
|
410
|
-
manifest = HTTP.follow.get("https://raw.githubusercontent.com/hetznercloud/csi-driver/v1.
|
423
|
+
manifest = HTTP.follow.get("https://raw.githubusercontent.com/hetznercloud/csi-driver/v1.6.0/deploy/kubernetes/hcloud-csi.yml").body
|
411
424
|
|
412
425
|
File.write("/tmp/csi-driver.yaml", manifest)
|
413
426
|
|
data/lib/hetzner/k3s/version.rb
CHANGED
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.4.
|
4
|
+
version: 0.4.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vito Botta
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-11-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -140,6 +140,7 @@ files:
|
|
140
140
|
- lib/hetzner/infra/firewall.rb
|
141
141
|
- lib/hetzner/infra/load_balancer.rb
|
142
142
|
- lib/hetzner/infra/network.rb
|
143
|
+
- lib/hetzner/infra/placement_group.rb
|
143
144
|
- lib/hetzner/infra/server.rb
|
144
145
|
- lib/hetzner/infra/ssh_key.rb
|
145
146
|
- lib/hetzner/k3s/cli.rb
|