diff --git a/deployment-examples/openstack-kubernetes/k3s-cluster/main.tf b/deployment-examples/openstack-kubernetes/k3s-cluster/main.tf index a9db2746..592cec85 100644 --- a/deployment-examples/openstack-kubernetes/k3s-cluster/main.tf +++ b/deployment-examples/openstack-kubernetes/k3s-cluster/main.tf @@ -1,5 +1,7 @@ module "openstack_cogstack_infra" { - source = "../../../terraform-modules/openstack-kubernetes-k3s" + source = "CogStack/kubernetes-k3s/openstack" + version = "0.1.0" + host_instances = [ { name = "cogstack-k3s", diff --git a/docs/docs/platform/deployment/reference/terraform/terraform-openstack-kubernetes-k3s.md b/docs/docs/platform/deployment/reference/terraform/terraform-openstack-kubernetes-k3s.md new file mode 100644 index 00000000..f2b0c968 --- /dev/null +++ b/docs/docs/platform/deployment/reference/terraform/terraform-openstack-kubernetes-k3s.md @@ -0,0 +1,21 @@ +# Terraform OpenStack Kubernetes K3s + +
+ +{{ cogstack_banner_logo() }} + +:simple-openstack:{ .tech-icon-openstack } :simple-kubernetes:{ .tech-icon-kubernetes } :simple-terraform:{ .tech-icon-terraform } + +
+ +This Terraform module provisions a Kubernetes cluster on OpenStack using [K3s](https://k3s.io/). It creates the VMs, installs K3s on them, sets up networking, and returns a kubeconfig so you can use the cluster with `kubectl`, Helm, and other Terraform Kubernetes providers. + +The module is published to the Terraform Registry: + +- [CogStack/kubernetes-k3s/openstack](https://registry.terraform.io/modules/CogStack/kubernetes-k3s/openstack/latest) + +Source code lives in this repository: + +- [terraform-modules/openstack-kubernetes-k3s](https://github.com/CogStack/cogstack-platform/tree/main/terraform-modules/openstack-kubernetes-k3s) + +For a full CogStack platform deployment that uses this module, see the [OpenStack Kubernetes K3s example](../../examples/openstack-kubernetes-k3s.md). diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index e525adf2..f0442274 100644 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -83,7 +83,10 @@ nav: - Azure Kubernetes AKS: platform/deployment/examples/azure-kubernetes-aks.md - OpenStack Kubernetes K3s: platform/deployment/examples/openstack-kubernetes-k3s.md - OpenStack Docker: platform/deployment/examples/openstack-docker.md - - Docker Compose: platform/deployment/reference/docker-compose/_index.md + - Reference: + - Docker Compose: platform/deployment/reference/docker-compose/_index.md + - Terraform: + - OpenStack Kubernetes K3s: platform/deployment/reference/terraform/terraform-openstack-kubernetes-k3s.md - Observability: - Overview: platform/observability/index.md diff --git a/terraform-modules/README.md b/terraform-modules/README.md index d8490246..4e11d377 100644 --- a/terraform-modules/README.md +++ b/terraform-modules/README.md @@ -1,4 +1,16 @@ -Reusable terraform modules for CogStack deployments. +Reusable terraform modules for CogStack deployments. These modules should not be limited to a specific deployment or contain secrets. +## Generating module docs + +Modules that use [terraform-docs](https://github.com/terraform-docs/terraform-docs) keep a `.terraform-docs.yml` and inject generated Requirements, Providers, Resources, Inputs, and Outputs between `` and `` in the module README. + +From the module directory: + +```bash +docker run --rm --volume "$(pwd):/terraform-docs" -u $(id -u) quay.io/terraform-docs/terraform-docs:0.24.0 markdown /terraform-docs +``` + +If that tag is missing for your architecture, use `quay.io/terraform-docs/terraform-docs:0.24.0-amd64` (or `-arm64`) instead. + diff --git a/terraform-modules/openstack-kubernetes-k3s/.terraform-docs.yml b/terraform-modules/openstack-kubernetes-k3s/.terraform-docs.yml new file mode 100644 index 00000000..fc451fc5 --- /dev/null +++ b/terraform-modules/openstack-kubernetes-k3s/.terraform-docs.yml @@ -0,0 +1,61 @@ +formatter: markdown table + +output: + file: README.md + mode: inject + +sort: + enabled: true + by: required + +settings: + anchor: true + color: true + default: true + description: true + escape: true + hide-empty: true + html: true + indent: 2 + lockfile: true + read-comments: true + required: true + sensitive: true + type: true + +content: |- + ## Example + + This example deploys a two node kubernetes cluster in Openstack with K3s. + + ```hcl + {{ include "examples/minimal/main.tf" }} + ``` + + {{ .Requirements }} + + {{ .Providers }} + + {{ .Modules }} + + {{ .Resources }} + + {{ .Inputs }} + + {{ .Outputs }} + + ## Existing Network and Floating IPs + + You can use this module with a custom OpenStack network by specifying the `network` variable with your own network name or network ID. + + Using a custom OpenStack network with your own subnet allows you to improve security by keeping most nodes private. This ensures worker nodes and other internal resources are not directly exposed, reducing security risks. Only the controller node needs a floating IP to be accessible in order to use the k8s api server (eg for kubectl to work from outside the network). Using floating ips will also have the advantage of being stable, so you can destroy/create VMs without having to update anywhere the IP address is referenced by reassigning the floating ip. + + To use this configuration, you will probably need to assign a floating IP to the controller node so that it is accessible. You can configure floating IP assignment per node using the `floating_ip` block within each entry in the `host_instances` variable. + + Please see this example for using this module with a custom network and floating IPs. + + ```hcl + {{ include "examples/floating-ips/main.tf" }} + ``` + + When using a non-default network, ensure the controller host has a floating IP so Terraform can access it for provisioning. diff --git a/terraform-modules/openstack-kubernetes-k3s/.terraform.lock.hcl b/terraform-modules/openstack-kubernetes-k3s/.terraform.lock.hcl deleted file mode 100644 index 6d5aed29..00000000 --- a/terraform-modules/openstack-kubernetes-k3s/.terraform.lock.hcl +++ /dev/null @@ -1,104 +0,0 @@ -# This file is maintained automatically by "terraform init". -# Manual edits may be lost in future updates. - -provider "registry.terraform.io/hashicorp/cloudinit" { - version = "2.4.1" - hashes = [ - "h1:TKuE7Sq6387hl4eBo0/Gur73M9IP7OM0soSr6IqXWr0=", - "zh:0290af752ce1617c9258e11ccac1787ff134c59f444197db759af65e6e4fed2e", - "zh:489e950720f129c51a3868575c8656e165cd58652c34cb5d2efd9f89057f46b4", - "zh:5688e28d20f3a4cfea7808d882824e75ebdd6b2cb305df126d13b04f7a874ba2", - "zh:59cf1a815c8f1316c7e05ffd34fd78a9bf6e1de4823f40b4951ef2e538b9d6d6", - "zh:637a27f88d25e549dd096936a4c1eac85cf2a6d1cc44cf592690b4158cd2f969", - "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:95c80caef31829666a71adc9deaf70010a1fa8a9bda8a742b469e218b49c6442", - "zh:a23fc664a6f53d432684b8b9745c209e0eb8df8ad8455d98180d97fe8626afbf", - "zh:b74fe251542d65137dbf0b4b8cc597fbb89f862776456179db05865c717646e6", - "zh:d15dfa0a50147cd34c6c8192990d3c880f38ab64db825da8a322301930aa10f9", - "zh:d1757d138f00e79b8ad3f53c07d9569de7b44b6343e40407faeaaf07b43382c3", - "zh:daac40bbcd0e3fc8fc6be6e57b746995ed40996d3bfd077db60f1ec32b7a205e", - "zh:f2dfc80edb573514ce98add5eb4c178fb5b041ba6a8e94d1098d28fa2b0988a5", - ] -} - -provider "registry.terraform.io/hashicorp/local" { - version = "2.9.1" - hashes = [ - "h1:qGLHCuYSus+uHNnoEL4SuJqOs5yrNOcB7gnuHoVqizo=", - "zh:25606c7a5e308144fb627f6e31611bb52ff72bb9ae2d27af39673ab1a6b3c1bf", - "zh:2568c4ef4dab31821f6f7040af0d1a2aa2b9455b8d9cc546598b791b8ada34cd", - "zh:25ac210f136042047975896e5e11fe6012425301c826d6b7ce22a49f96a1e0e8", - "zh:55d3a7bf01eced8e1f259b548020ef1221c5687e0fe6b5b30f81ad0b4121ff12", - "zh:6168d6934777b853c57815baa18a54101c604a6f1124ca47cd23d016c6f2f1e5", - "zh:63c0aa17c8373f761123376226debffd1f2259901ff259d4547c520def9a6787", - "zh:6d1f1572db6c85bd6d6b1b1deef247084e189816875f67e6bcc5d4736794e0a9", - "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:a8ea1c155bd5e0d695a28d3c0e2f542de8844e1791ea021f015a3f08e1c059e1", - "zh:ccd790f97269509ade0574ef63c955d3943cb1d812c59177bd85ce4c1d17ca0f", - "zh:dcfc17bb666e659a9daa9ff52fd8f6ec9ea519868726015e645955c372296332", - "zh:eb83abbfa7f52cba609b48cbb9a6a5cab07780a672b2020fc2ba190e699a2516", - "zh:eedffca70074ae153790fb23c4ace8d1637a60ceba4e3c42c8eaeda7c1f9d10f", - ] -} - -provider "registry.terraform.io/hashicorp/null" { - version = "3.3.2" - hashes = [ - "h1:IQ1qrkht1sC1nibUR+AJ3ulryyhVDHfCHZhoJi0sg2Y=", - "zh:10ec43b8b7b18d5639238c7fb9e111f6a4b038523dd66c7a426bf27b25fa4c08", - "zh:60beb9cc2ad5b871c710860cee75b42850cc6acd43db0d77cb5e00fda7288b55", - "zh:62538582d0a4a2f10ad8a8d9a6c3cd3f05af6c6d91c6641ffc78d4f0e8e69b27", - "zh:64a8f9ce7852d9efc5b464c12306c946366d59f5e2757def97969c9fd64bd1d6", - "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:92a374fb736a52f465283326d0a5bf4f495132eb99be209dfb4c75ec803fe8db", - "zh:98da9c42785d27a50f0604758bcb61a30f6278b9f2acd92bb3b2046e0e71916c", - "zh:b0f7896fae554729cdf4a24ac06359a050cff5817e6cd8597cba8a4ae01a7409", - "zh:bc8179ee35d67c72fb03012e7023b9f9816f033a7ec4109c001dd6d29752e812", - "zh:d23a598f713bfb6098bc003571d7de90b5a33b78f9be240488252fe5f3c2a60d", - "zh:d2855b922ea345dbd89ea287e4c6c4757e38bc0aaffeb2b79aa0b8004f9c53ff", - "zh:d3a60422bc6a2f9244d076c5222c07060c826ef91bdbaf4634cb752b86057473", - "zh:faa01928c25d2a6ecd9c7eb8b88134cb08de55a6b11ca6c703ac0092845344ba", - ] -} - -provider "registry.terraform.io/hashicorp/random" { - version = "3.9.1" - hashes = [ - "h1:g40qr7yDmIpaur4SsK5BcOda3HSo1RJ6zHVMqN4EJ+0=", - "zh:05f4734c1f0be840b711b3eff259ebc5fca436784c728955b1678078466f48d7", - "zh:0b91bf19371d012434eba1deeb6aab77158def9b39601dcbd94450b3974a2a26", - "zh:0ee6eacd47ec00183d55d726a4b6c4ce951a199f944bf22f1aa58392ebdfa7a2", - "zh:19388a4074b76a89a43a6c8328d7ae8ee2e7de3d346af51e80d3e6d3d12925f1", - "zh:23e74d48c5e2ac2e823fd527f49fee9db37d32a1990c9e3bf126ead697b843eb", - "zh:3cabf7fbd096c520064aae3aba61aba670af83ab91291a71fa1b1332929c2b7f", - "zh:5c0a3b8af0be60be4eca12ddee385cfa8babc1ec8e98cdf9de2f2274c73eabfa", - "zh:60b4f8a8ef18f52bf8e19215229dae408bee732825964092db7c989fd2de4097", - "zh:7359015acfedcbd6366f2329c854cf8d3c8ca5cd0faa89d2d37db358d6eba6c5", - "zh:78d5eefdd9e494defcb3c68d282b8f96630502cac21d1ea161f53cfe9bb483b3", - "zh:7b38758402f0e13a1071162da28994023cd2ac676e54af350c9ffd8dfa73fa7b", - "zh:7c7fbb8895eb75bb4de1f933e98553bd99c8d048c89a925ddba490aa5a67f7dc", - "zh:8c2b8c6a7ccdec16b73e2fb9f3700ea097f58c592571e4c5de60c93d2301732c", - ] -} - -provider "registry.terraform.io/terraform-provider-openstack/openstack" { - version = "3.0.0" - constraints = "~> 3.0.0" - hashes = [ - "h1:sxq+0vFl4SfV9dlut5liwaH4FejyNIf4ClAjRgowxv8=", - "zh:01718f229597b34ed430236a230a407dacd6289543556d33910e151462e8cb8a", - "zh:2424c5347d35fe0de778d1c40dbe8d9b1278309c4d65cce31709e6fcbec139df", - "zh:2a785f9efd6d8c979031803dd78411a583bc0d9a572ddf5fb9e539cbbfc1ce43", - "zh:8ab18c7eb1fd04b34be75fcecfc461888bd37ff017973f46745abeabd21b3fda", - "zh:98e805318292b58d9692bfe6d3d82e0db0f8044e588a38b239309221198aa92d", - "zh:9a99c9801f96dc69e7c76c5ddc0e2800b77a333becacae530d7a3acd18855347", - "zh:c5aa6690c094be211d2700d7ea44ffe937763e4dd566506c87eb99d6d8330b52", - "zh:d06fc3a148a49aab059a1f08ceadbfe1a5c82c7b80b960169987603dddaaaf58", - "zh:d079da24a9f2cc0d6fec9616e7ebe994245a3d98da629f012069c26d650edb05", - "zh:d1d2b63dba9045a4ff3869c65ddcaf2703d993254b58b2a0230d067f5c036de2", - "zh:d2b9d09c47e7eca08091da825cdf0982dc30089ee401888ce8704b79c7636e95", - "zh:dd6be78f98772bfc1ebf022fc36e5d68ef0f165f9e87476430d4e0dc3f1cc57f", - "zh:e7743c11dd0c83a5c1905f04ffd490b4471941218b4c841b760223fcf416affd", - "zh:f234aefac77f4e9a2b05877a00d322ee165009713d79a8d8e19039c6c6f7cf1b", - ] -} diff --git a/terraform-modules/openstack-kubernetes-k3s/README.md b/terraform-modules/openstack-kubernetes-k3s/README.md index dcbcc62c..bdc6af13 100644 --- a/terraform-modules/openstack-kubernetes-k3s/README.md +++ b/terraform-modules/openstack-kubernetes-k3s/README.md @@ -1,80 +1,149 @@ -# Cogstack Opesntack K3S Module +# Cogstack Openstack Kubernetes K3S Module Terraform Module for provisioning VMs on Openstack as a kubernetes cluster using K3s ## Features -- Create a multi node kuberentes cluster in Openstack with K3s -- Create VMs and initialise their setup using K3s install scripts +- Creates a multi node kuberentes cluster in Openstack with K3s +- VMs will initialise their setup using K3s install scripts - Setup Networking in Openstack to allow communications between expected services - Return a KUBECONFIG file for integration with kubernetes and helm providers in terraform -## Requirements +## Prerequisites - An Openstack Environment able to create Compute and Networking rules - An accessible Ubuntu image in the openstack environment + ## Example +This example deploys a two node kubernetes cluster in Openstack with K3s. + ```hcl module "openstack_kubernetes_cluster" { - source = "../../modules/openstack-kubernetes-k3s" - host_instances = [ - { name = "cogstack-k3s-server", is_controller = true, flavour = "m1.small" }, - { - name = "cogstack-k3s-node-2" - flavour = "m1.small" - volume_size = 20 - is_controller = false - }, - ] + source = "../.." + + ubuntu_image_name = "ubuntu-22.04" network = { name = "public" } - allowed_ingress_ips_cidr = "0.0.0.0/24" - ubuntu_image_name = "ubuntu-22.04" - ssh_key_pair = { - private_key_file = "~/.ssh/id_rsa", - public_key_file = "~/.ssh/id_rsa.pub", - } + host_instances = [ + { name = "controller", is_controller = true, flavour = "m1.small" }, + { name = "worker", flavour = "m1.small" }, + ] } ``` +## Requirements + +| Name | Version | +| ---- | ------- | +| [openstack](#requirement\_openstack) | ~> 3.0.0 | + +## Providers + +| Name | Version | +| ---- | ------- | +| [cloudinit](#provider\_cloudinit) | 2.4.1 | +| [local](#provider\_local) | 2.9.1 | +| [null](#provider\_null) | 3.3.2 | +| [openstack](#provider\_openstack) | 3.0.0 | +| [random](#provider\_random) | 3.9.1 | + + + +## Resources + +| Name | Type | +| ---- | ---- | +| [local_file.private_key](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/file) | resource | +| [local_file.public_key](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/file) | resource | +| [null_resource.copy_kubeconfig](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | +| [null_resource.kubernetes_nodes_provisioner](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | +| [null_resource.kubernetes_server_provisioner](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource | +| [openstack_compute_instance_v2.kubernetes_nodes](https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs/resources/compute_instance_v2) | resource | +| [openstack_compute_instance_v2.kubernetes_server](https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs/resources/compute_instance_v2) | resource | +| [openstack_compute_keypair_v2.compute_keypair](https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs/resources/compute_keypair_v2) | resource | +| [openstack_networking_floatingip_associate_v2.kubernetes_nodes_fip](https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs/resources/networking_floatingip_associate_v2) | resource | +| [openstack_networking_floatingip_associate_v2.kubernetes_server_fip](https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs/resources/networking_floatingip_associate_v2) | resource | +| [openstack_networking_secgroup_rule_v2.cogstack_apps_port_rules](https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs/resources/networking_secgroup_rule_v2) | resource | +| [openstack_networking_secgroup_v2.cogstack_apps_security_group](https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs/resources/networking_secgroup_v2) | resource | +| [random_id.server](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id) | resource | +| [random_password.k3s_token](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/password) | resource | +| [cloudinit_config.init_docker](https://registry.terraform.io/providers/hashicorp/cloudinit/latest/docs/data-sources/config) | data source | +| [cloudinit_config.init_docker_controller](https://registry.terraform.io/providers/hashicorp/cloudinit/latest/docs/data-sources/config) | data source | +| [local_file.kubeconfig_file](https://registry.terraform.io/providers/hashicorp/local/latest/docs/data-sources/file) | data source | +| [openstack_compute_flavor_v2.available_compute_flavors](https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs/data-sources/compute_flavor_v2) | data source | +| [openstack_images_image_v2.ubuntu](https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs/data-sources/images_image_v2) | data source | +| [openstack_networking_network_v2.network](https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs/data-sources/networking_network_v2) | data source | +| [openstack_networking_port_v2.nodes_port](https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs/data-sources/networking_port_v2) | data source | +| [openstack_networking_port_v2.server_port](https://registry.terraform.io/providers/terraform-provider-openstack/openstack/latest/docs/data-sources/networking_port_v2) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +| ---- | ----------- | ---- | ------- | :------: | +| [host\_instances](#input\_host\_instances) | Hosts to Create:
name = Human readable hostname for this host.
is\_controller = Must be true for exactly one host. This will run the k3s "server". All other nodes run the k3s "agent".
flavour = The openstack\_compute\_flavor\_v2 for the host
volume\_size = Size in GB for the disk volume for the node
image\_uuid = (Optional) The Openstack image you want to run, to override the default in ubuntu\_image\_name
floating\_ip = (Optional) Floating IP configuration. Set use\_floating\_ip to true and provide address to associate a floating IP with this host |
list(object({
name = string,
flavour = string,
volume_size = optional(number, 20),
is_controller = optional(bool, false),
image_uuid = optional(string, null),
floating_ip = optional(object({
use_floating_ip = optional(bool, false) # Using a boolean to make it a plan time value.
address = optional(string)
}), null)
}))
| n/a | yes | +| [network](#input\_network) | Network configuration. Either provide 'name' to lookup the network by name, or 'network\_id' to use a network UUID directly. |
object({
name = optional(string)
network_id = optional(string)
})
| n/a | yes | +| [ubuntu\_image\_name](#input\_ubuntu\_image\_name) | Name of an available Machine Image running ubuntu in the openstack environment | `string` | n/a | yes | +| [allowed\_ingress\_ips\_cidr](#input\_allowed\_ingress\_ips\_cidr) | CIDR Block that is allowed ingress to deployed services | `string` | `"0.0.0.0/24"` | no | +| [generate\_random\_name\_prefix](#input\_generate\_random\_name\_prefix) | Whether to generate a random prefix for hostnames. If false, hostnames will use only the name from host\_instances | `bool` | `true` | no | +| [k3s\_version](#input\_k3s\_version) | Optional k3s version to install (INSTALL\_K3S\_VERSION), for example v1.32.2+k3s1. When unset, the installer downloads from the stable channel. | `string` | `null` | no | +| [output\_file\_directory](#input\_output\_file\_directory) | Optional path to write output files to. If directory doesnt exist it will be created | `string` | `null` | no | +| [prefix](#input\_prefix) | Optional custom prefix for resource names. If provided will override generate\_random\_name\_prefix | `string` | `null` | no | +| [ssh\_key\_pair](#input\_ssh\_key\_pair) | Paths to an SSH Public and Private Keypair. If provided these will be given SSH access on the created hosts. If not provided, a Keypair will be generated and accessible as a local file |
object({
public_key_file = string
private_key_file = string
})
| `null` | no | + +## Outputs + +| Name | Description | +| ---- | ----------- | +| [compute\_keypair](#output\_compute\_keypair) | Absolute path to a public and private SSH key pair that is granted login on created VMs | +| [created\_controller\_host](#output\_created\_controller\_host) | Created Controller Host: A map of { hostname: { data } } | +| [created\_hosts](#output\_created\_hosts) | Created Hosts: A map of { hostname: { data } } | +| [created\_security\_group](#output\_created\_security\_group) | Security group associated to the created hosts | +| [kubeconfig\_file](#output\_kubeconfig\_file) | Path to the generated KUBECONFIG file used to connect to kubernetes | +| [kubeconfig\_raw](#output\_kubeconfig\_raw) | Kubeconfig for this cluster | + ## Existing Network and Floating IPs -You can use this module with a custom OpenStack network by specifying the `network` variable with your own network name or network ID. -Using a custom OpenStack network with your own subnet allows you to improve security by keeping most nodes private. This ensures worker nodes and other internal resources are not directly exposed, reducing security risks. Only the controller node needs a floating IP to be accessible in order to use the k8s api server (eg for kubectl to work from outside the network). Using floating ips will also have the advantage of being stable, so you can destroy/create VMs without having to update anywhere the IP address is referenced by reassigning the floating ip. +You can use this module with a custom OpenStack network by specifying the `network` variable with your own network name or network ID. + +Using a custom OpenStack network with your own subnet allows you to improve security by keeping most nodes private. This ensures worker nodes and other internal resources are not directly exposed, reducing security risks. Only the controller node needs a floating IP to be accessible in order to use the k8s api server (eg for kubectl to work from outside the network). Using floating ips will also have the advantage of being stable, so you can destroy/create VMs without having to update anywhere the IP address is referenced by reassigning the floating ip. -To use this configuration, you will probably need to assign a floating IP to the controller node so that it is accessible. You can configure floating IP assignment per node using the `floating_ip` block within each entry in the `host_instances` variable +To use this configuration, you will probably need to assign a floating IP to the controller node so that it is accessible. You can configure floating IP assignment per node using the `floating_ip` block within each entry in the `host_instances` variable. -Please see this example for using thism module with a custom network and floating IPs. +Please see this example for using this module with a custom network and floating IPs. ```hcl -host_instances = [ - { - name = "controller" - is_controller = true - flavour = "m1.small" - floating_ip = { - use_floating_ip = true - address = "203.0.113.10" # Address of an existing floating_ip in openstack - } - }, - { - name = "worker" - flavour = "m1.small" - # Optionally also assign a floating IP here, or leave blank to keep it internal to the network - } +module "openstack_kubernetes_cluster" { + source = "../.." + + ubuntu_image_name = "ubuntu-22.04" network = { network_id = openstack_networking_network_v2.example_network.id } -] - + host_instances = [ + { + name = "controller" + is_controller = true + flavour = "m1.small" + floating_ip = { + use_floating_ip = true + address = "203.0.113.10" # Address of an existing floating_ip in openstack + } + }, + { + name = "worker" + flavour = "m1.small" + # Optionally also assign a floating IP here, or leave blank to keep it internal to the network + }, + ] +} resource "openstack_networking_network_v2" "example_network" { name = "dev-example-network" admin_state_up = "true" } -resource "openstack_networking_subnet_v2" "example_subnet"{ +resource "openstack_networking_subnet_v2" "example_subnet" { name = "dev-example-subnet" network_id = openstack_networking_network_v2.example_network.id cidr = "192.168.0.0/24" @@ -86,8 +155,11 @@ resource "openstack_networking_router_v2" "example_router" { admin_state_up = true external_network_id = data.openstack_networking_network_v2.public.id } + +data "openstack_networking_network_v2" "public" { + name = "public" +} ``` When using a non-default network, ensure the controller host has a floating IP so Terraform can access it for provisioning. - - + diff --git a/terraform-modules/openstack-kubernetes-k3s/examples/floating-ips/main.tf b/terraform-modules/openstack-kubernetes-k3s/examples/floating-ips/main.tf new file mode 100644 index 00000000..e64d0e1c --- /dev/null +++ b/terraform-modules/openstack-kubernetes-k3s/examples/floating-ips/main.tf @@ -0,0 +1,47 @@ +module "openstack_kubernetes_cluster" { + source = "CogStack/kubernetes-k3s/openstack" + version = "0.1.0" + + ubuntu_image_name = "ubuntu-22.04" + network = { + network_id = openstack_networking_network_v2.example_network.id + } + host_instances = [ + { + name = "controller" + is_controller = true + flavour = "m1.small" + floating_ip = { + use_floating_ip = true + address = "203.0.113.10" # Address of an existing floating_ip in openstack + } + }, + { + name = "worker" + flavour = "m1.small" + # Optionally also assign a floating IP here, or leave blank to keep it internal to the network + }, + ] +} + +resource "openstack_networking_network_v2" "example_network" { + name = "dev-example-network" + admin_state_up = "true" +} + +resource "openstack_networking_subnet_v2" "example_subnet" { + name = "dev-example-subnet" + network_id = openstack_networking_network_v2.example_network.id + cidr = "192.168.0.0/24" + ip_version = 4 +} + +resource "openstack_networking_router_v2" "example_router" { + name = "test-router" + admin_state_up = true + external_network_id = data.openstack_networking_network_v2.public.id +} + +data "openstack_networking_network_v2" "public" { + name = "public" +} diff --git a/terraform-modules/openstack-kubernetes-k3s/examples/floating-ips/providers.tf b/terraform-modules/openstack-kubernetes-k3s/examples/floating-ips/providers.tf new file mode 100644 index 00000000..1b717a17 --- /dev/null +++ b/terraform-modules/openstack-kubernetes-k3s/examples/floating-ips/providers.tf @@ -0,0 +1,8 @@ +terraform { + required_providers { + openstack = { + source = "terraform-provider-openstack/openstack" + version = "~> 3.0.0" + } + } +} diff --git a/terraform-modules/openstack-kubernetes-k3s/examples/minimal/main.tf b/terraform-modules/openstack-kubernetes-k3s/examples/minimal/main.tf new file mode 100644 index 00000000..98f98343 --- /dev/null +++ b/terraform-modules/openstack-kubernetes-k3s/examples/minimal/main.tf @@ -0,0 +1,13 @@ +module "openstack_kubernetes_cluster" { + source = "CogStack/kubernetes-k3s/openstack" + version = "0.1.0" + + ubuntu_image_name = "ubuntu-22.04" + network = { + name = "public" + } + host_instances = [ + { name = "controller", is_controller = true, flavour = "m1.small" }, + { name = "worker", flavour = "m1.small" }, + ] +} diff --git a/terraform-modules/openstack-kubernetes-k3s/examples/minimal/providers.tf b/terraform-modules/openstack-kubernetes-k3s/examples/minimal/providers.tf new file mode 100644 index 00000000..1b717a17 --- /dev/null +++ b/terraform-modules/openstack-kubernetes-k3s/examples/minimal/providers.tf @@ -0,0 +1,8 @@ +terraform { + required_providers { + openstack = { + source = "terraform-provider-openstack/openstack" + version = "~> 3.0.0" + } + } +} diff --git a/terraform-modules/openstack-kubernetes-k3s/tests/compute.tftest.hcl b/terraform-modules/openstack-kubernetes-k3s/tests/compute.tftest.hcl index b9df2293..e4e01867 100644 --- a/terraform-modules/openstack-kubernetes-k3s/tests/compute.tftest.hcl +++ b/terraform-modules/openstack-kubernetes-k3s/tests/compute.tftest.hcl @@ -28,7 +28,7 @@ run "server_and_node" { command = plan variables { - ubuntu_image_name = "ubuntu" + ubuntu_image_name = "ubuntu" generate_random_name_prefix = false prefix = "test" network = { name = "public" } @@ -59,7 +59,7 @@ run "required_only" { variables { ubuntu_image_name = "ubuntu" - network = { name = "public" } + network = { name = "public" } host_instances = [ { name = "controller", is_controller = true, flavour = "m1.small" }, { name = "worker", flavour = "m1.small" }, @@ -86,7 +86,7 @@ run "all_variables" { command = plan variables { - ubuntu_image_name = "ubuntu" + ubuntu_image_name = "ubuntu" allowed_ingress_ips_cidr = "10.1.2.0/24" k3s_version = "v1.32.2+k3s1" generate_random_name_prefix = false