diff --git a/modules/kubernetes/.terraform.lock.hcl b/modules/kubernetes/.terraform.lock.hcl
index 568b4d9..41e3a68 100644
--- a/modules/kubernetes/.terraform.lock.hcl
+++ b/modules/kubernetes/.terraform.lock.hcl
@@ -20,3 +20,46 @@ provider "registry.terraform.io/hashicorp/kubernetes" {
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
]
}
+
+provider "registry.terraform.io/hashicorp/time" {
+ version = "0.11.2"
+ constraints = ">= 0.11.2, < 1.0.0"
+ hashes = [
+ "h1:bC4b7n4g30ciIn5w6b66mXSTIo2CH6XQbp+gBdDvlYs=",
+ "zh:02588b5b8ba5d31e86d93edc93b306bcbf47c789f576769245968cc157a9e8c5",
+ "zh:088a30c23796133678d1d6614da5cf5544430570408a17062288b58c0bd67ac8",
+ "zh:0df5faa072d67616154d38021934d8a8a316533429a3f582df3b4b48c836cf89",
+ "zh:12edeeaef96c47f694bd1ba7ead6ccdb96028b25df352eea4bc5e40de7a59177",
+ "zh:1e859504a656a6e988f07b908e6ffe946b28bfb56889417c0a07ea9605a3b7b0",
+ "zh:64a6ae0320d4956c4fdb05629cfcebd03bcbd2206e2d733f2f18e4a97f4d5c7c",
+ "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
+ "zh:924d137959193bf7aee6ebf241fbb9aec46d6eef828c5cf8d3c588770acae7b2",
+ "zh:b3cc76281a4faa9c2293a2460fc6962f6539e900994053f85185304887dddab8",
+ "zh:cbb40c791d4a1cdba56cffa43a9c0ed8e69930d49aa6bd931546b18c36e3b720",
+ "zh:d227d43594f8cb3d24f1fdd71382f14502cbe2a6deaddbc74242656bb5b38daf",
+ "zh:d4840641c46176bb9d70ba3aff09de749282136c779996b546c81e5ff701bbf6",
+ ]
+}
+
+provider "registry.terraform.io/integrations/github" {
+ version = "6.2.2"
+ constraints = ">= 6.2.2, < 7.0.0"
+ hashes = [
+ "h1:3gbrNGsK0dQ5zpN0qeHm3uNdWJl+f760+VtV2GJZ8Vg=",
+ "zh:43d7e5f1e11d67e38ca717016d209d6d9a6fa03321b489f91984351bfb143b69",
+ "zh:46e788395034b410bf59dfa43eb748a3d81ecfd23fc442349990fd7d92bd856a",
+ "zh:5234b7d5c5817ff7ebec29756050708372a071a701e2c8236e714a0bd29ef160",
+ "zh:74c485a241cc8e8cb99f988d38116fb14e51de896761fc9ca35a34ca5c999a7e",
+ "zh:7606789521c50937913ea13f851150828b5f9b8804ba80c5b2538c0b019339d8",
+ "zh:760fb0e74590459689c7159456b6e76f165634f7d0f89f5572d56b57d387f645",
+ "zh:7979d9085d809bb7d0db2c67e6c3443d1c18d12e51b72220dcb4cc5e883cd64a",
+ "zh:8bed25d8199bf8b2e7ccf67edc1a4a2fc041bd490b2c11565c669b80be43896c",
+ "zh:9ff82a6279fb7ae0cd9e44f1e73b64dd2aeca43d4d3096f3f2866b1ebbcb9431",
+ "zh:a886055ecd63ccb9b880e3c3301c0eca9acb108580d12519617554ae2be9a393",
+ "zh:c1f20386704919c7964a95daffcb29f494efb061abc28469840df4532833cecf",
+ "zh:cb6e9c4e33d6a57770073867e174c09c0eed401ee70473a688d20cb1cf0394f7",
+ "zh:f89ca130cc90b87dc25d036fe8f8cadb6fb53dc33368a032c5cee6275f3bcddc",
+ "zh:f94a2d1174091f04ed361192cdda9503baa3d161849d4f218c55a96bfb1ea33d",
+ "zh:fbd1fee2c9df3aa19cf8851ce134dea6e45ea01cb85695c1726670c285797e25",
+ ]
+}
diff --git a/modules/kubernetes/README.md b/modules/kubernetes/README.md
index 1826400..292f8f4 100644
--- a/modules/kubernetes/README.md
+++ b/modules/kubernetes/README.md
@@ -5,12 +5,18 @@
| Name | Version |
|------|---------|
-| [terraform](#requirement\_terraform) | >= 1.0.0 |
+| [terraform](#requirement\_terraform) | >= 1.8.0 |
+| [github](#requirement\_github) | >= 6.2.2, < 7.0.0 |
| [kubernetes](#requirement\_kubernetes) | >= 2.31.0, < 3.0.0 |
+| [time](#requirement\_time) | >= 0.11.2, < 1.0.0 |
## Providers
-No providers.
+| Name | Version |
+|------|---------|
+| [github](#provider\_github) | 6.2.2 |
+| [kubernetes](#provider\_kubernetes) | 2.31.0 |
+| [time](#provider\_time) | 0.11.2 |
## Modules
@@ -18,12 +24,23 @@ No modules.
## Resources
-No resources.
+| Name | Type |
+|------|------|
+| [kubernetes_annotations.restarts](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/annotations) | resource |
+| [kubernetes_manifest.csi_driver](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/manifest) | resource |
+| [kubernetes_secret_v1.hcloud_token](https://registry.terraform.io/providers/hashicorp/kubernetes/latest/docs/resources/secret_v1) | resource |
+| [time_static.restarted_at](https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/static) | resource |
+| [github_release.csi_driver](https://registry.terraform.io/providers/integrations/github/latest/docs/data-sources/release) | data source |
+| [github_repository_file.csi_driver](https://registry.terraform.io/providers/integrations/github/latest/docs/data-sources/repository_file) | data source |
## Inputs
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
+| [hcloud\_token](#input\_hcloud\_token) | Hetzner API token | `string` | n/a | yes |
+| [hetzner\_csi\_driver\_owner](#input\_hetzner\_csi\_driver\_owner) | GitHub owner to get the CSI driver from | `string` | `"hetznercloud"` | no |
+| [hetzner\_csi\_driver\_repo](#input\_hetzner\_csi\_driver\_repo) | GitHub repo to get the CSI driver from | `string` | `"csi-driver"` | no |
+| [hetzner\_csi\_driver\_version](#input\_hetzner\_csi\_driver\_version) | Tag of the CSI driver to use - provide the tag name or latest | `string` | `"latest"` | no |
| [kube\_context](#input\_kube\_context) | Kubernetes context to use | `string` | `"default"` | no |
| [kubeconfig](#input\_kubeconfig) | Kubeconfig for the cluster | `string` | n/a | yes |
diff --git a/modules/kubernetes/csi.tf b/modules/kubernetes/csi.tf
new file mode 100644
index 0000000..6a365e7
--- /dev/null
+++ b/modules/kubernetes/csi.tf
@@ -0,0 +1,77 @@
+# Copyright 2024 Simon Emms
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+data "github_release" "csi_driver" {
+ repository = var.hetzner_csi_driver_repo
+ owner = var.hetzner_csi_driver_owner
+
+ retrieve_by = var.hetzner_csi_driver_version == "latest" ? var.hetzner_csi_driver_version : "tag"
+ release_tag = var.hetzner_csi_driver_version != "latest" ? var.hetzner_csi_driver_version : null
+}
+
+data "github_repository_file" "csi_driver" {
+ repository = "${var.hetzner_csi_driver_owner}/${var.hetzner_csi_driver_repo}"
+ branch = data.github_release.csi_driver.release_tag
+ file = "deploy/kubernetes/hcloud-csi.yml"
+}
+
+// This secret is required by the Hetzner CSI to create cloud resources
+resource "kubernetes_secret_v1" "hcloud_token" {
+ metadata {
+ name = "hcloud"
+ namespace = "kube-system"
+ }
+
+ data = {
+ token = var.hcloud_token
+ }
+}
+
+resource "kubernetes_manifest" "csi_driver" {
+ for_each = {
+ for m in provider::kubernetes::manifest_decode_multi(data.github_repository_file.csi_driver.content) :
+ "${m.apiVersion}.${m.kind}.${m.metadata.name}" => m
+ }
+ manifest = each.value
+
+ // The hcloud-csi-controller deployment has 5 containers
+ computed_fields = [
+ "spec.template.spec.containers[0].resources",
+ "spec.template.spec.containers[1].resources",
+ "spec.template.spec.containers[2].resources",
+ "spec.template.spec.containers[3].resources",
+ "spec.template.spec.containers[4].resources",
+ ]
+
+ depends_on = [kubernetes_secret_v1.hcloud_token, kubernetes_annotations.restarts]
+}
+
+// Restart the core-dns pods as the CSI controller may be in a failed state
+// @link https://github.com/hetznercloud/csi-driver/issues/465#issuecomment-1649216197
+resource "time_static" "restarted_at" {}
+
+resource "kubernetes_annotations" "restarts" {
+ // The order is important
+ for_each = toset(["coredns"])
+
+ api_version = "apps/v1"
+ kind = "Deployment"
+ metadata {
+ name = each.key
+ namespace = "kube-system"
+ }
+ template_annotations = {
+ "kubectl.kubernetes.io/restartedAt" = time_static.restarted_at.rfc3339
+ }
+}
diff --git a/modules/kubernetes/terraform.tf b/modules/kubernetes/terraform.tf
index 3e68222..2fc777d 100644
--- a/modules/kubernetes/terraform.tf
+++ b/modules/kubernetes/terraform.tf
@@ -13,12 +13,20 @@
# limitations under the License.
terraform {
- required_version = ">= 1.0.0"
+ required_version = ">= 1.8.0"
required_providers {
+ github = {
+ source = "integrations/github"
+ version = ">= 6.2.2, < 7.0.0"
+ }
kubernetes = {
source = "hashicorp/kubernetes"
version = ">= 2.31.0, < 3.0.0"
}
+ time = {
+ source = "hashicorp/time"
+ version = ">= 0.11.2, < 1.0.0"
+ }
}
}
diff --git a/modules/kubernetes/variables.tf b/modules/kubernetes/variables.tf
index c8dcbe5..65d3315 100644
--- a/modules/kubernetes/variables.tf
+++ b/modules/kubernetes/variables.tf
@@ -12,6 +12,30 @@
# See the License for the specific language governing permissions and
# limitations under the License.
+variable "hcloud_token" {
+ type = string
+ description = "Hetzner API token"
+ sensitive = true
+}
+
+variable "hetzner_csi_driver_owner" {
+ type = string
+ description = "GitHub owner to get the CSI driver from"
+ default = "hetznercloud"
+}
+
+variable "hetzner_csi_driver_repo" {
+ type = string
+ description = "GitHub repo to get the CSI driver from"
+ default = "csi-driver"
+}
+
+variable "hetzner_csi_driver_version" {
+ type = string
+ description = "Tag of the CSI driver to use - provide the tag name or latest"
+ default = "latest"
+}
+
variable "kubeconfig" {
type = string
description = "Kubeconfig for the cluster"
diff --git a/stacks/dev/kubernetes/.terraform.lock.hcl b/stacks/dev/kubernetes/.terraform.lock.hcl
index 568b4d9..41e3a68 100644
--- a/stacks/dev/kubernetes/.terraform.lock.hcl
+++ b/stacks/dev/kubernetes/.terraform.lock.hcl
@@ -20,3 +20,46 @@ provider "registry.terraform.io/hashicorp/kubernetes" {
"zh:f569b65999264a9416862bca5cd2a6177d94ccb0424f3a4ef424428912b9cb3c",
]
}
+
+provider "registry.terraform.io/hashicorp/time" {
+ version = "0.11.2"
+ constraints = ">= 0.11.2, < 1.0.0"
+ hashes = [
+ "h1:bC4b7n4g30ciIn5w6b66mXSTIo2CH6XQbp+gBdDvlYs=",
+ "zh:02588b5b8ba5d31e86d93edc93b306bcbf47c789f576769245968cc157a9e8c5",
+ "zh:088a30c23796133678d1d6614da5cf5544430570408a17062288b58c0bd67ac8",
+ "zh:0df5faa072d67616154d38021934d8a8a316533429a3f582df3b4b48c836cf89",
+ "zh:12edeeaef96c47f694bd1ba7ead6ccdb96028b25df352eea4bc5e40de7a59177",
+ "zh:1e859504a656a6e988f07b908e6ffe946b28bfb56889417c0a07ea9605a3b7b0",
+ "zh:64a6ae0320d4956c4fdb05629cfcebd03bcbd2206e2d733f2f18e4a97f4d5c7c",
+ "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3",
+ "zh:924d137959193bf7aee6ebf241fbb9aec46d6eef828c5cf8d3c588770acae7b2",
+ "zh:b3cc76281a4faa9c2293a2460fc6962f6539e900994053f85185304887dddab8",
+ "zh:cbb40c791d4a1cdba56cffa43a9c0ed8e69930d49aa6bd931546b18c36e3b720",
+ "zh:d227d43594f8cb3d24f1fdd71382f14502cbe2a6deaddbc74242656bb5b38daf",
+ "zh:d4840641c46176bb9d70ba3aff09de749282136c779996b546c81e5ff701bbf6",
+ ]
+}
+
+provider "registry.terraform.io/integrations/github" {
+ version = "6.2.2"
+ constraints = ">= 6.2.2, < 7.0.0"
+ hashes = [
+ "h1:3gbrNGsK0dQ5zpN0qeHm3uNdWJl+f760+VtV2GJZ8Vg=",
+ "zh:43d7e5f1e11d67e38ca717016d209d6d9a6fa03321b489f91984351bfb143b69",
+ "zh:46e788395034b410bf59dfa43eb748a3d81ecfd23fc442349990fd7d92bd856a",
+ "zh:5234b7d5c5817ff7ebec29756050708372a071a701e2c8236e714a0bd29ef160",
+ "zh:74c485a241cc8e8cb99f988d38116fb14e51de896761fc9ca35a34ca5c999a7e",
+ "zh:7606789521c50937913ea13f851150828b5f9b8804ba80c5b2538c0b019339d8",
+ "zh:760fb0e74590459689c7159456b6e76f165634f7d0f89f5572d56b57d387f645",
+ "zh:7979d9085d809bb7d0db2c67e6c3443d1c18d12e51b72220dcb4cc5e883cd64a",
+ "zh:8bed25d8199bf8b2e7ccf67edc1a4a2fc041bd490b2c11565c669b80be43896c",
+ "zh:9ff82a6279fb7ae0cd9e44f1e73b64dd2aeca43d4d3096f3f2866b1ebbcb9431",
+ "zh:a886055ecd63ccb9b880e3c3301c0eca9acb108580d12519617554ae2be9a393",
+ "zh:c1f20386704919c7964a95daffcb29f494efb061abc28469840df4532833cecf",
+ "zh:cb6e9c4e33d6a57770073867e174c09c0eed401ee70473a688d20cb1cf0394f7",
+ "zh:f89ca130cc90b87dc25d036fe8f8cadb6fb53dc33368a032c5cee6275f3bcddc",
+ "zh:f94a2d1174091f04ed361192cdda9503baa3d161849d4f218c55a96bfb1ea33d",
+ "zh:fbd1fee2c9df3aa19cf8851ce134dea6e45ea01cb85695c1726670c285797e25",
+ ]
+}