Skip to content

Commit f744991

Browse files
committed
Add user_kustomizations-parameter and supporting modules, which can be used to define multiple Kustomization-sets that are run sequentially.
This allows to e.g. install CRD in one step, wait for their deployment and then proceed with the next set.
1 parent ee1b6ba commit f744991

File tree

16 files changed

+540
-116
lines changed

16 files changed

+540
-116
lines changed

MIGRATION.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Migration advice when updating the module
2+
3+
# 2.18.3 -> 2.19.0
4+
5+
## User Kustomization
6+
The extra_kustomization-feature has been moved to a module so that multiple extra_kustomizations can be run in sequential steps.
7+
A new variable `user_kustomizations` is now in use, which contains the previous extra_kustomize_* vars.
8+
9+
### Affects
10+
If you are using Helm charts from the `extra-manifests` folder or if you are using any of the following variables: `extra_kustomize_deployment_commands`, `extra_kustomize_parameters` or `extra_kustomize_folder`.
11+
12+
### Steps
13+
14+
1. Create a new variable `user_kustomizations`, see below and the kube.tf.example.
15+
16+
```
17+
user_kustomizations = {
18+
"1" = {
19+
source_folder = "extra-manifests" # Place here the source-folder defined previously in `var.extra_kustomize_folder`. If `var.extra_kustomize_folder` was previously undefined, leave as "extra-manifests".
20+
21+
kustomize_parameters = {} # Replace with contents of `var.extra_kustomize_parameters`. If `var.extra_kustomize_parameters` was previously undefined, remove the line or keep the default {}.
22+
23+
pre_commands = ""
24+
25+
post_commands = "" # Replace with contents of `var.extra_kustomize_deployment_commands`. If `var.extra_kustomize_deployment_commands` was previously undefined, remove the line or keep the default "".
26+
27+
}
28+
}
29+
```
30+
31+
2. After placing the variables, remove the variables `extra_kustomize_deployment_commands`, `extra_kustomize_parameters` and `extra_kustomize_folder` from kube.tf.

README.md

Lines changed: 132 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -318,12 +318,26 @@ See the [guide on adding robot servers](docs/add-robot-server.md)
318318

