initial commit
This commit is contained in:
339
RUNBOOK.md
Normal file
339
RUNBOOK.md
Normal file
@@ -0,0 +1,339 @@
|
||||
# K8s Cluster Runbook — Build From Scratch
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
Client machine (192.168.1.39)
|
||||
├── Terraform → Proxmox API → provision VMs
|
||||
└── Ansible → SSH → configure k8s
|
||||
|
||||
Proxmox cluster
|
||||
├── proxmox (node 1)
|
||||
├── proxmox02 (node 2)
|
||||
└── proxmox03 (node 3, 192.168.1.18) ← all VMs here
|
||||
|
||||
VMs (CentOS Stream 10, cloud-init)
|
||||
├── master01 192.168.1.31 2 vCPU 8GB RAM 100GB disk
|
||||
├── worker01 192.168.1.35 2 vCPU 12GB RAM 100GB disk
|
||||
├── worker02 192.168.1.36 2 vCPU 12GB RAM 100GB disk
|
||||
└── worker03 192.168.1.37 2 vCPU 12GB RAM 100GB disk
|
||||
|
||||
Storage: xpen (NFS NAS) — all VM disks
|
||||
local — cloud image download + cloud-init drive
|
||||
Pool: IaC
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 1 — Client machine setup
|
||||
|
||||
### 1.1 Install tools
|
||||
|
||||
```bash
|
||||
# Terraform
|
||||
yum install -y yum-utils
|
||||
yum-config-manager --add-repo https://rpm.releases.hashicorp.com/RHEL/hashicorp.repo
|
||||
yum install -y terraform
|
||||
terraform version
|
||||
|
||||
# Ansible
|
||||
pip3 install ansible
|
||||
# or: dnf install ansible
|
||||
|
||||
# Git
|
||||
yum install -y git
|
||||
```
|
||||
|
||||
### 1.2 Clone repo
|
||||
|
||||
```bash
|
||||
git clone <your-gitea-repo-url> ~/k8s
|
||||
cd ~/k8s
|
||||
```
|
||||
|
||||
### 1.3 Set up Terraform credentials
|
||||
|
||||
```bash
|
||||
cp cluster-init/terraform/.env.example cluster-init/terraform/.env
|
||||
# edit cluster-init/terraform/.env — fill in endpoint + token
|
||||
```
|
||||
|
||||
`cluster-init/terraform/.env` is gitignored — never commit it.
|
||||
|
||||
### 1.4 Generate SSH keypair for VM access
|
||||
|
||||
> Skip if `cluster-init/terraform/k8s_terraform` already exists.
|
||||
|
||||
```bash
|
||||
ssh-keygen -t ed25519 -f ~/k8s/cluster-init/terraform/k8s_terraform -N "" -C "terraform-k8s"
|
||||
```
|
||||
|
||||
Private key: `cluster-init/terraform/k8s_terraform` (gitignored — do not commit)
|
||||
Public key: `cluster-init/terraform/k8s_terraform.pub` (gitignored — injected into VMs via cloud-init)
|
||||
|
||||
---
|
||||
|
||||
## Phase 2 — Proxmox preparation
|
||||
|
||||
### 2.1 Enable local storage content types
|
||||
|
||||
**Proxmox UI → Datacenter → Storage → local → Edit → Content**
|
||||
|
||||
Enable:
|
||||
- `Disk image (import)` — for cloud image download via Terraform
|
||||
- `Snippets` — for cloud-init drive
|
||||
|
||||
### 2.2 Create Terraform user, role, token
|
||||
|
||||
SSH into any Proxmox node as root:
|
||||
|
||||
```bash
|
||||
# Create role
|
||||
pveum role add TerraformRole --privs \
|
||||
"VM.Allocate,VM.Clone,VM.Config.Disk,VM.Config.CPU,\
|
||||
VM.Config.Memory,VM.Config.Network,VM.Config.Options,\
|
||||
VM.Config.CloudInit,VM.Config.CDROM,VM.PowerMgmt,VM.Audit,\
|
||||
Datastore.AllocateSpace,Datastore.AllocateTemplate,\
|
||||
Datastore.Allocate,Datastore.Audit,Sys.Audit,Sys.Modify,\
|
||||
Pool.Allocate,SDN.Use"
|
||||
|
||||
# Create user + token — SAVE the secret, shown only once
|
||||
pveum user add terraform@pve --comment "Terraform IaC"
|
||||
pveum user token add terraform@pve terraform --privsep 0
|
||||
|
||||
# ACLs
|
||||
pveum acl modify /nodes --user terraform@pve --role TerraformRole
|
||||
pveum acl modify /nodes/proxmox03 --user terraform@pve --role TerraformRole
|
||||
pveum acl modify /storage/local --user terraform@pve --role TerraformRole
|
||||
pveum acl modify /storage/xpen --user terraform@pve --role TerraformRole
|
||||
pveum acl modify /pool/IaC --user terraform@pve --role TerraformRole
|
||||
pveum acl modify /sdn/zones/localnetwork/vmbr0 --user terraform@pve --role TerraformRole
|
||||
|
||||
# Required for proxmox_download_file — Sys.Audit + Sys.Modify must be at root
|
||||
pveum role add SysDownloadRole --privs "Sys.Audit,Sys.Modify"
|
||||
pveum acl modify / --user terraform@pve --role SysDownloadRole
|
||||
|
||||
# SDN — token needs explicit ACL (separate from user ACL)
|
||||
pveum acl modify /sdn/zones/localnetwork/vmbr0 \
|
||||
--token terraform@pve!terraform --role TerraformRole
|
||||
```
|
||||
|
||||
Update `cluster-init/terraform/.env` with the token secret.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3 — Provision VMs with Terraform
|
||||
|
||||
### 3.1 Init
|
||||
|
||||
```bash
|
||||
cd ~/k8s/cluster-init/terraform
|
||||
source .env
|
||||
terraform init
|
||||
```
|
||||
|
||||
### 3.2 Plan
|
||||
|
||||
```bash
|
||||
source .env
|
||||
terraform plan
|
||||
```
|
||||
|
||||
Expected: 5 resources to create
|
||||
- `proxmox_download_file.centos10`
|
||||
- `proxmox_virtual_environment_vm.master`
|
||||
- `proxmox_virtual_environment_vm.workers["worker01"]`
|
||||
- `proxmox_virtual_environment_vm.workers["worker02"]`
|
||||
- `proxmox_virtual_environment_vm.workers["worker03"]`
|
||||
|
||||
### 3.3 Apply
|
||||
|
||||
```bash
|
||||
terraform apply -parallelism=1
|
||||
```
|
||||
|
||||
> Must use `-parallelism=1` — parallel disk clones to xpen NFS cause storage lock timeout.
|
||||
|
||||
Takes ~10-15 min (cloud image download ~1 min + 4 VMs × ~3 min each).
|
||||
|
||||
### 3.4 Post-apply state sync
|
||||
|
||||
After first apply, run once to sync pool membership state:
|
||||
```bash
|
||||
terraform apply -refresh-only
|
||||
```
|
||||
|
||||
Type `yes`. Then verify no further changes:
|
||||
```bash
|
||||
terraform plan
|
||||
```
|
||||
|
||||
### 3.5 Verify VMs
|
||||
|
||||
```bash
|
||||
ssh -i cluster-init/terraform/k8s_terraform cloud-user@192.168.1.31
|
||||
hostname # master01
|
||||
free -h # Swap: 0 (disabled by cloud-init)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 4 — Configure k8s with Ansible
|
||||
|
||||
> Playbooks in `cluster-init/ansible/`
|
||||
|
||||
### 4.1 Run all playbooks
|
||||
|
||||
```bash
|
||||
cd ~/k8s/cluster-init/ansible
|
||||
|
||||
# All nodes — OS prerequisites (swap, kernel modules, sysctl)
|
||||
ansible-playbook -i inventory.ini playbooks/01-common.yml
|
||||
|
||||
# All nodes — /etc/hosts (nodes know each other by hostname)
|
||||
ansible-playbook -i inventory.ini playbooks/02-hosts.yml
|
||||
|
||||
# All nodes — container runtime (containerd)
|
||||
ansible-playbook -i inventory.ini playbooks/03-containerd.yml
|
||||
|
||||
# All nodes — kubeadm/kubelet/kubectl
|
||||
ansible-playbook -i inventory.ini playbooks/04-kube-tools.yml
|
||||
|
||||
# master01 only — init cluster + CNI
|
||||
ansible-playbook -i inventory.ini playbooks/05-master-init.yml
|
||||
|
||||
# worker01/02/03 — join cluster
|
||||
ansible-playbook -i inventory.ini playbooks/06-worker-join.yml
|
||||
```
|
||||
|
||||
### 4.2 Verify cluster (from master01)
|
||||
|
||||
```bash
|
||||
ssh -i ../terraform/k8s_terraform cloud-user@192.168.1.31
|
||||
kubectl get nodes
|
||||
```
|
||||
|
||||
All 4 nodes should be `Ready`.
|
||||
|
||||
---
|
||||
|
||||
## Phase 5 — kubectl from client machine (192.168.1.39)
|
||||
|
||||
### 5.1 Install kubectl
|
||||
|
||||
```bash
|
||||
# Match the cluster version (1.32)
|
||||
curl -LO "https://dl.k8s.io/release/v1.32.0/bin/linux/amd64/kubectl"
|
||||
chmod +x kubectl
|
||||
sudo mv kubectl /usr/local/bin/kubectl
|
||||
kubectl version --client
|
||||
```
|
||||
|
||||
### 5.2 Copy kubeconfig from master01
|
||||
|
||||
```bash
|
||||
mkdir -p ~/.kube
|
||||
scp -i ~/k8s/cluster-init/terraform/k8s_terraform \
|
||||
cloud-user@192.168.1.31:/home/cloud-user/.kube/config \
|
||||
~/.kube/config
|
||||
```
|
||||
|
||||
### 5.3 Add cluster nodes to client /etc/hosts
|
||||
|
||||
```bash
|
||||
sudo tee -a /etc/hosts <<'EOF'
|
||||
|
||||
# k8s cluster nodes
|
||||
192.168.1.31 master01
|
||||
192.168.1.35 worker01
|
||||
192.168.1.36 worker02
|
||||
192.168.1.37 worker03
|
||||
EOF
|
||||
```
|
||||
|
||||
### 5.4 Verify
|
||||
|
||||
```bash
|
||||
kubectl get nodes
|
||||
kubectl get pods -A
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Teardown
|
||||
|
||||
```bash
|
||||
cd ~/k8s/cluster-init/terraform
|
||||
source .env
|
||||
terraform destroy -parallelism=1
|
||||
```
|
||||
|
||||
Destroys all 4 VMs + cloud image file. Re-run Phase 3 to rebuild from scratch.
|
||||
|
||||
---
|
||||
|
||||
## SSH access
|
||||
|
||||
```bash
|
||||
ssh -i ~/k8s/cluster-init/terraform/k8s_terraform cloud-user@192.168.1.31 # master01
|
||||
ssh -i ~/k8s/cluster-init/terraform/k8s_terraform cloud-user@192.168.1.35 # worker01
|
||||
ssh -i ~/k8s/cluster-init/terraform/k8s_terraform cloud-user@192.168.1.36 # worker02
|
||||
ssh -i ~/k8s/cluster-init/terraform/k8s_terraform cloud-user@192.168.1.37 # worker03
|
||||
```
|
||||
|
||||
Or add to `~/.ssh/config`:
|
||||
|
||||
```
|
||||
Host master01
|
||||
HostName 192.168.1.31
|
||||
User cloud-user
|
||||
IdentityFile ~/k8s/cluster-init/terraform/k8s_terraform
|
||||
|
||||
Host worker01
|
||||
HostName 192.168.1.35
|
||||
User cloud-user
|
||||
IdentityFile ~/k8s/cluster-init/terraform/k8s_terraform
|
||||
|
||||
Host worker02
|
||||
HostName 192.168.1.36
|
||||
User cloud-user
|
||||
IdentityFile ~/k8s/cluster-init/terraform/k8s_terraform
|
||||
|
||||
Host worker03
|
||||
HostName 192.168.1.37
|
||||
User cloud-user
|
||||
IdentityFile ~/k8s/cluster-init/terraform/k8s_terraform
|
||||
```
|
||||
|
||||
Then: `ssh master01`, `ssh worker01`, etc.
|
||||
|
||||
---
|
||||
|
||||
## File reference
|
||||
|
||||
```
|
||||
k8s/cluster-init/
|
||||
├── RUNBOOK.md
|
||||
├── terraform/
|
||||
│ ├── .env # Terraform credentials (gitignored)
|
||||
│ ├── .env.example # template — safe to commit
|
||||
│ ├── main.tf # provider config
|
||||
│ ├── variables.tf # input variables
|
||||
│ ├── terraform.tfvars # non-secret defaults
|
||||
│ ├── cloud_image.tf # CentOS Stream 10 cloud image download
|
||||
│ ├── vms.tf # master01 + worker01/02/03
|
||||
│ ├── outputs.tf # IPs + SSH command
|
||||
│ ├── k8s_terraform # SSH private key (gitignored)
|
||||
│ ├── k8s_terraform.pub # SSH public key (gitignored)
|
||||
│ └── .gitignore
|
||||
└── ansible/
|
||||
├── inventory.ini
|
||||
├── ansible.cfg
|
||||
└── playbooks/
|
||||
├── 01-common.yml
|
||||
├── 02-hosts.yml
|
||||
├── 03-containerd.yml
|
||||
├── 04-kube-tools.yml
|
||||
├── 05-master-init.yml
|
||||
└── 06-worker-join.yml
|
||||
```
|
||||
13
ansible/ansible.cfg
Normal file
13
ansible/ansible.cfg
Normal file
@@ -0,0 +1,13 @@
|
||||
[defaults]
|
||||
inventory = inventory.ini
|
||||
remote_user = cloud-user
|
||||
private_key_file = ../terraform/k8s_terraform
|
||||
host_key_checking = False
|
||||
stdout_callback = default
|
||||
result_format = yaml
|
||||
interpreter_python = /usr/bin/python3.12
|
||||
deprecation_warnings = False
|
||||
|
||||
[privilege_escalation]
|
||||
become = True
|
||||
become_method = sudo
|
||||
11
ansible/inventory.ini
Normal file
11
ansible/inventory.ini
Normal file
@@ -0,0 +1,11 @@
|
||||
[masters]
|
||||
master01 ansible_host=192.168.1.31
|
||||
|
||||
[workers]
|
||||
worker01 ansible_host=192.168.1.35
|
||||
worker02 ansible_host=192.168.1.36
|
||||
worker03 ansible_host=192.168.1.37
|
||||
|
||||
[k8s:children]
|
||||
masters
|
||||
workers
|
||||
40
ansible/playbooks/01-common.yml
Normal file
40
ansible/playbooks/01-common.yml
Normal file
@@ -0,0 +1,40 @@
|
||||
---
|
||||
- name: Common OS prerequisites for all k8s nodes
|
||||
hosts: k8s
|
||||
become: true
|
||||
|
||||
tasks:
|
||||
- name: Disable swap now
|
||||
command: swapoff -a
|
||||
when: ansible_facts['swaptotal_mb'] > 0
|
||||
|
||||
- name: Remove swap from /etc/fstab
|
||||
replace:
|
||||
path: /etc/fstab
|
||||
regexp: '^([^#].*\s+swap\s+.*)$'
|
||||
replace: '# \1'
|
||||
|
||||
- name: Load kernel modules at boot
|
||||
copy:
|
||||
dest: /etc/modules-load.d/k8s.conf
|
||||
content: |
|
||||
overlay
|
||||
br_netfilter
|
||||
|
||||
- name: Load kernel modules now
|
||||
modprobe:
|
||||
name: "{{ item }}"
|
||||
loop:
|
||||
- overlay
|
||||
- br_netfilter
|
||||
|
||||
- name: Set sysctl for k8s networking
|
||||
copy:
|
||||
dest: /etc/sysctl.d/k8s.conf
|
||||
content: |
|
||||
net.bridge.bridge-nf-call-iptables = 1
|
||||
net.bridge.bridge-nf-call-ip6tables = 1
|
||||
net.ipv4.ip_forward = 1
|
||||
|
||||
- name: Apply sysctl
|
||||
command: sysctl --system
|
||||
15
ansible/playbooks/02-hosts.yml
Normal file
15
ansible/playbooks/02-hosts.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
- name: Configure /etc/hosts for all nodes
|
||||
hosts: k8s
|
||||
become: true
|
||||
|
||||
tasks:
|
||||
- name: Add cluster nodes to /etc/hosts
|
||||
blockinfile:
|
||||
path: /etc/hosts
|
||||
marker: "# {mark} k8s cluster nodes"
|
||||
block: |
|
||||
192.168.1.31 master01
|
||||
192.168.1.35 worker01
|
||||
192.168.1.36 worker02
|
||||
192.168.1.37 worker03
|
||||
35
ansible/playbooks/03-containerd.yml
Normal file
35
ansible/playbooks/03-containerd.yml
Normal file
@@ -0,0 +1,35 @@
|
||||
---
|
||||
- name: Install and configure containerd
|
||||
hosts: k8s
|
||||
become: true
|
||||
|
||||
tasks:
|
||||
- name: Add Docker CE repo (provides containerd.io)
|
||||
get_url:
|
||||
url: https://download.docker.com/linux/centos/docker-ce.repo
|
||||
dest: /etc/yum.repos.d/docker-ce.repo
|
||||
|
||||
- name: Install containerd
|
||||
dnf:
|
||||
name: containerd.io
|
||||
state: present
|
||||
|
||||
- name: Create containerd config directory
|
||||
file:
|
||||
path: /etc/containerd
|
||||
state: directory
|
||||
|
||||
- name: Generate default containerd config (overwrites Docker CE default which disables CRI)
|
||||
shell: containerd config default > /etc/containerd/config.toml
|
||||
|
||||
- name: Enable SystemdCgroup in containerd config
|
||||
replace:
|
||||
path: /etc/containerd/config.toml
|
||||
regexp: 'SystemdCgroup = false'
|
||||
replace: 'SystemdCgroup = true'
|
||||
|
||||
- name: Enable and start containerd
|
||||
systemd:
|
||||
name: containerd
|
||||
enabled: true
|
||||
state: restarted
|
||||
35
ansible/playbooks/04-kube-tools.yml
Normal file
35
ansible/playbooks/04-kube-tools.yml
Normal file
@@ -0,0 +1,35 @@
|
||||
---
|
||||
- name: Install kubeadm, kubelet, kubectl
|
||||
hosts: k8s
|
||||
become: true
|
||||
|
||||
vars:
|
||||
kube_version: "1.32"
|
||||
|
||||
tasks:
|
||||
- name: Add Kubernetes repo
|
||||
copy:
|
||||
dest: /etc/yum.repos.d/kubernetes.repo
|
||||
content: |
|
||||
[kubernetes]
|
||||
name=Kubernetes
|
||||
baseurl=https://pkgs.k8s.io/core:/stable:/v{{ kube_version }}/rpm/
|
||||
enabled=1
|
||||
gpgcheck=1
|
||||
gpgkey=https://pkgs.k8s.io/core:/stable:/v{{ kube_version }}/rpm/repodata/repomd.xml.key
|
||||
exclude=kubelet kubeadm kubectl cri-tools kubernetes-cni
|
||||
|
||||
- name: Install kubeadm, kubelet, kubectl
|
||||
dnf:
|
||||
name:
|
||||
- kubelet
|
||||
- kubeadm
|
||||
- kubectl
|
||||
state: present
|
||||
disable_excludes: kubernetes
|
||||
|
||||
- name: Enable kubelet
|
||||
systemd:
|
||||
name: kubelet
|
||||
enabled: true
|
||||
state: started
|
||||
67
ansible/playbooks/05-master-init.yml
Normal file
67
ansible/playbooks/05-master-init.yml
Normal file
@@ -0,0 +1,67 @@
|
||||
---
|
||||
- name: Initialize Kubernetes master
|
||||
hosts: masters
|
||||
become: true
|
||||
|
||||
vars:
|
||||
pod_network_cidr: "10.244.0.0/16" # Flannel default
|
||||
|
||||
tasks:
|
||||
- name: Check if cluster already initialized
|
||||
stat:
|
||||
path: /etc/kubernetes/admin.conf
|
||||
register: kubeadm_init_done
|
||||
|
||||
- name: Run kubeadm init
|
||||
command: >
|
||||
kubeadm init
|
||||
--apiserver-advertise-address={{ ansible_host }}
|
||||
--pod-network-cidr={{ pod_network_cidr }}
|
||||
when: not kubeadm_init_done.stat.exists
|
||||
register: kubeadm_output
|
||||
|
||||
- name: Create .kube dir for cloud-user
|
||||
file:
|
||||
path: /home/cloud-user/.kube
|
||||
state: directory
|
||||
mode: "0700"
|
||||
owner: cloud-user
|
||||
group: cloud-user
|
||||
|
||||
- name: Copy admin.conf to cloud-user kubeconfig
|
||||
copy:
|
||||
src: /etc/kubernetes/admin.conf
|
||||
dest: /home/cloud-user/.kube/config
|
||||
remote_src: true
|
||||
owner: cloud-user
|
||||
group: cloud-user
|
||||
mode: "0600"
|
||||
|
||||
- name: Create .kube dir for root (enables sudo kubectl)
|
||||
file:
|
||||
path: /root/.kube
|
||||
state: directory
|
||||
mode: "0700"
|
||||
|
||||
- name: Copy admin.conf to root kubeconfig
|
||||
copy:
|
||||
src: /etc/kubernetes/admin.conf
|
||||
dest: /root/.kube/config
|
||||
remote_src: true
|
||||
mode: "0600"
|
||||
|
||||
- name: Install Flannel CNI
|
||||
command: kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
|
||||
environment:
|
||||
KUBECONFIG: /etc/kubernetes/admin.conf
|
||||
|
||||
- name: Get join command
|
||||
command: kubeadm token create --print-join-command
|
||||
register: join_command
|
||||
|
||||
- name: Save join command to local file
|
||||
local_action:
|
||||
module: copy
|
||||
content: "{{ join_command.stdout }}"
|
||||
dest: /tmp/k8s_join_command.sh
|
||||
mode: "0600"
|
||||
21
ansible/playbooks/06-worker-join.yml
Normal file
21
ansible/playbooks/06-worker-join.yml
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
- name: Join workers to Kubernetes cluster
|
||||
hosts: workers
|
||||
become: true
|
||||
|
||||
tasks:
|
||||
- name: Check if already joined
|
||||
stat:
|
||||
path: /etc/kubernetes/kubelet.conf
|
||||
register: kubelet_conf
|
||||
|
||||
- name: Read join command from local file
|
||||
local_action:
|
||||
module: slurp
|
||||
src: /tmp/k8s_join_command.sh
|
||||
register: join_command_b64
|
||||
when: not kubelet_conf.stat.exists
|
||||
|
||||
- name: Join cluster
|
||||
command: "{{ join_command_b64.content | b64decode | trim }}"
|
||||
when: not kubelet_conf.stat.exists
|
||||
2
terraform/.env.example
Normal file
2
terraform/.env.example
Normal file
@@ -0,0 +1,2 @@
|
||||
export TF_VAR_proxmox_endpoint=https://<proxmox-node-ip>:8006
|
||||
export TF_VAR_proxmox_api_token=terraform@pve!terraform=<token-secret>
|
||||
10
terraform/.gitignore
vendored
Normal file
10
terraform/.gitignore
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
.env
|
||||
.terraform/
|
||||
.terraform.lock.hcl
|
||||
terraform.tfstate
|
||||
terraform.tfstate.backup
|
||||
*.tfstate
|
||||
*.tfstate.*
|
||||
k8s_terraform
|
||||
k8s_terraform.pub
|
||||
*.tfvars.local
|
||||
8
terraform/cloud_image.tf
Normal file
8
terraform/cloud_image.tf
Normal file
@@ -0,0 +1,8 @@
|
||||
resource "proxmox_download_file" "centos10" {
|
||||
content_type = "import"
|
||||
datastore_id = "local"
|
||||
node_name = var.proxmox_node
|
||||
url = "https://cloud.centos.org/centos/10-stream/x86_64/images/CentOS-Stream-GenericCloud-10-latest.x86_64.qcow2"
|
||||
file_name = "centos-stream-10-cloud.qcow2"
|
||||
overwrite = false
|
||||
}
|
||||
14
terraform/main.tf
Normal file
14
terraform/main.tf
Normal file
@@ -0,0 +1,14 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
proxmox = {
|
||||
source = "bpg/proxmox"
|
||||
version = "~> 0.107"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provider "proxmox" {
|
||||
endpoint = var.proxmox_endpoint
|
||||
api_token = var.proxmox_api_token
|
||||
insecure = true
|
||||
}
|
||||
11
terraform/outputs.tf
Normal file
11
terraform/outputs.tf
Normal file
@@ -0,0 +1,11 @@
|
||||
output "master_ip" {
|
||||
value = "192.168.1.31"
|
||||
}
|
||||
|
||||
output "worker_ips" {
|
||||
value = { for k, v in proxmox_virtual_environment_vm.workers : k => v.initialization[0].ip_config[0].ipv4[0].address }
|
||||
}
|
||||
|
||||
output "ssh_command" {
|
||||
value = "ssh -i ${path.module}/k8s_terraform cloud-user@192.168.1.31"
|
||||
}
|
||||
5
terraform/terraform.tfvars
Normal file
5
terraform/terraform.tfvars
Normal file
@@ -0,0 +1,5 @@
|
||||
proxmox_endpoint = "https://192.168.1.18:8006"
|
||||
proxmox_node = "proxmox03"
|
||||
proxmox_pool = "IaC"
|
||||
gateway = "192.168.1.1"
|
||||
dns_server = "192.168.1.1"
|
||||
24
terraform/variables.tf
Normal file
24
terraform/variables.tf
Normal file
@@ -0,0 +1,24 @@
|
||||
variable "proxmox_endpoint" {
|
||||
description = "Proxmox API endpoint URL"
|
||||
}
|
||||
|
||||
variable "proxmox_api_token" {
|
||||
description = "Proxmox API token (user@realm!tokenid=secret)"
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "proxmox_node" {
|
||||
default = "proxmox03"
|
||||
}
|
||||
|
||||
variable "proxmox_pool" {
|
||||
default = "IaC"
|
||||
}
|
||||
|
||||
variable "gateway" {
|
||||
default = "192.168.1.1"
|
||||
}
|
||||
|
||||
variable "dns_server" {
|
||||
default = "192.168.1.1"
|
||||
}
|
||||
121
terraform/vms.tf
Normal file
121
terraform/vms.tf
Normal file
@@ -0,0 +1,121 @@
|
||||
resource "proxmox_virtual_environment_vm" "master" {
|
||||
name = "master01"
|
||||
vm_id = 131
|
||||
node_name = var.proxmox_node
|
||||
pool_id = var.proxmox_pool
|
||||
stop_on_destroy = true
|
||||
|
||||
cpu {
|
||||
cores = 2
|
||||
type = "host"
|
||||
}
|
||||
|
||||
memory {
|
||||
dedicated = 8192
|
||||
}
|
||||
|
||||
scsi_hardware = "virtio-scsi-single"
|
||||
|
||||
disk {
|
||||
datastore_id = "xpen"
|
||||
import_from = proxmox_download_file.centos10.id
|
||||
interface = "scsi0"
|
||||
iothread = true
|
||||
size = 100
|
||||
}
|
||||
|
||||
network_device {
|
||||
bridge = "vmbr0"
|
||||
model = "virtio"
|
||||
}
|
||||
|
||||
boot_order = ["scsi0"]
|
||||
|
||||
agent {
|
||||
enabled = true
|
||||
}
|
||||
|
||||
initialization {
|
||||
datastore_id = "local"
|
||||
|
||||
ip_config {
|
||||
ipv4 {
|
||||
address = "192.168.1.31/24"
|
||||
gateway = var.gateway
|
||||
}
|
||||
}
|
||||
|
||||
dns {
|
||||
servers = [var.dns_server]
|
||||
}
|
||||
|
||||
user_account {
|
||||
username = "cloud-user"
|
||||
keys = [trimspace(file("${path.module}/k8s_terraform.pub"))]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
resource "proxmox_virtual_environment_vm" "workers" {
|
||||
for_each = {
|
||||
worker01 = { vm_id = 135, ip = "192.168.1.35" }
|
||||
worker02 = { vm_id = 136, ip = "192.168.1.36" }
|
||||
worker03 = { vm_id = 137, ip = "192.168.1.37" }
|
||||
}
|
||||
|
||||
name = each.key
|
||||
vm_id = each.value.vm_id
|
||||
node_name = var.proxmox_node
|
||||
pool_id = var.proxmox_pool
|
||||
stop_on_destroy = true
|
||||
|
||||
cpu {
|
||||
cores = 2
|
||||
type = "host"
|
||||
}
|
||||
|
||||
memory {
|
||||
dedicated = 12288
|
||||
}
|
||||
|
||||
scsi_hardware = "virtio-scsi-single"
|
||||
|
||||
disk {
|
||||
datastore_id = "xpen"
|
||||
import_from = proxmox_download_file.centos10.id
|
||||
interface = "scsi0"
|
||||
iothread = true
|
||||
size = 100
|
||||
}
|
||||
|
||||
network_device {
|
||||
bridge = "vmbr0"
|
||||
model = "virtio"
|
||||
}
|
||||
|
||||
boot_order = ["scsi0"]
|
||||
|
||||
agent {
|
||||
enabled = true
|
||||
}
|
||||
|
||||
initialization {
|
||||
datastore_id = "local"
|
||||
|
||||
ip_config {
|
||||
ipv4 {
|
||||
address = "${each.value.ip}/24"
|
||||
gateway = var.gateway
|
||||
}
|
||||
}
|
||||
|
||||
dns {
|
||||
servers = [var.dns_server]
|
||||
}
|
||||
|
||||
user_account {
|
||||
username = "cloud-user"
|
||||
keys = [trimspace(file("${path.module}/k8s_terraform.pub"))]
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user