├── .gitignore
├── LICENSE
├── README.md
├── locals.tf
├── main.tf
├── outputs.tf
└── variables.tf
/.gitignore:
--------------------------------------------------------------------------------
1 | .terraform/
2 | *.tfvars
3 | .terraform.lock.hcl
4 | *.tfstate*
5 |
6 | configs/
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Talos OS vSphere Cluster Terraform Module
2 |
3 | Page in [Terraform Registry](https://registry.terraform.io/modules/ilpozzd/vsphere-cluster/talos/latest)
4 |
5 | This module allows you to deploy a Kubernetes cluster based on Talos OS in the vSphere infrastructure.
6 | The configuration of the virtual machines fully corresponds to the configuration of [Talos OS v1.0.x](https://www.talos.dev/v1.0/).
7 |
8 | ## Usage
9 |
10 | ```hcl
11 | module "kubernetes-cluster" {
12 | source = "ilpozzd/vsphere-cluster/talos"
13 | version = "1.1.0"
14 |
15 | datacenter = "Company_Datacenter"
16 | datastores = [
17 | "Datastore-1",
18 | "Datastore-2",
19 | "Datastore-3"
20 | ]
21 | hosts = [
22 | "host-1.company.local",
23 | "host-2.company.local",
24 | "host-3.company.local",
25 | "host-4.company.local"
26 | ]
27 | resource_pool = "Kubernetes_Cluster"
28 | folder = "Office/Kubernetes_Cluster"
29 | remote_ovf_url = "https://github.com/siderolabs/talos/releases/download/v1.0.5/vmware-amd64.ova"
30 |
31 | control_plane_count = 3
32 | control_plane_num_cpus = 2
33 | control_plane_memory = 2048
34 | control_plane_disks = [
35 | {
36 | label = "sda"
37 | size = 20
38 | }
39 | ]
40 | control_plane_network_interfaces = [
41 | {
42 | name = "192_168_10_0"
43 | }
44 | ]
45 |
46 | worker_count = 2
47 | worker_num_cpus = 4
48 | worker_memory = 4096
49 | worker_disks = [
50 | {
51 | label = "sda"
52 | size = 40
53 | }
54 | ]
55 | worker_network_interfaces = [
56 | {
57 | name = "192_168_10_0"
58 | }
59 | ]
60 |
61 | machine_base_configuration = {
62 | install = {
63 | disk = "/dev/sda"
64 | image = "ghcr.io/siderolabs/installer:latest"
65 | bootloader = true
66 | wipe = false
67 | }
68 | time = {
69 | disabled = false
70 | servers = [
71 | "ntp.company.local"
72 | ]
73 | bootTimeout = "2m0s"
74 | }
75 | features = {
76 | rbac = true
77 | }
78 | }
79 |
80 | machine_network = {
81 | nameservers = [
82 | "192.168.1.10",
83 | "192.168.1.11"
84 | ]
85 | }
86 |
87 | control_plane_machine_network_interfaces = [
88 | [
89 | {
90 | interface = "eth0"
91 | addresses = [
92 | "192.168.10.10/24"
93 | ]
94 | routes = [
95 | {
96 | network = "0.0.0.0/0"
97 | gateway = "192.168.10.1"
98 | }
99 | ]
100 | }
101 | ],
102 | [
103 | {
104 | interface = "eth0"
105 | addresses = [
106 | "192.168.10.11/24"
107 | ]
108 | routes = [
109 | {
110 | network = "0.0.0.0/0"
111 | gateway = "192.168.10.1"
112 | }
113 | ]
114 | }
115 | ],
116 | [
117 | {
118 | interface = "eth0"
119 | addresses = [
120 | "192.168.10.12/24"
121 | ]
122 | routes = [
123 | {
124 | network = "0.0.0.0/0"
125 | gateway = "192.168.10.1"
126 | }
127 | ]
128 | }
129 | ]
130 | ]
131 |
132 | worker_machine_network_interfaces = [
133 | [
134 | {
135 | interface = "eth0"
136 | addresses = [
137 | "192.168.10.13/24"
138 | ]
139 | routes = [
140 | {
141 | network = "0.0.0.0/0"
142 | gateway = "192.168.10.1"
143 | }
144 | ]
145 | }
146 | ],
147 | [
148 | {
149 | interface = "eth0"
150 | addresses = [
151 | "192.168.10.14/24"
152 | ]
153 | routes = [
154 | {
155 | network = "0.0.0.0/0"
156 | gateway = "192.168.10.1"
157 | }
158 | ]
159 | }
160 | ]
161 | ]
162 |
163 | cluster_name = "kubernetes-cluster"
164 | kubeconfig_path = "./configs/kubeconfig"
165 | talosconfig_path = "./configs/talosconfig"
166 | }
167 | ```
168 |
169 | ## Examples
170 |
171 | * [Terragrunt Example](https://github.com/ilpozzd/talos-vsphere-cluster-terragrunt-example)
172 |
173 | ## Requirements
174 |
175 | | Name | Version |
176 | |---|---|
177 | | terraform | >= 1.1.9, < 2.0.0 |
178 | | [hashicorp/vsphere](https://registry.terraform.io/providers/hashicorp/vsphere/2.1.1) | 2.1.1 |
179 |
180 | ### vSphere Version >= `6.7u3`
181 |
182 | ### Required `Terraform Role` permissions in **vSphere**
183 |
184 | Datastore:
185 | * Allocate space
186 | * Browse datastore
187 | * Low level file operations
188 | * Remove file
189 | * Update virtual machine files
190 | * Update virtual machine metadata
191 |
192 | Folder:
193 | * Create folder
194 | * Delete folder
195 | * Move folder
196 | * Rename folder
197 |
198 | Network:
199 | * Assign network
200 |
201 | Resource:
202 | * Assign virtual machine to resource pool
203 | * Migrate powered off virtual machine
204 | * Migrate powered on virtual machine
205 |
206 | Profile-driven storage:
207 | * Profile-driven storage view
208 |
209 | vApp:
210 | * Import
211 | * View OVF environment
212 | * vApp application configuration
213 | * vApp instance configuration
214 | * vApp managedBy configuration
215 | * vApp resource configuration
216 |
217 | Virtual machine:
218 | * Change Configuration
219 | * Edit Inventory
220 | * Guest Operations
221 | * Interaction
222 | * Provisioning
223 |
224 | ### Required objects to apply `roles`
225 |
226 | | Object | Role | Defined in |
227 | |---|---|---|
228 | | vCenter | `Terraform Role` | This object |
229 | | Datacenter | `Read-only Role` | This object |
230 | | Datastore Cluster | `Terraform Role` | This object and it's children |
231 | | Hosts Cluster | `Read-only Role` | This object |
232 | | Hosts | `Terraform Role` | This object |
233 | | DPG | `Terraform Role` | This object |
234 | | Folder | `Terraform Role` | This object and it's children |
235 | | Resource pool | `Terraform Role` | This object and it's children |
236 |
237 | ## Providers
238 |
239 | | Name | Version |
240 | |---|---|
241 | | [hashicorp/vsphere](https://registry.terraform.io/providers/hashicorp/vsphere/2.1.1) | 2.1.1 |
242 | | [hashicorp/local](https://registry.terraform.io/providers/hashicorp/local/2.2.3) | 2.2.3 |
243 |
244 | ## Modules
245 |
246 | | Name | Version |
247 | |---|---|
248 | | [ilpozzd/secrets/talos](https://registry.terraform.io/modules/ilpozzd/secrets/talos/1.0.0) | 1.0.0 |
249 | | [ilpozzd/vsphere-vm/talos](https://registry.terraform.io/modules/ilpozzd/vsphere-vm/talos/1.1.0) | 1.1.0 |
250 |
251 | ## Resources
252 |
253 | | Name | Type |
254 | |---|---|
255 | | [local_file.kubeconfig](https://registry.terraform.io/providers/hashicorp/local/2.2.3/docs/resources/file) | resource |
256 | | [local_file.talosconfig](https://registry.terraform.io/providers/hashicorp/local/2.2.3/docs/resources/file) | resource |
257 |
258 | ## Inputs
259 |
260 | | Name | Description | Type | Default | Required |
261 | |---|---|---|---|---|
262 | | datacenter | VMware datacenter name. | `string` | `-` | Yes |
263 | | datastores | VMWare datastore(s) where all data for the virtual machine will be placed in. | `list(string)` | `-` | Yes |
264 | | hosts | ESXi host(s) where the virtual machine will be created. | `list(string)` | `-` | Yes |
265 | | resource_pool | VMWare resource pool where the virtual machine will be created. | `string` | `-` | Yes |
266 | | folder | Folder to create the virtual machines in. | `string` | `-` | Yes |
267 | | remote_ovf_url | URL to the remote [Talos OS 1.0.x](https://github.com/siderolabs/talos/releases) ovf/ova file. | `string` | `-` | Yes |
268 | | control_plane_count | Number of 'controlplane' virtual machines.| `number` | `2` | No |
269 | | worker_count | Number of 'worker' virtual machines.| `number` | `0` | No |
270 | | control_plane_num_cpus | The total number of virtual processor cores to assign to 'controlplane' virtual machines. | `number` | `2` | No |
271 | | worker_num_cpus | The total number of virtual processor cores to assign to 'worker' virtual machines. | `number` | `4` | No |
272 | | control_plane_memory | The amount of RAM for 'controlplane' virtual machines, in Mb. | `number` | `2048` | No |
273 | | worker_memory | The amount of RAM for 'worker' virtual machines, in Mb. | `number` | `4096` | No |
274 | | control_plane_disks | A specification list for a virtual disk devices on 'controlplane' virtual machines. Use only first disk to Talos installation in 'machine_base_configuration'. block | [`list`](#disks-input) | `-` | Yes |
275 | | worker_disks | "A specification list for a virtual disk devices on 'worker' virtual machines. Use only first disk to Talos installation in 'machine_base_configuration' block. | [`list`](#disks-input) | `[]` | No |
276 | | control_plane_network_interfaces | A specification list for a virtual NIC on 'controlplane' virtual machines. | [`list`](#network-interfaces-input) | `-` | Yes |
277 | | worker_network_interfaces | A specification list for a virtual NIC on 'worker' virtual machines. | [`list`](#network-interfaces-input) | `[]` | No |
278 | | talos_base_configuration | Talos OS top-level configuration. | [`object`](#talos-base-configuration-input) | [`object`](#talos-base-configuration-input) | No |
279 | | machine_secrets | Secret data that is used to create trust relationships between virtual machines. | [`object`](#machine-secrets-input) | `-` | [No](#machine-secrets-input) |
280 | | talos_admin_pki | Base64 encoded certificate (signed by [machine_secrets.ca.crt](#machine-secrets-input) and key (in ED25519) to provide access to virtual machine trought `talosctl`. | [`object`](#talos-admin-pki-input) | `{}` | [No](#talos-admin-pki-input) |
281 | | machine_base_configuration | Basic configuration of all virtual machines. | [`object`](#machine-base-configuration-input) | `-` | Yes |
282 | | control_plane_machine_extra_configuration | Extended configuration of 'controlplane' virtual machine. | [`object`](#machine-extra-configuration-input) | `{}` | No |
283 | | worker_machine_extra_configuration | Extended configuration of 'worker' virtual machines. | [`object`](#machine-extra-configuration-input) | `{}` | No |
284 | | control_plane_machine_cert_sans | A list of alternative names for [control_plane_count](#control-plane-count-cell) control planes (optional). | `list(list(string))` | `[]` | No |
285 | | worker_machine_cert_sans | A list of alternative names for [worker_count](#worker-count-cell) workers (optional). | `list(list(string))` | `[]` | No |
286 | | machine_network | General network configuration of the virtual machine. 'hostname' and 'interfaces' parameters are described in separate inputs. | [`object`](#machine-network-input) | `{}` | No |
287 | | control_plane_machine_network_hostnames | A list of hostnames for [control_plane_count](#control-plane-count-cell) of 'controlplane' virtual machines (if not set will be generated automatically). | `list(string)` | `[]` | No |
288 | | worker_machine_network_hostnames | A list of hostnames for [worker_count](#worker-count-cell) of 'worker' virtual machines (if not set will be generated automatically). | `list(string)` | `[]` | No |
289 | | control_plane_machine_network_interfaces | A list of network interfaces for [control_plane_count](#control-plane-count-cell) of 'controlplane' virtual machines (if not set DHCP will be used). Not less than one element with one static IP address required. | [`list`](#machine-network-interfaces-input) | `[]` | Yes |
290 | | worker_machine_network_interfaces | A list of network interfaces for [worker_count](#worker-count-cell) of 'worker' virtual machines (if not set DHCP will be used). | [`list`](#machine-network-interfaces-input) | `[]` | No |
291 | | cluster_secrets | Secret data that is used to establish trust relationships between Kubernetes cluster nodes. | [`object`](#cluster-secrets-input) | `-` | [No](#cluster-secrets-input) |
292 | | control_plane_cluster_secrets | Secret data required to establish trust relationships between components used by 'controlplane' nodes in the Kubernetes cluster. | [`object`](#control-plane-cluster-secrets-input) | `{}` | [No](#control-plane-cluster-secrets-input) |
293 | | cluster_name | The name of the cluster. | `string` | `-` | Yes |
294 | | cluster_control_plane | Data to define the API endpoint address for joining a node to the Kubernetes cluster. | [`object`](#cluster-control-plane-input) | `-` | [Yes/No](#cluster-control-plane-input) |
295 | | cluster_discovery | Data that sets up the discovery of nodes in the Kubernetes cluster. | [`object`](#cluster-discovery-input) | [`object`](#cluster-discovery-input) | No |
296 | | control_plane_cluster_configuration | Data that configure the components of the 'controlplane' nodes in the Kubernetes cluster. | [`object`](#control-plane-cluster-configuration-input) | `{}` | No |
297 | | cluster_inline_manifests |A list of Kuberenetes manifests whose content is represented as a string. These will get automatically deployed as part of the bootstrap. | [`list`](#cluster-inline-manifests-input) | `[]` | No |
298 | | cluster_extra_manifests | A list of `URLs` that point to additional manifests. These will get automatically deployed as part of the bootstrap. | `list(string)` | `[]` | No |
299 | | cluster_extra_manifest_headers | A map of key value pairs that will be added while fetching the `cluster_extra_manifests`. | `map(string)` | `{}` | No |
300 | | validity_period_hours | The number of hours after initial issuing that **ALL** generated certificates become invalid. | `number` | `8760` | No |
301 | | kubeconfig_path | Path to save kubeconfig file (Include filename. If not set config will not be created). | `string` | `""` | No |
302 | | talosconfig_path | Path to save talosconfig file (Include filename. If not set config will not be created). | `string` | `""` | No |
303 | | vmtoolsd_extra_manifest | A link to talos-vmtoolsd Kubernetes manifest. | `string` | [`Link`](https://raw.githubusercontent.com/mologie/talos-vmtoolsd/release-0.3/deploy/0.3.yaml) | No |
304 |
305 | ### Disks Input
306 |
307 | ```hcl
308 | list(object({
309 | label = string
310 | size = number
311 | eagerly_scrub = optional(bool)
312 | thin_provisioned = optional(bool)
313 | }))
314 | ```
315 | * `label` - Any name for disk (label for Terraform)
316 | * `size` - Capacity in **Gb**
317 | * `eagerly_scrub` and `thin_provisioned` - See [vSphere Provider Documentation](https://registry.terraform.io/providers/hashicorp/vsphere/latest/docs/resources/virtual_machine#disk-options)
318 |
319 | ### Network Interfaces Input
320 |
321 | ```hcl
322 | list(object({
323 | name = string
324 | }))
325 | ```
326 | * `name` - Distributed Port Group (DPG) name
327 |
328 | ### Talos Base Configuration Input
329 |
330 | ```hcl
331 | object({
332 | version = string
333 | persist = bool
334 | })
335 | ```
336 |
337 | Default:
338 |
339 | ```hcl
340 | {
341 | version = "v1alpha1"
342 | persist = false
343 | }
344 | ```
345 |
346 | See [Config](https://www.talos.dev/v1.0/reference/configuration/#config) section in Talos Configuration Reference for detail description.
347 |
348 | ### Machine Secrets Input
349 |
350 | ```hcl
351 | object({
352 | token = string
353 | ca = object({
354 | crt = string
355 | key = string
356 | })
357 | })
358 | ```
359 |
360 | See [MachineConfig](https://www.talos.dev/v1.0/reference/configuration/#machineconfig) section in Talos Configuration Reference for detail description.
361 |
362 | By default generated by [ilpozzd/secrets/talos](https://registry.terraform.io/modules/ilpozzd/secrets/talos/1.0.0). You can provide your own. If you provide this secrets you also must provide [talos_admin_pki](#talos-admin-pki)
363 |
364 | ### Talos Admin PKI Input
365 |
366 | ```hcl
367 | object({
368 | crt = optional(string)
369 | key = optional(string)
370 | })
371 | ```
372 | * `crt` - Base64 encoded certificate in **PEM** format
373 | * `key` - Base64 encoded key in **PEM** format
374 |
375 | By default generated by [ilpozzd/secrets/talos](https://registry.terraform.io/modules/ilpozzd/secrets/talos/1.0.0).
376 |
377 | ### Machine Base Configuration
378 |
379 | ```hcl
380 | object({
381 | install = object({
382 | disk = string
383 | extraKernelArgs = optional(list(string))
384 | image = string
385 | bootloader = bool
386 | wipe = bool
387 | diskSelector = optional(object({
388 | size = string
389 | model = string
390 | busPath = string
391 | }))
392 | extensions = optional(list(string))
393 | })
394 | kubelet = optional(object({
395 | image = string
396 | extraArgs = optional(map(string))
397 | clusterDNS = optional(list(string))
398 | extraMounts = optional(list(object({
399 | destination = string
400 | type = string
401 | source = string
402 | options = list(string)
403 | })))
404 | extraConfig = optional(map(string))
405 | nodeIP = optional(object({
406 | validSubnets = list(string)
407 | }))
408 | }))
409 | time = optional(object({
410 | disabled = optional(bool)
411 | servers = optional(list(string))
412 | bootTimeout = optional(string)
413 | }))
414 | features = optional(object({
415 | rbac = optional(bool)
416 | }))
417 | })
418 | ```
419 |
420 | See [MachineConfig](https://www.talos.dev/v1.0/reference/configuration/#machineconfig) section in Talos Configuration Reference for detail description.
421 |
422 | ### Machine Extra Configuration Input
423 |
424 | ```hcl
425 | object({
426 | controlPlane = optional(object({
427 | controllerManager = object({
428 | disabled = bool
429 | })
430 | scheduler = object({
431 | disabled = bool
432 | })
433 | }))
434 | pods = optional(list(map(any)))
435 | disks = optional(list(object({
436 | device = string
437 | partitions = list(object({
438 | mountpoint = string
439 | size = string
440 | }))
441 | })))
442 | files = optional(list(object({
443 | content = string
444 | permissions = string
445 | path = string
446 | op = string
447 | })))
448 | env = optional(object({
449 | GRPC_GO_LOG_VERBOSITY_LEVEL = optional(string)
450 | GRPC_GO_LOG_SEVERITY_LEVEL = optional(string)
451 | http_proxy = optional(string)
452 | https_proxy = optional(string)
453 | no_proxy = optional(bool)
454 | }))
455 | sysctls = optional(map(string))
456 | sysfs = optional(map(string))
457 | registries = optional(object({
458 | mirrors = optional(map(object({
459 | endpoints = list(string)
460 | })))
461 | config = optional(map(object({
462 | tls = object({
463 | insecureSkipVerify = bool
464 | clientIdentity = optional(object({
465 | crt = string
466 | key = string
467 | }))
468 | ca = optional(string)
469 | })
470 | auth = optional(object({
471 | username = optional(string)
472 | password = optional(string)
473 | auth = optional(string)
474 | identityToken = optional(string)
475 | }))
476 | })))
477 | }))
478 | systemDiskEncryption = optional(map(object({
479 | provider = string
480 | keys = optional(list(object({
481 | static = optional(object({
482 | passphrase = string
483 | }))
484 | nodeID = optional(map(string))
485 | slot = optional(number)
486 | })))
487 | cipher = optional(string)
488 | keySize = optional(number)
489 | blockSize = optional(number)
490 | options = optional(list(string))
491 | })))
492 | udev = optional(object({
493 | rules = list(string)
494 | }))
495 | logging = optional(object({
496 | destinations = list(object({
497 | endpoint = string
498 | format = string
499 | }))
500 | }))
501 | kernel = optional(object({
502 | modules = list(object({
503 | name = string
504 | }))
505 | }))
506 | })
507 | ```
508 |
509 | See [MachineConfig](https://www.talos.dev/v1.0/reference/configuration/#machineconfig) section in Talos Configuration Reference for detail description.
510 |
511 | ### Machine Network Input
512 |
513 | ```hcl
514 | object({
515 | nameservers = optional(list(string))
516 | extraHostEntries = optional(list(object({
517 | ip = string
518 | aliases = list(string)
519 | })))
520 | kubespan = optional(object({
521 | enabled = bool
522 | }))
523 | })
524 | ```
525 | See [NetworkConfig](https://www.talos.dev/v1.0/reference/configuration/#networkconfig) section in Talos Configuration Reference for detail description.
526 |
527 | [hostname](#machine-network-hostnames-cell) and [interfaces](#machine-network-interfaces-cell) parameters are described in separate inputs.
528 |
529 | ### Machine Network Interfaces Input
530 |
531 | ```hcl
532 | list(list(object({
533 | interface = string
534 | addresses = optional(list(string))
535 | routes = optional(list(object({
536 | network = string
537 | gateway = optional(string)
538 | source = optional(string)
539 | metric = optional(number)
540 | })))
541 | vlans = optional(list(object({
542 | addresses = list(string)
543 | routes = optional(list(object({
544 | network = string
545 | gateway = optional(string)
546 | source = optional(string)
547 | metric = optional(number)
548 | })))
549 | dhcp = optional(boolbase64decode(module.secrets.kubernetes_admin_pki.key)
550 | mtu = optional(number)
551 | bond = optional(object({
552 | interfaces = list(string)
553 | mode = string
554 | lacpRate = string
555 | }))
556 | dhcp = optional(bool)
557 | ignore = optional(bool)
558 | dummy = optional(bool)
559 | dhcpOptions = optional(object({
560 | routeMetric = number
561 | ipv4 = optional(bool)
562 | ipv6 = optional(bool)
563 | }))
564 | wireguard = optional(object({
565 | privateKey = string
566 | listenPort = number
567 | firewallMark = number
568 | peers = list(object({
569 | publicKey = string
570 | endpoint = string
571 | persistentKeepaliveInterval = optional(string)
572 | allowedIPs = list(string)
573 | }))
574 | }))
575 | vip = optional(object({
576 | ip = string
577 | equinixMetal = optional(object({
578 | apiToken = string
579 | }))
580 | hcloud = optional(object({
581 | apiToken = string
582 | }))
583 | }))
584 | })))
585 | ```
586 |
587 | See [Device](https://www.talos.dev/v1.0/reference/configuration/#device) section in Talos Configuration Reference for detail description.
588 |
589 | ### Cluster Secrets Input
590 |
591 | ```hcl
592 | object({
593 | id = string
594 | secret = string
595 | token = string
596 | ca = object({
597 | crt = string
598 | key = string
599 | })
600 | })
601 | ```
602 | See [ClusterConfig](https://www.talos.dev/v1.0/reference/configuration/#clusterconfig) section in Talos Configuration Reference for detail description.
603 |
604 | By default generated by [ilpozzd/secrets/talos](https://registry.terraform.io/modules/ilpozzd/secrets/talos/1.0.0). You can provide your own.
605 |
606 | ### Control Plane Cluster Secrets Input
607 |
608 | ```hcl
609 | object({
610 | aescbcEncryptionSecret = optional(string)
611 | aggregatorCA = optional(object({
612 | crt = optional(string)
613 | key = optional(string)
614 | }))
615 | serviceAccount = optional(object({
616 | key = optional(string)
617 | }))
618 | etcd = optional(object({
619 | ca = object({
620 | crt = optional(string)
621 | key = optional(string)
622 | })
623 | }))
624 | })
625 | ```
626 |
627 | See [ClusterConfig](https://www.talos.dev/v1.0/reference/configuration/#clusterconfig) section in Talos Configuration Reference for detail description.
628 |
629 | By default generated by [ilpozzd/secrets/talos](https://registry.terraform.io/modules/ilpozzd/secrets/talos/1.0.0). You can provide your own.
630 |
631 | ### Cluster Control Plane Input
632 |
633 | ```hcl
634 | object({
635 | endpoint = optional(string)
636 | localAPIServerPort = optional(number)
637 | })
638 | ```
639 |
640 | See [ControlPlaneConfig](https://www.talos.dev/v1.0/reference/configuration/#controlplaneconfig) section in Talos Configuration Reference for detail description.
641 |
642 | Required if `init` node is outside of this cluster.
643 |
644 | ### Cluster Discovery Input
645 |
646 | ```hcl
647 | object({
648 | enabled = bool
649 | registries = optional(object({
650 | kubernetes = optional(object({
651 | disabled = bool
652 | }))
653 | service = optional(object({
654 | disabled = bool
655 | endpoint = string
656 | }))
657 | }))
658 | })
659 | ```
660 |
661 | Default:
662 |
663 | ```hcl
664 | {
665 | enabled = true
666 | }
667 | ```
668 |
669 | See [ClusterDiscoveryConfig](https://www.talos.dev/v1.0/reference/configuration/#clusterdiscoveryconfig) section in Talos Configuration Reference for detail description.
670 |
671 | ### Control Plane Cluster Configuration Input
672 |
673 | ```hcl
674 | object({
675 | network = optional(object({
676 | cni = optional(object({
677 | name = string
678 | urls = optional(list(string))
679 | }))
680 | dnsDomain = optional(string)
681 | podSubnets = optional(list(string))
682 | serviceSubnets = optional(list(string))
683 | }))
684 | apiServer = optional(object({
685 | image = string
686 | extraArgs = optional(map(string))
687 | extraVolumes = optional(list(object({
688 | hostPath = string
689 | mountPath = string
690 | readonly = bool
691 | })))
692 | env = optional(map(string))
693 | certSANs = optional(list(string))
694 | disablePodSecurityPolicy = optional(bool)
695 | admissionControl = optional(list(object({
696 | name = string
697 | configuration = map(any)
698 | })))
699 | }))
700 | controllerManager = optional(object({
701 | image = string
702 | extraArgs = optional(map(string))
703 | extraVolumes = optional(list(object({
704 | hostPath = string
705 | mountPath = string
706 | readonly = bool
707 | })))
708 | env = optional(map(string))
709 | }))
710 | proxy = optional(object({
711 | disabled = bool
712 | image = optional(string)
713 | mode = optional(string)
714 | extraArgs = optional(map(string))
715 | }))
716 | scheduler = optional(object({
717 | image = string
718 | extraArgs = optional(map(string))
719 | extraVolumes = optional(list(object({
720 | hostPath = string
721 | mountPath = string
722 | readonly = bool
723 | })))
724 | env = optional(map(string))
725 | }))
726 | etcd = optional(object({
727 | image = optional(string)
728 | extraArgs = optional(map(string))
729 | subnet = optional(string)
730 | }))
731 | coreDNS = optional(object({
732 | disabled = bool
733 | image = optional(string)
734 | }))
735 | externalCloudProvider = optional(object({
736 | enabled = bool
737 | manifests = list(string)
738 | }))
739 | adminKubeconfig = optional(object({
740 | certLifetime = string
741 | }))
742 | allowSchedulingOnMasters = optional(bool)
743 | })
744 | ```
745 |
746 | See [ClusterConfig](https://www.talos.dev/v1.0/reference/configuration/#clusterconfig) section in Talos Configuration Reference for detail description.
747 |
748 | ### Cluster Inline Manifests Input
749 |
750 | ```hcl
751 | list(object({
752 | name = string
753 | contents = string
754 | }))
755 | ```
756 |
757 | See [ClusterConfig](https://www.talos.dev/v1.0/reference/configuration/#clusterconfig) section in Talos Configuration Reference for detail description.
758 |
759 | ## Outputs
760 |
761 | | Name | Description | Type | Sensitive |
762 | |---|---|---|---|
763 | | cluster_endpoint | API endpoint of the cluster. | `string` | `false` |
764 | | cluster_id | Qunique identificator of the cluster. | `string` | `true` |
765 | | cluster_nodes | List of all nodes in the cluster. | [`object`](#cluster-nodes-output) | `false` |
766 | | kubeconfig | Configuration file for obtaining administrative access to the cluster. | `string` | `true` |
767 | | talosconfig | Configuration file for obtaining administrative access to Talos virtual machines. | `string` | `true` |
768 | | kubernetes_admin_pki | Cerificates and keys for obtaining administrative access to the cluster. | [`object`](#kubernetes-admin-pki-output) | `string` |
769 |
770 | ### Cluster Nodes Output
771 |
772 | ```hcl
773 | {
774 | control_plane = list(string)
775 | worker = list(string)
776 | }
777 | ```
778 |
779 | ### Kubernetes Admin PKI Output
780 |
781 | ```hcl
782 | {
783 | cluster_ca_certificate = string
784 | client_certificate = string
785 | client_key = string
786 | }
787 | ```
788 |
789 | ## Authors
790 |
791 | Module is maintained by [Ilya Pozdnov](https://github.com/ilpozzd).
792 |
793 | ## License
794 |
795 | Apache 2 Licensed. See [LICENSE](LICENSE) for full details.
796 |
--------------------------------------------------------------------------------
/locals.tf:
--------------------------------------------------------------------------------
1 | locals {
2 | machine_secrets = defaults(var.machine_secrets, module.secrets.machine_secrets)
3 | talos_admin_pki = defaults(var.talos_admin_pki, module.secrets.talos_admin_pki)
4 | cluster_secrets = defaults(var.cluster_secrets, module.secrets.cluster_secrets)
5 | control_plane_cluster_secrets = defaults(var.control_plane_cluster_secrets, module.secrets.control_plane_cluster_secrets)
6 |
7 | cluster_control_plane = defaults(var.cluster_control_plane, {
8 | endpoint = "https://${replace(var.control_plane_machine_network_interfaces[0][0].addresses[0], "/[/].*/", "")}:6443"
9 | })
10 |
11 | kubeconfig = {
12 | apiVersion = "v1"
13 | kind = "Config"
14 | clusters = [
15 | {
16 | name = var.cluster_name
17 | cluster = {
18 | server = local.cluster_control_plane.endpoint
19 | certificate-authority-data = module.secrets.cluster_secrets.ca.crt
20 | }
21 | }
22 | ]
23 | users = [
24 | {
25 | name = "admin@${var.cluster_name}"
26 | user = {
27 | client-certificate-data = module.secrets.kubernetes_admin_pki.crt
28 | client-key-data = module.secrets.kubernetes_admin_pki.key
29 | }
30 | }
31 | ]
32 | contexts = [
33 | {
34 | context = {
35 | cluster = var.cluster_name
36 | namespace = "default"
37 | user = "admin@${var.cluster_name}"
38 | }
39 | name = "admin@${var.cluster_name}"
40 | }
41 | ]
42 | current-context = "admin@${var.cluster_name}"
43 | }
44 |
45 | talosconfig = {
46 | context = "admin@${var.cluster_name}"
47 | contexts = {
48 | "admin@${var.cluster_name}" = merge(
49 | { endpoints = module.control_plane_vm.default_ip_addresses },
50 | { nodes = concat(module.control_plane_vm.default_ip_addresses, module.worker_vm.default_ip_addresses) },
51 | { ca = local.machine_secrets.ca.crt },
52 | local.talos_admin_pki
53 | )
54 | }
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/main.tf:
--------------------------------------------------------------------------------
1 | terraform {
2 | experiments = [
3 | module_variable_optional_attrs
4 | ]
5 |
6 | required_version = ">= 1.1.9, < 2.0.0"
7 | required_providers {
8 | vsphere = {
9 | source = "hashicorp/vsphere"
10 | version = "2.1.1"
11 | }
12 | local = {
13 | source = "hashicorp/local"
14 | version = "2.2.3"
15 | }
16 | }
17 | }
18 |
19 | module "secrets" {
20 | source = "ilpozzd/secrets/talos"
21 | version = "1.0.0"
22 |
23 | validity_period_hours = var.validity_period_hours
24 | }
25 |
26 | module "control_plane_vm" {
27 | source = "ilpozzd/vsphere-vm/talos"
28 | version = "1.1.3"
29 |
30 | datacenter = var.datacenter
31 | datastores = var.datastores
32 | hosts = var.hosts
33 | resource_pool = var.resource_pool
34 | folder = var.folder
35 | remote_ovf_url = var.remote_ovf_url
36 |
37 | vm_count = var.control_plane_count
38 | num_cpus = var.control_plane_num_cpus
39 | memory = var.control_plane_memory
40 |
41 | disks = var.control_plane_disks
42 | network_interfaces = var.control_plane_network_interfaces
43 |
44 | create_init_node = true
45 |
46 | talos_base_configuration = var.talos_base_configuration
47 | talos_admin_pki = local.talos_admin_pki
48 |
49 | machine_base_configuration = var.machine_base_configuration
50 | machine_extra_configuration = var.control_plane_machine_extra_configuration
51 | machine_secrets = local.machine_secrets
52 |
53 | machine_type = "controlplane"
54 | machine_cert_sans = var.control_plane_machine_cert_sans
55 | machine_network = var.machine_network
56 | machine_network_hostnames = var.control_plane_machine_network_hostnames
57 | machine_network_interfaces = var.control_plane_machine_network_interfaces
58 |
59 | cluster_name = var.cluster_name
60 | cluster_control_plane = local.cluster_control_plane
61 | cluster_discovery = var.cluster_discovery
62 | control_plane_cluster_configuration = var.control_plane_cluster_configuration
63 |
64 | cluster_secrets = local.cluster_secrets
65 | control_plane_cluster_secrets = local.control_plane_cluster_secrets
66 |
67 | cluster_inline_manifests = var.cluster_inline_manifests
68 | cluster_extra_manifests = var.cluster_extra_manifests
69 | cluster_extra_manifest_headers = var.cluster_extra_manifest_headers
70 | }
71 |
72 | module "worker_vm" {
73 | source = "ilpozzd/vsphere-vm/talos"
74 | version = "1.1.3"
75 |
76 | datacenter = var.datacenter
77 | datastores = reverse(var.datastores)
78 | hosts = reverse(var.hosts)
79 | resource_pool = var.resource_pool
80 | folder = var.folder
81 | remote_ovf_url = var.remote_ovf_url
82 |
83 | vm_count = var.worker_count
84 | num_cpus = var.worker_num_cpus
85 | memory = var.worker_memory
86 |
87 | disks = var.worker_disks
88 | network_interfaces = var.worker_network_interfaces
89 |
90 | talos_base_configuration = var.talos_base_configuration
91 |
92 | machine_base_configuration = var.machine_base_configuration
93 | machine_extra_configuration = var.worker_machine_extra_configuration
94 | machine_secrets = local.machine_secrets
95 |
96 | machine_type = "worker"
97 | machine_cert_sans = var.worker_machine_cert_sans
98 | machine_network = var.machine_network
99 | machine_network_hostnames = var.worker_machine_network_hostnames
100 | machine_network_interfaces = var.worker_machine_network_interfaces
101 |
102 | cluster_name = var.cluster_name
103 | cluster_control_plane = local.cluster_control_plane
104 | cluster_discovery = var.cluster_discovery
105 |
106 | cluster_secrets = local.cluster_secrets
107 | }
108 |
109 | resource "local_file" "kubeconfig" {
110 | count = var.kubeconfig_path != "" ? 1 : 0
111 | filename = var.kubeconfig_path
112 | content = yamlencode(local.kubeconfig)
113 | }
114 |
115 | resource "local_file" "talosconfig" {
116 | count = var.talosconfig_path != "" ? 1 : 0
117 | filename = var.talosconfig_path
118 | content = yamlencode(local.talosconfig)
119 | }
120 |
--------------------------------------------------------------------------------
/outputs.tf:
--------------------------------------------------------------------------------
1 | output "cluster_endpoint" {
2 | description = "API endpoint of the cluster."
3 | value = local.cluster_control_plane.endpoint
4 | }
5 |
6 | output "cluster_id" {
7 | description = "Qunique identificator of the cluster."
8 | sensitive = true
9 | value = module.secrets.cluster_secrets.id
10 | }
11 |
12 | output "cluster_nodes" {
13 | description = "List of all nodes in the cluster."
14 | value = {
15 | control_plane = module.control_plane_vm.default_ip_addresses
16 | worker = module.worker_vm.default_ip_addresses
17 | }
18 | }
19 |
20 | output "kubeconfig" {
21 | description = "Configuration file for obtaining administrative access to the cluster."
22 | sensitive = true
23 | value = yamlencode(local.kubeconfig)
24 | }
25 |
26 | output "talosconfig" {
27 | description = "Configuration file for obtaining administrative access to Talos virtual machines."
28 | sensitive = true
29 | value = yamlencode(local.talosconfig)
30 | }
31 |
32 | output "kubernetes_admin_pki" {
33 | description = "Cerificates and keys for obtaining administrative access to the cluster."
34 | sensitive = true
35 | value = {
36 | cluster_ca_certificate = base64decode(module.secrets.cluster_secrets.ca.crt)
37 | client_certificate = base64decode(module.secrets.kubernetes_admin_pki.crt)
38 | client_key = base64decode(module.secrets.kubernetes_admin_pki.key)
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/variables.tf:
--------------------------------------------------------------------------------
1 | variable "datacenter" {
2 | description = "VMware datacenter name."
3 | type = string
4 | }
5 |
6 | variable "datastores" {
7 | description = "VMWare datastore(s) where all data for the virtual machine will be placed in."
8 | type = list(string)
9 | }
10 |
11 | variable "hosts" {
12 | description = "ESXi host(s) where the virtual machine will be created."
13 | type = list(string)
14 | }
15 |
16 | variable "resource_pool" {
17 | description = "VMWare resource pool where the virtual machine will be created."
18 | type = string
19 | }
20 |
21 | variable "folder" {
22 | description = "Folder to create the virtual machines in."
23 | type = string
24 | }
25 |
26 | variable "remote_ovf_url" {
27 | description = "URL to the remote Talos OS 1.0.x ovf/ova file."
28 | type = string
29 | }
30 |
31 | variable "control_plane_count" {
32 | description = "Number of 'controlplane' virtual machines."
33 | type = number
34 | default = 2
35 | }
36 |
37 | variable "worker_count" {
38 | description = "Number of 'worker' virtual machines."
39 | type = number
40 | default = 0
41 | }
42 |
43 | variable "control_plane_num_cpus" {
44 | description = "The total number of virtual processor cores to assign to 'controlplane' virtual machines."
45 | type = number
46 | default = 2
47 | }
48 |
49 | variable "worker_num_cpus" {
50 | description = "The total number of virtual processor cores to assign to 'worker' virtual machines."
51 | type = number
52 | default = 4
53 | }
54 |
55 | variable "control_plane_memory" {
56 | description = "The amount of RAM for 'controlplane' virtual machines, in Mb."
57 | type = number
58 | default = 2048
59 | }
60 |
61 | variable "worker_memory" {
62 | description = "The amount of RAM for 'worker' virtual machines, in Mb."
63 | type = number
64 | default = 4096
65 | }
66 |
67 | variable "control_plane_disks" {
68 | description = "A specification list for a virtual disk devices on 'controlplane' virtual machines. Use only first disk to Talos installation in 'machine_base_configuration' block."
69 | type = list(object({
70 | label = string
71 | size = number
72 | }))
73 | }
74 |
75 | variable "worker_disks" {
76 | description = "A specification list for a virtual disk devices on 'worker' virtual machines. Use only first disk to Talos installation in 'machine_base_configuration' block."
77 | type = list(object({
78 | label = string
79 | size = number
80 | }))
81 | default = []
82 | }
83 |
84 | variable "control_plane_network_interfaces" {
85 | description = "A specification list for a virtual NIC on 'controlplane' virtual machines."
86 | type = list(object({
87 | name = string
88 | }))
89 | }
90 |
91 | variable "worker_network_interfaces" {
92 | description = "A specification list for a virtual NIC on 'worker' virtual machines."
93 | type = list(object({
94 | name = string
95 | }))
96 | default = []
97 | }
98 |
99 | variable "talos_base_configuration" {
100 | description = "Talos OS top-level configuration. See https://www.talos.dev/v1.0/reference/configuration/#config."
101 | type = object({
102 | version = string
103 | persist = bool
104 | })
105 |
106 | default = {
107 | version = "v1alpha1"
108 | persist = false
109 | }
110 | }
111 |
112 | variable "machine_secrets" {
113 | description = "Secret data that is used to create trust relationships between virtual machines (if not set will be generated automatically). See https://www.talos.dev/v1.0/reference/configuration/#machineconfig."
114 | type = object({
115 | token = optional(string)
116 | ca = object({
117 | crt = optional(string)
118 | key = optional(string)
119 | })
120 | })
121 |
122 | default = {
123 | ca = {}
124 | }
125 | }
126 |
127 | variable "talos_admin_pki" {
128 | description = "Base64 encoded certificate (signed by machine_secrets.ca.crt) and key (in ED25519) to provide access to virtual machine trought talosctl (required if node type is 'controlplane' init node will be create; if not set will be generate automaticly)."
129 | type = object({
130 | crt = optional(string)
131 | key = optional(string)
132 | })
133 | default = {}
134 | }
135 |
136 | variable "machine_base_configuration" {
137 | description = "Basic configuration of all virtual machines. See https://www.talos.dev/v1.0/reference/configuration/#machineconfig."
138 | type = object({
139 | install = object({
140 | disk = string
141 | extraKernelArgs = optional(list(string))
142 | image = string
143 | bootloader = bool
144 | wipe = bool
145 | diskSelector = optional(object({
146 | size = string
147 | model = string
148 | busPath = string
149 | }))
150 | extensions = optional(list(string))
151 | })
152 | kubelet = optional(object({
153 | image = string
154 | extraArgs = optional(map(string))
155 | clusterDNS = optional(list(string))
156 | extraMounts = optional(list(object({
157 | destination = string
158 | type = string
159 | source = string
160 | options = list(string)
161 | })))
162 | extraConfig = optional(map(string))
163 | nodeIP = optional(object({
164 | validSubnets = list(string)
165 | }))
166 | }))
167 | time = optional(object({
168 | disabled = bool
169 | servers = optional(list(string))
170 | bootTimeout = optional(string)
171 | }))
172 | features = optional(object({
173 | rbac = optional(bool)
174 | }))
175 | })
176 | }
177 |
178 | variable "control_plane_machine_extra_configuration" {
179 | description = "Extended configuration of 'controlplane' virtual machine. See https://www.talos.dev/v1.0/reference/configuration/#machineconfig."
180 | type = object({
181 | controlPlane = optional(object({
182 | controllerManager = optional(object({
183 | disabled = bool
184 | }))
185 | scheduler = optional(object({
186 | disabled = bool
187 | }))
188 | }))
189 | pods = optional(list(map(any)))
190 | disks = optional(list(object({
191 | device = string
192 | partitions = list(object({
193 | mountpoint = string
194 | size = string
195 | }))
196 | })))
197 | files = optional(list(object({
198 | content = string
199 | permissions = string
200 | path = string
201 | op = string
202 | })))
203 | env = optional(object({
204 | GRPC_GO_LOG_VERBOSITY_LEVEL = optional(string)
205 | GRPC_GO_LOG_SEVERITY_LEVEL = optional(string)
206 | http_proxy = optional(string)
207 | https_proxy = optional(string)
208 | no_proxy = optional(bool)
209 | }))
210 | sysctls = optional(map(string))
211 | sysfs = optional(map(string))
212 | registries = optional(object({
213 | mirrors = optional(map(object({
214 | endpoints = list(string)
215 | })))
216 | config = optional(map(object({
217 | tls = object({
218 | insecureSkipVerify = bool
219 | clientIdentity = optional(object({
220 | crt = string
221 | key = string
222 | }))
223 | ca = optional(string)
224 | })
225 | auth = optional(object({
226 | username = optional(string)
227 | password = optional(string)
228 | auth = optional(string)
229 | identityToken = optional(string)
230 | }))
231 | })))
232 | }))
233 | systemDiskEncryption = optional(map(object({
234 | provider = string
235 | keys = optional(list(object({
236 | static = optional(object({
237 | passphrase = string
238 | }))
239 | nodeID = optional(map(string))
240 | slot = optional(number)
241 | })))
242 | cipher = optional(string)
243 | keySize = optional(number)
244 | blockSize = optional(number)
245 | options = optional(list(string))
246 | })))
247 | udev = optional(object({
248 | rules = list(string)
249 | }))
250 | logging = optional(object({
251 | destinations = list(object({
252 | endpoint = string
253 | format = string
254 | }))
255 | }))
256 | kernel = optional(object({
257 | modules = list(object({
258 | name = string
259 | }))
260 | }))
261 | })
262 | default = {}
263 | }
264 |
265 | variable "worker_machine_extra_configuration" {
266 | description = "Extended configuration of 'worker' virtual machines. See https://www.talos.dev/v1.0/reference/configuration/#machineconfig."
267 | type = object({
268 | pods = optional(list(map(any)))
269 | disks = optional(list(object({
270 | device = string
271 | partitions = list(object({
272 | mountpoint = string
273 | size = string
274 | }))
275 | })))
276 | files = optional(list(object({
277 | content = string
278 | permissions = string
279 | path = string
280 | op = string
281 | })))
282 | env = optional(object({
283 | GRPC_GO_LOG_VERBOSITY_LEVEL = optional(string)
284 | GRPC_GO_LOG_SEVERITY_LEVEL = optional(string)
285 | http_proxy = optional(string)
286 | https_proxy = optional(string)
287 | no_proxy = optional(bool)
288 | }))
289 | sysctls = optional(map(string))
290 | sysfs = optional(map(string))
291 | registries = optional(object({
292 | mirrors = optional(map(object({
293 | endpoints = list(string)
294 | })))
295 | config = optional(map(object({
296 | tls = object({
297 | insecureSkipVerify = bool
298 | clientIdentity = optional(object({
299 | crt = string
300 | key = string
301 | }))
302 | ca = optional(string)
303 | })
304 | auth = optional(object({
305 | username = optional(string)
306 | password = optional(string)
307 | auth = optional(string)
308 | identityToken = optional(string)
309 | }))
310 | })))
311 | }))
312 | systemDiskEncryption = optional(map(object({
313 | provider = string
314 | keys = optional(list(object({
315 | static = optional(object({
316 | passphrase = string
317 | }))
318 | nodeID = optional(map(string))
319 | slot = optional(number)
320 | })))
321 | cipher = optional(string)
322 | keySize = optional(number)
323 | blockSize = optional(number)
324 | options = optional(list(string))
325 | })))
326 | udev = optional(object({
327 | rules = list(string)
328 | }))
329 | logging = optional(object({
330 | destinations = list(object({
331 | endpoint = string
332 | format = string
333 | }))
334 | }))
335 | kernel = optional(object({
336 | modules = list(object({
337 | name = string
338 | }))
339 | }))
340 | })
341 | default = {}
342 | }
343 |
344 | variable "control_plane_machine_cert_sans" {
345 | description = "A list of alternative names for *count* of 'controlplane' virtual machines. See https://www.talos.dev/v1.0/reference/configuration/#machineconfig."
346 | type = list(list(string))
347 | default = []
348 | }
349 |
350 | variable "worker_machine_cert_sans" {
351 | description = "A list of alternative names for *count* of 'worker' virtual machines. See https://www.talos.dev/v1.0/reference/configuration/#machineconfig."
352 | type = list(list(string))
353 | default = []
354 | }
355 |
356 | variable "machine_network" {
357 | description = "General network configuration of the virtual machine. 'hostname' and 'interfaces' parameters are described in separate inputs. See https://www.talos.dev/v1.0/reference/configuration/#networkconfig."
358 | type = object({
359 | nameservers = optional(list(string))
360 | extraHostEntries = optional(list(object({
361 | ip = string
362 | aliases = list(string)
363 | })))
364 | kubespan = optional(object({
365 | enabled = bool
366 | }))
367 | })
368 | default = {}
369 | }
370 |
371 | variable "control_plane_machine_network_hostnames" {
372 | description = "A list of hostnames for *count* of 'controlplane' virtual machines (if not set will be generated automatically). See https://www.talos.dev/v1.0/reference/configuration/#networkconfig."
373 | type = list(string)
374 | default = []
375 | }
376 |
377 | variable "worker_machine_network_hostnames" {
378 | description = "A list of hostnames for *count* of 'worker' virtual machines (if not set will be generated automatically). See https://www.talos.dev/v1.0/reference/configuration/#networkconfig."
379 | type = list(string)
380 | default = []
381 | }
382 |
383 | variable "control_plane_machine_network_interfaces" {
384 | description = "A list of network interfaces for *count* of 'controlplane' virtual machines (if not set DHCP will be used). Not less than one element with one static IP address required. See https://www.talos.dev/v1.0/reference/configuration/#device."
385 | type = list(list(object({
386 | interface = string
387 | addresses = optional(list(string))
388 | routes = optional(list(object({
389 | network = string
390 | gateway = optional(string)
391 | source = optional(string)
392 | metric = optional(number)
393 | })))
394 | vlans = optional(list(object({
395 | addresses = list(string)
396 | routes = optional(list(object({
397 | network = string
398 | gateway = optional(string)
399 | source = optional(string)
400 | metric = optional(number)
401 | })))
402 | dhcp = optional(bool)
403 | vlanId = number
404 | mtu = number
405 | vip = optional(object({
406 | ip = string
407 | equinixMetal = optional(object({
408 | apiToken = string
409 | }))
410 | hcloud = optional(object({
411 | apiToken = string
412 | }))
413 | }))
414 | })))
415 | mtu = optional(number)
416 | bond = optional(object({
417 | interfaces = list(string)
418 | mode = string
419 | lacpRate = string
420 | }))
421 | dhcp = optional(bool)
422 | ignore = optional(bool)
423 | dummy = optional(bool)
424 | dhcpOptions = optional(object({
425 | routeMetric = number
426 | ipv4 = optional(bool)
427 | ipv6 = optional(bool)
428 | }))
429 | wireguard = optional(object({
430 | privateKey = string
431 | listenPort = number
432 | firewallMark = number
433 | peers = list(object({
434 | publicKey = string
435 | endpoint = string
436 | persistentKeepaliveInterval = optional(string)
437 | allowedIPs = list(string)
438 | }))
439 | }))
440 | vip = optional(object({
441 | ip = string
442 | equinixMetal = optional(object({
443 | apiToken = string
444 | }))
445 | hcloud = optional(object({
446 | apiToken = string
447 | }))
448 | }))
449 | })))
450 | default = []
451 | }
452 |
453 | variable "worker_machine_network_interfaces" {
454 | description = "A list of network interfaces for *count* of 'worker' virtual machines (if not set DHCP will be used). See https://www.talos.dev/v1.0/reference/configuration/#device."
455 | type = list(list(object({
456 | interface = string
457 | addresses = optional(list(string))
458 | routes = optional(list(object({
459 | network = string
460 | gateway = optional(string)
461 | source = optional(string)
462 | metric = optional(number)
463 | })))
464 | vlans = optional(list(object({
465 | addresses = list(string)
466 | routes = optional(list(object({
467 | network = string
468 | gateway = optional(string)
469 | source = optional(string)
470 | metric = optional(number)
471 | })))
472 | dhcp = optional(bool)
473 | vlanId = number
474 | mtu = number
475 | vip = optional(object({
476 | ip = string
477 | equinixMetal = optional(object({
478 | apiToken = string
479 | }))
480 | hcloud = optional(object({
481 | apiToken = string
482 | }))
483 | }))
484 | })))
485 | mtu = optional(number)
486 | bond = optional(object({
487 | interfaces = list(string)
488 | mode = string
489 | lacpRate = string
490 | }))
491 | dhcp = optional(bool)
492 | ignore = optional(bool)
493 | dummy = optional(bool)
494 | dhcpOptions = optional(object({
495 | routeMetric = number
496 | ipv4 = optional(bool)
497 | ipv6 = optional(bool)
498 | }))
499 | wireguard = optional(object({
500 | privateKey = string
501 | listenPort = number
502 | firewallMark = number
503 | peers = list(object({
504 | publicKey = string
505 | endpoint = string
506 | persistentKeepaliveInterval = optional(string)
507 | allowedIPs = list(string)
508 | }))
509 | }))
510 | vip = optional(object({
511 | ip = string
512 | equinixMetal = optional(object({
513 | apiToken = string
514 | }))
515 | hcloud = optional(object({
516 | apiToken = string
517 | }))
518 | }))
519 | })))
520 | default = []
521 | }
522 |
523 | variable "cluster_secrets" {
524 | description = "Secret data that is used to establish trust relationships between Kubernetes cluster nodes. See https://www.talos.dev/v1.0/reference/configuration/#clusterconfig."
525 | type = object({
526 | id = optional(string)
527 | secret = optional(string)
528 | token = optional(string)
529 | ca = object({
530 | crt = optional(string)
531 | key = optional(string)
532 | })
533 | })
534 |
535 | default = {
536 | ca = {}
537 | }
538 | }
539 |
540 | variable "control_plane_cluster_secrets" {
541 | description = "Secret data required to establish trust relationships between components used by 'controlplane' nodes in the Kubernetes cluster. See https://www.talos.dev/v1.0/reference/configuration/#clusterconfig."
542 | type = object({
543 | aescbcEncryptionSecret = optional(string)
544 | aggregatorCA = object({
545 | crt = optional(string)
546 | key = optional(string)
547 | })
548 | serviceAccount = object({
549 | key = optional(string)
550 | })
551 | etcd = object({
552 | ca = object({
553 | crt = optional(string)
554 | key = optional(string)
555 | })
556 | })
557 | })
558 |
559 | default = {
560 | aggregatorCA = {}
561 | etcd = {
562 | ca = {}
563 | }
564 | serviceAccount = {}
565 | }
566 | }
567 |
568 | variable "cluster_name" {
569 | description = "The name of the cluster. See https://www.talos.dev/v1.0/reference/configuration/#clusterconfig."
570 | type = string
571 | }
572 |
573 | variable "cluster_control_plane" {
574 | description = "Data to define the API endpoint address for joining a node to the Kubernetes cluster. Required if 'init' node is outside of this cluster. See https://www.talos.dev/v1.0/reference/configuration/#controlplaneconfig."
575 | type = object({
576 | endpoint = optional(string)
577 | localAPIServerPort = optional(number)
578 | })
579 | default = {}
580 | }
581 |
582 | variable "cluster_discovery" {
583 | description = "Data that sets up the discovery of nodes in the Kubernetes cluster. See https://www.talos.dev/v1.0/reference/configuration/#clusterdiscoveryconfig."
584 | type = object({
585 | enabled = bool
586 | registries = optional(object({
587 | kubernetes = optional(object({
588 | disabled = bool
589 | }))
590 | service = optional(object({
591 | disabled = bool
592 | endpoint = string
593 | }))
594 | }))
595 | })
596 | default = {
597 | enabled = true
598 | }
599 | }
600 |
601 | variable "control_plane_cluster_configuration" {
602 | description = "Data that configure the components of the 'controlplane' nodes in the Kubernetes cluster. See https://www.talos.dev/v1.0/reference/configuration/#clusterconfig."
603 | type = object({
604 | network = optional(object({
605 | cni = optional(object({
606 | name = string
607 | urls = optional(list(string))
608 | }))
609 | dnsDomain = optional(string)
610 | podSubnets = optional(list(string))
611 | serviceSubnets = optional(list(string))
612 | }))
613 | apiServer = optional(object({
614 | image = string
615 | extraArgs = optional(map(string))
616 | extraVolumes = optional(list(object({
617 | hostPath = string
618 | mountPath = string
619 | readonly = bool
620 | })))
621 | env = optional(map(string))
622 | certSANs = optional(list(string))
623 | disablePodSecurityPolicy = optional(bool)
624 | admissionControl = optional(list(object({
625 | name = string
626 | configuration = map(any)
627 | })))
628 | }))
629 | controllerManager = optional(object({
630 | image = string
631 | extraArgs = optional(map(string))
632 | extraVolumes = optional(list(object({
633 | hostPath = string
634 | mountPath = string
635 | readonly = bool
636 | })))
637 | env = optional(map(string))
638 | }))
639 | proxy = optional(object({
640 | disabled = bool
641 | image = optional(string)
642 | mode = optional(string)
643 | extraArgs = optional(map(string))
644 | }))
645 | scheduler = optional(object({
646 | image = string
647 | extraArgs = optional(map(string))
648 | extraVolumes = optional(list(object({
649 | hostPath = string
650 | mountPath = string
651 | readonly = bool
652 | })))
653 | env = optional(map(string))
654 | }))
655 | etcd = optional(object({
656 | image = optional(string)
657 | extraArgs = optional(map(string))
658 | subnet = optional(string)
659 | }))
660 | coreDNS = optional(object({
661 | disabled = bool
662 | image = optional(string)
663 | }))
664 | externalCloudProvider = optional(object({
665 | enabled = bool
666 | manifests = list(string)
667 | }))
668 | adminKubeconfig = optional(object({
669 | certLifetime = string
670 | }))
671 | allowSchedulingOnMasters = optional(bool)
672 | })
673 | default = {}
674 | }
675 |
676 | variable "cluster_inline_manifests" {
677 | description = "A list of Kuberenetes manifests whose content is represented as a string. These will get automatically deployed as part of the bootstrap. See https://www.talos.dev/v1.0/reference/configuration/#clusterconfig."
678 | type = list(object({
679 | name = string
680 | contents = string
681 | }))
682 | default = []
683 | }
684 |
685 | variable "cluster_extra_manifests" {
686 | description = "A list of 'URLs' that point to additional manifests. These will get automatically deployed as part of the bootstrap. See https://www.talos.dev/v1.0/reference/configuration/#clusterconfig."
687 | type = list(string)
688 | default = []
689 | }
690 |
691 | variable "cluster_extra_manifest_headers" {
692 | description = "A map of key value pairs that will be added while fetching the 'cluster_extra_manifests'. See https://www.talos.dev/v1.0/reference/configuration/#clusterconfig."
693 | type = map(string)
694 | default = {}
695 | }
696 |
697 | variable "validity_period_hours" {
698 | description = "The number of hours after initial issuing that ALL generated certificates become invalid."
699 | type = number
700 | default = 8760
701 | }
702 |
703 | variable "kubeconfig_path" {
704 | description = "Path to save kubeconfig file (Include filename. If not set config will not be created)."
705 | type = string
706 | default = ""
707 | }
708 |
709 | variable "talosconfig_path" {
710 | description = "Path to save talosconfig file (Include filename. If if not set config will not be created)."
711 | type = string
712 | default = ""
713 | }
714 |
715 | variable "vmtoolsd_extra_manifest" {
716 | description = "A link to talos-vmtoolsd Kubernetes manifest."
717 | type = string
718 | default = "https://raw.githubusercontent.com/mologie/talos-vmtoolsd/release-0.3/deploy/0.3.yaml"
719 | }
720 |
--------------------------------------------------------------------------------