From 85772b9168ba41cfbea58d5435801bfae4a25bd9 Mon Sep 17 00:00:00 2001 From: doudou Date: Fri, 7 Nov 2025 15:23:27 +0800 Subject: [PATCH] chore: initialize k3s master iac skeleton --- .gitea/workflows/plan.yml | 29 ++++++++++++ README.md | 21 +++++++++ ansible/inventory/README.md | 5 +++ ansible/playbooks/master-init.yml | 21 +++++++++ terraform/README.md | 27 ++++++++++++ terraform/main.tf | 11 +++++ terraform/variables.tf | 73 +++++++++++++++++++++++++++++++ terraform/versions.tf | 12 +++++ 8 files changed, 199 insertions(+) create mode 100644 .gitea/workflows/plan.yml create mode 100644 README.md create mode 100644 ansible/inventory/README.md create mode 100644 ansible/playbooks/master-init.yml create mode 100644 terraform/README.md create mode 100644 terraform/main.tf create mode 100644 terraform/variables.tf create mode 100644 terraform/versions.tf diff --git a/.gitea/workflows/plan.yml b/.gitea/workflows/plan.yml new file mode 100644 index 0000000..cfa0e37 --- /dev/null +++ b/.gitea/workflows/plan.yml @@ -0,0 +1,29 @@ +name: terraform-plan + +on: + push: + branches: + - main + pull_request: + branches: + - main + +jobs: + plan: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Terraform + uses: hashicorp/setup-terraform@v3 + with: + terraform_wrapper: false + + - name: Terraform init + working-directory: terraform + run: echo TODO - terraform init + + - name: Terraform plan + working-directory: terraform + run: echo TODO - terraform plan diff --git a/README.md b/README.md new file mode 100644 index 0000000..4cc643c --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +# K3s Master Infrastructure-as-Code + +This repository tracks the Terraform + Ansible automation for provisioning and configuring K3s control-plane nodes on vSphere. Initial commit supplies scaffolding only; functional resources, modules, and tasks follow in upcoming iterations. + +## Current Status +- Gitea repository `iac/k3s-master` initialized with protected `main` branch and PR review requirement. +- Terraform directory contains provider baseline, version pinning, and documented variables. +- Ansible inventory/playbook skeleton captures control-plane bootstrap flow. +- Gitea Actions workflow stub (`.gitea/workflows/plan.yml`) reserved for Terraform plan execution. + +## Next Steps +1. Author Terraform data sources and VM definitions aligned with K3s sizing doc (ID 588). +2. Implement dynamic inventory output bridging Terraform state and Ansible. +3. Build hardened Ansible roles for OS baseline and K3s installation, leveraging security guidelines. +4. Replace workflow placeholders with real Terraform fmt/init/plan stages and artifact upload. + +## Dependencies +- vSphere endpoint with service account credentials and API access. +- Terraform CLI >= 1.8 and HashiCorp vsphere provider >= 2.5 (managed by CI image). +- Secrets storage for vSphere credentials (Gitea Actions secrets or Vault). +- Ansible control node with access to provisioned masters for configuration. diff --git a/ansible/inventory/README.md b/ansible/inventory/README.md new file mode 100644 index 0000000..f4ba034 --- /dev/null +++ b/ansible/inventory/README.md @@ -0,0 +1,5 @@ +# Inventory Layout + +Terraform will render a dynamic inventory (e.g., via `terraform output` or `ansible-inventory` plugin) exposing the K3s control-plane nodes under the `k3s_master` group. + +For local testing, drop an `inventory.ini` or `inventory.yaml` into this directory with the same group name. Keep secrets out of version control; prefer Ansible Vault or CI secret storage. diff --git a/ansible/playbooks/master-init.yml b/ansible/playbooks/master-init.yml new file mode 100644 index 0000000..c1a1fc6 --- /dev/null +++ b/ansible/playbooks/master-init.yml @@ -0,0 +1,21 @@ +--- +- name: Bootstrap K3s control-plane node + hosts: k3s_master + become: true + gather_facts: true + + vars: + kubeconfig_output: /etc/rancher/k3s/k3s.yaml + + pre_tasks: + - name: Assert control-plane requirements are satisfied + assert: + that: + - ansible_os_family is defined + fail_msg: "Host facts missing; ensure Ansible inventory is generated post-Terraform" + + roles: + # TODO: add hardened OS baseline, container runtime prerequisites, and k3s installation role. + - role: placeholder.k3s-master + vars: + kubeconfig_path: "{{ kubeconfig_output }}" diff --git a/terraform/README.md b/terraform/README.md new file mode 100644 index 0000000..2d30968 --- /dev/null +++ b/terraform/README.md @@ -0,0 +1,27 @@ +# Terraform K3s Master Scaffold + +## Purpose +This module provisions K3s control-plane virtual machines on vSphere. It only includes the provider bootstrap today; VM resources and data sources are added in future iterations. + +## Required Inputs +| Variable | Description | +| --- | --- | +| `vsphere_user` / `vsphere_password` | Service account stored in CI secrets (never commit plaintext). | +| `vsphere_server` | vCenter hostname or IP. | +| `datacenter`, `cluster`, `resource_pool` | Target placement scope. | +| `datastore` | Datastore or datastore cluster for disks. | +| `template` | Hardened golden image for K3s masters. | +| `network` | Portgroup for primary NIC. | +| `vm_count`, `vm_cpu`, `vm_memory_mb` | Control-plane sizing knobs. | +| `tags` | Optional key/value metadata for governance. | + +## Security Notes +- Inject credentials via Terraform Cloud/Enterprise variables, Vault, or Gitea Actions secrets. +- Rotate the vSphere service account per security policy; constrain RBAC to cloning and tagging only. +- Validate SSL certificates where possible; set `allow_unverified_ssl` only for lab use. +- Store generated Terraform state in a remote backend with encryption-at-rest (e.g., Consul, S3 compatible). + +## Next Steps +1. Wire vSphere data sources (datacenter, datastore, network). +2. Define `vsphere_virtual_machine` resources aligned with K3s sizing guidance. +3. Emit provisioning outputs consumed by Ansible inventory generation. diff --git a/terraform/main.tf b/terraform/main.tf new file mode 100644 index 0000000..531b075 --- /dev/null +++ b/terraform/main.tf @@ -0,0 +1,11 @@ +provider "vsphere" { + user = var.vsphere_user + password = var.vsphere_password + vsphere_server = var.vsphere_server + + # CI pipeline injects sensitive certificates and ignores insecure SSL via TF vars if required. + allow_unverified_ssl = false +} + +# Placeholder resource block intentionally omitted. +# Actual VM cloning, tagging, and network configuration will be added in follow-up stories. diff --git a/terraform/variables.tf b/terraform/variables.tf new file mode 100644 index 0000000..9487648 --- /dev/null +++ b/terraform/variables.tf @@ -0,0 +1,73 @@ +variable "vsphere_user" { + description = "vSphere username with permissions to deploy K3s master VMs" + type = string + sensitive = true +} + +variable "vsphere_password" { + description = "vSphere password stored in CI secrets manager" + type = string + sensitive = true +} + +variable "vsphere_server" { + description = "vCenter endpoint (FQDN or IP)" + type = string +} + +variable "datacenter" { + description = "Target vSphere datacenter name" + type = string +} + +variable "cluster" { + description = "Target vSphere compute cluster" + type = string +} + +variable "resource_pool" { + description = "Resource pool for the K3s master instances" + type = string + default = "" +} + +variable "datastore" { + description = "Primary datastore to host the VM disks" + type = string +} + +variable "template" { + description = "Hardened golden image used to clone K3s masters" + type = string +} + +variable "network" { + description = "Primary portgroup the masters attach to" + type = string +} + +variable "vm_count" { + description = "Number of K3s control-plane VMs to provision" + type = number + default = 3 +} + +variable "vm_cpu" { + description = "vCPU count per K3s control-plane VM" + type = number + default = 4 +} + +variable "vm_memory_mb" { + description = "Memory in MB per control-plane VM" + type = number + default = 8192 +} + +variable "tags" { + description = "Map of tags applied to all created resources" + type = map(string) + default = {} +} + +# Sensitive values are marked and must flow through secrets management, never plain text. diff --git a/terraform/versions.tf b/terraform/versions.tf new file mode 100644 index 0000000..fb933cf --- /dev/null +++ b/terraform/versions.tf @@ -0,0 +1,12 @@ +terraform { + required_version = ">= 1.8.0" + + required_providers { + vsphere = { + source = "hashicorp/vsphere" + version = ">= 2.5.0" + } + } +} + +# Locking Terraform and provider versions prevents pipeline drift.