319319
If you need to install additional Helm charts or Kubernetes manifests that are not provided by default, you can easily do so by using [Kustomize](https://kustomize.io). This is done by creating one or more `extra-manifests/kustomization.yaml.tpl` files beside your `kube.tf`.
320320

321-
If you'd like to use a different folder name, you can configure it using the `extra_kustomize_folder` variable. By default, it is set to `extra-manifests`. This can be useful when working with multiple environments, allowing you to deploy different manifests for each one.
322-
323-
These files need to be valid `Kustomization` manifests, additionally supporting terraform templating! (The templating parameters can be passed via the `extra_kustomize_parameters` variable (via a map) to the module).
321+
These files need to be valid `Kustomization` manifests, additionally supporting terraform templating! (The templating parameters can be passed via the `user_kustomizations` variable (via a map) to the module).
324322

325323
All files in the `extra-manifests` directory and its subdirectories including the rendered versions of the `*.yaml.tpl` will be applied to k3s with `kubectl apply -k` (which will be executed after and independently of the basic cluster configuration).
326324

325+
If you'd like to use a different folder name, specify the template parameters or apply the kustomizations in multiple steps due to CRD installation etc, you can override the values using `user_kustomizations`-variable, see below:
326+
327+
Example of using user_kustomizations in `kube.tf`:
328+
```
329+
user_kustomizations = {
330+
"1" = {
331+
source_folder = "extra-manifests-pre"
332+
},
333+
"2" = {
334+
source_folder = "extra-manifests"
335+
kustomize_parameters = {key: "LowSecretKey"}
336+
post_commands = "kubectl wait --for=condition=Available deployment --all -A --timeout=120s || true"
337+
}
338+
}
339+
```
340+
327341
See a working example in [examples/kustomization_user_deploy](https://github.com/kube-hetzner/terraform-hcloud-kube-hetzner/tree/master/examples/kustomization_user_deploy).
328342

329343
_You can use the above to pass all kinds of Kubernetes YAML configs, including HelmChart and/or HelmChartConfig definitions (see the previous section if you do not know what those are in the context of k3s)._
@@ -334,20 +348,126 @@ _That said, you can also use pure Terraform and import the kube-hetzner module a
334348

335349
<details>
336350

337-
<summary>Custom post-install actions</summary>
351+
<summary>Adding applications with Helm, custom pre- and post-install actions</summary>
338352

339353
After the initial bootstrapping of your Kubernetes cluster, you might want to deploy applications using the same terraform mechanism. For many scenarios it is sufficient to create a `kustomization.yaml.tpl` file (see [Adding Extras](#adding-extras)). All applied kustomizations will be applied at once by executing a single `kubectl apply -k` command.
340354

341-
However, some applications that e.g. provide custom CRDs (e.g. [ArgoCD](https://argoproj.github.io/cd/)) need a different deployment strategy: one has to deploy CRDs first, then wait for the deployment, before being able to install the actual application. In the ArgoCD case, not waiting for the CRD setup to finish will cause failures. Therefore, an additional mechanism is available to support these kind of deployments. Specify `extra_kustomize_deployment_commands` in your `kube.tf` file containing a series of commands to be executed, after the `Kustomization` step finished:
355+
However, some applications that e.g. provide custom CRDs (e.g. [ArgoCD](https://argoproj.github.io/cd/)) need a different deployment strategy: one has to deploy CRDs first, then wait for the deployment, before being able to install the actual application. In the ArgoCD case, not waiting for the CRD setup to finish will cause failures.
342356

343-
```tf
344-
extra_kustomize_deployment_commands = <<-EOT
345-
kubectl -n argocd wait --for condition=established --timeout=120s crd/appprojects.argoproj.io
346-
kubectl -n argocd wait --for condition=established --timeout=120s crd/applications.argoproj.io
347-
kubectl apply -f /var/user_kustomize/argocd-projects.yaml
348-
kubectl apply -f /var/user_kustomize/argocd-application-argocd.yaml
357+
To support these scenarios, you can use the `user_kustomizations` variable in your `kube.tf`. This allows you to define multiple "sets" of kustomizations that are applied sequentially. Each set can have its own `source_folder`, `kustomize_parameters`, and `pre_commands`/`post_commands` for running scripts before or after the `kubectl apply -k`.
358+
359+
### Example: external-secrets repo and Helm
360+
You can install Helm repos and CRDs before the main Kustomization scripts by adding the Helm charts a different folder, e.g. `extra-manifests-preinstall` and specifying the folder in `user_kustomizations`-settings.
361+
362+
For example, to add `external-secrets` you can first create the CRDs:
363+
```yaml
364+
# extra-manifests-1/eso-crd.yaml.tpl
365+
apiVersion: helm.cattle.io/v1
366+
kind: HelmChart
367+
metadata:
368+
name: external-secrets
369+
namespace: kube-system
370+
spec:
371+
chart: external-secrets
372+
repo: https://charts.external-secrets.io
373+
targetNamespace: external-secrets
374+
createNamespace: true
375+
```
376+
```yaml
377+
# extra-manifests-1/kustomization.yaml.tpl
378+
apiVersion: kustomize.config.k8s.io/v1beta1
379+
kind: Kustomization
380+
381+
resources:
382+
- eso-crd.yaml
383+
```
384+
385+
Then create the objects that use the previously created CRDs:
386+
387+
```yaml
388+
# extra-manifests-2/eso-secrets.yaml.tpl
389+
apiVersion: v1
390+
kind: Secret
391+
metadata:
392+
name: vault-creds
393+
namespace: external-secrets
394+
type: Opaque
395+
data:
396+
username: ${base64encode(eso_access_username)}
397+
password: ${base64encode(eso_access_password)}
398+
399+
---
400+
apiVersion: external-secrets.io/v1
401+
kind: SecretStore
402+
metadata:
403+
name: vault-sm-store
404+
namespace: external-secrets
405+
spec:
406+
provider:
407+
aws:
408+
service: SecretsManager
409+
region: us-east-1
410+
411+
auth:
412+
secretRef:
413+
accessKeyIDSecretRef:
414+
name: vault-creds
415+
key: username
416+
namespace: external-secrets
417+
secretAccessKeySecretRef:
418+
name: vault-creds
419+
key: password
420+
namespace: external-secrets
421+
422+
```
423+
```yaml
424+
# extra-manifests-2/kustomization.yaml.tpl
425+
apiVersion: kustomize.config.k8s.io/v1beta1
426+
kind: Kustomization
427+
428+
resources:
429+
- eso-secrets.yaml
430+
```
431+
432+
In `kube.tf`, specify the folders in `user_kustomizations`.
433+
434+
```
435+
# kube.tf
436+
...
437+
user_kustomizations = {
438+
"1" = {
439+
source_folder = "extra-manifests-1"
440+
post_commands = "kubectl -n external-secrets wait --for=condition=Available deployment --all --timeout=120s || true"
441+
},
442+
"2" = {
443+
source_folder = "extra-manifests-2"
444+
kustomize_parameters = {
445+
eso_access_username = "..."
446+
eso_access_password = "..."
447+
}
448+
},
349449
...
350-
EOT
450+
}
451+
```
452+
453+
### Example: ArgoCD with Post-install actions
454+
455+
See examples from `examples/kustomization_user_deploy/helm-chart`, place the chart-files along with Kustomization.yaml.tpl into folder `argocd`.
456+
Then specify additional project-helms in `argocd-projects`.
457+
458+
```
459+
user_kustomizations = {
460+
"1" = {
461+
source_folder = "argocd"
462+
post_commands = <<-EOT
463+
kubectl -n argocd wait --for condition=established --timeout=120s crd/appprojects.argoproj.io
464+
kubectl -n argocd wait --for condition=established --timeout=120s crd/applications.argoproj.io
465+
EOT
466+
},
467+
"2" = {
468+
source_folder = "argocd-projects"
469+
}
470+
}
351471
```
352472
353473
</details>

docs/llms.md

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2201,33 +2201,34 @@ Locked and loaded! Let's continue the detailed exploration.
22012201
**Section 2.21: Kustomize and Post-Deployment Operations**
22022202

22032203
```terraform
2204-
# Extra commands to be executed after the `kubectl apply -k` (useful for post-install actions, e.g. wait for CRD, apply additional manifests, etc.).
2205-
# extra_kustomize_deployment_commands=""
2204+
# You can add user kustomizations to be deployed in sequence by setting the `user_kustomizations` variable.
2205+
# The Kustomization "sets" are run in sequential order (by numeric key) so that you can for example install a CRD and wait for it to be deployed.
2206+
#
2207+
# Properties of each value:
2208+
# - source_folder: Sets the source folder for *.yaml.tpl and Kustomization.yaml.tpl
2209+
# - kustomize_parameters: Key-value map for passing variables into Kustomization. Applies only to the Kustomization-set in the object, but to all files defined in the source_folder of the "set". Defaults to {}.
2210+
# - pre_commands: Commands to be executed before applying the Kustomization ("kubectl apply -k"). Defaults to "".
2211+
# - post_commands: Commands to be executed after applying the Kustomization ("kubectl apply -k"). You can use it to wait for CRD deployment etc. Defaults to "".
2212+
# -- An example to wait for deployments in all namespaces: `kubectl wait --for=condition=Available deployment --all -A --timeout=120s || true` (The `|| true` is necessary to prevent the script from exiting on a timeout if you want the sequence to continue.)
2213+
# -- It is recommended to use more specific `kubectl wait` commands depending on the case, for example filtering for a certain deployment or pod.
2214+
# -- You can pass full bash-compatible scripts into the `post_commands`-variable with EOT
2215+
#
2216+
# An example:
2217+
# user_kustomizations = {
2218+
# "1" = {
2219+
# source_folder = "extra-manifests"
2220+
# kustomize_parameters = { myvar = "myvalue" }
2221+
# pre_commands = ""
2222+
# post_commands = "kubectl wait --for=condition=Available deployment --all -A --timeout=120s || true"
2223+
# }
2224+
# }
22062225
```
22072226

2208-
* **`extra_kustomize_deployment_commands` (String or List of Strings, Optional):**
2209-
* **Purpose:** Allows you to specify shell commands that will be executed *after* the module has run its main Kustomize deployment (which applies manifests for core components like CCM, CSI, Ingress, etc., based on your selections).
2210-
* **Mechanism:** The module likely uses a `local-exec` or `remote-exec` provisioner (if commands need to run on a node) to execute these. If they are `kubectl` commands, they'd run from where Terraform is executed, using the generated kubeconfig.
2227+
* **`user_kustomizations` (Map of Objects, Optional):**
2228+
* **Purpose:** Allows you to specify Kustomization sets that are run sequentially, with each set containing its own source_folder, pre_commands, post_commands and kustomize_parameters
22112229
* **Use Cases:**
2212-
* **Waiting for CRDs:** Some applications deployed via Helm or Kustomize install CustomResourceDefinitions (CRDs) first, and then CustomResources (CRs) that depend on those CRDs. There can be a race condition if the CRs are applied before the CRDs are fully registered. You could add a command here to wait for CRDs to become available (e.g., `kubectl wait --for condition=established crd/mycrd.example.com --timeout=120s`).
2213-
* Applying additional Kubernetes manifests that depend on the core setup.
2214-
* Running post-install scripts or triggering initial application setup jobs.
2215-
* **Format:** Can be a single string with commands separated by `&&` or `\n`, or a list of individual command strings.
2216-
2217-
```terraform
2218-
# Extra values that will be passed to the `extra-manifests/kustomization.yaml.tpl` if its present.
2219-
# extra_kustomize_parameters={}
2220-
```
2221-
2222-
* **`extra_kustomize_parameters` (Map of Strings, Optional):**
2223-
* **Purpose:** If you are using the module's "extra manifests" feature (where you can provide your own Kustomize setup in an `extra-manifests` directory), this map allows you to pass key-value parameters into a `kustomization.yaml.tpl` template file within that directory.
2224-
* **Mechanism:** The module would process `extra-manifests/kustomization.yaml.tpl` as a template, substituting placeholders with values from this map, and then run `kustomize build` on the result.
2225-
* **Use Case:** Parameterizing your custom Kustomize deployments based on Terraform inputs or computed values from the `kube-hetzner` module (e.g., passing in the cluster name, node IPs, etc., to your custom manifests).
2226-
* **Reference:** The comment points to examples in the module's repository for how to use this feature.
2227-
2228-
```terraform
2229-
# See working examples for extra manifests or a HelmChart in examples/kustomization_user_deploy/README.md
2230-
```
2230+
* Some applications deployed via Helm or Kustomize install CustomResourceDefinitions (CRDs) first, and then CustomResources (CRs) that depend on those CRDs. There can be a race condition if the CRs are applied before the CRDs are fully registered. You could add a command here to wait for CRDs to become available (e.g., `kubectl wait --for condition=established crd/mycrd.example.com --timeout=120s`).
2231+
* The `user_kustomizations`-map allows you to define steps of install where e.g. the first step installs CRDs, checks for their proper existence and then second step that install further CRs.
22312232

22322233
* **Documentation Pointer:** This directs users to example usage of the "extra manifests" feature, which is crucial for extending the module's capabilities with custom deployments.
22332234

examples/kustomization_user_deploy/README.md

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ Kube-Hetzner allows you to provide user-defined resources after the initial setu
44

55
When you execute terraform apply, the manifests in the extra-manifests directory, including the rendered versions of the `*.yaml.tpl` files, will be automatically deployed to the cluster.
66

7+
Note: If you would like to use a different folder, define the `user_kustomizations` in kube.tf.
8+
79
## Examples
810

911
Here are some examples of common use cases for deploying additional resources:
@@ -12,14 +14,18 @@ Here are some examples of common use cases for deploying additional resources:
1214
1315
### Deploying Simple Resources
1416

15-
The easiest use case is to deploy simple resources to the cluster. Since the Kustomize resources are [Terraform template](https://registry.terraform.io/providers/hashicorp/template/latest/docs/data-sources/file) files, they can make use of parameters provided in the `extra_kustomize_parameters` map of the `kube.tf` file.
17+
The easiest use case is to deploy simple resources to the cluster. Since the Kustomize resources are [Terraform template](https://registry.terraform.io/providers/hashicorp/template/latest/docs/data-sources/file) files, they can make use of parameters provided in the `kustomize_parameters` map of the `user_kustomizations`.
1618

1719
#### `kube.tf`
1820

1921
```
2022
...
21-
extra_kustomize_parameters = {
22-
my_config_key = "somestring"
23+
user_kustomizations = {
24+
...
25+
kustomize_parameters = {
26+
my_config_key = "somestring"
27+
}
28+
...
2329
}
2430
...
2531
```

examples/kustomization_user_deploy/letsencrypt/kustomization.yaml.tpl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,3 @@ kind: Kustomization
33

44
resources:
55
- letsencrypt.yaml
6-

kube.tf.example

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -961,12 +961,27 @@ module "kube-hetzner" {
961961
# More information about the registration can be found here https://rancher.com/docs/rancher/v2.6/en/cluster-provisioning/registered-clusters/
962962
# rancher_registration_manifest_url = "https://rancher.xyz.dev/v3/import/xxxxxxxxxxxxxxxxxxYYYYYYYYYYYYYYYYYYYzzzzzzzzzzzzzzzzzzzzz.yaml"
963963

964-
# Extra commands to be executed after the `kubectl apply -k` (useful for post-install actions, e.g. wait for CRD, apply additional manifests, etc.).
965-
# extra_kustomize_deployment_commands=""
966-
967-
# Extra values that will be passed to the `extra-manifests/kustomization.yaml.tpl` if its present.
968-
# extra_kustomize_parameters={}
969-
964+
# You can add user kustomizations to be deployed in sequence by setting the `user_kustomizations` variable.
965+
# The Kustomization "sets" are run in sequential order (by numeric key) so that you can for example install a CRD and wait for it to be deployed.
966+
#
967+
# Properties of each value:
968+
# - source_folder: Sets the source folder for *.yaml.tpl and Kustomization.yaml.tpl
969+
# - kustomize_parameters: Key-value map for passing variables into Kustomization. Applies only to the Kustomization-set in the object, but to all files defined in the source_folder of the "set". Defaults to {}.
970+
# - pre_commands: Commands to be executed before applying the Kustomization ("kubectl apply -k"). Defaults to "".
971+
# - post_commands: Commands to be executed after applying the Kustomization ("kubectl apply -k"). You can use it to wait for CRD deployment etc. Defaults to "".
972+
# -- An example to wait for deployments in all namespaces: `kubectl wait --for=condition=Available deployment --all -A --timeout=120s || true` (The `|| true` is necessary to prevent the script from exiting on a timeout if you want the sequence to continue.)
973+
# -- It is recommended to use more specific `kubectl wait` commands depending on the case, for example filtering for a certain deployment or pod.
974+
# -- You can pass full bash-compatible scripts into the `post_commands`-variable with EOT
975+
#
976+
# An example:
977+
# user_kustomizations = {
978+
# "1" = {
979+
# source_folder = "extra-manifests"
980+
# kustomize_parameters = { myvar = "myvalue" }
981+
# pre_commands = ""
982+
# post_commands = "kubectl wait --for=condition=Available deployment --all -A --timeout=120s || true"
983+
# }
984+
# }
970985
# See working examples for extra manifests or a HelmChart in examples/kustomization_user_deploy/README.md
971986

972987
# It is best practice to turn this off, but for backwards compatibility it is set to "true" by default.

0 commit comments

Comments
 (0)