Skip to content

Commit 353a12a

Browse files
committed
added kustomization backup
1 parent 0dd979a commit 353a12a

File tree

6 files changed

+119
-82
lines changed

6 files changed

+119
-82
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@ kubeconfig.yaml-e
66
terraform.tfvars
77
plans-custom.yaml
88
traefik-custom.yaml
9-
kured-custom.yaml
9+
kured-custom.yaml
10+
kustomization.yaml
11+
kustomization_backup.yaml

README.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,25 +114,38 @@ Otherwise, it's essential to turn off automatic OS upgrades (k3s can continue to
114114

115115
## Automatic Upgrade
116116

117+
### The Default Setting
118+
117119
By default, MicroOS gets upgraded automatically on each node and reboot safely via [Kured](https://github.com/weaveworks/kured) installed in the cluster.
118120

119121
As for k3s, it also automatically upgrades thanks to Rancher's [system upgrade controller](https://github.com/rancher/system-upgrade-controller). By default, it follows the k3s `stable` channel, but you can also change to the `latest` one if needed or specify a target version to upgrade to via the upgrade plan.
120122

121123
You can copy and modify the [one in the templates](https://github.com/kube-hetzner/kube-hetzner/blob/master/templates/plans.yaml.tpl) for that! More on the subject in [k3s upgrades](https://rancher.com/docs/k3s/latest/en/upgrades/basic/).
122124

123-
_If you wish to turn off automatic MicroOS upgrades on a specific node, you need to ssh into it and issue the following command:_
125+
### Turning Off Automatic Upgrade
126+
127+
_If you wish to turn off automatic MicroOS upgrades (Important if you are not launching an HA setup which requires at least 3 control-plane nodes), you need to ssh into each node and issue the following command:_
124128

125129
```sh
126130
systemctl --now disable transactional-update.timer
127131

128132
```
129133

130-
_To turn off k3s upgrades, you can either set the `k3s_upgrade=true` label in the node you want or set it to `false`. To remove it, apply:_
134+
_To turn off k3s upgrades, you can either remove the `k3s_upgrade=true` label or set it to `false`. This needs to happen for all the nodes too! To remove it, apply:_
131135

132136
```sh
133137
kubectl -n system-upgrade label node <node-name> k3s_upgrade-
134138
```
135139

140+
### Individual Components Upgrade
141+
142+
Rarely needed, but can be handy in the long run. During the installation, we automatically download a backup of the kustomization to a `kustomization_backup.yaml` file. You will find it next to your `kubeconfig.yaml` at the root of your project.
143+
144+
1. First create a duplicate of that file and name it `kustomization.yaml`, keeping the original file intact, in case you need to restore the old config.
145+
2. Edit the `kustomization.yaml` file; you want to go to the very bottom where you have the links to the different source files; grab the latest versions for each on Github, and replace.
146+
3. If present, remove any local reference to `traefik_config.yaml`, as Traefik is updated automatically by the system upgrade controller.
147+
4. Apply the the updated `kustomization.yaml` with `kubectl apply -k ./`.
148+
136149
## Examples
137150

138151
<details>

init.tf

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ resource "null_resource" "first_control_plane" {
4040
inline = [
4141
"systemctl start k3s",
4242
# prepare the post_install directory
43-
"mkdir -p /tmp/post_install",
43+
"mkdir -p /var/post_install",
4444
# wait for k3s to become ready
4545
<<-EOT
4646
timeout 120 bash <<EOF
@@ -85,15 +85,15 @@ resource "null_resource" "kustomization" {
8585
"https://raw.githubusercontent.com/hetznercloud/csi-driver/${local.csi_version}/deploy/kubernetes/hcloud-csi.yml",
8686
"https://github.com/weaveworks/kured/releases/download/${local.kured_version}/kured-${local.kured_version}-dockerhub.yaml",
8787
"https://raw.githubusercontent.com/rancher/system-upgrade-controller/master/manifests/system-upgrade-controller.yaml",
88-
], local.is_single_node_cluster ? [] : var.traefik_enabled ? ["traefik.yaml"] : []
88+
], local.is_single_node_cluster ? [] : var.traefik_enabled ? ["traefik_config.yaml"] : []
8989
, var.cni_plugin == "calico" ? ["https://projectcalico.docs.tigera.io/manifests/calico.yaml"] : []),
9090
patchesStrategicMerge = concat([
9191
file("${path.module}/kustomize/kured.yaml"),
9292
file("${path.module}/kustomize/ccm.yaml"),
9393
file("${path.module}/kustomize/system-upgrade-controller.yaml")
9494
], var.cni_plugin == "calico" ? [file("${path.module}/kustomize/calico.yaml")] : [])
9595
})
96-
destination = "/tmp/post_install/kustomization.yaml"
96+
destination = "/var/post_install/kustomization.yaml"
9797
}
9898

9999
# Upload traefik config
@@ -109,7 +109,7 @@ resource "null_resource" "kustomization" {
109109
traefik_acme_email = var.traefik_acme_email
110110
traefik_additional_options = var.traefik_additional_options
111111
})
112-
destination = "/tmp/post_install/traefik.yaml"
112+
destination = "/var/post_install/traefik_config.yaml"
113113
}
114114

115115
# Upload the system upgrade controller plans config
@@ -119,7 +119,7 @@ resource "null_resource" "kustomization" {
119119
{
120120
channel = var.initial_k3s_channel
121121
})
122-
destination = "/tmp/post_install/plans.yaml"
122+
destination = "/var/post_install/plans.yaml"
123123
}
124124

125125
# Deploy secrets, logging is automatically disabled due to sensitive variables
@@ -143,11 +143,11 @@ resource "null_resource" "kustomization" {
143143
# replace lines like "- |3" by "- |" (yaml block syntax).
144144
# due to indendation this should not changes the embedded
145145
# manifests themselves
146-
"sed -i 's/^- |[0-9]\\+$/- |/g' /tmp/post_install/kustomization.yaml",
147-
"kubectl apply -k /tmp/post_install",
146+
"sed -i 's/^- |[0-9]\\+$/- |/g' /var/post_install/kustomization.yaml",
147+
"kubectl apply -k /var/post_install",
148148
"echo 'Waiting for the system-upgrade-controller deployment to become available...'",
149149
"kubectl -n system-upgrade wait --for=condition=available --timeout=120s deployment/system-upgrade-controller",
150-
"kubectl -n system-upgrade apply -f /tmp/post_install/plans.yaml"
150+
"kubectl -n system-upgrade apply -f /var/post_install/plans.yaml"
151151
],
152152
local.is_single_node_cluster || var.traefik_enabled == false ? [] : [<<-EOT
153153
timeout 120 bash <<EOF

kustomization_backup.tf

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
data "remote_file" "kustomization_backup" {
2+
conn {
3+
host = module.control_planes[keys(module.control_planes)[0]].ipv4_address
4+
port = 22
5+
user = "root"
6+
private_key = local.ssh_private_key
7+
agent = var.private_key == null
8+
}
9+
path = "/var/post_install/kustomization.yaml"
10+
11+
depends_on = [null_resource.kustomization]
12+
}
13+
14+
resource "local_file" "kustomization_backup" {
15+
content = data.remote_file.kustomization_backup.content
16+
filename = "kustomization_backup.yaml"
17+
file_permission = "600"
18+
}

locals.tf

Lines changed: 68 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,5 @@
11
locals {
2-
# if we are in a single cluster config, we use the default klipper lb instead of Hetzner LB
3-
total_node_count = sum(concat([for v in var.control_plane_nodepools : v.count], [0])) + sum(concat([for v in var.agent_nodepools : v.count], [0]))
4-
control_plane_count = sum(concat([for v in var.control_plane_nodepools : v.count], [0]))
5-
agent_count = sum(concat([for v in var.agent_nodepools : v.count], [0]))
6-
is_single_node_cluster = local.total_node_count == 1
7-
ssh_public_key = trimspace(file(var.public_key))
2+
ssh_public_key = trimspace(file(var.public_key))
83
# ssh_private_key is either the contents of var.private_key or null to use a ssh agent.
94
ssh_private_key = var.private_key == null ? null : trimspace(file(var.private_key))
105
# ssh_identity is not set if the private key is passed directly, but if ssh agent is used, the public key tells ssh agent which private key to use.
@@ -20,6 +15,73 @@ locals {
2015
csi_version = var.hetzner_csi_version != null ? var.hetzner_csi_version : data.github_release.hetzner_csi.release_tag
2116
kured_version = data.github_release.kured.release_tag
2217

18+
common_commands_install_k3s = [
19+
"set -ex",
20+
# prepare the k3s config directory
21+
"mkdir -p /etc/rancher/k3s",
22+
# move the config file into place
23+
"mv /tmp/config.yaml /etc/rancher/k3s/config.yaml",
24+
# if the server has already been initialized just stop here
25+
"[ -e /etc/rancher/k3s/k3s.yaml ] && exit 0",
26+
]
27+
28+
apply_k3s_selinux = ["/sbin/semodule -v -i /usr/share/selinux/packages/k3s.pp"]
29+
30+
install_k3s_server = concat(local.common_commands_install_k3s, ["curl -sfL https://get.k3s.io | INSTALL_K3S_SKIP_START=true INSTALL_K3S_SKIP_SELINUX_RPM=true INSTALL_K3S_CHANNEL=${var.initial_k3s_channel} INSTALL_K3S_EXEC=server sh -"], local.apply_k3s_selinux)
31+
install_k3s_agent = concat(local.common_commands_install_k3s, ["curl -sfL https://get.k3s.io | INSTALL_K3S_SKIP_START=true INSTALL_K3S_SKIP_SELINUX_RPM=true INSTALL_K3S_CHANNEL=${var.initial_k3s_channel} INSTALL_K3S_EXEC=agent sh -"], local.apply_k3s_selinux)
32+
33+
control_plane_nodes = merge([
34+
for pool_index, nodepool_obj in var.control_plane_nodepools : {
35+
for node_index in range(nodepool_obj.count) :
36+
format("%s-%s-%s", pool_index, node_index, nodepool_obj.name) => {
37+
nodepool_name : nodepool_obj.name,
38+
server_type : nodepool_obj.server_type,
39+
location : nodepool_obj.location,
40+
labels : concat(local.default_control_plane_labels, nodepool_obj.labels),
41+
taints : concat(local.default_control_plane_taints, nodepool_obj.taints),
42+
index : node_index
43+
}
44+
}
45+
]...)
46+
47+
agent_nodes = merge([
48+
for pool_index, nodepool_obj in var.agent_nodepools : {
49+
for node_index in range(nodepool_obj.count) :
50+
format("%s-%s-%s", pool_index, node_index, nodepool_obj.name) => {
51+
nodepool_name : nodepool_obj.name,
52+
server_type : nodepool_obj.server_type,
53+
location : nodepool_obj.location,
54+
labels : concat(local.default_agent_labels, nodepool_obj.labels),
55+
taints : nodepool_obj.taints,
56+
index : node_index
57+
}
58+
}
59+
]...)
60+
61+
# The main network cidr that all subnets will be created upon
62+
network_ipv4_cidr = "10.0.0.0/8"
63+
64+
# The first two subnets are respectively the default subnet 10.0.0.0/16 use for potientially anything and 10.1.0.0/16 used for control plane nodes.
65+
# the rest of the subnets are for agent nodes in each nodepools.
66+
network_ipv4_subnets = [for index in range(256) : cidrsubnet(local.network_ipv4_cidr, 8, index)]
67+
68+
# if we are in a single cluster config, we use the default klipper lb instead of Hetzner LB
69+
control_plane_count = sum([for v in var.control_plane_nodepools : v.count])
70+
agent_count = sum([for v in var.agent_nodepools : v.count])
71+
is_single_node_cluster = local.control_plane_count + local.agent_count == 1
72+
73+
# disable k3s extras
74+
disable_extras = concat(["local-storage"], local.is_single_node_cluster ? [] : ["servicelb"], var.traefik_enabled ? [] : ["traefik"], var.metrics_server_enabled ? [] : ["metrics-server"])
75+
76+
# Default k3s node labels
77+
default_agent_labels = concat([], var.automatically_upgrade_k3s ? ["k3s_upgrade=true"] : [])
78+
default_control_plane_labels = concat([], var.automatically_upgrade_k3s ? ["k3s_upgrade=true"] : [])
79+
80+
allow_scheduling_on_control_plane = local.is_single_node_cluster ? true : var.allow_scheduling_on_control_plane
81+
82+
# Default k3s node taints
83+
default_control_plane_taints = concat([], local.allow_scheduling_on_control_plane ? [] : ["node-role.kubernetes.io/master:NoSchedule"])
84+
2385
# The following IPs are important to be whitelisted because they communicate with Hetzner services and enable the CCM and CSI to work properly.
2486
# Source https://github.com/hetznercloud/csi-driver/issues/204#issuecomment-848625566
2587
hetzner_metadata_service_ipv4 = "169.254.169.254/32"
@@ -156,66 +218,4 @@ locals {
156218
]
157219
}
158220
])
159-
160-
common_commands_install_k3s = [
161-
"set -ex",
162-
# prepare the k3s config directory
163-
"mkdir -p /etc/rancher/k3s",
164-
# move the config file into place
165-
"mv /tmp/config.yaml /etc/rancher/k3s/config.yaml",
166-
# if the server has already been initialized just stop here
167-
"[ -e /etc/rancher/k3s/k3s.yaml ] && exit 0",
168-
]
169-
170-
apply_k3s_selinux = ["/sbin/semodule -v -i /usr/share/selinux/packages/k3s.pp"]
171-
172-
install_k3s_server = concat(local.common_commands_install_k3s, ["curl -sfL https://get.k3s.io | INSTALL_K3S_SKIP_START=true INSTALL_K3S_SKIP_SELINUX_RPM=true INSTALL_K3S_CHANNEL=${var.initial_k3s_channel} INSTALL_K3S_EXEC=server sh -"], local.apply_k3s_selinux)
173-
install_k3s_agent = concat(local.common_commands_install_k3s, ["curl -sfL https://get.k3s.io | INSTALL_K3S_SKIP_START=true INSTALL_K3S_SKIP_SELINUX_RPM=true INSTALL_K3S_CHANNEL=${var.initial_k3s_channel} INSTALL_K3S_EXEC=agent sh -"], local.apply_k3s_selinux)
174-
175-
control_plane_nodes = merge([
176-
for pool_index, nodepool_obj in var.control_plane_nodepools : {
177-
for node_index in range(nodepool_obj.count) :
178-
format("%s-%s-%s", pool_index, node_index, nodepool_obj.name) => {
179-
nodepool_name : nodepool_obj.name,
180-
server_type : nodepool_obj.server_type,
181-
location : nodepool_obj.location,
182-
labels : concat(local.default_control_plane_labels, nodepool_obj.labels),
183-
taints : concat(local.default_control_plane_taints, nodepool_obj.taints),
184-
index : node_index
185-
}
186-
}
187-
]...)
188-
189-
agent_nodes = merge([
190-
for pool_index, nodepool_obj in var.agent_nodepools : {
191-
for node_index in range(nodepool_obj.count) :
192-
format("%s-%s-%s", pool_index, node_index, nodepool_obj.name) => {
193-
nodepool_name : nodepool_obj.name,
194-
server_type : nodepool_obj.server_type,
195-
location : nodepool_obj.location,
196-
labels : concat(local.default_agent_labels, nodepool_obj.labels),
197-
taints : nodepool_obj.taints,
198-
index : node_index
199-
}
200-
}
201-
]...)
202-
203-
# The main network cidr that all subnets will be created upon
204-
network_ipv4_cidr = "10.0.0.0/8"
205-
206-
# The first two subnets are respectively the default subnet 10.0.0.0/16 use for potientially anything and 10.1.0.0/16 used for control plane nodes.
207-
# the rest of the subnets are for agent nodes in each nodepools.
208-
network_ipv4_subnets = [for index in range(256) : cidrsubnet(local.network_ipv4_cidr, 8, index)]
209-
210-
# disable k3s extras
211-
disable_extras = concat(["local-storage"], local.is_single_node_cluster ? [] : ["servicelb"], var.traefik_enabled ? [] : ["traefik"], var.metrics_server_enabled ? [] : ["metrics-server"])
212-
213-
# Default k3s node labels
214-
default_agent_labels = concat([], var.automatically_upgrade_k3s ? ["k3s_upgrade=true"] : [])
215-
default_control_plane_labels = concat([], var.automatically_upgrade_k3s ? ["k3s_upgrade=true"] : [])
216-
217-
allow_scheduling_on_control_plane = local.is_single_node_cluster ? true : var.allow_scheduling_on_control_plane
218-
219-
# Default k3s node taints
220-
default_control_plane_taints = concat([], local.allow_scheduling_on_control_plane ? [] : ["node-role.kubernetes.io/master:NoSchedule"])
221221
}

terraform.tfvars.example

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ network_region = "eu-central" # change to `us-east` if location is ash
3333
# Also, before decreasing the count of any nodepools to 0, it's essential to drain and cordon the nodes in question. Otherwise, it will leave your cluster in a bad state.
3434

3535
# Before initializing the cluster, you can change all parameters and add or remove any nodepools. You need at least one nodepool of each kind, control plane, and agent.
36-
# The nodepool names are entirely arbitrary, you can choose whatever you want, but no special characters or underscore; only alphanumeric characters and dashes are allowed.
36+
# The nodepool names are entirely arbitrary, you can choose whatever you want, but no special characters or underscore, and they must be unique; only alphanumeric characters and dashes are allowed.
3737

3838
# If you want to have a single node cluster, have one control plane nodepools with a count of 1, and one agent nodepool with a count of 0.
3939

@@ -108,11 +108,13 @@ load_balancer_location = "fsn1"
108108
# hetzner_csi_version = ""
109109

110110

111-
# If you want to use letsencrypt with tls Challenge, the email address is used to send you certificates expiration notices
111+
# We give you the possibility to use letsencrypt directly with Traefik because it's an easy setup, however it's not optimal,
112+
# as the free version of Traefik causes a little bit of downtime when when the certificates get renewed. For proper SSL management,
113+
# we instead recommend you to use cert-manager, that you can easily deploy with helm; see https://cert-manager.io/.
112114
# traefik_acme_tls = true
113115
# traefik_acme_email = "mail@example.com"
114116

115-
# If you want to disable the Traefik ingress controller, you can. Default is "true".
117+
# If you want to disable the Traefik ingress controller, you can can set this to "false". Default is "true".
116118
# traefik_enabled = false
117119

118120
# If you want to disable the metric server, you can! Default is "true".
@@ -162,6 +164,8 @@ load_balancer_location = "fsn1"
162164

163165
# If you want to configure a different CNI for k3s, use this flag
164166
# possible values: flannel (Default), calico
167+
# Cilium or other would be easy to add, you can mirror how Calico was added. PRs are welcome!
168+
# CAVEATS: Calico is not supported for single node setups, because of the following issue https://github.com/k3s-io/klipper-lb/issues/6.
165169
# cni_plugin = "calico"
166170

167171
# If you want to disable the k3s default network policy controller, use this flag

0 commit comments

Comments
 (0)